Page 2 of 2 FirstFirst 12
Results 16 to 18 of 18

Thread: Windows CSRSS cross-version API Table

  1. #16
    Teach, Not Flame Kayaker's Avatar
    Join Date
    Oct 2000
    Posts
    4,085
    Blog Entries
    5
    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...

  2. #17
    Well, sorry for such a delay, I've been quite busy lately.

    @Kayaker: Thanks for sheding some more light on your concept Heap scanning is indeed a 99.9% stable method, it's just me that doesn't like basing on certain assumptions that might not always be true
    Anyway, good work!

    As for the wrapper DLL idea, and the Proof of Concept.
    The DONT_RESOLVE_DLL_REFERENCES or LOAD_LIBRARY_AS_DATAFILE flags on loading the modules might help to not "shake the boat" too much...
    Well, what's the purpose of not fully loading the original server libraries? If we're performing a dll-in-the-middle attack, by supplying a wrapper fake_winsrv.dll file, for instance - we still want winsrv.dll to be fully functional, since it is still responsible for normal server execution (csrss would not load winsrv.dll by himself).

    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.
    Certainly... However, don't you think that it would be pointless if it was CSRSS that filled the ApiBase, HighestApiSupported, DispatchTable fields instead of individual libraries? I personally think it would make no sense :-P

    To prove that my method works, I've speedily written the aforementioned wrapper lib, filtering the ConServerDllInitialization and UserServerDllInitialization exports, and storing the data initialized by winsrv in a text file [since it's a PoC, I haven't implemented any symbol-recognition mechanism to actually assoc the addresses with their names].

    After setting up the library and rebooting the system, C:\log.txt contains the following:
    Code:
    UserServer->ApiBase              = 0x00000400
    UserServer->HighestApiSupported  = 0x0000040b
    UserServer->DispatchTable        = 0x75b6d560
     -- Server Dispatch Table:
     [0x00000400] 0x75b48910
     [0x00000401] 0x75b48f18
     [0x00000402] 0x75b37977
     [0x00000403] 0x75b37b6c
     [0x00000404] 0x75b4796f
     [0x00000405] 0x75b316a9
     [0x00000406] 0x75b478cc
     [0x00000407] 0x75b37d09
     [0x00000408] 0x75b4787c
     [0x00000409] 0x75b4787c
     [0x0000040a] 0x75b3bd30
    ConServer->ApiBase              = 0x00000200
    ConServer->HighestApiSupported  = 0x00000255
    ConServer->DispatchTable        = 0x75b389f0
     -- Server Dispatch Table:
     [0x00000200] 0x75b3bae8
     [0x00000201] 0x75b45a50
     [0x00000202] 0x75b56627
     [0x00000203] 0x75b4694d
     [0x00000204] 0x75b569ab
     [0x00000205] 0x75b56c0b
     [0x00000206] 0x75b56cc1
     [0x00000207] 0x75b458c6
     [0x00000208] 0x75b324e5
     [0x00000209] 0x75b50a82
     [0x0000020a] 0x75b515b0
     [0x0000020b] 0x75b3411a
     [0x0000020c] 0x75b46a60
     [0x0000020d] 0x75b50b3f
     [0x0000020e] 0x75b50b77
     [0x0000020f] 0x75b50c15
     [0x00000210] 0x75b50c93
     [0x00000211] 0x75b32814
     [0x00000212] 0x75b50dc9
     [0x00000213] 0x75b50e2c
     [0x00000214] 0x75b46495
     [0x00000215] 0x75b461cd
     [0x00000216] 0x75b45c72
     [0x00000217] 0x75b50e8f
     [0x00000218] 0x75b46293
     [0x00000219] 0x75b50f0e
     [0x0000021a] 0x75b45ec4
     [0x0000021b] 0x75b510d2
     [0x0000021c] 0x75b51189
     [0x0000021d] 0x75b45da3
     [0x0000021e] 0x75b3358a
    In fact, there's nothing magic about the DLL source code. A dirty example of the initialization filters follow:

    Code:
    DWORD STDCALL ConServerDllInitialization(CSR_SERVER_DLL* ConServer)
    {
      DWORD dwReturn = orgConServerDllInitialization(ConServer);
      DWORD i;
    
      FILE* f = fopen("C:\\log.txt","a+");
      if(f)
      {
        fprintf(f,"ConServer->ApiBase              = 0x%.8x\n"
                  "ConServer->HighestApiSupported  = 0x%.8x\n"
                  "ConServer->DispatchTable        = 0x%.8x\n",
                  ConServer->ApiBase,ConServer->HighestApiSupported,ConServer->DispatchTable);
    
        fputs(" -- Server Dispatch Table:\n",f);
        for( i=ConServer->ApiBase;i<ConServer->HighestApiSupported;i++ )
          fprintf(f," [0x%.8x] 0x%.8x\n",i,ConServer->DispatchTable[i-ConServer->ApiBase]);
    
        fclose(f);
      }
    
      return dwReturn;
    }
    
    DWORD STDCALL UserServerDllInitialization(CSR_SERVER_DLL* UserServer)
    {
      DWORD dwReturn = orgUserServerDllInitialization(UserServer);
      DWORD i;
    
      FILE* f = fopen("C:\\log.txt","a+");
      if(f)
      {
        fprintf(f,"UserServer->ApiBase              = 0x%.8x\n"
                  "UserServer->HighestApiSupported  = 0x%.8x\n"
                  "UserServer->DispatchTable        = 0x%.8x\n",
                  UserServer->ApiBase,UserServer->HighestApiSupported,UserServer->DispatchTable);
    
        fputs(" -- Server Dispatch Table:\n",f);
        for( i=UserServer->ApiBase;i<UserServer->HighestApiSupported;i++ )
          fprintf(f," [0x%.8x] 0x%.8x\n",i,UserServer->DispatchTable[i-UserServer->ApiBase]);
    
        fclose(f);
      }
    
      return dwReturn;
    }
    The installation of such a dll is fairly simple - it is enough to replace the "winsrv" string in the registry value mentioned previously, with our library filename (i.e. fake_winsrv), and copy the file itself to \Windows\system32. I hope everything is clear here ;-)

    Cheers

  3. #18
    |< x != '+' BanMe's Avatar
    Join Date
    Oct 2008
    Location
    Farmington NH
    Posts
    510
    Blog Entries
    4

    good stuff..

    Well this seems to almost be the path that I decided to take,except I've wondered down the path to actualy implementing a 'ServerDll' inside csrss, by doing this allows me to use more user mode coding techniques(though I don't..yet) and to separate off the threads that use these functions..Thats some interesting stuff you got going though..
    Last edited by BanMe; June 18th, 2010 at 21:10.
    No hate for the lost children;
    more love for the paths we walk,
    'words' shatter the truth we seek.
    from the heart and mind of Me
    me, to you.. down and across

    No more words from me, to you...
    Hate and love shatter the heart and Mind of Me.
    For the Lost Children;For the paths we walk; the real truth we seek!

Similar Threads

  1. 0-day Windows XP SP3 Denial of Service (CSRSS Crash #1)
    By j00ru vx tech blog in forum Blogs Forum
    Replies: 0
    Last Post: August 3rd, 2011, 17:18
  2. Replies: 0
    Last Post: July 15th, 2011, 03:27
  3. Windows CSRSS Write Up: Inter-process Communication (part 2/3)
    By j00ru vx tech blog in forum Blogs Forum
    Replies: 0
    Last Post: July 27th, 2010, 17:52
  4. Windows CSRSS Write Up: Inter-process Communication (part 1/3)
    By j00ru vx tech blog in forum Blogs Forum
    Replies: 2
    Last Post: July 17th, 2010, 12:18
  5. Windows CSRSS Write Up: the basics (part 1/1)
    By j00ru vx tech blog in forum Blogs Forum
    Replies: 2
    Last Post: July 9th, 2010, 15:59

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •