Skip to main content

Python package to create shellcdoes from elfs supported arch (mips, arm (32bit), i386 32bit, i386 64bit, aarch64)

Project description

Elf to shellcode

Convert standard elf files to standalone shellcodes. Please read the following documentation and view the examples for this project to work properly

Project links

Github

Pypi

Supported architectures

  • mips
  • i386 (32bit)
  • i386 (64bit)
  • arm (32bit)
  • aarch64 (arm 64 bit)

Installation:

# Unfortunately only python2 is supported for now
python2 -m pip install elf_to_shellcode

How does this work ?

The python library parses the elf and create a simple relocatable file format Then the mini loader is inserted as the entry point of the elf the mini loader will load the relocatable format and execute it. There are no special requirements, the library contain the compiled mini loaders.

This project is intended to convert elf to os independent shellcodes. Therefor the loader never allocate memory and the shellcode format is not packed. You can just execute it, eg ...

((void (*)()) shellcode)();

note that __libc_start_main perform syscalls therefor if you want your shellcode to be fully os independent you must compile with -nostartfiles follow the examples below

Creating a shellcode

Some compilation flags are required for this to work properly. You must compile the binary with -fPIE and -static take a look at the provided examples below (makefile).

shellcode is a stripped binary with no symbols and no elf information only opcodes, in order to make the shellcode this library require a binary with elf information. so make sure you are not stripping the binary before using this library

simplified make command for mips big endian

gcc example.c -fno-stack-protector -fPIE -fpic -static -nostartfiles --entry=main -o binary.out
#                       [Architectures] [ENDIAN] [Libc full support]
python -m elf_to_shellcode --input binary.out --arch mips --endain big
                                         

Examples:

Makefile

Example.c

Compiling with libc

Libc has destructors and constructors only some architectures fully support libc. take a look at the provided example (which uses libc) and note that some function won't work properly in some architectures.

eg...

printf is using fwrite which uses the FILE * struct for stdout. this file is opened post libc initialization (in one of the libc constructors). __libc_start_main is responsible for calling libc constructors and we don't support __start in all architecutres (for other reasons). therefor you can't use printf in the shellcode, but you can implement it using snprintf and write

Architectures that fully support libc:

  • None

Converting the elf to shellcode:

from elf_to_shellcode.relocate import make_shellcode, Arches, Startfiles
shellcode = make_shellcode(
    binary_path="/tmp/binary.out",
    arch=Arches.MIPS_32,
    endian="big",
    # Currently, no arch support glibc
    start_file_method=Startfiles.no_start_files, 
)

with open("myshellcode.out", 'wb') as fp:
    fp.write(shellcode)

Testing your shellcode

You can use the provided shellcode Loader to test you shellcodes

qemu-mips ./shellcode_loader ./myshellcode.out

Output example

Shellcode size = 66620
Allocating shellcode buffer, size = 69632
Mapping new memory, size = 69632
Jumping to shellcode, address = 0x7f7ee000
Hello from shellcode !

Specific architecture limitations

AARCH64

arm in 64 bit mode generate adrl instruction. These instructions are (2 ** 12) aligned (page) therfore the shellcode should be page aligned to overcome this limitation the shellcode is padded

Optimizations

some Compiler optimization (like -o3) may produce un-shellcodeable output.

Example of compiler optimization (intel x32):

void * func1() {
    // ... function code
}
void * func2() {
    // ... function code
}

void * funcs[2] = {
    func1,
    func2
};

void main(int argc) {
    if(argc == 1) {
        funcs[0]();    
    }
    else {
        funcs[1]();
    }
}

This example actually fools -fPIE and the provided output is

cmp eax, 1 ; argc
je call_func_zero
; address is incorrect here because we are in PIC mode
call <address_of_func_one> 
call_func_zero:
    call <address_of_func_zero>

Address is incorrect and should be calculated as:

get_pc:
    mov eax, [esp]
    ret

call get_pc
lea eax, [eax+relative_address_of_func_1]
; then
call eax

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

elf_to_shellcode-2.0.tar.gz (14.4 kB view details)

Uploaded Source

File details

Details for the file elf_to_shellcode-2.0.tar.gz.

File metadata

  • Download URL: elf_to_shellcode-2.0.tar.gz
  • Upload date:
  • Size: 14.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.0 CPython/3.9.12

File hashes

Hashes for elf_to_shellcode-2.0.tar.gz
Algorithm Hash digest
SHA256 50b9fe6ee125ab0c78e85a54f1a6f24b22cb99c726736a514f7c3657f73c5c87
MD5 e4ff895d5026da0056b2586f1c517c4a
BLAKE2b-256 229c63b5ba4bd448f23f64ec8022a79fed7aa1005112194f0222f5f3f54f6c45

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page