如何在 ELF header 中嵌入机器代码? Err:执行格式错误
How to embed machine code inside ELF header? Err: Exec format error
根据本教程:http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html,我可以将这段代码嵌入到 elf header 结构中。
前一步,我的代码和 elf header 是分开的(也在教程中),它可以工作。但是之后就没有了。
这是我的来源:
BITS 32
org 0x08048000
ehdr:
db 0x7F, "ELF"
db 1,1,1,0 ;e_indent = magic numbers, 32objects, 2compl, arch
;times 8 db 0 ; to the end of e_indent buffer (e_indent[16])
;PROGRAM EMBEDDED IN ELF HEADER
_start:
mov bl, 42
xor eax, eax
inc eax
int 0x80
dw 2; e_type (2 == executable type)
dw 3; e_machine (3 == intel_80386)
dd 1; e_version (1 == current_version)
dd _start; e_entry
dd phdr - $$; e_phoff (size between this struct and struct phdr)
dd 0; e_shoff -----> why is offset 0? == org ?
dd 0; e_flags (should some processor specific flags, do not know value 0)
dw ehdr_size; e_ehsize
dw phdr_size; e_phentsize
dw 1; e_phnum (real number of program headers, do not know what it means)
dw 0; e_shentsize (because e_shoff == 0)
dw 0; e_shnum
dw 0; e_shstrndx
ehdr_size equ $ - ehdr
phdr:
dd 1; p_type (1 == loadable program segment)
dd 0; p_offset (segment file offset, but why 0, beginning?)
dd $$; p_vaddr (segment virtual address, $$ == org)
dd $$; p_paddr (segment physical address, $$ == org)
dd file_size; p_filesz (segment size in file)
dd file_size; p_memsz (segment size in memory)
dd 5; p_flags (((1<<0) | (1<<2))) == segment is readable and executable)
dd 0x1000; p_align (segment alignment - 4096 page alignment)
phdr_size equ $ - phdr
file_size equ $ - $$
查看 elf.h
文件中结构成员的含义后,只有我的评论。
编译为:
nasm -fbin -o a.out a.s
chmod +x a.out
./a.out
bash: ./a.out: cannot execute binary file: Exec format error
前面说了,分开了,但是工作。在 "merging" 之后,它停止工作。一些想法为什么?
您没有嵌入源代码(ASCII 文本),您试图将机器代码指令嵌入到 ELF header.
你的汇编为 83 字节,但这篇文章有 84 字节的版本。看起来你改变了一些东西,而不是文章的版本,破坏了它。比较二进制文件或源代码,找出导致 ELF header 无效的问题。
(after assembling both your source and the working source from the article)
$ file tiny-84
tiny-84: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, no section header
$ file tiny-bad
tiny-bad: ELF 32-bit LSB *unknown arch 0x100* (SYSV)
$ cmp tiny-84 tiny-bad
tiny-84 tiny-bad differ: byte 9, line 1
结果发现差异在 ehdr 的第 2 条数据线上:
both versions db 0x7F, "ELF" ; e_ident
-theirs db 1, 1, 1, 0, 0
+yours db 1, 1, 1, 0 ;e_indent = magic numbers, 32objects, 2compl, arch
(手动调整差异格式以将它们对齐)
所以你遗漏了一个字节,使所有后面的字节相对于它们在 ELF 中的预期位置没有对齐 header。 显然这会破坏它,但幸运的是有一个 known-good binary-compare 的示例可以很容易地找到问题。
实际上,我使用 cmp -l tiny-84 tiny-bad
来打印二进制文件的不匹配字节。当它产生很多差异时,加上文件大小不匹配是丢失字节扭曲所有内容的有力证据,而不仅仅是 1 个字段具有错误的值。您还可以直观地看到倾斜:
$ cmp -l tiny-84 tiny-bad
9 0 263
10 263 52
11 52 61
12 61 300
13 300 100
14 100 315
15 315 200
16 200 2
17 2 0
...
根据本教程:http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html,我可以将这段代码嵌入到 elf header 结构中。
前一步,我的代码和 elf header 是分开的(也在教程中),它可以工作。但是之后就没有了。
这是我的来源:
BITS 32
org 0x08048000
ehdr:
db 0x7F, "ELF"
db 1,1,1,0 ;e_indent = magic numbers, 32objects, 2compl, arch
;times 8 db 0 ; to the end of e_indent buffer (e_indent[16])
;PROGRAM EMBEDDED IN ELF HEADER
_start:
mov bl, 42
xor eax, eax
inc eax
int 0x80
dw 2; e_type (2 == executable type)
dw 3; e_machine (3 == intel_80386)
dd 1; e_version (1 == current_version)
dd _start; e_entry
dd phdr - $$; e_phoff (size between this struct and struct phdr)
dd 0; e_shoff -----> why is offset 0? == org ?
dd 0; e_flags (should some processor specific flags, do not know value 0)
dw ehdr_size; e_ehsize
dw phdr_size; e_phentsize
dw 1; e_phnum (real number of program headers, do not know what it means)
dw 0; e_shentsize (because e_shoff == 0)
dw 0; e_shnum
dw 0; e_shstrndx
ehdr_size equ $ - ehdr
phdr:
dd 1; p_type (1 == loadable program segment)
dd 0; p_offset (segment file offset, but why 0, beginning?)
dd $$; p_vaddr (segment virtual address, $$ == org)
dd $$; p_paddr (segment physical address, $$ == org)
dd file_size; p_filesz (segment size in file)
dd file_size; p_memsz (segment size in memory)
dd 5; p_flags (((1<<0) | (1<<2))) == segment is readable and executable)
dd 0x1000; p_align (segment alignment - 4096 page alignment)
phdr_size equ $ - phdr
file_size equ $ - $$
查看 elf.h
文件中结构成员的含义后,只有我的评论。
编译为:
nasm -fbin -o a.out a.s
chmod +x a.out
./a.out
bash: ./a.out: cannot execute binary file: Exec format error
前面说了,分开了,但是工作。在 "merging" 之后,它停止工作。一些想法为什么?
您没有嵌入源代码(ASCII 文本),您试图将机器代码指令嵌入到 ELF header.
你的汇编为 83 字节,但这篇文章有 84 字节的版本。看起来你改变了一些东西,而不是文章的版本,破坏了它。比较二进制文件或源代码,找出导致 ELF header 无效的问题。
(after assembling both your source and the working source from the article)
$ file tiny-84
tiny-84: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, no section header
$ file tiny-bad
tiny-bad: ELF 32-bit LSB *unknown arch 0x100* (SYSV)
$ cmp tiny-84 tiny-bad
tiny-84 tiny-bad differ: byte 9, line 1
结果发现差异在 ehdr 的第 2 条数据线上:
both versions db 0x7F, "ELF" ; e_ident
-theirs db 1, 1, 1, 0, 0
+yours db 1, 1, 1, 0 ;e_indent = magic numbers, 32objects, 2compl, arch
(手动调整差异格式以将它们对齐)
所以你遗漏了一个字节,使所有后面的字节相对于它们在 ELF 中的预期位置没有对齐 header。 显然这会破坏它,但幸运的是有一个 known-good binary-compare 的示例可以很容易地找到问题。
实际上,我使用 cmp -l tiny-84 tiny-bad
来打印二进制文件的不匹配字节。当它产生很多差异时,加上文件大小不匹配是丢失字节扭曲所有内容的有力证据,而不仅仅是 1 个字段具有错误的值。您还可以直观地看到倾斜:
$ cmp -l tiny-84 tiny-bad
9 0 263
10 263 52
11 52 61
12 61 300
13 300 100
14 100 315
15 315 200
16 200 2
17 2 0
...