5

If the ELF header which usually can be read using readelf has been manually manipulated, let's say by increasing the value for the "Size of section headers" the binary still can be executed and works well.

However, this manipulation seems to trip up reverse engineering tools like GDC and GDB gives me the error: not in executable format: File format not recognized.

Is there a way to fix the ELF header without knowing the original value of "Size of section headers" in order to be able again to analyze the file using standard tools?

Detailed info:

GDB is failing to run the binary because it says the file is not in executable format : File format not recognized but it works outside the GDB. The same things happen with the libbfd parser, it can't parse because file format is not recognized. The fact is I only change the number of section headers.

Code

#include <stdio.h>

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

Build by invoking make hello or on a 64-bit system make CFLAGS=-m32 hello.

ELF header before

$ readelf -h hello
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:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x8048320
  Start of program headers:          52 (bytes into file)
  Start of section headers:          4472 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         9
  Size of section headers:           40 (bytes)
  Number of section headers:         30 <-- notice me!
  Section header string table index: 27

ELF header after

$ readelf -h hello
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:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x8048320
  Start of program headers:          52 (bytes into file)
  Start of section headers:          4472 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         9
  Size of section headers:           40 (bytes)
  Number of section headers:         52 <-- already changed!
  Section header string table index: 27

GDB will output,

not in executable format: File format not recognized

But if I run it outside of GDB,

$ ./hello output:
Hello World!

So is there either a method to fix the value for e_shnum without knowing the correct value, or a workaround so I can debug this file in GDB?

  • Can you please clarify: so binutils is unable to parse the file, but the system can parse and execute it, right? Have you tried using the underlying libbfd and written your own parser with its help, to see where exactly it fails? Also, is the version used by GDB up-to-date? (i.e. make sure to test against a version of libbfd that is also used by your GDB) – 0xC0000022L Apr 4 '16 at 12:25
  • Still not working and i've tried both using elf.h and bfd.h still can't parse the header. – Fakhri Zulkifli Apr 4 '16 at 15:52
  • 1
    You need to describe what exactly you have changed and maybe show the readelf output before and after. "change the number in section headers" is terribly vague. – Igor Skochinsky Apr 5 '16 at 8:18
  • 1
    I think by now it's clear what the intention is. Roughly: If the ELF is structurally "damaged" in a way that prevents it from being parsed with RCE tools (here GDB), how can one restore a state that doesn't trip up the RCE tools. – 0xC0000022L Apr 6 '16 at 8:04
  • 1
    @EvanCarroll: well, the question is 2.5 years old and the inquirer seems to have no further interest (going by the lack of response). If you feel like the title also needs to be adjusted, go right ahead. – 0xC0000022L Nov 20 '18 at 22:51
0

I recreated your binary and then used Radare to corrupt the header exactly as you did, changing the number of section headers to 52.

r2 -w a.out -1c's 0; pfo elf64; .pf.elf_header.shnum=52'

This only generated a warning with subsequent invocations of readelf.

$ readelf -h a.out 
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x1050
  Start of program headers:          64 (bytes into file)
  Start of section headers:          14624 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         11
  Size of section headers:           64 (bytes)
  Number of section headers:         52
  Section header string table index: 28
readelf: Error: Reading 3328 bytes extends past end of file for section headers

But I got the similar error from GDB,

not in executable format: file truncated

And, if I try to debug that file, I get

No executable file specified.

I could go back to the original easily with

r2 -w a.out -c's 0; pfo elf64; .pf.elf_header.shnum=52'

However to answer your question about tooling,

  • Radare works with it even if the header is set to 52. You can still debug it.
  • You can get gdb to work if the header is less than the original shnum, for instance setting it to 1 will only warn you,

    BFD: warning: /tmp/a.out has a corrupt string table index - ignoring

    but you can still debug the program.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.