Day 4 of 100 Discontiguous Days of YARA
Improving YARA writing skills by writing more YARA rules.
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:
Looking at the bytes in a hexeditor, the GUID consists of these hex digits in green.
For those who are curious, here is how those bytes are interpreted.
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 asf590
// 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: