Skip to main content

Complete Binary Patcher

Project description

Datolite

A modular binary patcher


Patch File Structure (.dpt)

BASE HIDDEN_OFFSET START:END (FILLER?)

00 01 02 03 04 05 06 07 08

(Single patch file)

EVERY VALUE IN THE FILE IS HEXADECIMAL

BASE HIDDEN_OFFSET START:END (FILLER?)

01 02 03 04 05 06 07 08

---

BASE HIDDEN_OFFSET START:END (FILLER?)

09 0A 0B 0C 0D 0E 0F 10

(Multi patch file)

BASE HIDDEN_OFFSET START:END (FILLER?)

$ data/message.txt

(Including file content as bytes)

BASE HIDDEN_OFFSET START:END (FILLER?)

09 0A 0B 0C 0D 0E 0F 10
>> mov rax, 0x10

(Instruction encoding at patch time, the architecutre is detected from the source file)

BASE HIDDEN_OFFSET START:END (FILLER?)

c=> testing/test.c:main

(Compilation, disassembly and encoding of a C file at patch-time, format path:function)

! SPACES AND DASHES ARE IMPORTANT AS THERE ISN'T A LEXER SO THE PARSING IS DONE WITH REGEX!


Explaination

BASE = Virtual Offset, 0x100000 by convention

HIDDEN_OFFSET = Win32/64 executables have a 0xC00 offset from base

START = Start address of the VIRTUAL memory region to map (gather via disassembler)

END = End address of the VIRTUAL memory region to map (gather via disassembler)

FILLER = Optional value that is going to be put to fill the region, 0x90 is the default as it is NOP instruction

(In case of instructions the end is always the address of the instruction after the region)


Root Config File (.dls)

When patching an executable without scripting the process you have to use root.dls

Just JSON without comments

{
  "executable": "testing/test",
  "output": "patched_test",
  "patches": ["testing/stringPatch.dpt"]
}

(Output is optional, if not set it will be path/patched.filename)

Working with C

So when using the C compilation feature you'll have problems with referencing executable functions. To solve this issue you just have to define this macro:

#define DECLARE(ADDRESS, RET_TYPE, NAME, ...) \
    typedef RET_TYPE (*NAME##_t)(__VA_ARGS__); \
    static const NAME##_t NAME = (NAME##_t)(ADDRESS);

#define RELATIVE(offset) ({ \
    void* _current_address; \
    void* _target_address = (void*)(&not_present_in_code); \
    __asm__ volatile ( \
        "lea (%%rip), %0" \
        : "=r" (_current_address) \
    ); \
    (char*)_target_address - (char*)_current_address + (offset); \
})

#define RELCALL(offset) ({ \
    void (*func)(); \
    void* _target_address = RELATIVE(offset); \
    func = (void (*)())(_target_address); \
    func(); \
})

Then you can use it like this:

DECLARE(0x12345678, void, exploit_function)
DECLARE(0x87654321, int, add, int, int)

int patch_fn() {
  add(1,2);
  exploit_function();
  return 0;
}

DECLARE WILL NOT WORK WITH PIE, KASLR AND SIMILIAR MITIGATIONS. USE RELATIVE INSTEAD

int patch_fn() {
  int placeholder=0;
  RELCALL(+0x10);
  return 0;
}

This will call any instruction at instruction_after_placeholder + 0x10

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

datolite-1.0.6.tar.gz (9.3 kB view hashes)

Uploaded Source

Built Distribution

datolite-1.0.6-py3-none-any.whl (9.6 kB view hashes)

Uploaded Python 3

Supported by

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