• Stars
    star
    207
  • Rank 189,769 (Top 4 %)
  • Language
    Rust
  • License
    MIT License
  • Created about 3 years ago
  • Updated over 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

An architecture-agnostic ELF file flattener for shellcode

Summary

elfloader is a super simple loader for ELF files that generates a flat in-memory representation of the ELF.

Pair this with Rust and now you can write your shellcode in a proper, safe, high-level language. Any target that LLVM can target can be used, including custom target specifications for really exotic platforms and ABIs. Enjoy using things like u64s on 32-bit systems, bounds checked arrays, drop handling of allocations, etc :)

It simply concatenates all LOAD sections together, using zero-padding if there are gaps, into one big flat file.

This file includes zero-initialization of .bss sections, and thus can be used directly as a shellcode payload.

If you don't want to waste time with fail-open linker scripts, this is probably a great way to go.

This doesn't handle any relocations, it's on you to make sure the original ELF is based at the address you want it to be at.

Usage

To use this tool, simply:

Usage: elfloader [--perms] [--binary] [--base=<addr>] <input ELF> <output>
    --binary      - Don't output a FELF, output the raw loaded image with no
                    metadata
    --perms       - Create a FELF0002 which includes permission data, overrides
                    --binary
    --base=<addr> - Force the output to start at `<addr>`, zero padding from
                    the base to the start of the first LOAD segment if needed.
                    `<addr>` is default hex, can be overrided with `0d`, `0b`,
                    `0x`, or `0o` prefixes.
                    Warning: This does not _relocate_ to base, it simply starts
                    the output at `<addr>` (adding zero bytes such that the
                    output image can be loaded at `<addr>` instead of the
                    original ELF base)
    <input ELF>   - Path to input ELF
    <output>      - Path to output file

To install this tool run:

cargo install --path .

Now you can use elfloader from anywhere in your shell!

Dev

This project was developed live here:

https://www.youtube.com/watch?v=x0V-CEmXQCQ

Example

There's an example in example_small_program, simply run make or nmake and this should generate an example.bin which is 8 bytes.

pleb@gamey ~/elfloader/example_small_program $ make
cargo build --release
    Finished release [optimized] target(s) in 0.03s
elfloader --binary target/aarch64-unknown-none/release/example_small_program example.bin
pleb@gamey ~/elfloader/example_small_program $ ls -l ./example.bin 
-rw-r--r-- 1 pleb pleb 8 Nov  8 12:27 ./example.bin

pleb@gamey ~/elfloader/example_small_program $ objdump -d target/aarch64-unknown-none/release/example_small_program

target/aarch64-unknown-none/release/example_small_program:     file format elf64-littleaarch64


Disassembly of section .text:

00000000133700b0 <_start>:
    133700b0:   8b000020        add     x0, x1, x0
    133700b4:   d65f03c0        ret

Now you can write your shellcode in Rust, and you don't have to worry about whether you emit .data, .rodata, .bss, etc. This will handle it all for you!

There's also an example with .bss and .rodata

pleb@gamey ~/elfloader/example_program_with_data $ make
cargo build --release
    Finished release [optimized] target(s) in 0.04s
elfloader --binary target/aarch64-unknown-none/release/example_program_with_data example.bin
pleb@gamey ~/elfloader/example_program_with_data $ ls -l ./example.bin
-rw-r--r-- 1 pleb pleb 29 Nov  8 12:39 ./example.bin
pleb@gamey ~/elfloader/example_program_with_data $ objdump -d target/aarch64-unknown-none/release/example_program_with_data

target/aarch64-unknown-none/release/example_program_with_data:     file format elf64-littleaarch64


Disassembly of section .text:

