How to get the content of a Section object in a kernel dump

3

The section object from a 3thParty vendor is named rpsPdf10.mutex and it's intended use is to mimic a semaphore by writing a Boolean flag to it.

Using LiveKd and with a lot of help from SO, I've issued following command's trying to get detailed info of this Section object.

0: kd>!process 0 0 3thParty.exe
...
PROCESS fffffa800ea80060
    SessionId: 0  Cid: 0a00    Peb: fffdf000  ParentCid: 014c
    DirBase: 99349000  ObjectTable: fffff8a004448bf0  HandleCount: 338.
    Image: 3thParty.exe
...    

0: kd> !handle 0 7 fffffa800ea80060
         ...
         08  fffff8a012e26710 Section                   rpsPdf10.mutex
         ...

0: kd> !object fffff8a012e26710
Object: fffff8a012e26710  Type: (fffffa800cd7cea0) Section
    ObjectHeader: fffff8a012e266e0 (new version)
    HandleCount: 38  PointerCount: 39
    Directory Object: fffff8a00a980080  Name: rpsPdf10.mutex

0: kd> dt -r1 nt!_SECTION_OBJECT 0xfffff8a012e26710
   +0x000 StartingVa       : 0x00000022`00000100 Void
   +0x008 EndingVa         : 0x00000000`0008dfb0 Void
   +0x010 Parent           : 0xfffffa80`c0000001 Void
   +0x018 LeftChild        : (null) 
   +0x020 RightChild       : 0xfffffa80`00000034 Void
   +0x028 Segment          : 0xfffff8a0`102d7820 _SEGMENT_OBJECT
      +0x000 BaseAddress      : 0xfffffa80`0fbed900 Void
      +0x008 TotalNumberOfPtes : 1
      +0x010 SizeOfSegment    : _LARGE_INTEGER 0x1
      +0x018 NonExtendedPtes  : 0x1000
      +0x01c ImageCommitment  : 0
      +0x020 ControlArea      : (null) 
      +0x028 Subsection       : (null) 
      +0x030 MmSectionFlags   : 0xfffffa80`10987b10 _MMSECTION_FLAGS
      +0x038 MmSubSectionFlags : 0x00000000`03400000 _MMSUBSECTION_FLAGS

All this looks correct to me but how can I find the content the section?

windows
kernel
windbg
shared-memory

2 Answers

4

points to note as in earlier answer machine is 32 bit and os is win7 and windbg version is insider preview 16278 commands are arch agnostic and pointer arithmetic if any are arch dependent
and the walk through is on live binary not in a dump as there is a very fair chance that the page might have been paged out in the dump and demo might be inconclusive i might add to this answer later

getting contents form section is kinda convoluted
(there are several types of Section like
1) ALPC section(com objects )
2) File backed Section
3) PageFileBacked Section etc

the walkthrough below is for a pagefile backed section (most common type)

Assuming you compiled and executed the code below
the exe will create a SectionObject in global namespace
and the contents will be backed by PagingFile and will be waiting for a keypress

#include <windows.h>
#include <stdio.h>
#define bsize 256
int main(){
    char szMsg[]={"Message from blabb to lieven from Stack Overflow."};
    int ret = NULL;
    HANDLE hMap = CreateFileMapping((HANDLE)-1,NULL,4,0,bsize,"Global\\MyMap");
    if(hMap){
        PCHAR buff = (PCHAR) MapViewOfFile(hMap,0xf001f,0,0,bsize);
        if(buff){
            CopyMemory(buff, szMsg, sizeof(szMsg));
            ret = getchar();
            UnmapViewOfFile(buff);
        }
        CloseHandle(hMap);
    }
    return ret;
}

assuming the process is waiting for a keypress launch livekd or setup a live kernel debugging connection if it is running in a remote machine / vm

C:>livekd -k "c:\Program Files\Windows Kits\10\Debuggers\x86\cdb.exe"

LiveKd v5.62 - Execute kd/windbg on a live system
Launching c:\Program Files\Windows Kits\10\Debuggers\x86\cdb.exe:

Microsoft (R) Windows Debugger Version 10.0.16278.1000 X86

get the the _EPROCESS and set context

kd> !process 0 0 secobj.exe

PROCESS 8605ab28  SessionId: 1  Cid: 0fbc    Peb: 7ffd9000  ParentCid: 0af4
    DirBase: 7e2712e0  ObjectTable: c288ba00  HandleCount:   9.
    Image: secobj.exe

