Cisco-Talos / Nim-IDA-FLIRT-Generator

Nim-IDA-FLIRT-Generator
Apache License 2.0
13 stars 1 forks source link

Nim-IDA-FLIRT-Generator for Nim 1.6.12 (use devel branch for Nim 2.0.x)

Adversaries are increasingly writing malware in programming languages such as Go, Rust, or Nim, likely because these languages present challenges to investigators using reverse engineering tools designed to work best against the C family of languages. It’s often difficult for reverse engineers examining non-C languages to differentiate between the malware author’s code and the language’s standard library code. In the vast majority of cases, HexRay’s Interactive Disassembler (IDA) has the out-of-the-box capability to identify library functions or generate custom Fast Library Identification and Recognition Technology (FLIRT) signatures and solve the issue. But for Nim, generating signatures is distinctly more difficult. With all this in mind we decided to start a project to find an automated way to generate custom FLIRT signatures for IDA, which led to a talk at Recon.cx 2023 and a guest blog on Hexrays.

To fully automate the signature-generating process and for educational purposes, we wrote three POC scripts: one generating Nim source code files (nim_rtl_builder.py) which include the majority of Nim functions from Nim's runtime library (RTL) and compiling them, one COFF parser (coffparser.py), and one using the COFF parser to parse the generated object files (.o) in the Nim cache directory (obj2patfile.py) from step one. These object files are generated by the Nim compiler automatically at compile time. The obj2patfile.py script also generates the final FLIRT signature for IDA. If you do not need signatures for special versions or compiler settings of the Nim runtime library, you can also download ready to go signature files for Nim 1.6.12 from the signatures/ directory of this repo. These signature files likely work for some other Nim versions too. After execution, each script will give you instructions on what to do next.

You can find a detailed description of the tools and our research in the HexRays guest blog. If this is tl;dr here is a short summary:

Quick Steps to generate a Nim FLIRT signature

These scripts and the whole workflow is written for the Windows OS. It may run on other platforms, but is not explicitly supported. It is also mandatory to use the default compiler for Nim on Windows: MinGW. This is required because we are using the -ffunction-sections option of MinGW. We used Python 3.10.5 on Windows 11 for our tests.

Before executing, you have to edit the nim_rtl_builder.py script and change some variables, of which only the first one is mandatory. You then must change to the \lib\pure directory of your Nim installation (e.g. ..\nim-1.6.12\lib\pure).

OBJ2PATFILE          = "C:\\tools\\Nim\\src\\obj2patfile.py"  # The path to the next script
MISSED_FUNC_FILENAME = f"missed_functions-{timestamp}"        # The name of the file which includes the functions the script was not able to parse 
NIM_CACHE_DIR        = 'HU_nim_cache'                         # The directory name the scripts uses for the Nim Cache directory to store the object files
cd <NIM_INSTALL_DIR>\lib\pure                                 # e.g. C:\Users\hunte\.choosenim\toolchains\nim-1.6.12\lib\pure
python <PATH_TO_SCRIPT>\nim_rtl_builder.py                    

These steps build the executables from our fake RTL source code, in addition to the object files in the Nim cache directory, which we need for the next stage.

Now you can parse all generated COFF object files (.o) in the Nim compiler cache directory by executing the obj2patfile.py script. Again, you need to set the right paths in the header of the obj2patfile.py script first.

NIM_SIGNAME = "nim-1612"                                        # signature filename - no underscores or blanks are allowed
COFFPARSER  = "C:\\tools\\Nim\\src\\coffparser.py"              # Path to coffparser.py script    
SIGMAKE     = "C:\\tools\\IDA\\flair82\\bin\\win\\sigmake.exe"  # Path to HexRays SDK sigmake executable

Make sure you changed the directory to the Nim cache directory before running the obj2patfile.py script. As a reminder, the cache directory name was set in the nim_rtl_builder.py script above.

cd <NIM_CACHE_DIR>                                             # e.g. ..\nim-1.6.12\lib\pure\HU_nim_cache
python <PATH_TO_SCRIPT>\obj2patfile.py

Now run the sigmake.exe tool from the FLAIR toolkit to generate the final signature file — just copy and paste it from the output of the obj2patfile.py script.

C:\tools\IDA\flair82\bin\win\sigmake.exe -n"nim-1612" sdigitsutils.nim.c.pat+swin_setenv.nim.c.pat+ssystem.nim.c.pat+sassertions.nim.c.pat+sdollars.nim.c.pat+sio.nim.c.pat+swidestrs.nim.c.pat+swinlean.nim.c.pat+malgorithm.nim.c.pat+mbrowsers_hu.nim.c.pat+mcstrutils_hu.nim.c.pat+mdollars.nim.c.pat+mdynlib.nim.c.pat+mformatfloat.nim.c.pat+mio.nim.c.pat+mio_hu.nim.c.pat+mmath.nim.c.pat+mmath_hu.nim.c.pat+mos.nim.c.pat+mosproc_hu.nim.c.pat+mparsecfg_hu.nim.c.pat+mparseopt_hu.nim.c.pat+mparseutils.nim.c.pat+mparseutils_hu.nim.c.pat+mpathnorm.nim.c.pat+mropes_hu.nim.c.pat+mstreams.nim.c.pat+mstrtabs_hu.nim.c.pat+mstrutils.nim.c.pat+mstrutils_hu.nim.c.pat+mtimes.nim.c.pat+municode_hu.nim.c.pat+mwidestrs.nim.c.pat nim-1612.sig

There will be some collisions, which is expected. You need to delete the comments in the nim-1612.exec file that was generated by sigmake.exe. In other words, delete the first 4-5 lines in the .exec file, starting with semicolons. Once the comments are deleted, run the sigmake.exe command again in the same way you did before.

C:\tools\IDA\flair82\bin\win\sigmake.exe -n"nim-1612" sdigitsutils.nim.c.pat+swin_setenv.nim.c.pat+ssystem.nim.c.pat+sassertions.nim.c.pat+sdollars.nim.c.pat+sio.nim.c.pat+swidestrs.nim.c.pat+swinlean.nim.c.pat+malgorithm.nim.c.pat+mbrowsers_hu.nim.c.pat+mcstrutils_hu.nim.c.pat+mdollars.nim.c.pat+mdynlib.nim.c.pat+mformatfloat.nim.c.pat+mio.nim.c.pat+mio_hu.nim.c.pat+mmath.nim.c.pat+mmath_hu.nim.c.pat+mos.nim.c.pat+mosproc_hu.nim.c.pat+mparsecfg_hu.nim.c.pat+mparseopt_hu.nim.c.pat+mparseutils.nim.c.pat+mparseutils_hu.nim.c.pat+mpathnorm.nim.c.pat+mropes_hu.nim.c.pat+mstreams.nim.c.pat+mstrtabs_hu.nim.c.pat+mstrutils.nim.c.pat+mstrutils_hu.nim.c.pat+mtimes.nim.c.pat+municode_hu.nim.c.pat+mwidestrs.nim.c.pat nim-1612.sig

Now that you have a valid IDA signature file (nim-1612.sig), the last step is to copy this over to the IDA signature directory (e.g. C:\Program Files\IDA Pro 8.2\sig\pc). You can load these signatures when you are analyzing a Nim executable in IDA via the File/Load File/FLIRT Signature file… menu.

Happy reversing !