这次我们再来介绍一个栈的经典题型
在我们先前遇到的题目中,都有着出题人为我们提供的后门函数,如果没有后门函数,我们又该如何自己构建shellcode呢?
带着这个疑问,我们开始今天的学习
如何写入system(/bin/sh)?
由于题目通常都会开启NX保护,所以我们要想在栈中写入字符串是不现实的打算
我们好好想想,在内存块的五个分区中,还有哪个区块是可以为我们自由编辑的,这里我们想到了用来存储未初始化的全局变量区bss段
那么如何写入呢?
我们先前已经知道了,计算机读不懂高级语言,即system(/bin/sh)
先前我们已经通过构造rop的方式用汇编语言指引执行流
这次我们尝试用机器码来将shellcode注入到内存中
常用的shellcode:”\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05”
这个shellcode只有23个字节,当题目的输入字长给的不够多的时候可以使用这个
当然还有第二种构造机器码的方式
shellcode = asm(shellcraft.sh())
但是你很快就会发现,为什么自己在32位情况下可以使用,但是64位下就不行
我们还需要在后面加上amd64才能使其输出64位的机器码
当然我们也可以通过**context.arch = “amd64”**来使环境转化为64位,于是我们在接下来即使不用amd64也能输出64位机器码
例题解析
这里以NewStarCTF 2022新生赛公开赛 的ret2shellcode作为例题讲解
老规矩看一下保护机制,NX开了,看来不能在栈上写入
ida看一下具体情况
int __cdecl main(int argc, const char **argv, const char **envp) |
出现了个mmap函数,用来干什么的?
可以简单理解为 开辟一块空间存放我们输入的值 其地址为第一个参数addr(0x233000)
那么我们的目的就是将shellcode写入这块空间,然后在接下来的栈溢出中控制程序执行流到shellcode
from pwn import* |
其实本质上还是栈溢出控制程序执行流到后门函数,只不过这个后门函数是我们自己存入到程序中的,还是挺好理解的