From df5e85f1197178df0fac2822e41cf66a59adb502 Mon Sep 17 00:00:00 2001 From: dusoleil Date: Fri, 11 Mar 2022 09:01:18 -0500 Subject: sploit: add rev module to sploit Signed-off-by: dusoleil --- sploit/rev/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 sploit/rev/__init__.py (limited to 'sploit/rev') diff --git a/sploit/rev/__init__.py b/sploit/rev/__init__.py new file mode 100644 index 0000000..e69de29 -- cgit v1.2.3 From 57e5d92be7e82f28adcb3212c73bb06b0b8d7fe8 Mon Sep 17 00:00:00 2001 From: dusoleil Date: Fri, 11 Mar 2022 09:04:32 -0500 Subject: sploit: add ldd ability to rev module add helper function to invoke ldd to get a list of libraries that will be linked to a given ELF Signed-off-by: dusoleil --- sploit/rev/__init__.py | 4 ++++ sploit/rev/ldd.py | 10 ++++++++++ 2 files changed, 14 insertions(+) create mode 100644 sploit/rev/ldd.py (limited to 'sploit/rev') diff --git a/sploit/rev/__init__.py b/sploit/rev/__init__.py index e69de29..c489b98 100644 --- a/sploit/rev/__init__.py +++ b/sploit/rev/__init__.py @@ -0,0 +1,4 @@ +from . import ( + ldd +) + diff --git a/sploit/rev/ldd.py b/sploit/rev/ldd.py new file mode 100644 index 0000000..60306f1 --- /dev/null +++ b/sploit/rev/ldd.py @@ -0,0 +1,10 @@ +import re +from subprocess import run +from collections import namedtuple as nt + +def get_libraries(elf): + out = run(['ldd',elf],capture_output=True).stdout.decode('utf-8').split('\n')[:-1] + 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 -- cgit v1.2.3 From 729c5598b3fcb85e52c62bf19d28a7db2647659d Mon Sep 17 00:00:00 2001 From: dusoleil Date: Fri, 11 Mar 2022 09:15:31 -0500 Subject: sploit: add r2 funcionality to rev module Add an r2 module with several helper functions that do a number of simple reverse engineering tasks to aid in writing simple sploit scripts. The functions in this module invoke radare2 to accomplish their tasks. Signed-off-by: dusoleil --- sploit/rev/__init__.py | 3 +- sploit/rev/r2.py | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 sploit/rev/r2.py (limited to 'sploit/rev') diff --git a/sploit/rev/__init__.py b/sploit/rev/__init__.py index c489b98..b6a73a2 100644 --- a/sploit/rev/__init__.py +++ b/sploit/rev/__init__.py @@ -1,4 +1,5 @@ from . import ( - ldd + ldd, + r2, ) diff --git a/sploit/rev/r2.py b/sploit/rev/r2.py new file mode 100644 index 0000000..cd4684f --- /dev/null +++ b/sploit/rev/r2.py @@ -0,0 +1,92 @@ +from sploit.mem import Symtbl +from sploit.arch import arch + +import re +from subprocess import run +from collections import namedtuple as nt + +def run_cmd(binary,cmd): + return run(['r2','-q','-c',cmd,'-e','scr.color=false',binary],capture_output=True).stdout.decode('utf-8').split('\n')[:-1] + +def get_elf_symbols(elf): + out = {} + + cmd_syms = 'is~ FUNC ' + out_syms = r2.run_cmd(elf,cmd_syms) + out_syms = [re.split(r'\s+',sym) for sym in out_syms] + out_syms = {sym[6]:int(sym[2],0) for sym in out_syms if sym[6].find('.')<0} + out.update(out_syms) + + cmd_syms = 'is~ LOOS ' + out_syms = r2.run_cmd(elf,cmd_syms) + out_syms = [re.split(r'\s+',sym) for sym in out_syms] + out_syms = {sym[6]:int(sym[2],0) for sym in out_syms if sym[6].find('.')<0} + out.update(out_syms) + + cmd_syms = 'is~ TLS ' + out_syms = r2.run_cmd(elf,cmd_syms) + out_syms = [re.split(r'\s+',sym) for sym in out_syms] + out_syms = {sym[6]:int(sym[2],0) for sym in out_syms if sym[6].find('.')<0} + out.update(out_syms) + + cmd_syms = 'ii~ FUNC ' + out_syms = r2.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 = r2.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 = r2.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): + addr = hex(func) + cmd_locals = f's {func};af;aafr;aaft;afvf' + out = r2.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} + return Symtbl(**out) + +def ret_gadget(binary): + cmd_ret = '/R/ ret~ret' + out = r2.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): + cmd_gad = f'"/R/q {gad}"' + out = r2.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 = r2.rop_gadget(gad,elf) + for g in gads: + if g.asm[:-1].replace('; ',';') == gad: + return g + +def get_call_returns(binary,xref_from,xref_to): + cmd_xrefs = f's {hex(xref_from)};af;axq' + xrefs = r2.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 = r2.run_cmd(binary,cmd_ret) + rets.append(CallRet(xref_from,xref_to,int(x[0],0),int(ret[0],0))) + return rets -- cgit v1.2.3 From 8e2b4fab035279f18b015374121933b2f937a8fc Mon Sep 17 00:00:00 2001 From: dusoleil Date: Fri, 11 Mar 2022 09:19:25 -0500 Subject: sploit: reverse direction of r2 get_locals offsets rev.r2's get_locals() function returns a Symtbl of offsets representing the local variables on in a stack frame of a particular function. The offsets returned by r2 are based around the base of the stack, but they are increasing in value as they grow from the stack. To properly model memory, they should decrease in value as they grow from the stack. Signed-off-by: dusoleil --- sploit/rev/r2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sploit/rev') diff --git a/sploit/rev/r2.py b/sploit/rev/r2.py index cd4684f..c133c33 100644 --- a/sploit/rev/r2.py +++ b/sploit/rev/r2.py @@ -54,7 +54,7 @@ def get_locals(binary,func): cmd_locals = f's {func};af;aafr;aaft;afvf' out = r2.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 = {var[1]:-(int(var[0],0)-arch.wordsize) for var in out} return Symtbl(**out) def ret_gadget(binary): -- cgit v1.2.3 From f3b278a1da4bd80c57d54188c270f780fac32c27 Mon Sep 17 00:00:00 2001 From: dusoleil Date: Fri, 11 Mar 2022 09:27:00 -0500 Subject: sploit: fix r2 module syntax error forgot to remove the r2 namespace from the calls from back when it was implemented differently Signed-off-by: dusoleil --- sploit/rev/r2.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'sploit/rev') diff --git a/sploit/rev/r2.py b/sploit/rev/r2.py index c133c33..306e026 100644 --- a/sploit/rev/r2.py +++ b/sploit/rev/r2.py @@ -12,37 +12,37 @@ def get_elf_symbols(elf): out = {} cmd_syms = 'is~ FUNC ' - out_syms = r2.run_cmd(elf,cmd_syms) + out_syms = run_cmd(elf,cmd_syms) out_syms = [re.split(r'\s+',sym) for sym in out_syms] out_syms = {sym[6]:int(sym[2],0) for sym in out_syms if sym[6].find('.')<0} out.update(out_syms) cmd_syms = 'is~ LOOS ' - out_syms = r2.run_cmd(elf,cmd_syms) + out_syms = run_cmd(elf,cmd_syms) out_syms = [re.split(r'\s+',sym) for sym in out_syms] out_syms = {sym[6]:int(sym[2],0) for sym in out_syms if sym[6].find('.')<0} out.update(out_syms) cmd_syms = 'is~ TLS ' - out_syms = r2.run_cmd(elf,cmd_syms) + out_syms = run_cmd(elf,cmd_syms) out_syms = [re.split(r'\s+',sym) for sym in out_syms] out_syms = {sym[6]:int(sym[2],0) for sym in out_syms if sym[6].find('.')<0} out.update(out_syms) cmd_syms = 'ii~ FUNC ' - out_syms = r2.run_cmd(elf,cmd_syms) + 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 = r2.run_cmd(elf,cmd_syms) + 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 = r2.run_cmd(elf,cmd_strs) + 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) @@ -52,14 +52,14 @@ def get_elf_symbols(elf): def get_locals(binary,func): addr = hex(func) cmd_locals = f's {func};af;aafr;aaft;afvf' - out = r2.run_cmd(binary,cmd_locals) + 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} return Symtbl(**out) def ret_gadget(binary): cmd_ret = '/R/ ret~ret' - out = r2.run_cmd(binary,cmd_ret) + out = run_cmd(binary,cmd_ret) out = out[0] out = re.split(r'\s+',out) out = out[1] @@ -67,26 +67,26 @@ def ret_gadget(binary): def rop_gadget(binary,gad): cmd_gad = f'"/R/q {gad}"' - out = r2.run_cmd(binary,cmd_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 = r2.rop_gadget(gad,elf) + gads = rop_gadget(gad,elf) for g in gads: if g.asm[:-1].replace('; ',';') == gad: return g def get_call_returns(binary,xref_from,xref_to): cmd_xrefs = f's {hex(xref_from)};af;axq' - xrefs = r2.run_cmd(binary,cmd_xrefs) + 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 = r2.run_cmd(binary,cmd_ret) + ret = run_cmd(binary,cmd_ret) rets.append(CallRet(xref_from,xref_to,int(x[0],0),int(ret[0],0))) return rets -- cgit v1.2.3 From 63b9139833b847000fe6cc76fad07f6f6866e416 Mon Sep 17 00:00:00 2001 From: dusoleil Date: Fri, 11 Mar 2022 09:48:42 -0500 Subject: sploit: consolidate r2 symbol search calls Consolidate some of the r2 calls that get combined to create the symbol list. Instead of doing multiple calls with different greps within radare2, just do a single call and search it in the python side. This gives us a slight, but noticeable performance increase. Signed-off-by: dusoleil --- sploit/rev/r2.py | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) (limited to 'sploit/rev') diff --git a/sploit/rev/r2.py b/sploit/rev/r2.py index 306e026..6fde112 100644 --- a/sploit/rev/r2.py +++ b/sploit/rev/r2.py @@ -10,23 +10,12 @@ def run_cmd(binary,cmd): def get_elf_symbols(elf): out = {} - - cmd_syms = 'is~ FUNC ' - out_syms = run_cmd(elf,cmd_syms) - out_syms = [re.split(r'\s+',sym) for sym in out_syms] - out_syms = {sym[6]:int(sym[2],0) for sym in out_syms if sym[6].find('.')<0} - out.update(out_syms) - - cmd_syms = 'is~ LOOS ' + cmd_syms = 'is' out_syms = run_cmd(elf,cmd_syms) - out_syms = [re.split(r'\s+',sym) for sym in out_syms] - out_syms = {sym[6]:int(sym[2],0) for sym in out_syms if sym[6].find('.')<0} - out.update(out_syms) - - cmd_syms = 'is~ TLS ' - out_syms = run_cmd(elf,cmd_syms) - out_syms = [re.split(r'\s+',sym) for sym in out_syms] - out_syms = {sym[6]:int(sym[2],0) for sym in out_syms if sym[6].find('.')<0} + 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 ' -- cgit v1.2.3 From 13a1931d7b765009d35c72594310f4a5abcacff4 Mon Sep 17 00:00:00 2001 From: dusoleil Date: Fri, 11 Mar 2022 10:15:35 -0500 Subject: sploit: add ELF helper class to rev Create a class which encapsulates some basic information about an ELF file and provides a convenient interface for basic reverse engineering. In particular, ELF automatically loads the symbol table of the given elf file and recursively creates ELF objects for any linked libraries. Signed-off-by: dusoleil --- sploit/rev/__init__.py | 1 + sploit/rev/elf.py | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 sploit/rev/elf.py (limited to 'sploit/rev') diff --git a/sploit/rev/__init__.py b/sploit/rev/__init__.py index b6a73a2..43cee7b 100644 --- a/sploit/rev/__init__.py +++ b/sploit/rev/__init__.py @@ -1,5 +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..a748f10 --- /dev/null +++ b/sploit/rev/elf.py @@ -0,0 +1,22 @@ +from sploit.rev import ldd, r2 + +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 = {lib.name:ELF(lib.path) for lib in libs.values() if lib.path} + + 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------------' + for name,lib in self.libs.items(): + s += '\n' + str(name) + ' => ' + str(lib.path) + return s -- cgit v1.2.3 From 5cec6f91cb03e568fe30f06b429a178279a518bb Mon Sep 17 00:00:00 2001 From: dusoleil Date: Fri, 11 Mar 2022 10:27:58 -0500 Subject: sploit: cache ELF loads With recursive ELF loads, there is the possibility of loading in a heavy ELF (like libc) multiple times. Hiding instantiation of the class behind a factory method and caching instances should eliminate this problem. Signed-off-by: dusoleil --- sploit/rev/elf.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'sploit/rev') diff --git a/sploit/rev/elf.py b/sploit/rev/elf.py index a748f10..bdced0a 100644 --- a/sploit/rev/elf.py +++ b/sploit/rev/elf.py @@ -1,6 +1,16 @@ from sploit.rev import ldd, r2 -class ELF: +__ELF_CACHE__ = {} + +def ELF(path): + if path in __ELF_CACHE__: + return __ELF_CACHE__[path] + else: + elf = __ELF__(path) + __ELF_CACHE__[path] = elf + return elf + +class __ELF__: def __init__(self, path): self.path = path self.sym = r2.get_elf_symbols(self.path) -- cgit v1.2.3 From 19fc4694e7f825b1fee0cce05c4a34f3ae717679 Mon Sep 17 00:00:00 2001 From: dusoleil Date: Fri, 11 Mar 2022 11:21:34 -0500 Subject: sploit: typo fix in rev.r2 accidentally left the argument as "elf" instead of "binary" and had the arguments in the wrong order Signed-off-by: dusoleil --- sploit/rev/r2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sploit/rev') diff --git a/sploit/rev/r2.py b/sploit/rev/r2.py index 6fde112..af0fe24 100644 --- a/sploit/rev/r2.py +++ b/sploit/rev/r2.py @@ -62,7 +62,7 @@ def rop_gadget(binary,gad): return out def rop_gadget_exact(binary,gad): - gads = rop_gadget(gad,elf) + gads = rop_gadget(binary,gad) for g in gads: if g.asm[:-1].replace('; ',';') == gad: return g -- cgit v1.2.3 From fc1c413bc6b0054cc9c079dbdd2e74eefd75557a Mon Sep 17 00:00:00 2001 From: dusoleil Date: Fri, 11 Mar 2022 11:36:59 -0500 Subject: sploit: add the rest of r2 functions through elf expose the rest of the rev.r2 capabilities through rev.elf Signed-off-by: dusoleil --- sploit/rev/elf.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'sploit/rev') diff --git a/sploit/rev/elf.py b/sploit/rev/elf.py index bdced0a..d9edd40 100644 --- a/sploit/rev/elf.py +++ b/sploit/rev/elf.py @@ -16,6 +16,7 @@ class __ELF__: self.sym = r2.get_elf_symbols(self.path) libs = ldd.get_libraries(self.path) self.libs = {lib.name:ELF(lib.path) for lib in libs.values() if lib.path} + self.locals = self.__LOCALS__(self) def __str__(self): s = 'ELF: ' @@ -30,3 +31,22 @@ class __ELF__: for name,lib in self.libs.items(): s += '\n' + str(name) + ' => ' + str(lib.path) return s + + class __LOCALS__: + def __init__(self,elf): + self.elf = elf + def __getattribute__(self, sym): + if(sym=='elf'):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 -- cgit v1.2.3 From 509a8cfcadcca94d336fe08be897f62a721079d2 Mon Sep 17 00:00:00 2001 From: dusoleil Date: Sat, 12 Mar 2022 19:18:28 -0500 Subject: sploit: cache results of external commands rather than cacheing ELF instantiations, just cache the results of external commands Signed-off-by: dusoleil --- sploit/rev/elf.py | 12 +----------- sploit/rev/ldd.py | 5 +++-- sploit/rev/r2.py | 4 ++-- 3 files changed, 6 insertions(+), 15 deletions(-) (limited to 'sploit/rev') diff --git a/sploit/rev/elf.py b/sploit/rev/elf.py index d9edd40..1957c15 100644 --- a/sploit/rev/elf.py +++ b/sploit/rev/elf.py @@ -1,16 +1,6 @@ from sploit.rev import ldd, r2 -__ELF_CACHE__ = {} - -def ELF(path): - if path in __ELF_CACHE__: - return __ELF_CACHE__[path] - else: - elf = __ELF__(path) - __ELF_CACHE__[path] = elf - return elf - -class __ELF__: +class ELF: def __init__(self, path): self.path = path self.sym = r2.get_elf_symbols(self.path) diff --git a/sploit/rev/ldd.py b/sploit/rev/ldd.py index 60306f1..d162207 100644 --- a/sploit/rev/ldd.py +++ b/sploit/rev/ldd.py @@ -1,9 +1,10 @@ +from sploit.util import run_cmd_cached + import re -from subprocess import run from collections import namedtuple as nt def get_libraries(elf): - out = run(['ldd',elf],capture_output=True).stdout.decode('utf-8').split('\n')[:-1] + 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} diff --git a/sploit/rev/r2.py b/sploit/rev/r2.py index af0fe24..c7a8a65 100644 --- a/sploit/rev/r2.py +++ b/sploit/rev/r2.py @@ -1,12 +1,12 @@ from sploit.mem import Symtbl from sploit.arch import arch +from sploit.util import run_cmd_cached import re -from subprocess import run from collections import namedtuple as nt def run_cmd(binary,cmd): - return run(['r2','-q','-c',cmd,'-e','scr.color=false',binary],capture_output=True).stdout.decode('utf-8').split('\n')[:-1] + return run_cmd_cached(['r2','-q','-c',cmd,'-e','scr.color=false',binary]) def get_elf_symbols(elf): out = {} -- cgit v1.2.3 From 8897faa7387f8103df9dfdb54149d59bfde0e681 Mon Sep 17 00:00:00 2001 From: dusoleil Date: Sat, 12 Mar 2022 20:36:30 -0500 Subject: sploit: lazy load libs for ELF Signed-off-by: dusoleil --- sploit/rev/elf.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'sploit/rev') diff --git a/sploit/rev/elf.py b/sploit/rev/elf.py index 1957c15..acfe73b 100644 --- a/sploit/rev/elf.py +++ b/sploit/rev/elf.py @@ -5,7 +5,7 @@ class ELF: self.path = path self.sym = r2.get_elf_symbols(self.path) libs = ldd.get_libraries(self.path) - self.libs = {lib.name:ELF(lib.path) for lib in libs.values() if lib.path} + self.libs = self.__LIBS__(libs) self.locals = self.__LOCALS__(self) def __str__(self): @@ -18,12 +18,24 @@ class ELF: s += '\n------------' s += '\nLibararies' s += '\n------------' - for name,lib in self.libs.items(): - s += '\n' + str(name) + ' => ' + str(lib.path) + 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): + def __init__(self, elf): self.elf = elf def __getattribute__(self, sym): if(sym=='elf'):return object.__getattribute__(self,sym) -- cgit v1.2.3 From 6bc9c69c534447ecec79ae551d8f6b3e50c71eba Mon Sep 17 00:00:00 2001 From: dusoleil Date: Sat, 12 Mar 2022 21:22:36 -0500 Subject: sploit: add status logging to rev module Signed-off-by: dusoleil --- sploit/rev/ldd.py | 2 ++ sploit/rev/r2.py | 11 +++++++++++ 2 files changed, 13 insertions(+) (limited to 'sploit/rev') diff --git a/sploit/rev/ldd.py b/sploit/rev/ldd.py index d162207..1a28c7c 100644 --- a/sploit/rev/ldd.py +++ b/sploit/rev/ldd.py @@ -1,9 +1,11 @@ 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") diff --git a/sploit/rev/r2.py b/sploit/rev/r2.py index c7a8a65..ffa6dd4 100644 --- a/sploit/rev/r2.py +++ b/sploit/rev/r2.py @@ -1,6 +1,7 @@ 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 @@ -9,7 +10,9 @@ 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:] @@ -39,6 +42,8 @@ def get_elf_symbols(elf): return Symtbl(**out) def get_locals(binary,func): + ilog(f'Retrieving local stack frame of {func} in {binary} with r2...') + addr = hex(func) cmd_locals = f's {func};af;aafr;aaft;afvf' out = run_cmd(binary,cmd_locals) @@ -47,6 +52,8 @@ def get_locals(binary,func): return Symtbl(**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] @@ -55,6 +62,8 @@ def ret_gadget(binary): 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") @@ -68,6 +77,8 @@ def rop_gadget_exact(binary,gad): return g def get_call_returns(binary,xref_from,xref_to): + ilog(f'Getting return addresses of calls from {xref_from} to {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] -- cgit v1.2.3 From 22771b12afcc50e3281e48301cedfd0599624b6e Mon Sep 17 00:00:00 2001 From: dusoleil Date: Sun, 13 Mar 2022 00:27:21 -0500 Subject: sploit: print hex of addresses in rev logs Signed-off-by: dusoleil --- sploit/rev/r2.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sploit/rev') diff --git a/sploit/rev/r2.py b/sploit/rev/r2.py index ffa6dd4..97eeadd 100644 --- a/sploit/rev/r2.py +++ b/sploit/rev/r2.py @@ -42,7 +42,7 @@ def get_elf_symbols(elf): return Symtbl(**out) def get_locals(binary,func): - ilog(f'Retrieving local stack frame of {func} in {binary} with r2...') + 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' @@ -77,7 +77,7 @@ def rop_gadget_exact(binary,gad): return g def get_call_returns(binary,xref_from,xref_to): - ilog(f'Getting return addresses of calls from {xref_from} to {xref_to} in {binary} with r2...') + 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) -- cgit v1.2.3 From 0ddf210c257cd27bb78743b5548d4c26fe1521df Mon Sep 17 00:00:00 2001 From: dusoleil Date: Sun, 13 Mar 2022 04:33:58 -0400 Subject: sploit: add stack base pointer to locals symtbl Signed-off-by: dusoleil --- sploit/rev/r2.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sploit/rev') diff --git a/sploit/rev/r2.py b/sploit/rev/r2.py index 97eeadd..bb3edb3 100644 --- a/sploit/rev/r2.py +++ b/sploit/rev/r2.py @@ -49,7 +49,9 @@ def get_locals(binary,func): 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} - return Symtbl(**out) + out = Symtbl(**out) + out.sbp = 0 + return out def ret_gadget(binary): ilog(f'Searching for a ret gadget in {binary} with r2...') -- cgit v1.2.3 From c493a8f8073702bcdccdbc40bf09931e201c9013 Mon Sep 17 00:00:00 2001 From: dusoleil Date: Sun, 13 Mar 2022 23:34:23 -0400 Subject: sploit: Move __attr_filter__ to a general place in util Found a spot to use __attr_filter__ in the rev module, so moving it out of mem and into a shared place (util). Signed-off-by: dusoleil --- sploit/rev/elf.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sploit/rev') diff --git a/sploit/rev/elf.py b/sploit/rev/elf.py index acfe73b..7bfd31f 100644 --- a/sploit/rev/elf.py +++ b/sploit/rev/elf.py @@ -1,4 +1,5 @@ from sploit.rev import ldd, r2 +from sploit.util import __attr_filter__ class ELF: def __init__(self, path): @@ -38,7 +39,8 @@ class ELF: def __init__(self, elf): self.elf = elf def __getattribute__(self, sym): - if(sym=='elf'):return object.__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): -- cgit v1.2.3