easyre
153 points
Please submit the flag like RCTF{flag}.
We are given a Linux application, that asks for input and exits:
1
2
3
4
5
$ ./easy_re
OMG!!!! I forgot kid's id
Ready to exit
AAAA
After reversing the application in Snowman
we see the rough outline:
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
...
pipe(esp1 + 6);
eax3 = fork(esp1 + 6);
esp4 = reinterpret_cast<int32_t*>(esp1 - 1 + 1 - 1 + 1);
if (!eax3) {
puts("\nOMG!!!! I forgot kid's id", v5, v6);
write(v7, "69800876143568214356928753", 29);
puts("Ready to exit ", "69800876143568214356928753", 29);
exit(0, "69800876143568214356928753", 29);
esp4 = esp4 - 1 + 1 - 1 + 1 - 1 + 1 - 1 + 1;
}
read(v8, reinterpret_cast<uint32_t>(esp4) + 46, 29);
esp9 = reinterpret_cast<void*>(esp4 - 1 + 1);
__isoc99_scanf("%d", reinterpret_cast<uint32_t>(esp9) + 36, 29);
esp10 = reinterpret_cast<void*>(reinterpret_cast<uint32_t>(esp9) - 4 + 4);
if (v11 == eax3) {
eax12 = g80485f7;
if ((eax12 & 0xff) == 0xcc) {
puts(":D", reinterpret_cast<uint32_t>(esp9) + 36, 29);
exit(1, reinterpret_cast<uint32_t>(esp9) + 36, 29);
esp10 = reinterpret_cast<void*>(reinterpret_cast<uint32_t>(esp10) - 4 + 4 - 4 + 4);
}
printf("\nYou got the key\n ", reinterpret_cast<uint32_t>(esp9) + 36, 29);
lol(reinterpret_cast<uint32_t>(esp10) - 4 + 4 + 46, reinterpret_cast<uint32_t>(esp9) + 36, 29);
}
...
The above code:
- Opens a pipe for communication
- Forks
- The parent application writes to pipe and exits
- The forked child reads from the pipe and reads a number from keyboard (it expects the entered value to match the PID of the child)
- Forked child then does some work in
lol
function:
1
2
3
4
5
6
7
8
9
10
11
12
void lol(void* a1, void* a2, int32_t a3) {
void* v4;
int32_t v5;
int32_t v6;
if (1) {
printf("flag_is_not_here", v4, v5);
} else {
printf("%s", reinterpret_cast<int32_t>(__zero_stack_offset()) - 4 - 19, v6);
}
return;
}
Notice that there is a dead branch in this method that seems to output something. Let’s go to the disassembled code (objdump -d -M intel ./easy_re
):
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
080485f4 <lol>:
80485f4: 55 push ebp
80485f5: 89 e5 mov ebp,esp
80485f7: 83 ec 28 sub esp,0x28
80485fa: 8b 45 08 mov eax,DWORD PTR [ebp+0x8] # some interesting calculations happening here
80485fd: 83 c0 01 add eax,0x1
8048600: 0f b6 00 movzx eax,BYTE PTR [eax]
8048603: 89 c2 mov edx,eax
8048605: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]
8048608: 83 c0 01 add eax,0x1
804860b: 0f b6 00 movzx eax,BYTE PTR [eax]
804860e: 8d 04 02 lea eax,[edx+eax*1]
8048611: 88 45 ed mov BYTE PTR [ebp-0x13],al
8048614: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]
8048617: 83 c0 04 add eax,0x4
804861a: 0f b6 00 movzx eax,BYTE PTR [eax]
804861d: 89 c2 mov edx,eax
804861f: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]
8048622: 83 c0 05 add eax,0x5
8048625: 0f b6 00 movzx eax,BYTE PTR [eax]
8048628: 8d 04 02 lea eax,[edx+eax*1]
804862b: 88 45 ee mov BYTE PTR [ebp-0x12],al
804862e: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]
8048631: 83 c0 08 add eax,0x8
8048634: 0f b6 00 movzx eax,BYTE PTR [eax]
8048637: 89 c2 mov edx,eax
8048639: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]
804863c: 83 c0 09 add eax,0x9
804863f: 0f b6 00 movzx eax,BYTE PTR [eax]
8048642: 8d 04 02 lea eax,[edx+eax*1]
8048645: 88 45 ef mov BYTE PTR [ebp-0x11],al
8048648: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]
804864b: 83 c0 0c add eax,0xc
804864e: 0f b6 00 movzx eax,BYTE PTR [eax]
8048651: 89 c2 mov edx,eax
8048653: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]
8048656: 83 c0 0c add eax,0xc
8048659: 0f b6 00 movzx eax,BYTE PTR [eax]
804865c: 8d 04 02 lea eax,[edx+eax*1]
804865f: 88 45 f0 mov BYTE PTR [ebp-0x10],al
8048662: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]
8048665: 83 c0 12 add eax,0x12
8048668: 0f b6 00 movzx eax,BYTE PTR [eax]
804866b: 89 c2 mov edx,eax
804866d: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]
8048670: 83 c0 11 add eax,0x11
8048673: 0f b6 00 movzx eax,BYTE PTR [eax]
8048676: 8d 04 02 lea eax,[edx+eax*1]
8048679: 88 45 f1 mov BYTE PTR [ebp-0xf],al
804867c: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]
804867f: 83 c0 0a add eax,0xa
8048682: 0f b6 00 movzx eax,BYTE PTR [eax]
8048685: 89 c2 mov edx,eax
8048687: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]
804868a: 83 c0 15 add eax,0x15
804868d: 0f b6 00 movzx eax,BYTE PTR [eax]
8048690: 8d 04 02 lea eax,[edx+eax*1]
8048693: 88 45 f2 mov BYTE PTR [ebp-0xe],al
8048696: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]
8048699: 83 c0 09 add eax,0x9
804869c: 0f b6 00 movzx eax,BYTE PTR [eax]
804869f: 89 c2 mov edx,eax
80486a1: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]
80486a4: 83 c0 19 add eax,0x19
80486a7: 0f b6 00 movzx eax,BYTE PTR [eax]
80486aa: 8d 04 02 lea eax,[edx+eax*1]
80486ad: 88 45 f3 mov BYTE PTR [ebp-0xd],al
80486b0: c7 45 f4 00 00 00 00 mov DWORD PTR [ebp-0xc],0x0 # we set the value to 0
80486b7: 83 7d f4 01 cmp DWORD PTR [ebp-0xc],0x1 # and then compare it to 1
80486bb: 75 16 jne 80486d3 <lol+0xdf>
80486bd: b8 c0 88 04 08 mov eax,0x80488c0 # this branch will never be taken
80486c2: 8d 55 ed lea edx,[ebp-0x13] # and yet it's the one that prints
80486c5: 89 54 24 04 mov DWORD PTR [esp+0x4],edx # the value built above
80486c9: 89 04 24 mov DWORD PTR [esp],eax
80486cc: e8 ff fd ff ff call 80484d0 <printf@plt>
80486d1: eb 0d jmp 80486e0 <lol+0xec>
80486d3: b8 c3 88 04 08 mov eax,0x80488c3
80486d8: 89 04 24 mov DWORD PTR [esp],eax
80486db: e8 f0 fd ff ff call 80484d0 <printf@plt>
80486e0: c9 leave
80486e1: c3 ret
As it turns out the decompiled C code does not reveal everything, there is a bunch of calculations occurring in that function, and yet the calculated value is abandoned and flag_is_not_here
is printed instead.
To reveal that value let’s patch out the executable and replace cmp DWORD PTR [ebp-0xc],0x1
with cmp DWORD PTR [ebp-0xc],0x0
. This can be done in any binary editor. Essentially we are replacing 83 7d f4 01
with 83 7d f4 00
.
Once the binary is patched we can run it. To figure out the PID we can first run the application, and while it’s waiting for input run ps
in a separate shell:
1
2
3
4
$ ps -ef | grep easy
root 1695 1529 0 15:54 pts/0 00:00:00 ./easy_re_patched
root 1696 1695 0 15:54 pts/0 00:00:00 [easy_re_patched] <defunct>
root 1702 1536 0 15:55 pts/1 00:00:00 grep easy
When we enter the PID we get the flag:
1
2
3
4
5
6
7
8
$ ./easy_re_patched
OMG!!!! I forgot kid's id
Ready to exit
1696
You got the key
rhelheg
The flag is RCTF{rhelheg}
.