The minimal requirement to run a given sample, is to provide the “-file” argument, along with a file name or file path. If a full path is given, it is used. If a file name is given, the current working directory is checked, as well as the folder of DotDumper’s executable location.
Unless a directory name is provided, the “-log” folder name is set equal to the file name of the sample without the extension (if any). The folder is located in the same folder as DotDumper resides in, which is where the logs and dumped files will be saved in.
In the case of a library, or an alternative entry point into a binary, one must override the entry point using “-overrideEntry true”. Additionally, one has to provide the fully qualified class, which includes the name space using “-fqcn My.NameSpace.MyClass”. This tells DotDumper which class to select, which is where the provided function name (using “-functionName MyFunction”) is retrieved.
If the selected function requires arguments, one has to provide the number of arguments using “-argc” and the number of required arguments. The argument types and values are to be provided as “string|myValue int|9”. Note that when spaces are used in the values, the argument on the command-line interface needs to be encapsulated between quotes to ensure it is passed as a single argument.
Other less frequently used options such as “-raceTime” or “-deprecated” are safe in their default settings but might require tweaking in the future due to changes in the DotNet Framework. They are currently exposed in the command-line interface to easily allow changes, if need be, even if one is using an older version of DotDumper when the time comes.
First, the local system time is given, together with the original function’s return type, name, and argument(s). Second, the stack trace is given, where it shows that the sample’s main function leads to a constructor, initialises the components, and calls two custom functions. The Assembly.Load function was called from within “NavigationLib.TaskEightBestOil.GGGGGGGGGGGGGGGGGGGG(String str)”. This provides context for the analyst to find the code around this call if it is of interest.
Then, information regarding the assembly call order is given. The more stages are loaded, the more complex it becomes to see via which stages the call came to be. One normally expects one stage to load the next, but in some cases later stages utilize previous stages in a non-linear order. Additionally, information regarding the originating assembly is given to further enrich the data for the analyst.
Next, the parent hash is given. The parent of a stage is the previous stage, which in this example is not yet present. The newly loaded stage will have this stage as its parent. This allows the analyst to correlate events more easily.
Finally, the function’s return type and value are stored, along with the type, name, and value of each argument that is passed to the hooked function. If any variable is larger than 100 bytes in size, it is stored on the disk instead. A reference is then inserted in the log to reference the file, rather than showing the value. The threshold has been set to avoid hiccups in the printing of the log, as some arrays are thousands of indices in size.
The function name in the first line is not an internal function of the DotNet Framework, but rather a call to a specific function in the second stage. The types and names of the three arguments are listed in the function signature. Their values can be found in the function argument information section. This would allow an analyst to load the second stage in a custom loader with the given values for the arguments, or even do this using DotDumper by loading the previously dumped stage and providing the arguments.
Knowing what hooks are is essential to understand what managed hooks are. Managed code is executed in a virtual and managed environment, such as the DotNet runtime or Java’s virtual machine. Obtaining the memory address where the managed function resides differs from an unmanaged language such as C. Once the correct memory addresses for both functions have been obtained, the hook can be set by directly accessing memory using unsafe C#, along with DotNet’s interoperability service to call native
DotDumper is under constant review and development, all of which is focused on two main areas of interest: bug fixing and the addition of new features. During the development, the code was tested, but due to injection of hooks into the DotNet Framework’s functions which can be subject to change, it’s very well possible that there are bugs in the code. Anyone who encounters a bug is urged to open an issue on the GitHub repository, which will then be looked at. The suggestion of new features is also possible via the GitHub repository. For those with a GitHub account, or for those who rather not publicly interact, feel free to send me a private message on my Twitter.
Needless to say, if you’ve used DotDumper during an analysis, or used it in a creative way, feel free to reach out in public or in private! There’s nothing like hearing about the usage of a home-made tool!
There is more in store for DotDumper, and an update will be sent out to the community once it is available!
Framework for Automating Fuzzable Target Discovery with Static Analysis.
Vulnerability researchers conducting security assessments on software will often harness the capabilities of coverage-guided fuzzing through powerful tools like AFL++ and libFuzzer. This is important as it automates the
fuzzable comes with various options to help better tune your analysis. More will be supported in future plans and any feature requests made.
Static Analysis Heuristics
To determine fuzzability, fuzzable utilize several heuristics to determine which targets are the most viable to target for dynamic analysis. These heuristics are all weighted differently using the scikit-criteria library, which utilizes multi-criteria decision analysis to determine the best candidates. These metrics and are there weights can be seen here:
|Fuzz Friendly Name
||Symbol name implies behavior that ingests file/buffer input
||Arguments that flow into risky calls (ie memcpy)
||Number of loops detected with the dominance frontier
||Complexity of function target based on edges + nodes
||Number of callees the target traverses into
As mentioned, check out the technical blog post for a more in-depth look into why and how these metrics are utilized.
Many metrics were largely inspired by Vincenzo Iozzo’s original work in 0-knowledge fuzzing.
Every targets you want to analyze is diverse, and fuzzable will not be able to account for every edge case behavior in the program target. Thus, it may be important during analysis to tune these weights appropriately to see if different results make more sense for your use case. To tune these weights in the CLI, simply specify the
$ fuzzable analyze <TARGET> --score-weights=0.2,0.2,0.2,0.2,0.2
By default, fuzzable will filter out function targets based on the following criteria:
- Top-level entry calls – functions that aren’t called by any other calls in the target. These are ideal entry points that have potentially very high coverage.
- Static calls – (source only) functions that are
static and aren’t exposed through headers.
- Imports – (binary only) other library dependencies being used by the target’s implementations.
To see calls that got filtered out by fuzzable, set the
$ fuzzable analyze --list-ignored <TARGET>
In Binary Ninja, you can turn this setting in
Settings > Fuzzable > List Ignored Calls.
In the case that fuzzable falsely filters out important calls that should be analyzed, it is recommended to use
--include-* arguments to include them during the run:
# include ALL non top-level calls that were filtered out
$ fuzzable analyze --include-nontop <TARGET>
# include specific symbols that were filtered out
$ fuzzable analyze --include-sym <SYM> <TARGET>
In Binary Ninja, this is supported through
Settings > Fuzzable > Include non-top level calls and
Symbols to Exclude.
Now that you have found your ideal candidates to fuzz, fuzzable will also help you generate fuzzing harnesses that are (almost) ready to instrument and compile for use with either a file-based fuzzer (ie. AFL++, Honggfuzz) or in-memory fuzzer (libFuzzer). To do so in the CLI:
If this target is a source codebase, the generic source template
will be used.
If the target is a binary, the generic black-box template will be used, which ideally can be used with a fuzzing emulation mode like AFL-QEMU. A copy of the binary will also be created as a shared object if the symbol isn’t exported directly to be
dlopened using LIEF.
At the moment, this feature is quite rudimentary, as it simply will create a standalone C++ harness populated with the appropriate parameters, and will not auto-generate code that is needed for any runtime behaviors (ie. instantiating and freeing structures). However, the templates created for fuzzable should get still get you running quickly. Here are some ambitious features I would like to implement down the road:
- Full harness synthesis – harnesses will work directly with absolutely no manual changes needed.
- Synthesis from potential unit tests using the DeepState framework (Source only).
- Immediate deployment to a managed continuous fuzzing fleet.
fuzzable supports generating reports in various formats. The current ones that are supported are JSON, CSV and Markdown. This can be useful if you are utilizing this as part of automation where you would like to ingest the output in a serializable format.
In the CLI, simply pass the
--export argument with a filename with the appropriate extension:
$ fuzzable analyze --export=report.json <TARGET>
In Binary Ninja, go to
Plugins > Fuzzable > Export Fuzzability Report > ... and select the format you want to export to and the path you want to write it to.
This tool will be continuously developed, and any help from external mantainers are appreciated!
- Create an issue for feature requests or bugs that you have come across.
- Submit a pull request for fixes and enhancements that you would like to see contributed to this tool.
Fuzzable is licensed under the MIT License.
As last year
, this year we made a ranking with the most popular tools between January and December 2022.
Without going into further details, we have prepared a useful list of the most popular tools in Kitploit 2022:
- Zphisher – Automated Phishing Tool
- CiLocks – Android LockScreen Bypass
- Arkhota – A Web Brute Forcer For Android
- GodGenesis – A Python3 Based C2 Server To Make Life Of Red Teamer A Bit Easier. The Payload Is Capable To Bypass All The Known Antiviruses And Endpoints
- AdvPhishing – This Is Advance Phishing Tool! OTP PHISHING
- Modded-Ubuntu – Run Ubuntu GUI On Your Termux With Much Features
- Android-PIN-Bruteforce – Unlock An Android Phone (Or Device) By Bruteforcing The Lockscreen PIN
- Android_Hid – Use Android As Rubber Ducky Against Another Android Device
- Cracken – A Fast Password Wordlist Generator, Smartlist Creation And Password Hybrid-Mask Analysis Tool
- HackingTool – ALL IN ONE Hacking Tool For Hackers
- Arbitrium-RAT – A Cross-Platform, Fully Undetectable Remote Access Trojan, To Control Android, Windows And Linux
- Weakpass – Rule-Based Online Generator To Create A Wordlist Based On A Set Of Words
- Geowifi – Search WiFi Geolocation Data By BSSID And SSID On Different Public Databases
- BITB – Browser In The Browser (BITB) Templates
- Blackbird – An OSINT Tool To Search For Accounts By Username In 101 Social Networks
- Espoofer – An Email Spoofing Testing Tool That Aims To Bypass SPF/DKIM/DMARC And Forge DKIM Signatures
- Pycrypt – Python Based Crypter That Can Bypass Any Kinds Of Antivirus Products
- Grafiki – Threat Hunting Tool About Sysmon And Graphs
- VLANPWN – VLAN Attacks Toolkit
- linWinPwn – A Bash Script That Automates A Number Of Active Directory Enumeration And Vulnerability Checks
Happy New Year wishes the KitPloit team!