xorhex logo

xorhex

Focus on Threat Research through malware reverse engineering

Day 4 of 100 Discontiguous Days of YARA

Improving YARA writing skills by writing more YARA rules.

xorhex

3-Minute Read

#100DaysOfDiscontiguousDaysOfYARA

Summary

Partaking in Greg’s #100DaysOfYARA, but to be honest it’s more likely to be #100DiscontiguousDaysOfYARA for me - if I make it that far.

I doubt that the rules shared these 100 days will contain any truly original ideas, but I’d still like to share what I’ve learned.

Day 4

import "pe"

rule pdb_guid{
    meta:
        Author = "xorhex"
        Description = "Search for a PDB Guid String"
        PDB_guid = "dcabb77e-c56c-4f3a-90f5-e604e0d01a87"
        HundredDaysOfYARA = "Day 4"
    condition:
            // RSDS Sig
            uint32(uint32(pe.rva_to_offset(pe.data_directories[pe.IMAGE_DIRECTORY_ENTRY_DEBUG].virtual_address)+ (6*4))) == 0x53445352
        and
            // GUID dcabb77e-____-____-____-____________
            uint32(uint32(pe.rva_to_offset(pe.data_directories[pe.IMAGE_DIRECTORY_ENTRY_DEBUG].virtual_address)+ (6*4)) + 4 ) == 0xdcabb77e
        and
            // GUID ________-c56c-____-____-____________
            uint16(uint32(pe.rva_to_offset(pe.data_directories[pe.IMAGE_DIRECTORY_ENTRY_DEBUG].virtual_address)+ (6*4)) + 8 ) == 0xc56c
        and
            // GUID ________-____-4f3a-____-____________
            uint16(uint32(pe.rva_to_offset(pe.data_directories[pe.IMAGE_DIRECTORY_ENTRY_DEBUG].virtual_address)+ (6*4)) + 10 ) == 0x4f3a
        and
            // GUID ________-____-____-90f5-____________ (According to VT)
            uint16be(uint32(pe.rva_to_offset(pe.data_directories[pe.IMAGE_DIRECTORY_ENTRY_DEBUG].virtual_address)+ (6*4)) + 12 ) == 0x90f5
        and
            // GUID ________-____-____-____-e604e0d0____
            uint32be(uint32(pe.rva_to_offset(pe.data_directories[pe.IMAGE_DIRECTORY_ENTRY_DEBUG].virtual_address)+ (6*4)) + 14 ) == 0xe604e0d0 
        and
            // GUID ________-____-____-____-________1a87
            uint16be(uint32(pe.rva_to_offset(pe.data_directories[pe.IMAGE_DIRECTORY_ENTRY_DEBUG].virtual_address)+ (6*4)) + 18 ) == 0x1a87
}

The PDB GUID value is not currently exposed via the YARA PE module. While THE PDB GUID has limited pivoting ability due to the fact that this value get recreated by the linker each time the file is compiled, I’m curious what I can find with it. First step, figure out how to capture this in YARA.

GUID Representation

Looking at VT, this is how the value is represented:

VT PDB GUID

Looking at the bytes in a hexeditor, the GUID consists of these hex digits in green.

ImHex HexView

HexView

For those who are curious, here is how those bytes are interpreted.

ImHex Pattern

Pattern

Locating the Start of the CodeView

The PDB values are stored in the CodeView. The CodeView is located in the debug directory and starts with the signature RSDS. To capture this in YARA, make use of the YARA PE module to locate the debug directory and confirm that the signature found 24 bytes from the start of the directory is RSDS:

uint32(uint32(pe.rva_to_offset(pe.data_directories[pe.IMAGE_DIRECTORY_ENTRY_DEBUG].virtual_address)+ (6*4))) == 0x53445352

Next take the values from the GUID and compare the bytes following the signature using uint32, uint16, uint16be, and uint32be.

First Half of the GUID

GUID Part 1

// GUID dcabb77e-____-____-____-____________
uint32(uint32(pe.rva_to_offset(pe.data_directories[pe.IMAGE_DIRECTORY_ENTRY_DEBUG].virtual_address)+ (6*4)) + 4 ) == 0xdcabb77e

GUID Part 2

// GUID ________-c56c-____-____-____________
uint16(uint32(pe.rva_to_offset(pe.data_directories[pe.IMAGE_DIRECTORY_ENTRY_DEBUG].virtual_address)+ (6*4)) + 8 ) == 0xc56c

GUID Part 3

// GUID ________-____-4f3a-____-____________
uint16(uint32(pe.rva_to_offset(pe.data_directories[pe.IMAGE_DIRECTORY_ENTRY_DEBUG].virtual_address)+ (6*4)) + 10 ) == 0x4f3a

Second Half of the GUID

Add be to the end of the remaining uintX as the order of the bytes display changes for the remainder of the GUID.

GUID Part 4

Careful: When viewing the fourth part of the GUID, different tools will represent this differently. VirusTotal shows it like 90f5 but other tools like PE-Bear and this issue on LIEF show it as f590

// GUID ________-____-____-90f5-____________ (According to VT)
uint16be(uint32(pe.rva_to_offset(pe.data_directories[pe.IMAGE_DIRECTORY_ENTRY_DEBUG].virtual_address)+ (6*4)) + 12 ) == 0x90f5

GUID Part 5

// GUID ________-____-____-____-e604e0d0____
uint32be(uint32(pe.rva_to_offset(pe.data_directories[pe.IMAGE_DIRECTORY_ENTRY_DEBUG].virtual_address)+ (6*4)) + 14 ) == 0xe604e0d0 
// GUID ________-____-____-____-________1a87
uint16be(uint32(pe.rva_to_offset(pe.data_directories[pe.IMAGE_DIRECTORY_ENTRY_DEBUG].virtual_address)+ (6*4)) + 18 ) == 0x1a87

And that’s it! For those that want to read more about the PDB check out:

Recent Posts

Categories

About

Hosting my custom tools, threat research, and general reverse engineering notes.