// 简单的进程伪装就是修改进程名称,比如svchost.exe、services.exe等系统进程。
// 高级的进程伪装就是修改进程的PEB数据,也就是在任务管理器中看到的进程的名称、启动路径等信息。
// NtQueryInformationProcess函数
// 作用:获取指定进程的信息。
// 原型:NSTATUS WINAPI NtQueryInformationProcess(
// _In_ HANLDE hProcess;
// _In_ PROCESSINFOCLASS ProcessInformationClass,
// _Out_ PVOID ProcesInformation,
// _In_ ULONG ProcessInformationLength,
// _Out_opt_ PULONG ReturnLength
// )
// 参数:hProcess:进程句柄,由OpenProcess函数获取。
// ProcessInformationClass:进程信息的类型,为以下枚举值之一:
// ProcessBasicInformation:检索指向PEB结构的指针。
// ProcessDebugPort:获取作为进程调试器端口号的DWORD_PTR值。
// ProcessWow64Information:确定进程是否在Wow64环境中运行。
// ProcessImageFileName:检索包含该进程映像文件名称的UNICODE_STRING值。
// ProcessBreakOnTermination:检索指示进程是否被视为关键的ULONG值。
// ProcessSubsystemInformation:检索指示进程子系统类别的SUBSYSTEM_INFORMATION_TYPE值。
// ProcessInformation:接收值,
// ProcessInformationLength:指定接收数据缓冲区的大小。
// ReturnLength:接收返回所请求信息的大小。
// 结果:返回一个NTSTATUS成功或错误代码。
// PROCESS_BASIC_INFORMATION结构体
// 定义: typedef struct _PROCESS_BASIC_INFORMATION {
// PVOID Reserved1;
// PPEB PebBaseAddress,
// PVOID Reserved2[2];
// ULONG_PTR UniqueProcessId;
// PVOID Reserved3;
// } PROCESS_BASIC_INFORMATION;
// 参数:PebBaseAddress成员指向PEB结构。
// 实现原理:就是修改指定进程环境块(PEB)中的进程路径以及命令行信息,从而达到进程伪装的效果。
// PS:NtQueryInformationProcess这个函数不是公开的,需要从ntdll.dll中获取函数地址。
// 示例代码:
BOOL DisguiseProcess(DWORD dwProcessId, wchar_t* lpwszPath, wchar_t* lpwszCmd)
{
// 打开进程,获取进程句柄
HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
if (NLL == hProcess)
{
ShowError("OpenProcess");
return FALSE;
}
typedef_NtQueryInformationProcess NtQueryInformationProcess = NULL;
PROCESS_BASIC_INFORMATION pbi = {0};
PEB peb = {0};
RTL_USER_PROCESS_PARAMETERS Param = {0};
USHORT usCmdLen = 0;
USHORT usPathLen = 0;
// 需要通过LoadLibrary、GetProcessAddress从ntdll.dll中获取地址
NtQueryInformationProcess = ::GetProcAddress(::LoadLibrary("ntdll.dll"), "NtQueryInformationProcess");
if (NULL == NtQueryInformationProcess)
{
ShowError("GetProcAddress");
return FALSE;
}
// 获取指定进程的基本信息
NTSATUS status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
if (!NT_SUCCESS(status))
{
ShowError("NtQueryInformationProcess");
return FALSE;
}
// 获取指定进程基本信息结构中的PebBaseAddress
::ReadProcessMemory(hProcess, pbi.PebBaseAddress, &peb, sizeof(peb), NULL);
// 获取指定进程环境块结构中的ProcessParameters
::ReadProcessMemory(hProcess, peb.ProcessParameters, &Param, sizeof(Param), NULL);
// 修改指定PEB中命令行信息
usCmdLen = 2 + 2 * ::wcslen(lpwszCmd);
::WriteProcessMemory(hProcess, Param.CommandLine.Buffer, lpwszCmd, usCmdLen, NULL);
::WriteProcessMemory(hProcess, Param.CommandLine.Length, &usCmdLen, sizeof(usCmdLen), NULL);
// 修改指定PEB中的路径信息
usPathLen = 2 + 2 * wcslen(lpwszPath);
::WriteProcessMemory(hProcess, Param.ImagePathName.Buffer, lpwszPath, usPathLen, NULL);
::WriteProcessMemory(hProcess, Param.ImagePathName.Length, &usPathLen, sizeof(usPathLen), NULL);
return TRUE;
}