【舊文章搬運】獲取並修改PEB中的映像路徑,命令列和當前目錄
原文發表於百度空間,2008-7-24
當時對UNICODE_STRING的使用還有點問題,導致最終效果圖中字串被截斷了
==========================================================================
先從分析PEB開始吧.
感覺分析這個東西,首先要把型別定義搞清楚,這個在Windbg裡dt _PEB就可以了
搞清楚定義主要是為了定位相關變數的偏移.
PEB中的ProcessParameters部分就是程序的引數了,裡面就有我們感興趣的映像路徑等資訊
之所以對這個感興趣,是因為以前看到過修改PEB中的映像路徑過防火牆的
獲取PEB很簡單,也早有人說過這個問題.
在使用者模式下,fs暫存器指向TEB結構,在TEB開頭部分是這麼定義的:
lkd> dt _TEB
nt!_TEB
+0x000 NtTib : _NT_TIB
+0x01c EnvironmentPointer : Ptr32 Void
+0x020 ClientId : _CLIENT_ID
+0x028 ActiveRpcHandle : Ptr32 Void
+0x02c ThreadLocalStoragePointer : Ptr32 Void
+0x030 ProcessEnvironmentBlock : Ptr32 _PEB //這個就指向PEB
再看PEB的開頭部分:
lkd> dt _PEB
nt!_PEB
+0x000 InheritedAddressSpace : UChar
+0x001 ReadImageFileExecOptions : UChar
+0x002 BeingDebugged : UChar
+0x003 SpareBool : UChar
+0x004 Mutant : Ptr32 Void
+0x008 ImageBaseAddress : Ptr32 Void
+0x00c Ldr : Ptr32 _PEB_LDR_DATA
+0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS //指向程序的引數
再來看_RTL_USER_PROCESS_PARAMETERS 的結構:
lkd> dt _RTL_USER_PROCESS_PARAMETERS
nt!_RTL_USER_PROCESS_PARAMETERS
+0x000 MaximumLength : Uint4B
+0x004 Length : Uint4B
+0x008 Flags : Uint4B
+0x00c DebugFlags : Uint4B
+0x010 ConsoleHandle : Ptr32 Void
+0x014 ConsoleFlags : Uint4B
+0x018 StandardInput : Ptr32 Void
+0x01c StandardOutput : Ptr32 Void
+0x020 StandardError : Ptr32 Void
+0x024 CurrentDirectory : _CURDIR //當前目錄
+0x030 DllPath : _UNICODE_STRING
+0x038 ImagePathName : _UNICODE_STRING //映像路徑
+0x040 CommandLine : _UNICODE_STRING //命令列
+0x048 Environment : Ptr32 Void
+0x04c StartingX : Uint4B
+0x050 StartingY : Uint4B
+0x054 CountX : Uint4B
+0x058 CountY : Uint4B
+0x05c CountCharsX : Uint4B
+0x060 CountCharsY : Uint4B
+0x064 FillAttribute : Uint4B
+0x068 WindowFlags : Uint4B
+0x06c ShowWindowFlags : Uint4B
+0x070 WindowTitle : _UNICODE_STRING
+0x078 DesktopInfo : _UNICODE_STRING
+0x080 ShellInfo : _UNICODE_STRING
+0x088 RuntimeData : _UNICODE_STRING
+0x090 CurrentDirectores : [32] _RTL_DRIVE_LETTER_CURDIR
到這兒,應該就比較清楚了,反正這些東西都是在使用者空間的,可以看也可以改.
關鍵程式碼如下:
typedef struct _RTL_USER_PROCESS_PARAMETERS { DWORD MaximumLength; DWORD Length; DWORD Flags; DWORD DebugFlags; HANDLE ConsoleHandle; DWORD ConsoleFlags; HANDLE StandardInput; HANDLE StandardOutput; HANDLE StandardError; CURDIR CurrentDirectory; UNICODE_STRING DllPath; UNICODE_STRING ImagePathName; UNICODE_STRING CommandLine; void* Environment; //指向MULTI的寬字串 DWORD StartingX; DWORD StartingY; DWORD CountX; DWORD CountY; DWORD CountCharsX; DWORD CountCharsY; DWORD FillAttribute; DWORD WindowFlags; DWORD ShowWindowFlags; UNICODE_STRING WindowTitle; UNICODE_STRING DesktopInfo; UNICODE_STRING ShellInfo; UNICODE_STRING RuntimeData; RTL_DRIVE_LETTER_CURDIR CurrentDirectores; }RTL_USER_PROCESS_PARAMETERS; void* PEB; PWSTR p; PWSTR fakeImagePath=L"I am achillis,this is fake image path"; PWSTR fakeCommandLine=L"I am achillis,this is fake commandline"; PWSTR fakeCurrentDirectory=L"I am achillis,this is fake CurrentDirectory"; RTL_USER_PROCESS_PARAMETERS *pUserParam; _asm { mov eax,fs:[0x30] //TEB->PEB mov eax,[eax+0x10] //PEB->ProcessParameters mov pUserParam,eax } printf("RTL_USER_PROCESS_PARAMETERS:0x%08x\n",pUserParam); //輸出映像路徑等資訊 //wprintf(L"DllPath:%s\n",pUserParam->DllPath.Buffer); wprintf(L"[ImagePath]:%s\n",pUserParam->ImagePathName.Buffer); wprintf(L"[CommandLine]:%s\n",pUserParam->CommandLine.Buffer); wprintf(L"[CurrentDirectory]:%s\n",pUserParam->CurrentDirectory.DosPath.Buffer); //修改其中的內容 lstrcpyW(pUserParam->ImagePathName.Buffer,fakeImagePath); lstrcpyW(pUserParam->CommandLine.Buffer,fakeCommandLine); lstrcpyW(pUserParam->CurrentDirectory.DosPath.Buffer,fakeCurrentDirectory);
效果還行,但是路徑那塊兒還是有問題,被截斷了.
丟個圖吧,高手飄過~