nuitka-helper is a collection of IDAPython scripts to help analyze Nuitka binaries. It is intended to be used in conjunction with its accompanying blog post here. If you have queries, the answers are probably in the blog.
See blog for detailed information
- Unpack Nuitka binary
- Create Nuitka header file
- Optional since
nuitka.h
is provided, but some structs might become obsolete in the future
- Optional since
- Create FLIRT signature
- Optional but highly recommended as other heuristics may not be as reliable
- Use
get_nuitka_version.py
to help
- Use
- Optional but highly recommended as other heuristics may not be as reliable
Some scripts use the debugger so run them in a VM if needed
-
Run
nuitka-helper.py
on unpacked binary -
Organize functions by module
-
View logged constants in
constants.log
-
Parse additional constants using
parse_module_constants.py
-
Hook functions using
hook_module_functions.py
-
Get function definitions by injecting
get_module_functions.py
into Python process-
This can be done using a Python injector like pynject
- Inject after target modules get imported for best results
-
View function definitions in
functions.log
-
├───files
│ nuitka.h (Nuitka header file)
│
└───flake (output files for flake.exe)
flake.sig
solve.py
├───projects
├───types: (test cases for parse_module_constants.py)
│ scalar
│ collections
│
└───constructs: (code constructs that are harder to recognize)
loops
try-except
├───scripts
├───setup
│ get_nuitka_version.py
│
├───symbol recovery
│ nuitka-helper.py
│ recover_library_code.py
│ recover_modules.py
│ recover_constants.py
│ recover_functions.py
│
└───plugins
get_module_functions.py
hook_module_functions.py
parse_module_constants.py
- Windows (not tested on other platforms)
-
Script crashes sometimes due to some Appcall/debugger bug (internal error 40731/unhandled c++ exception)
- Temporary Fix:
- Increase the sleep timer in
recover_constants.py
- Re-run
nuitka-helper.py
- Increase the sleep timer in
- Temporary Fix:
Work that never gets done
recover_constants.py
- Fix Appcall/debugger bug (not sure why but this occurs occasionally for certain samples)
recover_library_code.py
- Load structs as type library instead of header file
recover_module_constants.py
- Comment gets cut off if its too long
- e.g. module dictionary -> gets printed as fallback for now
- IDA crashes if name is too long
- Comment gets cut off if its too long
The answers are in the blog for these questions:
- Q: How can I manually identify
Nuitka_Function_New
? - Q: How do I identify the main module dictionary
moduledict___main__
? - Q: Where do I find the code logic in the Nuitka module/function?
- Q: Why did you choose to parse the constants dynamically (instead of statically)?
- A: First, doing so enables me to trace the module dictionary, which changes at different points of the program. Second, I want the parsing algorithm to be independent of how Nuitka loads its constants, in case it gets updated in the future.
- Q: What Nuitka versions does this tool support?
- A: I only tested the tool on
flake
(1.8.0) &GhostLocker
(1.8.4), but I think it should (somewhat) work for other versions too. I did not test the tool on any commercial Nuitka binaries.
- A: I only tested the tool on
- Q: What can I do if the tool breaks?
- A: Here are some things you can try:
- Manually identify
modulecode__main__
using theLoaded %s
string instead of__main__
- Manually identify important library functions (i.e.
loadConstantsBlob
,Nuitka_Function_New
) ida_typeinf.get_arg_addrs
might be broken (function typed wrongly/remote debugging buggy)- Let the binary automatically load the constants instead of forcibly loading them
- Manually identify
- A: Here are some things you can try: