Re[2]: !wlse extension

> Well Dr NewComer I Am Not Sure If Visual Studio Debugger Can handle

parsing

Working Set List Entries

in kernelmode

Pages in Both process are a simple one liner with VirtualAlloc Pasted
below only change is the sprintf_string process 1 has WsleTestOne
process 2 has WsleTestTwo

*****
OK, I was a bit confused from the first post, because it sounded like you
were sharing a page between two processes. This makes it clearer that you
have two independent processes each of which is allocating a private page.
****

int main(void)
{
PCHAR PageAllot = (PCHAR) VirtualAlloc(
NULL,
4096,
****
Generally, you should not assume pages are 4096 bytes; there’s an API that
reurns this value
*****

MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE
);
if (PageAllot != 0 ) {
sprintf_s(
PageAllot,
200,
“WsleTestOne Alloted This Page @ %p\n”,
PageAllot
);
DebugBreak();
VirtualFree(
PageAllot,
0,
MEM_RELEASE
);
return 0;
}
return 1;
}

and i want to break both these similar process in kernel debugger
simultaneously
*****
I have never tried to use a kernel debugger to handle int3 calls from user
space. The VS debugger works nicely for this purpose. But since you need
to be in the kernel to get the information you need, VS isn’t going to be
much help here. What will happen is that the first process to hit the
breakpoint enters windbg, and Windows stops. This means the second
process cannot run until you proceed from the breakpoint, at which point
the first process frees the memory.

It is an ugly hack, but perhaps putting a lengthy Sleep() call after the
breakpoint call will help.
joe
*****

and want to examine wsle

like below

kd> g
Break instruction exception - code 80000003 (first chance)
ntdll!DbgBreakPoint:
001b:7c90120e cc int 3
kd> .process /p /r
Implicit process is now ffb38ad8
.cache noforcedecodeptes done
Loading User Symbols

*** WARNING: Unable to verify checksum for WsleTestModOne.exe
kd> kbL
ChildEBP RetAddr Args to Child
0012ff6c 00401051 00350000 0012ffc0 004013a3 ntdll!DbgBreakPoint
0012ff78 004013a3 00000001 00332ea8 00332ef0 WsleTestModOne!main+0x41
0012ffc0 7c817067 00380036 00360037 7ffdc000
WsleTestModOne!__tmainCRTStartup+0xfb
0012fff0 00000000 004013fa 00000000 78746341
kernel32!BaseProcessStart+0x23

kd> ?? ((((nt!_EPROCESS *)@$proc)->Vm).VmWorkingSetList)->Wsle->u1

union __unnamed
+0x000 VirtualAddress : 0xc0300203 Void
+0x000 Long : 0xc0300203
+0x000 e1 : _MMWSLENTRY

kd> .for( r $t0 =5d ; $t0<61;R $t0 = $t0+1) {da
(poi(0xc050369c+$t0*4)&0xfffff000) l40 }
00413000 “.}.”
7c814000 “torageOnILockBytes”
00350000 "WsleTestOne Alloted This Page @ "
00350020 “00350000.”
00251000 “”

On 5/23/12, xxxxx@flounder.com wrote:
>> Visual Studio has supported multiprocess debugging for years. So I
>> would
>> suggest looking into that as a better solution. In my lab exercise, we
>> had
>> two programs writing to a shared page, and unless there was a breakpoint
>> set in the receiver, it would continue to run even while I was
>> single-stepping the sender.
>>
>> How are you “allocating” a page into both processes?
>> joe
>>
>>> Thanks Dr NewComer Your Comments are As usual quiet Right and i agree
>>> i should stop coding assembly styled C infact i posted the whole
>>> snippet a few posts above including declaration for PageAllot which
>>> incidentally was declared as LPVOID PageAllot;
>>>
>>> i dont know but i tried while (true) / i tried running the app in a
>>> usermode debugger and trapping it in kd but none of the things shows
>>> the newly alloted page in working set list
>>>
>>> let me clarify the whole purpose of the DEMO was to see the results of
>>> the pages allocated by two executables that has minor difference in
>>> them in any possible way (either by hook or crook)
>>>
>>> so basically the CONCEPT was to make two exes that each alloted a page
>>> wrote something to that page and broke into debugger using
>>> DebugBreak()
>>>
>>> now this posed a problem once the first app broke in KD i couldn’t
>>> execute the second app
>>> so to bypass this problem i assembled an infinite jump let it spin and
>>> executed the second app which again broke in KD
>>>
>>> now i could examine both of them side by side in KD
>>>
>>> so after the DEMO i was trying to improve the strategy
>>>
>>> so i posed the question to the group asking if there is a better way
>>> to break two apps simultaneously in any way possible exactly like
>>> DebugBreak breaks in KD
>>>
>>> while i did it with asm _emit { 0xeb 0xfe } inline in code
>>> instead of DebugBreak()
>>>
>>> or some while (true)
>>>
>>> or when run in a local debugger and redirecting the output to kd (viz
>>> ntsd -d “mytestapp.exe”
>>>
>>> the working set list (dt nt!_MMWSL <
_______________> ->wsle) donot
>>> show the PAGE that was alloted
>>>
>>> they were visible as posted in an earlier post only immediatly after
>>> DebugBreak In kernel
>>>
>>> possibly because of BalanceSetManagers background operation or some
>>> thing which i am not sure of either terminology or logic
>>>
>>>
>>>
>>> just for the sake of referance i am pasting the earlier posts content
>>>
>>>
>>> well even though the address seem to be same the contents differ based
>>> on process
>>>
>>> to confirm compile these few lines into two executables by making a
>>> difference between them as follows
>>>
>>> Comparing files WsleTestOne.cpp and WSLETESTTWO.CPP
>>> WsleTestOne.cpp
>>> 200,
>>> “WsleTestOne Alloted This Page\n”
>>> );
>>>
WSLETESTTWO.CPP
>>> 200,
>>> “WsleTestTwo Alloted This Page\n”
>>> );
>>> *****
>>>
>>> #include <windows.h>
>>> #include <stdio.h>
>>> int main(void)
>>> {
>>> printf(
>>> “lets test wsle entries by alloting a page writing to
>>> \n”
>>> “that page and checking that page in wsldata as mmwsl*
>>> \n”
>>> “for all processes seems to be located at same Address
>>> \n”
>>> );
>>> LPVOID PageAllot;
>>> if (( PageAllot = VirtualAlloc(
>>> NULL,
>>> 4096,
>>> MEM_COMMIT | MEM_RESERVE,
>>> PAGE_EXECUTE_READWRITE
>>> ) ) == 0 ) {
>>> printf(
>>> “virtual Alloc Failed\n”
>>> );
>>> return 0;
>>> }
>>> printf (
>>> “Page Allocated at %p\n”,
>>> PageAllot
>>> );
>>> sprintf_s(
>>> (char )PageAllot,
>>> 200,
>>> “WsleTestOne Alloted This Page\n”
>>> );
>>> DebugBreak();
>>> VirtualFree(
>>> NULL,
>>> 1000,
>>> MEM_RELEASE
>>> );
>>> return 1;
>>> }
>>>
>>> run the first app and let it break in kd
>>>
>>> when it breaks assemble an infinte jmp (0xeb 0xfe ) at the return
>>> address on stack and hit G
>>> the app will be spinning indefinitely
>>>
>>> launch the second executable and let it break in kd
>>>
>>> when it broke you will have two executables with just minor
>>> differences and you compare the
>>> pages
>>>
>>> even though the address 0xc088 whatever appears to be same
>>> the page contents will definately not be the same
>>>
>>> see below an output
>>>
>>> kd> !grep -i -b2 -a1 -e “wsle” -c “!process 0 0”
>>> PROCESS ffa21228 SessionId: 0 Cid: 07f0 Peb: 7ffdc000 ParentCid:
>>> 0574
>>> DirBase: 0255d000 ObjectTable: e1bf01a0 HandleCount: 7.
>>> Image: WsleTestTwo.exe
>>>
>>> PROCESS ff9d4250 SessionId: 0 Cid: 0104 Peb: 7ffd4000 ParentCid:
>>> 0574
>>> DirBase: 046bb000 ObjectTable: e1750be0 HandleCount: 7.
>>> Image: WsleTestOne.exe
>>>
>>> kd> .process /p ffa21228
>>> Implicit process is now ffa21228
>>> .cache forcedecodeuser done
>>> kd> .shell -ci "r $t0 = 0; .while ( $t0< 0xd3 ) { dc /c 8
>>> (poi(0xc050369c+($t0
4))&0xfffff000) l 8; r $t0 = $t0+1}" grep -i
>>> “wsle”
>>> 00350000 656c7357 74736554 206f7754 6f6c6c41 20646574 73696854
>>> 67615020 00000a65 WsleTestTwo Alloted This Page…
>>> .shell: Process exited
>>> kd> .process /p ff9d4250
>>> Implicit process is now ff9d4250
>>> .cache forcedecodeuser done
>>> kd> .shell -ci “r $t0 = 0; .while ( $t0< 0xd3 ) { dc /c 8
>>> (poi(0xc050369c+($t0*4))&0xfffff000) l 8; r $t0 = $t0+1}” grep -i
>>> “wsle”
>>> 00350000 656c7357 74736554 20656e4f 6f6c6c41 20646574 73696854
>>> 67615020 00000a65 WsleTestOne Alloted This Page…
>>> .shell: Process exited
>>> kd> dt nt!_EPROCESS vm.vmworkingsetlist ffa21228
>>> +0x1f8 Vm :
>>> +0x020 VmWorkingSetList : 0xc0503000 _MMWSL
>>> kd> dt nt!_EPROCESS vm.vmworkingsetlist ff9d4250
>>> +0x1f8 Vm :
>>> +0x020 VmWorkingSetList : 0xc0503000 _MMWSL
>>> kd> dt nt!_EPROCESS vm.vmworkingsetlist->Wsle ffa21228
>>> +0x1f8 Vm :
>>> +0x020 VmWorkingSetList :
>>> +0x014 Wsle : 0xc050369c _MMWSLE
>>> kd> dt nt!_EPROCESS vm.vmworkingsetlist->Wsle ff9d4250
>>> +0x1f8 Vm :
>>> +0x020 VmWorkingSetList :
>>> +0x014 Wsle : 0xc050369c _MMWSLE
>>>
>>>
>>>
>>>
>>>
>>>
>>> On 5/21/12, xxxxx@alice.it
>>> wrote:
>>>>> compile these few lines into two executables by making a difference
>>>>> between them as follows
>>>>> run the first app and let it break in kd when it breaks assemble an
>>>>> infinte jmp (0xeb 0xfe ) at the return address on stack and hit G the
>>>>> app
>>>>> will be spinning indefinitely
>>>>
>>>> I compiled and run the two executables (compiled using VC 10) on my
>>>> Win
>>>> XP
>>>> laptop…however they break in user windbg debugger (not lkd or
>>>> kd)…
>>>>
>>>> Can you give me some help ??
>>>>
>>>>
>>>>
>>>> —
>>>> WINDBG is sponsored by OSR
>>>>
>>>> For our schedule of WDF, WDM, debugging and other seminars visit:
>>>> http://www.osr.com/seminars
>>>>
>>>> To unsubscribe, visit the List Server section of OSR Online at
>>>> http://www.osronline.com/page.cfm?name=ListServer
>>>>
>>>
>>> —
>>> WINDBG is sponsored by OSR
>>>
>>> For our schedule of WDF, WDM, debugging and other seminars visit:
>>> http://www.osr.com/seminars
>>>
>>> To unsubscribe, visit the List Server section of OSR Online at
>>> http://www.osronline.com/page.cfm?name=ListServer
>>>
>>
>>
>>
>> —
>> WINDBG is sponsored by OSR
>>
>> For our schedule of WDF, WDM, debugging and other seminars visit:
>> http://www.osr.com/seminars
>>
>> To unsubscribe, visit the List Server section of OSR Online at
>> http://www.osronline.com/page.cfm?name=ListServer
>>
>
> —
> WINDBG is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
></stdio.h></windows.h>

I completed the setup as suggested and now it works

kd> kb
ChildEBP RetAddr Args to Child
0012fdfc 00411abc 00300034 00390036 7ffdf000 ntdll!DbgBreakPoint
0012fedc 00412020 00000001 00320ca0 00320ce0 WSLE!main+0x8c [c:\documents and settings\20144620\my documents\visual studio projects\wsle\wsle.cpp @ 17]
0012ffc0 7c816d4f 00300034 00390036 7ffdf000 WSLE!mainCRTStartup+0x170 [f:\vs70builds\3077\vc\crtbld\crt\src\crt0.c @ 259]
0012fff0 00000000 00411339 00000000 78746341 kernel32!BaseProcessStart+0x23

coming back in the post, could you help me in understanding the long command…

kd> .shell -ci “r $t0 = 0; .while ( $t0< 0xd3 ) { dc /c 8 (poi(0xc050369c+($t0*4))&0xfffff000) l 8; r $t0 = $t0+1}” grep -i “wsle”
00350000 656c7357 74736554 206f7754 6f6c6c41 20646574 73696854 67615020 00000a65 WsleTestTwo Alloted This Page…
.shell: Process exited

in particular what it refers to the address 0xc050369c ? (Maybe it is the virtual address of the allocated page…)

0xc050369c is Wsle i already gave you that

kd> dt nt!_EPROCESS vm.vmworkingsetlist->Wsle ffa21228
+0x1f8 Vm :
+0x020 VmWorkingSetList :
+0x014 Wsle : 0xc050369c _MMWSLE

kd> !process 0 0 WsleTestOne.exe
PROCESS 811d0380 SessionId: 0 Cid: 0ce4 Peb: 7ffdf000 ParentCid: 0578
DirBase: 061d2000 ObjectTable: e19794f0 HandleCount: 7.
Image: WsleTestOne.exe

kd> .process /p
Implicit process is now 811d0380
.cache noforcedecodeptes done

kd> $$ we are already in process Context @$proc is; ? @$proc
Evaluate expression: -2128804992 = 811d0380

kd> $$ the _MMSUPPORT structure is called Vm ; dt nt!_EPROCESS vm @$proc
+0x1f8 Vm : _MMSUPPORT

kd> $$ the _MMWSL structure is called VmWorkingSetList ; dt
nt!_EPROCESS vm.VmWorkingSetList @$proc
+0x1f8 Vm :
+0x020 VmWorkingSetList : 0xc0503000 _MMWSL

kd> $$ the _MMWSLE structure is called Wsle ; dt nt!_EPROCESS
vm.VmWorkingSetList->Wsle @$proc
+0x1f8 Vm :
+0x020 VmWorkingSetList :
+0x014 Wsle : 0xc050369c _MMWSLE

kd> $$ the FirstFree Entry in this structure is at ; dt nt!_EPROCESS
vm.VmWorkingSetList->FirstFree @$proc
+0x1f8 Vm :
+0x020 VmWorkingSetList :
+0x004 FirstFree : 0x9c

kd> $$ so we can check what all the pages contain by dumping them
using this script;r $t0 = 0; .while ( $t0< 0x9c ) { dc /c 8
(poi(0xc050369c+($t0*4))&0xfffff000) l 8; r $t0 = $t0+1}

we need to look at page start not somewhere random so discard the
trailing 3 bytes using

&0xfffff000

c0300000 070b3067 04f2d067 00000000 00000000 00000000 00000000
00000000 00000000 g0…g…
snip

00400000 00905a4d 00000003 00000004 0000ffff 000000b8 00000000
00000040 00000000 MZ…@… see MZ
wsletestone.Exe Dos header

00010000 004c0041 0055004c 00450053 00530052 00520050 0046004f
004c0049 003d0045 A.L.L.U.S.E.R.S.P.R.O.F.I.L.E. =. Environment

00020000 00001000 0000077c 00000001 00000000 00350001 00000000
00000003 00000007 …|…5…
_RTL_PROCESS_PARAMETERS See Length /to Stdhandle
7ffde000 0012ffb0 00130000 0012e000 00000000 00001e00 00000000
7ffde000 00000000 … !teb

0012f000 00460020 006c006f 00650064 005c0072 00730057 0065006c
00650054 00740073 .F.o.l.d.e.r..W.s.l.e.T.e.s.t. stack

snip

7c900000 00905a4d 00000003 00000004 0000ffff 000000b8 00000000
00000040 00000000 MZ…@… dll

00130000 78746341 00000020 00000001 00002498 000000c4 00000000
00000020 00000000 Actx …$… … stackbase

00401000 cccccccc 0006e9cc cccc0000 cccccccc 51ec8b55 41ec6068
024ce800 c4830000 …U…Qh`.A…L… exes .text
section

00350000 656c7357 74736554 20656e4f 6f6c6c41 20646574 73696854
67615020 00000a65 WsleTestOne Alloted This Page… virtual allocated
page with signature

7c800000 00905a4d 00000003 00000004 0000ffff 000000b8 00000000
00000040 00000000 MZ…@… dll dos header

and so on

On 5/29/12, xxxxx@alice.it wrote:
> I completed the setup as suggested and now it works
>
> kd> kb
> ChildEBP RetAddr Args to Child
> 0012fdfc 00411abc 00300034 00390036 7ffdf000 ntdll!DbgBreakPoint
> 0012fedc 00412020 00000001 00320ca0 00320ce0 WSLE!main+0x8c [c:\documents
> and settings\20144620\my documents\visual studio projects\wsle\wsle.cpp @
> 17]
> 0012ffc0 7c816d4f 00300034 00390036 7ffdf000 WSLE!mainCRTStartup+0x170
> [f:\vs70builds\3077\vc\crtbld\crt\src\crt0.c @ 259]
> 0012fff0 00000000 00411339 00000000 78746341 kernel32!BaseProcessStart+0x23
>
>
> coming back in the post, could you help me in understanding the long
> command…
>
> kd> .shell -ci “r $t0 = 0; .while ( $t0< 0xd3 ) { dc /c 8
> (poi(0xc050369c+($t0*4))&0xfffff000) l 8; r $t0 = $t0+1}” grep -i “wsle”
> 00350000 656c7357 74736554 206f7754 6f6c6c41 20646574 73696854 67615020
> 00000a65 WsleTestTwo Alloted This Page…
> .shell: Process exited
>
> in particular what it refers to the address 0xc050369c ? (Maybe it is the
> virtual address of the allocated page…)
>
>
> —
> WINDBG is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

Thanks for help !

kd> dt nt!_EPROCESS vm.VmWorkingSetList->FirstFree @$proc
+0x1f8 Vm :
+0x020 VmWorkingSetList :
+0x004 FirstFree : 0x9a

I’ve found this doc http://www.cs.umd.edu/~waa/412-F10/Lab3.pdf with some details about _MMWSL.

Here, IIUC, FirstFree (0x9a) should be the first entry available for next allocations…Each WS list contains a fixed maximum number of entries (possibly not valid if unused) ?

On 5/29/12, xxxxx@alice.it wrote:

> I’ve found this doc http://www.cs.umd.edu/~waa/412-F10/Lab3.pdf with some
> details about _MMWSL.
>

this lab outlines almost everything in the same way i posted except it
sets a break in wslist.c in kernel it seems

anyone with wrk access or access to that wslist.c as quoted below care
to explain how this lab breaks both process simultaneoulsy ??

< quote >
Here, two programs Other-Alloc.exe and alloc.exe are executed. Write
the content
?VirtualAlloc?Alloc Page mum ?..? in the page for the first process,
and write the content
?Other VirtualAlloc?Alloc Page mum?..? in the page for the second
process. Do not
perform any other operation. The purpose of this experiment is to be
able to see the difference
between the content of the two pages. In the experiment, the
breakpoint is set in Row 194 in
the kernel file wslist.c, and then two processes are run at the same
time. The records are
shown in the Table 3.

i am interested in knowing how the two process are run at same time
and broken at same time

i would love to know if there is a proper method to do it instead of

1 ) 0xeb 0xfe hack
2) inlining 0xeb 0xfe by __asm _emit hack
3) trying to sleep for inifnite time kludge
4) may be setting some Waitfor / event / semaphore / blah
blah and triggering it by
running a third app ?? // haven’t tried this approach
is on my to do list

versus

1) something graceful and elegant :slight_smile:

> Here, IIUC, FirstFree (0x9a) should be the first entry available for next
> allocations…Each WS list contains a fixed maximum number of entries
> (possibly not valid if unused) ?

first free is the slot where the nest allocation should happen
you can check that out by adding one more virtual alloc call and
checking free entry and dumping the page

kd> dt nt!_EPROCESS vm.vmworkingsetlist->firstfree @$proc
+0x1f8 Vm :
+0x020 VmWorkingSetList :
+0x004 FirstFree : 0x96
kd> da 350000
00350000 "WsleTestOne Alloted This Page @ "
00350020 “00350000.”
kd> g
Break instruction exception - code 80000003 (first chance)
7c90120e cc int 3
kd> dt nt!_EPROCESS vm.vmworkingsetlist->firstfree @$proc
+0x1f8 Vm :
+0x020 VmWorkingSetList :
+0x004 FirstFree : 0x97
kd> da 350000;da 360000
00350000 "WsleTestOne Alloted This Page @ "
00350020 “00350000.”
00360000 “Testing the First Free entry @ 0”
00360020 “0360000.”

code below

beware tweak it yourself do not ask code no error checking done and
magic numbers used

#include <windows.h>
#include <stdio.h>
int main(void)
{
PCHAR PageAllot = (PCHAR) VirtualAlloc(
NULL,
4096,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE
);
sprintf_s(
PageAllot,
200,
“WsleTestOne Alloted This Page @ %p\n”,
PageAllot
);
DebugBreak();
PCHAR PageAllot1 = (PCHAR) VirtualAlloc(
NULL,
4096,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE
);
sprintf_s(
PageAllot1,
200,
“Testing the First Free entry @ %p\n”,
PageAllot1
);
DebugBreak();
VirtualFree(
PageAllot,
0,
MEM_RELEASE
);
VirtualFree(
PageAllot1,
0,
MEM_RELEASE
);
return 1;
}

lastInitialisedWsleEntry contains a marker

+0x018 LastInitializedWsle : 0x258

kd> dd 0xc050369c+258*4 l1
c0503ffc fffffff0

never checked it but wsle entries can span upto

+0x02c HashTableStart : 0xc0704000 Void

any expert comments welcome on last sentence</stdio.h></windows.h>

ok the lastinitialised Entry in vmworkingsetlist is increased by 0x400
when wsle entries cross the limit and first free is a negative ie if
there are no free slot
then 0x400 free slots are made available when there is a requirement
see lastInitialised Entry becoming 0x658 from 0x258

as seen below

code to allot pages in a loop to simulate wsle array extension

#include <windows.h>
#include <stdio.h>
#define WSLEARRAYSIZE 0x300
int main(void)
{
int i;
PCHAR PageAllot[WSLEARRAYSIZE];
for ( i=0; i {
PageAllot[i] = (PCHAR) VirtualAlloc(
NULL,
4096,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE
);
sprintf_s(
PageAllot[i],
200,
“WsleTest loop no 0x%08x\t Page address @ %p\n”,
i,
PageAllot[i]
);
DebugBreak();
}
for ( i=0; i {
VirtualFree(
PageAllot[i],
0,
MEM_RELEASE
);
}
return 1;
}

result below watch the Lastinitialised Entry in the series

ntdll!DbgBreakPoint:
001b:7c90120e cc int 3
kd> dt nt!_EPROCESS vm.vmworkingsetlist->firstfree @$proc;g
+0x1f8 Vm :
+0x020 VmWorkingSetList :
+0x004 FirstFree : 0x256
Break instruction exception - code 80000003 (first chance)
ntdll!DbgBreakPoint:
001b:7c90120e cc int 3
kd> dt nt!_EPROCESS vm.vmworkingsetlist->firstfree @$proc;g
+0x1f8 Vm :
+0x020 VmWorkingSetList :
+0x004 FirstFree : 0x257
Break instruction exception - code 80000003 (first chance)
ntdll!DbgBreakPoint:
001b:7c90120e cc int 3
kd> dt nt!_EPROCESS vm.vmworkingsetlist->* @$proc
+0x1f8 Vm :
+0x020 VmWorkingSetList :
+0x000 Quota : 0
+0x004 FirstFree : 0x258
+0x008 FirstDynamic : 4
+0x00c LastEntry : 0x257
+0x010 NextSlot : 4
+0x014 Wsle : 0xc050369c _MMWSLE
+0x018 LastInitializedWsle : 0x258
+0x01c NonDirectCount : 0x5c
+0x020 HashTable : (null)
+0x024 HashTableSize : 0
+0x028 NumberOfCommittedPageTables : 0xb
+0x02c HashTableStart : 0xc0704000 Void
+0x030 HighestPermittedHashAddress : 0xc0c00000 Void
+0x034 NumberOfImageWaiters : 0
+0x038 VadBitMapHint : 0x40
+0x03c UsedPageTableEntries : [768] 0x2f
+0x63c CommittedPageTables : [24] 0xff
+0x248 VmDeleted : 0xd0800
+0x248 VmTopDown : 0xd0800
kd> dt nt!_EPROCESS vm.vmworkingsetlist->firstfree @$proc;g
+0x1f8 Vm :
+0x020 VmWorkingSetList :
+0x004 FirstFree : 0x258
Break instruction exception - code 80000003 (first chance)
ntdll!DbgBreakPoint:
001b:7c90120e cc int 3
kd> dt nt!_EPROCESS vm.vmworkingsetlist->* @$proc
+0x1f8 Vm :
+0x020 VmWorkingSetList :
+0x000 Quota : 0
+0x004 FirstFree : 0xfffffff
+0x008 FirstDynamic : 4
+0x00c LastEntry : 0x258
+0x010 NextSlot : 4
+0x014 Wsle : 0xc050369c _MMWSLE
+0x018 LastInitializedWsle : 0x258
+0x01c NonDirectCount : 0x5c
+0x020 HashTable : (null)
+0x024 HashTableSize : 0
+0x028 NumberOfCommittedPageTables : 0xb
+0x02c HashTableStart : 0xc0704000 Void
+0x030 HighestPermittedHashAddress : 0xc0c00000 Void
+0x034 NumberOfImageWaiters : 0
+0x038 VadBitMapHint : 0x40
+0x03c UsedPageTableEntries : [768] 0x2f
+0x63c CommittedPageTables : [24] 0xff
+0x248 VmDeleted : 0xd0800
+0x248 VmTopDown : 0xd0800
kd> dt nt!_EPROCESS vm.vmworkingsetlist->firstfree @$proc;g
+0x1f8 Vm :
+0x020 VmWorkingSetList :
+0x004 FirstFree : 0xfffffff
Break instruction exception - code 80000003 (first chance)
ntdll!DbgBreakPoint:
001b:7c90120e cc int 3
kd> dt nt!_EPROCESS vm.vmworkingsetlist->* @$proc
+0x1f8 Vm :
+0x020 VmWorkingSetList :
+0x000 Quota : 0
+0x004 FirstFree : 0x25c
+0x008 FirstDynamic : 6
+0x00c LastEntry : 0x25b
+0x010 NextSlot : 4
+0x014 Wsle : 0xc050369c _MMWSLE
+0x018 LastInitializedWsle : 0x658
+0x01c NonDirectCount : 0x5c
+0x020 HashTable : 0xc0704000 _MMWSLE_HASH
+0x024 HashTableSize : 0x200
+0x028 NumberOfCommittedPageTables : 0xb
+0x02c HashTableStart : 0xc0704000 Void
+0x030 HighestPermittedHashAddress : 0xc0c00000 Void
+0x034 NumberOfImageWaiters : 0
+0x038 VadBitMapHint : 0x40
+0x03c UsedPageTableEntries : [768] 0x2f
+0x63c CommittedPageTables : [24] 0xff
+0x248 VmDeleted : 0xd0800
+0x248 VmTopDown : 0xd0800

marker has shifted from 0x258 to 0x 658
kd> dd (0xc050369c+6584) l1
c0504ffc fffffff0

so this will probably happen till it reaches

kd> dd (0xc050369c+80258
4) l1
c0703ffc ???

which you are left to experiment and post the result back :slight_smile:

On 5/29/12, raj_r wrote:
> On 5/29/12, xxxxx@alice.it wrote:
>
>> I’ve found this doc http://www.cs.umd.edu/~waa/412-F10/Lab3.pdf with some
>> details about _MMWSL.
>>
>
> this lab outlines almost everything in the same way i posted except it
> sets a break in wslist.c in kernel it seems
>
> anyone with wrk access or access to that wslist.c as quoted below care
> to explain how this lab breaks both process simultaneoulsy ??
>
> < quote >
> Here, two programs Other-Alloc.exe and alloc.exe are executed. Write
> the content
> ?VirtualAlloc?Alloc Page mum ?..? in the page for the first process,
> and write the content
> ?Other VirtualAlloc?Alloc Page mum?..? in the page for the second
> process. Do not
> perform any other operation. The purpose of this experiment is to be
> able to see the difference
> between the content of the two pages. In the experiment, the
> breakpoint is set in Row 194 in
> the kernel file wslist.c, and then two processes are run at the same
> time. The records are
> shown in the Table 3.
>
> i am interested in knowing how the two process are run at same time
> and broken at same time
>
> i would love to know if there is a proper method to do it instead of
>
> 1 ) 0xeb 0xfe hack
> 2) inlining 0xeb 0xfe by __asm _emit hack
> 3) trying to sleep for inifnite time kludge
> 4) may be setting some Waitfor / event / semaphore / blah
> blah and triggering it by
> running a third app ?? // haven’t tried this approach
> is on my to do list
>
> versus
>
> 1) something graceful and elegant :slight_smile:
>
>
>
>
>> Here, IIUC, FirstFree (0x9a) should be the first entry available for next
>> allocations…Each WS list contains a fixed maximum number of entries
>> (possibly not valid if unused) ?
>
> first free is the slot where the nest allocation should happen
> you can check that out by adding one more virtual alloc call and
> checking free entry and dumping the page
>
> kd> dt nt!_EPROCESS vm.vmworkingsetlist->firstfree @$proc
> +0x1f8 Vm :
> +0x020 VmWorkingSetList :
> +0x004 FirstFree : 0x96
> kd> da 350000
> 00350000 "WsleTestOne Alloted This Page @ "
> 00350020 “00350000.”
> kd> g
> Break instruction exception - code 80000003 (first chance)
> 7c90120e cc int 3
> kd> dt nt!_EPROCESS vm.vmworkingsetlist->firstfree @$proc
> +0x1f8 Vm :
> +0x020 VmWorkingSetList :
> +0x004 FirstFree : 0x97
> kd> da 350000;da 360000
> 00350000 "WsleTestOne Alloted This Page @ "
> 00350020 “00350000.”
> 00360000 “Testing the First Free entry @ 0”
> 00360020 “0360000.”
>
> code below
>
> beware tweak it yourself do not ask code no error checking done and
> magic numbers used
>
> #include <windows.h>
> #include <stdio.h>
> int main(void)
> {
> PCHAR PageAllot = (PCHAR) VirtualAlloc(
> NULL,
> 4096,
> MEM_COMMIT | MEM_RESERVE,
> PAGE_EXECUTE_READWRITE
> );
> sprintf_s(
> PageAllot,
> 200,
> “WsleTestOne Alloted This Page @ %p\n”,
> PageAllot
> );
> DebugBreak();
> PCHAR PageAllot1 = (PCHAR) VirtualAlloc(
> NULL,
> 4096,
> MEM_COMMIT | MEM_RESERVE,
> PAGE_EXECUTE_READWRITE
> );
> sprintf_s(
> PageAllot1,
> 200,
> “Testing the First Free entry @ %p\n”,
> PageAllot1
> );
> DebugBreak();
> VirtualFree(
> PageAllot,
> 0,
> MEM_RELEASE
> );
> VirtualFree(
> PageAllot1,
> 0,
> MEM_RELEASE
> );
> return 1;
> }
>
> lastInitialisedWsleEntry contains a marker
>
> +0x018 LastInitializedWsle : 0x258
>
> kd> dd 0xc050369c+258*4 l1
> c0503ffc fffffff0
>
> never checked it but wsle entries can span upto
>
> +0x02c HashTableStart : 0xc0704000 Void
>
> any expert comments welcome on last sentence
></stdio.h></windows.h></stdio.h></windows.h>

I compiled last code (using sprintf() instead of sprintf_s() because it seems not supported on my compiler…)

on vpc XP target:

Y:\>WSLE.exe
Page Allocated at 00340000
Page Allocated at 00350000

when it breaks in kd the second time (page allocation @ 00350000)

kd> da 340000; da 350000
00340000 "WsleTestOne Alloted This Page @ "
00340020 “00340000.”
00350000 “Testing the First Free entry @ 0”
00350020 “0350000.”

kd> !wsle

Working Set @ c0503000
FirstFree 95 FirstDynamic 4
LastEntry 23d NextSlot 4 LastInitialized 258
NonDirect 57 HashTable 0 HashTableSize 0

FirstFree is 0x95 so last valid entry has index 0x94

kd> dd (0xc050369c + 0x94*4) L1
c05038ec 00350201

kd> !pte 00350000
VA 00350000
PDE at C0300000 PTE at C0000D40
contains 0F07C067 contains 0EFF3067
pfn f07c —DA–UWEV pfn eff3 —DA–UWEV

kd> !pfn eff3
PFN 0000EFF3 at address 81196EC8
flink 00000094 blink / share count 00000001 pteaddress C0000D40
reference count 0001 Cached color 0
restore pte 000000C0 containing page 00F07C Active M
Modified

As you can see the allocated page is “Modified” and actually PFN working set index is 0x94 (as expected…)

> As you can see the allocated page is “Modified” and actually PFN working set index is 0x94 (as expected…)

good so you still have a question ?

btw did you find out how much pages can be alloted before the wsle
last entry changes ?

does it grow linearly

if yes to what limit and what happens when a limit is reached ?

or does some thing else jump in and reset the last Entry back to square one ?

assuming you allot a million / billion / trillion /gazillion pages how
Wsle entries reflect them

can you read / view all the gazillion pages in windbg ?

what is the ultimate allotment before app / os crashes

did you compare the output of

!vm
!memusage

in kernel mode

did you on some point do a !vadump on a user mode debugger in the target

hope i gave you enough to chew :slight_smile:

and if you find some answers post back here so other searchers may
benefit from the dialog

On 5/31/12, xxxxx@alice.it wrote:
> I compiled last code (using sprintf() instead of sprintf_s() because it
> seems not supported on my compiler…)
>
> on vpc XP target:
>
> Y:&gt;WSLE.exe
> Page Allocated at 00340000
> Page Allocated at 00350000
>
> when it breaks in kd the second time (page allocation @ 00350000)
>
> kd> da 340000; da 350000
> 00340000 "WsleTestOne Alloted This Page @ "
> 00340020 “00340000.”
> 00350000 “Testing the First Free entry @ 0”
> 00350020 “0350000.”
>
> kd> !wsle
>
> Working Set @ c0503000
> FirstFree 95 FirstDynamic 4
> LastEntry 23d NextSlot 4 LastInitialized 258
> NonDirect 57 HashTable 0 HashTableSize 0
>
> FirstFree is 0x95 so last valid entry has index 0x94
>
> kd> dd (0xc050369c + 0x94*4) L1
> c05038ec 00350201
>
> kd> !pte 00350000
> VA 00350000
> PDE at C0300000 PTE at C0000D40
> contains 0F07C067 contains 0EFF3067
> pfn f07c —DA–UWEV pfn eff3 —DA–UWEV
>
>
> kd> !pfn eff3
> PFN 0000EFF3 at address 81196EC8
> flink 00000094 blink / share count 00000001 pteaddress C0000D40
> reference count 0001 Cached color 0
> restore pte 000000C0 containing page 00F07C Active M
>
> Modified
>
> As you can see the allocated page is “Modified” and actually PFN working set
> index is 0x94 (as expected…)
>
> —
> WINDBG is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

…If I will be able to do some test I will post back here…

anyway a doubt arises about working set management…as we seen, PFN database entries for “Active/Valid” pages in a working set (process or system WS) have a field containing working set index (an index in the working set page)…

In case of page belonging to a process’s working set why the related PFN database entry does not contain any reference to the process itself ? How can WS manager code understand which page frame belong to which process’ working set ?

kd> !wsle

Working Set @ c0503000
FirstFree 95 FirstDynamic 4
LastEntry 23d NextSlot 4 LastInitialized 258
NonDirect 57 HashTable 0 HashTableSize 0

FirstFree is 0x95 so last valid entry has index 0x94

kd> dd (0xc050369c + 0x94*4) L1
c05038ec 00350201 this can be an invalid XXXXXXXX too instead of
what you got viz 00350201

are you assuming something here ?

each process has a dir base

kd> dt nt!_EPROCESS pcb.DirectoryTableBase @$proc
+0x000 Pcb :
+0x018 DirectoryTableBase : [2] 0x3dfe000

you can get the physical page for a virtual address using !vtop and
this dirbase

!kd> !vtop 03dfe 350000
X86VtoP: Virt 00350000, pagedir 3dfe000
X86VtoP: PDE 3dfe000 - 062ed067
X86VtoP: PTE 62edd40 - 04024067
X86VtoP: Mapped phys 4024000
Virtual address 350000 translates to physical address 4024000.
kd> !dc 4024000

4024000 656c7357 74736554 20656e4f 6f6c6c41 WsleTestOne Allo

4024010 20646574 73696854 67615020 20402065 ted This Page @

4024020 35333030 30303030 0000000a 00000000 00350000…

On 5/31/12, xxxxx@alice.it wrote:
> …If I will be able to do some test I will post back here…
>
> anyway a doubt arises about working set management…as we seen, PFN
> database entries for “Active/Valid” pages in a working set (process or
> system WS) have a field containing working set index (an index in the
> working set page)…
>
> In case of page belonging to a process’s working set why the related PFN
> database entry does not contain any reference to the process itself ? How
> can WS manager code understand which page frame belong to which process’
> working set ?
>
> —
> WINDBG is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

> are you assuming something here ?

Trying to explain in another way…

PFN database entries store a working set index for Active/Valid pages belonging to either system or process working set…What is the usefulness of this field ? (…maybe there is not usefulness for WS manager itself…)

Note that the working set list structures are in the kernel space but the PTEs mapping them are process-specific rather than global. Which means you have to use .process /P or .process /i instead of .process /p if you want to look at WSLE entries of a non-current process.


From: raj_r
Sent: 5/28/2012 5:55 PM
To: Kernel Debugging Interest List
Subject: Re: [windbg] Re[2]: !wlse extension

0xc050369c is Wsle i already gave you that

kd> dt nt!_EPROCESS vm.vmworkingsetlist->Wsle ffa21228
+0x1f8 Vm :
+0x020 VmWorkingSetList :
+0x014 Wsle : 0xc050369c _MMWSLE

kd> !process 0 0 WsleTestOne.exe
PROCESS 811d0380 SessionId: 0 Cid: 0ce4 Peb: 7ffdf000 ParentCid: 0578
DirBase: 061d2000 ObjectTable: e19794f0 HandleCount: 7.
Image: WsleTestOne.exe

kd> .process /p
Implicit process is now 811d0380
.cache noforcedecodeptes done

kd> $$ we are already in process Context @$proc is; ? @$proc
Evaluate expression: -2128804992 = 811d0380

kd> $$ the _MMSUPPORT structure is called Vm ; dt nt!_EPROCESS vm @$proc
+0x1f8 Vm : _MMSUPPORT

kd> $$ the _MMWSL structure is called VmWorkingSetList ; dt
nt!_EPROCESS vm.VmWorkingSetList @$proc
+0x1f8 Vm :
+0x020 VmWorkingSetList : 0xc0503000 _MMWSL

kd> $$ the _MMWSLE structure is called Wsle ; dt nt!_EPROCESS
vm.VmWorkingSetList->Wsle @$proc
+0x1f8 Vm :
+0x020 VmWorkingSetList :
+0x014 Wsle : 0xc050369c _MMWSLE

kd> $$ the FirstFree Entry in this structure is at ; dt nt!_EPROCESS
vm.VmWorkingSetList->FirstFree @$proc
+0x1f8 Vm :
+0x020 VmWorkingSetList :
+0x004 FirstFree : 0x9c

kd> $$ so we can check what all the pages contain by dumping them
using this script;r $t0 = 0; .while ( $t0< 0x9c ) { dc /c 8
(poi(0xc050369c+($t0*4))&0xfffff000) l 8; r $t0 = $t0+1}

we need to look at page start not somewhere random so discard the
trailing 3 bytes using

&0xfffff000

c0300000 070b3067 04f2d067 00000000 00000000 00000000 00000000
00000000 00000000 g0…g…
snip

00400000 00905a4d 00000003 00000004 0000ffff 000000b8 00000000
00000040 00000000 MZ…@… see MZ
wsletestone.Exe Dos header

00010000 004c0041 0055004c 00450053 00530052 00520050 0046004f
004c0049 003d0045 A.L.L.U.S.E.R.S.P.R.O.F.I.L.E. =. Environment

00020000 00001000 0000077c 00000001 00000000 00350001 00000000
00000003 00000007 …|…5…
_RTL_PROCESS_PARAMETERS See Length /to Stdhandle
7ffde000 0012ffb0 00130000 0012e000 00000000 00001e00 00000000
7ffde000 00000000 … !teb

0012f000 00460020 006c006f 00650064 005c0072 00730057 0065006c
00650054 00740073 .F.o.l.d.e.r..W.s.l.e.T.e.s.t. stack

snip

7c900000 00905a4d 00000003 00000004 0000ffff 000000b8 00000000
00000040 00000000 MZ…@… dll

00130000 78746341 00000020 00000001 00002498 000000c4 00000000
00000020 00000000 Actx …$… … stackbase

00401000 cccccccc 0006e9cc cccc0000 cccccccc 51ec8b55 41ec6068
024ce800 c4830000 …U…Qh`.A…L… exes .text
section

