wd_extract_sig.cpp
🧩 Syntax:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <filesystem>
#include <stdint.h>
#include <ctype.h>
typedef struct
{
uint8_t sig_type;
uint8_t size_low;
uint16_t size_high;
uint8_t value[1];
} sig_entry;
typedef struct
{
char reversed_0[0xa];
uint16_t nameSize;
char name[1];
} THREAT_BEGIN;
char *ByteToHex(unsigned char *bytes, size_t size)
{
char *out = (char *)malloc(size * 2 + 1);
const char hexChar[] = "0123456789ABCDEF";
if (out != NULL)
{
memset(out, 0, size * 2 + 1);
for (size_t i = 0; i < size; i++)
{
(out)[i * 2 + 0] = hexChar[(bytes[i] >> 4) & 0x0F];
(out)[i * 2 + 1] = hexChar[(bytes[i]) & 0x0F];
}
}
return out;
}
size_t get_sig_size(sig_entry *entry)
{
return entry->size_low | entry->size_high << 8;
}
const char *get_sig_type(uint8_t a1)
{
if (a1 <= 0x9Du)
{
if (a1 == 157)
return "SIGNATURE_TYPE_THREAD_X86";
if (a1 > 0x6Au)
{
if (a1 > 0x86u)
{
if (a1 > 0x90u)
{
switch (a1)
{
case 0x91u:
return "SIGNATURE_TYPE_VDLL_IA64";
case 0x95u:
return "SIGNATURE_TYPE_PEBMPAT";
case 0x96u:
return "SIGNATURE_TYPE_AAGGREGATOR";
case 0x97u:
return "SIGNATURE_TYPE_SAMPLE_REQUEST_BY_NAME";
case 0x98u:
return "SIGNATURE_TYPE_REMOVAL_POLICY_BY_NAME";
case 0x99u:
return "SIGNATURE_TYPE_TUNNEL_X86";
case 0x9Au:
return "SIGNATURE_TYPE_TUNNEL_X64";
case 0x9Bu:
return "SIGNATURE_TYPE_TUNNEL_IA64";
case 0x9Cu:
return "SIGNATURE_TYPE_VDLL_ARM";
}
}
else
{
switch (a1)
{
case 0x90u:
return "SIGNATURE_TYPE_TARGET_SCRIPT_PCODE";
case 0x87u:
return "SIGNATURE_TYPE_PESTATIC";
case 0x88u:
return "SIGNATURE_TYPE_UFSP_DISABLE";
case 0x89u:
return "SIGNATURE_TYPE_FOPEX";
case 0x8Au:
return "SIGNATURE_TYPE_PEPCODE";
case 0x8Bu:
return "SIGNATURE_TYPE_IL_PATTERN";
case 0x8Cu:
return "SIGNATURE_TYPE_ELFHSTR_EXT";
case 0x8Du:
return "SIGNATURE_TYPE_MACHOHSTR_EXT";
case 0x8Eu:
return "SIGNATURE_TYPE_DOSHSTR_EXT";
case 0x8Fu:
return "SIGNATURE_TYPE_MACROHSTR_EXT";
}
}
}
else
{
if (a1 == 134)
return "SIGNATURE_TYPE_PEMAIN_LOCATOR";
if (a1 > 0x79u)
{
switch (a1)
{
case 0x7Au:
return "SIGNATURE_TYPE_VERSIONCHECK";
case 0x7Bu:
return "SIGNATURE_TYPE_SAMPLE_REQUEST";
case 0x7Cu:
return "SIGNATURE_TYPE_VDLL_X64";
case 0x7Eu:
return "SIGNATURE_TYPE_SNID";
case 0x7Fu:
return "SIGNATURE_TYPE_FOP";
case 0x80u:
return "SIGNATURE_TYPE_KCRCE";
case 0x83u:
return "SIGNATURE_TYPE_VFILE";
case 0x84u:
return "SIGNATURE_TYPE_SIGFLAGS";
case 0x85u:
return "SIGNATURE_TYPE_PEHSTR_EXT2";
}
}
else
{
switch (a1)
{
case 'y':
return "SIGNATURE_TYPE_VDLL_X86";
case 'k':
return "SIGNATURE_TYPE_WVT_EXCEPTION";
case 'l':
return "SIGNATURE_TYPE_REVOKED_CERTIFICATE";
case 'p':
return "SIGNATURE_TYPE_TRUSTED_PUBLISHER";
case 'q':
return "SIGNATURE_TYPE_ASEP_FILEPATH";
case 's':
return "SIGNATURE_TYPE_DELTA_BLOB";
case 't':
return "SIGNATURE_TYPE_DELTA_BLOB_RECINFO";
case 'u':
return "SIGNATURE_TYPE_ASEP_FOLDERNAME";
case 'w':
return "SIGNATURE_TYPE_PATTMATCH_V2";
case 'x':
return "SIGNATURE_TYPE_PEHSTR_EXT";
}
}
}
}
else
{
if (a1 == 106)
return "SIGNATURE_TYPE_REMOVAL_POLICY";
if (a1 > 0x4Au)
{
if (a1 > 0x5Du)
{
switch (a1)
{
case '^':
return "SIGNATURE_TYPE_FILENAME";
case '_':
return "SIGNATURE_TYPE_FILEPATH";
case '`':
return "SIGNATURE_TYPE_FOLDERNAME";
case 'a':
return "SIGNATURE_TYPE_PEHSTR";
case 'b':
return "SIGNATURE_TYPE_LOCALHASH";
case 'c':
return "SIGNATURE_TYPE_REGKEY";
case 'd':
return "SIGNATURE_TYPE_HOSTSENTRY";
case 'g':
return "SIGNATURE_TYPE_STATIC";
case 'i':
return "SIGNATURE_TYPE_LATENT_THREAT";
}
}
else
{
switch (a1)
{
case ']':
return "SIGNATURE_TYPE_THREAT_END";
case 'P':
return "SIGNATURE_TYPE_CKSIMPLEREC";
case 'Q':
return "SIGNATURE_TYPE_PATTMATCH";
case 'S':
return "SIGNATURE_TYPE_RPFROUTINE";
case 'U':
return "SIGNATURE_TYPE_NID";
case 'V':
return "SIGNATURE_TYPE_GENSFX";
case 'W':
return "SIGNATURE_TYPE_UNPLIB";
case 'X':
return "SIGNATURE_TYPE_DEFAULTS";
case '[':
return "SIGNATURE_TYPE_DBVAR";
case '\\':
return "SIGNATURE_TYPE_THREAT_BEGIN";
}
}
}
else
{
if (a1 == 74)
return "SIGNATURE_TYPE_TARGET_SCRIPT";
if (a1 > 0x2Cu)
{
switch (a1)
{
case '0':
return "SIGNATURE_TYPE_TITANFLT";
case '=':
return "SIGNATURE_TYPE_PEFILE_CURE";
case '>':
return "SIGNATURE_TYPE_MAC_CURE";
case '@':
return "SIGNATURE_TYPE_SIGTREE";
case 'A':
return "SIGNATURE_TYPE_SIGTREE_EXT";
case 'B':
return "SIGNATURE_TYPE_MACRO_PCODE";
case 'C':
return "SIGNATURE_TYPE_MACRO_SOURCE";
case 'D':
return "SIGNATURE_TYPE_BOOT";
case 'I':
return "SIGNATURE_TYPE_CLEANSCRIPT";
}
}
else
{
switch (a1)
{
case 0x2Cu:
return "SIGNATURE_TYPE_NSCRIPT_CURE";
case 1u:
return "SIGNATURE_TYPE_RESERVED";
case 2u:
return "SIGNATURE_TYPE_VOLATILE_THREAT_INFO";
case 3u:
return "SIGNATURE_TYPE_VOLATILE_THREAT_ID";
case 0x11u:
return "SIGNATURE_TYPE_CKOLDREC";
case 0x20u:
return "SIGNATURE_TYPE_KVIR32";
case 0x21u:
return "SIGNATURE_TYPE_POLYVIR32";
case 0x27u:
return "SIGNATURE_TYPE_NSCRIPT_NORMAL";
case 0x28u:
return "SIGNATURE_TYPE_NSCRIPT_SP";
case 0x29u:
return "SIGNATURE_TYPE_NSCRIPT_BRUTE";
}
}
}
}
return "SIGNATURE_TYPE_UNKNOWN";
}
if (a1 <= 0xC6u)
{
if (a1 == 198)
return "SIGNATURE_TYPE_MSILFOPEX";
if (a1 > 0xB1u)
{
if (a1 > 0xBCu)
{
switch (a1)
{
case 0xBDu:
return "SIGNATURE_TYPE_LUASTANDALONE";
case 0xBEu:
return "SIGNATURE_TYPE_DEXHSTR_EXT";
case 0xBFu:
return "SIGNATURE_TYPE_JAVAHSTR_EXT";
case 0xC0u:
return "SIGNATURE_TYPE_MAGICCODE";
case 0xC1u:
return "SIGNATURE_TYPE_CLEANSTORE_RULE";
case 0xC2u:
return "SIGNATURE_TYPE_VDLL_CHECKSUM";
case 0xC3u:
return "SIGNATURE_TYPE_THREAT_UPDATE_STATUS";
case 0xC4u:
return "SIGNATURE_TYPE_VDLL_MSIL";
case 0xC5u:
return "SIGNATURE_TYPE_ARHSTR_EXT";
}
}
else
{
switch (a1)
{
case 0xBCu:
return "SIGNATURE_TYPE_KPATEX";
case 0xB2u:
return "SIGNATURE_TYPE_VFILEEX";
case 0xB3u:
return "SIGNATURE_TYPE_SIGTREE_BM";
case 0xB4u:
return "SIGNATURE_TYPE_VBFOP";
case 0xB5u:
return "SIGNATURE_TYPE_VDLL_META";
case 0xB6u:
return "SIGNATURE_TYPE_TUNNEL_ARM";
case 0xB7u:
return "SIGNATURE_TYPE_THREAD_ARM";
case 0xB8u:
return "SIGNATURE_TYPE_PCODEVALIDATOR";
case 0xBAu:
return "SIGNATURE_TYPE_MSILFOP";
case 0xBBu:
return "SIGNATURE_TYPE_KPAT";
}
}
}
else
{
if (a1 == 177)
return "SIGNATURE_TYPE_NISBLOB";
if (a1 > 0xA7u)
{
switch (a1)
{
case 0xA8u:
return "SIGNATURE_TYPE_BM_INFO";
case 0xA9u:
return "SIGNATURE_TYPE_NDAT";
case 0xAAu:
return "SIGNATURE_TYPE_FASTPATH_DATA";
case 0xABu:
return "SIGNATURE_TYPE_FASTPATH_SDN";
case 0xACu:
return "SIGNATURE_TYPE_DATABASE_CERT";
case 0xADu:
return "SIGNATURE_TYPE_SOURCE_INFO";
case 0xAEu:
return "SIGNATURE_TYPE_HIDDEN_FILE";
case 0xAFu:
return "SIGNATURE_TYPE_COMMON_CODE";
case 0xB0u:
return "SIGNATURE_TYPE_VREG";
}
}
else
{
switch (a1)
{
case 0xA7u:
return "SIGNATURE_TYPE_BM_STATIC";
case 0x9Eu:
return "SIGNATURE_TYPE_THREAD_X64";
case 0x9Fu:
return "SIGNATURE_TYPE_THREAD_IA64";
case 0xA0u:
return "SIGNATURE_TYPE_FRIENDLYFILE_SHA256";
case 0xA1u:
return "SIGNATURE_TYPE_FRIENDLYFILE_SHA512";
case 0xA2u:
return "SIGNATURE_TYPE_SHARED_THREAT";
case 0xA3u:
return "SIGNATURE_TYPE_VDM_METADATA";
case 0xA4u:
return "SIGNATURE_TYPE_VSTORE";
case 0xA5u:
return "SIGNATURE_TYPE_VDLL_SYMINFO";
case 0xA6u:
return "SIGNATURE_TYPE_IL2_PATTERN";
}
}
}
return "SIGNATURE_TYPE_UNKNOWN";
}
if (a1 <= 0xDAu)
{
if (a1 == 218)
return "SIGNATURE_TYPE_FASTPATH_SDN_EX";
if (a1 > 0xD0u)
{
switch (a1)
{
case 0xD1u:
return "SIGNATURE_TYPE_SWFHSTR_EXT";
case 0xD2u:
return "SIGNATURE_TYPE_REWSIGS";
case 0xD3u:
return "SIGNATURE_TYPE_AUTOITHSTR_EXT";
case 0xD4u:
return "SIGNATURE_TYPE_INNOHSTR_EXT";
case 0xD5u:
return "SIGNATURE_TYPE_CERT_STORE_ENTRY";
case 0xD6u:
return "SIGNATURE_TYPE_EXPLICITRESOURCE";
case 0xD7u:
return "SIGNATURE_TYPE_CMDHSTR_EXT";
case 0xD8u:
return "SIGNATURE_TYPE_FASTPATH_TDN";
case 0xD9u:
return "SIGNATURE_TYPE_EXPLICITRESOURCEHASH";
}
}
else
{
switch (a1)
{
case 0xD0u:
return "SIGNATURE_TYPE_BRUTE";
case 0xC7u:
return "SIGNATURE_TYPE_VBFOPEX";
case 0xC8u:
return "SIGNATURE_TYPE_FOP64";
case 0xC9u:
return "SIGNATURE_TYPE_FOPEX64";
case 0xCAu:
return "SIGNATURE_TYPE_JSINIT";
case 0xCBu:
return "SIGNATURE_TYPE_PESTATICEX";
case 0xCCu:
return "SIGNATURE_TYPE_KCRCEX";
case 0xCDu:
return "SIGNATURE_TYPE_FTRIE_POS";
case 0xCEu:
return "SIGNATURE_TYPE_NID64";
case 0xCFu:
return "SIGNATURE_TYPE_MACRO_PCODE64";
}
}
return "SIGNATURE_TYPE_UNKNOWN";
}
if (a1 <= 0xE5u)
{
switch (a1)
{
case 0xE5u:
return "SIGNATURE_TYPE_SNIDEX";
case 0xDBu:
return "SIGNATURE_TYPE_BLOOM_FILTER";
case 0xDCu:
return "SIGNATURE_TYPE_RESEARCH_TAG";
case 0xDEu:
return "SIGNATURE_TYPE_ENVELOPE";
case 0xDFu:
return "SIGNATURE_TYPE_REMOVAL_POLICY64";
case 0xE0u:
return "SIGNATURE_TYPE_REMOVAL_POLICY64_BY_NAME";
case 0xE1u:
return "SIGNATURE_TYPE_VDLL_META_X64";
case 0xE2u:
return "SIGNATURE_TYPE_VDLL_META_ARM";
case 0xE3u:
return "SIGNATURE_TYPE_VDLL_META_MSIL";
case 0xE4u:
return "SIGNATURE_TYPE_MDBHSTR_EXT";
}
return "SIGNATURE_TYPE_UNKNOWN";
}
switch (a1)
{
case 0xE6u:
return "SIGNATURE_TYPE_SNIDEX2";
case 0xE7u:
return "SIGNATURE_TYPE_AAGGREGATOREX";
case 0xE8u:
return "SIGNATURE_TYPE_PUA_APPMAP";
case 0xE9u:
return "SIGNATURE_TYPE_PROPERTY_BAG";
case 0xEAu:
return "SIGNATURE_TYPE_DMGHSTR_EXT";
case 0xEBu:
return "SIGNATURE_TYPE_DATABASE_CATALOG";
}
if (a1 != 236)
{
if (a1 == 237)
return "SIGNATURE_TYPE_BM_ENV_VAR_MAP";
return "SIGNATURE_TYPE_UNKNOWN";
}
return "SIGNATURE_TYPE_DATABASE_CERT2";
}
size_t get_file_size(FILE *h_file)
{
size_t size = 0;
fseek(h_file, 0L, SEEK_END);
size = ftell(h_file);
rewind(h_file);
return size;
}
#if defined(WIN32)
#define DIR_SEPARATOR '\\'
#else
#define DIR_SEPARATOR '/'
#endif
void fix_file_name(char *fileName)
{
int len = strlen(fileName);
for (int i = 0; i < len; i++)
{
if (!isprint(fileName[i]))
{
fileName[i] = '_';
}
}
return;
}
#pragma pack(push, 1)
typedef struct string_data
{
uint16_t reversed0;
unsigned char string_size;
unsigned char str[1];
} string_data;
typedef struct PE_HSTR_ALL
{
uint16_t count_1;
uint16_t count_2;
uint16_t count_3;
char reversed_0;
string_data s_data[1];
} PE_HSTR_ALL, *PPE_HSTR_ALL;
#pragma pack(pop)
void simple_str(char *str, size_t size)
{
for (size_t i = 0; i < size; i++)
{
if (!isprint(str[i]))
{
str[i] = '_';
}
}
}
void print_pehstr_sig(char *pehstrdata, size_t size)
{
size_t ptrSize = 0;
int strSize = 0;
PPE_HSTR_ALL pehstr = (PPE_HSTR_ALL)(pehstrdata + ptrSize);
printf("\nCount1: %x, count2: %x, count3: %x", pehstr->count_1, pehstr->count_2, pehstr->count_3);
do
{
strSize = 0;
string_data *sdata = (string_data *)((char *)(&pehstr->s_data) + ptrSize);
if (sdata->reversed0 == 0)
{
break;
}
printf("\n\t%02x--%02x: ", sdata->reversed0, sdata->string_size);
strSize = sdata->string_size;
char *str = (char *)malloc(strSize + 1);
memset(str, 0, strSize + 1);
memcpy(str, sdata->str, strSize);
simple_str(str, strSize);
printf("%s", str);
free(str);
ptrSize += sizeof(string_data) + strSize - 1;
} while (1);
}
size_t print_sig(unsigned char *out_buffer, char *threatName, sig_entry *entry)
{
size_t nWrite = 0;
const char *sigtype = get_sig_type(entry->sig_type);
size_t sigSize = get_sig_size(entry);
if (entry->sig_type == 0x61)
{
print_pehstr_sig((char *)entry->value, sigSize);
}
char *data = ByteToHex(entry->value, sigSize);
if (data != NULL)
{
nWrite = sprintf((char*)out_buffer, "\"%s\",\"%s\",\"%s\"\r\n", threatName, sigtype, data);
free(data);
}
return nWrite;
}
int main(int argc, char *argv[])
{
if (argc != 3)
{
printf("\nUsage:");
printf("\n%s [vmd_base] [out_folder]", argv[0]);
printf("\nEg.");
printf("\nwdextract.exe mpavdlta.vdm");
printf("\n%s mpavdlta.vdm.extracted mpavdlta_vdm_data", argv[0]);
// for (int i = 0; i < 0xff; i++)
// {
// const char *type = get_sig_type(i);
// if (strcmp(type, "SIGNATURE_TYPE_UNKNOWN") != 0)
// {
// printf("\n0x%02x:%s", i, get_sig_type(i));
// }
// }
return -1;
}
FILE *h_file = NULL;
FILE *out_file = NULL;
size_t i = 0;
sig_entry *entry = NULL;
int sig_enum[0xff] = {0};
char threatName[0x100] = {0};
char sig_out_file[0x100] = {0};
char pehstr_sig_out_file[0x100] = {0};
size_t threat_index = 0;
char *file_path = argv[1];
char *out_folder = argv[2];
unsigned char *out_buf = (unsigned char *)malloc(536870912 * 2); // 1024 MB. Hope no overflow
unsigned char *pehstr_buf = (unsigned char *)malloc(536870912); // 1024 MB. Hope no overflow
unsigned char *threatBegin = NULL;
size_t nPEHstrSig = 0;
size_t nOtherSig = 0;
size_t threat_length = 0;
size_t out_length = 0;
if (out_buf == NULL)
{
return -1;
}
if (pehstr_buf == NULL) {
free(out_buf);
return -1;
}
// to lazyyy
std::filesystem::create_directories(out_folder);
sprintf(sig_out_file, "%s%c%s.csv", out_folder, DIR_SEPARATOR, strrchr(file_path, DIR_SEPARATOR) + 1);
sprintf(pehstr_sig_out_file, "%s%cpehstr_%s.csv", out_folder, DIR_SEPARATOR, strrchr(file_path, DIR_SEPARATOR) + 1);
h_file = fopen(file_path, "rb");
if (h_file)
{
size_t file_size = get_file_size(h_file);
unsigned char *buf = (unsigned char *)malloc(file_size);
if (buf)
{
fread(buf, file_size, 1, h_file);
do
{
memset(threatName, 0, sizeof(threatName));
entry = (sig_entry *)(buf + i);
sig_enum[entry->sig_type] += 1;
threatBegin = NULL;
threat_length = 0;
nPEHstrSig = 0;
nOtherSig = 0;
if (entry->sig_type == 0x5c) // threat_begin
{
THREAT_BEGIN *threat = (THREAT_BEGIN *)(entry->value);
memcpy(threatName, threat->name, threat->nameSize);
fix_file_name(threatName);
printf("\nThreat: %s", threatName);
threatBegin = out_buf + out_length;
out_length += print_sig(out_buf + out_length, threatName, entry);
do
{
i += sizeof(entry->sig_type) + sizeof(entry->size_low) + sizeof(entry->size_high);
i += get_sig_size(entry);
entry = (sig_entry *)(buf + i);
sig_enum[entry->sig_type] += 1;
out_length += print_sig(out_buf + out_length, threatName, entry);
if (entry->sig_type == 0x61)
{
nPEHstrSig += 1;
}
else if (entry->sig_type != 0x5d)
{
nOtherSig += 1;
}
} while (entry->sig_type != 0x5d); // threat end
threat_length = out_buf + out_length - threatBegin;
if (nPEHstrSig != 0 && nOtherSig == 0)
{
memcpy(pehstr_buf + threat_index, threatBegin, threat_length);
threat_index += threat_length;
}
}
i += sizeof(entry->sig_type) + sizeof(entry->size_low) + sizeof(entry->size_high);
i += get_sig_size(entry);
} while (i < file_size);
free(buf);
for (int j = 0; j < 0xff; j++)
{
if (sig_enum[j] > 0)
{
printf("\n0x%08x: 0x%08x_%s", sig_enum[j], j, get_sig_type(j));
}
}
char header[] = "threat_name,sig_type,sig_data\r\n";
if ((out_file = fopen(sig_out_file, "wb")) == NULL)
{
return -1;
}
fwrite(header, strlen(header), 1, out_file);
fwrite(out_buf, out_length, 1, out_file);
fclose(out_file);
if (threat_index > 0)
{
FILE *outpe_file = fopen(pehstr_sig_out_file, "wb");
fwrite(header, strlen(header), 1, outpe_file);
fwrite(pehstr_buf, threat_index, 1, outpe_file);
fclose(outpe_file);
}
}
fclose(h_file);
}
else
{
printf("\nRead file error");
}
free(out_buf);
free(pehstr_buf);
return 0;
}
// g++ .\extract_sig.cpp -o .\extract_sig.exe -std=c++17 -Wall -lstdc++fs
// g++ .\extract_sig.cpp -o .\extract_sig.out -std=c++17 -Wall -lstdc++fs