0000000013370124 <_start>:
    13370124:   90000000        adrp    x0, 13370000 <_start-0x124>
    13370128:   90000008        adrp    x8, 13370000 <_start-0x124>
    1337012c:   52800029        mov     w9, #0x1                        // #1
    13370130:   91048000        add     x0, x0, #0x120
    13370134:   3904f109        strb    w9, [x8, #316]
    13370138:   d65f03c0        ret
pleb@gamey ~/elfloader/example_program_with_data $ readelf -l target/aarch64-unknown-none/release/example_program_with_data

Elf file type is EXEC (Executable file)
Entry point 0x13370124
There are 4 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000120 0x0000000013370120 0x0000000013370120
                 0x0000000000000004 0x0000000000000004  R      0x1
  LOAD           0x0000000000000124 0x0000000013370124 0x0000000013370124
                 0x0000000000000018 0x0000000000000018  R E    0x4
  LOAD           0x000000000000013c 0x000000001337013c 0x000000001337013c
                 0x0000000000000000 0x0000000000000001  RW     0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x0

 Section to Segment mapping:
  Segment Sections...
   00     .rodata 
   01     .text 
   02     .bss 
   03     

Internals

This tool doesn't care about anything except for LOAD sections. It determines the endianness (little vs big) and bitness (32 vs 64) from the ELF header, and from there it creates a flat image based on program header virtual addresses (where it's loaded), file size (number of initialized bytes) and mem size (size of actual memory region). The bytes are initialized from the file based on the offset and file size, and this is then extended with zeros until mem size (or truncated if mem size is smaller than file size).

These LOAD sections are then concatenated together with zero-byte padding for gaps.

This is designed to be incredibly simple, and agnostic to the ELF input. It could be an executable, object file, shared object, core dump, etc, doesn't really care. It'll simply give you the flat representation of the memory, nothing more.

This allows you to turn any ELF into shellcode, or a simpler file format that is easier to load in hard-to-reach areas, like embedded devices. Personally, I developed this for my MIPS NT 4.0 loader which allows me to run Rust code.

FELF0001 format

This tool by default generates a FELF file format. This is a Falk ELF. This is a simple file format:

FELF0001 - Magic header
entry    - 64-bit little endian integer of the entry point address
base     - 64-bit little endian integer of the base address to load the image
<image>  - Rest of the file is the raw image, to be loaded at `base` and jumped
           into at `entry`

FELF0002 format (when --perms flag is used)

This tool by default generates a FELF file format. This is a Falk ELF. This is a simple file format with permissions:

FELF0002 - Magic header
entry    - 64-bit little endian integer of the entry point address
base     - 64-bit little endian integer of the base address to load the image
<image>  - Rest of the file is the raw image, to be loaded at `base` and jumped
           into at `entry`
<perms>  - Permissions, matching the bytes of <image> where the byte contains
           the following flags bitwise or-ed together:
           0x01 - Executable, 0x02 - Writable, 0x04 - Readable
           Padding bytes will be 0x00, and thus have no permissions for any
           access

More Repositories

1

orange_slice

A research kernel and hypervisor attempting to get fully deterministic emulation with minimum performance cost
Rust
506
star
2

chocolate_milk

Pure Rust x86_64 bootloader and kernel
Rust
478
star
3

mesos

Binary coverage tool without binary modification for Windows
Rust
405
star
4

applepie

A hypervisor for fuzzing built with WHVP and Bochs
C++
361
star
5

mempeek

A command line tool that resembles a debugger as well as Cheat Engine, to search for values in memory
Rust
217
star
6

fzero_fuzzer

A fast Rust-based safe and thead-friendly grammar-based fuzz generator
Rust
208
star
7

falkervisor_grilled_cheese

C
168
star
8

cookie_dough

A fuzzing introspection tool
Rust
161
star
9

proc_mem_ida_loader

A /proc/mem IDA loader to snapshot a running process
Python
149
star
10

fuzz_with_emus

Why fuzzing with emulators is amazing
Rust
129
star
11

nginx_shitpost

Nginx 0-day on latest nginx
C
116
star
12

rv32i_jit

A super simple RV32i JIT, designed for ease of understanding and modification
C
76
star
13

lemonade

A debugger for Linux in Rust
Rust
76
star
14

falkervisor_beta

Assembly
75
star
15

basic_mutator

About as basic of a mutator as you can get, but it does the trick in most situations
Rust
55
star
16

slime_tree

Worst Android kernel fuzzer
Rust
43
star
17

falkhash

Exotic Shitty Hash Maybe
C
43
star
18

guifuzz

A GUI fuzzing application set up to fuzz calc.exe right now
Rust
36
star
19

riscv

A div-less, mul-less, atomic-less `rv64i` compiler toolchain using purely clang, musl, and compiler-rt
C
27
star
20

whylol

Shhh
Rust
27
star
21

adventures_in_fuzzing

Here's the slides and audio for a talk I did at NYU on the 13th of November 2018
27
star
22

init

A super simple /sbin/init for Linux which allows running one and only one program
Rust
22
star
23

vectorized_mmu

Snapshot of the vectorized MMU that lines up with the vectorized MMU blog
Rust
22
star
24

rust_mips_nt4

Rust development environment for MIPS on NT4
Rust
19
star
25

aflbench

An AFL scaling benchmarking tool
Python
18
star
26

flounder

Flounder is an old corpus collector I wrote, but it still works. Just need a Bing API key
Python
18
star
27

pdblister

Faster version of `symchk /om` for generating PDB manifests of offline machines
Rust
18
star
28

gamozolabs.github.io

Apparently this maybe blogs or something?
Ruby
16
star
29

fuzzyneural

A neural network using fuzzing-style feedback rather than back-propagation
Rust
16
star
30

vectorized_emulation_recon_2019

Gave a talk on Vectorized emulation at Recon Montreal 2019, here are the slides
16
star
31

cuddly_kangaroo

A static website generator that embeds all images as base64, and thus can be used with a single resource.
Rust
15
star
32

snuffles

A high-performance graphics API designed mainly for data visualization
Rust
15
star
33

hellscape

Playground for testing feedback
Assembly
14
star
34

helicopter_game

This is uhh, a "clone" of the helicopter game
Rust
13
star
35

canon_pixma_mx492

Reverse engineering project on stream
Rust
13
star
36

coverage_highlight

A very simple coverage highlighter for VIM
Python
12
star
37

freetype_harness

Definitely not for fuzzing
Rust
11
star
38

qemu_chrooter

Take a QEMU binary, copy the dependencies into a chroot
Rust
11
star
39

bridengroom

Windows Heap Loggin'
Rust
11
star
40

statusbar

A DWM status that shows the MPD playing song and the current datetime in milliseconds
Rust
10
star
41

libprocmem

A simple /proc/<pid>/{mem,maps} library for Rust
Rust
9
star
42

fuzztheory

A project for simulating fuzzing such that analysis can be done on coverage/feedback/scaling mechanisms
Rust
9
star
43

safecast

Safe casting in Rust!
Rust
7
star
44

ffmpegged

Uhh, trying to make encoding actually use cores
Rust
7
star
45

coff_nm

`nm` and `addr2line` but for DI "debug-info" COFF files
Rust
7
star
46

streamwrite

Benchmarking sequential i32 stores
Rust
6
star
47

teraflopter420

A helicoptor game engine with perf
Rust
6
star
48

bochs_determinism_test

Used to run 2 Bochs instances in lockstep to verify they do the same things
C++
5
star
49

noodle

A non-procedrual Rust serialization and deserialization library
Rust
4
star
50

fork_benchmarking

I get asked about this a lot
Rust
4
star
51

lossless_compression_tutorial

An old tutorial I wrote during class about 10 years ago. It's probably bad, don't use it.
3
star
52

server_simulator_2020

Simulates servers to find the best server to run for the cost
Rust
3
star
53

OnorineAutoCandy

An automated WoW chocolate addon
Lua
3
star
54

simple_slope_viewer

A basic 3d model viewer with a fly-based model. Designed for exploring WoW collision maps
Rust
2
star
55

font_test

Font test do not use ever
Rust
2
star
56

gamlang

Some ancient programming language I thought was a good idea
C
2
star
57

wow_priest_theorycraftin

Here we use supercomputers to optimize WoW characters, why not
Rust
1
star
58

onorine_jumps

A WoW addon for helping with doing tricky jumps and exploring
Lua
1
star
59

triangle_test

Testing triangles
Rust
1
star
60

ErannaAuctions

Dumping ground for auction data harvesting
Lua
1
star
61

FishingBuddy

The FishingBuddy addon for Classic WoW, but with per-hour stat tracking
Lua
1
star
62

speculation_data

Just some random data from an observed speculative session on Kaby Lake
Gnuplot
1
star
63

wow_classic_manatick_reversing

Trying to figure out exactly how mana ticks work in WoW vanilla
Lua
1
star