Reputation: 183
According to this tutorial: http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html, I can embed so piece of code inside a elf header structure.
One step before, where my code and elf header were separate (also in the tutorial), it works. But after that, it does not.
This is my source:
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 $ - $$
There are just my comments after viewing the meanings of members of the struct in elf.h
file.
Compiled as:
nasm -fbin -o a.out a.s
chmod +x a.out
./a.out
bash: ./a.out: cannot execute binary file: Exec format error
As I said, before, it was separated, but work. After "merging", it stops working. Some ideas why?
Upvotes: 1
Views: 224
Reputation: 364190
You're not embedding source code (ASCII text), you're trying to embed machine code instructions into the ELF header.
Yours assembles to 83 bytes, but the article has an 84 byte version. It seems you changed something vs. the article's version, breaking it. Compare the binaries or source to figure out what you broke that makes the ELF headers invalid.
(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
Turns out the difference is on the 2nd data line of the ehdr:
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
(diff formatting hand tweaked to line them up)
So you left out one byte, misaligning all later bytes relative to their intended position in the ELF header. Obviously this breaks it, but fortunately having a known-good example to binary-compare against made it easy to find the problem.
In practice I used cmp -l tiny-84 tiny-bad
to print the mismatching bytes of the binary. When it spewed a lot of differences, that plus the file size mismatch was strong evidence of a missing bytes skewing everything, rather than just 1 field having the wrong value. Also you can visually see the skew:
$ 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
...
Upvotes: 1