Results 1 to 8 of 8

Thread: x86 Kernel Memory Space Visualization (KernelMAP v0.0.1)

  1. #1

    x86 Kernel Memory Space Visualization (KernelMAP v0.0.1)

    What I would like to write about today is a subject I have been playing with for quite some time – Windows kernel vulnerability exploitation techniques. While digging through various articles and other materials, I appeared to find bunches of interesting facts that are worth being described here. The post presented today aims to describe various ways of obtaining kernel-mode addresses from the user-mode (application) level.

    One could ask, what would we want to retrieve any internal system addresses for. Well, it is indeed a very good question – as for me, the kernel addresses become most useful in the vulnerability exploitation process. Since a majority of bugs found in device drivers belong, directly (pointer validation) or indirectly (pool buffer overflow), to the write-what-where condition family, one must know the exact address to be overwritten before performing the operation. This basically means that the more information about kernel memory layout we can gather, the more stable and effective attacks can be conducted.

    The idea I am writing about is not new, for sure. A great part of kernel exploits programmers has already used such techniques in their source code. However, I haven’t ever found any publication that would thoroughly describe every possible vector of obtaining somewhat “sensitive” kernel data (addresses) from within user-mode. Hence, I would like to present a short introduction of each method I could think of – a longer article will presumably be released within a few days. Huh, let’s get to the point, already!

    NtQuerySystemInformation function

    Before trying to retrieve any information from the kernel, one should firstly realize, what are the possible “communication channels”, that could be used to get the desired data from. The most basic method division could look like this:

    • Kernel communication – calling some of the exported system routines and receive the data we are interested in, through the output buffer
    • Processor communication – directly using some of the processor characteristics (i.e. instruction set) in order to query for some processor-specific values that the system is obliged to fill.
    All in all, the kernel isn’t meant to release too much information about itself to the user (since every leaked piece of data could potentially help the attacker to hack the machine); due to this fact, there are special routines designed to handle queries about the system state, configuration etc. As it turns out, these system calls (named NtQuery*Information) can provide very miscellaneous kinds of information that not every low-level coder is aware of. I strongly advice you to take a look and test the functions below, using many different arguments:

    Even thought these syscalls are either documented very poorly or not documented at all, some independent researchers have already managed to describe a great part of them – their work is publicly available, for example here. For our purposes (global system info), the last function on the list seems to be the most useful one – it is, indeed. As one can see, the first routine parameter is _SYSTEM_INFORMATION_CLASS – a single enum containing all the possible request types, shown below:

    Code:
    typedef enum _SYSTEM_INFORMATION_CLASS {
    SystemInformationClassMin = 0,
    SystemBasicInformation = 0,
    SystemProcessorInformation = 1,
    SystemPerformanceInformation = 2,
    SystemTimeOfDayInformation = 3,
    SystemPathInformation = 4,
    SystemNotImplemented1 = 4,
    SystemProcessInformation = 5,
    SystemProcessesAndThreadsInformation = 5,
    SystemCallCountInfoInformation = 6,
    SystemCallCounts = 6,
    SystemDeviceInformation = 7,
    SystemConfigurationInformation = 7,
    SystemProcessorPerformanceInformation = 8,
    SystemProcessorTimes = 8,
    SystemFlagsInformation = 9,
    SystemGlobalFlag = 9,
    SystemCallTimeInformation = 10,
    SystemNotImplemented2 = 10,
    SystemModuleInformation = 11,
    SystemLocksInformation = 12,
    SystemLockInformation = 12,
    SystemStackTraceInformation = 13,
    SystemNotImplemented3 = 13,
    SystemPagedPoolInformation = 14,
    SystemNotImplemented4 = 14,
    SystemNonPagedPoolInformation = 15,
    SystemNotImplemented5 = 15,
    SystemHandleInformation = 16,
    SystemObjectInformation = 17,
    SystemPageFileInformation = 18,
    SystemPagefileInformation = 18,
    SystemVdmInstemulInformation = 19,
    SystemInstructionEmulationCounts = 19,
    SystemVdmBopInformation = 20,
    (...)
    } SYSTEM_INFORMATION_CLASS;
    (you can find the complete definition in the standard ddk\ntapi.h header file). As the name implies, there are really plenty of information to get – the only thing required is the knowledge of how to the input/output structures for each request looks like. At this point, we are particularly interested in three query types – SystemModuleInformation, SystemHandleInformation and SystemLocksInformation. Moreover, SystemObjectInformation could be also useful, under specific circumstances. Let’s go through these requests and find out, what information can we get.

    SystemModuleInformation

    As far as my observations go, this request is the most commonly used type, across kernel-mode exploits. To understand why, one should first take a look at what this operation returns:

    Code:
    typedef struct _SYSTEM_MODULE_INFORMATION_ENTRY {
    ULONG** * Unknown1;
    ULONG** * Unknown2;
    PVOID* Base;
    ULONG* Size;
    ULONG* Flags;
    USHORT* Index;
    /* Length of module name not including the path, this
    field contains valid value only for NTOSKRNL module */
    USHORT** *NameLength;
    USHORT* LoadCount;
    USHORT* PathLength;
    CHAR* ImageName[256];
    } SYSTEM_MODULE_INFORMATION_ENTRY, *PSYSTEM_MODULE_INFORMATION_ENTRY;
    
    typedef struct _SYSTEM_MODULE_INFORMATION {
    ULONG* Count;
    SYSTEM_MODULE_INFORMATION_ENTRY Module[1];
    } SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
    What the listing presents is a main structure, containing the number of module information entries returned. Right after this value, Count SYSTEM_MODULE_INFORMATION_ENTRY structures follow, each containing information about one, specific executable image, loaded inside the kernel-mode address space.

    As the names themselves suggest, after calling NtQuerySystemInformation(SystemModuleInformation,…) and passing a properly-sized buffer, the application obtains the Name, ImageBase and ImageSize of every single device driver (excluding those that are hidden by rootkits, of course ). This includes the very first Windows kernel images like ntosknrl.exe (or other types of the system core), HAL.dll (hardware support), win32k.sys (std graphic device driver) and so on. Because of the fact that most write-what-where attacks are based on modyfing the ntosknrl.exe memory regions (such as the [HalDispatchTable+4] technique), obtaining the kernel ImageBase* value is an essential part of the entire exploitation. Some very educational articles covering kernel-mode exploitation techniques can be found here (Analyzing local privilege escalations in win32k), here (Exploiting Common Flaws in Drivers) and here (Exploiting Windows Device Drivers).

    SystemHandleInformation

    Another interesting request type, already used by some rootkit detection mechanisms (RootkitAnalytics.com). The general purpose is providing information about all the active HANDLE objects present in the system memory. Performing a NtQuerySystemInformation(SystemHandleInformation,…) will result in filling the output buffer with structures of the following definition:

    Code:
    typedef struct _SYSTEM_HANDLE_INFORMATION {
    ULONG* ProcessId;
    UCHAR* ObjectTypeNumber;
    UCHAR* Flags;
    USHORT* Handle;
    PVOID* Object;
    ACCESS_MASK* GrantedAccess;
    } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
    Not too many fields, this time; however, the most important part of the struct is present – PVOID Object. This is where we can find another kernel-mode pointer (inaccessible from user-mode, of course). Apart from the address itself, the HANDLE is also described with the creator process ID, type of the object and most importantly – the HANDLE value itself. Therefore, the object identification is very easy to perform and should not cause too much of a problem to the coder. More information will follow in the upcoming paper

    SystemLocksInformation

    This time, what we are getting is the information regarding locks used by the kernel. Locks in Windows are special “multiple reader single writer” synchronization mechanisms, otherwise known as “resources”.* The output structure definition follows:

    Code:
    typedef struct _SYSTEM_LOCK_INFORMATION {
    PVOID* Address;
    USHORT* Type;
    USHORT* Reserved1;
    ULONG* ExclusiveOwnerThreadId;
    ULONG* ActiveCount;
    ULONG* ContentionCount;
    ULONG* Reserved2[2];
    ULONG* NumberOfSharedWaiters;
    ULONG* NumberOfExclusiveWaiters;
    } SYSTEM_LOCK_INFORMATION, *PSYSTEM_LOCK_INFORMATION;
    where the PVOID Address value points to a ERESOURCE structure in the kernel memory. These structures can be initialized using the ExInitializeResourceLite routine and are said to be documented in DDK (Windows NT 2000 Native API Reference).

    These are, more or less, all the places (known by me), one can request K-M addresses from. Even though only three sources could seem to be little, it is enough to create a really impressive (imho) kernel memory map, as you will see in a few minutes. If you – the blog reader – are aware of any other kind of system information request leading to kernel address “leak”, please let me know through e-mail / post comments – I will be more than happy to add it to this list.

    Processor specific structures

    Apart from asking the system kernel to provide some information about its memory layout, one can also use direct application -> processor communication in order to read addresses related to some of the architectural structures that the system has to implement to work correctly. To be more precise, these structures are Global Descriptor Table (per processor/core) and Interrupt Descriptor Table (per processor/core) plus structures implemented inside GDT (Task State Segment, Local Descriptor Table etc).

    To start playing with these structures, one should begin by reading Intel Software Developer’s Manuals: Volume 1 (Basic Architecture) and Volume 3A, 3B (System Programming Guide) – all of these can be found here. The most interesting instructions here appear to be SGDT and SIDT, storing the GDTR and IDTR registers in user-specified memory.

    What is more, the system itself also makes some segment-related API functions available; these are:

    It should be noted (once more), that each processor has its own GDT/IDT structure. Hence, in order to retrieve all the addresses possible, it is necessary to make sure that a specified thread/routine is executed in the context of a chosen processor. This can be achieved by using SetThreadAffinityMask or SetProcessAffinityMask API functions. Please refer to the KernelMAP source code to get more information about how to implement it in practice.

    KernelMAP v0.0.1

    Despite some strictly theoretical deliberations, I would also like to present a simple program of mine. Its main purpose is to gather all (or most, at least) information about kernel-mode memory layout and show it to the user in the most attractive way possible. The application consists of two windows: the first, text window prints some basic, statistical information based on the data provided by kernel. Second, graphical window is responsible for the real visualization. Its size is equal 1024512 (400200 hexdecimally), and every virtual page is represented by a single pixel on the board. These pixels have various colors associated to themselves, depending on what type of data the page in consideration contains.

    As the above description might not give you any idea of how it looks like on a real system, some screenshots from various systems follow:



    Windows XP SP3



    Windows Vista SP2



    Windows 7 SP0

    Some strictly technical info: this program is designed to be compiled using MinGW GCC compiler and is probably not MS VC++ compatible. In order to make it work correctly, the program needs to find the SDL.dll, libpng3.dll and zlib1.dll libraries – you can find them inside the package.

    A complete ZIP file, including the source code, executable and external DLL files can be downloaded from here (387kB)

    Since I am myself very curious about how the kernel memory layout looks like on different systems that I don’t have access to, you should feel encouraged to make your own shot and share (I hope this is not too much of information disclosure ;D). Furthermore, if you find any bugs in the existing code, or would like it to be extended with some additional functionalities (like new kernel addresses I don’t know about, yet), please let me know.

    Every single comment is very welcome!

    Have fun!



    http://j00ru.vexillium.org/?p=269&lang=en

  2. #2
    wow! this is looking very nice!!!
    but can you explaing what we are seeing ? i mean i can see RED and GREEN and BLUE marks but what are they stand for ? more over what does the space between each mark stand for ?


    Thanks,
    LaBBa.

  3. #3
    Teach, Not Flame Kayaker's Avatar
    Join Date
    Oct 2000
    Posts
    4,081
    Blog Entries
    5
    That was my initial thought too Labba, then I remembered Star Wars and "Use the Source Luke!". The colors are listed there (color descriptions added by me using a color ref):

    PHP Code:
    struct _AddressConf
    {
      
    CHAR Name[256]; // XXX: should be always enough
      
    struct {BYTE r,g,b;} Color;
    AddressConf[] =
    {
      {
    "UNKNOWN",{0x50,0x50,0x50}}, // black(ish)
      
    {"MODULE", {0xff,0x00,0x00}}, // red
      
    {"HANDLE", {0x00,0xff,0x00}}, // green
      
    {"LOCK",   {0x00,0x00,0xff}}, // blue
      
    {"GDT",    {0xff,0xff,0x00}}  // yellow,
      
    {"LDT",    {0x00,0xff,0xff}}, // cyan
      
    {"IDT",    {0xff,0x00,0xff}}  // pink
    }; 
    There's also output in the console window which is easy to miss since it's in the background.


    Nice J00ru. One quick thought I had, though I don't know if it adds to what you're aiming for. Some of the black "blanks" of the complete memory map might be filled in with the Paged/Unpaged pools, something along the lines of:

    Code:
    KdDebuggerDataBlock = (PKDDEBUGGER_DATA64)GetKdDebuggerDataBlock();
    
    // Get PagedPool limits
    MmPagedPoolStart = *(ULONG*)KdDebuggerDataBlock->MmPagedPoolStart; // 0xE1000000
    MmPagedPoolEnd = *(ULONG*)KdDebuggerDataBlock->MmPagedPoolEnd; // 0xEBFFFFFF
    Individual blocks, though perhaps an extreme step for the purposes, might be parsed out by following PoolHeader allocations within the region.

    KdDebuggerDataBlock is obtained from KdVersionBlock, which in turn is obtained from KPCR, or probably more legally from NtSystemDebugControl with DEBUG_CONTROL_CODE = 7 (DebugSysGetVersion). KdSystemDebugControl in Vista. If I've got the details correct.


    btw, I apologize for the oversized png graphics in the rss imported blog, this post has made us realize vbulletin doesn't resize [IMG] tags, but we'll try to take care of that with the next forum upgrade coming soon.

    Cheers,
    Kayaker

  4. #4
    LaBBa, look at GlobalInformation.cpp =)

    j00ru, Thanks for sharing the source over here.

    EDIT:Ah speedy Kayaker got it first.
    Last edited by Silkut; January 5th, 2010 at 06:29. Reason: too slow, but i'll be back !
    Please consider donating to help Woodmann.com staying online (here is why).
    Any amount greatly appreciated. Thank you.

  5. #5
    Thanks.
    I will next time i'm not used to have the code .. allways reversing for it

  6. #6
    Hi there!

    I'm really glad you like the tool ;>
    Yep, I forgot to mention what do the colors mean, however I can see the case is already solved the source code doesn't bite, even the RE-s

    @Kayaker:
    Thanks for your message. However, I'm not really sure if what you have written is possible to be performed from within user-mode. I've read some info about the mentioned NtSystemDebugControl routine.

    YES, it is possible to retrieve the KdVersionBlock data (0x28 bytes long) using the DebugSysGetVersion (7) code. The structure's definition is as follows:
    Code:
    typedef struct _DBGKD_GET_VERSION64 {
        USHORT  MajorVersion;
        USHORT  MinorVersion;
        UCHAR   ProtocolVersion;
        UCHAR   KdSecondaryVersion; // Cannot be 'A' for compat with dump header
        USHORT  Flags;
        USHORT  MachineType;
    
        //
        // Protocol command support descriptions.
        // These allow the debugger to automatically
        // adapt to different levels of command support
        // in different kernels.
        //
    
        // One beyond highest packet type understood, zero based.
        UCHAR   MaxPacketType;
        // One beyond highest state change understood, zero based.
        UCHAR   MaxStateChange;
        // One beyond highest state manipulate message understood, zero based.
        UCHAR   MaxManipulate;
    
        // Kind of execution environment the kernel is running in,
        // such as a real machine or a simulator.  Written back
        // by the simulation if one exists.
        UCHAR   Simulation;
    
        USHORT  Unused[1];
    
        ULONG64 KernBase;
        ULONG64 PsLoadedModuleList;
    
        //
        // Components may register a debug data block for use by
        // debugger extensions.  This is the address of the list head.
        //
        // There will always be an entry for the debugger.
        //
    
        ULONG64 DebuggerDataList;
    
    } DBGKD_GET_VERSION64, *PDBGKD_GET_VERSION64;
    Moreover YES, it is possible to get the address of KdDebuggerDataBlock (it is present in the DebuggerDataList field plus it is placed right after KdVersionBlock in the systems I tested). However, I cannot see any way of obtaining the Data Block content from application level.

    You referred to some GetKdDebuggerDataBlock (dummy?) function... Again, I would be very happy to find such a routine in UM libraries - the paged memory ranges, together with other info present in this structure would be very useful.

    Since the major purpose is to present the possible ways of gathering information about the kernel memory layout (presumably before some ring-0 vulnerability exploitation), we assume that the user has minimum privileges. Hence, ring-0 code is not the case.

    Cheers,
    j00ru//vx

  7. #7
    Teach, Not Flame Kayaker's Avatar
    Join Date
    Oct 2000
    Posts
    4,081
    Blog Entries
    5
    Oh, that damn pesky user mode limitation. Yeah, I try to avoid that wherever possible

    I understand and you're right, the useful info stops at KdDebuggerDataBlock then in UM.

    If I can continue to be annoying though , the PngFile.SetPixel function seems to be based on a system address range that starts at 0x80000000, which is what we're all used to, but a more rigorous method might be as mentioned in

    http://ericuday.googlepages.com/EICAR2008_UserMode_Memory_Scanning_3.doc

    Usually the system address range begins at 0x80000000. However, it is not right to assume this because of the ability to boot Windows with the /3GB boot.ini switch. In order to determine the correct system address range start address, we can use the native API call to NtQuerySystemInformation (exported by ntdll.dll) with the SystemInformationClass parameter set to SystemRangeStartInformation sub-function (whose information class number is 50).




    This is sort of off topic now, but in case anyone is interested the dummy GetKdDebuggerDataBlock() function from above is just:

    Code:
    /////////////////////////////////////////////////////////////////////
    //
    //			GetKdVersionBlock
    // 
    /*
    
      For XP and above only!
    
      For full explanation of how these structures relate to each other, see
    
    	How to get some hidden kernel variables without scanning by Opc0de
    	http://www.rootkit.com/newsread.php?newsid=101
    
    	Getting Kernel Variables from KdVersionBlock, Part 2 by Alex Ionescu
    	http://www.rootkit.com/newsread.php?newsid=153
    
      
    	
      KdVersionBlock field is only valid in the 1st processor KPCR,
      so we use KeSetSystemAffinityThread to set to CPU 0. See
    
    	Multi-Processors and KdVersionBlock
    	http://www.msuiche.net/2009/01/05/multi-processors-and-kdversionblock/
    
    
    	One could also use:
    
    	KAFFINITY AffinityMask;
    	AffinityMask = (1 << ProcessorNumber);
    
    	ZwSetInformationThread(ThreadHandle,	// IN HANDLE ThreadHandle
    				ThreadAffinityMask,	// IN THREADINFOCLASS  ThreadInformationClass
    				&Affinity,		// IN PVOID ThreadInformation
    				sizeof(KAFFINITY));	// IN ULONG ThreadInformationLength
    
    
    
      Under a MP/HT system, the multiple _KPRCB addresses are found in KiProcessorBlock
    	kd> dd KiProcessorBlock
    
    */
    
    /////////////////////////////////////////////////////////////////////
    
    PDBGKD_GET_VERSION64 GetKdVersionBlock()
    {
    
        UCHAR                   ProcessorNumber = 0;	
    //  PKPCR                   pKpcr =	(PKPCR)0xffdff000;
        PKPCR                   SelfPcr;
        PDBGKD_GET_VERSION64    KdVersionBlock;
    
    	/////////////////////////////////////////////////////
    
    	// Set the system affinity of the current thread
    	// (set to first processor for multiprocessor systems)
    
    	KeSetSystemAffinityThread ((KAFFINITY) (1 << ProcessorNumber));
    
    	// Get pointer to KPCR
    
    	_asm{
    		mov eax, fs:[0x1C]  // _KPCR.SelfPcr
    		mov SelfPcr, eax
    	}
    
    	// Get KdVersionBlock ([eax + 34])
    
    	KdVersionBlock = (PDBGKD_GET_VERSION64)SelfPcr->KdVersionBlock;	
    	
    	// Restore the previous affinity of the current thread
    	
    	KeRevertToUserAffinityThread();
    
    	return KdVersionBlock;  // 0x8054C738
    }
    
    /////////////////////////////////////////////////////////////////////
    
    
    /////////////////////////////////////////////////////////////////////
    //			GetKdDebuggerDataBlock
    //
    // Returns the value of the kernel variable KdDebuggerDataBlock
    //
    // See IG_GET_KERNEL_VERSION
    // http://msdn.microsoft.com/en-us/library/cc267894.aspx
    //
    /////////////////////////////////////////////////////////////////////
    
    PKDDEBUGGER_DATA64 GetKdDebuggerDataBlock()
    {
    
    	PDBGKD_GET_VERSION64 KdVersionBlock;
    	ULONG64 KdpDebuggerDataListHead;	// LIST_ENTRY
    	PKDDEBUGGER_DATA64 KdDebuggerDataBlock;
    
      /////////////////////////////////////////////////////
    
    	// Get KdVersionBlock
    	KdVersionBlock = (PDBGKD_GET_VERSION64)GetKdVersionBlock();
    
    	KdpDebuggerDataListHead = KdVersionBlock->DebuggerDataList;
    
    	KdDebuggerDataBlock = *(PKDDEBUGGER_DATA64*)KdpDebuggerDataListHead;
    
    	return KdDebuggerDataBlock;  // 0x8054C760
    }
    
    /////////////////////////////////////////////////////////////////////

  8. #8
    Hi, thanks for your reply!

    Quote Originally Posted by Kayaker View Post
    If I can continue to be annoying though , the PngFile.SetPixel function seems to be based on a system address range that starts at 0x80000000, which is what we're all used to, but a more rigorous method might be as mentioned in

    http://ericuday.googlepages.com/EICAR2008_UserMode_Memory_Scanning_3.doc
    Haha, the more annoying you are, the more I am learning. You are certainly right at this point; I always forget to add the /3G switch support to kernel-related applications.
    However, having the kernel memory address range start at 0xC0000000, the application is expected to use the bottom half of the window, still creating a tighter visualization (tho wasting the other half of user screen). Anyway, I'll fix it in the next version, if one will come

    Furthermore, thanks for the GetKdDebuggerDataBlock function - I honestly haven't had any idea of how much usable information is stored in the kernel, in one place.

    One more thing I wrote no word about: the KernelMAP application doesn't take the Win32-subsystem (win32k.sys) object addresses into consideration. This will also, hopefully, change in the next version as I get some more information about those
    So... stay tuned!

Similar Threads

  1. FlexLM Space in NOTICE
    By silke in forum The Newbie Forum
    Replies: 2
    Last Post: April 8th, 2010, 02:05
  2. Where to Make Space Inside a DLL?
    By RobertReed in forum The Newbie Forum
    Replies: 8
    Last Post: June 22nd, 2009, 13:56
  3. Free Web Space
    By bilbo in forum Off Topic
    Replies: 8
    Last Post: July 31st, 2004, 23:35
  4. Link: Kernel Services in User Space on Win2K
    By doug in forum Advanced Reversing and Programming
    Replies: 8
    Last Post: June 11th, 2004, 09:18
  5. Lost in Space
    By shymu in forum Advanced Reversing and Programming
    Replies: 1
    Last Post: February 7th, 2001, 00:08

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
  •