1. 程式人生 > >【舊文章搬運】獲取並修改PEB中的映像路徑,命令列和當前目錄

【舊文章搬運】獲取並修改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);

 

效果還行,但是路徑那塊兒還是有問題,被截斷了.
丟個圖吧,高手飄過~