UM Virus Detecting: Part 2 - Sigs

Good morning! It's me, seb here again. Last time we talked about import scanning to catch usermode viruses. Today, let’s break down signature scanning, hunting for malware’s fingerprints inside the raw bytes of a file.


First, I open the file so I can read its contents:

HANDLE hFile = CreateFileW(filePath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) return false;

No file, no scan so pretty basic.


Next, I filter files by size. This is important because Easy SuperInfector stubs I’m hunting are usually about 20 - 150KB. Filtering helps me ignore tiny junk and huge files that aren’t relevant to make scanning faster:

DWORD fileSize = GetFileSize(hFile, NULL);
DWORD minFileSize = 0x1000; // 4kb, ignore smaller
DWORD maxFileSize = 20 * 1024 * 1024; // 20mb max, ignore huge files

if (fileSize == INVALID_FILE_SIZE || fileSize < minFileSize || fileSize > maxFileSize) {
    CloseHandle(hFile);
    return false;
}

After that, I map the file into memory. This way, I can scan the bytes super fast, without reading piece by piece:

HANDLE hMapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (!hMapping) {
    CloseHandle(hFile);
    return false;
}

LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
if (!pBase) {
    CloseHandle(hMapping);
    CloseHandle(hFile);
    return false;
}

Now I search for a specific XOR key pattern I found by reversing multiple stubs and found they each have this:

If it’s not there, the file probably isn’t Easy SuperInfector.


After confirming the XOR pattern, I look inside the PE sections to find executable code:

I limit scanning to the first 20 sections to keep it efficient.


For each section, I check if it’s executable by testing flags:


Before scanning, I make sure pointers to section data are valid:


Inside these sections, I scan for two more patterns:

The first is a stack alignment opcode malware uses. The second is a push of 5000 milliseconds, meaning the malware sleeps for 5 seconds, a common trick to avoid detection in VirusTotal.


If both patterns are found in executable sections, I’m confident this is the malware I want.


Finally, I clean up everything by unmapping and closing handles:

Always important to avoid leaks.


Signature scanning is solid for known malware, but it falls apart if the malware uses packing or obfuscation to hide these patterns. That’s why I’m layering detection methods such as imports, signatures, and soon hooking and runtime checks.

Last updated