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/elf.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 sploit/rev/elf.py (limited to 'sploit/rev/elf.py') 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/elf.py') 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 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/elf.py') 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 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'sploit/rev/elf.py') 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) -- 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/elf.py') 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 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/elf.py') 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