Python library to automate gdb debugging
Project description
Patchelfy
Patchelfy is a library to inject new code into an ELF without breaking it. It can be used when you can't attach to the process to alter part of the execution or simply log informations while reversing it.
The code has to be written in assembly and some methods are offered to add calls to any libc function or to access specific addresses in the binary.
Log
The simplest use for this library is to log data during the execution.
You can write as many shellcodes as you want on the same address, but you just have to keep in mind that they will be called from the last to the fist you set and the memory will be restored between each of them.
from patchelfy import Patchelf
p = Patchelf("./binary")
# Warning the \n must be escaped
p.log(0x1651, "the function returned %ld\\n", ["rax"])
p.log(0x1651, "I'm at address: 0x%lx\\n", [0x1651])
p.log(0x1651, "This is a log\\n", [])
#p.save("./binary_patched")
# If left empty the name for the new binary will be <name>_patched
p.save()
output:
$ ./binary_patched
This is a log
I'm at address: 0x1651
the function returned 0x7f41f656a000
Access variables on stack
To access variables on the stack, or in another stackframe, you can load them into a register with pre
. Remember to save the original value and restore it after.
from patchelfy import Patchelf
p = Patchelf("./binary")
shellcode = """
push rbp
push rbx
mov rbp, qword ptr [rbp]
mov ebx, dword ptr [rbp - 0x4]
"""
p.log(0x154c, "[process: %d] returned %ld\\n", ["rbx", "rax"], pre=shellcode, post="pop rbx\npop rbp")
p.save()
Place shellcodes
You can insert your own shellcodes inside the binary and reffer to functions in the binary by their relative address
from patchelfy import Patchelf
p = Patchelf("./binary")
# Skip a portion of code
shellcode = """
jmp 0x1537
"""
p.place_shellcode(0x1526, shellcode)
p.save()
Calling a function
If you have to call a function in your shellcode you can use the wrapper Patchelf.shellcode_call
to save all registers and parse your arguments.
If the function you want to call is in the libc you can get a relative address to it with Patchelf.setup_libc
to build your shellcode.
from patchelfy import Patchelf
p = Patchelf("./binary")
system_address = p.setup_libc("memcpy")
ptable = list(range(0x100))
shellcode = p.shellcode_call(system_address, [0x205153, ptable, 0x100])
p.place_shellcode(0x1526, shellcode)
p.save()
Edge cases
To place your shellcode we overwrite 6 bytes of the binary. It is not a problem except if the program has to jump right in that area. Try not to place it there, but if you REALY have to you can use restoring_shellcode that restore the memory once executed. Unfortunately there is nothing I can do if you jump into that area before running your shellcode.
from patchelfy import Patchelf
p = Patchelf("./binary")
# overwrite return value with True
shellcode = """
xor rax, rax
inc rax
"""
p.restoring_shellcode(0x15a3, shellcode)
# If you are in a loop and want your shellcode to be executed each time you need a point to set again your shellcode. This will be developed in a future version
#p.restoring_shellcode(0x15a3, shellcode, loop = 0x15bb)
p.save()
If you need it for a log, use the argument p.log(..., restoring=True)
Installation
stable
pip3 install patchelfy
Limitations
- Can not yet patch a section that will be unpacked at runtime. I will look into a setup to handle it.
- Setup_libc requires the binary to be relro or at least the last function in the got table to be loaded when called. You can inject a restoring_shellcode on entry to the last function of the plt or disable ASLR, load the absolute address in a register and call that register.
- You can only write 2MB of shellcode... Do you really have a case where it isn't enough ?
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file patchelfy-0.1.tar.gz
.
File metadata
- Download URL: patchelfy-0.1.tar.gz
- Upload date:
- Size: 18.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.10.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | a11525a209849c126cdd36ab49dfe5e14fc7b8fff3c75ed16172d5bf00de7df5 |
|
MD5 | a76ac2b0243a7d4a6c790d0a0622be41 |
|
BLAKE2b-256 | 642fc7069e60ad5b341ea348570e94a5db001f177d6da175d59b671a96f65f8c |
File details
Details for the file patchelfy-0.1-py3-none-any.whl
.
File metadata
- Download URL: patchelfy-0.1-py3-none-any.whl
- Upload date:
- Size: 21.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.10.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 25c3f94214470d44994a8d48410a58ac406cb3f16f4f3335655c6b241e8c1511 |
|
MD5 | 78c2e8c8862f8b3050b78bf63c32ef76 |
|
BLAKE2b-256 | 9d6d531a5c19e8d5494a348e85e40ebc237da549a747e245be8d4e5c46070a04 |