summaryrefslogtreecommitdiffstats
AgeCommit message (Collapse)AuthorFilesLines
2023-02-23Add the version to the splash screendusoleil1-1/+2
Print the current version (sourced from git describe) when sploit starts up. Signed-off-by: dusoleil <howcansocksbereal@gmail.com> Reviewed-by: Malfurious <m@lfurio.us>
2023-02-23Dynamically source version in toml from gitdusoleil4-5/+54
Instead of hard-coding the version into the pyproject.toml, we can dynamically source it at build time. Ideally, we want to use git describe as a single authority source on the version. The version is stored in sploit.__version__ and can be consumed during sploit runtime or during a build/package to populate the project's core metadata version in the toml file. hatchling provides a tool.hatch.version plugin that can read out the variable during a build/package. Because this variable is populated from a git command, if the source tree isn't in a git repo, it will fail. In this case, sploit will report a PEP 440 compliant fake version "0+unknown.version" to let the user know. Because a packaged distribution doesn't exist in a git repo, we want to bake in the version at build time into the package. hatchling provides a plugin to help with this, but it had some technical limitations that didn't quite work for our use case. Instead, I added a custom build hook which will take the version sourced from the package (and by proxy the git command), and overwrite the __init__.py with a hard-coded version in the __version__ variable. This means that built/packaged distributions of this project will have a fixed version hard-coded in rather than dynamically sourcing from git. The build hook operates just before the build executes. It seems that most build/packager front-ends (e.g. build, pip) will just run it in the current source tree rather than making a temp copy. This means that when we modify the __init__.py, it is modifying our git tree. Ideally, we want this to be restored at the end of the build. The build hook interface allows us to write a hook that happens after the build, but it won't run in the case of a crash or failed build. Instead, I added a custom solution to this using a member variable deconstructor. If the build ends in any way, the original contents of __init__.py are written back out. Signed-off-by: dusoleil <howcansocksbereal@gmail.com> Reviewed-by: Malfurious <m@lfurio.us>
2023-02-23Update project's build and package to the newer standarddusoleil3-7/+23
Currently, the standard way to build and package a Python project is through a pyproject.toml file rather than the old setup.py. This is also build back-end agnostic and we can choose to use something other than setuptools. After looking through a few options, I've decided to use hatchling. Signed-off-by: dusoleil <howcansocksbereal@gmail.com> Reviewed-by: Malfurious <m@lfurio.us>
2023-02-18comm: Localize stdin nonblock to interact's readalldusoleil1-4/+6
In interact(), we set stdin to be nonblocking for the duration of the function. As an unexpected side-effect, this was setting stdout to be nonblocking as well. This has caused at least one crash in the past. Localizing the nonblock to just when we're reading from stdin should solve this. Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2023-02-18Use buffered read throughout Commdusoleil1-1/+1
We had originally decided to use the os.read() function instead of the actual buffered file object's read function. This was due to the blocking behavior or os.read() being closer to POSIX read than the other function. As it turns out, os.read() is an unbuffered read. Every other read call in this interface is buffered. This causes some undefined behavior in certain cases and leads to some really confusing bugs. After some discussion, we've decided that, in this application's domain, the blocking behavior of the buffered file object's read is actually often more useful anyways. Changing this call will deal with both issues. Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2023-02-18Read once at the beginning of interact mode.dusoleil1-0/+1
This behavior was accidentally removed in dcba5f2 interact mode works by polling for IO events, but it will miss any unread data already in the buffer when it is first entered. We can ensure this gets caught by just doing a read once at the beginning. Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2023-02-18comm: Strip \n character from readline()Malfurious1-1/+4
Line-oriented reads now strip the newline from the end of their returned string. Additionally, readall() strips the newline, but only from the string that gets logged to the user's terminal (goodbye to all the "\n" printed at the end of each line). Of course, these functions are called by other parts of the read API and have downstream effects. Consideration was given to the entire API with these rules in mind: - Raw reads (or non-line-oriented reads) will not filter ANY of their read content. They are logged to the screen as one "line" of log text with \n characters shown in-place (not actually resetting the terminal cursor). If reading binary, these bytes dont actually mean line termination anyway. functions: read, readall(_nonblock) *, readuntil - Line-oriented reads will strip the terminating \n, log the single line to the screen, and return it. functions: readline, readlineuntil ** * readall(_nonblock) functions turn out to be a special case. They will operate as raw reads, returning a blob of content. However, we generally want to run them on line-oriented input, so they log according to the line-oriented rules. ** Although content returned from readlineuntil will have \n's stripped, the lines are returned in an array, so we can still distinguish them. Signed-off-by: Malfurious <m@lfurio.us> Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2023-02-18comm: Add default argument for writeline()Malfurious1-1/+1
The writeline function will now default to send an empty line when called without an argument. I don't believe any such default makes sense for the plain write function, as writing nothing should have no effect. Signed-off-by: Malfurious <m@lfurio.us> Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2023-02-18comm: Enable logonread during interact()Malfurious1-0/+3
This is normally not an issue, since logonread defaults to True. However, if the user disables this setting, interact() becomes a lot less useful. logonread is now forced on during io.interact(), but respected through the rest of the API. Signed-off-by: Malfurious <m@lfurio.us> Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2023-02-18comm: Squelch BrokenPipeError during shutdown()Malfurious1-1/+4
Failure to close target stdout is not interesting. Furthermore, if sploit ever gets into this situation, the user script has likely already raised a more useful error/backtrace. Handling this exception typically results in a duplicate error. Signed-off-by: Malfurious <m@lfurio.us> Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2023-02-18Always shutdown comms after executing scriptMalfurious1-2/+3
Moving this io cleanup code to the finally block allows it to also run when recovering from an exception. This prevents cases where the target may hang if the user sploit script crashes, and avoids requiring the user to press an additonal CTRL-C to move on. Signed-off-by: Malfurious <m@lfurio.us> Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2023-02-12Version 0.1v0.1dusoleil1-1/+1
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2023-02-12Add .gitignore, README, and UNLICENSEdusoleil3-0/+91
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-09-12Merge branch 'sploit/symtbl-base'Malfurious2-8/+15
This branch brings some conveniences to the semantics behind Symtbl base values. * sploit/symtbl-base: sploit: rev: Properly base Symtbls for non-PIC binaries sploit: Fix bugs involving Symtbl base value sploit: mem: Allow Symtbl base to be modified
2022-09-12sploit: rev: Properly base Symtbls for non-PIC binariesMalfurious1-1/+6
The baddr property identified by r2 is now used as the base address for ELF symbol tables. This should not change the addresses retrieved via the table normally, however should fix the internal offsets of the table so that rebasing makes sense. Note that for PIC/PIE binaries we would already get a Symtbl with 'correct' offsets, as r2 is unable to absolutely resolve them for us. In these cases, the Symtbl base value remains at zero. Signed-off-by: Malfurious <m@lfurio.us> Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-09-12sploit: Fix bugs involving Symtbl base valueMalfurious2-3/+3
Some code previously assumed a Symtbl's base value to always be zero. This was often the case, however the assumption would break (for example) when attempting to rebase() a mapped Symtbl. As of the previous patch enabling freer modification of base, the potentiality of these bugs will be higher. Signed-off-by: Malfurious <m@lfurio.us> Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-09-12sploit: mem: Allow Symtbl base to be modifiedMalfurious1-6/+8
Allow a Symtbl's base to be modified in-place, without mapping into a new object. This is useful when working with the Symtbl aspect of a Payload. This includes setting a non-zero base on construction. As usual, when defining base on construction, any additional kwargs symbols are interpreted relative to the given base. The order of arguments does not matter. Signed-off-by: Malfurious <m@lfurio.us> Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-09-12sploit: payload: Promote private methods to "protected" accessMalfurious1-15/+15
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>
2022-09-12sploit: payload: Clean up automatic symbol namingMalfurious1-10/+11
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>
2022-09-12sploit: payload: Class no longer extends SymtblMalfurious1-11/+8
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>
2022-09-12sploit: payload: Allow variadic insertionsMalfurious1-13/+15
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>
2022-04-08sploit: Allow multiple reads in Comm.readall_nonblock()Malfurious1-2/+6
Due to line buffering, we may often trigger a burst of data to be sent by the target, but resolve the non-blocking read only after the first line is received. We would like to wait just a little longer to receive the entire burst instead. readall_nonblock() will now reset its timeout period whenever any data becomes readable and will not return until we go an entire period of silence. Under normal conditions, the full duration of readall_nonblock should barely be any longer than the defined period itself. Signed-off-by: Malfurious <m@lfurio.us> Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-04-08sploit: Fix units for Comm.timeoutMalfurious1-1/+1
select's poll.poll() function expects its timeout argument to be in milliseconds. This is an artifact from earlier developent where we were using the higher-level 'selectors' API, which never got merged. Signed-off-by: Malfurious <m@lfurio.us> Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-19Add indirection to arch accessdusoleil1-1/+7
Add a layer of indirection to access the active arch config. Currently when importing sploit.arch.arch, the name will be bound to whatever the current reference is and won't follow if another module (user script) updates the reference in sploit.arch. A layer of indirection seemlessly solves that issue and also provides a cleaner interface for setting the active arch from the user script. Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-17sploit: Rework payload builderMalfurious1-57/+68
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>
2022-03-17sploit: Clean up use of __getattribute__Malfurious2-12/+1
__getattribute__ is the low-level magic func and will intercept every attribute lookup, whereas __getattr__ is high-level, and is only invoked in specific conditions (such as __getattribute__'s failure). As such, any overload of __getattribute__ which preferentially falls back to object.__getattribute__() before serving a request, can more simply be replaced by a __getattr__ overload without the fallback. Signed-off-by: Malfurious <m@lfurio.us> Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-17sploit: Fix bugs and simplify SymtblMalfurious1-82/+45
The recent implementation of the new design for Symtbl contained a few bugs: - Attempting to access .base on a Symtbl or intermediate __InnerTable__ caused an exception. - Symtbl objects all used the same static collection of nested subtables, rather than an instanced one. If two table objects contained the same named key, they would refer to the same nested table from both locations. - Printing the contents of a table accessed via an absolute nesting (aka: via an __InnerTable__ object) would not show the offsets adjusted for the curent context. In addition to these fixes, the class implementation is largely simplified as well. This is in part due to the removal of unnecessary logic, such as the way our __getattribute__ overloads were implemented. Mainly, this came down to merging the redundant abstractions in our original design. Over time, the differences between these interfaces became blurred to the point where simply reusing one is not at all problematic. It is very much the intent of this patch to preserve the semantics of the tool's design (that being: flexable, nestable tables, to which a separate, but linked, mapped view may be obtained), but to state it as cleanly as possible. Note that all of the working state of a Symtbl is kept in its new _namesp member. This is primarily done to enable subclassing the Symtbl class. Ordinarily, setattr() on self would force the incoming value into the actual symbol table, making it impossible for subclasses to store separate instance data. Furthermore, the consolidation of properties into this object creates fewer potential collisions with user-defined symbols. Signed-off-by: Malfurious <m@lfurio.us> Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-14Merge tag 'pull-sploit-rev' of https://github.com/Dusoleil/lib-des-gnuxMalfurious8-5/+201
Add rev for basic reverse engineering * tag 'pull-sploit-rev' of https://github.com/Dusoleil/lib-des-gnux: sploit: Move __attr_filter__ to a general place in util sploit: Filter all magic python members by default in mem module sploit: add stack base pointer to locals symtbl sploit: print hex of addresses in rev logs sploit: add status logging to rev module sploit: lazy load libs for ELF sploit: cache results of external commands sploit: add the rest of r2 functions through elf sploit: typo fix in rev.r2 sploit: cache ELF loads sploit: add ELF helper class to rev sploit: consolidate r2 symbol search calls sploit: fix r2 module syntax error sploit: reverse direction of r2 get_locals offsets sploit: add r2 funcionality to rev module sploit: add ldd ability to rev module sploit: add rev module to sploit
2022-03-14sploit: Clean up function Comm.interact()Malfurious1-32/+26
The previous patches in this series have needed to utilize similar logic as Comm.interact() throughout other parts of the Comm class. This patch just revisits .interact() to clean up redundant code. Co-authored-by: dusoleil <howcansocksbereal@gmail.com> Signed-off-by: Malfurious <m@lfurio.us> Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-14sploit: Add function popen()Malfurious1-0/+6
This is a free-function in the comm module, intended to help setup Sploit plumbing when working in the Python interactive interpreter. At the moment, the intended user experience in the interpreter is to err on the side of being interactive/responsive. As such, the Comm object returned from popen() is initialized with overridden IO settings to prefer 'readonwrite' by default. Addtionally, any early output from the target is also read, so that it may be immediately visible. A consequence of this configuration is that, until readonwrite is set False, most target output will be consumed before any .read* function has a chance to return it. While that would be a hard showstopper for any Sploit script, an interactive user can simply copy/paste any important data that is produced. Given that the interpreter workflow is likely going to be most useful for quick prototyping and recon with the proposed rev module, I consider this tradeoff appropriate at the moment, but will consider revisiting this if its usage is problematic. Signed-off-by: Malfurious <m@lfurio.us> Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-14sploit: Add Comm property 'readonwrite'Malfurious1-0/+2
If readonwrite is set to True (default False), Sploit will catch up and read all available stdin data from the target in a non-blocking fashion. If logonread is also set to True, this data will immediately be presented to the user whenever data is sent, but is otherwise lost (not returned). This mode is primarily intended for use in the interactive Python interpreter, where it can be cumbersome to keep alternating read and write calls when one does not care to actually record the read values. Signed-off-by: Malfurious <m@lfurio.us> Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-14sploit: Add function Comm.readall_nonblock()Malfurious1-0/+11
Function should consume all available incoming data from target and return it, however will return 'immediately' (according to a configurable timeout) if the pipe is empty. Signed-off-by: Malfurious <m@lfurio.us> Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-13sploit: Move __attr_filter__ to a general place in utildusoleil3-3/+11
Found a spot to use __attr_filter__ in the rev module, so moving it out of mem and into a shared place (util). Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-13sploit: Filter all magic python members by default in mem moduledusoleil1-3/+6
In the various __getattribute__() overloads in the mem module, we should filter all of the built-in magic members to do the default object.__getattribute__() behavior. This is opposed to the earlier stance of just caring about the ones that I saw as realistically being called. Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-13sploit: add stack base pointer to locals symtbldusoleil1-1/+3
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-13sploit: print hex of addresses in rev logsdusoleil1-2/+2
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-13sploit: add status logging to rev moduledusoleil2-0/+13
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-13sploit: lazy load libs for ELFdusoleil2-6/+16
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-13sploit: cache results of external commandsdusoleil5-15/+25
rather than cacheing ELF instantiations, just cache the results of external commands Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-13sploit: add the rest of r2 functions through elfdusoleil1-0/+20
expose the rest of the rev.r2 capabilities through rev.elf Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-13sploit: typo fix in rev.r2dusoleil1-1/+1
accidentally left the argument as "elf" instead of "binary" and had the arguments in the wrong order Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-13sploit: cache ELF loadsdusoleil1-1/+11
With recursive ELF loads, there is the possibility of loading in a heavy ELF (like libc) multiple times. Hiding instantiation of the class behind a factory method and caching instances should eliminate this problem. Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-13sploit: add ELF helper class to revdusoleil2-0/+23
Create a class which encapsulates some basic information about an ELF file and provides a convenient interface for basic reverse engineering. In particular, ELF automatically loads the symbol table of the given elf file and recursively creates ELF objects for any linked libraries. Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-13sploit: consolidate r2 symbol search callsdusoleil1-16/+5
Consolidate some of the r2 calls that get combined to create the symbol list. Instead of doing multiple calls with different greps within radare2, just do a single call and search it in the python side. This gives us a slight, but noticeable performance increase. Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-13sploit: fix r2 module syntax errordusoleil1-12/+12
forgot to remove the r2 namespace from the calls from back when it was implemented differently Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-13sploit: reverse direction of r2 get_locals offsetsdusoleil1-1/+1
rev.r2's get_locals() function returns a Symtbl of offsets representing the local variables on in a stack frame of a particular function. The offsets returned by r2 are based around the base of the stack, but they are increasing in value as they grow from the stack. To properly model memory, they should decrease in value as they grow from the stack. Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-13sploit: add r2 funcionality to rev moduledusoleil2-1/+94
Add an r2 module with several helper functions that do a number of simple reverse engineering tasks to aid in writing simple sploit scripts. The functions in this module invoke radare2 to accomplish their tasks. Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-13sploit: add ldd ability to rev moduledusoleil2-0/+14
add helper function to invoke ldd to get a list of libraries that will be linked to a given ELF Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-13sploit: add rev module to sploitdusoleil3-2/+3
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>
2022-03-13sploit: Add support for nested Symtblsdusoleil1-3/+45
Signed-off-by: dusoleil <howcansocksbereal@gmail.com>