修改GetCommandLine()的命令行参数
Modifying command line arguments for GetCommandLine()
我试图修改我的可执行文件的命令行参数,以便GetCommandLine()将返回我设置的字符串。由于我想在任何人之前修改命令行值,因此我通过/entry开关将入口点更改为testme()函数,并设置/NODEFAULTLIB选项以排除CRT。使用下面的代码为什么我可以通过命令行改变字符串缓冲区指针,但不能分配一个全新的缓冲区?
代码:
#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' ';
pbi.PebBaseAddress->ProcessParameters->CommandLine.Length = 6;
// This does not work
UNICODE_STRING cmdLine;
wchar_t wszNewCmdLine[] = L"x y ";
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' ');
//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钩子,但更简单的解决方案可能是首先使用所需的命令行启动可执行文件。您可以在它启动时测试命令行是否正确,如果不正确,则使用所需的命令行生成另一个副本。
经过一些尝试和错误后,我得出了以下结论。我写了一个C可执行文件,它只链接kernel32.lib
而不链接CRT
。在exe
中,我在kernel32.dll
中对GetCommandLineX
功能进行EAT
补丁。然后我加载我的另一个dll (test.dll),它需要GetCommandLineX
方法作为其功能的一部分。由于kernel32
被打了补丁,所以loader用打了补丁的函数指针填充了test.dll的导入表。最后,test.dll中的方法调用我的GetCommandLineX版本,我可以很容易地改变它们的实现。
相关文章:
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 如何处理linux终端中带有负号(-)的C++中的命令行参数
- 使用 C++ 将命令行参数拆分为参数/向量
- 如何在OMNET++中添加专门的命令行参数?
- 如何在不传递命令行参数的情况下在 c++ 中设置环境变量
- atoi() 在应用于大型命令行参数时会产生不正确的值
- 命令行参数,cant 或两个变量
- 在 Windows 中使用 boost::p rogram_options 从命令行参数读取 Unicode 字符
- 如何在 Android/NDK 上将命令行参数从 gradlew.bat 传递到 Clang
- 编写一个将 LLVM IR 文件作为命令行参数的程序
- 通过命令行参数获取llvm ir文件时面临问题
- 有没有办法根据命令行参数定义数组大小?运行时与编译时实例化?
- 如何在不使用文件扩展名的情况下使用命令行参数打开C++中的文本文件?
- 命令行参数在不到 3 个 LOC 中 int?
- 在命令行参数中使用引号
- 在VS2013中使用devenv (C++)传递命令行参数argv
- 二进制数据作为命令行参数
- 如何在 C++11 中创建具有命令行参数大小的动态数组?
- 需要有关如何设置getopt_long以正确传递命令行参数的建议
- Bash 脚本和命令行参数