使用ida查看程序,首先保存esp和_exit地址,随后将输出的字符串压栈:
1 | push esp |
随后执行输入函数:
1 | xor ebx, ebx ; fd |
由于ecx在之前已经被赋值为esp,所以put
函数仍是对同一个变量(输出的字符串)进行输入。使用gdb-peda
的checksec
查看,虽然显示NX: enable
,但是通过vmmap
执行,发现栈是可执行的。使用pattern create
和pattern offset
获取偏移量为20。因此构造的payload结构如下:
1 | 'a' * 20 + [ret addr] + getshell |
因为要获取栈的地址来达到ret2shellcode的目的,所以需要通过write
泄漏栈地址。在程序运行的开始,执行了:
1 | push esp |
在put函数后,执行:
1 | add esp, 14h |
使得字符串参数、_exit
被移出栈、pop,栈顶从而变为之前储存的esp
。因此在第一个put
函数执行时,输入:
1 | 'a' * 20 + 0x8048087 |
便可以打印出esp
的地址。获取esp
的地址后,将会继续再次执行put
函数(此时ecx
仍为字符串参数的地址),此时输入:
1 | 'a' * 20 + [ret addr] + getshell |
即可。需要注意shellcode长度以满足输入的条件(3Ch)。