。内存中的文本在执行过程中被覆盖
问题描述:
我一直在研究一个简单的用于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位和虚拟机,我在(Xubuntu上12.04)运行也是32位。我将loader作为内核模块编译并使用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...
我想知道什么可以让这样的事情发生,我可能能够做到要解决这个问题。我怀疑我用来设置堆栈框架的代码可能有点...关闭,但我不确定如何判断这是什么原因造成的。我知道这是一个非常具体的问题,但我希望有人能给我一些建议。
答
错误是由我的错误页面对齐引起的,神秘的十六进制转储内容实际上是所讨论的PE文件的MS-DOS标题。我通过使用kernel_read
和copy_to_user
而不是do_mmap
来修复它,以避免在非页面对齐的部分出现故障。
mmap:ed内存是否获得执行权限? – 2012-08-16 16:37:25
@JensBjörnhager它被映射到保护'PROT_READ | PROT_EXEC'和标志'MAP_PRIVATE | MAP_FIXED | MAP_DENYWRITE'。据我所知,这与ELF加载程序的做法是一样的。 – nosuchthingasstars 2012-08-16 16:52:48
'4d 5a ...'看起来像一个MS-DOS标题。你确定你没有意外地映射过吗? – atomicinf 2012-08-16 17:26:36