C++ 修改指定进程 PEB 中路径和命令行信息实现进程伪装

背景

所谓的进程伪装,指的修改任意一个指定进程的信息,是它的信息在系统中的显示是另一个进程的信息,这样看来,指定的进程就像是被伪装的进程一样,因为进程信息相同,但实际上,它还是原来的进程,做着原来的进程操作。

函数介绍

NtQueryInformationProcess

    NTSTATUS WINAPI NtQueryInformationProcess(
        _In_      HANDLE           ProcessHandle,				// 要获取信息的进程的句柄。
        _In_      PROCESSINFOCLASS ProcessInformationClass,		// 要获取的进程信息的类型
        _Out_     PVOID            ProcessInformation,			// 指向由调用应用程序提供的缓冲区的指针
        _In_      ULONG            ProcessInformationLength,	// 指向的缓冲区的大小
        _Out_opt_ PULONG           ReturnLength					// 返回所请求信息的大小
    );

实现原理

进程伪装的原理不是很复杂,就是修改指定进程的进程环境块 PEB 中的进程路径以及命令行信息,即可达到进程伪装的效果。

具体实现原理分析如下:

  • 首先,我们根据进程的 PID 号打开指定进程,并获取进程的句柄。
  • 然后,我们要从 ntdll.dll 中获取 NtQueryInformationProcess 函数的导出地址,因为 NtQueryInformationProcess 函数没有关联导入库,所以只能动态获取,这个函数是这个程序功能实现的关键步骤。
  • 接着,使用 NtQueryInformationProcess 函数获取指定进程的进程基本信息 PROCESS_BASIC_INFORMATION,并从中获取指定进程的进程环境块 PEB。
  • 然后,我们就可以根据进程环境块中的 ProcessParameters,获取指定进程的 RTL_USER_PROCESS_PARAMETERS 信息,因为PEB的路径信息、命令行信息存储在这个结构体中。
  • 最后,我们开始对指定进程 PEB 中路径信息、命令行信息进行更改,实现进程伪装

编码实现

    // 修改指定进程的进程环境块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("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;
    }

程序测试

我们运行一个测试程序 Demon Memory.exe,先使用 Process Explorer 查看它的进程信息:C++ 修改指定进程 PEB 中路径和命令行信息实现进程伪装_第1张图片

现在,我们运行我们的进程伪装程序,修改上述的测试程序 Demon Memory.exe 进程的PEB进程环境块信息,实现进程伪装。程序执行提示成功,我们再运行 Process Explorer 程序查看进程信息,发现测试程序 Demon Memory.exe 进程信息成功伪装了 explorer.exe 资源管理器进程。
C++ 修改指定进程 PEB 中路径和命令行信息实现进程伪装_第2张图片

你可能感兴趣的:(C++功能函数)