修改GetCommandLine()的命令行参数 [英] Modifying command line arguments for GetCommandLine()

查看:178
本文介绍了修改GetCommandLine()的命令行参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图修改可执行文件的命令行参数,以便GetCommandLine()将返回我设置的字符串。由于我想在任何人之前修改命令行值,我已经通过/ ENTRY开关更改了我的入口点testme()函数,还设置/ NODEFAULTLIB选项,以排除CRT。使用以下代码为什么我可以通过CommandLine更改字符串缓冲区指针,但不能分配一个完全新的缓冲区?

I am trying to modify command line arguments of my executable so that GetCommandLine() will return the string I set. Since I want to modify the command line value before anyone, I have changed my entry point to testme() function via /ENTRY switch and also set /NODEFAULTLIB option in order to exclude CRT. Using the following code why can I change the string buffer pointer by CommandLine but cannot allocate a completely new buffer?

代码:

#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 。你需要在内存中找到这个副本,以便修改它,这似乎很困难,也是危险的/不可靠的。

Unfortunately GetCommandLineW doesn't return the command line from the PEB. In the BaseDllInitialize routine a copy is made of the PEB command line structure, and from then on this copy is used by GetCommandLineW. You would need to locate this copy in memory in order to modify it, which seems quite difficult and also dangerous/unreliable.

你可以看看一个API钩子像Detours,但更容易的解决方案可能只是首先使用所需的命令行启动可执行文件。你可以测试它启动时,如果命令行是正确的,如果没有它产生另一个副本的本身与所需的命令行。

You could look at an API hook like Detours, but an easier solution might just be to launch your executable with your desired command line in the first place. You could test when it starts up if the command line is right and if not have it spawn another copy of itself with the desired command line.

这篇关于修改GetCommandLine()的命令行参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