c++ - 修改 GetCommandLine() 的命令行参数

标签 c++ windows winapi

我正在尝试修改我的可执行文件的命令行参数,以便 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/

相关文章:

c++ - 部署 OpenCL 应用程序?

C++ 构造函数初始化多个成员

c++ - 为什么 reinterpret_cast 不将 'unsigned char' 转换为 'char' ?

c++ - 拦截WinAPI调用并修改返回值

c++ - 获取当前 CPU 利用率的方法在 Windows 10 上运行不可靠

具有隐式转换的 C++ 类字符串类

java - 为什么我每次尝试运行 android studio 应用程序时都会遇到相同的错误?

python - 在 Windows 上部署应用程序的最佳做法是什么?

windows - 通过插入符和符号回显在批处理文件中换行。 (^&回声。)

c++ - 如何通过给定序号将文件存储在文件夹中