summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordusoleil <howcansocksbereal@gmail.com>2023-03-16 18:57:11 -0400
committerdusoleil <howcansocksbereal@gmail.com>2023-03-16 18:57:11 -0400
commit42ab380423553720a2a80d03dee68957e6f3b4ff (patch)
tree3aecf3483e2cc83d124781e1979e0d004f65dd85
parent143f585b0e02ae87e0d383e27c48aa76745db51b (diff)
downloadsploit-42ab380423553720a2a80d03dee68957e6f3b4ff.tar.gz
sploit-42ab380423553720a2a80d03dee68957e6f3b4ff.zip
elf: Add docstrings
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
-rw-r--r--sploit/rev/elf.py107
1 files changed, 107 insertions, 0 deletions
diff --git a/sploit/rev/elf.py b/sploit/rev/elf.py
index 5833bf5..990cfde 100644
--- a/sploit/rev/elf.py
+++ b/sploit/rev/elf.py
@@ -1,9 +1,95 @@
+"""
+Definition of the ELF class
+"""
+
from sploit.rev import ldd, r2
from sploit.arch import lookup_arch
from itertools import zip_longest
class ELF:
+ """
+ Representation of an ELF binary file.
+
+ This class is effectively a front-end for the r2 module. Through ELF, you
+ can get information about an ELF binary in a convenient, object-oriented
+ interface and automate some of your static analysis reverse engineering.
+
+ Because much of the functionality of r2 is cached, much of the functionality
+ of ELF is also implicitly cached. Longer operations like retrieving the
+ symbol table or looking up gadgets will be faster on subsequent attempts.
+ This is mostly useful when sploit is run from the REPL or in Pipes mode
+ where this cache is preserved across script runs.
+
+ Some of the behavior of this class is done upfront while other operations
+ are performed lazily. Retrieving symbols, binary info, security info, and
+ the list of library dependencies are all done upfront when the object is
+ constructed.
+
+ path (str): Absolute file path to the underlying ELF file.
+
+ sym (Symtbl): A collection of named address offsets exposed through the ELF.
+
+ libs (dict{str:ELF}): A dictionary of ELFs representing linked library
+ dependencies of the current ELF. They are indexed by their base filename
+ (i.e. elf.libs["libc.so.6"]). The actual ELF is lazily constructed when it
+ is requested. Pretty printing of the libs dict is implemented.
+
+ locals (->Symtbl): A psuedo-namespace to access Symtbls for the local
+ variables of functions. i.e. If a function existed in the elf called foo(),
+ you could get a Symtbl of its local variables with elf.locals.foo
+
+ info (->str|int): A psuedo-namespace to access various info about the ELF
+ file. Printing elf.info will pretty-print this info in a tabulated form.
+
+ info.type (str): The type of file.
+
+ info.os (str): The os the binary was compiled for.
+
+ info.baddr (int): The virtual base address of the binary.
+
+ info.arch_string (str): A string given by r2 iI that helps identify the
+ architecture the binary was compiled for.
+
+ info.wordsize (int): The natual width of an int on the architecture the
+ binary was compiled for.
+
+ info.endianness (str): The byte order of an int on the architecture the
+ binary was compiled for.
+
+ security (->bool|str): A psuedo-namespace to access security info about the
+ binary. Printing elf.security will pretty-print this info in a tabulated
+ form.
+
+ security.stripped (bool): True if the binary was stripped of debugging
+ information, symbols, and strings.
+
+ security.pic (bool): True if the binary's code is position independent.
+
+ security.relro (str): The level of "Relocation Read-Only" that the binary
+ was compiled with. Pertains to if the Global Offset Table is read-only.
+ This is often "partial" or "full".
+
+ security.relocs (bool): True if the binary uses dynamic runtime relocation.
+
+ security.canary (bool): True if the binary uses stack canaries.
+
+ security.nx (bool): True if the binary does not have stack execution
+ privileges.
+
+ security.rpath (str): Runtime library lookup path. If there isn't one, this
+ will say "NONE".
+
+ arch (Arch): On Construction, an ELF will automatically try to figure out if
+ it was compiled for one of sploit's predefined Arch's. If so, it will set it
+ here. Otherwise, this is None.
+ """
+
def __init__(self, path):
+ """
+ Construct an ELF.
+
+ path (str): The filepath to the ELF binary file.
+ """
self.path = path
self.sym = r2.get_elf_symbols(self.path)
try:
@@ -18,6 +104,7 @@ class ELF:
self.arch = lookup_arch(self.info.arch_string, self.info.wordsize, self.info.endianness)
def __repr__(self):
+ """Pretty-print a summary of the ELF."""
s = 'ELF: '
s += self.path
s += f'\n{len(self.sym)} symbols @ {hex(self.sym)}'
@@ -36,6 +123,7 @@ class ELF:
return s
class __LIBS__(dict):
+ # Fancy magic dict of {filename:ELF} which will lazy load the ELF
def __init__(self, libs):
super().__init__({lib.name:lib.path for lib in libs.values() if lib.path})
def __getitem__(self, lib):
@@ -49,6 +137,7 @@ class ELF:
return s.strip()
class __LOCALS__:
+ # Fancy magic class that provides a psuedo-namespace to lookup locals for functions
def __init__(self, elf):
self.elf = elf
def __getattr__(self, sym):
@@ -89,10 +178,28 @@ class ELF:
}
def retaddr(self, caller, callee):
+ """
+ Returns a list of addresses where a function returns into another
+ function at.
+
+ caller (int): Address of the calling function to be returned into.
+
+ callee (int): Address of the function that was called and will return.
+ """
return [c.ret_addr for c in r2.get_call_returns(self.path, caller, callee)]
def gadgets(self, *regexes, cont=False):
+ """
+ Returns a list of gadgets that match the given regex list.
+
+ *regexes (str): All positional arguments are treated as regex strings
+ for the gadget search.
+
+ cont (bool): If true, this function will return all of the assembly past
+ the found gadget up to the next return point.
+ """
return r2.rop_gadgets(self.path, *regexes, cont=cont)
def gadget(self, *regexes):
+ """Returns the first gadget found that matches the given regex list."""
return r2.rop_gadget(self.path, *regexes)