We received a file that looked like it was compressed. Let's just pipe it
through xz and see what it really is. Aaah, looks like some old and obscure
machine code of a machine that has long since been retired.
The machine code is of the CDC 6600, a very weird machine that has a set of 24
registers, some of them address (A0-A7), index (B0-B1), and arithmetic
registers (X0-X7). The ISA is kind of RISC like with some weird quirks.
The address width is 18 bit and there are 60 bits in a word (which is the
access granularity). I'm not entirely sure on the endianness but it worked out
either way.
Individual A and X registers are coupled, i.e., if something is written into
A{1-5} then an implicit memory load to X{1-5} happens. A0 and X0 are scratch
registers, B0 is hardwired to 0 (cheap bastards), B1 contains 1 by convention
(seems like a waste of a register to me).
Interestingly the machine does not use ASCII characters but the following
table:
XXX 000 001 010 011 100 101 110 111
000 : A B C D E F G
001 H I J K L M N O
010 P Q R S T U V W
011 X Y Z 0 1 2 3 4
100 5 6 7 8 9 + - *
101 \ ( ) $ = , .
110 # [ ] % " _ ! &
111 ' ? < > @ \ ^ ;
When we start looking at the assembly code we see that there are two functions,
CTF that initializes a set of registers and addresses and CTF2 which is
basically a loop through the raw data region at the end of the file.
The initialization looks as follows:
CTF BSS 0
SB1 1 B1 = 1
SA1 CTFB A1 = &CTFB, X1 = *CTFB
BX6 X1 X6 = X1
SB7 27 B7 = 27
SA6 A1 A6 = &CTFB, *CTFB = X6
SA2 CTFA A2 = &CTFA, X2 = *CTFA
MX0 30 X0 = 30 bit mask of 1 from top
SA1 A2+B1 A1 = A2+1 = CTFA+1, X1= *(CTFA+1)
The CTF2 loop looks as follows:
CTF2 BX6 X0*X1 X6 = X0 AND X1 (clear lower 30bit)
ZR X6,CTF4 X6 = 0 ? CTF4
JR FCT call FCT
SA6 A6+B1 A6 = A6 + 1; *(A6+1) = X6
BX6 -X0*X1 X6 = -X0 AND X1 (inverted X0)
ZR X6,CTF4 X6 = 0 ? CTF4
JR FCT call FCT
SA6 A6+B1 A6 = A6 + 1; *(A6+1) = X6
SA1 A1+B1 A1 = A1 + 1; X1 = *(A1+1)
NZ X1,CTF2
CTF2 loads a word and processes the top 30 bits first and then the lower 30
bits. CTF2 then calls a subroutine that either just counts the number of bits
for each half word or looks at the first word in the buffer and shifts it right
to extract some part of special character for extra fun.
The FCT subroutine looks as follows:
FCT SUBR
CX6 X6 X6 = number of 1's in X6
SB6 X6 B6 = X6
LT B6,B7,FCT2 B6 < B7? goto FCT2
SB6 B6-B7 B6 = B6 - B7
SB6 B6+B6 B6 = 2*B6 < 2 B6
SB5 B6+B6 B5 = 2*B6 < 4 B6
SB5 B5+B5 B5 = 2*B5 < 8 B6
SB6 B5+B6 B6 = B5+B6 < 10 B6
AX6 X2,B6 X6 = X2 >> B6
MX7 -10 X7 = 53 bit mask of 1 from top 110101=53
BX6 -X7*X6 X6 = last 7 bits
FCT2 JP FCTX
If the number of 1 bits in the 30 bit half word is lower than 27 then we just
print the character. If it is 28 to 30 then we do (nrbits-27)*10 and shift the
first word of memory that many bits to the right and then store it as
character.
Note that the loop jumps over the first data word and starts processing from
the 1st word on. But the 0 data word is used for the two parentheses ( ) in the
flag.
So the algorithm is as follows: for each 60bit word, first look at the higher
30 bits, count the bits, use the lookup table above to encode the character.
Then look at the lower 30 bit word, count bits and look up the character.
Now let's look at the data block:
0000000052 0244120057 3=C 9=I // 0 address, ignored
4021000310 0774415040 6=F 12=L
0000040000 0442211001 1=A 7=G
7777677777 0010002004 29=2=20; 520244>>2= 0.101.001_00 = 051 = ( 3=C
7737757761 0040000400 25=Y 2=B
0010020034 3556115671 5=E 18=R
0000000444 1625031752 3=C 15=O
6301523622 7165273762 14=N 20=T
2716771305 7111504353 18=R 15=O
1420532413 0006000100 12=L 3=C
6777567373 6000000000 25=Y 2=B
1000700020 4666666661 5=E 18=R
1001001001 0002000000 4=D 1=A
3567107765 0001000000 20=T 1=A
7000000000 7677737566 3=C 25=Y
4000000004 4000700004 2=B 5=E
5713542707 2000400010 18=R 3=C
5471065072 2667170671 15=O 18=R
3750335406 1653521704 16=P 15=O
6753156470 0000000004 18=R 1=A
1234567767 4127002011 20=T 9=I
2731534064 7003653700 15=O 14=N
77777777770000000000B 30=3=30; 052 = )
00000000000000000055B
And we get the flag FLAG(CYBERCONTROLCYBERDATACYBERCORPORATION)
You can find some more information at Wikipedia, ISA manual or
Subroutines.