diff options
-rw-r--r-- | sploit/payload/payload.py | 45 | ||||
-rw-r--r-- | sploit/payload/payload_entry.py | 45 |
2 files changed, 57 insertions, 33 deletions
diff --git a/sploit/payload/payload.py b/sploit/payload/payload.py index b88e323..2a9521f 100644 --- a/sploit/payload/payload.py +++ b/sploit/payload/payload.py @@ -144,7 +144,9 @@ class Payload(IndexTbl): def __len__(self): """Return the size of the payload content in bytes.""" - return len(bytes(self)) + memo = {} + x = [ self.__lenof(i, memo) for i in range(len(self.__entries__)) ] + return sum(x) def __getindex__(self, index): """Return payload index value or address.""" @@ -167,7 +169,7 @@ class Payload(IndexTbl): # Payload helpers def __valueof(self, index, memo): - """Return a tuple: (addr of value, literal value) for index.""" + """Return a tuple (addr of value, literal value) for index.""" value = self.__entries__[index] addr = self.__addrof(index, memo) if isinstance(value, IndexEntry): @@ -178,21 +180,27 @@ class Payload(IndexTbl): def __addrof(self, index, memo): """Return address (base + offset) for index.""" index = self.__entries__.key2idx(index) - sizes = [ len(self.__bytesof(i, memo)) for i in range(index) ] - return self.base + sum(sizes) - - def __bytesof(self, index, memo): - """Return byte output for index.""" try: return memo[index] except KeyError: - _, value = self.__valueof(index, memo) - if isinstance(value, PayloadEntry): - data = value.payload_bytes(self) - else: - data = bytes(value) - memo[index] = data - return data + sizes = [ self.__lenof(i, memo) for i in range(index) ] + addr = self.base + sum(sizes) + memo[index] = addr + return addr + + def __lenof(self, index, memo): + """Return element length for index.""" + _, value = self.__valueof(index, memo) + if isinstance(value, PayloadEntry): + return value.payload_len(self) + return len(value) + + def __bytesof(self, index, memo): + """Return byte output for index.""" + _, value = self.__valueof(index, memo) + if isinstance(value, PayloadEntry): + return value.payload_bytes(self) + return bytes(value) def __prep_insertion(self, value, addr): """Initialize or type coerce input value for payload insert.""" @@ -206,6 +214,11 @@ class Payload(IndexTbl): elif type(value) is int: value = itob(value) - # Confirm value has a functional conversion to bytes - bytes(value) + try: + # Confirm value supports our required operations + len(value) + bytes(value) + except TypeError as ex: + raise TypeError(f"Payload: Bad type {type(value)} given") from ex + return value diff --git a/sploit/payload/payload_entry.py b/sploit/payload/payload_entry.py index 7088f83..4dca83d 100644 --- a/sploit/payload/payload_entry.py +++ b/sploit/payload/payload_entry.py @@ -20,15 +20,23 @@ class PayloadEntry(IndexEntry): """ pass + def payload_len(self, payload): + """ + Called to compute size of this entry. + + Implement this method to calculate the length of this dynamic payload + entry. self.base is set to the current entry address or offset. + """ + raise NotImplementedError + def payload_bytes(self, payload): """ Called to generate bytes for this entry. - Override this method to generate and return the binary output for this - dynamic payload entry. self.base is set to the current entry address - or offset. + Implement this method to generate the binary output for this dynamic + payload entry. self.base is set to the current entry address or offset. """ - return b"" + raise NotImplementedError # Concrete payload entry definitions @@ -43,6 +51,9 @@ class pointer(PayloadEntry): self.target = self.base self.target -= self.base + def payload_len(self, payload): + return arch.wordsize + def payload_bytes(self, payload): return itob(self.target + self.base) @@ -53,7 +64,11 @@ class padlen(PayloadEntry): self.size = size self.data = data - def _gen_padding(self, size): + def payload_len(self, payload): + return self.size - (self.base - payload.base) + + def payload_bytes(self, payload): + size = self.payload_len(payload) data = self.data or arch.nopcode if size < 0: raise ValueError("padding: Available space is negative") @@ -61,20 +76,17 @@ class padlen(PayloadEntry): raise ValueError("padding: Element does not divide the space evenly") return data * int(size) - def payload_bytes(self, payload): - return self._gen_padding(self.size - (self.base - payload.base)) - class padabs(padlen): """Generate padding to reach a target absolute address.""" - def payload_bytes(self, payload): - return self._gen_padding(self.size - self.base) + def payload_len(self, payload): + return self.size - self.base class padrel(padlen): """Generate a fixed length of padding (aka: length relative to self).""" - def payload_bytes(self, payload): - return self._gen_padding(self.size) + def payload_len(self, payload): + return self.size class padalign(padlen): """Generate padding to reach next aligned address.""" @@ -83,9 +95,9 @@ class padalign(padlen): self.size = size self.data = data - def payload_bytes(self, payload): + def payload_len(self, payload): size = self.size or arch.alignment - return self._gen_padding(-self.base % size) + return -self.base % size class placeholder(padlen): """Generate fixed length of magic bytes, one word length by default.""" @@ -94,6 +106,5 @@ class placeholder(padlen): self.size = size self.data = _PLACEHOLDER_MAGIC - def payload_bytes(self, payload): - size = self.size or arch.wordsize - return self._gen_padding(size) + def payload_len(self, payload): + return self.size or arch.wordsize |