淺談ImagePath映像路徑

原作者:Inndy 首發於:Hack-Stuff
Q:

ImagePath是什麼?

A:
執行程式的時候,系統會建立一些資料區塊,裡面放了該程式執行時的一些資料,例如:CommandLine(就是程式參數,像是楓之谷私服登入器就是透過CommandLine來決定登入的IP和Port)....等
而ImagePath就是其中的一項



Q:
為什麼改ImagePath可以過HackShield的記憶體存取保護?

A:
因為HackShield對於NtOpenProcess、 NtReadVirtualMemory...等這幾條API有做Hook,就是大家一直說的InlineHook,然後去找這是哪個程式呼叫的,再去去 得該程式的ImagePath判斷是否為白名單,不然就拒絕呼叫,所以我們只要改掉ImagePath騙HackShield說我們是白名單上的程式(工 作管理員)。

Q:
ImagePath怎麼改?

A:
透過一連串的結構、指標下去改就好了,但是Win7 64bit的架構似乎不太一樣,雖然有找到結構體,但是似乎無效。

ImagePath的修改
ImagePath位於...
  1. PEB->_RTL_USER_PROCESS_PARAMETERS->ImagePathName
複製代碼
所以說我們要先取得PEB的位址,再延著這條路徑往下走去改..
(亦可使用ZwQueryInformationProcess這條API取得PEB基址)


我們來看看Win7 32bit的結構吧!

PEB
          typedef struct _PEB                                                                               // 91 elements, 0x248 bytes (sizeof)
          {
/*0x000*/     UINT8        InheritedAddressSpace;
/*0x001*/     UINT8        ReadImageFileExecOptions;
/*0x002*/     UINT8        BeingDebugged;
              union                                                                                         // 2 elements, 0x1 bytes (sizeof)
              {
/*0x003*/         UINT8        BitField;
                  struct                                                                                    // 6 elements, 0x1 bytes (sizeof)
                  {
/*0x003*/             UINT8        ImageUsesLargePages : 1;                                                 // 0 BitPosition
/*0x003*/             UINT8        IsProtectedProcess : 1;                                                  // 1 BitPosition
/*0x003*/             UINT8        IsLegacyProcess : 1;                                                     // 2 BitPosition
/*0x003*/             UINT8        IsImageDynamicallyRelocated : 1;                                         // 3 BitPosition
/*0x003*/             UINT8        SkipPatchingUser32Forwarders : 1;                                        // 4 BitPosition
/*0x003*/             UINT8        SpareBits : 3;                                                           // 5 BitPosition
                  };
              };
/*0x004*/     VOID*        Mutant;
/*0x008*/     VOID*        ImageBaseAddress;
/*0x00C*/     struct _PEB_LDR_DATA* Ldr;
/*0x010*/     struct _RTL_USER_PROCESS_PARAMETERS* ProcessParameters;
/*0x014*/     VOID*        SubSystemData;
/*0x018*/     VOID*        ProcessHeap;
...................................................
          }

_RTL_USER_PROCESS_PARAMETERS
          typedef struct _RTL_USER_PROCESS_PARAMETERS                // 30 elements, 0x298 bytes (sizeof)
          {
/*0x000*/     ULONG32      MaximumLength;
/*0x004*/     ULONG32      Length;
/*0x008*/     ULONG32      Flags;
/*0x00C*/     ULONG32      DebugFlags;
/*0x010*/     VOID*        ConsoleHandle;
/*0x014*/     ULONG32      ConsoleFlags;
/*0x018*/     VOID*        StandardInput;
/*0x01C*/     VOID*        StandardOutput;
/*0x020*/     VOID*        StandardError;
/*0x024*/     struct _CURDIR CurrentDirectory;                       // 2 elements, 0xC bytes (sizeof)
/*0x030*/     struct _UNICODE_STRING DllPath;                        // 3 elements, 0x8 bytes (sizeof)
/*0x038*/     struct _UNICODE_STRING ImagePathName;                  // 3 elements, 0x8 bytes (sizeof)
/*0x040*/     struct _UNICODE_STRING CommandLine;                    // 3 elements, 0x8 bytes (sizeof)
/*0x048*/     VOID*        Environment;
/*0x04C*/     ULONG32      StartingX;
/*0x050*/     ULONG32      StartingY;
/*0x054*/     ULONG32      CountX;
/*0x058*/     ULONG32      CountY;
.........................................
          }