00350000 656c7357 74736554 20656e4f 6f6c6c41 20646574 73696854
67615020 00000a65 WsleTestOne Alloted This Page… virtual allocated
page with signature

7c800000 00905a4d 00000003 00000004 0000ffff 000000b8 00000000
00000040 00000000 MZ…@… dll dos header

and so on

On 5/29/12, xxxxx@alice.it wrote:
> I completed the setup as suggested and now it works
>
> kd> kb
> ChildEBP RetAddr Args to Child
> 0012fdfc 00411abc 00300034 00390036 7ffdf000 ntdll!DbgBreakPoint
> 0012fedc 00412020 00000001 00320ca0 00320ce0 WSLE!main+0x8c [c:\documents
> and settings\20144620\my documents\visual studio projects\wsle\wsle.cpp @
> 17]
> 0012ffc0 7c816d4f 00300034 00390036 7ffdf000 WSLE!mainCRTStartup+0x170
> [f:\vs70builds\3077\vc\crtbld\crt\src\crt0.c @ 259]
> 0012fff0 00000000 00411339 00000000 78746341 kernel32!BaseProcessStart+0x23
>
>
> coming back in the post, could you help me in understanding the long
> command…
>
> kd> .shell -ci “r $t0 = 0; .while ( $t0< 0xd3 ) { dc /c 8
> (poi(0xc050369c+($t0*4))&0xfffff000) l 8; r $t0 = $t0+1}” grep -i “wsle”
> 00350000 656c7357 74736554 206f7754 6f6c6c41 20646574 73696854 67615020
> 00000a65 WsleTestTwo Alloted This Page…
> .shell: Process exited
>
> in particular what it refers to the address 0xc050369c ? (Maybe it is the
> virtual address of the allocated page…)
>
>
> —
> WINDBG is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>


