我正在尝试修改我的可执行文件的命令行参数,以便 GetCommandLine() 将返回我设置的字符串。因为我想在任何人之前修改命令行值,所以我通过/ENTRY 开关将入口点更改为 testme() 函数,还设置了/NODEFAULTLIB 选项以排除 CRT。使用以下代码为什么我可以通过 CommandLine 更改字符串缓冲区指针但不能分配一个全新的缓冲区?
代码:
#include <Windows.h>
#include <winternl.h>
typedef NTSTATUS (WINAPI *PFN_NtQueryInformationProcess)(
IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass,
IN PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
_Out_opt_ PULONG ReturnLength );
int testme()
{
// Get PEB block address
PROCESS_BASIC_INFORMATION pbi;
ULONG result;
PFN_NtQueryInformationProcess pfnQueryProcess =
(PFN_NtQueryInformationProcess) GetProcAddress(LoadLibrary("ntdll"),
"NtQueryInformationProcess");
pfnQueryProcess(GetCurrentProcessId(),
ProcessBasicInformation, &pbi, sizeof(pbi), &result);
// Modify ProcessParameters->CommandLine
// This works
pbi.PebBaseAddress->ProcessParameters->CommandLine.Buffer[0] = L'a';
pbi.PebBaseAddress->ProcessParameters->CommandLine.Buffer[1] = L' ';
pbi.PebBaseAddress->ProcessParameters->CommandLine.Buffer[2] = L'b';
pbi.PebBaseAddress->ProcessParameters->CommandLine.Buffer[3] = L'\0';
pbi.PebBaseAddress->ProcessParameters->CommandLine.Length = 6;
// This does not work
UNICODE_STRING cmdLine;
wchar_t wszNewCmdLine[] = L"x y\0";
cmdLine.Buffer = (wchar_t*)GlobalAlloc(GMEM_FIXED, sizeof(wchar_t)*pbi.PebBaseAddress->ProcessParameters->CommandLine.MaximumLength);
cmdLine.MaximumLength = pbi.PebBaseAddress->ProcessParameters->CommandLine.MaximumLength;
cmdLine.Length = sizeof(wszNewCmdLine) - sizeof(L'\0');
//Copy buffer
for(int i=0; i<cmdLine.Length; ++i)
cmdLine.Buffer[i] = wszNewCmdLine[i];
pbi.PebBaseAddress->ProcessParameters->CommandLine.Buffer = cmdLine.Buffer;
pbi.PebBaseAddress->ProcessParameters->CommandLine.Length = cmdLine.Length;
pbi.PebBaseAddress->ProcessParameters->CommandLine.MaximumLength = cmdLine.MaximumLength;
// Now testing, pCmdLine returned is "a b", not "x y".
wchar_t *pCmdLine = GetCommandLine();
return 0;
}
最佳答案
不幸的是 GetCommandLineW
没有从 PEB 返回命令行。在 BaseDllInitialize
例程中,对 PEB 命令行结构进行了复制,然后此拷贝由 GetCommandLineW
使用。您需要在内存中找到此拷贝才能对其进行修改,这似乎非常困难,而且也很危险/不可靠。
您可以查看像 Detours 这样的 API Hook ,但更简单的解决方案可能只是首先使用所需的命令行启动可执行文件。如果命令行正确,您可以测试它何时启动,如果不正确,它会使用所需的命令行生成自己的另一个拷贝。
关于c++ - 修改 GetCommandLine() 的命令行参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24754844/