使用FormatMessageW/A格式化4688日志时进程名称显示异常问题
问题
使用ReadEventLogW读取Windows事件日志中的4688事件,调用FormatMessageW进行格式化时结果不符合预期。从adtschema.dll(版本10.0.22621.2506)中提取的4688消息模板里,New Process Name:%t%6! S!%n%t是否应该写成New Process Name:%t%6!s!%n%t?
尝试使用FormatMessageA和FormatMessageW两个版本的函数,都无法正确显示结果,New Process Name和Creator Process Name字段出现乱码或为空值。相关C代码示例如下:
#include <windows.h> #include <stdio.h> void main(void) { //adtschema.dll (library:10.0.22621.2506) messageTable id 4688 const wchar_t* pMessage = L"A new process has been created.%n%nCreator Subject:%n%tSecurity ID:%t%t%1%n%tAccount Name:%t%t%2%n%tAccount Domain:%t%t%3%n%tLogon ID:%t%t%4%n%nTarget Subject:%n%tSecurity ID:%t%t%10%n%tAccount Name:%t%t%11%n%tAccount Domain:% t%t%12%n%tLogon ID:%t%t%13%n%nProcess Information:%n%tNew Process ID:%t%t%5%n%tNew Process Name:%t%6! S!%n%tToken Elevation Type:%t%7%n%tMandatory Label:%t%t%15%n%tCreator Process ID:%t%8%n%tCreator Process Name:%t%14! S!%n%tProcess Command Line:%t%9! S!%n%nToken Elevation Type indicates the type of token that was assigned to the new process in accordance with User Account Control policy.%n%nType 1 is a full token with no privileges removed or groups disabled. A full token is only used if User Account Control is disabled or if the user is the built-in Administrator account or a service account.%n%nType 2 is an elevated token with no privileges removed or groups disabled. An elevated token is used when User Account Control is enabled and the user chooses to start the program using Run as administrator. An elevated token is also used when an application is configured to always require administrative privilege or to always require maximum privilege, and the user is a member of the Administrators group.%n%nType 3 is a limited token with administrative privileges removed and administrative groups disabled. The limited token is used when User Account Control is enabled, the application does not require administrative privilege, and the user does not choose to start the program using Run as administrator."; DWORD_PTR pArgs[16] = { (DWORD_PTR)L"S-1-5-21-2772055006-295584695-1149559003-500", (DWORD_PTR) L"Administrator", (DWORD_PTR) L"cs-NBIR", (DWORD_PTR) L"0x5b45f71f", (DWORD_PTR) L"0x2730", (DWORD_PTR) L"C:/Program Files/Microsoft Visual Studio/2022/Professional/Common7/IDE/Remote Debugger/x64/msvsmon.exe", (DWORD_PTR) L"%%1936", (DWORD_PTR) L"0x204c", (DWORD_PTR) L"", (DWORD_PTR) L"S-1-0-0", (DWORD_PTR) L"-", (DWORD_PTR) L"-", (DWORD_PTR) L"0x0", (DWORD_PTR) L"C:/Program Files/Microsoft Visual Studio/2022/Professional/Common7/IDE/devenv.exe", (DWORD_PTR) L"S-1-16-12288", }; pArgs[15] = 0; const DWORD size = 4000; WCHAR buffer[size]; if (! FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, pMessage, 0, 0, buffer, size, (va_list*)pArgs)) { wprintf(L"Format message failed with 0x%x\n", GetLastError()); return; } wprintf(L"Formatted message: %s\n", buffer); //const char* pMessage = "A new process has been created.%n%nCreator Subject:%n%tSecurity ID:%t%t%1%n%tAccount Name:%t%t%2%n%tAccount Domain:%t%t%3%n%tLogon ID:%t%t%4%n%nTarget Subject:%n%tSecurity ID:%t%t%10%n%tAccount Name:%t%t%11%n%tAccount Domain:%t%t%12%n%tLogon ID:% t%t%13%n%nProcess Information:%n%tNew Process ID:%t%t%5%n%tNew Process Name:%t%6! S!%n%tToken Elevation Type:%t%7%n%tMandatory Label:%t%t%15%n%tCreator Process ID:%t%8%n%tCreator Process Name:%t%14! S!%n%tProcess Command Line:%t%9! S!%n%nToken Elevation Type indicates the type of token that was assigned to the new process in accordance with User Account Control policy.%n%nType 1 is a full token with no privileges removed or groups disabled. A full token is only used if User Account Control is disabled or if the user is the built-in Administrator account or a service account.%n%nType 2 is an elevated token with no privileges removed or groups disabled. An elevated token is used when User Account Control is enabled and the user chooses to start the program using Run as administrator. An elevated token is also used when an application is configured to always require administrative privilege or to always require maximum privilege, and the user is a member of the Administrators group.%n%nType 3 is a limited token with administrative privileges removed and administrative groups disabled. The limited token is used when User Account Control is enabled, the application does not require administrative privilege, and the user does not choose to start the program using Run as administrator."; //DWORD_PTR pArgs[16] = { (DWORD_PTR)"S-1-5-21-2772055006-295584695-1149559003-500", //(DWORD_PTR)"Administrator", //(DWORD_PTR)"cs-NBIR", // (DWORD_PTR)"0x5b45f71f", // (DWORD_PTR)"0x2730", // (DWORD_PTR)"C:/Program Files/Microsoft Visual Studio/2022/Professional/Common7/IDE/Remote Debugger/x64/msvsmon.exe", // (DWORD_PTR)"%%1936", // (DWORD_PTR)"0x204c", // (DWORD_PTR)"", // (DWORD_PTR)"S-1-0-0", // (DWORD_PTR)"-", // (DWORD_PTR)"-", // (DWORD_PTR)"0x0", // (DWORD_PTR)"C:/Program Files/Microsoft Visual Studio/2022/Professional/Common7/IDE/devenv.exe", // (DWORD_PTR)"S-1-16-12288", //}; //pArgs[15] = 0; //const DWORD size = 4000; //char buffer[size]; //if (! FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, // pMessage, // 0, // 0, // buffer, // size, // (va_list*)pArgs)) //{ // printf("Format message failed with 0x%x\n", GetLastError()); // return; //} //printf("Formatted message: %s\n", buffer); }
解决方法
你的怀疑是正确的,消息模板中的%6! S!必须改成%6!s!,同理%14! S!和%9! S!也需要去掉类型说明符中的空格。
原因分析
FormatMessage函数的格式说明符规则中,%N!类型!里的类型标识必须是连续的有效字符,! S!中的空格会被函数识别为无效的类型标记,导致无法正确将参数解析为字符串类型,最终出现乱码或空值的情况。而!s!是标准的字符串类型说明符,能正确匹配传入的宽字符串/窄字符串参数。
修改后的代码片段
将原pMessage中的三处错误格式修正:
%6! S!→%6!s!(对应New Process Name)%14! S!→%14!s!(对应Creator Process Name)%9! S!→%9!s!(对应Process Command Line)
修改后的宽字符串模板如下:
const wchar_t* pMessage = L"A new process has been created.%n%nCreator Subject:%n%tSecurity ID:%t%t%1%n%tAccount Name:%t%t%2%n%tAccount Domain:%t%t%3%n%tLogon ID:%t%t%4%n%nTarget Subject:%n%tSecurity ID:%t%t%10%n%tAccount Name:%t%t%11%n%tAccount Domain:%t%t%12%n%tLogon ID:%t%t%13%n%nProcess Information:%n%tNew Process ID:%t%t%5%n%tNew Process Name:%t%6!s!%n%tToken Elevation Type:%t%7%n%tMandatory Label:%t%t%15%n%tCreator Process ID:%t%8%n%tCreator Process Name:%t%14!s!%n%tProcess Command Line:%t%9!s!%n%nToken Elevation Type indicates the type of token that was assigned to the new process in accordance with User Account Control policy.%n%nType 1 is a full token with no privileges removed or groups disabled. A full token is only used if User Account Control is disabled or if the user is the built-in Administrator account or a service account.%n%nType 2 is an elevated token with no privileges removed or groups disabled. An elevated token is used when User Account Control is enabled and the user chooses to start the program using Run as administrator. An elevated token is also used when an application is configured to always require administrative privilege or to always require maximum privilege, and the user is a member of the Administrators group.%n%nType 3 is a limited token with administrative privileges removed and administrative groups disabled. The limited token is used when User Account Control is enabled, the application does not require administrative privilege, and the user does not choose to start the program using Run as administrator.";
验证结果
修改后重新调用FormatMessageW或FormatMessageA,New Process Name、Creator Process Name等字段将正确显示传入的参数值,不会出现乱码或空值问题。
内容的提问来源于stack exchange,提问作者tianchen
相关产品推荐
相关产品推荐

