Skip to content

Commit

Permalink
Merge pull request #20 from ChrisTheCoolHut/point_to_rop_support_git
Browse files Browse the repository at this point in the history
Added support for RopChain leaking and RopChain overflow pwning.
  • Loading branch information
ChrisTheCoolHut authored Dec 22, 2021
2 parents 66bcae1 + b6e10e9 commit 92a9603
Show file tree
Hide file tree
Showing 33 changed files with 1,629 additions and 760 deletions.
56 changes: 33 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
# Zeratool
# Zeratool v2.1
Automatic Exploit Generation (AEG) and remote flag capture for exploitable CTF problems

This tool uses [angr](https://github.com/angr/angr) to concolically analyze binaries by hooking printf and looking for [unconstrained paths](https://github.com/angr/angr-doc/blob/master/docs/examples.md#vulnerability-discovery). These program states are then weaponized for remote code execution through [pwntools](https://github.com/Gallopsled/pwntools) and a series of script tricks. Finally the payload is tested locally then submitted to a remote CTF server to recover the flag.

[![asciicast](https://asciinema.org/a/188002.png)](https://asciinema.org/a/188002)
[![asciicast](https://asciinema.org/a/14.png)](https://asciinema.org/a/14)

## Version 2.1 changes

Zeratool now supports some smart rop chain generation. During a buffer overflow
Zeratool will attempt to leak a libc address and compute the base address and build a execve(/bin/sh,NULL,NULL) chain or system(/bin/sh) chain.

## Installing
Zeratool has been tested on Ubuntu 16.04 and 18.04. Please install [radare2](https://github.com/radareorg/radare2) first
Zeratool has been tested on Ubuntu 16.04 through 20.04. Please install [radare2](https://github.com/radareorg/radare2) first

pip install zeratool

## Usage
Zeratool is a python script which accept a binary as an argument and optionally a linked libc library, and a CTF Server connection information

```
[chris:~/Zeratool] [angr] zerapwn.py -h
usage: zerapwn.py [-h] [-l LIBC] [-u URL] [-p PORT] [-v] file
[chris:~/Zeratool] zerapwn.py -h
usage: zerapwn.py [-h] [-l LIBC] [-u URL] [-p PORT] [-v] [--force_shellcode]
[--format_only] [--overflow_only]
file
positional arguments:
file File to analyze
Expand All @@ -26,6 +33,9 @@ optional arguments:
-u URL, --url URL Remote URL to pwn
-p PORT, --port PORT Remote port to pwn
-v, --verbose Verbose mode
--force_shellcode Set overflow pwn mode to point to shellcode
--format_only Only run format strings check
--overflow_only Only run overflow check
```

## Exploit Types
Expand All @@ -35,30 +45,26 @@ Zeratool is designed around weaponizing buffer overflows and format string vulne
* Point program counter to win function
* Point program counter to shellcode
* Point program counter to rop chain
* Rop chains need a libc base address
* one-gadget and ropper are used rop chain building
* Rop chains will attempt to leak a libc function
* Rop chains will then execve(/bin/sh) or system(/bin/sh)
* Format String
* Point GOT entry to win function
* Point GOT entry to shellcode

Zeratool has room to grow and future iterations of Zeratool will include information disclosure discovery and linking those leaks to an offset for general ASLR bypasses.

## Examples
Checkout the samples.sh file. The file contains several examples of Zeratool automatically solving exploitable CTF problems.

[Long Asciinema with Three Solves](https://asciinema.org/a/188001)

```
#!/bin/bash
#Buffer Overflows with win functions
zerapwn.py challenges/ret -u ctf.hackucf.org -p 9003
zerapwn.py challenges/bof3 -u ctf.hackucf.org -p 9002
zerapwn.py challenges/bof2 -u ctf.hackucf.org -p 9001
zerapwn.py challenges/bof1 -u ctf.hackucf.org -p 9000
#Down for the summer
#python zerapwn.py challenges/easy_format -u tctf.competitivecyber.club -p 7801
#python zerapwn.py challenges/medium_format -u tctf.competitivecyber.club -p 7802
# Buffer Overflows with win functions
zerapwn.py tests/bin/bof_win_32
zerapwn.py tests/bin/bof_win_64
# Buffer Overflows with ropping
zerapwn.py tests/bin/bof_nx_32
zerapwn.py tests/bin/bof_nx_64
# Buffer Overflow with ropping and libc leak
zerapwn.py tests/bin/bof_nx_64 -l tests/bin/libc.so.6_amd64
#Format string leak
zerapwn.py tests/bin/read_stack_32
Expand All @@ -68,11 +74,15 @@ zerapwn.py challenges/medium_format
#Format string point to shellcode
#zerapwn.py challenges/hard_format #This one sometimes needs to be run twice
#Buffer overflow point to shellcode
zerapwn.py tests/bin/bof_32
zerapwn.py tests/bin/bof_64
zerapwn.py challenges/demo_bin # is slow
# Buffer overflow point to shellcode
# Turn off aslr
# echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
zerapwn.py tests/bin/bof_32 --force_shellcode
zerapwn.py tests/bin/bof_64 --force_shellcode
```

[Long Asciinema with Three Solves](https://asciinema.org/a/188001)

## Run the tests!
Tox and Pytest are used to verify that Zeratool is working correctly.
```
Expand Down
84 changes: 64 additions & 20 deletions bin/zerapwn.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import logging
import os

#logging.disable(logging.CRITICAL)
from zeratool import formatDetector
from zeratool import formatLeak
from zeratool import inputDetector
Expand All @@ -16,15 +15,30 @@
from zeratool import winFunctionDetector
from zeratool import formatExploiter

logging.getLogger().disabled = True
logging.basicConfig()
logging.root.setLevel(logging.INFO)

loud_loggers = [
"angr.engines",
"angr.sim_manager",
"angr.simos",
"angr.project",
"angr.procedures",
"cle",
"angr.storage",
]

log = logging.getLogger(__name__)


def is_radare_installed():
return which("r2") is not None


def main():

if not is_radare_installed():
print("[-] Error radare2 is not installed.")
log.info("[-] Error radare2 is not installed.")
exit(1)

parser = argparse.ArgumentParser()
Expand All @@ -35,13 +49,37 @@ def main():
parser.add_argument(
"-v", "--verbose", help="Verbose mode", action="store_true", default=False
)
parser.add_argument(
"--force_shellcode",
default=False,
action="store_true",
help="Set overflow pwn mode to point to shellcode",
)

parser.add_argument(
"--format_only",
default=False,
action="store_true",
help="Only run format strings check",
)
parser.add_argument(
"--overflow_only",
default=False,
action="store_true",
help="Only run overflow check",
)

args = parser.parse_args()
if args.file is None:
print("[-] Exitting no file specified")
log.info("[-] Exitting no file specified")
exit(1)
if args.verbose:
logging.disable(logging.CRITICAL)
logging.basicConfig(level=logging.DEBUG)
if not args.verbose:
for loud_logger in loud_loggers:
logging.getLogger(loud_logger).setLevel(logging.ERROR)

logging.getLogger("angr.project").disabled = True

# For stack problems where env gets shifted
# based on path, using the abs path everywhere
Expand All @@ -53,29 +91,34 @@ def main():
properties["input_type"] = inputDetector.checkInputType(args.file)
properties["libc"] = args.libc
properties["file"] = args.file
print("[+] Checking pwn type...")
print("[+] Checking for overflow pwn type...")
properties["pwn_type"] = overflowDetector.checkOverflow(
args.file, inputType=properties["input_type"]
)
if properties["pwn_type"]["type"] is None:
print("[+] Checking for format string pwn type...")
properties["pwn_type"] = formatDetector.checkFormat(
properties["force_shellcode"] = args.force_shellcode
properties["pwn_type"] = {}
properties["pwn_type"]["type"] = None
log.info("[+] Checking pwn type...")
if not args.format_only:
log.info("[+] Checking for overflow pwn type...")
properties["pwn_type"] = overflowDetector.checkOverflow(
args.file, inputType=properties["input_type"]
)
if not args.overflow_only:
if properties["pwn_type"]["type"] is None:
log.info("[+] Checking for format string pwn type...")
properties["pwn_type"] = formatDetector.checkFormat(
args.file, inputType=properties["input_type"]
)

# Get problem mitigations
print("[+] Getting binary protections")
log.info("[+] Getting binary protections")
properties["protections"] = protectionDetector.getProperties(args.file)

# Is it a leak based one?
if properties["pwn_type"]["type"] == "Format":
print("[+] Checking for flag leak")
log.info("[+] Checking for flag leak")
properties["pwn"] = formatLeak.checkLeak(args.file, properties)
# Launch leak remotely
if properties["pwn"]["flag_found"] and args.url != "":
print("[+] Found flag through leaks locally. Launching remote exploit")
print("[+] Connecting to {}:{}".format(args.url, args.port))
log.info("[+] Found flag through leaks locally. Launching remote exploit")
log.info("[+] Connecting to {}:{}".format(args.url, args.port))
properties["pwn"]["exploit"] = formatLeak.checkLeak(
args.file,
properties,
Expand All @@ -91,11 +134,12 @@ def main():

# Exploit overflows
if properties["pwn_type"]["type"] == "Overflow":
print("[+] Exploiting overflow")
log.info("[+] Exploiting overflow")
properties["pwn_type"]["results"] = {}
properties["pwn_type"]["results"] = overflowExploiter.exploitOverflow(
args.file, properties, inputType=properties["input_type"]
)
if properties["pwn_type"]["results"]["input"]:
if properties["pwn_type"]["results"]["type"]:
properties["send_results"] = overflowExploitSender.sendExploit(
args.file, properties
)
Expand All @@ -122,7 +166,7 @@ def main():
properties, remote_url=args.url, remote_port=int(args.port)
)
else:
print("[-] Can not determine vulnerable type")
log.info("[-] Can not determine vulnerable type")


if __name__ == "__main__":
Expand Down
41 changes: 20 additions & 21 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,23 @@


setuptools.setup(
name='zeratool',
version='2.0',
scripts=['bin/zerapwn.py'] ,
author="Christoppher Roberts",
author_email="",
description="Automatic Exploit Generation (AEG) and remote flag capture for exploitable CTF problems",
url="https://github.com/ChrisTheCoolHut/Zeratool",
packages=["zeratool"],
install_package_data=True,
install_requires=[
"angr",
"r2pipe",
"claripy",
"IPython",
"timeout_decorator",
"pwntools",
"tox",
"tqdm",
],

)
name="zeratool",
version="2.1",
scripts=["bin/zerapwn.py"],
author="Christopher Roberts",
author_email="",
description="Automatic Exploit Generation (AEG) and remote flag capture for exploitable CTF problems",
url="https://github.com/ChrisTheCoolHut/Zeratool",
packages=["zeratool"],
install_package_data=True,
install_requires=[
"angr",
"r2pipe",
"claripy",
"IPython",
"timeout_decorator",
"pwntools",
"tox",
"tqdm",
],
)
9 changes: 7 additions & 2 deletions tests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
build_flags := -fno-stack-protector -z execstack \
-Wno-implicit-function-declaration -no-pie \
-Wno-format-security
build_NX_flags := -fno-stack-protector \
-Wno-implicit-function-declaration -no-pie \
-Wno-format-security -z relro
bin_names := bof_32 bof_64 bof_win_32 bof_win_64 \
read_stack_32 format_pc_write_32 format_write_and_constrain_32 \
read_stack_64 format_pc_write_64 format_write_and_constrain_64 \
Expand All @@ -12,22 +15,24 @@ all: build_bof build_format_32 build_format_64 build_flag
build_bof:
gcc -m32 buffer_overflow.c -o bin/bof_32 $(build_flags)
gcc buffer_overflow.c -o bin/bof_64 $(build_flags)
gcc -m32 buffer_overflow.c -o bin/bof_nx_32 $(build_NX_flags)
gcc buffer_overflow.c -o bin/bof_nx_64 $(build_NX_flags)
gcc -m32 buffer_overflow.c -o bin/bof_win_32 -Dwin_func $(build_flags)
gcc buffer_overflow.c -o bin/bof_win_64 -Dwin_func $(build_flags)

build_format_32:
gcc -O0 -m32 -fno-stack-protector -o bin/read_stack_32 \
format_string.c -DEASY $(build_flags)
gcc -O0 -m32 -fno-stack-protector -o bin/format_pc_write_32 \
format_string.c -DMEDIUM $(build_flags)
format_string.c -DMEDIUM $(build_flags) -z relro
gcc -O0 -m32 -fno-stack-protector -o bin/format_write_and_constrain_32 \
format_string.c -DHARD $(build_flags)

build_format_64:
gcc -O0 -fno-stack-protector -o bin/read_stack_64 \
format_string.c -DEASY $(build_flags)
gcc -O0 -fno-stack-protector -o bin/format_pc_write_64 \
format_string.c -DMEDIUM $(build_flags)
format_string.c -DMEDIUM $(build_flags) -z relro
gcc -O0 -fno-stack-protector -o bin/format_write_and_constrain_64 \
format_string.c -DHARD $(build_flags)

Expand Down
Binary file modified tests/bin/bof_32
Binary file not shown.
Binary file modified tests/bin/bof_64
Binary file not shown.
Binary file added tests/bin/bof_nx_32
Binary file not shown.
Binary file added tests/bin/bof_nx_64
Binary file not shown.
Binary file modified tests/bin/bof_win_32
Binary file not shown.
Binary file modified tests/bin/bof_win_64
Binary file not shown.
Binary file modified tests/bin/format_pc_write_32
Binary file not shown.
Binary file modified tests/bin/format_pc_write_64
Binary file not shown.
Binary file added tests/bin/libc.so.6_amd64
Binary file not shown.
Binary file added tests/bin/libc.so.6_i386
Binary file not shown.
Binary file modified tests/bin/read_stack_32
Binary file not shown.
Binary file modified tests/bin/read_stack_64
Binary file not shown.
Loading

0 comments on commit 92a9603

Please sign in to comment.