在 MIPS 平台上运行时动态生成指令并执行 (2)

上次是直接在可执行的栈中写入指令并转移至执行的,这次在当栈和堆都不可执行的情况下,分配空间、写入指令并执行。还是直接看代码吧。

#include <stdio.h>
#include <errno.h>
#include <sys/mman.h>
 
int main(int argc, char *argv[])
{
	unsigned int *insn = NULL;
 
	insn = mmap(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC,
				MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
	if(MAP_FAILED != insn)
	{
		printf("%p\n", insn);
		insn[0] = 0x1000ffff;
		insn[1] = 0x00000000;
		__asm__ volatile (
					"jr %0 \n\t"
					"nop \n\t"
					::"r"(insn)
				);
		munmap(insn, 4096);
	}
	else
	{
		printf("%s\n", strerror(errno));
	}
 
	return 0;
}

在上面的代码中,使用系统调用 mmap 分配了一块 4096 字节的可读写、可执行的私有、匿名 VMA,并在此 VMA 中写入指令并转移至执行了。

我们来看一下此程序的运行时输出与 maps:

0x2ac88000
00400000-00404000 r-xp 00000000 08:04 262145                             /home/heiher/tmp/test
00410000-00414000 rw-p 00000000 08:04 262145                             /home/heiher/tmp/test
2ac64000-2ac88000 r-xp 00000000 08:02 917518                             /lib/ld-2.14.so
2ac88000-2ac8c000 rwxp 00000000 00:00 0 
2ac94000-2ac98000 rw-p 00020000 08:02 917518                             /lib/ld-2.14.so
2ac98000-2aca8000 rw-p 00000000 00:00 0 
2acb4000-2ae0c000 r-xp 00000000 08:02 918040                             /lib/libc-2.14.so
2ae0c000-2ae18000 ---p 00158000 08:02 918040                             /lib/libc-2.14.so
2ae18000-2ae1c000 r--p 00154000 08:02 918040                             /lib/libc-2.14.so
2ae1c000-2ae20000 rw-p 00158000 08:02 918040                             /lib/libc-2.14.so
2ae20000-2ae24000 rw-p 00000000 00:00 0 
7fc04000-7fc28000 rwxp 00000000 00:00 0                                  [stack]
7fff4000-7fff8000 r-xp 00000000 00:00 0                                  [vdso]

我们看到确定多出了一个我们所需要的 VMA:

2ac88000-2ac8c000 rwxp 00000000 00:00 0

但其长度却不是 4096 字节,而是 16K(16384)。这是因为我们当前的操作系统页面长度是 16K(16384),分配一个VMA至少需要一个完整的页面,当小于它的时候也需要分配一个完整的页面。

如何让进程的栈和堆都不可执行呢?有没有办法可以修改代码段的数据?在上面分配了 4096 字节的内存,而实际则是 16K,那么其 4096 之后的空间是否可以使用呢?动态生成指令随后立即执行是否有问题呢?

Over!

Leave a Reply

Your email address will not be published. Required fields are marked *