GithubHelp home page GithubHelp logo

finixbit / elf-parser Goto Github PK

View Code? Open in Web Editor NEW
245.0 13.0 43.0 89 KB

Lightweight elf binary parser with no external dependencies - Sections, Symbols, Relocations, Segments

License: MIT License

C++ 100.00%
elf parser symbols sections relocations relocation elf-parser segment readelf vector

elf-parser's Introduction

elf-parser

Lightweight elf binary parser with no external dependencies - Sections, Symbols, Relocations, Segments

Required libraries

No dependencies

Usage

Sections (readelf -S executable)

parse sections header table from elf binary and return vector of section_t below

typedef struct {
    int section_index = 0; 
    std::intptr_t section_offset, section_addr;
    std::string section_name;
    std::string section_type; 
    int section_size, section_ent_size, section_addr_align;
} section_t;

get elf sections using elf-parser

#include <elf-parser.h>
elf_parser::Elf_parser elf_parser(executable_path);
std::vector<elf_parser::section_t> secs = elf_parser.get_sections();

see example

Segments (readelf -l executable)

parse program header table from elf binary and return vector of segment_t below

typedef struct {
    std::string segment_type, segment_flags;
    long segment_offset, segment_virtaddr, segment_physaddr, segment_filesize, segment_memsize;
    int segment_align;
} segment_t;

get elf segments using elf-parser

#include <elf-parser.h>
elf_parser::Elf_parser elf_parser(executable_path);
std::vector<elf_parser::segment_t> segs = elf_parser.get_segments();

see example

Symbols (readelf -s executable)

parse symbols table from elf binary and return vector of symbol_t below

typedef struct {
    std::string symbol_index;
    std::intptr_t symbol_value;
    int symbol_num = 0, symbol_size = 0;
    std::string symbol_type, symbol_bind, symbol_visibility, symbol_name, symbol_section;      
} symbol_t;

get elf symbols using elf-parser

#include <elf-parser.h>
elf_parser::Elf_parser elf_parser(executable_path);
std::vector<elf_parser::symbol_t> syms = elf_parser.get_symbols();

see example

Relocations (readelf -r executable)

parse relocations with plt address from elf binary and return vector of relocation_t below

typedef struct {
    std::intptr_t relocation_offset, relocation_info, relocation_symbol_value;
    std::string   relocation_type, relocation_symbol_name, relocation_section_name;
    std::intptr_t relocation_plt_address;
} relocation_t;

get elf relocations using elf-parser

#include <elf-parser.h>
elf_parser::Elf_parser elf_parser(executable_path);
std::vector<elf_parser::relocation_t> relocs = elf_parser.get_relocations();

see example

Supported Architecture

amd64

Projects using elf-parser

finixbit / ltrace - Library call tracer

finixbit / ftrace - Function call tracer

elf-parser's People

Contributors

finixbit avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

elf-parser's Issues

Calling get_* multiple times causes dups

Parser’s getters are not guarded against multiple calls and not only repeat unnecessary parsing over and over but also populate data vectors with duplicate entries.
At least it would be nice to clean vectos before parsing
At best it may makes sense to cache results

AddressSanitizer: SIGSEGV in elf_parser.cpp

ubuntu@ubuntu:~/Desktop/elf-parser/examples/elf-parser/examples$ ./asan_segments id03 
=================================================================
==1022431==ERROR: AddressSanitizer: unknown-crash on address 0x7ffff7fb1000 at pc 0x555555562f82 bp 0x7fffffffdac0 sp 0x7fffffffdab0
READ of size 8 at 0x7ffff7fb1000 thread T0
    #0 0x555555562f81 in elf_parser::Elf_parser::get_segments() ../elf_parser.cpp:66
    #1 0x555555559288 in main /home/ubuntu/Desktop/elf-parser/examples/elf-parser/examples/segments.cc:17
    #2 0x7ffff705f082 in __libc_start_main ../csu/libc-start.c:308
    #3 0x5555555586ad in _start (/home/ubuntu/Desktop/elf-parser/examples/elf-parser/examples/asan_segments+0x46ad)

Address 0x7ffff7fb1000 is a wild pointer.
SUMMARY: AddressSanitizer: unknown-crash ../elf_parser.cpp:66 in elf_parser::Elf_parser::get_segments()
Shadow bytes around the buggy address:
  0x10007efee1b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007efee1c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007efee1d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007efee1e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007efee1f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10007efee200:[fe]fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
  0x10007efee210: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
  0x10007efee220: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
  0x10007efee230: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
  0x10007efee240: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
  0x10007efee250: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==1022431==ABORTING

