我一直在为Linux开发一个简单的PE流程加载器。我想我已经掌握了基础知识;我使用的大部分代码来自binfmt_elf.c
和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 ?? ()
在segfault之后,转储到同一个地址,内存已完全改变,并且从寄存器转储中看起来似乎没有执行第一条指令:
(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...
我想知道会发生什么样的事情,以及我可以做些什么来解决它。我怀疑用于设置堆栈帧的代码可能有点......关闭,但我不知道如何判断这是否是导致这种情况的原因。我知道这是一个非常具体的问题,但我希望有人可以给我一些建议。
答案 0 :(得分:0)
错误是由我的页面对齐错误引起的,而神秘的十六进制转储内容实际上是有问题的PE文件的MS-DOS头。我使用kernel_read
和copy_to_user
代替do_mmap
修复了此问题,以避免在非页面对齐的部分出现故障。