Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

load ELF file into memory

I'm trying to put an elf file into memory and then execute it, these are the steps:

1- file to put into memory

int main()
{
   printf("Hello world! \n");
   return 0;
}

2- Compile it gcc -o hello hello.c -static

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x8120
  Start of program headers:          52 (bytes into file)
  Start of section headers:          119864 (bytes into file)
  Flags:                             0x5000000, Version5 EABI
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         4
  Size of section headers:           40 (bytes)
  Number of section headers:         18
  Section header string table index: 17

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x00008000 0x00008000 0x16828 0x16828 R E 0x1000
  LOAD           0x016840 0x0001f840 0x0001f840 0x00250 0x02660 RW  0x1000
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0
  EXIDX          0x015f40 0x0001df40 0x0001df40 0x008e8 0x008e8 R   0x4

3- I write a Loader (compiled for ARM)

mmap2(0x8000, 92200, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x8000
mmap2(0x1f000, 65536, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x1f000

3.1- Then I have copied all the elf bytes into the allocations

3.2- jmp to main function

ldr r0, =0x008160
blx r0

.text:00008160 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00008160                 EXPORT main
.text:00008160 main                                    ; DATA XREF: _start+8o
.text:00008160                                         ; .text:off_8150o
.text:00008160                 STMFD           SP!, {R11,LR}
.text:00008164                 ADD             R11, SP, #4
.text:00008168                 LDR             R3, =(aHelloWorld - 0x8174)
.text:0000816C                 ADD             R3, PC, R3 ; "Hello world! "
.text:00008170                 MOV             R0, R3
.text:00008174                 BLX             puts
.text:00008178                 MOV             R3, #0
.text:0000817C                 MOV             R0, R3
.text:00008180                 LDMFD           SP!, {R11,PC}
.text:00008180 ; End of function main

The problem is that every time I get to the line 0x8174, then jump into, after a bit of instructions I always have a SIGSEGV in a random position, more time the crash instruction is => 0x9cc0: ldr r0, [r0, #4] with r0=0x70a34

00008000-0002f000 rwxp 00000000 00:00 0 
80000000-80001000 r-xp 00000000 b3:18 129754     /data/local/tmp/main
80001000-8001a000 rwxp 00001000 b3:18 129754     /data/local/tmp/main
becdf000-bed00000 rwxp 00000000 00:00 0 
ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]

These are more instructions after the crash:

.text:00009CB4 loc_9CB4                                ; CODE XREF: pthread_mutex_lock_impl+18j
.text:00009CB4                 MOV             R3, #0xFFFF0FE0
.text:00009CBC                 BLX             R3
.text:00009CC0                 LDR             R0, [R0,#4]

At this location 0x9CB4, the value of r0 is 0x1f96c (it is ok), after the blx the value of r0 is 0x70a34

(gdb) x/10x 0xffff0fe0
0xffff0fe0: 0xee1d0f70  0xe12fff1e  0xee1d0f70  0x00000000
0xffff0ff0: 0x00000000  0x00000000  0x00000000  0x00000005
0xffff1000: Cannot access memory at address 0xffff1000

Thanks!

like image 799
Livio Avatar asked Sep 14 '16 08:09

Livio


People also ask

What do I do with an ELF file?

An ELF file consists of zero or more segments, and describe how to create a process/memory image for runtime execution. When the kernel sees these segments, it uses them to map them into virtual address space, using the mmap(2) system call. In other words, it converts predefined instructions into a memory image.

How do I decode an ELF file?

you can use readelf and objdump to read parts of an elf file. You can also use 'hexdump filename' to get a hexdump of the contents of a binary file (this is likely only useful if you like reading machine code or you are writing an assembler).

How is an ELF file loaded into memory?

ELF files are used by two tools: the linker and the loader. A linker combines multiple ELF files into an executable or a library and a loader loads the executable ELF file in the memory of the process.


2 Answers

I'm trying to put an elf file into memory and then execute it,

For a fully-statically-linked executable, your steps would work (except you need to jump to _start == entry point 0x8120, not main).

Then I have copied all the elf bytes into the allocations

Another possible problem is not paying attention to the .p_offset. Your memcpyies should look something like this:

unsigned char buf1[0x16828];  // read 0x16828 bytes from start of file
memcpy(0x8000, buf1, 0x16828);

unsigned char buf2[0x250];  // read 0x250 bytes from offset 0x016840 into the file
memcpy(0x0001f840, buf2, 0x250);
like image 57
Employed Russian Avatar answered Nov 16 '22 03:11

Employed Russian


Your problem is that you need to use the correct entry point and you need initialize the program's stack (and maybe registers) the same way the OS would. You need to use the correct entry point so that the C runtime library is initialized, otherwise your call to printf (or puts as the case may be) will almost certainly crash. You need to setup the stack correctly because that's where the C runtime library's initialization code will look for the program's arguments and environment (and maybe other things).

You didn't say what operating system you're using, but if your using Linux you might want to look as an answer to different question given by CesarB describing the initial state of the stack on ARM Linux.

like image 44
Ross Ridge Avatar answered Nov 16 '22 03:11

Ross Ridge