kd> .process /p /r 8605ab28

Implicit process is now 8605ab28

kd> ? @$proc
Evaluate expression: -2046448856 = 8605ab28

kd> ?? (char *)@$proc->ImageFileName
char * 0x8605ac94
 "secobj.exe"

look for a handle of type Section in the current process notice since our section is named in global namespace windbg deciphers that for us

kd> !handle 0 3 @$proc Section

Searching for handles of type Section

PROCESS 8605ab28  SessionId: 1  Cid: 0fbc    Peb: 7ffd9000  ParentCid: 0af4
    DirBase: 7e2712e0  ObjectTable: c288ba00  HandleCount:   9.
    Image: secobj.exe

Handle table at c288ba00 with 9 entries in use

0024: Object: c238e9c8  GrantedAccess: 000f0007 Entry: c37b7048
Object: c238e9c8  Type: (84ec6040) Section
    ObjectHeader: c238e9b0 (new version)
        HandleCount: 1 PointerCount: 2
        Directory Object: 98a0f170  Name: MyMap

dumping the SectionObject

kd> dt nt!_SECTION_OBJECT c238e9c8
   +0x000 StartingVa       : 0xc227e2c8 Void
   +0x004 EndingVa         : 0x00d3db6c Void
   +0x008 Parent           : 0xb0d3db20 Void
   +0x00c LeftChild        : (null)
   +0x010 RightChild       : 0x00000003 Void
   +0x014 Segment          : 0xc36aba20 _SEGMENT_OBJECT

kd> $$ Notice the Last Segment member it is not SEGMENT_OBJECT but
nt!_segment or actually a pointer to ControlArea for this Section

kd> dt nt!_SEGMENT 0xc36aba20
   +0x000 ControlArea      : 0x85182d08 _CONTROL_AREA
   +0x004 TotalNumberOfPtes : 1
   +0x008 SegmentFlags     : _SEGMENT_FLAGS
   +0x00c NumberOfCommittedPages : 1
   +0x010 SizeOfSegment    : 0x1000
   +0x018 ExtendInfo       : (null)
   +0x018 BasedAddress     : (null)
   +0x01c SegmentLock      : _EX_PUSH_LOCK
   +0x020 u1               : <unnamed-tag>
   +0x024 u2               : <unnamed-tag>
   +0x028 PrototypePte     : 0xc36aba50 _MMPTE
   +0x030 ThePtes          : [1] _MMPTE

kd> $$ you can expand the union u2 and dump the FirstMappedVa of the union to look at the contents of this Section

kd> dt nt!_SEGMENT u2.FirstMappedVa 0xc36aba20
   +0x024 u2               :
      +0x000 FirstMappedVa    : 0x000e0000 Void

dumping the contents

kd> da 0xe0000
000e0000  "Message from blabb to lieven fro"
000e0020  "m Stack Overflow."
kd>

or do !ca to get the FirstMappedVa which points to the first page
if the contents are greater than one page boundary fetching them is
kinda tedious as they may have been paged out and would need an execution operation and thus a page fault handled to get them into view

kd> !ca poi(0xc36aba20)

ControlArea  @ 85182d08
  Segment      c36aba20  Flink      00000000  Blink        00000000
  Section Ref         1  Pfn Ref           0  Mapped Views        1
  User Ref            2  WaitForDel        0  Flush Count         0
  File Object  00000000  ModWriteCount     0  System Views        0
  WritableRefs        0
  Flags (2000) Commit

      Pagefile-backed section

Segment @ c36aba20
  ControlArea       85182d08  ExtendInfo    00000000
  Total Ptes               1
  Segment Size          1000  Committed            1
  CreatingProcess   8605ab28  FirstMappedVa    e0000 <-------------
  ProtoPtes         c36aba50
  Flags (80000) ProtectionMask

Subsection 1 @ 85182d58
  ControlArea  85182d08  Starting Sector        0  Number Of Sectors    0
  Base Pte     c36aba50  Ptes In Subsect        1  Unused Ptes          0
  Flags               8  Sector Offset          0  Protection           4
kd>
answered on Stack Overflow Oct 15, 2017 by blabb
3

Adding another answer to show another pagefile backed section contents where you may need to go to the Creating Process and look at its virtual address instead of the process that is current

you may know shell keeps some global counters in a shared section

