Skip to content

Instantly share code, notes, and snippets.

@dmknght
Created October 30, 2023 23:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dmknght/3d415f535669aca1ff9f803bceda2e81 to your computer and use it in GitHub Desktop.
Save dmknght/3d415f535669aca1ff9f803bceda2e81 to your computer and use it in GitHub Desktop.
Read, Extract, Merge extracted db of Windows Defender
/*
Forked from https://github.com/hongson11698/defender-database-extract/
- Fixed some buffer overflow in sprintf
- Compile: g++ extract_sig.cpp -o extract_sig -Wall -lstdc++fs
- Usage: ./extract_sig <dir to write result> <extracted av/as base> <optional: extracted av/as dlta>
If both av and dlta is defined, the program will merge both of them to make a final db
*/
#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
{
// SignatureHeader header;
// unsigned int Id; // u32
// // u16: Unknown1
// // u16 Counter
// u16: category
uint32_t Id;
uint16_t Unknown1;
uint16_t Counter;
uint16_t Category;
uint16_t nameSize;
char name[1];
// u16 unknown2,
// u16: Resouces[Counter]
// u8: Sevirity
// u8: Action;
// u8: Unknown3[4];
} THREAT_BEGIN;
#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;
typedef struct LUA_STANDALONE
{
uint16_t Type;
uint16_t DescSize;
uint32_t LUASize;
unsigned char data[1];
} LUA_STANDALONE, *PLUA_STANDALONE;
typedef struct delta_blob
{
unsigned int mergeSize;
unsigned int mergeCrc;
unsigned char data_blob[1];
} delta_blob, *pdelta_blob;
#pragma pack(pop)
#if defined(WIN32)
#define DIR_SEPARATOR '\\'
#else
#define DIR_SEPARATOR '/'
#endif
// global variable
char *out_folder = NULL;
unsigned char *lua_buffer = NULL;
size_t lua_buffer_index = 0;
unsigned char *friendly_buffer = NULL;
size_t friendly_buffer_index = 0;
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;
}
void fix_file_name(char *fileName)
{
int len = strlen(fileName);
for (int i = 0; i < len; i++)
{
if (!isprint(fileName[i]))
{
fileName[i] = '_';
}
}
return;
}
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)
{
int strSize = 0;
size_t ptrSize = 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);
}
void print_lua_signature(char *threatName, char *lua_data, size_t size)
{
size_t nWrite = 0;
size_t ptrSize = 0;
char *catag = NULL;
char temp[0x1000] = {0};
PLUA_STANDALONE plua_standard = (PLUA_STANDALONE)(lua_data + ptrSize);
if (plua_standard->DescSize == 0)
{
catag = (char*)"Unknowcategory";
ptrSize = 0;
}
else
{
memset(temp, 0, 0x1000);
strncpy(temp, (const char *)plua_standard->data, plua_standard->DescSize);
catag = temp;
ptrSize = plua_standard->DescSize;
}
do
{
if (memcmp(plua_standard->data + ptrSize, "\x1b\x4c\x75\x61\x51", 5) == 0)
{
break;
}
ptrSize += 1;
} while (1);
// printf("\n%s :LUA: %02x - %s", threatName, plua_standard->Type, catag);
char *data = ByteToHex(plua_standard->data + ptrSize, plua_standard->LUASize);
if (data != NULL)
{
// threat,lua_attr,category,hexdata
nWrite = sprintf((char *)lua_buffer + lua_buffer_index, "\"%s\",\"0x%04x\",\"%s\",\"%d\",\"%s\"\r\n", threatName, plua_standard->Type, catag, plua_standard->LUASize,
data);
lua_buffer_index += nWrite;
free(data);
}
}
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 == 0xA1 || entry->sig_type == 0xA0)
{
char *data_hash = ByteToHex(entry->value, sigSize);
nWrite = sprintf((char *)friendly_buffer + friendly_buffer_index, "\"%s\",\"%s\"\r\n", sigtype, data_hash);
friendly_buffer_index += nWrite;
free(data_hash);
}
if (entry->sig_type == 0x61)
{
// print_pehstr_sig((char *)entry->value, sigSize);
}
if (entry->sig_type == 0xBD)
{
print_lua_signature(threatName, (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;
}
char GetMSB(short num)
{
short msb;
msb = 1 << (sizeof(num) * 8 - 1);
if (num & msb)
{
return 1;
}
return 0;
}
unsigned char *get_delta_blob_sig(unsigned char *dt_data)
{
sig_entry *entry_delta = (sig_entry *)dt_data;
// printf("%s", get_sig_type(entry_delta->sig_type));
size_t s = get_sig_size(entry_delta);
return (unsigned char *)(dt_data + s + sizeof(entry_delta->sig_type) + sizeof(entry_delta->size_low) + sizeof(entry_delta->size_high));
}
unsigned char *delta_patch(char *outfile, size_t *outSize, unsigned char *delta, size_t dsize, unsigned char *base, size_t size)
{
size_t index = 0;
unsigned char *databuf = NULL;
size_t databuf_size = 0;
sig_entry *entry_delta_blob = (sig_entry *)get_delta_blob_sig(delta);
unsigned short sizeX = 0;
size_t cSize = 0;
size_t blob_size = get_sig_size(entry_delta_blob);
delta_blob *blob = (delta_blob *)entry_delta_blob->value;
printf("\nMerge delta database...");
printf("\nMergeSize: %d - CRC: %x", blob->mergeSize, blob->mergeCrc);
unsigned char *deta_blob = blob->data_blob;
databuf = (unsigned char *)malloc(dsize + size);
do
{
// printf("\nIndex: 0x%x", index);
sizeX = *(unsigned short *)(deta_blob + index);
index += 2;
if (GetMSB(sizeX))
{
unsigned int offset = *(unsigned int *)(deta_blob + index);
cSize = (sizeX & 0x7fff) + 6;
// printf("\nAppend 0x%08x bytes from base at offset 0x%08x to the new file", cSize, offset);
memcpy(databuf + databuf_size, base + offset, cSize);
databuf_size += cSize;
index += 4;
}
else
{
// printf("\nAppend 0x%08x bytes from the current place in dlta to the new file", sizeX);
memcpy(databuf + databuf_size, deta_blob + index, sizeX);
databuf_size += sizeX;
index += sizeX;
}
} while (index < blob_size - 8);
FILE *out_file = fopen(outfile, "wb");
fwrite(databuf, databuf_size, 1, out_file);
fclose(out_file);
*outSize = databuf_size;
return databuf;
}
unsigned char *prepare_deltapatch(char *outfile, size_t *out_size, char *delta_file, char *base_file)
{
FILE *h_delta_file = NULL;
FILE *h_base_file = NULL;
unsigned char *delta_buf = NULL;
unsigned char *base_buf = NULL;
size_t delta_file_size = 0;
size_t base_file_size = 0;
unsigned char *out_buf = NULL;
h_delta_file = fopen(delta_file, "rb");
if (h_delta_file)
{
delta_file_size = get_file_size(h_delta_file);
delta_buf = (unsigned char *)malloc(delta_file_size);
if (delta_buf)
{
fread(delta_buf, delta_file_size, 1, h_delta_file);
}
h_base_file = fopen(base_file, "rb");
if (h_base_file)
{
base_file_size = get_file_size(h_base_file);
base_buf = (unsigned char *)malloc(base_file_size);
if (base_buf)
{
fread(base_buf, base_file_size, 1, h_base_file);
}
fclose(h_base_file);
}
fclose(h_delta_file);
}
if (delta_buf != NULL && base_buf != NULL)
{
size_t outSize = 0;
out_buf = delta_patch(outfile, &outSize, delta_buf, delta_file_size, base_buf, base_file_size);
*out_size = outSize;
}
if (delta_buf != NULL)
{
free(delta_buf);
}
if (base_buf != NULL)
{
free(base_buf);
}
return out_buf;
}
int main(int argc, char *argv[])
{
if (argc < 3)
{
printf("\nUsage:");
printf("\n%s out_folder vdm_base [vdm_dlta] ", argv[0]);
printf("\nEg.");
printf("\nwdextract.exe mpavdlta.vdm");
printf("\n%s mpavdlta_vdm_data_folder mpavdlta.vdm.extracted", argv[0]);
printf("\n%s mpavdlta_vdm_data_folder mpavbase.vdm.extracted mpavdlta.vdm.extracted ", argv[0]);
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 lua_sign_out_file[0x100] = {0};
char friendly_sign_out_file[0x100] = {0};
char pehstr_sig_out_file[0x100] = {0};
size_t threat_index = 0;
out_folder = argv[1];
char *file_path = argv[2];
size_t nPEHstrSig = 0;
size_t nOtherSig = 0;
size_t threat_length = 0;
size_t out_length = 0;
size_t file_size = 0;
unsigned char *buf = NULL;
friendly_buffer = (unsigned char *)malloc(536870912);
lua_buffer = (unsigned char *)malloc(536870912);
unsigned char *out_buf = (unsigned char *)malloc(536870912 * 2);
unsigned char *pehstr_buf = (unsigned char *)malloc(536870912);
unsigned char *threatBegin = NULL;
// to lazyyy
std::filesystem::create_directories(out_folder);
// Use snprintf to fix Buffer overflow.
snprintf(sig_out_file, strlen(out_folder) + strlen(file_path) + 6, "%s%c%s.csv", out_folder, DIR_SEPARATOR, file_path); // crash here
snprintf(pehstr_sig_out_file, strlen(out_folder) + strlen(file_path) + 25, "%s%cthreat_only_pehstr_%s.csv", out_folder, DIR_SEPARATOR, file_path);
snprintf(lua_sign_out_file, strlen(out_folder) + strlen(file_path) + 25, "%s%clua_standalone_sig_%s.csv", out_folder, DIR_SEPARATOR, file_path);
snprintf(friendly_sign_out_file, strlen(out_folder) + strlen(file_path) + 24, "%s%cfriendly_hash_sig_%s.csv", out_folder, DIR_SEPARATOR, file_path);
if (argc == 3)
{
h_file = fopen(file_path, "rb");
if (h_file)
{
file_size = get_file_size(h_file);
buf = (unsigned char *)malloc(file_size);
if (buf)
{
fread(buf, file_size, 1, h_file);
}
fclose(h_file);
}
else
{
printf("\nRead file error");
}
}
else if (argc == 4)
{
char *delta_path = argv[3];
char out_path[1024] = {0};
sprintf(out_path, "%s%cdelta_patched.vdm", out_folder, DIR_SEPARATOR);
buf = prepare_deltapatch(out_path, &file_size, delta_path, file_path);
}
printf("\nBegin parser ...");
if (buf)
{
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);
printf("\nParse completed:");
for (int j = 0; j < 0xff; j++)
{
if (sig_enum[j] > 0)
{
printf("\n0x%08x sigs of 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 (lua_buffer_index > 0)
{
char header_lua[] = "threat,lua_attr,category,size,hexdata\r\n";
if ((out_file = fopen(lua_sign_out_file, "wb")) == NULL)
{
return -1;
}
fwrite(header_lua, strlen(header_lua), 1, out_file);
fwrite(lua_buffer, lua_buffer_index, 1, out_file);
fclose(out_file);
}
if (friendly_buffer_index > 0)
{
char header_friendly[] = "type,hash\r\n";
if ((out_file = fopen(friendly_sign_out_file, "wb")) == NULL)
{
return -1;
}
fwrite(header_friendly, strlen(header_friendly), 1, out_file);
fwrite(friendly_buffer, friendly_buffer_index, 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);
}
}
free(lua_buffer);
free(friendly_buffer);
free(out_buf);
free(pehstr_buf);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment