Quote Originally Posted by Indy View Post
The only question for what it is you need
Thanks for the info Indy. Need? Oh there's no need. In fact it shouldn't even be considered

That is always the problem of course j00ru, one needs to make certain assumptions. However in the simple situation, if we assume a known CSR_SERVER_DLL structure that will be used in the expected manner, then the ANSI_STRING Name field should always point to one of the 3 module names.


Here is a nice article describing a protocol for walking the heap

http://www.informit.com/articles/article.aspx?p=1081496

So as a thought experiment we could propose:

- Access csrss.exe PEB

- PEB.ProcessHeaps points to default process heap

- Walk the heap looking for allocations of appropriate size

- Test for identifiable Name string

ConServerDllInitialization and UserServerDllInitialization are both under "winsrv", but if you look at the results above, the ServerId field seems to match the DllIndex values from these defines, a second thing one could use for confirmation:

#define CSRSRV_SERVERDLL_INDEX 0
#define BASESRV_SERVERDLL_INDEX 1
#define CONSRV_SERVERDLL_INDEX 2
#define USERSRV_SERVERDLL_INDEX 3

Using HeapMemView and the proposed search criteria (allocation size + csr name string), the 4 CSR_SERVER_DLL structures are easily picked out with no false positives.


The header before the heap allocation is now identified as a HEAP_ENTRY structure. Similar to a POOL_HEADER it will give the Size of the allocation and is key to "walking" the entire heap accurately.

Now we can go back and look at the heap headers for the CSR_SERVER_DLL allocations. Like in POOL_HEADER, the true size of the allocation = (Size * granularity) = (0xc * 8) = 0x60 bytes for CSR_SERVER_DLL.

Code:
kd> dt _HEAP_ENTRY -b -v 162b50
struct _HEAP_ENTRY, 7 elements, 0x8 bytes
   +0x000 Size             : 0xc
   +0x002 PreviousSize     : 3
   +0x000 SubSegmentCode   : 0x0003000c 
   +0x004 SmallTagIndex    : 0xa5 ''
   +0x005 Flags            : 0x1 ''
   +0x006 UnusedBytes      : 0xe ''
   +0x007 SegmentIndex     : 0 ''
   
kd> dt _HEAP_ENTRY -b -v 162bb0
struct _HEAP_ENTRY, 7 elements, 0x8 bytes
   +0x000 Size             : 0xc
   +0x002 PreviousSize     : 0xc
   +0x000 SubSegmentCode   : 0x000c000c 
   +0x004 SmallTagIndex    : 0xb9 ''
   +0x005 Flags            : 0x1 ''
   +0x006 UnusedBytes      : 0xc ''
   +0x007 SegmentIndex     : 0 ''

kd> dt _HEAP_ENTRY -b -v 163a78
struct _HEAP_ENTRY, 7 elements, 0x8 bytes
   +0x000 Size             : 0xc
   +0x002 PreviousSize     : 9
   +0x000 SubSegmentCode   : 0x0009000c 
   +0x004 SmallTagIndex    : 0x80 ''
   +0x005 Flags            : 0x1 ''
   +0x006 UnusedBytes      : 0xd ''
   +0x007 SegmentIndex     : 0 ''

kd> dt _HEAP_ENTRY -b -v 163bd8
struct _HEAP_ENTRY, 7 elements, 0x8 bytes
   +0x000 Size             : 0xc
   +0x002 PreviousSize     : 8
   +0x000 SubSegmentCode   : 0x0008000c 
   +0x004 SmallTagIndex    : 0xb4 ''
   +0x005 Flags            : 0x1 ''
   +0x006 UnusedBytes      : 0xd ''
   +0x007 SegmentIndex     : 0 ''

Enough of that anyway, it's just another way of looking at things.

Very clever idea of using a wrapper or calling the module initialization routines supplying your own buffer. The DONT_RESOLVE_DLL_REFERENCES or LOAD_LIBRARY_AS_DATAFILE flags on loading the modules might help to not "shake the boat" too much... The initialization of the CSR_SERVER_DLL structure seems to be scattered though, some fields are filled in CsrLoadServerDll, some in the individual *ServerDllInitialization routines. So just calling the init routines with a supplied buffer might not get all the definitions, but maybe the ones you need at least.

Anticipating POC...