![](/img/trans.png)
[英]What is the command line at GetCommandLine and at WinMain API?
[英]Modifying command line arguments for GetCommandLine()
我試圖修改可執行文件的命令行參數,以便GetCommandLine()返回我設置的字符串。 由於我想在任何人之前修改命令行值,因此我已通過/ ENTRY開關將入口點更改為testme()函數,並且還設置了/ NODEFAULTLIB選項以排除CRT。 使用以下代碼,為什么我可以通過CommandLine更改字符串緩沖區指針,但不能分配全新的緩沖區?
編碼:
#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
。 您可能需要在內存中找到此副本才能對其進行修改,這看起來非常困難,而且危險/不可靠。
您可以看一下Detours之類的API掛鈎,但更簡單的解決方案可能只是首先使用所需的命令行啟動可執行文件。 如果命令行正確,您可以測試它何時啟動,如果沒有,則使用所需的命令行生成它自身的另一個副本。
經過反復試驗,我得出以下結論。 我編寫了一個C可執行文件,該文件僅與kernel32.lib
鏈接,而不與CRT
鏈接。 在exe
,我對kernel32.dll
的GetCommandLineX
函數進行EAT
修補。 然后,我加載另一個需要GetCommandLineX
方法作為其功能一部分的dll(test.dll)。 由於已對kernel32
進行了修補,因此加載程序將使用修補后的函數指針填充test.dll的導入表。 最后,test.dll中的方法調用了我的GetCommandLineX版本,我可以輕松地更改其實現。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.