Age | Commit message (Collapse) | Author | Files | Lines |
|
|
|
- Payload improvements
- Format string attack
- Ret2dlresolve attack
|
|
This updates the ROP class to work with the new Payload changes. Its
behavior should be largely the same, and I've taken the opportunity to
touch up documentation.
The main change here is that we no longer extend the Payload class.
Instead, each function constructs and returns a Payload representation
of the generated ROP chain. These returned objects can easily be lumped
into the Payload being built by a user script, or interrogated to help
troubleshoot their use.
Signed-off-by: Malfurious <m@lfurio.us>
|
|
This leverages some code reuse and helps these types play nicely with
the new Symtbl updates.
Signed-off-by: Malfurious <m@lfurio.us>
|
|
Payload is now an index table, wherein each index is a byte string (or
compatible type). The retrieval of indices will return a corresponding
offset or address of the indexed data (which is sensitive to the payload
base). There is no longer a Symtbl member.
Due to this new design, the class no longer keeps a running payload
buffer that is appended to every time the payload is updated. When the
user wants to get the full data, this buffer is constructed from the
Lict elements backing the payload. This allows individual elements to
be modified or removed easily after they are inserted.
The use of a Lict allows data elements to be referred to by either their
positional array index, or the key specified when first creating that
element (done using the IndexTbl interface).
Payload objects may now be directly nested inside eachother, as opposed
to simply taking a payload's bytes and inserting those. This allows
payloads to be used in a way resembling C structures.
The type-specific insertion functions have been removed and we instead
now lean on the __setindex__ interface inherited from IndexTbl to
directly assign values and append them to the payload. In this case,
values are taken as-is from the assignment if they are bytes-like, and
automatically converted in some cases.
Payload's __call__ overload is now used to perform the quick, chainable,
and inline value insertion that was lost by the removal of the
type-specific functions. "Calling" a payload with zero arguments will
still provide the old behavior of returning the payload bytes, however.
The semi-advanced features such as padding, alignment, and inserting
placeholder bytes have been removed from the main payload interface and
are now provided as compatible types that can be directly inserted into
Payload via the means described above. In most cases, these are now
implemented to dynamically react to changes in the Payload content. For
example, a "padlen" element, which is constructed with a fixed target
length parameter, will grow or shrink in length if the data preceding it
changes.
Automatic "badbytes" detection is removed, simply due to API conflict.
In my experience, this feature was little-used and can easily be done
manually by scripts if desired. I don't plan to reintroduce this
feature.
pad_front functionality is also removed by this patch, since at the
moment it doesn't fit into the new design very well. We may attempt to
reimplement it as a PayloadEntry down the road. However, this feature
has also only seen rare use in my experience.
Signed-off-by: Malfurious <m@lfurio.us>
|
|
Lict is a fairly fully-featured data structure which stores elements in
a well ordered list, while offering opt-in support for per-element
dictionary keys. This type is intended to be the new back-end storage
for Payload data, but may have other use-cases as well.
An OrderedDict is not a suitable replacement, as they do not permit
unkeyed elements.
Signed-off-by: Malfurious <m@lfurio.us>
|
|
There are some useful concepts expressed in the Symtbl class that can
provide good value if applied elsewhere as well. In this particular
case, I want to address the somewhat awkward relationship between Symtbl
and the Payload class by providing an abstract base for both of them. I
will go into more details in an upcoming commit for Payload.
This patch shouldn't change any behavior for Symtbl barring perhaps its
new preference of the new IndexEntry type described below. Some
characteristics of Symtbl are refactored into two new interface types:
IndexEntry provides "base" and implements logic supporting the use of
instance objects as integers. The intent is to extend from this class
when creating special types to be used in IndexTbls, Symtbls, etc.
IndexTbl (extends IndexEntry) provides a unified system for attribute /
element access, and acts as an abstract container where storage and
lookup semantics are up to the specific implementation.
Symtbl (extends IndexTbl) is now better described as an Index table,
where indices represent numeric addresses. The nominal data type is
int, however IndexEntries (which are int-like) may be nested to record
the addresses of ROP gadgets, sub-symtbls, and perhaps more in the
future.
Signed-off-by: Malfurious <m@lfurio.us>
|
|
Signed-off-by: Malfurious <m@lfurio.us>
|
|
This completes the overarching package reorganization changes. The
contents of the top-level "sploit" package's direct children modules are
exported via the package. Explicit imports for sploit's subpackages are
not necessary.
Other package __init__.py files are using relative imports. However,
doing so here causes the hatchling build process to fail. Fortunately,
since this is the top level, absolute paths aren't too long.
The last few modules left in this package have been kept back since they
lack any specific niche, are considered "universally relevant", or are
typically imported so frequently that it makes sense to provide them to
scripts automatically.
Signed-off-by: Malfurious <m@lfurio.us>
|
|
The CLI logic is moved to sploit/__main__.py. This file is now the
target of:
- python -m sploit
- sploit.py (via import)
- sploit (installed executable - via pyproject.toml)
A module guard (`if __name__ == "__main__"`) is added to allow the
application to run when this file is invoked directly. And the
entrypoint symlink is no longer necessary.
Signed-off-by: Malfurious <m@lfurio.us>
|
|
This is done to help clean the top-level "sploit" package. Furthermore,
there is some planned future work to refactor comm into multiple
modules, so this lays some groundwork for that.
Signed-off-by: Malfurious <m@lfurio.us>
|
|
Signed-off-by: Malfurious <m@lfurio.us>
|
|
We would like to move additional modules under the namespace of "util"
to clean up the top-level "sploit" package. To start, the functions
from the previous util module are moved. Given the package is named
"util" the module is renamed to "cmd" to somewhat match the theme of the
contained functions.
Per the previous commits, these functions are now exposed via the util
package as well.
Signed-off-by: Malfurious <m@lfurio.us>
|
|
This follows in the package contents export change. Additionally, the
builder package is renamed to "payload".
"payload" is actually the preferred name of this package. It was
previously renamed due to the absurdity of importing
"sploit.payload.payload.Payload()", and the fact that additional modules
were being bundled together so a more broad name _seemed_ desirable.
Signed-off-by: Malfurious <m@lfurio.us>
|
|
This is the start of an overarching change meant to simplify sploit
library imports. In general, all packages (directories) are intended to
export all the classes, methods, and variables of their contained
modules. This way users need only import the package, which leads to
less verbose import statements (and usually fewer import statements).
We would still like to gate objects behind their respective packages,
rather than providing the whole world with `from sploit import *` so
that users can still have some amount of control over what is brought
into their global namespace.
Beware: For code internal to sploit, full module imports should probably
continue to be used. Otherwise, there is a possibility for circular
imports if two modules from two packages cross import.
Signed-off-by: Malfurious <m@lfurio.us>
|
|
This file doesn't seem to be serving any purpose, and removing it
doesn't break any of the supported ways to run sploit.
sploit.py, python -m sploit, interpreter, installed, uninstalled, in or
out of the repo, are all fine.
Signed-off-by: Malfurious <m@lfurio.us>
|
|
|
|
We should strip the newline from the data after checking if we got an
empty string returned.
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
Add the ability to select which location to create FIFOs when running in
pipes mode, by passing the directory name to sploit where a target
executable would usually go. This has been an API feature from the start,
but not exposed via the sploit runner command-line interface.
There are a couple new use-cases where this is very convenient, including
scriptifying sploit in pipes mode (testing, for example) and when running
sploit under Docker. If pipes are placed in the working directory, all
project files can be shared with a single bind mount.
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
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>
|
|
Originally I was deciding whether to get a reloc based on the type. I'm
not sure what SET_64 vs ADD_64 means, but the SET* types seemed to be
the only symbols we care about. After running into a binary where a
SET* symbol didn't have a name (and crashed sploit), I have decided to
filter on that instead.
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
Grabbing the json and returning that dict directly avoids all of the
processing we were doing before. I also added in a small, temporary
band-aid for PE files until we add actual support for them. The 'relro'
key doesn't exist on PE files, so just default it to '' in ELF.
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
This addresses a couple issues with get_elf_symbols().
First of all, we can greatly simplify our processing of the r2 output by
getting back json instead of trying to do string processing on their
pretty-printed tables. This resolves a number of issues we were running
into and also makes the code way more maintainable.
Second, we have reevaluated what we actually want to get out of r2. We
now grab section offsets, all FUNC, OBJ, and NOTYPE symbols, and all
strings. The strings and section offsets no longer try to escape
special characters and sometimes aren't accessible through normal object
attributes, but now that we have dictionary subscripting, this isn't an
issue.
Lastly, a few subsets of the symbols are separated into their own tables
and added to the main table as subtables. Sections are located at
sym.sect and offset at 0. Imported symbols are located at sym.imp and are
offset at sect['.plt']. Relocations are located at sym.rel and are offset at
sect['.got']. Strings are located at sym.str and are offset at
sect['.rodata'].
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
When iterating over a symtbl, the returned tuples should be sorted by
offset.
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
Adds a ROP-enabled payload builder under the builder namespace. Much of
the behavior is parameterized by the active arch, so several new columns
are added to the Arch class.
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
This dataclass is intended to be used directly with the new ROP builder
class. GadHints allow users to teach the library about gadgets it can
not find on its own and how to use them correctly.
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
To determine the address of the end of a payload, based on its Symtbl
data. I believe it makes the most sense to make this a part of the
Payload API, since Symtbl lacks a concept of element size.
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
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>
|
|
ROP gadgets returned through search from the r2 API will now always
contain a file-relative offset, even if they come from a non-pic binary
using a fixed baddr.
However, gadgets returned through the ELF API will be mapped according
to the ELF's Symtbl. This ensures the correct offset is returned
following a library leak, and allows the user to always safely insert an
ELF-returned gadget into that ELF's Symtbl without issue.
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
This fixes a bug with Symtbl's __getitem__. An object that is
convertable to int should also cause __getitem__ to behave as though an
int was given, and translate the object as a foreign offset.
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
On ELF construction, call r2.get_bin_info() and keep the results under
the psuedo-namespaces .info and .security. Also add a pretty-print to
these in a tabulated form. Also rewrite the ELF pretty-print to just
summarize and not print out the entirety of .sym. Lastly, fixed a small
bug where ELF could crash on construction if ldd fails (loading a
non-native ELF, for instance).
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
Code reuse since we were using r2 iI in get_elf_symbols to get the
baddr. This can cause get_bin_info to be called (and log that it's
being called) multiple times, so I'm also adding the @cache annotation.
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
Call r2's iI command and return a subset of the fields that we care
about.
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
You can now lookup a predefined Arch based on a tuple of arch_string
(returned by r2 iI), wordsize, and endianness.
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
Also added a DEFAULT_ARCH constant.
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
Also check type when setting arch.
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
Sets the value of rop.len = 10 in r2, to give the search function more
data to sift through. This is a doubling from the default value (5).
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
Development on the rop chain builder has produced this upgrade to our
gadget search facility. The primary advantages in this version are
increased flexibility and runtime performance.
It is now easier to find specific 'stray' instructions (not immediately
followed by a ret) since we search from every position in the data
returned by r2. If you _do_ want a ret, just specify it in your input
regexes. For this reason, a dedicated function for locating a simple
'ret' gadget is no longer present - elf.gadget("ret") is the equivalent.
A major change in this version is that we now obtain and operate on r2's
JSON representation of the gadget data. We now only reach out to r2
once to get all information for a binary (which is cached) and the
actual 'search' is implemented in Python. This provides a significant
performance speedup in cases where we need many gadgets from one binary,
as r2 doesn't need to inspect the entire file each time. Additional
caching is done on specific search results, so that 100% redundant
searches are returned immediately. Access to the raw JSON data is made
available through a new function rop_json(), but is not exposed in the
ELF interface, since it seems like a niche need.
Search results are returned via Gadget objects (or a list thereof),
which contain regular expression Match objects for each assembly
instruction found in the gadget. This allows the caller to retrieve the
values contained in regular expression capture groups if present.
Also, anecdotally, the search functionality in r2 has seemed to return
false negatives for some queries in the past, whereas I haven't noticed
similar cases with this implementation yet.
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
This new class is intended to be used to return data from gadget
searches, and is able to be nested within object Symtbls.
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
Can now use Symtbl subscript syntax to obtain the mapped address of a
foreign offset (not a defined symbol) without having to modify the
object or add a new symbol entry.
Assuming a base value of 10, tbl[15] will return 25, for example.
We now assert that the defined table keys are strings, to prevent the
creation of entries that are now un-readable by this patch. However,
this always should have been the case.
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
Sometimes we might be working on an object that can be treated as an
int, but python won't automatically type coerce. For example, grabbing a
nested symtbl and passing it in here expecting it to resolve to a type
conversion of its base offset.
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
Previously, due to precedence rules, the text produced for any library
whose corresponding ELF object has already been initialized would simply
be `str(lib.path)`, instead of the intended formatted string.
Also fixes a typo.
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
QoL change - Don't print the headings if the table is empty. Just
report "0 symbols" and the base address.
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|
|
When printing a human readable Symtbl, show all nested objects within
[brackets], not just Symtbl itself. Primarily useful since more types
are being developed with the intent of being stored in a Symtbl.
Signed-off-by: Malfurious <m@lfurio.us>
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
|