我一直在为 Linux 开发一个简单的 PE 进程加载器。我想我已经掌握了基础知识;我使用的大部分代码来自binfmt_elf.c
and binfmt_aout.c
。我的测试可执行文件尽可能简单(FASM 格式):
format PE GUI 4.0
entry main
section '.text' code readable executable
main:
mov eax, 4
add eax, 5
ret
这个程序(math1
)是32位编译的,我运行的VM(Xubuntu 12.04)也是32位的。我将加载器编译为内核模块并使用insmod
. 到目前为止,加载程序似乎可以正常工作,并且我已经在每个可能的步骤中检查了错误代码。它所做的只是mmap
起始地址的代码部分0x401000
并使用该地址调用start_thread()
。如果我./math1.exe
在命令行输入类似的内容,我的加载器确实被调用了。所以,如果一切按计划进行,我应该9
每次都得到返回值。然而,不是math1
每次都执行段错误,所以我打开它gdb
看看发生了什么。
在执行之前,一切看起来都很正常。如果我在起始地址转储,我会看到我应该看到的确切内容(我可以确认这是上述程序的机器代码):
(gdb) x/9xb 0x401000
0x401000: 0xb8 0x04 0x00 0x00 0x00 0x83 0xc0 0x05
0x401008: 0xc3
(gdb) run
Starting program: /media/sf_Sandbox/math1.exe
Program received signal SIGSEGV, Segmentation fault.
0x00401002 in ?? ()
在段错误之后,转储到相同的地址,内存已经完全改变,并且从寄存器转储来看,第一条指令似乎没有被执行:
(gdb) x/9xb 0x401000
0x401000: 0x4d 0x5a 0x80 0x00 0x01 0x00 0x00 0x00
0x401008: 0x04
(gdb) info all-registers
eax 0x0 0
ecx 0x81394e8 135501032
edx 0x64656d2f 1684368687
ebx 0x8139548 135501128
esp 0xbfffe5a0 0xbfffe5a0
ebp 0xffffffff 0xffffffff
esi 0x81394e8 135501032
edi 0x2f7ff4 3112948
eip 0x401002 0x401002
eflags 0x210296 [ PF AF SF IF RF ID ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x0 0
...more registers...
我想知道什么会导致这样的事情发生,以及我可以做些什么来解决它。我怀疑我用来设置堆栈框架的代码可能有点……关闭,但我不确定如何判断这是否是导致这种情况的原因。我知道这是一个非常具体的问题,但我希望有人能给我一些建议。