2

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?

The code:

#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;
}
1
  • 1
    NtQueryInformationProcess() takes a process handle, not a PID. Commented Aug 11, 2015 at 4:53

2 Answers 2

4

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.

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.

Sign up to request clarification or add additional context in comments.

1 Comment

This is also my conclusion, yet your answer came first. Thank you.
2

After a bit of trial and error I come up with following. I wrote a C executable that only links with kernel32.lib and does not link CRT. In the exe, I do EAT patching of GetCommandLineX functions in kernel32.dll. Then I load another of my dll (test.dll) which needs GetCommandLineX method as part of its functions. Since kernel32 is patched, loader fills the import table of the test.dll with the patched function pointers. In the end, methods in the test.dll calls my version of GetCommandLineX, which I can easily change their implementation.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.