Hello, here’s my take on the picoCTF2019 reverse engineering asm challenges. If you don’t know assembly, please watch a few tutorials on it:
asm1 – Points: 200#
CMP: Compares the first source operand with the second source operand and sets the status flags in the EFLAGS register according to the results. The comparison is performed by subtracting the second operand from the first operand and then setting the status flags in the same manner as the SUB instruction. When an immediate value is used as an operand, it is sign-extended to the length of the first operand.
JG: Jump short if greater (ZF=0 and SF=OF)
JNE: Jump short if not equal (ZF=0)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| asm1:
<+0>: push ebp #
<+1>: mov ebp,esp #
<+3>: cmp DWORD PTR [ebp+0x8],0x37a # 0x345 - 0x37a = -0x35
<+10>: jg 0x512
# -0x35 is greater than 0x512 because it overflowed.
<+12>: cmp DWORD PTR [ebp+0x8],0x345
<+19>: jne 0x50a
<+21>: mov eax,DWORD PTR [ebp+0x8]
<+24>: add eax,0x3
<+27>: jmp 0x529
<+29>: mov eax,DWORD PTR [ebp+0x8]
<+32>: sub eax,0x3
<+35>: jmp 0x529
<+37>: cmp DWORD PTR [ebp+0x8],0x5ff # 0x345 - 0x5ff = -0x2BA
<+44>: jne 0x523
# -0x2BA is not equal to 0x523
<+46>: mov eax,DWORD PTR [ebp+0x8]
<+49>: sub eax,0x3
<+52>: jmp 0x529
<+54>: mov eax,DWORD PTR [ebp+0x8] # eax = 0x348
<+57>: add eax,0x3 # eax = eax + 3
<+60>: pop ebp
<+61>: ret # return eax
|
Next Levels#
The next levels asm2, asm3 and asm4 got a little more complex and solving them was starting to feel like a chore, my mind was hurting and I didn’t want to keep going the manual way. Lucky, I found noahc3 and this writeup I managed to solve them easily.
We’re going to modify the assembly and compile it with GCC,
on my 64 bit Ubuntu I had to install the gcc-multilib package in order to compile 32 bit executables.
Here’s the modified code for the asm3 task:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| .intel_syntax noprefix
.global asm3
asm3:
push ebp
mov ebp,esp
xor eax,eax
mov ah,BYTE PTR [ebp+0x8]
shl ax,0x10
sub al,BYTE PTR [ebp+0xe]
add ah,BYTE PTR [ebp+0xc]
xor ax,WORD PTR [ebp+0x10]
nop
pop ebp
ret
|
What we’re going to do next is to write a simple main.c program that calls the functions with the required arguments:
1
2
3
4
5
6
7
8
| #include <stdio.h>
int main(void) {
printf("Hello World!");
// printf("Flag: %un", asm2(0xe,0x22));
printf("Flag: %un", asm3(0xcdc485c1,0xd6bd5e88,0xe4c1548d));
// printf("Flag: %un", asm4("picoCTF_fdb55"));
}
|
Next we’re going to compile the assembly code, the main.c file and the final executable:
1
2
3
| gcc -m32 -c asm3.S -o asm3.o -fno-stack-protector -no-pie
gcc -m32 -c main.c -o main.o -fno-stack-protector -no-pie
gcc -m32 -o a.out main.o asm3.o -fno-stack-protector -no-pie
|
If we execute a.out we should get our flag.
Thanks for reading!