I use gdb check SIGSEGV:

ubuntu@ubuntu:~/Desktop/elf-parser/examples/elf-parser/examples$ gdb --args ./segments id03
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./segments...
gdb-peda$ r
Starting program: /home/ubuntu/Desktop/elf-parser/examples/elf-parser/examples/segments id03

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
RAX: 0x87 
RBX: 0x7fffffffddc0 --> 0x4e57004c4c554e ('NULL')
RCX: 0x4160a0 --> 0x100000100 
RDX: 0x25 ('%')
RSI: 0x7fffffffdd98 --> 0x4e57004c4c5500 ('')
RDI: 0x7fffffffdd98 --> 0x4e57004c4c5500 ('')
RBP: 0x7fffffffdde0 --> 0x4500 ('')
RSP: 0x7fffffffdd80 --> 0x1 
RIP: 0x404fa7 (<elf_parser::Elf_parser::get_segments()+615>:	movups xmm0,XMMWORD PTR [r15+0x18])
R8 : 0x415218 --> 0x4160a0 --> 0x100000100 
R9 : 0xb0 
R10: 0x638000 --> 0x638010 --> 0x0 
R11: 0xfffffffffffff000 
R12: 0x415218 --> 0x4160a0 --> 0x100000100 
R13: 0xf1e8 
R14: 0x7fffffffde98 --> 0x636ed0 --> 0x636ee0 --> 0x52444850 ('PHDR')
R15: 0x7ffff7ffefe8 --> 0x0
EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x404f98 <elf_parser::Elf_parser::get_segments()+600>:	lea    rbx,[rsp+0x40]
   0x404f9d <elf_parser::Elf_parser::get_segments()+605>:	movups xmm0,XMMWORD PTR [r15+0x8]
   0x404fa2 <elf_parser::Elf_parser::get_segments()+610>:	movups XMMWORD PTR [rsp+0x70],xmm0
=> 0x404fa7 <elf_parser::Elf_parser::get_segments()+615>:	movups xmm0,XMMWORD PTR [r15+0x18]
   0x404fac <elf_parser::Elf_parser::get_segments()+620>:	movups XMMWORD PTR [rsp+0x80],xmm0
   0x404fb4 <elf_parser::Elf_parser::get_segments()+628>:	mov    rax,QWORD PTR [r15+0x28]
   0x404fb8 <elf_parser::Elf_parser::get_segments()+632>:	mov    QWORD PTR [rsp+0x90],rax
   0x404fc0 <elf_parser::Elf_parser::get_segments()+640>:	lea    rdx,[r15+0x4]
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffdd80 --> 0x1 
0008| 0x7fffffffdd88 --> 0x7fffffffdd98 --> 0x4e57004c4c5500 ('')
0016| 0x7fffffffdd90 --> 0x0 
0024| 0x7fffffffdd98 --> 0x4e57004c4c5500 ('')
0032| 0x7fffffffdda0 --> 0x7fffffffde70 --> 0x7fffffffde80 --> 0x7f0033306469 
0040| 0x7fffffffdda8 --> 0x7fffffffde98 --> 0x636ed0 --> 0x636ee0 --> 0x52444850 ('PHDR')
0048| 0x7fffffffddb0 --> 0x7fffffffddc0 --> 0x4e57004c4c554e ('NULL')
0056| 0x7fffffffddb8 --> 0x4 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
elf_parser::Elf_parser::get_segments (this=<optimized out>) at ../elf_parser.cpp:66
66	        segment.segment_physaddr = phdr[i].p_paddr;

poc file: https://github.com/10cksYiqiyinHangzhouTechnology/elf-parser_segments_poc/blob/main/id3

asan_segments: https://github.com/10cksYiqiyinHangzhouTechnology/elf-parser_segments_poc/blob/main/asan_segments

don't exit() on error

Instead of calling exit() on an error, can't you just set a flag or something and leave it up to the programmer to decide what to do?
Something like this:

elf_parser::Elf_parser elf_parser(file);
if (!elf_parser.success()) return 1;

Missing validation

Your parser seems to not validate the input files. This makes it easy to crash and possible exploit a program using it. If this is by design it should be documented in the readme.

32-bit support

It would be great if this library supported 32-bit binaries as well since 32-bit is still often used nowadays:

auto header = (Elf64_Ehdr*)m_mmap_program;
if (header->e_ident[EI_CLASS] != ELFCLASS64) {
	printf("Only 64-bit files supported\n");
	exit(1);
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.