MalDev Myths

Since years i see techniques used in MalDev which are obsolete since a long time, or just applied wrongly. A short list.

When doing MalDev, you have to consider against what you want to protect:

  • Automated systems which will detect and block your malware
  • Manual reverse engineering of the functionality of your malware

I focus on the first, as I want a working beacon. If the SOC reverses my malware, i buy them beer. This article is RedTeaming specific and about loaders and droppers. Storing malicious code in files or memory.

Automated detection mostly means AntiVirus (AV), EDR, and stuff like sandboxes. This article doesnt consider the use case for manually reverse engineering.

This list is based on Sektor7’s courses (maldev essentials, intermediate, windows evasion). But I see this kind of obsolete information everywhere - as if the hacker scene didnt catch up to current developments, and just blindly rehashes stuff from the 90s. Even worse is that all MalDev courses or trainings i’ve seen just randomly throw techniques together and hope for the best. Instead of analyzing security software first, and find blind spots. For example by trying to understand how EDRs work first.

This information is not based on experience, but by understanding.

Where to store payloads

If you want store data in an exe, for example for a dropper, there are several places to chose from, including:

  • .text
  • .data
  • .rsrc

Which one should you take? It doesnt really matter.

PE sections

PE sections2

If you modify an existing .exe, both .text and .data dont really have enough free space (only maybe a few 100 bytes). If you add a lot of data in it, you gonna trash it, making the program unable to run correctly. .rsrc often has lots of available space.

If you generate the .exe by yourself, it doesnt matter. EDR’s dont really see where data is coming from when copying it around. Its inside the process space from one memory location to another, which cant really be seen - the EDR isnt able to distinguish it.

Software doing static analysis of the file may influence your decision a little bit.

Conclusion:

  • Stop to care about where to put your data.
  • Just put code into .text, and data into .data or .rsrc. Look normal.
  • When backdooring exes, use .rsrc or other sections where overwriting data doesnt matter
  • Just dont create new PE sections, that stands out.

Entropy

If you encrypt or compress stuff and put it into a .exe, it will have higher entropy that the surrounding data. This can be detected, and will result in an event like:

Higher entroy found in .text section between 0x1234 and 0x5432.

Here a graphical example:

PE entropy

This is not a reliable detection. Security software blocking executables with high entropy at unexpected places will block many genuine executables. The above screenshot from the tool DIE-engine, analysing DIE-engine itself.

Discussing entropy is cool - but its not that relevant for automated analysis.

Conclusion:

  • Entropy can help manual reverse engineering, but is rarely a reliable automated indicator.
  • If you are scared from entropy analysis, just base64 your data
  • Generally try to blend in, by encoding your stuff similar to surrounding data

How to encrypt/encode the payload for storage

In many shellcode loaders, there are several implementation of different encryption/encoding methods implemented. Like XOR, RC4, AES, Hex-Encoding or similar (see 1 2 3 ).

Which one you choose doesnt matter. A EDR or AV cannot magically crack encryption - it doesnt have a quantum computer inside. It doesnt even know which encryption algorithmn you implemented - hell it doesnt even know that you encrypt or decrypt something. It cannot trace all the instruction, and recover the original intent from it. An exception is using standard Windows API to encrypt, like AES or Base64 from crypt32.dll . Or when using a standard encryption library with well-known signatures. See Shellcode Obfsucation Lab for a detailed analysis.

Static analysis software which have enough time (async, e.g. virustotal) can attempt to try all the standard decodings like base64 or XOR with all 255 single byte keys on all (?), data, like in global variables.

Conclusion:

  • Encrypt your stuff however you want, it doesnt matter much
  • Avoid using Windows API’s to do it tho
  • The data will be securely encrypted in the file on disk - and decrypted in memory on usage (memory scanners!)
  • Try to avoid 1-byte XOR, as it results in a potential pattern - use at least 2-byte XOR
  • If your data is very easily discernable, avoid standard methods (base64, single byte XOR etc.) or prepend an random character

Function call obfuscation / IAT heuristics

The .exe has a list of all used/imported DLL functions in the IAT (import address table). Some security software has a look at this to decide if a software looks malicious or not. If your output is “may be malicious”, then its heuristics.

