docs | ||
out | ||
ROPgadget | ||
test-binaries | ||
.gitignore | ||
.vsjs.json | ||
autoRop.py | ||
exec_args.json | ||
init.sh | ||
README.md | ||
rop_exec_bash.json | ||
rop_exec_default.json | ||
rop_exec.json | ||
ropinstall.sh | ||
Vagrantfile |
AutoROP
_ ___ _.--. ___ _____ ______ _____ ______ ______
\`.|\..----...-'` `-._.-'_.-'` / _ \ / ____| /\ |____ / ____| /\ | ____| ____|
/ ' ` , __.--' | | | |_ _| | / \ / / | / \ | |__ | |__
)/' _/ \ `-_, / | | | \ \/ / | / /\ \ / /| | / /\ \ | __| | __|
`-'" `"\_ ,_.-;_.-\_ ', | |_| |> <| |____ / ____ \ / / | |____ / ____ \| | | |____
_.-'_./ {_.' ; / \___//_/\_\\_____/_/ \_\/_/ \_____/_/ \_\_| |______|
{_.-``-' {_/
__ __
| _______ _ _ _______ _____ ______ _____ _____ |
| |_____| | | | | | |_____/ | | |_____] |
| | | |_____| | |_____| | \_ |_____| | |
|__ __|
Set up Vagrant
The project uses vagrant to ensure consistent results across machines.
vagrant up
vagrant ssh
cd cw
Our test environment uses:
- Vagrant with the Libvirt provider
- Ubuntu 18.04, provided by the image
generic/ubuntu1804
- Python 3.9.0
- A modified version of ROPGadget
autoRop.py
Our ROP exploit is in the Python script autoRop.py
. The script supports automatic gadget discovery and ROP chain exploitation of 32-bit x86 Linux ELF binaries. Broadly, the script works by:
- Generating a padding discovery ROP payload from the target program which executes
/bin/echo "[ Successful ROP! ]"
. - Modifying the padding length on the discovery payload until the exploit is successful.
- Generating the target ROP payload in
exec_args.json
with the discovered padding in step 2. - Running the program with the target payload.
ROP exploit on test binaries
All binaries are located in the test-binaries
directory. Each of them uses a different method for supplying the ROP exploit. Below are instructions for each type. You will see for each attack that it is successful when it prints [ Successful ROP! ]
.
vuln-32
- Binary using file input
This is the original vulnerable program from the lab. It takes its payload from a file, the path to which is passed as an argument.
python autoRop.py --input_method file --run test-binaries/vuln-32
null-data-addr
- Binary using file input
This is the original vulnerable program from the lab, compiled with the flag -Tdata 0x080f0000
. This sets the base .data
address to 0x080f0000
, resulting in null bytes in the data address. We can confirm the data address has been set accordingly with:
$ readelf --sections test-binaries/null-data-addr 2> /dev/null | grep -e "\.data "
> [ 2] .data PROGBITS 080f0000 091000 000f20 00 WA 0 0 32
AutoROP handles this and places its data at a
python autoRop.py --input_method file --run test-binaries/null-data-addr
elf-linux-x86
/elf-linux-x86-NDH-chall
- Binaries using a positional argument
These binaries are largely similar. They both take the payload as their first argument.
python autoRop.py --input_method arg --run test-binaries/elf-Linux-x86
python autoRop.py --input_method arg --run test-binaries/elf-Linux-x86-NDH-chall
crashmail
- Binary using an optional argument
This was a real world vulnerable version of the program crashmail. When the SETTINGS
option is used, the next argument has a buffer overflow vulnerability. Thus, we run this binary with the first argument as SETTINGS
and the next argument as the payload. This can be configured by changing the exec_args file from the default exec_args.json
[ "$PAYLOAD$" ]
to test-binaries/crashmail_exec_args.json
[ "SETTINGS", "$PAYLOAD$" ]
like so:
python autoRop.py --input_method arg --exec_args test-binaries/crashmail_exec_args.json --run test-binaries/crashmail
This may take a little while due to the fairly large required offset.
Changing the execve
target
AutoROP allows you to change what you execute with execve
- enabling the execution of any executable with any arguments. It also allows to automatically run the ROP chain where the ROP payload will generate an interactive program, using the argument --interactive
. Without --interactive
, the program simply dumps the output of the ROP to stdout.
We demonstrate this by making AutoROP generate an interactive shell payload. To do this, we use the file rop_exec_bash.json
:
["/bin/bash", "-p"]
This array represents the execve
arguments - the signature will be execve("/bin/bash", ["/bin/bash", "-p"])
.
The -p
flag is used to enable privileged mode. In this mode, bash will acknowledge the effective user id, allowing exploitation of the setuid
bit. This means that if the target binary has the setuid bit sit, we will be able to get a root shell. We demonstrate this by setting the setuid bit on vuln-32-setuid
. This binary is stored in the home directory due to issues surrounding setting the owner and setuid bit on files in the Vagrant shared directory.
Now we run AutoROP on this binary, and get an interactive root shell:
python autoRop.py --input_method file --rop_exec_file rop_exec_bash.json --run --interactive ~/vuln-32-setuid
We can verify this by typing
whoami
and we get root
!