chowey
chowey

Reputation: 9826

Modify Command Line Arguments

I have a Win32 C++ application and I need to modify the command line arguments in the application. Specifically, I want to edit the command line arguments in such a way that GetCommandLineW() returns my new arguments.

Believe it or not, this works (since we have a non-const pointer to the character array):

LPTSTR args = GetCommandLineW();
LPTSTR new_args = L"foo --bar=baz";
wmemcpy(args, new_args, lstrlenW(new_args));

// ...
LPTSTR args2 = GetGommentLineW(); // <- equals "foo --bar=baz"

But I don't know how long much memory Windows allocates for the LPTSTR provided by GetCommandLineW().

Is there another way to do this? Or does anyone know if there is a predictable amount of memory allocated for the command line arguments?

Upvotes: 2

Views: 2035

Answers (3)

Ben
Ben

Reputation: 410

Use the following code to inspect on PEB structure, where the CommandLine (unicode) string lies.

On my machine, under both x86 and x64 CommandLine is right after ImagePathName, so I think there won't be more space for the former one either. Writing a longer string to that buffer does might cause an overflow.

#include <winnt.h>
#include <winternl.h>


int main()
{
    // Thread Environment Block (TEB)
#if defined(_M_X64) // x64
    PTEB tebPtr = (PTEB)__readgsqword((DWORD) & (*(NT_TIB*)NULL).Self);
#else // x86
    PTEB tebPtr = (PTEB)__readfsdword((DWORD) & (*(NT_TIB*)NULL).Self);
#endif
    // Process Environment Block (PEB)
    PPEB pebPtr = tebPtr->ProcessEnvironmentBlock;
    PRTL_USER_PROCESS_PARAMETERS ppPtr = pebPtr->ProcessParameters;

    printf("ImagePathName:\tlen=%d maxlen=%d ptr=%p\n", ppPtr->ImagePathName.Length, ppPtr->ImagePathName.MaximumLength, ppPtr->ImagePathName.Buffer);
    printf("CommandLine:\tlen=%d maxlen=%d ptr=%p\n", ppPtr->CommandLine.Length, ppPtr->CommandLine.MaximumLength, ppPtr->CommandLine.Buffer);
    printf("GetCommandLineA:\tptr=%p\n", GetCommandLineA());
    printf("GetCommandLineW:\tptr=%p\n", GetCommandLineW());
    printf("Addr Delta between CommandLine and ImagePathName: %d\n", (char*)ppPtr->CommandLine.Buffer - (char*)ppPtr->ImagePathName.Buffer);
}

Upvotes: 1

David Heffernan
David Heffernan

Reputation: 612784

The cleanest and safest way to modify what that function returns is to modify the function. Install a detour so that any calls to the function from inside your process are re-routed to a function that you provide.

Upvotes: 1

Remy Lebeau
Remy Lebeau

Reputation: 595305

GetCommandLineW() does not allocate any memory. It simply returns a pointer to a buffer that is allocated by the OS in the process's PEB structure when the process is created. That buffer exists for the lifetime of the process.

Upvotes: 6

Related Questions