昨天晚上回去后实在无聊睡不着,拿着身边的 Yeeloong 笔记本随便找点事干干,想到了 JIT 的原理,于是简单的验证了一下运行时动态生成指令并执行。
我先找了一下进程中哪个 VMA 是可以执行的,使用命令 cat /proc/self/maps 可以找到:
00400000-0040c000 r-xp 00000000 08:02 524311 /bin/cat
00418000-0041c000 rw-p 00008000 08:02 524311 /bin/cat
0041c000-00440000 rwxp 00000000 00:00 0 [heap]
2b9c8000-2b9ec000 r-xp 00000000 08:02 917518 /lib/ld-2.14.so
2b9f8000-2b9fc000 rw-p 00020000 08:02 917518 /lib/ld-2.14.so
2ba18000-2bb70000 r-xp 00000000 08:02 918040 /lib/libc-2.14.so
2bb70000-2bb7c000 ---p 00158000 08:02 918040 /lib/libc-2.14.so
2bb7c000-2bb80000 r--p 00154000 08:02 918040 /lib/libc-2.14.so
2bb80000-2bb84000 rw-p 00158000 08:02 918040 /lib/libc-2.14.so
2bb84000-2bb88000 rw-p 00000000 00:00 0
2bb88000-2bd88000 r--p 00000000 08:02 786854 /usr/lib/locale/locale-archive
7ff70000-7ff94000 rwxp 00000000 00:00 0 [stack]
7fff4000-7fff8000 r-xp 00000000 00:00 0 [vdso]
从上面的结果中可以看到 heap 和 stack 两个 VMA 的权限属性都是 rwxp,意味着我可以向里面存入指令并执行。
我选择了在栈中存入两条指令,然后转过去执行。代码如下:
#include
int main(int argc, char *argv[])
{
unsigned int insn[] =
{
0x1000ffff,
0x00000000
};
__asm__ volatile (
"jr %0 \n\t"
"nop \n\t"
::"r"(insn)
);
return 0;
}
编译程序后,执行这个程序就会进入栈里的死循环了。
你可能会想到这个操作系统的 heap 和 stack 具有可执行权限是不安全的,我确认了一下 x86 里没有可执行权限的,那么当没有可执行权限又应该怎么办呢?我们下次再说。
Over!