Its not reliable, by definition, and as most Windows software does a lot of crazy things, and imports the typical malicious looking functions.

See for example the imports from the tool cffexplorer.exe of itself. Is this malicious or not?

PE imports

Analyze putty, process monitor or any other tool to see how abnormal their IAT looks.

Conclusion:

  • Dont use/import exclusively potentially malicious functions - try to look normal.
  • Try to make it look normal (good API stuffing, or backdooring existing executables).
  • If scared, use GetModuleHandle() and GetProcAddres() - these are very commonly used anyway by genuine programs, but can be an IOC
  • Alternatively, implement GetModuleHandle() & GetProcAddress yourself with a PEB walk. But: Existing PEB walk implementations ou copy may be signatures

Signed EXE / Certificate

What happens if you (correctly) sign a executable? Will it not be scanned by the AV? Will it be whitelisted by the EDR? I dont know, but i doubt it. This is heavily security tool dependent.

Leaked code signing certs are commonly available - expired, revoked, or not. Will sign your malware with such a cert improve detection, or make it more obvious? Can security software really depend on it, when we have leaked certs - and DLL sideloading? What about self-signed certificates, are they useful at all?

I think some security vendors want to make their life easy, and for performance- and false-positive reasons, will skip signed executable. Reasonable security software would just mostly ignore it.

Conclusion:

  • Sign it and try. I usually dont.

Code/Process injection

Want to inject code into another process? Dont.

There are typically three steps involved:

  • Access the target process (OpenProcess())
  • Allocate and write memory in remote process (VirtualAllocEx(), WriteProcessMemory())
  • Execution primitive (CreateRemoteThread())

EDR will depend on seeing variants of this three things for detection. Cross-process stuff is well scrutanized by the EDR.

Conclusion:

  • If you want to do process injection, skip at least one of the three primitives
  • As a starter, dont do CreateRemoteThread() - find another way
  • Prefer DLL sideloading

“EDR Bypass” / ntdll unhooking

Some EDR’s hook ntdll.dll instead of using ETW. Only bad ones. Many good EDR’s dont use this technique anymore. Including MDE, Elastic, Cortex.

ntdll hooking is obsolete. It always was, and always will be, bypassable with direct- or indirect syscalls, or ntdll recovering or re-patching. The EDR can also just check if their hook’s got removed - it blows my mind this is not standard. Direct- or indirect syscalls can be reliable detected with ETW and callstack analysis, and are a big IOC. The public implementations for in/direct syscalls are also often signatured.

If you have to use ntdll syscalls, include callstack spoofing.

Conclusion:

  • If you work against an obsolete fun EDR which does ntdll hooking, do some non signatured direct- or indirect syscalls implementation with callstack spoofing

ETW Patching

ETW is the Event Tracing for Windows, its like Syslog, or Windows Event Logs. A process can create ETW events by himself: e.g. for performance monitoring, or application specific events. The Windows kernel will also generate ETW events, based on what a process is doing.

Its not possible to disable ETW it, unless you are in the Kernel. You can only stop the application-specific events by patching ETW in the process - which arent that important. Most of the ETW events are not created by the process itself.

    Process                     OS                     EDR       
┌─────────────┐ EtwWrite() ┌──────────┐          ┌──────────────┐
│             ├───────────►│          │          │              │
│             │            │ ────────►│          │              │
│             │            │          │   ETW    │              │
│             │            │          ├─────────►│              │
│             │            │          │          │              │
│             │ syscalls   │ ────────►│          │              │
│             ├───────────►│          │          └──────────────┘
│             │            │          │                          
│             │            └──────────┘                          
│             │                                                  
│             │                                                  
└─────────────┘                                                  

The main confusion comes from the fact that there are “two ETW”: One can be influenced and patched away - the other, with the important data, cannot. Also, AMSI and Defender themselves create many ETW events about what they are doing, which may add to the confusion.

Conclusion:

  • Just dont. Unless you can 100% prove it’s useful

2/99 Virustotal Scan

VirusTotal is mostly static analysis. Which means it scans the file for known signatures. It does not really do a lot of runtime analysis (executing the file), like with a Sandbox or EDR.

