Give it a Go 2: CTF Writeup
Reverse engineering
1. Password protected secret
Solution:
> strings -a challenge1 | grep CTF
traceStopReadCPU called with trace enabledattempted to trace a bad status for a procout of memory allocating checkmarks bitmapThe flag is CTF{YnSS2Wen_Something_random}
Explanation:
When reverse engineering simple executables, despite the file being binary, text data is easily extractable. There is usually no encryption applied on top. There is no need to even run the program.
2. Garbled
Solution:
This should really be considered hard rather than medium because it requires knowledge of assembly.
It is pretty much the same binary as challenge 1 but obfuscated via garble. We know that there is some comparison happening followed by a conditional branch/jump. Even without pulling out the debugger or decompiler, this is solvable with objdump some grep. The binary is for x86_64, for which the instruction for comparisons is cmp and jne for jump if not equals.
> objdump -d -M intel ./challenge2 | grep -E -B1 -A2 "cmp" | grep -E "jne" | wc -l
2210
Purely searching for where there is a cmp followed by a jne yields too many results to sift through.
...
585e6b: 83 3d 5e 69 16 00 00 cmp DWORD PTR [rip+0x16695e],0x0 # 0x6ec7d0
585e72: 75 07 jne 0x585e7b
585e74: 4c 8b 64 24 50 mov r12,QWORD PTR [rsp+0x50]
--
585ed0: 83 3d f9 68 16 00 00 cmp DWORD PTR [rip+0x1668f9],0x0 # 0x6ec7d0
585ed7: 75 09 jne 0x585ee2
585ed9: 4c 8b 7c 24 48 mov r15,QWORD PTR [rsp+0x48]
--
58614a: 48 39 d0 cmp rax,rdx
58614d: 75 0e jne 0x58615d
58614f: 4d 89 dd mov r13,r11
--
586609: 48 83 78 10 00 cmp QWORD PTR [rax+0x10],0x0
58660e: 75 40 jne 0x586650
586610: 48 39 fe cmp rsi,rdi
We can generally ignore most of the QWORD/DWORD PTR or cmp with 2 registers since we know we have 1 register and 1 constant (you can tell by disassembling challenge1 which has the proper symbols and isn't deobfuscated).
> objdump -d -M intel ./challenge2 | grep -E -B1 -A2 "cmp.*(rax|eax|rbx|ebx|rcx|ecx|rdx|edx|rdi|edi|rsi|esi),0x[0-9a-f]{4,}" | grep -E "jne | wc -l
42
Just by filtering for common registers and a constant, we significantly reduce the number of cases. By reverse engineering challenge1 you can also tell that an xor is used against the user entered password before comparison.
> objdump -d -M intel ./challenge2 | grep -E -B2 -A2 "cmp.*(rax|eax|rbx|ebx|rcx|ecx|rdx|edx|rdi|edi|rsi|esi),0x[0-9a-f]{4,}" | grep -B2 -A2 -E "jne" | grep -B2 -A2 -E "xor"
--
47277f: 75 0d jne 0x47278e
472781: c5 f9 ef c0 vpxor xmm0,xmm0,xmm0
472785: 48 81 fb 00 00 00 02 cmp rbx,0x2000000
--
--
57fe48: 81 fa 00 40 00 00 cmp edx,0x4000
57fe4e: 75 07 jne 0x57fe57
57fe50: 31 c0 xor eax,eax
--
584743: 0f 85 4a 08 00 00 jne 0x584f93
584749: 48 35 0d 5d 00 00 xor rax,0x5d0d
58474f: 48 3d 13 60 07 00 cmp rax,0x76013
584755: 75 4c jne 0x5847a3
This makes it quite obvious that the keys are 0x5d0d and 0x76013.
> python3 -c "print(0x05d0d ^ 0x76013)"
474398
Running challenge2 and entering 474398 gives the correct flag:
The flag is CTF{HnS=Y2Fan}
3. Legacy code
Uhh... Ignore this one for now. Requires you to get a VM working for an AIX IBM machine with the PowerPC architecture.
Cryptography
WIP