How to Make an Executable Elf File in Linux Using a Hex Editor

How to make an executable ELF file in Linux using a hex editor?

As mentioned in my comment, you will essentially be writing your own elf-header for the executable eliminating the unneeded sections. There are still several required sections. The documentation at Muppetlabs-TinyPrograms does a fair job explaining this process. For fun, here are a couple of examples:

The equivalent of /bin/true (45 bytes):

00000000  7F 45 4C 46 01 00 00 00  00 00 00 00 00 00 49 25  |.ELF..........I%|
00000010 02 00 03 00 1A 00 49 25 1A 00 49 25 04 00 00 00 |......I%..I%....|
00000020 5B 5F F2 AE 40 22 5F FB CD 80 20 00 01 |[_..@"_... ..|
0000002d

Your classic 'Hello World!' (160 bytes):

00000000  7f 45 4c 46 01 01 01 03  00 00 00 00 00 00 00 00  |.ELF............|
00000010 02 00 03 00 01 00 00 00 74 80 04 08 34 00 00 00 |........t...4...|
00000020 00 00 00 00 00 00 00 00 34 00 20 00 02 00 28 00 |........4. ...(.|
00000030 00 00 00 00 01 00 00 00 74 00 00 00 74 80 04 08 |........t...t...|
00000040 74 80 04 08 1f 00 00 00 1f 00 00 00 05 00 00 00 |t...............|
00000050 00 10 00 00 01 00 00 00 93 00 00 00 93 90 04 08 |................|
00000060 93 90 04 08 0d 00 00 00 0d 00 00 00 06 00 00 00 |................|
00000070 00 10 00 00 b8 04 00 00 00 bb 01 00 00 00 b9 93 |................|
00000080 90 04 08 ba 0d 00 00 00 cd 80 b8 01 00 00 00 31 |...............1|
00000090 db cd 80 48 65 6c 6c 6f 20 77 6f 72 6c 64 21 0a |...Hello world!.|
000000a0

Don't forget to make them executable...

Create executable out of hexadecimal file under Linux

From my understanding of the discussion which followed my question, what I want to do is create an ELF file. This question covers how to create your own ELF header.

Although, if you do not want to go through the trouble, you can actually use gcc to compile a sequence of bytes to an executable.

.section .text
.global main
main:
.byte 0x48 0xc7 0xc0 0x7b 0x00 0x00 0x00 0x48 0xc7 0xc1 0x59 0x01 ...

You can then compile the above with gcc file.S -o file. This will create the desired ELF file.

finding integer declared variables in ELF executable using a hex editor

First, you would use readelf to determine the virtual address of the variable (where it lives in memory after the program is loaded). -s will show you the symbol table, and we'll grep for the name of your variable.

readelf -s a.out | grep value

This will output a line that looks like:

    64: 000000000060102c     4 OBJECT  GLOBAL DEFAULT   24 value

So here, the 64th symbol in the file is value. Its load address is 0x60102c, and it's 4 bytes in size. Now we have the virtual address, but this doesn't tell us where it's at in the file. To do that, we need to do three things:

  1. Figure out which section it's in,
  2. Figure out this value's section offset
  3. Add its section offset to that section's file offset, to get your item's actual file offset (the "address" you would see in a hex editor, if you opened the ELF file).

Let's run readelf again. -S will list the sections.

readelf -S a.out

Here's a snippet of the output. Remember the address of our variable is at 60102c, and we're looking for the section where 60102c lies between its Address and its Address + Size. Since this is a read-write variable, we can take a guess that it will be in the .data section.

Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
...
[21] .dynamic DYNAMIC 0000000000600e28 00000e28
00000000000001d0 0000000000000010 WA 6 0 8
[22] .got PROGBITS 0000000000600ff8 00000ff8
0000000000000008 0000000000000008 WA 0 0 8
[23] .got.plt PROGBITS 0000000000601000 00001000
0000000000000028 0000000000000008 WA 0 0 8
[24] .data PROGBITS 0000000000601028 00001028
0000000000000008 0000000000000000 WA 0 0 4
[25] .bss NOBITS 0000000000601030 00001030
0000000000000008 0000000000000000 WA 0 0 4
[26] .comment PROGBITS 0000000000000000 00001030
000000000000002c 0000000000000001 MS 0 0 1

Sure enough, .data lives in memory at 601028 to 601028+8 = 601030. Subtracting value's address from this section's address, we get:

  60102c       Address of `value`
- 601028 Start address of .data section
--------
4

Thus, value is at offset 4 from the start of the .data section. Now, where in the file is the .data section? That's what the Offset column tells us. .data begins at file offset 1028. Knowing this, we can find the file offset of value:

  1028         File offset of .data section
+ 4 Offset of `value` in .data section
-------
102c File offset of `value`

We've got our file offset, now let's make sure we know what to expect. Your variable has the value 1337. In hex, that's 0x539. But, we need to bring up byte order (or "endianness"). Intel x86 systems are little endian. That means when an integer larger than one byte is stored at an address, the least-signifiant byte (or "little" end) of the value is at that address, and the remaining bytes are at subsequent (increasing address).

So your 1337 will be stored (as a 4-byte int) in the file like this:

39 05 00 00

On a "big endian" system (e.g. Motorola 68k), the value would be seen in the file in the opposite order:

00 00 05 39

That all said, if you open your ELF file in a hex editor, an go to offset 102c, you will see your value:

Sample Image

ELF files have no checksum or CRC, so you should be able to simply edit that value in your hex editor, and it will have the new value when your program executes!



Related Topics



Leave a reply



Submit