一道题说明call system 与system plt调用的区别
一道题说明call system 与system plt调用的区别
题目为:buuctf wustctf2020_getshell_2
拿到题目,我们先checksec一下:
我们拖入IDA中:
非常明显的栈溢出,但是我们在构建payload的时候,发现了字节是不够的:
1 | payload = b"A"*(0x18+0x4) + p32(system_plt_addr) + p32(0) + p32(sh_addr) |
这样书写,是多了4个字节的,我们无法获取shell的,我们可以详细看看system_plt_addr干了什么:
可以看到他是直接跳转到某个地址,然后开始执行system函数的,那莫p32(0)就不能缺少,但是题目中有shell函数,其中有一条命令是call system,如果用这个指令,就可以少发送4个字节:
1 | payload = b"A"*(0x18+0x4) + p32(call_system) + p32(sh_addr) |
这是为啥呢?其实call 指令内含两条指令,一条是将下一条要执行的命令地址(rip)压入栈中,接下来再进行跳转到某个地址:
接下来会将0x804852e压入栈中,然后就会跳转:
此时相当于它自己造了一个p32(0),也就能取到sh的地址并传入了,其实本质是符合了正常函数的调用流程,用plt表跳入省略了将返回地址压入栈这一步操作,所以需要我们构造返回地址,而call 就不需要了,因为call 是正常的函数调用。payload如下:
1 | from pwn import * |