然後...我們在看看 _UNICODE_STRING 的結構...
          typedef struct _UNICODE_STRING  // 3 elements, 0x8 bytes (sizeof)
          {
/*0x000*/     UINT16       Length;
/*0x002*/     UINT16       MaximumLength;
/*0x004*/     UINT16*      Buffer;
          }UNICODE_STRING, *PUNICODE_STRING;

透過上面這串結構,我們可以寫出下面這段Code
  1. push eax
  2. push ebx
  3. mov eax, fs:[30h]        //指向:PEB+30h
  4. mov eax, [eax+10h]        //指向:_RTL_USER_PROCESS_PARAMETERS
  5. add eax, 38h            //偏移:ImagePathName
  6. add eax, 4h                //偏移:Buffer
  7. mov ebx, FakeImagePath    //把假的ImagePath暫放到ebx
  8. mov [eax], ebx            //修改Buffer的值
  9. pop ebx
  10. pop eax

PS:32bit Only
然後讓程式執行這段Code就可以過了。

底下附上Win7 64bit的結構資料,但是我還是搞不懂失敗的原因是啥...

PEB
          typedef struct _PEB                                                                               // 91 elements, 0x380 bytes (sizeof)
          {
/*0x000*/     UINT8        InheritedAddressSpace;
/*0x001*/     UINT8        ReadImageFileExecOptions;
/*0x002*/     UINT8        BeingDebugged;
              union                                                                                         // 2 elements, 0x1 bytes (sizeof)
              {
/*0x003*/         UINT8        BitField;
                  struct                                                                                    // 6 elements, 0x1 bytes (sizeof)
                  {
/*0x003*/             UINT8        ImageUsesLargePages : 1;                                                 // 0 BitPosition
/*0x003*/             UINT8        IsProtectedProcess : 1;                                                  // 1 BitPosition
/*0x003*/             UINT8        IsLegacyProcess : 1;                                                     // 2 BitPosition
/*0x003*/             UINT8        IsImageDynamicallyRelocated : 1;                                         // 3 BitPosition
/*0x003*/             UINT8        SkipPatchingUser32Forwarders : 1;                                        // 4 BitPosition
/*0x003*/             UINT8        SpareBits : 3;                                                           // 5 BitPosition
                  };
              };
/*0x008*/     VOID*        Mutant;
/*0x010*/     VOID*        ImageBaseAddress;
/*0x018*/     struct _PEB_LDR_DATA* Ldr;
/*0x020*/     struct _RTL_USER_PROCESS_PARAMETERS* ProcessParameters;
/*0x028*/     VOID*        SubSystemData;
/*0x030*/     VOID*        ProcessHeap;
........................................
          }



_RTL_USER_PROCESS_PARAMETERS
          typedef struct _RTL_USER_PROCESS_PARAMETERS                // 30 elements, 0x400 bytes (sizeof)
          {
/*0x000*/     ULONG32      MaximumLength;
/*0x004*/     ULONG32      Length;
/*0x008*/     ULONG32      Flags;
/*0x00C*/     ULONG32      DebugFlags;
/*0x010*/     VOID*        ConsoleHandle;
/*0x018*/     ULONG32      ConsoleFlags;
/*0x01C*/     UINT8        _PADDING0_[0x4];
/*0x020*/     VOID*        StandardInput;
/*0x028*/     VOID*        StandardOutput;
/*0x030*/     VOID*        StandardError;
/*0x038*/     struct _CURDIR CurrentDirectory;                       // 2 elements, 0x18 bytes (sizeof)
/*0x050*/     struct _UNICODE_STRING DllPath;                        // 3 elements, 0x10 bytes (sizeof)
/*0x060*/     struct _UNICODE_STRING ImagePathName;                  // 3 elements, 0x10 bytes (sizeof)
/*0x070*/     struct _UNICODE_STRING CommandLine;                    // 3 elements, 0x10 bytes (sizeof)
/*0x080*/     VOID*        Environment;
/*0x088*/     ULONG32      StartingX;
/*0x08C*/     ULONG32      StartingY;
/*0x090*/     ULONG32      CountX;
/*0x094*/     ULONG32      CountY;
...............................
          }

_UNICODE_STRING
          typedef struct _UNICODE_STRING    // 3 elements, 0x10 bytes (sizeof)
          {
/*0x000*/     UINT16       Length;
/*0x002*/     UINT16       MaximumLength;
/*0x004*/     UINT8        _PADDING0_[0x4];
/*0x008*/     UINT16*      Buffer;
          }UNICODE_STRING, *PUNICODE_STRING;

本月最夯