Age | Commit message (Collapse) | Author | Files | Lines |
|
This is a package to contain the related Payload and ROP modules, as
well as utility classes. Payload is moved into the new package.
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
Reviewed-by: Malfurious <m@lfurio.us>
|
|
The built in int's to_bytes and from_bytes functions have some weird
behavior with the signed parameter. Rather than expecting the user to
properly give btoi/itob the right signed value to pass through to
to_bytes/from_btyes, it makes more sense to just always convert an
unsigned number. Using the new int conversions, this can always be
unambiguous with respect to the width of the int.
There may also be situations where a user would like to truncate/sign
extend an int to a certain length other than the configured architecture
wordsize or convert to a different endianness. These are now
parameterized. There is no need to parameterize the width for btoi
because you will now always get an unsigned int back (and because of
python, the width is ambiguous). The user can convert it to whatever
width/sign they want after the fact with the new int conversion methods.
This also means that payload's int() does not need to take a signed
argument either. Whatever sign of int you give it, when it calls itob,
it will get the correct bytearray at the width of the configured
architecture's wordsize.
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
Reviewed-by: Malfurious <m@lfurio.us>
|
|
This effort was triggered by three immediate wants of the module:
An improved data container interface to support things like key
iteration and better key management. This is primarily wanted by
the ROP module (which is still in development).
The introduction of package documentation across the project. This
module is now fully documented.
To fix a bug in the Symtbl constructor, which would not allow a
caller to supply "self" as an initial symbol name, even though it is
legal in every other context. This problem was caused by the
constructor's bound instance parameter sharing this name.
This patch addresses all of these concerns, and also introduces some
fringe / QoL improvements that were discovered during the API refactor.
Element access may now be done via subscripting, as well as the previous
(and still generally perferred) .attribute notation. The syntax for
storing subtables within a parent Symtbl is now greatly streamlined due
to some implementation-level changes to the class. You may now directly
assign just a Symtbl object or a normal int, and you don't have to fuss
with tuples anymore. The subtable's base is taken as its offset in the
parent, and the new operator replacement for the .map() method may be
used to define a desired value for the parent.
This detail is actually a breaking change compared to the previous
version. While not technically a bug, it is unintuitive that the
previous version would not remove subtables when their offset was
changed by a simple assignment - the table would just move. This patch
make it such that any symbol assignment to a regular int will replace an
old mounted subtable if one exists.
There are now no normal instance methods on the Symtbl type (only dunder
method overrides). This is to free up the available symbol namespace as
much as possible. The previous methods map(), adjust(), and rebase()
are now implemented as operators which, in every case, yield a new
derivative object, rather than mutating the original. All operators are
listed here:
@ remap to absolute address
+ remap to relative address
- remap to negated relative address
>> adjust all symbol offsets upward
<< adjust all symbol offsets downward
% rebase all symbol offsets around an absolute zero point
Additionally, Symtbl objects will convert to an integer via int(),
hex(), oct(), or bin(), yielding the base value.
The addition of these operators presents another breaking change to the
previous version. Previously, symbol adjustments or rebases affected
the tracked offsets and caused symbols to shift around in linked tables
as well. Since these operators now preserve the state of their source
object, this is no longer the case. The amount of shift due to
adjustment or rebasing is localized in a specific Symtbl instance (and
is affected the the use of the related operators), however this value is
inherited by derivatives of that object.
There is a third breaking change caused by the use of operators as well.
Previously, the map() function allowed the caller to specify that the
given absolute address is not that of the table base, but of some offset
in the table, from which the new base is calculated. However, the
remapping operators take only a single numeric value as their right hand
side operand, which is the absolute or relative address. The new
intended way of accomplishing this (which is _nearly_ equivalent) is
through the combined use of the rebase and remap operations:
# The address of the puts() function in a libc tbl is leaked
sym = sym % sym.puts @ leak
aka: adjust offsets such that the known point is at the base, then move
that base to the known location. The way in which this is different to
what you would end up with before is that previously, following a
map(abs, off) the base of the table would be accurately valued
according to the known information. Now, the 'base' is considered to be
the leaked value, but internal offsets are shifted such that they still
resolve correctly.
Finally, a few new pieces of functionality are added to build out the
container API:
- symbol key deletion
- iteration over symbol:offset pairs
- can now check for symbol existence with the "in" keyword
- len(symtbl) returns the number of symbols defined
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
I assume that the preferred style is to leave one major class each to a
file. In this case, synchronize the names of the Symtbl class and its
containing module. Per PEP8, the module is lowercase, and the class
remains Pascal case.
If other memory-oriented utilities are introduced in the future, we may
wish to move them, as well as Symtbl, back into a subpackage named
'mem'.
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
Lift restriction (name mangling) to Payload helper functions, as their
use will be useful in Payload subclasses.
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
This is just a slight code reduction, but will make any future code
simpler as well. Explicit comparision to None is more correct as well;
centralizing this for reuse better justifies the wordier if statement.
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
Given the current design of Symtbl, creating subclasses of it gets more
tedious the further one goes down a potential class hierarchy. As I am
planning to introduce new features in the future that explicitly extend
Payload, make this change now to minimize the impact.
Additionally, switching Payload's relationship with Symtbl from "is-a"
to "has-a" makes it more consistent with rev.ELF, the other major user
of Symtbl. (And in both cases, the member is named 'sym')
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
Often times, users of the Payload module wish to push a list of integers
to a payload buffer. Currently, the best (and intended) way to do this
is to make several calls to .int(). However, as part of the ROP effort,
I am planning to add function 'gadget(addr, *params)' to the Payload
class. Per the design of this function, calling it with an expanded
list of values would be equivalent to passing each to .int()
individually. In order to discourage the use of .gadget(), as a
shortcut to a series of .int()s, .int(), and most other insertion
functions, now accept arbitrarily many value arguments.
Functions that support additional options (such as .int()'s 'signed'
parameter) will apply such options to all values. If a symbol name is
defined, it will reference the beginning of the block of values.
Keep in mind, this will also allow inserting zero values. For example,
obj.bin(sym='end') will tag the end of the payload without extending its
content. This use-case is not intended to be particularly useful, but
exists as a consequence of the change.
Payload.rep() and the pad functions are not affected by this commit, as
I don't think changing their semantics in this way makes sense.
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
The design/implementation of class Payload is updated for better
compatibility with Symtbl, and to address some usability issues that
have come up so far:
No more automatically fixed-up stack alignment by default: In fact,
alignment as a concept is fully removed from the tool, in preparation
for another upcoming ROP-centric addon to Payload. Therefore, insertion
of return addresses (via .ret()) are now equivalent to any other integer
value.
No instance size value: Each call to .pad() uses an independent size
passed as a parameter, but functions in the same manor as before.
Padding can also now be inserted at the beginning of the payload:
.pad_front() prepends the necessary amount of data, and updates the
tracked offsets of values that were already inserted to the payload.
Payload now directly extends Symtbl: Instead of possessing a Symtbl
member, payload objects can directly be treated as symbol tables for
things like mounting them as subtables, or mapping them to access
absolute addresses.
New call syntax to access binary data: As a shorthand, users may now
use the call syntax to get the bytes string built by the tool. If an
argument is passed, it is another byte string containing illegal bytes
that we check the built payload for. Unfortunately, the __str__ magic
func doesn't like returning bytes string; plus, that overload is already
in use for formatting the symbol table content (worth not hiding).
New semantic insertion functions: .bin(), .str() [C-style strings],
.int(), .ret(), and more. Some of these functions are direct synonyms,
however their use can provide more clarity in Sploit scripts.
Smarter default element symbol names: Instead of just using '_' as a
placeholder if no symbol name is ever given, we now uniquely name each
inserted element according to the API function that was used, then slap
on an incrementing number. An explicit name still bypasses this scheme.
Insertion functions can now be chained together: Functions previously
returned the offset/address of the inserted value. However, this
feature was seldom used, and there is now the possibility of
.pad_front() invalidating previously-returned offsets. Instead,
functional-style chaining is enabled to reduce boilerplate, and help
with quick oneliners.
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
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>
|