This is a personal project, intended for my own learning experience. While I will attempt to make it easily cloneable and runnable, it might not be and is not aiming to be.
This project was developed on ubuntu and might not work as expected on different environments (compiling and turning off ASLR might work differently)
This is very much a learning project and is not meant to be perfect, so expect it to be very rough around the edges. Criticism (even not constructive one if you just want to make fun of me) is very welcome!
Im pretty much done with this project, There are still plenty of TODOs in the code and in the TODO section, but I feel i've covered the most relevant parts for me, and I want to move on to other projects.
What is implemented:
- Successfully runs /bin/sh on target machine with 100% success rate.
- Either on local (GLIBC 2.39-0ubuntu8.3)
- And remote machine (GLIBC 2.32-0ubuntu3)
- Successfully uses DirtyPipe to change the password of root.
- Successfully installs ssh key for root as backdoor.
- Successfully restores the running program when existing shell.
- Successfully cleans up target after execution/on failure.
- Uses my own custom Offender library for offset and data extraction from target elfs! Check it out: #TODO: add link.
- Clone project
git clone [email protected]:RonItay/exploitation-fun.git
- Instantiate virtual environment for project and activate it
python -m venv ./.venv
source .venv/bin/activate
- Install dependencies
pip3 install -r requirements.txt
- Update PYTHONPATH to include project directory
export PYTHONPATH=</path/to/project/directory>
- Run exploit
runner/runner.py -f project_directory/vulnerable-program/vulnerable_no_protectoins.out ARGS
Currently, runner.py requires both libc path libc's external DWARF information path. libc path can be found with:
ldd vulnerable_no_information.out
. Its name will probably be libc.so.6
finding external DWARF file:
readelf -p .gnu_debuglink /your/libc/file
- This prints a file name ending with .debug.
- This file should be in one of the subdirectories of /usr/lib/debug/.build-id, use the
find
command to find it there (or just search your entire filesystem)
Also, for backdoor installation, create an ssh key named "test" in your home ssh file.
-
A vulnerable binary
- Currently written in
basic.c
- Just prints back what is said to it
- Contains both a buffer overflow (unsafe scanf) and an info leak (through format string attack)
- Compiled with all available mitigations
- DEP
- ASLR
- CANARY
- Currently written in
-
A vulnerable server
- A linux machine with kernel version vulnerable to dirty-pipe
The vulnerable server presents an endpoint that runs the vulnerable binary.
Get a rooted backdoor on the server.
- Leak information using format string attack
- ROP chain to shellcode using buffer overflow.
- Shellcode leads to arbitrary RCE (currently using
system
to/bin/sh
) - Privilege escalation using my own implementation of dirty-pipe
- Persistent backdoor installation (Still need to define with this backdoor contains)
- Finish TODOs in code.
- Make the code actually good
- Comb it
- mypy, black, ruff...
- add a massive dirtypipe explanation (couldn't find a super deep and adequate one online, might as well create it myself.)
- Get a full picture of exploitation from beginning to end
- Experience all parts of exploitation development
- Increase my knowledge of exploitation tools
- Build a can-do attitude
- Have fun
High level script to run the exploit from end to end. Changes the password of root to PWNED. Installs ssh key to root. Changes back to original password. Ended with and interactive shell.
It can currently accept either: (mutually exclusive)
- Path to a local vulnerable binary
- In this scenario, runner.py is responsible for running the vulnerable program.
- IP:PORT of the endpoint hosting the vulnerable binary.
- In this scenario, the endpoint needs to be already up and running.
- Endpoint script is found in
endpoint
directory, that will be expanded upon further.
Please run runner.py --help
to see all relevant arguments.
-
endpoint.py
- Python script that runs an endpoint that exposes the vulnerable binary.
- Run
endpoint.py --help
to see all relevant arguments.
-
endpoint.sh
- Bash script that runs the endpoint (if target machine has difficulties installing python)
- First argument is the vulnerable binary to expose.
- Second is the port to listen on.
- contains the vulnerable program
basic.c
- contains the compilation script
compile.sh
- Has explanations on all the flags used.
- Uses gcc, will not work on non-linux platforms
- contains different compilations of
basic.c
with different mitigations.
Contains classes that generate required payloads to send to the attacked binary. Currently, contains:
InfoLeakGenerator
- Generates payload that leaks info from the stack.
PayloadGenerator
- Top level class that orchestrates the entire payload
RopGenerator
- Generates the ROP chain structure.
ShellcodeGenerator
- generates different kinds of shellcodes. currently implemented:
execve
- callsexecve
syscall and exists upon finishing shell.system
- callssystem
syscall and restores running upon exiting shell.
PayloadByteArray
- Base class of the underlying byte array sent to the vulnerable program.
- dirtypipe.c contains C implementation of DirtyPipe
DirtyPipeRunner
orchestrates the exploitation- Exploitation is done by overriding the root password in /etc/passwd
- generate_password_hash.sh generates the password hash for /etc/passwd
- Orchestrates backdoor installation.
- Very simple backdoor, ssh key installed for root.
- Just contains some utils
- Currently, contains only a stress test.
- offset_config:
- Configuration for Offender. An example of its capabilities!
-
Offset extraction
- Uses my own library called Offender to extract the offsets!
- Please look at the Offender repository!
-
Process of find the (extremely easy) ROP chain
- used ropper python library
-
pwndbg scripts used