All the statements below are xp-sp3 based
windbg can also be used to parse for RWX pages in VadTree
Copy paste following lines to **.txt and run the script $$>a< path to **.txt
script contents needs grep in path for text parsing
aS proc @#Process ;
aS procname @@c++( (char *)(((nt!_EPROCESS *) @#Process ))->ImageFileName ) ;
aS procvad @@c++( (((nt!_EPROCESS *) @#Process ))->VadRoot ) ;
.block { !for_each_process ".printf \"%20ma\t%p\t%p\n\n\",${procname}, ${proc} , ${procvad}; .echo \n;.shell -ci \"!vad ${procvad}\" grep \"EXECUTE_READWRITE\"" } ;
ad *
and then set the process context to approriate process and examine the memory from StartVpn to EndVpn
iirc Winlogon and csrss always had a few RWX pages
the csrss RWX page always seemed to contain lots of initialization _UNICODE_STRING
most of the pages wont be available for viewing you may need to live debug in Phase1Init Stage
sxe ibp;.reboot
on reboot set bp NtCreateProcessEx
until csrss is about to be created
bc * ; gu ;!vad on csrss _EPROCESS
csrss process at this point wont have the RWX page
only 4 vads will exist in csrss VadTree
you may need to follow from here and catch the allocation / writes and executions
csrss.exe 86acebe0 86d62660
86d39250 ( 4) 7f6f0 7f7ef 0 Mapped EXECUTE_READWRITE Pagefile-backed section
this oneliner will fetch you most of the strings in that page
.foreach (place { s -[1]b 7f6f0000 l?7000 0x7f } ) { r $t0 = place ; dS @$t0-7}
output of the above line
7f6f2170 "C:\WINDOWS"
7f6f2190 "C:\WINDOWS\system32"
7f6f21c0 "\BaseNamedObjects"
7f6f2208 ".罯...罯"
7f6f22b0 ".罯...罯"
7f6f221c "Autorun.inf"
7f6f2300 ".罯02.罯Software\Microsoft\Clock"
7f6f226c "DoesNotExist"
7f6f2260 ".罯"
7f6f2368 "ヘ罯...罯.罯"
7f6f22c4 "Clock.ini"
7f6f23d8 ".罯68.罯Control Panel\Color Scheme"
7f6f2418 "s"
7f6f230c "Software\Microsoft\Clock"
the winlogon RWX pages will contain Executble code most of them will start with
push cx push ax
sequence and end with an indirect call to somehwre via jmp eax
and some intermediate calls to unviewable / non existing locations
may need live analysis
never observed rwx pages in clean explorer / iexplore / services.exe processos
they exist only if some antivirus etc are installed
see below for an Avasted RWX
page in explorer.exe patching RtlSetCurrentDirectory_U
and loading snxhk.dll using LdrLoadDll()
this same patch can also be observed in iexplore.exe
.shell dir /b scan*vad*
scanvad4rwx.txt
lkd> $$>a< scanvad4rwx.txt
System 86fc6830 86fbfa90
smss.exe 86b0e020 86dfd008
csrss.exe 86acebe0 86f4e4d0
86d39250 ( 4) 7f6f0 7f7ef 0 Mapped EXECUTE_READWRITE Pagefile-backed section
winlogon.exe 86d7b918 86d58930
86ae8ee0 ( 8) 9550 9553 4 Private EXECUTE_READWRITE
86340690 ( 7) 29c90 29c93 4 Private EXECUTE_READWRITE
86f370d0 ( 6) 2a4f0 2a4f3 4 Private EXECUTE_READWRITE
86b13a38 ( 5) 46580 46583 4 Private EXECUTE_READWRITE
86da2a00 ( 6) 497c0 497c3 4 Private EXECUTE_READWRITE
services.exe 86b0a020 86ec15c8
86da7c20 (12) 380 380 1 Private EXECUTE_READWRITE
lsass.exe 86b2a6b8 86b21110
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
explorer.exe 86241260 86b86768
86b13d28 (13) 90 90 1 Private EXECUTE_READWRITE
86545e50 (11) 2b0 2b0 1 Private EXECUTE_READWRITE
86aa6878 (12) 2c0 2ca 11 Private EXECUTE_READWRITE
86b056a0 (10) 2d0 2da 11 Private EXECUTE_READWRITE
86b3b9c8 (12) 2e0 2ea 11 Private EXECUTE_READWRITE
AvastUI.exe 86315a00 860fc008
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
iexplore.exe 86aaf020 861b3f00
862ae9f8 (16) 150 150 1 Private EXECUTE_READWRITE
on rereading i noticed the below output is from a differnt session
so splitting
and examine the memory using lkd> .process /p /r 862543e8 & lkd> uf 150000
00150000 50 push eax
00150001 60 pushad
00150002 bd42001500 mov ebp,150042h
00150007 8b7d10 mov edi,dword ptr [ebp+10h]
0015000a 8b4518 mov eax,dword ptr [ebp+18h]
0015000d 8b5d1c mov ebx,dword ptr [ebp+1Ch]
00150010 8907 mov dword ptr [edi],eax
00150012 895f04 mov dword ptr [edi+4],ebx
00150015 897c2420 mov dword ptr [esp+20h],edi
00150019 8d454c lea eax,[ebp+4Ch]
0015001c 50 push eax
0015001d ff7548 push dword ptr [ebp+48h]
00150020 8d4550 lea eax,[ebp+50h]
00150023 50 push eax
00150024 8d4540 lea eax,[ebp+40h]
00150027 50 push eax
00150028 6aff push 0FFFFFFFFh
0015002a ff5508 call dword ptr [ebp+8]
0015002d 85c0 test eax,eax
0015002f 750f jne 00150040
00150031 33c9 xor ecx,ecx
00150033 8d4538 lea eax,[ebp+38h]
00150036 50 push eax
00150037 8d4528 lea eax,[ebp+28h]
0015003a 50 push eax
0015003b 51 push ecx
0015003c 51 push ecx
0015003d ff5500 call dword ptr [ebp]
00150040 61 popad
00150041 c3 ret
put the commands in one line
? @$t1+10 ; ? poi(@$t1+10) ; ln poi(@$t1+10); db (@$t1+18) l8; u (@$t1+18) l3;
? poi(@$t1+4c) ; ? poi(@$t1+48) ; ? poi(@$t1+50) ;? poi(@$t1+40) ; lm m ntdll* ;
ln poi(@$t1+8) ; ? poi(@$t1+38); db (@$t1+28) l8; du /c 40 poi(@$t1+2c) ;
? poi(@$t1); ln poi(@$t1);.echo patches RtlSetCurwith pattern and sets return
address [esp+20]to patched instruction calls ntvirtproct for a pagein ntdll
on successloads a dll using LdrLoadDll;
Evaluate expression: 1376338 = 00150052
Evaluate expression: 2089936810 = 7c91e7aa
(7c91e7aa) Exact matches: ntdll!RtlSetCurrentDirectory_U
0015005a 6a 6c 68 78 e9 91 7c e8 jlhx..|.
0015005a 6a6c push 6Ch
0015005c 6878e9917c push offset ntdll!`string'+0x34 (7c91e978)
00150061 e81501ffff call 0014017b
Evaluate expression: 64 = 00000040
Evaluate expression: 32 = 00000020
Evaluate expression: 4096 = 00001000
Evaluate expression: 2089934848 = 7c91e000
start end module name
7c900000 7c9b2000 ntdll (pdb symbols) f:\symbols\ntdll.pdb
(7c90d6ee) Exact matches: ntdll!NtProtectVirtualMemory
Evaluate expression: 1691353088 = 64d00000
0015006a 60 00 60 00 9a 00 15 00 `.`.....
0015009a "C:\Program Files\Alwil Software\Avast5\snxhk.dll"
Evaluate expression: 2089903043 = 7c9163c3
(7c9163c3) Exact matches: ntdll!LdrLoadDll = <no type information>
patches RtlSetCurwith pattern and sets return address
[esp+20] to patched instruction calls ntvirtproct for
a page in ntdll on success loads a dll using LdrLoadDll
UPDATE
the rwx page in csrss.exe is being created during CSRSRV initialization seems to be heap
i set a conditional break after csrss.exe is created on NtAllocateVirtualMemory to print the VadTree on every allocation
and i see that the rwx page is inserted while CSRSRV init and a CreateSharedSection is observed in call stack
sxe ibp;.reboot
on reboot bp NtCreateprocessEx and hit g;kb
till csrss.exe is about to be created
you can glean the process being created by looking at the unicode_string passed to RtlCreateUserProcess api in the callstack printed
dS should print ........................../csrss.exe
enter gu
go up to allow the process to be created
!process 0 1 csrss.exe
save eprocess to scratch pad
!vad VadRoot
you should observe 4 vads in csrss vad tree
now set this conditional breakpoint (substitute the saved eprocess inplace of 0x81160020
note use 0x notation
)
bp
bp nt!NtAllocateVirtualMemory "!vad @@c++(((nt!_EPROCESS *) 0x81160020)->VadRoot);kb;.echo \n;dd poi(@esp+8);"
if you persist with an access breakpoint you can catch when the rwx page is being added to the ProcessHeapList
see below
ntdll!RtlCreateHeap+0x5b9:
001b:7c9253de e8a6000000 call ntdll!RtlpAddHeapToProcessList
(7c925489)
kd> !heap
HEAPEXT: Unable to get address of *ntdll!RtlpGlobalTagHeap.
Index Address Name Debugging options enabled
1: 00160000
2: 00260000
kd>
p step over the call
ntdll!RtlCreateHeap+0x5be:
001b:7c9253e3 8b45e4 mov eax,dword ptr [ebp-1Ch]
kd> !heap
Index Address Name Debugging options enabled
1: 00160000
2: 00260000
3: 7f6f0000
kd> `!process 0 1 csrss.exe`
PROCESS `81160020` SessionId: 0 Cid: 01c4 Peb: 7ffde000 ParentCid: 014c
DirBase: 06e30000 ObjectTable: e14a7f38 HandleCount: 10.
Image: csrss.exe
VadRoot `812275c0 Vads 13`
dump vadtree
kd> `!vad 812275c0`
VAD level start end commit
812201d8 ( 1) 0 ff 0 Private READWRITE
812280e8 ( 2) 100 100 1 Private READWRITE
81229dd0 ( 3) 110 110 1 Private READWRITE
81222a88 ( 4) 120 15f 4 Private READWRITE
811f30b8 ( 5) 160 25f 3 Private READWRITE
81223b80 ( 6) 260 26f 6 Private READWRITE
812275c0 ( 0) 4a680 4a684 2 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\csrss.exe
811f4fd8 ( 2) 75b40 75b4a 2 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\csrsrv.dll
811cced0 ( 1) 7c900 7c9b1 5 Mapped Exe EXECUTE_WRITECOPY \WINDOWS\system32\ntdll.dll
8121f440 ( 3) `7f6f0 7f7ef 0 Mapped EXECUTE_READWRITE` Pagefile-backed section
81167108 ( 2) 7ffb0 7ffd3 0 Mapped READONLY Pagefile-backed section
811e1d30 ( 4) 7ffdd 7ffdd 1 Private READWRITE
811e21b0 ( 3) 7ffde 7ffde 1 Private READWRITE
Total VADs: 13 average level: 3 maximum depth: 6
dump call stack
kd> kb
ChildEBP RetAddr Args to Child
0015fda4 75b437b8 00007008 7f6f0000 00100000 ntdll!RtlCreateHeap+0x5be
0015fe28 75b42f9a 001626dd 00000000 00000000 CSRSRV!CsrSrvCreateSharedSection+0x23f
0015ff74 75b430f3 0000000a 001624f0 7c90dc9e CSRSRV!CsrParseServerCommandLine+0x255
0015ff88 4a68115d 0000000a 001624f0 00000005 CSRSRV!CsrServerInitialization+0x95
0015ffa8 4a6818d7 0000000a 001624f0 0016251c csrss!main+0x4f
0015fff4 00000000 7ffde000 000000c8 00000166 csrss!NtProcessStartup+0x1d2
list of breakpoints
kd> bl
0 e 8058124c 0001 (0001) nt!NtCreateProcessEx
1 e 805691ea 0001 (0001) nt!NtAllocateVirtualMemory "!vad @@c++(((nt!_EPROCESS *) 0x81160020)->VadRoot);kb;.echo \n;dd poi(@esp+8);"
2 e 7f6f0000 w 1 0001 (0001)
you can follow this methodology with winlogon further below in the chain
update to answer comment
the breakpoint @NtAllocateVirtualMemory did not catch the allocation of vad 12
which was RWX allotment from vad11 my breakpoint got hit only when vad 13 was allocated
and printing vadtree i found that the vads had increased by 2 and one of them was the 7f6f0000 rwx page so maybe another way is used to add the vad to vad tree insted of NtAllocateVirtualMemory it is possible that rwx needs to be reset and isnt being reset needs investigation
i can only confirm that the page is indeed HEAP and seems to mapped in almost every process
with EXECUTE_READ permissions on all the process vads except in csrss where it is RWX
lkd> .logopen c:\check7f6f0page.txt
Opened log file 'c:\check7f6f0page.txt'
lkd> !for_each_process ".process /p /r @#Process ; !grep -c \"!vad @@c++( ( ( nt!_EPROCESS *) @#Process )->VadRoot)\" -e \"7f6f0\""
lkd> .logclose
Closing open log file c:\check7f6f0page.txt
results show this page is mapped in all process
lkd> .shell grep "7f6f0 7f7ef 0 Mapped" c:\check7f6f0page.txt
<.shell waiting 1 second(s) for process>
86d39250 ( 4) 7f6f0 7f7ef 0 Mapped EXECUTE_READWRITE Pagefile-backed section
86d39250 ( 4) 7f6f0 7f7ef 0 Mapped EXECUTE_READWRITE Pagefile-backed section
86e87fd8 ( 4) 7f6f0 7f7ef 0 Mapped EXECUTE_READ Pagefile-backed section
86e87fd8 ( 4) 7f6f0 7f7ef 0 Mapped EXECUTE_READ Pagefile-backed section
86b96d10 ( 3) 7f6f0 7f7ef 0 Mapped EXECUTE_READ Pagefile-backed section
86b96d10 ( 3) 7f6f0 7f7ef 0 Mapped EXECUTE_READ Pagefile-backed section
86abfe80 ( 3) 7f6f0 7f7ef 0 Mapped EXECUTE_READ Pagefile-backed section
86abfe80 ( 3) 7f6f0 7f7ef 0 Mapped EXECUTE_READ Pagefile-backed section
86eaf3a8 ( 3) 7f6f0 7f7ef 0 Mapped EXECUTE_READ Pagefile-backed section
86eaf3a8 ( 3) 7f6f0 7f7ef 0 Mapped EXECUTE_READ Pagefile-backed section
86b3fda8 ( 4) 7f6f0 7f7ef 0 Mapped EXECUTE_READ Pagefile-backed section
86e77b20 ( 2) 7f6f0 7f7ef 0 Mapped EXECUTE_READ Pagefile-backed section
and confirms to structure _HEAP
lkd> dt -r nt!_HEAP 0x7f6f0000
+0x000 Entry : _HEAP_ENTRY
+0x000 Size : 0xc8
+0x002 PreviousSize : 0
+0x000 SubSegmentCode : 0x000000c8 Void
+0x004 SmallTagIndex : 0x1e ''
+0x005 Flags : 0x1 ''
+0x006 UnusedBytes : 0 ''
+0x007 SegmentIndex : 0 ''
+0x008 Signature : 0xeeffeeff
+0x00c Flags : 0x7008
+0x010 ForceFlags : 8
+0x014 VirtualMemoryThreshold : 0xfe00
+0x018 SegmentReserve : 0x100000
dump of 7f6f0000
lkd> dd 7f6f0000 l1c/4
7f6f0000 000000c8 0000011e eeffeeff 00007008
7f6f0010 00000008 0000fe00 00100000
and you can confirm this pattern is indeed heap if you look at ntdll!RtlCreateHeap
lkd> !grep -c "uf ntdll!RtlCreateHeap" -e "ebp-24h"
7c925dcd c745dc88050000 mov dword ptr [ebp-24h],588h
7c925de7 c745dcc0050000 mov dword ptr [ebp-24h],5C0h
7c925e87 8145dc80000000 add dword ptr [ebp-24h],80h
7c925eb1 8b75dc mov esi,dword ptr [ebp-24h]
7c93c079 0145dc add dword ptr [ebp-24h],eax
dis assemble where the address is used
lkd> u 7c925eb1
ntdll!RtlCreateHeap+0x421:
7c925eb1 8b75dc mov esi,dword ptr [ebp-24h]
7c925eb4 83c607 add esi,7
7c925eb7 83e6f8 and esi,0FFFFFFF8h
7c925eba 8bc6 mov eax,esi
7c925ebc c1e803 shr eax,3
7c925ebf 8b4de4 mov ecx,dword ptr [ebp-1Ch]
7c925ec2 668901 mov word ptr [ecx],ax
evaluate the expression
lkd> ? ((588 + 80 >> 3) + 7) & 0x0fffffff8
Evaluate expression: 200 = 000000c8
update
the RWX page in csrss is _CsrSrvSharedSectionHeap
== _CsrSrvSharedSectionBase
that specifc value is queried from registry and mapped with NtMapViewOfSection
or a Section Created using NtCreateSection
all of this happens under
csrss!main ->csrsrv.dll ->CsrsrvCreateSharedSection
reg query "hklm\system\currentcontrolset\control\session manager\subsystems\csrss"
! REG.EXE VERSION 3.0
HKEY_LOCAL_MACHINE\system\currentcontrolset\control\session manager\subsystems\csrss
CsrSrvSharedSectionBase REG_DWORD 0x7f6f0000