Description
[EN]
Scavenging an old 318br repo, we found a program missing some line of code. Even without this line, we would like to know the result of
its execution.
Specific instruction: Put the flag on the format 3DS{} and submit.[PT]
Vasculhando um repositorio antigo do 318br, nos encontramos um programa faltando uma parte. Mesmo faltando uma parte, nos gostariamos que voce nos dissesse o resultado de sua execucao.
Instrucao especifica: Colocar o resultado no formato 3DS{} e submeter.Solved by 19 Teams
Resolution
The given zip file contains 33 files like this:
****************** Third Development Software Company for DEC9 ********************* 0 1 2 3 4 5 6 7 8 12345678901234567890123456789012345678901234567890123456789012345678901234567890 ________________________________________________________________________________ 12 /O 11|X 0|X 1|X O 2|X O 3|XO O 4|X O 5|X 6|X 7|X 8|X 9|X |_________________________________________________________________________________
It a simple Punched Card like this one:
How does it works? It’s very simple!
_________ 12 /O 11|X 0|X 1|X O 2|X O 3|XO O
The 2 first raws (12 and 11) are kind of “multiplier factor”, and the others (0-9) are the values.
- In the first column there are 2 holes (the O) : one at the raw 12, one at the raw 3.
The raw 12 adds 10 to the result 2, so for the first column it gave 12. - The second column there’s 1 hole in the raw 1, so it gave 1.
As the simplified charset is : 0-9, A-Z, we can deduce that 12 is a C, 1 is 1 etc. so the card was “C123” 🙂
The real charsets are:
029 &-0123456789ABCDEFGHIJKLMNOPQR/STUVWXYZ:#@'="¢.<(+|!$*);¬ ,%_>? IBME ¹-0123456789ABCDEFGHIJKLMNOPQR/STUVWXYZ:#²'="].<(+|[$*);¬³,%_>? EBCD &-0123456789ABCDEFGHIJKLMNOPQR/STUVWXYZ:#@'="[.<(+|]$*);^\,%_>?
A basic representation of the conversion:
12 value: [ not holed | holed ] 11 value: [ not holed | holed ] 0-9 value: [0|1|2|3|4|5|6|7|8|9|1|2|3|4|5|6|7|8|9|1|2|3|4|5|6|7|8|9] ASCII res: [0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R]
For the rest of the letters and special chars, it’s a little bit more complex.
You can refer to the script below.
The 3rd card was complex to handle manually:
****************** Third Development Software Company for DEC9 ********************* 0 1 2 3 4 5 6 7 8 12345678901234567890123456789012345678901234567890123456789012345678901234567890 ________________________________________________________________________________ 12 / O O O 11|X OOO O O OO OO 0|X 1|X O 2|X 3|X 4|X O O 5|X 6|X O 7|X O O O O 8|X 9|X O O O O |_________________________________________________________________________________
1st column: 11 is holed + 7 = P
2nd column: 11 is holed + 9 = R
3rd column: 11 is holed + 6 = O
4th column: 12 is holed + 7 = G
5th column: 11 is holed + 9 = R
6th column: 12 is holed + 1 = A
7th column: 11 is holed + 4 = M
etc.
Giving PROGRAM PRGRM
It’s an instruction in Fortran.
As decoding all the cards is quite boring, we made a script to do that:
#!/usr/bin/python2 # Based on a write up for the Boston Key Party CTF 2015, task Haymarket def decode(code): if code == ['0']: return '0' elif code == ['1']: return '1' elif code == ['2']: return '2' elif code == ['3']: return '3' elif code == ['4']: return '4' elif code == ['5']: return '5' elif code == ['6']: return '6' elif code == ['7']: return '7' elif code == ['8']: return '8' elif code == ['9']: return '9' elif code == ['12', '1']: return 'A' elif code == ['12', '2']: return 'B' elif code == ['12', '3']: return 'C' elif code == ['12', '4']: return 'D' elif code == ['12', '5']: return 'E' elif code == ['12', '6']: return 'F' elif code == ['12', '7']: return 'G' elif code == ['12', '8']: return 'H' elif code == ['12', '9']: return 'I' elif code == ['11', '1']: return 'J' elif code == ['11', '2']: return 'K' elif code == ['11', '3']: return 'L' elif code == ['11', '4']: return 'M' elif code == ['11', '5']: return 'N' elif code == ['11', '6']: return 'O' elif code == ['11', '7']: return 'P' elif code == ['11', '8']: return 'Q' elif code == ['11', '9']: return 'R' elif code == ['0', '1']: return '/' elif code == ['0', '2']: return 'S' elif code == ['0', '3']: return 'T' elif code == ['0', '4']: return 'U' elif code == ['0', '5']: return 'V' elif code == ['0', '6']: return 'W' elif code == ['0', '7']: return 'X' elif code == ['0', '8']: return 'Y' elif code == ['0', '9']: return 'Z' elif code == ['11', '2', '8']: return '!' elif code == ['4', '8']: return '@' elif code == ['3', '8']: return '#' elif code == ['11', '3', '8']: return '$' elif code == ['0', '4', '8']: return '%' elif code == ['12', '7', '8']: return '^' elif code == ['12']: return '&' elif code == ['11', '4', '8']: return '*' elif code == ['12', '5', '8']: return '(' elif code == ['11', '5', '8']: return ')' elif code == ['11']: return '-' elif code == ['6', '8']: return '=' elif code == ['0', '5', '8']: return '_' elif code == ['0', '3', '8']: return ',' elif code == ['12', '6', '8']: return '+' elif code == ['12', '2', '8']: return '[' elif code == ['0', '2', '8']: return '[' elif code == ['11', '6', '8']: return ';' elif code == ['0', '6', '8']: return '>' elif code == ['5', '8']: return "'" elif code == ['2', '8']: return ':' elif code == ['7', '8']: return '"' elif code == ['11', '7', '8']: return ' ' elif code == ['12', '3', '8']: return '.' elif code == ['12', '4', '8']: return '<' else: return '?' lines = list() for num in range(1,34): card = "card-" + str(format(num,'02')) + "-34.dec" file = open(card, "r") for line in file: lines.append(line) code = [] text = "" for c in range (80): for r in range (12): if lines[r+4][c+3] == "O": if r==0: code.append('12') if r==1: code.append('11') if r!=0 and r!=1: code.append(str(r-2)) if len(code) > 0: text += decode(code) code = [] print text lines = [] file.close()
Giving us:
C1234 C234567890123456789012345678901234567890 PROGRAMPRGRM INTEGERC,X DOUBLEPRECISIONI,R,A DOUBLEPRECISIONRES GOTO1598 1599A=1/RES GOTO2852 0666GOTO0665 7599A=-1/RES GOTO2852 1598C=1337 RES=1 X=0 1337X=X GOTO5523 0318I=I*4 PRINT*,I GOTO0666 5523IF(MOD(X,2).EQ.0)THEN GOTO1599 ELSE GOTO7599 ENDIF 2852I=I+A GOTO9513 9513RES=RES+2 X=X+1 IF(X.EQ.C)THEN GOTO0318 ENDIF GOTO1337
As they told in the task description, there was some code missing:
0666 GOTO 0665, but there’s no 0665, no “END PROGRAM” etc.
We modified the code to:
!C1234 !C234567890123456789012345678901234567890 PROGRAM PRGRM INTEGER C,X DOUBLE PRECISION I,R,A DOUBLE PRECISION RES GOTO 1598 1599 A=1/RES GOTO 2852 666 GOTO 665 7599 A=-1/RES GOTO 2852 1598 C=1337 RES=1 X=0 1337 X=X GOTO 5523 318 I=I*4 PRINT *,I GOTO 666 5523 IF(MOD(X,2).EQ.0) THEN GOTO 1599 ELSE GOTO 7599 ENDIF 2852 I=I+A GOTO 9513 9513 RES=RES+2 X=X+1 IF(X.EQ.C)THEN GOTO 318 ENDIF GOTO 1337 665 STOP END PROGRAM
Then executed it on an online interpreter: https://www.jdoodle.com/execute-fortran-online.
Note: The following floating-point exceptions are signalling: IEEE_DENORMAL 3.1423405966415094
Flag was 3DS{3.1423405966415094}