diff options
Diffstat (limited to 'sploit/rev')
| -rw-r--r-- | sploit/rev/__init__.py | 6 | ||||
| -rw-r--r-- | sploit/rev/elf.py | 56 | ||||
| -rw-r--r-- | sploit/rev/ldd.py | 13 | ||||
| -rw-r--r-- | sploit/rev/r2.py | 94 | 
4 files changed, 169 insertions, 0 deletions
| diff --git a/sploit/rev/__init__.py b/sploit/rev/__init__.py new file mode 100644 index 0000000..43cee7b --- /dev/null +++ b/sploit/rev/__init__.py @@ -0,0 +1,6 @@ +from . import ( +        ldd, +        r2, +        elf, +) + diff --git a/sploit/rev/elf.py b/sploit/rev/elf.py new file mode 100644 index 0000000..7bfd31f --- /dev/null +++ b/sploit/rev/elf.py @@ -0,0 +1,56 @@ +from sploit.rev import ldd, r2 +from sploit.util import __attr_filter__ + +class ELF: +    def __init__(self, path): +        self.path = path +        self.sym = r2.get_elf_symbols(self.path) +        libs = ldd.get_libraries(self.path) +        self.libs = self.__LIBS__(libs) +        self.locals = self.__LOCALS__(self) + +    def __str__(self): +        s = 'ELF: ' +        s += self.path +        s += '\nSymbol Table' +        s += '\n------------' +        s += '\n' +        s += str(self.sym) +        s += '\n------------' +        s += '\nLibararies' +        s += '\n------------' +        s += str(self.libs) +        return s + +    class __LIBS__(dict): +        def __init__(self, libs): +            super().__init__({lib.name:lib.path for lib in libs.values() if lib.path}) +        def __getitem__(self, lib): +            get = super().__getitem__ +            if(type(get(lib))==str):self[lib] = ELF(get(lib)) +            return get(lib) +        def __str__(self): +            s = '' +            for name,lib in self.items(): +                s += '\n' + str(name) + ' => ' + lib if(type(lib)==str) else str(lib.path) +            return s + +    class __LOCALS__: +        def __init__(self, elf): +            self.elf = elf +        def __getattribute__(self, sym): +            if(sym in (['elf'] + __attr_filter__)): +                return object.__getattribute__(self,sym) +            return r2.get_locals(self.elf.path, getattr(self.elf.sym, sym)) + +    def retaddr(self, caller, callee): +        return [c.ret_addr for c in r2.get_call_returns(self.path, caller, callee)] + +    def retgad(self): +        return r2.ret_gadget(self.path) + +    def gad(self, gad): +        return [g.addr for g in r2.rop_gadget(self.path, gad)] + +    def egad(self, gad): +        return r2.rop_gadget_exact(self.path, gad).addr diff --git a/sploit/rev/ldd.py b/sploit/rev/ldd.py new file mode 100644 index 0000000..1a28c7c --- /dev/null +++ b/sploit/rev/ldd.py @@ -0,0 +1,13 @@ +from sploit.util import run_cmd_cached +from sploit.log import ilog + +import re +from collections import namedtuple as nt + +def get_libraries(elf): +    ilog(f'Retrieving linked libraries of {elf} with ldd...') +    out = run_cmd_cached(['ldd',elf]) +    out = [re.split(r'\s+',lib)[1:] for lib in out] +    Lib = nt("Lib", "name path addr") +    out = {l[0]:Lib(l[0],l[0] if l[0][0]=='/' else l[2] if l[1]=='=>' else None,l[-1]) for l in out} +    return out diff --git a/sploit/rev/r2.py b/sploit/rev/r2.py new file mode 100644 index 0000000..bb3edb3 --- /dev/null +++ b/sploit/rev/r2.py @@ -0,0 +1,94 @@ +from sploit.mem import Symtbl +from sploit.arch import arch +from sploit.util import run_cmd_cached +from sploit.log import ilog + +import re +from collections import namedtuple as nt + +def run_cmd(binary,cmd): +    return run_cmd_cached(['r2','-q','-c',cmd,'-e','scr.color=false',binary]) + +def get_elf_symbols(elf): +    ilog(f'Retrieving symbols of {elf} with r2...') +    out = {} + +    cmd_syms = 'is' +    out_syms = run_cmd(elf,cmd_syms) +    out_syms = [re.split(r'\s+',sym) for sym in out_syms][4:] +    out_syms = [sym for sym in out_syms if sym[6].find('.')<0] +    out_syms = [sym for sym in out_syms if sym[4]=='FUNC' or sym[4]=='LOOS' or sym[4]=='TLS'] +    out_syms = {sym[6]:int(sym[2],0) for sym in out_syms} +    out.update(out_syms) + +    cmd_syms = 'ii~ FUNC ' +    out_syms = run_cmd(elf,cmd_syms) +    out_syms = [re.split(r'\s+',sym) for sym in out_syms] +    out_syms = {"_PLT_"+sym[4]:int(sym[1],0) for sym in out_syms} +    out.update(out_syms) + +    cmd_syms = 'fs relocs;f' +    out_syms = run_cmd(elf,cmd_syms) +    out_syms = [re.split(r'\s+',sym) for sym in out_syms] +    out_syms = {"_GOT_"+sym[2][sym[2].rfind('.')+1:]:int(sym[0],0) for sym in out_syms} +    out.update(out_syms) + +    cmd_strs = 'fs strings;f' +    out_strs = run_cmd(elf,cmd_strs) +    out_strs = [re.split(r'\s+',sym) for sym in out_strs] +    out_strs = {sym[2][sym[2].rfind('.')+1:]:int(sym[0],0) for sym in out_strs} +    out.update(out_strs) + +    return Symtbl(**out) + +def get_locals(binary,func): +    ilog(f'Retrieving local stack frame of {hex(func)} in {binary} with r2...') + +    addr = hex(func) +    cmd_locals = f's {func};af;aafr;aaft;afvf' +    out = run_cmd(binary,cmd_locals) +    out = [re.split(r':?\s+',var) for var in out] +    out = {var[1]:-(int(var[0],0)-arch.wordsize) for var in out} +    out = Symtbl(**out) +    out.sbp = 0 +    return out + +def ret_gadget(binary): +    ilog(f'Searching for a ret gadget in {binary} with r2...') + +    cmd_ret = '/R/ ret~ret' +    out = run_cmd(binary,cmd_ret) +    out = out[0] +    out = re.split(r'\s+',out) +    out = out[1] +    return int(out,0) + +def rop_gadget(binary,gad): +    ilog(f'Searching for "{gad}" gadgets in {binary} with r2...') + +    cmd_gad = f'"/R/q {gad}"' +    out = run_cmd(binary,cmd_gad) +    Gad = nt("Gad", "addr asm") +    out = [Gad(int(gad[:gad.find(':')],0),gad[gad.find(':')+2:]) for gad in out] +    return out + +def rop_gadget_exact(binary,gad): +    gads = rop_gadget(binary,gad) +    for g in gads: +        if g.asm[:-1].replace('; ',';') == gad: +            return g + +def get_call_returns(binary,xref_from,xref_to): +    ilog(f'Getting return addresses of calls from {hex(xref_from)} to {hex(xref_to)} in {binary} with r2...') + +    cmd_xrefs = f's {hex(xref_from)};af;axq' +    xrefs = run_cmd(binary,cmd_xrefs) +    xrefs = [re.split(r'\s+',x) for x in xrefs] +    xrefs = [x for x in xrefs if int(x[2],0)==xref_to] +    rets = [] +    CallRet = nt("CallRet", "xref_from xref_to call_addr ret_addr") +    for x in xrefs: +        cmd_ret = f's {x[0]};so;s' +        ret = run_cmd(binary,cmd_ret) +        rets.append(CallRet(xref_from,xref_to,int(x[0],0),int(ret[0],0))) +    return rets | 
