Detecting Suspicious API Usage with YARA Rules
YARA[1] is a beautiful tool for malware researchers and incident responders. No need to present it again. It became a standard tool to add to your arsenal. While teaching FOR610 (Malware Analysis & Reverse Engineering), a student asked me how to detect specific API calls with dangerous parameters during the triage phase. This phase will help you quickly assess the malware sample and help you decide how to perform the following steps.
A classic suspicious API call/parameter combo is VirtualAlloc() with the value 0x40 passed as flProtect parameter. This value corresponds to PAGE_EXECUTE_READWRITE[2]. If you see this, it means that the program will allocate some new memory that will contain executable code. This is a typical step to load a shell code in memory and execute it.
In the example below, the malware uses this technique, and we can detect the call to VirtualAlloc():
remnux@remnux:~$ capa -vv WinHost32.exe? ... allocate RWX memory (2 matches) namespace host-interaction/process/inject author moritz.raabe@fireeye.com scope basic block mbc Memory::Allocate Memory [C0007] examples Practical Malware Analysis Lab 03-03.exe_:0x4010EA, 563653399B82CD443F120ECEFF836EA3678D4CF11D9B351BB737573C2D856299:0x140001ABA basic block @ 0x401000 and: match: allocate memory @ 0x401000 or: api: kernel32.VirtualAlloc @ 0x401077 number: 0x40 = PAGE_EXECUTE_READWRITE @ 0x401068 basic block @ 0x4021EE and: match: allocate memory @ 0x4021EE or: api: kernel32.VirtualAllocEx @ 0x40220D number: 0x40 = PAGE_EXECUTE_READWRITE @ 0x402203 ...
They are two calls to VirtualAlloc. The first one is located at 0x401000:
remnux@remnux:~$ objdump -d WinHost32.exe
WinHost32.exe: file format pei-i386
Disassembly of section .text:
00401000 <.text>:
...
401068: 6a 40 push 0x40
40106a: 68 00 30 00 00 push 0x3000
40106f: 50 push eax
401070: 6a 00 push 0x0
401072: a3 94 ec 40 00 mov ds:0x40ec94,eax
401077: ff 15 b8 b1 40 00 call DWORD PTR ds:0x40b1b8
...
VirtualAlloc() expects four parameters. In a 32bits architecture, they are passed on the stack from write to left. The last one (flProtect) is pushed on the stack at 0x401068. How to read this code:
VirtualAlloc(0, EAX_value, 0x3000, 0x40)
How to detect this with the help of a YARA? Here is a very simple rule:
rule VirtualAlloc40 { meta: description = “Simple rule to detect PAGE_EXECUTE_READWRITE memory allocation” strings: $hex_string = { 6A 40 68 00 30 00 00 [5-15] (FF 15 | E8 ) } condition: $hex_string }
I’m looking for the following code (see the objdump output above)
- push a byte (0x6A) on the stack: 0x40
- push a dword (0x68) on the stack: 0x00003000
- a suite of 5 to 10 bytes (because the remaining parameters may be something else)
- call an address (where VirtualAlloc is loaded)
This rule gave me good results, but it remains basic. Indeed, it won’t detect simple obfuscation like this:
mov ecx, 0x40 push ecx push 0x3000 ...
If you've ideas to improve this simple rule or another interesting API call/parameter combination (example: CreateProcess / SUSPENDED_MODE), please share them with us!
[1] https://yara.readthedocs.io/en/latest/
[2] https://learn.microsoft.com/en-us/windows/win32/Memory/memory-protection-constants
Xavier Mertens (@xme)
Xameco
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key
Reverse-Engineering Malware: Malware Analysis Tools and Techniques | Frankfurt | Dec 9th - Dec 14th 2024 |
Comments
Anonymous
Apr 14th 2023
1 year ago