如何在 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
...