VirusTotal can be trivially bypassed by:

  • Encrypting your shellcode
  • Decrypt it without signatured code
  • Add some execution guardrails

Conclusion:

  • If you publish a x/y VT result to prove “FUD”, i know its gonna be bad

Examples

Random examples of loaders i encounter.

Pwntricks

In the blog Bypass Cortexxdr And Sophos Edr Like Real Red Teamer:

  • Patching ETW: ETW not really used here, bad
  • Decrypt with AES: using Windows functions, bad
  • Unhook ntdll: Cortex doesnt do hooking. Sophos does. Still bad
  • Module Stomping: Good
  • Local thread hijacking: Good
  • Custom Havoc C2 profile: Good
  • Sandbox bypass with file bloating: Good

The first three techniques are obsolete and most likely not needed, and only increase detection rate. The last four technique are good and useful, and doing the actual bypass work.

Hunter

https://github.com/S3N4T0R-0X0/Hunter

  • API Unhooking: Not important
  • Syscall Dispatcher: Together with API unhooking, not important
  • ETW Nullification: Not important or helpful
  • Process termination methods: Irrelevant
  • Anti-Analysis: Simple, irrelevant
  • Sandbox Detection: Good!

The only useful part of this project is the Sandbox Detection. The rest increases the detection rate more than reducing it.

How to do it correctly

My proposed shellcode loader architecture:


                                                                 ┌──────────┐                  
                                                                 │ encrypted│                  
                                                                 │ Payload  │                  
                                                                 └────┬─────┘                  
                                                                      │                        
                                                                      │                        
                                                                      ▼                        
┌──────┐    ┌────────────┐    ┌───────────┐    ┌─────────────┐   ┌──────────┐   ┌────────────┐
│ EXE  │    │ Execution  │    │ Anti      │    │EDR          │   │ Alloc RW │   │  Payload   │
│ File ├───►│ Guardrails ├───►│ Emulation ├───►│deconditioner├──►│ Decode/Cp├──►│  Execution │
│      │    │            │    │           │    │             │   │ RX       │   │            │
│      │    │            │    │           │    │             │   │ Exec     │   │            │
└──────┘    └────────────┘    └───────────┘    └─────────────┘   └──────────┘   └────────────┘

Execution Guardrails

Check first if you are on the intended target. For example by checking the ENV variables, if the host is in the correct AD.

This will prohibit middleboxes from executing your code: VirusTotal, Proxy AV, Sandboxes etc. It will only be executed on the target, with its AV and EDR.

Anti Emulation

Many AV will emulate the binary. The AV will interpret the instructions, and scan its memory for known signatures. Your encrypted will be exposed with this.

Emulation will have a cutoff, and stop analysis after X amount of time, or Y amount of instructions executed. So at the start of your loader, do a few 100'000 instructions.

Doing manual decryption of the shellcode may already fulfill the cutoff. This is where the myth of “more encryption means less detection” comes from.

EDR deconditioner

To execute your decrypted shellcode, need to:

  1. Allocate memory RW
  2. Copy shellcode
  3. Change memory permissions to RX
  4. Execute the shellcode

EDR deconditioning does number 1-3, many times, with non-malicious fake data, making the EDR tired of scanning our shit. Then later, do 1-4.

Executing the shellcode

Execute the shellcode as normal as possible. Just jump to the shellcode (jmp).

Do not use execution primitives like CreateThread(). Or, only if you know its not well known (e.g. with a Windows function callbacks).

Putting it together

Do the things i mention above first.

If it still gets detected, the fun begins. Try to think about how the stuff gets detected, and try to bypass it. When you find a solution, take step back and try to think about why it worked - if you assumption was correct. Or if it’s just not being detected anymore for completely unrelated reasons.

For more information, see:

MalDev Course examples

Sektor7

Malware Dev Essentials:

  • PE Intro
  • Droppers
    • Where to store payloads
  • Obfuscating and hiding
    • Shellcode encryption
    • Call obfuscation
  • Backdoors and trojans
    • Backdooring PE
  • Code injection
    • Injecting code into remote processes
    • Loading DLLs into remote processes