声明:本内容只作为个人学习研究使用,请勿用作其他用途。
修改ImagePathName和CommandLine伪装进程
原理和步骤
修改指定进程环境块PEB中的进程路径ImagePathName以及命令行CommandLine信息,比如可以修改成explorer.exe进程的信息,从而达到进程伪装的效果。
可以用ntdll.dll的导出函数NTQueryInfomationProcess来获取指定进程的PEB地址,
然后调用ReadProcessMemory和WriteProcessMemory来读写目标进程PEB中ProcessParameters的ImagePath和CommandLine的信息。
项目代码(测试成功)
#include "stdlib.h"
#include "tchar.h"
#include <Windows.h>
#include "direct.h"
#include "TlHelp32.h"
#include "atlstr.h"
#include <winternl.h>
#include <stdio.h>
#include <intrin.h>
#include <tchar.h>
#include <SDKDDKVer.h>
#define PROCESS_NAME "notepad.exe" //要注入的进程名
typedef NTSTATUS(NTAPI* typedef_NtQueryInformationProcess)(
IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
void ShowError(char* pszText)
{
wchar_t szErr[MAX_PATH] = { 0 };
::wsprintf(szErr, L"%s Error[%d]\n", pszText, ::GetLastError());
::MessageBox(NULL, szErr, L"ERROR", MB_OK);
}
//根据进程名获取进程Pid
DWORD GetPID(CString pProName)
{
...
return dwPID;
}
// 修改指定进程的进程环境块PEB中的路径和命令行信息, 实现进程伪装
BOOL DisguiseProcess(DWORD dwProcessId, wchar_t* lpwszPath, wchar_t* lpwszCmd)
{
// 打开进程获取句柄
HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
if (NULL == 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 = (typedef_NtQueryInformationProcess)::GetProcAddress(
::LoadLibrary(L"ntdll.dll"), "NtQueryInformationProcess");
if (NULL == NtQueryInformationProcess)
{
ShowError("GetProcAddress");
return FALSE;
}
// 获取指定进程的基本信息
NTSTATUS status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
if (!NT_SUCCESS(status))
{
ShowError("NtQueryInformationProcess");
return FALSE;
}
/*
注意在读写其他进程的时候,注意要使用ReadProcessMemory/WriteProcessMemory进行操作,
每个指针指向的内容都需要获取,因为指针只能指向本进程的地址空间,必须要读取到本进程空间。
要不然一直提示位置访问错误!
*/
// 获取指定进程进本信息结构中的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;
}
int main() {
if (FALSE == DisguiseProcess(1272, L"C:\Windows\explorer.exe", L"explorer.exe"))
{
printf("Dsisguise Process Error.\n");
}
printf("Dsisguise Process OK.\n");
system("pause");
return 0;
}
测试效果
针对notpad.exe进行测试,执行前内容如下
执行后,Command Line,Image Path成功被修改