diff options
author | Malfurious <m@lfurio.us> | 2022-03-14 00:43:15 -0400 |
---|---|---|
committer | Malfurious <m@lfurio.us> | 2022-03-14 00:43:15 -0400 |
commit | 380bc782b53bdafc2b1d5d37afb16d6d7b91a0e5 (patch) | |
tree | 6fb4228ddfc96d9591240e6a654e0fe199bb12fc | |
parent | 6e24dc3d70b9e915c89d47dc8d7c816f1ba8ffab (diff) | |
parent | cd12c17a6a41102f55ef034fb819a2ee093df356 (diff) | |
download | lib-des-gnux-380bc782b53bdafc2b1d5d37afb16d6d7b91a0e5.tar.gz lib-des-gnux-380bc782b53bdafc2b1d5d37afb16d6d7b91a0e5.zip |
Merge tag 'pull-sploit-rev' of https://github.com/Dusoleil/lib-des-gnux
Add rev for basic reverse engineering
* tag 'pull-sploit-rev' of https://github.com/Dusoleil/lib-des-gnux:
sploit: Move __attr_filter__ to a general place in util
sploit: Filter all magic python members by default in mem module
sploit: add stack base pointer to locals symtbl
sploit: print hex of addresses in rev logs
sploit: add status logging to rev module
sploit: lazy load libs for ELF
sploit: cache results of external commands
sploit: add the rest of r2 functions through elf
sploit: typo fix in rev.r2
sploit: cache ELF loads
sploit: add ELF helper class to rev
sploit: consolidate r2 symbol search calls
sploit: fix r2 module syntax error
sploit: reverse direction of r2 get_locals offsets
sploit: add r2 funcionality to rev module
sploit: add ldd ability to rev module
sploit: add rev module to sploit
-rw-r--r-- | tools/sploit/setup.py | 4 | ||||
-rw-r--r-- | tools/sploit/sploit/__init__.py | 2 | ||||
-rw-r--r-- | tools/sploit/sploit/mem.py | 9 | ||||
-rw-r--r-- | tools/sploit/sploit/rev/__init__.py | 6 | ||||
-rw-r--r-- | tools/sploit/sploit/rev/elf.py | 56 | ||||
-rw-r--r-- | tools/sploit/sploit/rev/ldd.py | 13 | ||||
-rw-r--r-- | tools/sploit/sploit/rev/r2.py | 94 | ||||
-rw-r--r-- | tools/sploit/sploit/util.py | 22 |
8 files changed, 201 insertions, 5 deletions
diff --git a/tools/sploit/setup.py b/tools/sploit/setup.py index eb1b299..5afa958 100644 --- a/tools/sploit/setup.py +++ b/tools/sploit/setup.py @@ -1,7 +1,7 @@ -from setuptools import setup +from setuptools import setup, find_packages setup( name='sploit', version='0', - packages=['sploit'], + packages=find_packages(), entry_points={"console_scripts":["sploit=sploit.main:main"]} ) diff --git a/tools/sploit/sploit/__init__.py b/tools/sploit/sploit/__init__.py index 9e637df..f5a82fc 100644 --- a/tools/sploit/sploit/__init__.py +++ b/tools/sploit/sploit/__init__.py @@ -5,4 +5,6 @@ from sploit import ( mem, payload, until, + util, + rev, ) diff --git a/tools/sploit/sploit/mem.py b/tools/sploit/sploit/mem.py index 3ad0c50..ac2bbb1 100644 --- a/tools/sploit/sploit/mem.py +++ b/tools/sploit/sploit/mem.py @@ -1,3 +1,5 @@ +from sploit.util import __attr_filter__ + class Symtbl: __subs__ = {} def __init__(self, **kwargs): @@ -12,7 +14,7 @@ class Symtbl: self.off = off self.tbl = tbl def __getattribute__(self,sym): - if(sym in ['off','tbl','__class__']): + if(sym in (['off','tbl'] + __attr_filter__)): return object.__getattribute__(self,sym) addr = getattr(self.tbl,sym) if(type(addr)==int): @@ -30,7 +32,8 @@ class Symtbl: def __getattribute__(self, sym): addr = object.__getattribute__(self,sym) - if(sym == '__subs__'):return addr + if(sym in (['__subs__'] + __attr_filter__)): + return addr if(sym == 'base'):return 0 if(sym in self.__subs__): return self.__InnerTable__(addr,self.__subs__[sym]) @@ -51,7 +54,7 @@ class Memmap: self.base = addr - sym def __getattribute__(self, sym): - if(sym in ['__tbl__','base']): + if(sym in (['__tbl__','base'] + __attr_filter__)): return object.__getattribute__(self, sym) addr = getattr(self.__tbl__, sym) if(type(addr)==Symtbl.__InnerTable__): diff --git a/tools/sploit/sploit/rev/__init__.py b/tools/sploit/sploit/rev/__init__.py new file mode 100644 index 0000000..43cee7b --- /dev/null +++ b/tools/sploit/sploit/rev/__init__.py @@ -0,0 +1,6 @@ +from . import ( + ldd, + r2, + elf, +) + diff --git a/tools/sploit/sploit/rev/elf.py b/tools/sploit/sploit/rev/elf.py new file mode 100644 index 0000000..7bfd31f --- /dev/null +++ b/tools/sploit/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/tools/sploit/sploit/rev/ldd.py b/tools/sploit/sploit/rev/ldd.py new file mode 100644 index 0000000..1a28c7c --- /dev/null +++ b/tools/sploit/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/tools/sploit/sploit/rev/r2.py b/tools/sploit/sploit/rev/r2.py new file mode 100644 index 0000000..bb3edb3 --- /dev/null +++ b/tools/sploit/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 diff --git a/tools/sploit/sploit/util.py b/tools/sploit/sploit/util.py new file mode 100644 index 0000000..8a259c4 --- /dev/null +++ b/tools/sploit/sploit/util.py @@ -0,0 +1,22 @@ +from subprocess import run + +def run_cmd(cmd): + return run(cmd,capture_output=True).stdout.decode('utf-8').split('\n')[:-1] + +__RUN_CACHE__ = {} +def run_cmd_cached(cmd): + key = ''.join(cmd) + if key in __RUN_CACHE__: + return __RUN_CACHE__[key] + else: + result = run_cmd(cmd) + __RUN_CACHE__[key] = result + return result + +__attr_filter__ = ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', + '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', + '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', + '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', + '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', + '__weakref__'] + |