The Nim programming language has turn out to be more and more enticing to malware builders attributable to its strong compiler and its capability to work simply with different languages. Nim’s compiler can compile Nim to JavaScript, C, C++, and Goal-C, and cross-compile for main working methods comparable to Home windows, Linux, macOS, Android, and iOS. Moreover, Nim helps importing features and symbols from the languages talked about above, and importing from dynamically linked libraries for Home windows and shared libraries for Linux. Nim wrapper modules are additionally out there, comparable to Winim, that make interplay with the working system painless. All these capabilities enable straightforward integration of Nim into improvement pipelines utilizing these languages and enhance the event of recent instruments, each benign and malicious.
It’s no shock, then, that ESET Analysis has seen an ongoing use of malware developed in Nim within the wild. Way back to 2019, Sednit was noticed utilizing a malicious downloader written in Nim. One other infamous group taking part in the Nim sport, and the impetus for creating Nimfilt, is the Mustang Panda APT group. ESET Analysis recorded Mustang Panda utilizing Nim in its toolset for the primary time in a marketing campaign towards a governmental group in Slovakia in August 2023. The malicious DLL detected – and used as a part of the group’s basic trident Korplug loader – was written in Nim.
For researchers tasked with reverse engineering such binaries, Nimfilt is a robust software to hurry up evaluation. Whereas Nimfilt may be run as a Python script each on the command line (with a subset of its performance) and in Hex-Rays’ IDA program, it is going to be offered right here primarily as a Python plugin for IDA.
Initializing Nimfilt in IDA
When IDA is first opened, it masses and initializes any plugins within the IDA plugins listing. Through the initialization of Nimfilt, the plugin makes use of fundamental heuristics to find out whether or not the disassembled binary was compiled with the Nim compiler. If one of many following checks is handed, Nimfilt determines that this compiler was used:
- The binary incorporates each of the next strings:
- The binary incorporates any of the next well-known Nim operate names:
- NimMain
- NimMainInner
- NimMainModule
- The binary incorporates a minimum of two of the next error message strings:
- @worth out of vary
- @division by zero
- @over- or underflow
- @index out of bounds
YARA guidelines are offered together with Nimfilt that make related checks to find out whether or not an ELF or PE file has been compiled with Nim. Collectively, these checks are much more strong than the method taken by different instruments, comparable to Detect It Simple, which at present solely checks the .rdata part of PE information for the string io.nim or deadly.nim.
As the ultimate initialization step, if Nimfilt’s AUTO_RUN flag is ready to true, the plugin runs instantly. In any other case, Nimfilt may be run as common from IDA’s plugins menu, as proven in Determine 1.

Demangling with Nimfilt
Nim makes use of a customized identify mangling scheme that Nimfilt can decode. Throughout a run, Nimfilt iterates via every operate identify within the binary, checking whether or not the identify is a Nim bundle or operate identify. Found names are renamed to their demangled varieties.
Apparently, these names can leak details about the developer’s atmosphere, in a lot the identical manner as PDB paths. That is as a result of Nim compiler including the file path to the identify throughout mangling – Nimfilt reveals the trail upon demangling.
For instance, operate names from third-party packages are saved as absolute paths throughout the mangling course of. Determine 2 exhibits a operate identify that’s saved as an absolute path revealing the model and checksum of the nimSHA2 bundle used, together with the developer’s set up path for nimble – Nim’s default bundle supervisor.
python nimfilt.py GET_UINT32_BE__6758Z85sersZ85serOnameZOnimbleZpkgs50Znim837265504548O49O494554555453d57a4852c515056c5452eb5354b51fa5748f5253545748505752cc56fdZnim83726550_u68
C:/Customers/Consumer.identify/.nimble/pkgs2/nimSHA2-0.1.1-6765d9a04c328c64eb56b3fa90f45690294cc8fd/nimSHA2::GET_UINT32_BE u68
Determine 2. Demangling the identify of a operate from a third-party bundle
In distinction, Determine 3 exhibits the identify of a operate from a normal Nim bundle saved as a relative path (that’s, relative to the Nim set up path).
python nimfilt.py toHex__pureZstrutils_u2067
pure/strutils::toHex u2067
Determine 3. Demangling the identify of a operate from a normal Nim bundle
Nonetheless, names should not all the time mangled in the identical manner. Determine 4 exhibits that the identical operate identify above from the nimSHA2 bundle is saved on Linux as a relative path.
python nimfilt.py GET_UINT32_BE__OOZOOZOOZhomeZalexZOnimbleZpkgs50Znim837265504548O49O494554555453d57a4852c515056c5452eb5354b51fa5748f5253545748505752cc56fdZnim83726550_u49
Determine 4. Demangling the identify of a operate from a third-party bundle on Linux
Package deal initialization features are mangled in a very totally different manner: the bundle identify is saved as a file path (together with the file extension) positioned earlier than the operate identify and an escaping scheme is used to symbolize sure characters like ahead slashes, hyphens, and dots. Upon demangling, Nimfilt cleans up the bundle identify by eradicating the .nim file extension, as proven in Determine 5.
python nimfilt.py atmdotdotatsdotdotatsdotnimbleatspkgsatswinimminus3dot9dot1atswinimatsincatswinbasedotnim_DatInit000
Determine 5. Demangling the identify of an initialization operate from a third-party bundle
Determine 6 exhibits how names of initialization features from native packages are saved as absolute paths.
python nimfilt.py atmCatcatstoolsatsNimatsnimminus2dot0dot0atslibatssystemdotnim_Init000
C:/instruments/Nim/nim-2.0.0/lib/system::Init000
Determine 6. Demangling the identify of an initialization operate from a local bundle
In IDA, Nimfilt’s identify demangling course of is adopted by the creation of directories within the Capabilities window to prepare features in response to their bundle identify or path, as proven in Determine 7.

Making use of structs to Nim strings
The final motion carried out throughout a run of Nimfilt is making use of C-style structs to Nim strings. Simply as strings in another programming languages are objects reasonably than null-terminated sequences of bytes, so are strings in Nim. Determine 8 exhibits how the string ABCDEF seems in IDA earlier than and after operating Nimfilt. Be aware that in disassembled kind, a Nim-compiled binary makes use of the prefix _TM as part of the short-term identify of some variables; these are sometimes Nim strings.

Nimfilt iterates via every deal with within the .rdata or .rodata section, and in every other read-only information section, in search of Nim strings. Structs are utilized to any found strings; the struct incorporates a size area and a pointer to the payload consisting of the characters within the string.
Wrap-up
On its technique to being compiled as an executable, Nim supply code is often translated to C or C++; nonetheless, this course of doesn’t solely take away all traces of Nim. By taking a journey via the Nim compiler supply code, we now have unraveled among the paths taken within the compilation course of and had been thus in a position to construct Nimfilt as a Python software, and IDA plugin, to help on this untangling.
In brief, whether or not or not you might be new to Nim, turning to Nimfilt will make your reverse engineering work with Nim-compiled binaries nearly immediately simpler and extra targeted. Not at all, nonetheless, is Nimfilt’s improvement at a standstill; we’re engaged on extra options to deal with double mangling, and enhance the formatting of demangled names and the grouping of bundle names.
Nimfilt’s supply code and documentation can be found in a repository hosted on ESET’s GitHub group at https://github.com/eset/nimfilt.