0104: Object: c2255450  GrantedAccess: 00000006 Entry: c5d9b208
Object: c2255450  Type: (84ec6040) Section
    ObjectHeader: c2255438 (new version)
        HandleCount: 6 PointerCount: 7
        Directory Object: 9d662520  Name: windows_shell_global_counters 

code to retrieve them

#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include <shlwapi.h>
#pragma comment(lib,"shlwapi.lib")

//add all items in the ... place holder in arrays below
PCHAR enuname[] = { "GLOBALCOUNTER_SEARCHMANAGER",...};
int foo [] =  { GLOBALCOUNTER_SEARCHMANAGER,...};

void main (void) {
    long cval = NULL;
    for(int i =0; i < _countof(foo) ;i++) {
        cval = SHGlobalCounterGetValue((SHGLOBALCOUNTER)foo[i]);
        printf ("%65s = %0x\n" ,enuname[i], cval);
    }
}

compiling and executing this you may get a result like this (keep in mind the counters are volatile so you may need to be quick enough for comparing)

C:\secobj\shglob>shglob.exe | head -n 13
                                      GLOBALCOUNTER_SEARCHMANAGER = 0
                                      GLOBALCOUNTER_SEARCHOPTIONS = 0
                               GLOBALCOUNTER_FOLDERSETTINGSCHANGE = 0
                                            GLOBALCOUNTER_RATINGS = 0
                                      GLOBALCOUNTER_APPROVEDSITES = 0
                                       GLOBALCOUNTER_RESTRICTIONS = 5
                               GLOBALCOUNTER_SHELLSETTINGSCHANGED = 2
                                   GLOBALCOUNTER_SYSTEMPIDLCHANGE = 0
                                     GLOBALCOUNTER_OVERLAYMANAGER = 0
                                  GLOBALCOUNTER_QUERYASSOCIATIONS = 0
                                         GLOBALCOUNTER_IESESSIONS = 0
                                    GLOBALCOUNTER_IEONLY_SESSIONS = 0
                           GLOBALCOUNTER_APPLICATION_DESTINATIONS = 83

looking at current process

kd> ? @$proc
Evaluate expression: -2033240552 = 86cf3618
kd> ?? (char *)@$proc->ImageFileName
char * 0x86cf3784
 "cdb.exe"
kd> !handle 0 3 @$proc Section
0164: Object: c2255450  GrantedAccess: 00000006 Entry: c3df32c8
Object: c2255450  Type: (84ec6040) Section
    ObjectHeader: c2255438 (new version)
        HandleCount: 11 PointerCount: 12
        Directory Object: 9d662520  Name: windows_shell_global_counters

kd> dc @@c++(((nt!_segment *)((nt!_section_object *) 0xc2255450)->Segment)->u2.FirstMappedVa)
00290000  ???????? ???????? ???????? ????????  ????????????????
00290010  ???????? ???????? ???????? ????????  ????????????????
00290020  ???????? ???????? ???????? ????????  ????????????????
00290030  ???????? ???????? ???????? ????????  ????????????????
00290040  ???????? ???????? ???????? ????????  ????????????????
00290050  ???????? ???????? ???????? ????????  ????????????????
00290060  ???????? ???????? ???????? ????????  ????????????????
00290070  ???????? ???????? ???????? ????????  ????????????????

it may be that this current process obtained a handle with OpenFileMapping but didn't map it yet or the page is paged out (livekd can't use pagein ) whatever we cant seem to view this section content

lets look who created this shared section

kd> ? @@c++(((nt!_segment *)((nt!_section_object *) 0xc2255450)->Segment)->u1.CreatingProcess)
Evaluate expression: -2050635184 = 85c5ca50

kd> !process 85c5ca50 0
PROCESS 85c5ca50  SessionId: 1  Cid: 0af4    Peb: 7ffd9000  ParentCid: 0704
    DirBase: 7e271420  ObjectTable: c5d873c8  HandleCount: 888.
    Image: explorer.exe

it looks logical explorer.exe seemed to have created this shared section

lets check by dumping 0n13 dwords from the creating process virtual address

kd> .process /p /r 85c5ca50

kd> dc @@c++(((nt!_segment *)((nt!_section_object *) 0xc2255450)->Segment)->u2.FirstMappedVa) l0n13
00290000  00000000 00000000 00000000 00000000  ................
00290010  00000000 00000005 00000002 00000000  ................
00290020  00000000 00000000 00000000 00000000  ................
00290030  00000083                             ....
answered on Stack Overflow Oct 15, 2017 by blabb

User contributions licensed under CC BY-SA 3.0