Simple Reverse - 0x29(2023 Lab - Unpackme)
Source code
1 |
|
:::spoiler Real File main Function
1 |
|
:::
Recon
這一題一開始就知道是UPX加殼,但是直接試了upx幫忙decompress,卻遇到error,代表可能有一些問題(在Unix環境底下?),所以我嘗試使用手動脫殼,去分析其中的內容
- 首先可以先靜態看一下脫完殼之前是在哪邊跳轉,經過實測和判斷,應該是:
1
LOAD:0000000000005AF5 jmp r13
:::info 如何在動態取得這一行的位置呢?手動算出rebase address
- 首先先用靜態分析看starti的時候的offset
- 開始動態執行程式
- 把目前指到的address拿去和靜態分析拿到的offset相減
- (optional)可以用vmmap確認一下
- 再把我們想要得知的那一行的offset加回來
一開始的offset是0x5888
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23gef➤ starti gef➤ x/x 0x7ffff7ffd888-0x5888 0x7ffff7ff8000: 0x7f gef➤ vmmap [ Legend: Code | Heap | Stack ] Start End Offset Perm Path 0x00007ffff7ff2000 0x00007ffff7ff6000 0x0000000000000000 r-- [vvar] 0x00007ffff7ff6000 0x00007ffff7ff8000 0x0000000000000000 r-x [vdso] 0x00007ffff7ff8000 0x00007ffff7ff9000 0x0000000000000000 rw- /mnt/d/NTU/Second Year/Computer Security/Reverse/Lab3/Unpackme/unpackme 0x00007ffff7ff9000 0x00007ffff7ffd000 0x0000000000000000 rw- 0x00007ffff7ffd000 0x00007ffff7fff000 0x0000000000000000 r-x /mnt/d/NTU/Second Year/Computer Security/Reverse/Lab3/Unpackme/unpackme 0x00007ffffffdd000 0x00007ffffffff000 0x0000000000000000 rw- [stack] gef➤ x/10i 0x7ffff7ff8000+0x5AF5 0x7ffff7ffdaf5: jmp r13 0x7ffff7ffdaf8: pop rbp 0x7ffff7ffdaf9: call 0x7ffff7ffda7c 0x7ffff7ffdafe: (bad) 0x7ffff7ffdaff: jo 0x7ffff7ffdb73 0x7ffff7ffdb01: outs dx,DWORD PTR ds:[rsi] 0x7ffff7ffdb02: movsxd ebp,DWORD PTR [rdi] 0x7ffff7ffdb04: jae 0x7ffff7ffdb6b 0x7ffff7ffdb06: ins BYTE PTR es:[rdi],dx 0x7ffff7ffdb07: data16 (bad)
:::
- 利用動態看r13的address會跳去哪邊$\to$0x00007ffff7ff1000
- 接下來我找不太到分析的地方,所以就直接c(continue)到user input的地方停下來,再看vmmap
:::spoiler vmmap
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[ Legend: Code | Heap | Stack ] Start End Offset Perm Path 0x00007ffff7d84000 0x00007ffff7d87000 0x0000000000000000 rw- 0x00007ffff7d87000 0x00007ffff7daf000 0x0000000000000000 r-- /usr/lib/x86_64-linux-gnu/libc.so.6 0x00007ffff7daf000 0x00007ffff7f44000 0x0000000000028000 r-x /usr/lib/x86_64-linux-gnu/libc.so.6 0x00007ffff7f44000 0x00007ffff7f9c000 0x00000000001bd000 r-- /usr/lib/x86_64-linux-gnu/libc.so.6 0x00007ffff7f9c000 0x00007ffff7fa0000 0x0000000000214000 r-- /usr/lib/x86_64-linux-gnu/libc.so.6 0x00007ffff7fa0000 0x00007ffff7fa2000 0x0000000000218000 rw- /usr/lib/x86_64-linux-gnu/libc.so.6 0x00007ffff7fa2000 0x00007ffff7faf000 0x0000000000000000 rw- 0x00007ffff7fb3000 0x00007ffff7fb5000 0x0000000000000000 rw- 0x00007ffff7fb5000 0x00007ffff7fb7000 0x0000000000000000 r-- /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 0x00007ffff7fb7000 0x00007ffff7fe1000 0x0000000000002000 r-x /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 0x00007ffff7fe1000 0x00007ffff7fec000 0x000000000002c000 r-- /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 0x00007ffff7fec000 0x00007ffff7fed000 0x0000000000000000 --- 0x00007ffff7fed000 0x00007ffff7fef000 0x0000000000037000 r-- /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 0x00007ffff7fef000 0x00007ffff7ff1000 0x0000000000039000 rw- /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 0x00007ffff7ff2000 0x00007ffff7ff6000 0x0000000000000000 r-- [vvar] 0x00007ffff7ff6000 0x00007ffff7ff8000 0x0000000000000000 r-x [vdso] 0x00007ffff7ff8000 0x00007ffff7ff9000 0x0000000000000000 r-- 0x00007ffff7ff9000 0x00007ffff7ffa000 0x0000000000000000 r-x 0x00007ffff7ffa000 0x00007ffff7ffc000 0x0000000000000000 r-- 0x00007ffff7ffc000 0x00007ffff7ffd000 0x0000000000000000 rw- 0x00007ffff7ffe000 0x00007ffff7fff000 0x0000000000000000 r-- /mnt/d/NTU/Second Year/Computer Security/Reverse/Lab3/Unpackme/unpackme 0x00007ffff7fff000 0x00007ffff8020000 0x0000000000000000 rw- [heap] 0x00007ffffffdd000 0x00007ffffffff000 0x0000000000000000 rw- [stack]
::: 可以看到
0x00007ffff7ff8000
開始會有ELF的字樣,代表應該是他脫殼完的結果,我的作法是直接把0x00007ffff7ff8000
~0x00007ffff7ffd000
全部dump下來進行分析1
2
3gef➤ x/s 0x00007ffff7ff8000 0x7ffff7ff8000: "77ELF
02gef➤ x/s 0x00007ffff7ff8000 0x7ffff7ff8000: "\177ELF\002\001\001" gef➤ dump memory real_file 0x00007ffff7ff8000 0x00007ffff7ffd000
01gef➤ x/s 0x00007ffff7ff8000 0x7ffff7ff8000: "\177ELF\002\001\001" gef➤ dump memory real_file 0x00007ffff7ff8000 0x00007ffff7ffd000
01" gef➤ dump memory real_file 0x00007ffff7ff8000 0x00007ffff7ffd000gef➤ x/s 0x00007ffff7ff8000 0x7ffff7ff8000: "\177ELF\002\001\001" gef➤ dump memory real_file 0x00007ffff7ff8000 0x00007ffff7ffd000
- 開始分析real_file,先用靜態看一下(如source code所示)
- 找到我們要停的地方的offset$\to$
0x1213
1
2
3
4
5
6
7
8
9
10
11gef➤ x/10i 0x00007ffff7ff8000+0x1213 0x7ffff7ff9213: mov rcx,QWORD PTR [rip+0x2dfe] # 0x7ffff7ffc018 0x7ffff7ff921a: lea rax,[rbp-0x50] 0x7ffff7ff921e: mov edx,0xa 0x7ffff7ff9223: mov rsi,rcx 0x7ffff7ff9226: mov rdi,rax => 0x7ffff7ff9229: call 0x7ffff7ff90c0 0x7ffff7ff922e: test eax,eax 0x7ffff7ff9230: je 0x7ffff7ff924b 0x7ffff7ff9232: lea rax,[rip+0xe13] # 0x7ffff7ffa04c 0x7ffff7ff9239: mov rdi,rax
可以看到解析出來的assembly和IDA的差不多,代表我們找對地方
- 設定breakpoint後continue就可以在stack中看到key
1
2
3
4
5
6
7
8gef➤ b *(0x00007ffff7ff9000+0x229) Breakpoint 1 at 0x7ffff7ff9229 gef➤ c Continuing. adjfl Breakpoint 1, 0x00007ffff7ff9229 in ?? ()
────────────────────────────────────────────────────────────────────────────────────────── arguments (guessed) ──── 0x7ffff7ff90c0 ( $rdi = 0x00007fffffffd6c0 → 0x0000006c666a6461 ("adjfl"?), $rsi = 0x00007ffff7ffa030 → "just_a_key", $rdx = 0x000000000000000a, $rcx = 0x00007ffff7ffa030 → "just_a_key" )
Exploit
key: just_a_key
1 |
|
Flag: FLAG{just_4_simple_unpackme_challenge!}