Security News

Cybersecurity news aggregator

📰
INFO News Reddit r/netsec

Evading Machine Learning Based Detections · MSec Operations Blog

  • What: A blog post discusses techniques to evade machine learning-based detections
  • Impact: Cybersecurity professionals must stay updated on evasion tactics
Read Full Article →

In my x33fcon talk The Art of Evasion , I presented general Packer/Loader explanations as well as what machine-learning-based detections are about and how to bypass them. This blog post is the companion to that talk and also introduces the RustPack version 1.7 features that cover ML evasion by default. The Packer/Loader Architecture and Minimum Needed Features When we talk about the architecture of a Packer in the malware development field, it usually consists of two main components: The Packer code The Loader code The Packer can be used by an operator with various input arguments to enable optional features. It typically encrypts or encodes an input payload, generates the “Loader code” and then compiles it to produce an executable, DLL or other output payload. That output payload executes the original input from memory in an OPSEC-safe way after decrypting or decoding it. From my perspective, any Packer needs at minimum the following features so that you can use it long-term without getting signatured or flagged at runtime: Polymorphism means that every output payload differs heavily from the next, so that creating signatures or YARA rules for that output is as hard as possible. This can be implemented in a simple or a more complex way. A very simple example would be to place RANDVALUE placeholders throughout the “Loader code” templates; for every single payload, the Packer then replaces these stubs with custom, always different-looking code before compiling it. This ensures that new random instructions are inserted every few instructions, so every output looks different. A very simple implementation is used in my public NimSyscallPacker , in which random, always different-looking strings are inserted: RustPack uses a far more complex implementation: various code snippets from a pool are inserted, and those snippets are heavily randomised as well, so that the inserted junk code never looks the same. In a bad implementation, the inserted junk code itself might get signatured and become an IoC of its own. Suspicious strings in your payload can get it caught directly, which is why string obfuscation is a must, at least for obvious IoCs. Something simple such as XOR with a custom seed, for example the compile time, can be sufficient: However, at the latest when an analyst or an LLM takes a look at the payload, this kind of encryption can simply be reversed to recover the original plaintext strings. So, to complicate analysis further, a random key for every single string as well as multiple different encryption/decryption functions are recommended, which is again implemented in RustPack. Any payload that is dropped to disk is analysed by an emulation engine at some AV/EDR vendors (not all). Emulation is different from a sandbox: payloads are not executed on a real, virtualized operating system. Instead, the vendor emulates the payload’s ASM instructions and, for any real Win32 API, provides the software with fake return values so that the malware thinks execution succeeded even though it never really happened. So, for example, when the malware calls LoadLibraryA to load amsi.dll , the emulation engine returns a fake success value and some fake handle to the malware, but the DLL was never really loaded. Different approaches can be used to bypass such emulation engines, for example: Resource Exhaustion Breaking the Implementation Emeric Nasi published a good talk on this topic at MCTTP 2024 - if you are interested, it is a recommended read! Some implementations might break one emulation engine but not another. The recommendation here is to be creative and to find your own custom bypasses. Encryption or encoding of the input payload is generally recommended, though not strictly necessary. If the input payload is not known-malicious, or is retrieved from a file on disk or some other channel at runtime, it is optional. Various optional features can be implemented in a Packer, such as userland hook evasion via different techniques, DLL sideloading output and so on. However, these are only needed against certain vendors or in specific situations. Bypassing AMSI or ETW data collection, for example, is only needed when executing known-malicious scripts or .NET assemblies from memory. Machine Learning Based Detections Even if you have implemented all of the minimum required features in your Packer/Loader, you might still face a detection like the following: And this is where machine-learning-based detections come into play. Talking about machine learning in 2026, most people think of ChatGPT, Claude, Grok and so on. But this is not what AV/EDR vendors use for detection in their products. What most vendors use is “passive metadata analysis”. But how does “passive metadata analysis” work? For me, this was a real question until Brandon (mez0) published the following blog post: https://mez0.cc/posts/evaluating-implants-with-ember/ Before that point, I was not aware of the publication of EMBER2024 , EMBER2018 or EMBER2017. In...

Share this article