diff options
author | Malfurious <m@lfurio.us> | 2021-09-04 21:04:00 -0400 |
---|---|---|
committer | Malfurious <m@lfurio.us> | 2021-09-07 23:02:19 -0400 |
commit | 66acac774b52856a9d15bd8a12e6a55a60209667 (patch) | |
tree | 69aeb2c6f0e17ddd2f74444c0e3117a8ef12250b /tools/sploit | |
parent | 94829fc6a5ef9d8e36af8f65a165dd733d5a0f50 (diff) | |
download | lib-des-gnux-66acac774b52856a9d15bd8a12e6a55a60209667.tar.gz lib-des-gnux-66acac774b52856a9d15bd8a12e6a55a60209667.zip |
sploit: Add payload builder module
class Payload is a tool for constructing stack-smash payloads and ROP
chains. Its design is intended to abstract away some of the more
tedious details of crafting a payload.
Payload utilizes mem.Symtbl internally to optionally manage a collection
of named offsets into its own buffer (these are usually in reference to
entities appended to the payload via its main API). Alternatively, the
API calls to append any entity will return the address of that entity as
well.
Returned (and looked-up) addresses are relative to the beginning of the
payload by default. However, when the payload is constructed with a
known base address value, these become absolute. This is useful for
reusing addresses later in the payload body.
class Placeholder is designed to be functionally compatible with
bytearrays and bytestrings. When constructed, they take the value of
'zero', according to the current arch config. This facility enables
some API's to detect whether a dummy value was passed as a required
argument when said argument _may_ be unnecessary in niche situations.
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
Diffstat (limited to 'tools/sploit')
-rw-r--r-- | tools/sploit/sploit/__init__.py | 4 | ||||
-rw-r--r-- | tools/sploit/sploit/payload.py | 64 |
2 files changed, 66 insertions, 2 deletions
diff --git a/tools/sploit/sploit/__init__.py b/tools/sploit/sploit/__init__.py index 5082cfa..7180910 100644 --- a/tools/sploit/sploit/__init__.py +++ b/tools/sploit/sploit/__init__.py @@ -1,2 +1,2 @@ -__all__ = ["log","comm","until","arch","mem"] -from sploit import log, comm, until, arch, mem +__all__ = ["log","comm","until","arch","mem","payload"] +from sploit import log, comm, until, arch, mem, payload diff --git a/tools/sploit/sploit/payload.py b/tools/sploit/sploit/payload.py new file mode 100644 index 0000000..49e0c04 --- /dev/null +++ b/tools/sploit/sploit/payload.py @@ -0,0 +1,64 @@ +from sploit.arch import arch, itob +from sploit.mem import Symtbl + +# Users can set this to the (absolute) address of a 'ret' ROP gadget. Some +# features may require it. +RETGADGET : int = None + +class Placeholder(bytearray): + def __init__(self, text='_unnamed_'): + self += bytearray(itob(0)) + self.text = text + +class Payload: + def __init__(self, size=0, base=0, **kwargs): + self.payload = b'' + self.size = size + self.alignstart = None + self.tab = Symtbl(base=base, **kwargs) + + def __len__(self): + return len(self.payload) + + def __getattr__(self, sym): + return getattr(self.tab, sym) + + def data(self, x, sym='_'): + off = len(self) + self.payload += x + setattr(self.tab, sym, off) + return getattr(self.tab, sym) + + def value(self, x, sym='_', signed=False): + return self.data(itob(x, signed=signed), sym=sym) + + def ret(self, x, sym='_'): + self.align() + return self.value(x, sym=sym) + + def stuff(self, x, size, sym='_', *, explain=''): + if size >= 0: + if (size := size / len(x)) == int(size): + if size == 0 or not isinstance(x, Placeholder): + return self.data(x * int(size), sym=sym) + + raise Exception(explain+"Can not stuff payload: " + f"Placeholder for {x.text} detected") + raise Exception(explain+"Can not stuff payload: " + "Element does not divide the space evenly") + raise Exception(explain+"Can not stuff payload: " + "Available space is negative") + + def pad(self, x=None, sym='_'): + size = self.size - len(self) + return self.stuff((x or arch.nopcode), size, sym=sym, + explain='Error padding payload: ') + + def align(self, x=None, sym='_'): + if self.alignstart is None: + self.alignstart = len(self) + + retgad = (itob(RETGADGET) if RETGADGET else Placeholder('ret gadget')) + size = (self.alignstart - len(self)) % arch.alignment + return self.stuff((x or retgad), size, sym=sym, + explain='Error aligning payload: ') |