栈上的Partial-Overwrite
原理:对于开了PIE保护的程序,每次的指令地址都是随机的,但是地址的最后十二位总是固定的,也就是ida对于的地址,我们只要修改最后十二位地址,就可以控制程序流程了,但是修改数据只能整字节修改,无法直接修改12位,所以一般都是直接修改两个字节,对于第十二位到第十六位就一个一个试,比如一个函数的地址是0x30a,我们想要程序跳到这里,可以这样构造/x0a/xy3,y属于0到f,一个一个试,总会对的。或者固定一个值,让程序连接多次,16分之一的概率。
例题:
1 | __int64 sub_960() |
可以看见这个程序还有canary保护,read函数碰到\0会停止读取,我们只要一直覆盖到canary处就可以了,不过要加1,因为canary最后一个字节是\x00,也得把他覆盖掉才行。
最后payload
1 | from pwn import * |
循环的原因就是y不确定,所以假设为0,如果程序真为0就会控制成功,如果不成功就会再连接一次
顺便来补一个程序保护
Pwn保护说明
1.Arch:
说明程序的架构,位数,和是大端序还是小端序
2.RELR:
设置符号重定位表为只读或者在程序启动时就解析所有动态符号,从二建扫对got表的攻击
编译选项:关闭: -z morello 开启部分:-z lazy 开启全部:-z now
stack:
栈保护溢出
编译选项:关闭:-fon-stack-protector 开启:-fstack_protector-all
NX:
堆栈不可执行
编译选项:关闭-z execstack 开启:-z noexecstack
PIE:
内存地址随机化(linux下pie启动必须同时开始aslr)
编译选项:关闭 -no-pie 开启 -pie ifPIC
RWX:
bss段可执行