CrewCTF - ez rev
Source Code
:::spoiler IDA Fake Main Function
1 |
|
:::
Recon
首先這一題真的太難了,超出我的守備範圍,所以我先寫一些當作紀錄,之後可以更快銜接繼續解
- 首先可以執行一下,如果是在Ubuntu 20.04(預設Libc版本是2.31)的版本和其他版本會有不一樣的output
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20$ ldd --version ldd (Ubuntu GLIBC 2.31-0ubuntu9.9) 2.31 Copyright (C) 2020 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Written by Roland McGrath and Ulrich Drepper. $ ./a.out [+] Another flag checker... 123456 [-] No :( $ ldd --version ldd (Ubuntu GLIBC 2.35-0ubuntu3) 2.35 Copyright (C) 2022 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Written by Roland McGrath and Ulrich Drepper. ./a.out [+] Another flag checker... 123456 [-] Why you still here
這是因為他和這隻程式執行的過程有關係
-
用IDA看一下發現有翻譯出main function,但這個main function其實是假的,這個可以從上面的進度條看出來,橘色的部分感覺很可疑,而假的main function卻是在整個進度的後半段,代表可以往前分析一下,但由於整體的流程太長,所以搞事的部分沒辦法分析出來,這要用動態去看會比較清楚(真正的main function是在==sub_40123E()==)
另外也可以用strings xref的方式知道他call strings的地方有兩個,其中一個就是真的main function
- 分析real main function過程大概是
- 用ptrace看有沒有使用debugger,所以這邊要先patch
- 接著輸入flag,放在
0x4200e0
- 接著就是進入
loc_4012FE()
,這邊應該就是做一些檢查,也要patch,會做三次,如果都正確才會真正進入到搞事的function(loc_4013AA
),否則會進到loc_401394
說掰掰,這一段其實就是在檢查libc是不是在正確的版本以利後面的搞事節奏 - 搞事的function做的事情很簡單,就是不斷用*($rbp-0x100e0)(也就是0x00007ffff7da52fd)做一些offset的加減,然後把對應到的address放到$rbp對應的位置
例如:
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
270x7ffffffed8c0: 0x00000000000008c0 0x0000000000000a40 0x7ffffffed8d0: 0x00007ffff7dc4000 0x0000000000000014 0x7ffffffed8e0: 0x00007ffff7de684d 0x00007ffff7de7b6a 0x7ffffffed8f0: 0x00007ffff7dfa174 0x00007ffff7de66c0 0x7ffffffed900: 0x00007ffff7dea01f 0x00007ffff7f06c92 0x7ffffffed910: 0x00007ffff7ec657e 0x00000000004011fc 0x7ffffffed920: 0x00007ffff7ed055f 0x00007ffff7ea9190 0x7ffffffed930: 0x00007ffff7e58eab 0x00007ffff7e70186 0x7ffffffed940: 0x00007ffff7df9a22 0x00007ffff7dea6e3 0x7ffffffed950: 0x00007ffff7e72df5 0x00007ffff7e6ff48 0x7ffffffed960: 0x00007ffff7e6e38c 0x00007ffff7e3561e 0x7ffffffed970: 0x00007ffff7f0873b 0x00007ffff7eb5b65 0x7ffffffed980: 0x00007ffff7e701dc 0x00007ffff7df7da1 0x7ffffffed990: 0x00007ffff7ee37d7 0x00000000004011ee 0x7ffffffed9a0: 0x00000000004011f3 0x00000000004011f8 0x7ffffffed9b0: 0x00007ffff7dea01f(pop rsi; ret) 0x00000000000000ff 0x7ffffffed9c0: 0x00007ffff7de66c0(pop rbp; ret) 0x0000000000420328 0x7ffffffed9d0: 0x00007ffff7f06c92(pop rdx; ret) 0x0000000000000000 0x7ffffffed9e0: 0x00007ffff7e58eab(cmp DWORD PTR [rbp+rdx*1+0x0], esi; ret) 0x00007ffff7dfa174(pop rax; ret) 0x7ffffffed9f0: 0x0000000000000000 0x00007ffff7ed055f(setl al; ret) 0x7ffffffeda00: 0x00000000004011ee 0x00007ffff7dea01f 0x7ffffffeda10: 0x000000000000001a 0x00000000004011f3 0x7ffffffeda20: 0x00007ffff7ec657e 0x0000000000000000 0x7ffffffeda30: 0x0000000038188124 0x00007ffff7e72df5 0x7ffffffeda40: 0x00007ffff7dfa174 0x000000000042029d
- 放完之後就call
memcpy(src=0x00007ffffffed9b0, dest=0x00007ffffffed8b0, n=0x6e50)
,然後執行ROP,沒錯就是ROP,所以他要先在前面檢查libc的版本,讓他可以取得正確的gadget - 現在的問題是因為他存放的ROP太多也很複雜,導致我不知道哪邊其實是確切在執行check flag的環節,我有想說要找system call之類的gadget,但還找不到,所以分析了老半天還是沒結果
Exploit
Discord上別人的腳本 :::spoiler Script
1 |
|
:::
Flag: crewctf{well_i_didnt_know_rop_can_be_so_obnoxious_especially_for_rever_but_if_you_can_find_this_you_are_a_god_rever}