Fix yara matching issue (#398)

* Fix yara matching issue

* fix yara.csv strings[x] column display
This commit is contained in:
Tokeii
2025-08-11 03:30:05 +08:00
committed by GitHub
parent 044d224dd1
commit 3f4a845fc6

View File

@@ -9,6 +9,7 @@
#include "fc.h"
#include "util.h"
#include "vmmwin.h"
#include "vmmwinobj.h"
// ----------------------------------------------------------------------------
// PARSE SINGLE RESULT FUNCTIONALITY BELOW:
@@ -246,7 +247,9 @@ BOOL VmmYaraUtil_ParseSingleResultNext(
LPSTR uszCommandLine = "", uszMemoryType = "", uszMemoryTag = "";
LPCSTR uszFindEvilSeverity;
BYTE pbBuffer[0x80];
BYTE pbBufPlain[0x40];
CHAR szTimeCRE[24] = { 0 }, uszUserName[0x20] = { 0 };
CHAR uszMatchPreview[0x100];
PVMM_MAP_PTEENTRY pePte;
PVMM_MAP_VADENTRY peVad;
PVMMOB_MAP_PTE pObPteMap = NULL;
@@ -408,6 +411,9 @@ BOOL VmmYaraUtil_ParseSingleResultNext(
hEPC->usz[0] = 0;
uszRuleMatchStringBuffer[0] = 0;
CharUtil_ReplaceMultiple(uszRuleMatchStringBuffer, sizeof(uszRuleMatchStringBuffer), NULL, peMatch->RuleMatch.Strings[i].szString, NULL, -1, VMMYARAUTIL_TEXT_ALLOW, '_');
if(!uszRuleMatchStringBuffer[0]) {
_snprintf_s(uszRuleMatchStringBuffer, sizeof(uszRuleMatchStringBuffer), _TRUNCATE, "string_%u", i);
}
o = _snprintf_s(hEPC->usz, _countof(hEPC->usz), _TRUNCATE, "[%s]:", uszRuleMatchStringBuffer);
for(j = 0; j < peMatch->RuleMatch.Strings[i].cMatch; j++) {
o += _snprintf_s(hEPC->usz + o, _countof(hEPC->usz) - o, _TRUNCATE,
@@ -426,6 +432,9 @@ BOOL VmmYaraUtil_ParseSingleResultNext(
va = peMatch->vaBase + (QWORD)peMatch->RuleMatch.Strings[i].cbMatchOffset[j];
uszRuleMatchStringBuffer[0] = 0;
CharUtil_ReplaceMultiple(uszRuleMatchStringBuffer, sizeof(uszRuleMatchStringBuffer), NULL, peMatch->RuleMatch.Strings[i].szString, NULL, -1, VMMYARAUTIL_TEXT_ALLOW, '_');
if(!uszRuleMatchStringBuffer[0]) {
_snprintf_s(uszRuleMatchStringBuffer, sizeof(uszRuleMatchStringBuffer), _TRUNCATE, "string_%u", i);
}
o = _snprintf_s(hEPC->usz, _countof(hEPC->usz), _TRUNCATE, "[%s] %llx:\n", uszRuleMatchStringBuffer, va);
vaAlign = (max(va, 0x40) - 0x40) & ~0xf;
VmmReadEx(H, pObProcess, vaAlign, pbBuffer, sizeof(pbBuffer), &cbRead, VMM_FLAG_ZEROPAD_ON_FAIL);
@@ -433,12 +442,93 @@ BOOL VmmYaraUtil_ParseSingleResultNext(
cbWrite = (DWORD)_countof(hEPC->usz) - o;
Util_FillHexAscii_WithAddress(pbBuffer, sizeof(pbBuffer), vaAlign, hEPC->usz + o, &cbWrite);
}
// build CSV preview from memory around match address
{
DWORD pos = (DWORD)(va - vaAlign);
DWORD k, maxk = 64;
uszMatchPreview[0] = 0;
if(cbRead > pos) {
maxk = min(maxk, cbRead - pos);
for(k = 0; k < maxk && k + 2 < _countof(uszMatchPreview); k++) {
BYTE ch = pbBuffer[pos + k];
uszMatchPreview[k] = (ch >= 0x20 && ch < 0x7f) ? (CHAR)ch : '.';
}
uszMatchPreview[k] = 0;
}
}
o2 += _snprintf_s(hEPC->uszMatchContextTXT + o2, _countof(hEPC->uszMatchContextTXT) - o2, _TRUNCATE, "\n%s", hEPC->usz);
if(iMatchCSV < 5) {
iMatchCSV++;
oMatchCSV += _snprintf_s(hEPC->uszMatchContextCSV + oMatchCSV, _countof(hEPC->uszMatchContextCSV) - oMatchCSV, _TRUNCATE,
",%s,%llx",
FcCsv_String(&hEPC->hCSV, uszRuleMatchStringBuffer),
FcCsv_String(&hEPC->hCSV, uszMatchPreview),
va
);
}
}
}
} else {
// FILE object: print both direct string output and hexdump from file content around the match offset.
o2 = 0;
for(i = 0; i < peMatch->RuleMatch.cStrings; i++) {
for(j = 0; j < peMatch->RuleMatch.Strings[i].cMatch; j++) {
cAddresses++;
hEPC->usz[0] = 0;
va = peMatch->vaBase + (QWORD)peMatch->RuleMatch.Strings[i].cbMatchOffset[j];
uszRuleMatchStringBuffer[0] = 0;
CharUtil_ReplaceMultiple(uszRuleMatchStringBuffer, sizeof(uszRuleMatchStringBuffer), NULL, peMatch->RuleMatch.Strings[i].szString, NULL, -1, VMMYARAUTIL_TEXT_ALLOW, '_');
if(!uszRuleMatchStringBuffer[0]) {
_snprintf_s(uszRuleMatchStringBuffer, sizeof(uszRuleMatchStringBuffer), _TRUNCATE, "string_%u", i);
}
// Read a small window from the file around the match offset for preview and hexdump.
vaAlign = (max(va, 0x40) - 0x40) & ~0xf; // align to 16 bytes, keep 0x40 bytes of context before
// read hexdump window (0x80 bytes) from file object address
cbRead = VmmWinObjFile_ReadFromObjectAddress(H, peMatch->vaObject, vaAlign - peMatch->vaBase, pbBuffer, sizeof(pbBuffer), VMM_FLAG_ZEROPAD_ON_FAIL, VMMWINOBJ_FILE_TP_DEFAULT);
// read plain text preview (up to 0x40 bytes) exactly from match offset
ZeroMemory(pbBufPlain, sizeof(pbBufPlain));
VmmWinObjFile_ReadFromObjectAddress(H, peMatch->vaObject, va - peMatch->vaBase, pbBufPlain, sizeof(pbBufPlain), VMM_FLAG_ZEROPAD_ON_FAIL, VMMWINOBJ_FILE_TP_DEFAULT);
// Build output: header, plain text and hexdump
o = _snprintf_s(hEPC->usz, _countof(hEPC->usz), _TRUNCATE, "[%s] %llx (FILE):\n", uszRuleMatchStringBuffer, va);
// Plain text (sanitize to printable)
{
CHAR szPlain[0x100];
DWORD k, oP = 0;
oP += _snprintf_s(szPlain + oP, _countof(szPlain) - oP, _TRUNCATE, "Plain: \"");
for(k = 0; k < sizeof(pbBufPlain) && oP + 4 < _countof(szPlain); k++) {
BYTE ch = pbBufPlain[k];
if(ch == '\0') { break; }
if(ch >= 0x20 && ch < 0x7f) {
szPlain[oP++] = (CHAR)ch;
} else {
szPlain[oP++] = '.';
}
}
oP += _snprintf_s(szPlain + oP, _countof(szPlain) - oP, _TRUNCATE, "\"\n");
o += _snprintf_s(hEPC->usz + o, _countof(hEPC->usz) - o, _TRUNCATE, "%s", szPlain);
}
if(cbRead) {
cbWrite = (DWORD)_countof(hEPC->usz) - o;
_snprintf_s(hEPC->usz + o, _countof(hEPC->usz) - o, _TRUNCATE, "Hexdump:\n");
o += (DWORD)strlen("Hexdump:\n");
Util_FillHexAscii_WithAddress(pbBuffer, sizeof(pbBuffer), vaAlign, hEPC->usz + o, &cbWrite);
}
// CSV preview from FILE bytes at match
{
DWORD k, maxk = 64;
uszMatchPreview[0] = 0;
for(k = 0; k < sizeof(pbBufPlain) && k < maxk && k + 2 < _countof(uszMatchPreview); k++) {
BYTE ch = pbBufPlain[k];
if(ch == '\0') { break; }
uszMatchPreview[k] = (ch >= 0x20 && ch < 0x7f) ? (CHAR)ch : '.';
}
uszMatchPreview[k] = 0;
}
o2 += _snprintf_s(hEPC->uszMatchContextTXT + o2, _countof(hEPC->uszMatchContextTXT) - o2, _TRUNCATE, "\n%s", hEPC->usz);
if(iMatchCSV < 5) {
iMatchCSV++;
oMatchCSV += _snprintf_s(hEPC->uszMatchContextCSV + oMatchCSV, _countof(hEPC->uszMatchContextCSV) - oMatchCSV, _TRUNCATE,
",%s,%llx",
FcCsv_String(&hEPC->hCSV, uszMatchPreview),
va
);
}