WINDBG is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

@ Pavel Lebedynskiy

Thanks For the Response and thanks for stressing the /i options

@ Cianf

like Pavel Says this is another classic case of LKD not usable for
peeking at real things

you would need invasive debugging and physically changing process
context by letting the debugger run using go

try doing .process /p /r and a few register context changing commands
like .cxr / .thread @$thread etc and then viewing cr3 register

you won’t be able to view the correct cr3 register

the correct cr3 register is viewable only if you are physically in the
process context

like below

kd> .process /P 811387a0 we changed process context but cr3
register is still for old process viz out wsletestone.exe

Implicit process is now 811387a0
.cache forcedecodeptes done
kd> r cr3
cr3=00b4c000 <----- old cr3

kd> .process /P /i 811387a0
You need to continue execution (press ‘g’ ) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
kd> g
Break instruction exception - code 80000003 (first chance)
nt!RtlpBreakWithStatusInstruction:
0008:804e3592 cc int 3
kd> r cr3
cr3=00fe7000 new cr3

kd> !process @$proc 2
PROCESS 811387a0 SessionId: 0 Cid: 00e8 Peb: 7ffd7000 ParentCid: 02fc
DirBase: 00fe7000 ObjectTable: e1a24a58 HandleCount: 102.
Image: alg.exe

kd> .process /p ffae4da0
Implicit process is now ffae4da0
.cache forcedecodeuser done
kd> r cr3
cr3=00fe7000
kd> .process /P ffae4da0
Implicit process is now ffae4da0
.cache forcedecodeptes done
kd> r cr3
cr3=00fe7000
kd> .process /i ffae4da0
You need to continue execution (press ‘g’ ) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
kd> g
Break instruction exception - code 80000003 (first chance)
nt!RtlpBreakWithStatusInstruction:
0008:804e3592 cc int 3
kd> r cr3
cr3=01fcd000
kd> !process @$proc 2
PROCESS ffae4da0 SessionId: 0 Cid: 0578 Peb: 7ffdd000 ParentCid: 0554
DirBase: 01fcd000 ObjectTable: e18e8b38 HandleCount: 314.
Image: explorer.exe

rgrds

On 6/1/12, Pavel Lebedynskiy wrote:
> Note that the working set list structures are in the kernel space but the
> PTEs mapping them are process-specific rather than global. Which means you
> have to use .process /P or .process /i instead of .process /p if you want to
> look at WSLE entries of a non-current process.
> ________________________________
> From: raj_r
> Sent: 5/28/2012 5:55 PM
> To: Kernel Debugging Interest List
> Subject: Re: [windbg] Re[2]: !wlse extension
>
> 0xc050369c is Wsle i already gave you that
>
> kd> dt nt!_EPROCESS vm.vmworkingsetlist->Wsle ffa21228
> +0x1f8 Vm :
> +0x020 VmWorkingSetList :
> +0x014 Wsle : 0xc050369c _MMWSLE
>
>
> kd> !process 0 0 WsleTestOne.exe
> PROCESS 811d0380 SessionId: 0 Cid: 0ce4 Peb: 7ffdf000 ParentCid: 0578
> DirBase: 061d2000 ObjectTable: e19794f0 HandleCount: 7.
> Image: WsleTestOne.exe
>
> kd> .process /p
> Implicit process is now 811d0380
> .cache noforcedecodeptes done
>
> kd> $$ we are already in process Context @$proc is; ? @$proc
> Evaluate expression: -2128804992 = 811d0380
>
> kd> $$ the _MMSUPPORT structure is called Vm ; dt nt!_EPROCESS vm @$proc
> +0x1f8 Vm : _MMSUPPORT
>
> kd> $$ the _MMWSL structure is called VmWorkingSetList ; dt
> nt!_EPROCESS vm.VmWorkingSetList @$proc
> +0x1f8 Vm :
> +0x020 VmWorkingSetList : 0xc0503000 _MMWSL
>
>
> kd> $$ the _MMWSLE structure is called Wsle ; dt nt!_EPROCESS
> vm.VmWorkingSetList->Wsle @$proc
> +0x1f8 Vm :
> +0x020 VmWorkingSetList :
> +0x014 Wsle : 0xc050369c _MMWSLE
>
>
> kd> $$ the FirstFree Entry in this structure is at ; dt nt!_EPROCESS
> vm.VmWorkingSetList->FirstFree @$proc
> +0x1f8 Vm :
> +0x020 VmWorkingSetList :
> +0x004 FirstFree : 0x9c
>
> kd> $$ so we can check what all the pages contain by dumping them
> using this script;r $t0 = 0; .while ( $t0< 0x9c ) { dc /c 8
> (poi(0xc050369c+($t04))&0xfffff000) l 8; r $t0 = $t0+1}
>
> we need to look at page start not somewhere random so discard the
> trailing 3 bytes using
>
> &0xfffff000
>
>
>
> c0300000 070b3067 04f2d067 00000000 00000000 00000000 00000000
> 00000000 00000000 g0…g…
> snip
>
> 00400000 00905a4d 00000003 00000004 0000ffff 000000b8 00000000
> 00000040 00000000 MZ…@… see MZ
> wsletestone.Exe Dos header
>
> 00010000 004c0041 0055004c 00450053 00530052 00520050 0046004f
> 004c0049 003d0045 A.L.L.U.S.E.R.S.P.R.O.F.I.L.E. =.
> Environment
>
> 00020000 00001000 0000077c 00000001 00000000 00350001 00000000
> 00000003 00000007 …|…5…
> _RTL_PROCESS_PARAMETERS See Length /to Stdhandle
> 7ffde000 0012ffb0 00130000 0012e000 00000000 00001e00 00000000
> 7ffde000 00000000 …
> !teb
>
> 0012f000 00460020 006c006f 00650064 005c0072 00730057 0065006c
> 00650054 00740073 .F.o.l.d.e.r..W.s.l.e.T.e.s.t. stack
>
> snip
>
> 7c900000 00905a4d 00000003 00000004 0000ffff 000000b8 00000000
> 00000040 00000000 MZ…@… dll
>
> 00130000 78746341 00000020 00000001 00002498 000000c4 00000000
> 00000020 00000000 Actx …$… … stackbase
>
> 00401000 cccccccc 0006e9cc cccc0000 cccccccc 51ec8b55 41ec6068
> 024ce800 c4830000 …U…Qh`.A…L… exes .text
> section
>
> 00350000 656c7357 74736554 20656e4f 6f6c6c41 20646574 73696854
> 67615020 00000a65 WsleTestOne Alloted This Page… virtual allocated
> page with signature
>
> 7c800000 00905a4d 00000003 00000004 0000ffff 000000b8 00000000
> 00000040 00000000 MZ…@… dll dos header
>
> and so on
>
>
>
>
>
> On 5/29/12, xxxxx@alice.it wrote:
>> I completed the setup as suggested and now it works
>>
>> kd> kb
>> ChildEBP RetAddr Args to Child
>> 0012fdfc 00411abc 00300034 00390036 7ffdf000 ntdll!DbgBreakPoint
>> 0012fedc 00412020 00000001 00320ca0 00320ce0 WSLE!main+0x8c [c:\documents
>> and settings\20144620\my documents\visual studio projects\wsle\wsle.cpp @
>> 17]
>> 0012ffc0 7c816d4f 00300034 00390036 7ffdf000 WSLE!mainCRTStartup+0x170
>> [f:\vs70builds\3077\vc\crtbld\crt\src\crt0.c @ 259]
>> 0012fff0 00000000 00411339 00000000 78746341
>> kernel32!BaseProcessStart+0x23
>>
>>
>> coming back in the post, could you help me in understanding the long
>> command…
>>
>> kd> .shell -ci "r $t0 = 0; .while ( $t0< 0xd3 ) { dc /c 8
>> (poi(0xc050369c+($t0
4))&0xfffff000) l 8; r $t0 = $t0+1}" grep -i “wsle”
>> 00350000 656c7357 74736554 206f7754 6f6c6c41 20646574 73696854 67615020
>> 00000a65 WsleTestTwo Alloted This Page…
>> .shell: Process exited
>>
>> in particular what it refers to the address 0xc050369c ? (Maybe it is the
>> virtual address of the allocated page…)
>>
>>
>> —
>> WINDBG is sponsored by OSR
>>
>> For our schedule of WDF, WDM, debugging and other seminars visit:
>> http://www.osr.com/seminars
>>
>> To unsubscribe, visit the List Server section of OSR Online at
>> http://www.osronline.com/page.cfm?name=ListServer
>>
>
> —
> WINDBG is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>
>
>
>
> —
> WINDBG is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer

> you would need invasive debugging and physically changing process context by letting the debugger run using go

Just to check if I understand correctly…

when the target breaks into host kd, the debugger is in the stopped target process context; now if we move in another process context (using .process /p ) the cr3 register, however, will remain unchanged…

option .process /p allows to access also to pages physically resident in RAM but either in stanby or modified list (the related PTEs are actually in Transition)

option /P (capital P) extend the access to all user-mode and kernel-mode process; anyway to access to another process context we have to switch to that process context, right ?

with .process /i when we run go the target will run and, when “normal” CPU scheduler will select the specified process to run, it will break newly in host debugger. Now we stay physically in that process context…

Does it make sense ? thanks

well i wont stamp your assertion with a resounding yes (may be pavel
would step in an offer a technically sound explanation of the actual
state of ptes with respect to /p /P /r and /i)

but you are almost right

when you break into a target like you broke into WsleXXXX.exe

you are exactly in the process context of wslexxx.exe and
DirectoryTable upper 20 bits / Cr3 register will both have same
content

/p /P etc alters debugger output ie the debugger takes some steps to
retrieve data
of the specific process from memory / cache / etc

but the actual state of target is not modified

ie if you issue say .thread without any argument the state of debugger
is reset to state that the target was at the time of breakin

but if you issue an /i option the debugger will ask you to run with G
the debugger internally will set some bps and break again and when it
breaks it will physically be in the process context you requested

though

On 6/1/12, xxxxx@alice.it wrote:
>> you would need invasive debugging and physically changing process context
>> by letting the debugger run using go
>
> Just to check if I understand correctly…
>
> when the target breaks into host kd, the debugger is in the stopped target
> process context; now if we move in another process context (using .process
> /p ) the cr3 register, however, will remain unchanged…
>
> option .process /p allows to access also to pages physically
> resident in RAM but either in stanby or modified list (the related PTEs are
> actually in Transition)
>
> option /P (capital P) extend the access to all user-mode and kernel-mode
> process; anyway to access to another process context we have to switch to
> that process context, right ?
>
> with .process /i when we run go the target will run and, when
> “normal” CPU scheduler will select the specified process to run, it will
> break newly in host debugger. Now we stay physically in that process
> context…
>
> Does it make sense ? thanks
>
>
> —
> WINDBG is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

> /p /P etc alters debugger output ie the debugger takes some steps to retrieve data of the specific process from memory / cache / etc but the actual state of target is not modified

quoted from Windbg help:

"
/P
(Live debugging only) Translates all transition page table entries (PTEs) to physical addresses before access, if you use /P and Process is nonzero. Unlike the /p option, the /P option translates the PTEs for all user-mode and kernel-mode processes, not only the specified process. This translation might cause slowdowns, because the debugger must find the physical addresses for all memory in use "

from this description it seem “.process /P ” in kd will perform virtual->physical translations for all user-mode and kernel-mode processes…but if the debugger state is in the “stopped” process context (i.e. WsleXXXX.exe process context when it breaks into kd) which different kind of information can give /P option ? In other words is not clear to me the differences between /p and /P and how to view them…

kd> .cache

Max cache size is : 1048576 bytes (0x400 KB)
Total memory in cache : 10757 bytes (0xb KB)
Number of regions cached: 40
477 full reads broken into 502 partial reads
counts: 451 cached/51 uncached, 89.84% cached
bytes : 18865 cached/8517 uncached, 68.90% cached
** Transition PTEs are implicitly decoded
** Prototype PTEs are implicitly decoded

kd> .cache forcedecodeuser

Max cache size is : 1048576 bytes (0x400 KB)
Total memory in cache : 0 bytes (0 KB)
Number of regions cached: 0
0 full reads broken into 0 partial reads
counts: 0 cached/0 uncached, 0.00% cached
bytes : 0 cached/0 uncached, 0.00% cached
** Transition PTEs are implicitly decoded
** User virtual addresses are translated to physical addresses before access
** Prototype PTEs are implicitly decoded

kd> .cache forcedecodeptes

Max cache size is : 1048576 bytes (0x400 KB)
Total memory in cache : 0 bytes (0 KB)
Number of regions cached: 0
0 full reads broken into 0 partial reads
counts: 0 cached/0 uncached, 0.00% cached
bytes : 0 cached/0 uncached, 0.00% cached
** Transition PTEs are implicitly decoded
** Virtual addresses are translated to physical addresses before access
** Prototype PTEs are implicitly decoded

On 6/1/12, xxxxx@alice.it wrote:
>> /p /P etc alters debugger output ie the debugger takes some steps to
>> retrieve data of the specific process from memory / cache / etc but the
>> actual state of target is not modified
>
> quoted from Windbg help:
>
> "
> /P
> (Live debugging only) Translates all transition page table entries (PTEs) to
> physical addresses before access, if you use /P and Process is nonzero.
> Unlike the /p option, the /P option translates the PTEs for all user-mode
> and kernel-mode processes, not only the specified process. This translation
> might cause slowdowns, because the debugger must find the physical addresses
> for all memory in use "
>
>
> from this description it seem “.process /P ” in kd will perform
> virtual->physical translations for all user-mode and kernel-mode
> processes…but if the debugger state is in the “stopped” process context
> (i.e. WsleXXXX.exe process context when it breaks into kd) which different
> kind of information can give /P option ? In other words is not clear to me
> the differences between /p and /P and how to view them…

atleast one clear case example in document / help file could be
usefull though it is lacking and everyone is left to interpret it in
thier own way

my interpretation is like this

when you are broken in process context it implies that
.forcedecodeuser for that process is available so any !pte queries
for that specific process will yield proper results

but when your target computer is in one state and you ask debugger to
fetch the result for anotehr process context

you would be forced to use /P to get proper results

i am exactly sure of /p

here is a sample

kd> .process
Implicit process is now ffb3d7b8 wsletest process we broke here on
Debugbreak()
kd> !pte 400000
VA 00400000 !pte seems to work
PDE at C0300004 PTE at C0001000
contains 04D97067 contains 0033D025
pfn 4d97 —DA–UWEV pfn 33d ----A–UREV

kd> !pte 1000000 trying 1pte of explorer.exe
VA 01000000
PDE at C0300010 PTE at C0004000
contains 00000000
not valid

kd> .process ffae4da0 we set the explorer process context no dice
Implicit process is now ffae4da0
WARNING: .cache forcedecodeuser is not enabled
kd> !pte 1000000
VA 01000000
PDE at C0300010 PTE at C0004000
contains 00000000
not valid

kd> !pte 400000 the old wsle va seems to be still valid
VA 00400000
PDE at C0300004 PTE at C0001000
contains 04D97067 contains 0033D025
pfn 4d97 —DA–UWEV pfn 33d ----A–UREV

kd> .process /p ffae4da0 lets try setting /p for explorer.exe still
this is not working
Implicit process is now ffae4da0
.cache forcedecodeuser done
kd> !pte 1000000
VA 01000000
PDE at C0300010 PTE at C0004000
contains 00000000
not valid

kd> !pte 400000 wsle =test is still returning result
VA 00400000
PDE at C0300004 PTE at C0001000
contains 04D97067 contains 0033D025
pfn 4d97 —DA–UWEV pfn 33d ----A–UREV

kd> .process /P ffae4da0 lets force it to decode ptes for all process
Implicit process is now ffae4da0
.cache forcedecodeptes done
kd> !pte 400000
VA 00400000 the wsle pte is now invalid
PDE at C0300004 PTE at C0001000
contains 0761D067 contains 00000000
pfn 761d —DA–UWEV not valid

kd> !pte 1000000 explorer.exe pte returns results fro !pte now
VA 01000000
PDE at C0300010 PTE at C0004000
contains 0582A067 contains 05AD4025
pfn 582a —DA–UWEV pfn 5ad4 ----A–UREV

> In other words is not clear to me the differences between /p and /P and how to view them…

.process /p: Use this when you want to look at user space memory for a process other than the current one. Commands like .reload /user, !peb, !teb, walking the user stack etc. require this.

.process /P: Use this when you want to look at user space memory OR process-specific parts of the kernel space, such as page tables, session space or the working set list.

> .process /p: Use this when you want to look at user space memory for a process

other than the current one. Commands like .reload /user, !peb, !teb, walking the
user stack etc. require this.

so also a !pte query for user-mode VAs for a process other than the current one needs /P (capital P) option ?

> so also a !pte query for user-mode VAs for a process other than the current one needs /P (capital P) option ?

Yes.