A forum for reverse engineering, OS internals and malware analysis 

 #18167  by myid
 Tue Feb 12, 2013 12:53 pm
rinn wrote:Hello,
myid wrote:But I just want to know how it works.
Yes indeed, starting from Windows Vista x64 EPROCESS->Wow64Process is no longer pointer on WOW64_PROCESS structure but simply a pointer to the PEB32.

Windows 2003 SP2
Code: Select all
PAGE:00000000006DD555                 mov     rax, [rsp+2E8h+var_2A0]
PAGE:00000000006DD55A                 mov     rcx, [rax+2A8h]
PAGE:00000000006DD561                 test    rcx, rcx
PAGE:00000000006DD564                 jz      short loc_6DD569
PAGE:00000000006DD566                 mov     r12, [rcx]
Code: Select all
  +0x2a8 Wow64Process     : Ptr64 _WOW64_PROCESS
Windows 7
Code: Select all
PAGE:000000014038E504                 mov     rcx, [rsp+468h+var_280] ; Object
PAGE:000000014038E50C                 mov     rbx, [rcx+320h]
Code: Select all
   +0x320 Wow64Process     : Ptr64 Void
Windows 8
Code: Select all
PAGE:000000014042EC7F                 mov     rcx, [rsp+4E8h+var_4A8] ; Object
PAGE:000000014042EC84                 mov     rbx, [rcx+418h]
Code: Select all
 +0x418 Wow64Process     : Ptr64 Void
Less code, less memory, faster.

Best Regards,
-rin
Thank you very much.
But my question is: What is the structure definition of PEB32.Ldr?
nt!_PEB32
+0x000 InheritedAddressSpace : UChar
......
+0x008 ImageBaseAddress : Uint4B
+0x00c Ldr : Uint4B
+0x010 ProcessParameters : Uint4B
......
+0x240 SpareTracingBits : Pos 2, 30 Bits
I don't think EP_X0FF's answer is correct. I think PEB32.Ldr is a structure of "LDR_DATA_TABLE_ENTRY32" BUT NOT "PEB_LDR_DATA32".
I try to use "LDR_DATA_TABLE_ENTRY32" structure of WIN7x86 on my program, it is wrong.
Another word, "LDR_DATA_TABLE_ENTRY32" on WIN7X64 is different from "LDR_DATA_TABLE_ENTRY32" on WIN7X86.
 #18173  by EP_X0FF
 Tue Feb 12, 2013 2:12 pm
myid wrote:I don't think EP_X0FF's answer is correct. I think PEB32.Ldr is a structure of "LDR_DATA_TABLE_ENTRY32" BUT NOT "PEB_LDR_DATA32".
I try to use "LDR_DATA_TABLE_ENTRY32" structure of WIN7x86 on my program, it is wrong.
Another word, "LDR_DATA_TABLE_ENTRY32" on WIN7X64 is different from "LDR_DATA_TABLE_ENTRY32" on WIN7X86.
Code: Select all
lkd> dt nt!_PEB32 7efde000
   +0x000 InheritedAddressSpace : 0 ''
   +0x001 ReadImageFileExecOptions : 0 ''
   +0x002 BeingDebugged    : 0 ''
   +0x003 BitField         : 0 ''
   +0x003 ImageUsesLargePages : 0y0
   +0x003 IsProtectedProcess : 0y0
   +0x003 IsLegacyProcess  : 0y0
   +0x003 IsImageDynamicallyRelocated : 0y0
   +0x003 SkipPatchingUser32Forwarders : 0y0
   +0x003 SpareBits        : 0y000
   +0x004 Mutant           : 0xffffffff
   +0x008 ImageBaseAddress : 0x400000
   +0x00c Ldr              : 0x77030200
Code: Select all
lkd> db 0x77030200
00000000`77030200  30 00 00 00 01 00 00 00-00 00 00 00 90 2f d5 00  0............/..
00000000`77030210  18 33 8b 0a 98 2f d5 00-20 33 8b 0a 20 30 d5 00  .3.../.. 3.. 0..
00000000`77030220  28 33 8b 0a 00 00 00 00-00 00 00 00 00 00 00 00  (3..............
00000000`77030230  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
ULONG Length
Code: Select all
30 00 00 00


= sizeof win32 PEB_LDR_DATA.

BOOLEAN Initialized
Code: Select all
01 00 00 00
Clearly visible LIST_ENTRY's.

All wow64 PEB structures are equal to their win32 parents, otherwise a lot of software will be incompatible with wow emulation.

Next. First LDR_TABLE_ENTRY32 from InLoadOrderModuleList
Code: Select all
lkd> dt nt!LIST_ENTRY32 0x77030200+c
   +0x000 Flink            : 0xd52f90
   +0x004 Blink            : 0xa8b3318
lkd> db 00d52f90
00000000`00d52f90  10 30 d5 00 0c 02 03 77-18 30 d5 00 14 02 03 77  .0.....w.0.....w
00000000`00d52fa0  00 00 00 00 00 00 00 00-00 00 40 00 f8 00 a7 00  ..........@.....
00000000`00d52fb0  00 70 85 00 4e 00 50 00-1a 1f d5 00 0e 00 10 00  .p..N.P.........
00000000`00d52fc0  5a 1f d5 00 00 40 00 00-ff ff ff ff 2c 47 df 00  Z....@......,G..
00000000`00d52fd0  30 48 03 77 19 5e 42 2a-00 00 00 00 00 00 00 00  0H.w.^B*........
00000000`00d52fe0  e0 2f d5 00 e0 2f d5 00-e8 2f d5 00 e8 2f d5 00  ./.../.../.../..
00000000`00d52ff0  58 b0 d7 00 00 3d d5 00-44 c9 f6 76 00 00 40 00  X....=..D..v..@.
00000000`00d53000  00 00 00 00 00 00 00 00-f6 1f d2 01 20 6e 00 08  ............ n..
Next, see DllBase of first item.

0x18 to skip first three LIST_ENTRY32
Code: Select all
lkd> dd 00d52f90+18 l1
00000000`00d52fa8  00400000
Next, get FullDllName, UNICODE_STRING32

0x24 offset of FullDllName
Code: Select all
lkd> db 00d52f90+24
00000000`00d52fb4  4e 00 50 00 1a 1f d5 00-0e 00 10 00 5a 1f d5 00  N.P.........Z...
00000000`00d52fc4  00 40 00 00 ff ff ff ff-2c 47 df 00 30 48 03 77  .@......,G..0H.w
00000000`00d52fd4  19 5e 42 2a 00 00 00 00-00 00 00 00 e0 2f d5 00  .^B*........./..
00000000`00d52fe4  e0 2f d5 00 e8 2f d5 00-e8 2f d5 00 58 b0 d7 00  ./.../.../..X...
00000000`00d52ff4  00 3d d5 00 44 c9 f6 76-00 00 40 00 00 00 00 00  .=..D..v..@.....
00000000`00d53004  00 00 00 00 f6 1f d2 01-20 6e 00 08 50 35 d5 00  ........ n..P5..
00000000`00d53014  90 2f d5 00 58 35 d5 00-98 2f d5 00 48 36 d5 00  ./..X5.../..H6..
00000000`00d53024  1c 02 03 77 00 00 f3 76-00 00 00 00 00 00 18 00  ...w...v........
0x28 - offset of FullDllName->Buffer
Code: Select all
lkd> db 00d52f90+24+4
00000000`00d52fb8  1a 1f d5 00 0e 00 10 00-5a 1f d5 00 00 40 00 00  ........Z....@..
00000000`00d52fc8  ff ff ff ff 2c 47 df 00-30 48 03 77 19 5e 42 2a  ....,G..0H.w.^B*
00000000`00d52fd8  00 00 00 00 00 00 00 00-e0 2f d5 00 e0 2f d5 00  ........./.../..
00000000`00d52fe8  e8 2f d5 00 e8 2f d5 00-58 b0 d7 00 00 3d d5 00  ./.../..X....=..
00000000`00d52ff8  44 c9 f6 76 00 00 40 00-00 00 00 00 00 00 00 00  D..v..@.........
00000000`00d53008  f6 1f d2 01 20 6e 00 08-50 35 d5 00 90 2f d5 00  .... n..P5.../..
00000000`00d53018  58 35 d5 00 98 2f d5 00-48 36 d5 00 1c 02 03 77  X5.../..H6.....w
00000000`00d53028  00 00 f3 76 00 00 00 00-00 00 18 00 3a 00 3c 00  ...v........:.<.
View buffer address
Code: Select all
lkd> dd 00d52f90+24+4 l1
00000000`00d52fb8  00d51f1a
Finally view dll name, first image, so it's EXE name.
Code: Select all
lkd> db 00d51f1a l50
00000000`00d51f1a  43 00 3a 00 5c 00 50 00-72 00 6f 00 67 00 72 00  C.:.\.P.r.o.g.r.
00000000`00d51f2a  61 00 6d 00 20 00 46 00-69 00 6c 00 65 00 73 00  a.m. .F.i.l.e.s.
00000000`00d51f3a  20 00 28 00 78 00 38 00-36 00 29 00 5c 00 51 00   .(.x.8.6.).\.Q.
00000000`00d51f4a  49 00 50 00 20 00 32 00-30 00 31 00 32 00 5c 00  I.P. .2.0.1.2.\.
00000000`00d51f5a  71 00 69 00 70 00 2e 00-65 00 78 00 65 00 00 00  q.i.p...e.x.e...
 #18179  by myid
 Tue Feb 12, 2013 4:56 pm
EP_X0FF wrote:
myid wrote:I don't think EP_X0FF's answer is correct. I think PEB32.Ldr is a structure of "LDR_DATA_TABLE_ENTRY32" BUT NOT "PEB_LDR_DATA32".
I try to use "LDR_DATA_TABLE_ENTRY32" structure of WIN7x86 on my program, it is wrong.
Another word, "LDR_DATA_TABLE_ENTRY32" on WIN7X64 is different from "LDR_DATA_TABLE_ENTRY32" on WIN7X86.
Code: Select all
lkd> dt nt!_PEB32 7efde000
   +0x000 InheritedAddressSpace : 0 ''
   +0x001 ReadImageFileExecOptions : 0 ''
   +0x002 BeingDebugged    : 0 ''
   +0x003 BitField         : 0 ''
   +0x003 ImageUsesLargePages : 0y0
   +0x003 IsProtectedProcess : 0y0
   +0x003 IsLegacyProcess  : 0y0
   +0x003 IsImageDynamicallyRelocated : 0y0
   +0x003 SkipPatchingUser32Forwarders : 0y0
   +0x003 SpareBits        : 0y000
   +0x004 Mutant           : 0xffffffff
   +0x008 ImageBaseAddress : 0x400000
   +0x00c Ldr              : 0x77030200
Code: Select all
lkd> db 0x77030200
00000000`77030200  30 00 00 00 01 00 00 00-00 00 00 00 90 2f d5 00  0............/..
00000000`77030210  18 33 8b 0a 98 2f d5 00-20 33 8b 0a 20 30 d5 00  .3.../.. 3.. 0..
00000000`77030220  28 33 8b 0a 00 00 00 00-00 00 00 00 00 00 00 00  (3..............
00000000`77030230  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
ULONG Length
Code: Select all
30 00 00 00


= sizeof win32 PEB_LDR_DATA.

BOOLEAN Initialized
Code: Select all
01 00 00 00
Clearly visible LIST_ENTRY's.

All wow64 PEB structures are equal to their win32 parents, otherwise a lot of software will be incompatible with wow emulation.

Next. First LDR_TABLE_ENTRY32 from InLoadOrderModuleList
Code: Select all
lkd> dt nt!LIST_ENTRY32 0x77030200+c
   +0x000 Flink            : 0xd52f90
   +0x004 Blink            : 0xa8b3318
lkd> db 00d52f90
00000000`00d52f90  10 30 d5 00 0c 02 03 77-18 30 d5 00 14 02 03 77  .0.....w.0.....w
00000000`00d52fa0  00 00 00 00 00 00 00 00-00 00 40 00 f8 00 a7 00  ..........@.....
00000000`00d52fb0  00 70 85 00 4e 00 50 00-1a 1f d5 00 0e 00 10 00  .p..N.P.........
00000000`00d52fc0  5a 1f d5 00 00 40 00 00-ff ff ff ff 2c 47 df 00  Z....@......,G..
00000000`00d52fd0  30 48 03 77 19 5e 42 2a-00 00 00 00 00 00 00 00  0H.w.^B*........
00000000`00d52fe0  e0 2f d5 00 e0 2f d5 00-e8 2f d5 00 e8 2f d5 00  ./.../.../.../..
00000000`00d52ff0  58 b0 d7 00 00 3d d5 00-44 c9 f6 76 00 00 40 00  X....=..D..v..@.
00000000`00d53000  00 00 00 00 00 00 00 00-f6 1f d2 01 20 6e 00 08  ............ n..
Next, see DllBase of first item.

0x18 to skip first three LIST_ENTRY32
Code: Select all
lkd> dd 00d52f90+18 l1
00000000`00d52fa8  00400000
Next, get FullDllName, UNICODE_STRING32

0x24 offset of FullDllName
Code: Select all
lkd> db 00d52f90+24
00000000`00d52fb4  4e 00 50 00 1a 1f d5 00-0e 00 10 00 5a 1f d5 00  N.P.........Z...
00000000`00d52fc4  00 40 00 00 ff ff ff ff-2c 47 df 00 30 48 03 77  .@......,G..0H.w
00000000`00d52fd4  19 5e 42 2a 00 00 00 00-00 00 00 00 e0 2f d5 00  .^B*........./..
00000000`00d52fe4  e0 2f d5 00 e8 2f d5 00-e8 2f d5 00 58 b0 d7 00  ./.../.../..X...
00000000`00d52ff4  00 3d d5 00 44 c9 f6 76-00 00 40 00 00 00 00 00  .=..D..v..@.....
00000000`00d53004  00 00 00 00 f6 1f d2 01-20 6e 00 08 50 35 d5 00  ........ n..P5..
00000000`00d53014  90 2f d5 00 58 35 d5 00-98 2f d5 00 48 36 d5 00  ./..X5.../..H6..
00000000`00d53024  1c 02 03 77 00 00 f3 76-00 00 00 00 00 00 18 00  ...w...v........
0x28 - offset of FullDllName->Buffer
Code: Select all
lkd> db 00d52f90+24+4
00000000`00d52fb8  1a 1f d5 00 0e 00 10 00-5a 1f d5 00 00 40 00 00  ........Z....@..
00000000`00d52fc8  ff ff ff ff 2c 47 df 00-30 48 03 77 19 5e 42 2a  ....,G..0H.w.^B*
00000000`00d52fd8  00 00 00 00 00 00 00 00-e0 2f d5 00 e0 2f d5 00  ........./.../..
00000000`00d52fe8  e8 2f d5 00 e8 2f d5 00-58 b0 d7 00 00 3d d5 00  ./.../..X....=..
00000000`00d52ff8  44 c9 f6 76 00 00 40 00-00 00 00 00 00 00 00 00  D..v..@.........
00000000`00d53008  f6 1f d2 01 20 6e 00 08-50 35 d5 00 90 2f d5 00  .... n..P5.../..
00000000`00d53018  58 35 d5 00 98 2f d5 00-48 36 d5 00 1c 02 03 77  X5.../..H6.....w
00000000`00d53028  00 00 f3 76 00 00 00 00-00 00 18 00 3a 00 3c 00  ...v........:.<.
View buffer address
Code: Select all
lkd> dd 00d52f90+24+4 l1
00000000`00d52fb8  00d51f1a
Finally view dll name, first image, so it's EXE name.
Code: Select all
lkd> db 00d51f1a l50
00000000`00d51f1a  43 00 3a 00 5c 00 50 00-72 00 6f 00 67 00 72 00  C.:.\.P.r.o.g.r.
00000000`00d51f2a  61 00 6d 00 20 00 46 00-69 00 6c 00 65 00 73 00  a.m. .F.i.l.e.s.
00000000`00d51f3a  20 00 28 00 78 00 38 00-36 00 29 00 5c 00 51 00   .(.x.8.6.).\.Q.
00000000`00d51f4a  49 00 50 00 20 00 32 00-30 00 31 00 32 00 5c 00  I.P. .2.0.1.2.\.
00000000`00d51f5a  71 00 69 00 70 00 2e 00-65 00 78 00 65 00 00 00  q.i.p...e.x.e...
Thank you, EP_X0FF.
 #18186  by kmd
 Wed Feb 13, 2013 11:08 am
im interested if i can manipulate 64 bit data from wow64 emulation. As i know wow64 process has two PEBs- one legacy PEB32 and native PEB(64) and every thread TEB32 and native TEB. Are they always located near each other ?
 #18187  by EP_X0FF
 Wed Feb 13, 2013 12:49 pm
kmd wrote:im interested if i can manipulate 64 bit data from wow64 emulation. As i know wow64 process has two PEBs- one legacy PEB32 and native PEB(64) and every thread TEB32 and native TEB. Are they always located near each other ?
Yes, every application running under wow64 has 2 PEB's. They are located next each other. Same for TEB's. The difference is in pointers length.

PEB32 has it own loader list, where located all win32 dll's, including special wow64 version of ntdll.dll (located in syswow64 folder)
Native PEB also owns loader list, where located native x64 ntdll.dll (mapped in memory before x86 wow64 ntdll) and wow64 emulator dlls (wow64, wow64cpu, wow64win, they all loaded from system32 folder). Native PEB can have fields with addresses > ULONG, so it should not be accessed directly without additional preparations, otherwise your 32 bit application will crash in best case.

You can manipulate x64 data with NtWow64WriteVirtualMemory64, NtWow64ReadVirtualMemory64, NtWow64QueryVirtualMemory64, NtWow64GetNativeSystemInformation, NtWow64QueryInformationProcess64. They all working with 64 bit data, so don't mess with their definitions.

See small example, it was used to test pdump64 few years ago.
Attachments
(3.98 KiB) Downloaded 34 times