修改命令行参数

Modify Command Line Arguments

本文关键字:参数 命令行 修改      更新时间:2023-10-16

我有一个Win32 C++应用程序,需要修改应用程序中的命令行参数。具体来说,我想编辑命令行参数,使GetCommandLineW()返回我的新参数。

信不信由你,这是有效的(因为我们有一个指向字符数组的非常量指针):

LPTSTR args = GetCommandLineW();
LPTSTR new_args = L"foo --bar=baz";
wmemcpy(args, new_args, lstrlenW(new_args));
// ...
LPTSTR args2 = GetGommentLineW(); // <- equals "foo --bar=baz"

但我不知道Windows为GetCommandLineW()提供的LPTSTR分配了多少内存。

有别的办法吗?或者有人知道是否为命令行参数分配了可预测的内存量吗?

GetCommandLineW()不分配任何内存。它只是返回一个指针,指向创建进程时OS在进程的PEB结构中分配的缓冲区。该缓冲区在进程的整个生命周期内都存在。

修改函数返回内容的最干净、最安全的方法是修改函数。安装一个迂回路径,以便从进程内部对函数的任何调用都会重新路由到您提供的函数。

使用以下代码检查PEB结构,CommandLine(unicode)字符串所在的位置。

在我的机器上,在x86和x64下,CommandLine就在ImagePathName之后,所以我认为前一个也不会有更多的空间。向缓冲区写入更长的字符串可能会导致溢出。

#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=%pn", ppPtr->ImagePathName.Length, ppPtr->ImagePathName.MaximumLength, ppPtr->ImagePathName.Buffer);
    printf("CommandLine:tlen=%d maxlen=%d ptr=%pn", ppPtr->CommandLine.Length, ppPtr->CommandLine.MaximumLength, ppPtr->CommandLine.Buffer);
    printf("GetCommandLineA:tptr=%pn", GetCommandLineA());
    printf("GetCommandLineW:tptr=%pn", GetCommandLineW());
    printf("Addr Delta between CommandLine and ImagePathName: %dn", (char*)ppPtr->CommandLine.Buffer - (char*)ppPtr->ImagePathName.Buffer);
}