2022年3月21栈迁移
这道题是栈迁移
1)先checksec一下
嗯哼哼,貌似影响不大
2)丢在ida里瞅
1、main()
没啥用再看看其它的
2、vul()
第一个read读进去的东西,可以被printf呸!吐出来!
芜湖!看到了第二个read可以栈溢出,但是可以溢出的空间太少!
————————那么就要来到了,刚学习的栈迁移——————————
3、hack()
芜湖看到system函数了,那我们就可以获得system的返回地址从而调用system
3)构造payload
首先我们先想一想
1、printf的作用?
肯定是让我们泄露什么!
我们刚刚说到,要用栈迁移,那么我们我就需要泄露ebp的地址。
所以我们想到用b'a'*(0x27) + b'b'填满栈
然后用printf就会顺带将ebp打印出来
什么printf能打印?
A:"%s"是打印字符串,那么字符串结束的标志是什么???
Q:是/x00!/x00有时候又可以用来截断字符串,并且/x00占据一个字节(这是即使你不打,程序也会自动帮你添上的。)
那么如果我将栈填满
0x00就没地方了,它就会顺着打印,而接下来就是esp的地址了
我们只需要令
orginal_addr = u32(p.recv(4))
就可以获得了
2、继续想
栈迁移核心思想就是利用leave和ret转移ebp和esp。leave和ret常用于复原栈
leave=mov esp,ebp
pop ebp
ret=pop eip
我们看ebp寄存器里面存的其实就是栈上ebp的地址 ,为上层函数main的old ebp,它与缓冲区变量相差0x38
然后我理解的栈迁移是这样的
esp的作用还原栈的最初的模样
“原来我们还是caller的模样”
然后我们通过将ebp的位置改变到现在esp的位置,也就是我们输入的缓冲区的起始位置。
3、理解payload构造过程
a、大小。首先刚开始的第一遍我们在执行read函数,它只允许我们达到0x30的大小,所以payload3
的长度应该控制在0x30之内。(?padding的大小可以商榷吗)
b、我们第一次在执行read函数,在buf的缓冲区有长达0x28的位置,我们做不了什么,不可执行,但是我们通过修改ebp到(old_ebp-0x38),将我们写入的东西通通算进栈中执行。
c、这里我认为有两个定位的东西。
首先是我们放在payload开头的b'aaaa',用于计算和控制ebp返回的位置到这里。
其次是old_ebp,因为它的大小可以通过printf泄露,作为一个固定的已知地址,计算其他需要的信息(new_ebp和bin_sh_addr)的偏移量。
d、理解一下leave|ret
有一些图片是网上找其他师傅的的,如有侵权请联系我删除 !!
谢谢各位师傅支持