SlideShare a Scribd company logo
I/O, YOU OWN:
REGAINING CONTROL
OF YOUR DISK IN THE
PRESENCE OF
BOOTKITS



Aaron LeMasters @lilhoser
Introduction
2


       My background
       Your background
       Brief history of this presentation
       Disclaimer: some of this might be wrong…
       Please read white paper for details
Agenda
3


       Technical Background
         What is the crash dump stack in Windows?
         How the operating system initializes and uses the
          crash dump stack (post Windows Vista)
               Pre Vista is in Appendix A
       Bootkit Defeat Technique for SCSI drives
         How we can use this stack outside of the operating
          system’s normal activity
         IDE drive technique in Appendix B
       Sneak peak at Windows 8 Release Preview
        changes
       Demo – Defeating TDL4
4   Technical Background
    Terminology and Concepts
Basics
5


       Port driver – abstraction interface provided by OS,
        hides underlying protocol details from class driver
       Miniport driver – manufacturer-supplied driver to
        interface with hardware (Host Bus Adapter/HBA);
        linked against port driver for specific transport
        technology
       Class driver – a driver that abstracts the
        underlying technology of a category of devices that
        share similar qualities (e.g., cdrom.sys)
       Normal I/O path – the route an I/O request takes
        during regular system operation
       Crash dump I/O path – the route the kernel uses to
        write a crash dump file to disk during a crash
Normal I/O Path
6
Crash Dump I/O Path
7
Why two paths?
8


       When a bugcheck occurs, the OS has no idea
        where the problem occurred – it could have
        happened inside a driver in the normal I/O
        path.
       What differs between the two paths?
                           Normal I/O Path   Crash Dump I/O Path
         Primary drivers   Many, layered     Modified port and miniport
         Filter drivers    Many, layered     Crash dump filters only
         Controlled by     I/O manager       Kernel or crashdmp.sys
         Documented?       Yes               *cough*
The Crash Dump Mechanism
9


       Encompasses the entire crash dump process
         Fromwhen it is initialized during system boot up
         to when it is used after KeBugCheck2()
       Primary components:
         The kernel
         Crashdmp.sys (Vista+)
         The crash dump driver stack or just “crash dump
          stack”
       Goal: Write a crash dump file to boot device or
        save state in a hibernation file
The Crash Dump Stack
10


        A “stack” of drivers, consisting of:
          A dump port driver
          A dump miniport driver
          One or more crash dump filter drivers

        Initialized in two phases:
          System startup/page file creation (pre-initialization)
          System crash (post-initialization)

        Used when:
          A bug check occurs
          The system is about to hibernate
The Crash Dump Stack – Common Drivers
11


         Driver Name On Disk   Driver Base Name in   Purpose
                               Memory
         diskdump.sys          dump_diskdump         SCSI/Storport dump port
                                                     driver with required exports
                                                     from scsiport.sys and
                                                     storport.sys. This driver is
                                                     unloaded.
         dumpata.sys           dump_dumpata          IDE/ATA dump port driver with
                                                     required ataport.sys exports.
                                                     This driver is unloaded.
         scsiport.sys          dump_scsiport         The final SCSI/Storport dump
                                                     port driver.
         ataport.sys           dump_ataport          The final IDE/ATA dump port
                                                     driver.
         atapi.sys             dump_atapi            An older, generic ATAPI
                                                     miniport driver provided by the
                                                     OS for IDE/ATA drives
         vmscsi.sys            dump_vmscsi           The miniport driver provided
                                                     by VMWare for SCSI drives.
         LSI_SAS.sys           dump_LSI_SAS          The miniport driver provided
                                                     by LSI Corporation for serial-
                                                     attached storage drives.
         dumpfve.sys           dump_dumpfve          Windows full volume
                                                     encryption crash dump filter
                                                     driver
Crash Dump Environment
12


        Normal I/O path is disabled
        All processors are disabled except the one the
         current thread is executing on
        Active CPU becomes single-threaded (IRQL is
         raised to HIGH_LEVEL) and uninterruptible
        I/O sent to the crash dump stack is
         synchronous
        If IDE controller, only the channel containing
         the device with the paging file is enabled
13
     Technical Background
     Crash Dump Stack Initialization and Usage
     after Windows Vista
Crash Dump Stack Configuration
14


        Crash dump is configured via
         IoConfigureCrashDump()
          Reads   in registry settings to control dump
           behavior
          Passes handle to system paging file to
           IopInitializeCrashDump()
        Triggered via NtSetSystemInformation()
         or PoBroadcastSystemState() or
         PoShutdownBugCheck()
Initialization
15
Load and Call Entry Point of
16
     Crashdmp.sys
        Nearly all of crash dump code was removed from
         kernel and put in crashdmp.sys
        KiInitializeKernel() 
         IoInitSystem() OR
         NtCreatePagingFile()
            IoInitializeCrashDump(HANDLE PageFile)
              IopLoadCrashDumpDriver() – loads crashdmp.sys
                   Crashdmp!DriverEntry() – fills crash dump call table
        Entry point called with two arguments:
          Name of the arc boot device
          Pointer to a global crashdmp callback table
Crashdmp.sys Call Table
17


               Table Offset*                          Value
     0x0                                 1
     0x4                                 1
     0x8                                 CrashdmpInitialize
     0xC                                 CrashdmpLoadDumpStack
     0x10                                CrashdmpInitDumpStack
     0x14                                CrashdmpFreeDumpStack
     0x18                                CrashdmpDisable
     0x1C                                CrashdmpNotify
     0x20                                CrashdmpWrite
     0x24                                CrashdmpUpdatePhysicalRange


     *Pointer width is 8 bytes on 64-bit systems
Identify and Initialize Crash Dump
18
     Drivers
        KiInitializeKernel() 
         IoInitSystem() OR
         NtCreatePagingFile()
            IoInitializeCrashDump()
              Crashdmp!CrashDmpInitialize():
                  Crashdmp!CrashdmpLoadDumpStack():
                      Crashdump!QueryPortDriver()

                      Crashdmp!LoadPortDriver()

                      Crashdmp!LoadFilterDrivers()

                      Crashdmp!InitializeFilterDrivers()
CrashdmpInitialize()
19


        References boot device’s FILE_OBJECT
        Read registry for crash dump settings
          Stored   in local crashdump control block
        Initializes crashdump control block
        Registers a KbCallbackSecondaryDumpData
         bugcheck callback
        Calls CrashdmpLoadDumpStack()…
CrashdmpLoadDumpStack()
20

        Queries port driver capabilities using
         IOCTL_SCSI_GET_DUMP_POINTERS,
         IOCTL_SCSI_GET_ADDRESS,
         IOCTL_SCSI_GET_PARTITION_INFO,
         IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
         IOCTL_SCSI_GET_DRIVE_GEOMETRY_EX
        Locates all crash dump drivers: port, miniport and
         crash dump filter drivers
            Copies them into memory with “dump_” prefix
                No DRIVER_OBJECT or DEVICE_OBJECT!
            Port driver will be one of dump_scsiport,
             dump_ataport or dump_storport; on disk either
             diskdump.sys (scsi/storport) or dumpata.sys (ataport)
            Miniport can be named anything
Usage
21
Call Dump Driver Entry Points
22


        KeBugCheck2()  IoWriteCrashDump():
          Calls  the eighth entry in the
           CrashDmpCallTable table,
           CrashDmpNotify() - displays the string
           “collecting data for crash dump”
          Fills dump block with bug check codes and other
           debug information
          Appends a triage dump if necessary
Call Dump Driver Entry Points and
23
     Dump Port Driver Callbacks
        KeBugCheck2()  IoWriteCrashDump():
          Callsthe ninth entry in the CrashDmpCallTable
          table, CrashDmpWrite():
            CrashdmpInitDumpStack():
                 StartFilterDrivers() – calls the DumpStart
                  callback of each crash dump filter driver
                 InitializeDumpDriver() – calls the dump driver
                  entry point; calls the DiskDumpOpen callback provided by
                  the dump port driver; fills dump context structure with
                  callback pointers CrashdmpWriteRoutine,
                  CrashdmpWritePendingRoutine,
                  CrashdmpFinishRoutine
Data Written to Dump File
24


        KeBugCheck2()  IoWriteCrashDump():
            CrashDmpWrite():
                CrashdmpInitDumpStack():
                     DumpWrite() – creates dump file based on configuration:
                         FillDumpHeader()
                         Calls one of:
                             WriteFullDump()
                             WriteKernelDump()
                             WriteMiniDump()
                       InvokeSecondaryDumpCallbacks() - Invokes all
                        BugCheckSecondaryDumpDataCallback callbacks to
                        allow drivers to append data to the completed crash dump
                        file.
                       InvokeDumpCallbacks() - Invokes all
                        BugCheckDumpIoCallback callbacks, informing them
                        crash dump is complete.
25
     Bootkit Defeat Technique
     How to bypass the Normal I/O Path and
     use the Crash Dump I/O Path to read and
     write to disk
Inspiration
26

     Restrictions on Miniport Drivers that Manage the Boot Drive:

     “A storage miniport driver that manages an adapter for a boot
     device is subject to special restrictions during a system crash.
     While dumping the system's memory image to disk, the miniport
     driver must operate within a different environment. The usual
     communication between the miniport driver, the port driver, and
     disk class driver is interrupted. The kernel does disk I/O by
     direct calls to the disk dump port driver (diskdump.sys for SCSI
     adapters or dumpata.sys for ATA controllers), bypassing file
     systems, and the normal I/O stack. The disk dump driver, in
     turn, calls the boot device's miniport driver to handle all I/O
     operations, and the disk dump driver intercepts all of the
     miniport driver's calls to the port driver.” [1]
Leveraging the Crash Dump I/O
27
     Path
        The crash dump mechanism provides a
         pristine path to disk
          But   it only provides write capabilities
        Leverage knowledge of the crash dump
         mechanism and internals of the port/miniport
         relationship to coerce read/write
        Here’s how…
..sort of like the O/S does…
28
…but more like this
29
Identify Crash Dump Port/Miniport
30
     Drivers
        Walk loaded module list
        Single out dump drivers easily via “dump_” prefix
        Port driver will be one of dump_scsiport,
         dump_storport or dump_ataport
        Miniport driver name:
            open a handle to the class driver’s device object, walk
             attached devices to the lowest one
            Vista+ DUMP_POINTERS_EX.DriverList
        Once drivers have been found, call their entry points
         with the appropriate arguments
            Dump port: DriverEntry(NULL, DumpInit*)
            Dump miniport: DriverEntry(NULL, NULL)
Get Boot Device Information
31


        IOCTL to get hardware register mapping and port
         configuration information
         (IOCTL_SCSI_GET_DUMP_POINTERS); data returned
         in DUMP_POINTERS or DUMP_POINTERS_EX structure
        IOCTL to get boot device location such as Target id,
         path Id, and Lun (IOCTL_GET_SCSI_ADDRESS); data
         returned in a SCSI_ADDRESS structure
        Resulting information is stored in the
         DUMP_INITIALIZATION_CONTEXT structure before
         calling the dump port driver’s DriverEntry
Find StartIo or DispatchCrb
32


        How do we send I/O requests?
          There   is no device object for dump port driver
        Use internal functions
          StartIo  (SCSI) – accepts a single
           SCSI_REQUEST_BLOCK (SRB) as argument
          DispatchCrb (IDE) – accepts a single
           argument, a channel extension structure
        Find functions by scanning dump port driver’s
         image’s text section for “magic bytes”
Find the Dump Port Driver’s
33
     Device Extension (1/2)
        Can’t simply call the internal functions, more initialization
         required
        Port/miniport share a device extension structure that must be
         properly initialized
            An internal variable of the port driver
            Most critical fields are filled in by dump port driver/miniport
             driver’s DriverEntry routines
        Two methods to find Device Extension
            Call a dump port function that leaks a pointer to it
            Use DumpInit.MemoryBlock + 16
                Dump port’s DriverEntry()assigns Device Extension to
                 DumpInit->MemoryBlock+16, which we control and pass as
                 second argument to DriverEntry() when we call it
        Both methods work for all transports all the way through
         Windows 8
Find the Dump Port Driver’s
34
     Device Extension (2/2)
        Function pointer leak example:
         Diskdump.sys leaks in ecx register in
         DiskDumpOpen()
         Transport            Leaking Function   Leaked in Register   Architecture



         SCSI/Storoprt        DiskDumpOpen       ecx                  x86
         (diskdump.sys)

         SCSI/Storport        DriverEntry        rdx                  x64
         (diskdump.sys)

         IDE (dumpata.sys)*   IdeDumpOpen        ecx                  x86

         IDE (dumpata.sys)*   IdeDumpOpen        rcx                  x64
Send SRB (SCSI) (1/2)
35


        Mimic DiskDumpWrite()
                  an MDL at offset 0xD0 (0x118 x64) into the
          Allocate
          device extension structure – MDL describes the
          SRB.DataBuffer
          Call   StartIo()
Send SRB (SCSI) (2/2)
36


        After MDL is created, send an SRB as follows:
          SRB.Function - SRB_FUNCTION_EXECUTE_SCSI
          SRB.PathId, SRB.TargetId, SRB.Lun – set to
           corresponding fields in SCSI_ADDRESS
          SRB.CdbLength - 10 for 10-byte SCSI-2 command
          SRB.SrbFlags - specify flags for a read operation
          SRB.DataTransferLength - 512
          SRB.DataBuffer - allocate 512 bytes
           NonPagedPool – result stored here
          SRB.Cdb – the SCSI-2 command descriptor block
           (cdb)
                Describes the location on disk to read
37
     Demo
     Overview
Recent Bootkits
38


        Alureon/TDL4 has gained popularity in the last
         few years
          Abuses driver trust chain by hooking the port and
           miniport drivers, which are at the bottom of the disk
           driver stack trust chain
          Modifies I/O requests in various ways to hide its
           rootkit file system, as well as return a clean MBR
        Similar MBR/VBR rootkits include Popureb,
         Stoned, Hasta La Vista, Zeroaccess
            Completely new strains, as well as variants, emerging
             constantly
TDL4 Bootkit Infection
39


        Modifies the miniport’s device object and driver
         object
          DRIVER_OBJECT.DriverStartIo  hooked
          DEVICE_OBJECT.DriverObject  hooked
          Lowest attached device is unlinked from the miniport
           device by hooking DEVICE_OBJECT.NextDevice
        Monitors for read or write attempts to the boot
         sector and its hidden file system
          If boot sector, return original, clean MBR
          If hidden file system, return zeroes

        For more info, see [2]
40
     Demo
     Defeating TDL4
Results – Full Disclosure!
41


        SCSI – working from Windows XP – 7 (tested)
        IDE – polling is hard 
            Method 1: IRB sent, garbage returned 
                Either the port driver is messing up the IRB somewhere
                 during polling or we are missing a field in dump extension
            Method 2: IRB sent, nothing returned , IRB status 2
             (data length mismatch), ATA status 0x20 (?)
                IRB.TaskFile might have invalid values
                     IDE_TASK_FILE: No examples anywhere!
                Dump extension field missing – data length?
PoC Improvements
42


        POCs for both transports can cause
         momentary lag or event deadlock, because
         normal I/O path is not properly “shutdown”
        Solution:
          SCSIPort  (push model, port driver controls
           queuing I/O) - Need to send flush and lock
           request SRB’s
          StorPort – (pull model, miniport driver controls
           queuing I/O) – StorPortPauseDevice()
43
     Windows 8 Release Preview
     A Sneak Peak at Exciting New Changes
Core Kernel Changes
44


        Synchronization changes suggest crash dump
         stack can be used in multiple places
          New    function IopInitializeCrashDump()
            Contents    of IoInitializeCrashDump() moved
            here
                 only called if a prior initialize attempt fails and it guards call
                  to IopInitializeCrashDump()with critical region
          IopCrashDumpLock     previously only used when
          crash dump stack is (re)configured; now
          additionally used when (re)initialized
Crashdmp Call Table Changes
45

        Table Offset*               Windows 7 Value             Windows 8 RP Value
0x0                          1                             1
0x4                          1                             4
0x8                          CrashdmpInitialize
0xC                          CrashdmpLoadDumpStack

0x10                         CrashdmpInitDumpStack

0x14                         CrashdmpFreeDumpStack

0x18                         CrashdmpDisable
0x1C                         CrashdmpNotify
0x20                         CrashdmpWrite
0x24                         CrashdmpUpdatePhysicalRange
0x28                                                       CrashdmpResumeCapable
0x2C                                                       CrashdmpGetTransferSizes
0x30                                                       CrashdmpLogStatusData
0x34                                                       CrashdmpReady

*Pointer width is 8 bytes on 64-bit systems
Crashdmp.sys Changes (1/6)
46

        GetLegacyPortDriverName() no longer uses static
         dump port driver names (e.g, “diskdump.sys”, “storport.sys”,
         “scsiport.sys”)
        After loading a crash dump driver in
         CrashdmpLoadDriver()via MmLoadSystemImage(), it
         uses RtlImageNtHeader on imageBase instead of direct
         return value – possible bug fix
        New hiber functions, ResumeCapable
        ETW tracing, performance counters
        Enhanced logging in c:DumpStack.log.tmp
        Crashdmp.sys “drive telemetry” callback
        New dump type: bitmap dump
Crashdmp.sys Changes (2/6)
47


        New security checks using __fastfail
         intrinsic [3]
          CORRUPT_LIST_ENTRY         cases
        DumpWrite function used by call table’s
         CrashdmpWrite is not handled by IDA auto
         analysis – you must undefine bogus
         data/code, restart analysis or force code
         generation on block, and recreate the function
          Several   other functions have this issue
Crashdmp.sys Changes (3/6)
48
Crashdmp.sys Changes (4/6)
49


        CrashdmpWrite behavior changed:
          Checks   that dump device is ready (eg, supported
           firmware); if so, call DumpWrite; if not, call
           DumpWriteCapsule which simulates the write
           by calling special “dump capsule” dump filters but
           does not write actual dump to disk
          “Dump capsule” concept not documented
Crashdmp.sys Changes (5/6)
50


        Dump port driver DriverEntry() prototype
         has changed
          Old:DriverEntry(NULL, DumpInit*)
          New: DriverEntry(NULL,
           CrashdmpContext*)
        This will affect our PoC (it won’t work on Win8)
          New    PoC coming soon…
Crashdmp.sys Changes (6/6)
51


        New CrashdmpReadRoutine populated in
         dump context structure by
         InitializeDumpDriver()
          Wrapper  around a call to new dump port driver
          function Diskdump!DiskDumpRead()
           Calls  new function DiskDumpIoIssue() which sets
            up SCSI read SRB and performs all of the hard tasks
            that the POC in this paper had to hack 
Why a New Read Capability?
52

        Not to make my research irrelevant 
        Internally: supports logging and new hibernation
         resume feature
        Externally: crash dump filter drivers now have the
         ability to filter read requests to dump port driver
            Define a DUMP_READ callback [4]
            Provide a pointer to the callback in
             FILTER_INITIALIZATION_CONTEXT [5]
        “Filter drivers can modify the contents of the data
         buffer contained in Mdl to revert any changes made to
         the data when it was written to disk” [4]
            Probably to support hibernation resume; for example,
             encryption drivers need to decrypt
How to Use It (1/3)
53


        Filter read callback is cool, but not helpful to the goal of
         this research
            We can only see read requests initiated by kernel/dump port
             driver; not useful for controlling what is read
        But the point is the Crash Dump I/O Path now supports
         reading – we don’t need to hack it
            At least not as bad as before
            Contention issues with normal I/O path still exist
How to Use It (2/3)
54


        We have two options:
         1.    CrashdmpReadRoutine(Type, Offset, Mdl): just a
               wrapper for port read routine; only adds functionality to call
               filter read callbacks
         2.    Diskdump!DumpRead(Type, Offset, Mdl): does the
               actual work with miniport to complete I/O
        The first option adds no value for us
        Best option: call the port driver’s DumpRead() routine
         directly
             Determine any pre-requisites
How to Use It (3/3)
55


        The dump port driver read routine is a simple wrapper:




        DiskDumpIoIssue() kindly handles the entire I/O
         issuing process for us (i.e, our POC’s hack):
            SRB initialization for a read operation
            Mapping the MDL if required
            Calling StartIo(), which calls the dump miniport
            Polling to wait on result
        Can we call DiskDumpRead() directly?
            Stay tuned…
56
     Conclusions
Takeaways
57


        Why is this important?
            We have a separate path to disk which is not currently
             hooked by any malware I am aware of
                Tampering with the crash dump mechanism could destabilize
                 the system
            We can read AND write to disk this way
                The crash dump port driver only provides callbacks to write to
                 disk, but the StartIo function lets us issue any arbitrary SRB
                The ability to write to disk with this technique provides us
                 unique remediation (file cleaning) opportunities
        New read functionality in Windows 8 makes reading
         disk via dump port driver officially supported (sort of)!
Stay Tuned…
58


        Keep an eye on blog.crowdstrike.com
          New   series on Windows 8 coming soon
            Alex   Ionescu (author of Windows Internals) covers
             new security features and how to break them
            I will be posting about crash dump changes related to
             this research
          Whitepapercoming soon
          Windows 8 PoC coming soon
References
59


     [1] http://msdn.microsoft.com/en-
     us/library/ff564084(v=VS.85).aspx
     [2] http://go.eset.com/us/resources/white-
     papers/The_Evolution_of_TDL.pdf
     [3] http://www.alex-ionescu.com/?m=201110
     [4] http://msdn.microsoft.com/en-
     us/library/windows/hardware/hh439713(v=vs.85).aspx
     [5] http://msdn.microsoft.com/en-
     us/library/windows/hardware/ff553865(v=vs.85).aspx

     Special thanks to Alex Ionescu
Thanks for listening!

       Questions ???

     lilhoser@gmail.com

          @lilhoser

60
61
     Appendix A
     Crash Dump Stack Initialization and Usage
     before Windows Vista
Initialization
62
Initialize IopDumpControlBlock
63


        KiInitializeKernel() 
         IoInitSystem() OR
         NtCreatePagingFile():
            IoInitializeCrashDump():
              IopInitializeDCB():
                  Allocate IopDumpControlBlock structure
                  Fill in basic debug information - # CPUs, architecture, OS
                   version, etc
                  Read registry settings for crash dump configuration
IopDumpControlBlock
64


     IopDumpControlBlock – global kernel variable
      typedef struct _DUMP_CONTROL_BLOCK
      {
          UCHAR Type;
          CHAR Flags;
          USHORT Size;
          CHAR NumberProcessors;
          CHAR Reserved;
          USHORT ProcessorArchitecture;
          PDUMP_STACK_CONTEXT DumpStack;
          PPHYSICAL_MEMORY_DESCRIPTOR MemoryDescriptor;
          ULONG MemoryDescriptorLength;
          PLARGE_INTEGER FileDescriptorArray;
          ULONG FileDescriptorSize;
          …
      }DUMP_CONTROL_BLOCK, *PDUMP_CONTROL_BLOCK;
Identify and Initialize Crash Dump
65
     Drivers
        IoInitializeCrashDump():
          IoGetDumpStack()  IopGetDumpStack():
              Fills IopDumpControlBlock.DumpInit:
                   Boot device type, geometry and hardware attributes
              Locates all crash dump drivers: port, miniport and crash
               dump filter drivers
                   Copies them into memory with “dump_” prefix
                       No DRIVER_OBJECT or DEVICE_OBJECT!
                   Port driver will be one of dump_scsiport, dump_ataport
                    or dump_storport; on disk either diskdump.sys
                    (scsi/storport) or dumpata.sys (ataport)
                   Miniport can be named anything
              Fills IopDumpControlBlock.DumpStack with linked list
               of copied drivers
IopDumpControlBlock.DumpStack
66

     typedef struct _DUMP_STACK_CONTEXT
     {
         DUMP_INITIALIZATION_CONTEXT Init;
         LARGE_INTEGER               PartitionOffset;
         PVOID                       DumpPointers;
         ULONG                       PointersLength;
         PWCHAR                      ModulePrefix;
         LIST_ENTRY                  DriverList;
         ANSI_STRING                 InitMsg;
         ANSI_STRING                 ProgMsg;
         ANSI_STRING                 DoneMsg;
         PVOID                       FileObject;
         enum _DEVICE_USAGE_NOTIFICATION_TYPE    UsageType;
     } DUMP_STACK_CONTEXT, *PDUMP_STACK_CONTEXT;
IopDumpControlBlock.DumpStack
67


        DumpPointers - contains hardware-specific
         information about the disk drive (via
         IOCTL_SCSI_GET_DUMP_POINTERS) which is used
         during write I/O operations to the crash dump file.
        DriverList - contains a linked list of data structures
         that describe the driver image of each driver in the
         crash dump stack; used at actual crash dump time to
         initialize each driver
        Init - of type DUMP_INITIALIZATION_CONTEXT
         (undocumented but exported), shown below, is only
         partially filled in during the 1st phase of initialization.
Usage
68
Call Dump Driver Entry Points (1/3)
69


        During pre-initialization, drivers were only mapped
         into memory - no management blocks created, no
         entry points called
        Each driver in the dump stack will now have its
         entry point called
        The first driver in the stack is always the dump
         port and it is always called first
        Two arguments:
         1.   NULL
         2.   IopDumpControlBlock.DumpInit
Call Dump Driver Entry Points (2/3)
70

     typedef struct _DUMP_INITIALIZATION_CONTEXT
     {
         ULONG Length;
         ULONG Reserved;
         PVOID MemoryBlock;
         PVOID CommonBuffer[2];
         PHYSICAL_ADDRESS PhysicalAddress[2];
         PSTALL_ROUTINE StallRoutine;
         PDUMP_DRIVER_OPEN OpenRoutine;
         PDUMP_DRIVER_WRITE WriteRoutine;
         PDUMP_DRIVER_FINISH FinishRoutine;
         struct _ADAPTER_OBJECT *AdapterObject;
         PVOID MappedRegisterBase;
         PVOID PortConfiguration;
         …
     } DUMP_INITIALIZATION_CONTEXT,*PDUMP_INITIALIZATION_CONTEXT;
Call Dump Driver Entry Points (3/3)
71


        OpenRoutine, WriteRoutine and
         FinishRoutine fields are populated:
            pointers to functions exported by the dump port driver
             which provide the kernel the ability to write the crash
             dump data to the crash dump file
        The dump miniport driver’s DriverEntry is
         called
            registers with the dump port driver
        All other dump driver’s DriverEntry are called
         with NULL arguments
            According to MSDN, this notifies them to operate in
             “crash dump mode”
Call Dump Port Driver Callbacks
72

        KeBugCheck2()  IoWriteCrashDump():
            IoInitializeDumpStack() – performs post-initialization of
             crash dump drivers
            DiskDumpOpen() – this port driver export is called to prepare
             the crash dump file
            Displays the dump string “Beginning dump of physical memory”,
             stored in the DUMP_CONTROL_BLOCK structure
            Calculates the dump storage space required based on
             configuration
            Fills a dump header with bug check codes and other debug
             information
            Invokes all BugCheckDumpIoCallback callbacks registered
             with the kernel via
             KeRegisterBugCheckReasonCallback(), passing the dump
             header
Data Written to Dump File
73

        KeBugCheck2()  IoWriteCrashDump():
            IoInitializeDumpStack() – performs post-
             initialization of crash dump drivers
            One of the following functions calls DiskDumpWrite()
             until all crash dump data is written:
                IopWriteSummaryHeader()
                IopWriteSummaryDump()
                IopWriteTriageDump()
            Invokes all BugCheckSecondaryDumpDataCallback
             callbacks to allow drivers to append data to the completed
             crash dump file
            Calls DiskDumpFinish() to close crash dump file
            Invokes all BugCheckDumpIoCallback callbacks,
             informing them crash dump is complete.
74
     Appendix B
     Bootkit Defeat Technique for IDE Drives
Send IRB (IDE) – General Idea
75
Send IRB (IDE) – Method 1
76

        Relies on calling port driver internal functions
        Mimic IdeDumpWritePending()
            Allocate a CRB in
             DUMP_INITIALIZATION_CONTEXT.MemoryBlock at
             the correct offset (0x120 for x86, 0x1C0 for x64)
            Allocate and fill in an IRB at offset 0x288 (0x3E8 for x64)
             in the CRB
            Store a pointer to a callback function in the CRB at offset
             0x4, which will be invoked when the dump port driver is
             notified that the I/O request is complete
            Allocate an MDL at offset 0x50 (0x88 for x64) in the CRB
            Send the CRB to DispatchCrb()
            Wait via IdeDumpWaitOnRequest()function
Send IRB (IDE) – Method 2
77

        Completely bypass dump port driver
        Mimic IdeDumpWritePending()
                Allocate a CRB in DUMP_INITIALIZATION_CONTEXT.MemoryBlock
                 at the correct offset (0x120 for x86, 0x1C0 for x64)
                Store a pointer to a callback function in the CRB at offset 0x4, which will
                 be invoked when the dump port driver is notified that the I/O request is
                 complete
                Allocate and fill in an IRB at offset 0x288 (0x3E8 for x64) in the CRB
                Replace DispatchCrb() with
                 Call the miniport’s HwStartIo routine, which is stored at offset 0x2E in the
                 
                 device extension, passing the device extension and the IRB
            Replace IdeDumpWaitOnRequest() with:
                Poll the device until the IRB status changes from zero by calling the miniport’s
                 HwInterrupt routine which is stored at offset 0x2F in the device extension,
                 passing the device extension only
Send IRB (IDE)
78


        IRB.Function - IRB_FUNCTION_ATA_COMMAND
        IRB.Channel - should be set to the value stored in
         the channel extension’s Channel field which is at
         offset 0x8A (0xEA for x64) from the start of the CRB
        IRB.TargetId - should be set to the value stored in
         the channel extension’s TargetId field which is at offset
         0x45D (0x6A9 for x64) from the start of the CRB
        IRB.Lun - should be set to the value stored in the
         channel extension’s Lun field which is at offset 0x45E
         (0x6AA for x64) from the start of the CRB

More Related Content

PDF
Hands-on ethernet driver
PDF
Interrupts
PPTX
Linux Network Stack
ODP
Inter-process communication of Android
PPTX
The TCP/IP Stack in the Linux Kernel
PPTX
用Raspberry Pi 學Linux I2C Driver
PPTX
Snort IDS/IPS Basics
PPTX
Linux Kernel MMC Storage driver Overview
Hands-on ethernet driver
Interrupts
Linux Network Stack
Inter-process communication of Android
The TCP/IP Stack in the Linux Kernel
用Raspberry Pi 學Linux I2C Driver
Snort IDS/IPS Basics
Linux Kernel MMC Storage driver Overview

What's hot (20)

PDF
Introduction to Linux Drivers
PDF
Character Drivers
PDF
Android Things : Building Embedded Devices
PPTX
Linux IO
PDF
Android Boot Time Optimization
PPT
Linux command ppt
PPTX
What is Bootloader???
PPTX
The Next Linux Superpower: eBPF Primer
PDF
DPDK: Multi Architecture High Performance Packet Processing
PPT
Windowsforensics
PDF
USB Drivers
PPT
Memory management in linux
PDF
Linux boot process
PDF
Play with FILE Structure - Yet Another Binary Exploit Technique
PDF
Linux Internals - Interview essentials - 1.0
PPTX
PART-2 : Mastering RTOS FreeRTOS and STM32Fx with Debugging
PPTX
Linux Memory Management with CMA (Contiguous Memory Allocator)
PPTX
PART-1 : Mastering RTOS FreeRTOS and STM32Fx with Debugging
PPTX
Understanding eBPF in a Hurry!
PDF
Reverse Engineering and Bug Hunting on KMDF Drivers - Enrique Nissim - 44CON ...
Introduction to Linux Drivers
Character Drivers
Android Things : Building Embedded Devices
Linux IO
Android Boot Time Optimization
Linux command ppt
What is Bootloader???
The Next Linux Superpower: eBPF Primer
DPDK: Multi Architecture High Performance Packet Processing
Windowsforensics
USB Drivers
Memory management in linux
Linux boot process
Play with FILE Structure - Yet Another Binary Exploit Technique
Linux Internals - Interview essentials - 1.0
PART-2 : Mastering RTOS FreeRTOS and STM32Fx with Debugging
Linux Memory Management with CMA (Contiguous Memory Allocator)
PART-1 : Mastering RTOS FreeRTOS and STM32Fx with Debugging
Understanding eBPF in a Hurry!
Reverse Engineering and Bug Hunting on KMDF Drivers - Enrique Nissim - 44CON ...
Ad

Viewers also liked (20)

PDF
CrowdCasts Monthly: When Pandas Attack
PDF
Be Social. Use CrowdRE.
PDF
CrowdCasts Monthly: Mitigating Pass the Hash
PDF
Hacking Exposed Live: Mobile Targeted Threats
PDF
Java Journal & Pyresso: A Python-Based Framework for Debugging Java
PDF
Venom
PDF
Bear Hunting: History and Attribution of Russian Intelligence Operations
PDF
End-to-End Analysis of a Domain Generating Algorithm Malware Family
PDF
TOR... ALL THE THINGS
PDF
CrowdCast Monthly: Operationalizing Intelligence
PDF
CrowdCasts Monthly: Going Beyond the Indicator
PDF
CrowdCasts Monthly: You Have an Adversary Problem
PDF
Battling Unknown Malware with Machine Learning
PDF
Cloud-Enabled: The Future of Endpoint Security
PDF
How to Replace Your Legacy Antivirus Solution with CrowdStrike
PDF
End-to-End Analysis of a Domain Generating Algorithm Malware Family Whitepaper
PPTX
BSides 2016 Presentation
PPTX
Hunting gh0st rat using memory forensics
PPTX
The Enemy Within: Stopping Advanced Attacks Against Local Users
PDF
IDAの脆弱性とBug Bounty by 千田 雅明
CrowdCasts Monthly: When Pandas Attack
Be Social. Use CrowdRE.
CrowdCasts Monthly: Mitigating Pass the Hash
Hacking Exposed Live: Mobile Targeted Threats
Java Journal & Pyresso: A Python-Based Framework for Debugging Java
Venom
Bear Hunting: History and Attribution of Russian Intelligence Operations
End-to-End Analysis of a Domain Generating Algorithm Malware Family
TOR... ALL THE THINGS
CrowdCast Monthly: Operationalizing Intelligence
CrowdCasts Monthly: Going Beyond the Indicator
CrowdCasts Monthly: You Have an Adversary Problem
Battling Unknown Malware with Machine Learning
Cloud-Enabled: The Future of Endpoint Security
How to Replace Your Legacy Antivirus Solution with CrowdStrike
End-to-End Analysis of a Domain Generating Algorithm Malware Family Whitepaper
BSides 2016 Presentation
Hunting gh0st rat using memory forensics
The Enemy Within: Stopping Advanced Attacks Against Local Users
IDAの脆弱性とBug Bounty by 千田 雅明
Ad

Similar to I/O, You Own: Regaining Control of Your Disk in the Presence of Bootkits (20)

PDF
CNIT 126: 10: Kernel Debugging with WinDbg
PDF
CNIT 126: 10: Kernel Debugging with WinDbg
PPTX
Device drivers and their applications
PPT
Device Driver in WinCE 6.0 R2
PDF
Blackfin Device Drivers
PDF
Solaris Kernel Debugging V1.0
PPTX
Acceleration of Statistical Detection of Zero-day Malware in the Memory Dump ...
PPTX
unit 5.pptx
PPT
WinCE
PDF
Understanding Windows NT Internals - Part 3
PDF
EclipseCon 2011: Deciphering the CDT debugger alphabet soup
PDF
Windows guest debugging presentation from KVM Forum 2012
PDF
Embedded I/O Management
PDF
Practical Malware Analysis: Ch 10: Kernel Debugging with WinDbg
PDF
Linux on System z the Toolchain in a Nutshell
PPT
Troubleshooting
PDF
Defeating Windows memory forensics
PDF
Faults inside System Software
PPTX
Device drivers by prabu m
PDF
ACPI and FreeBSD (Part 1)
CNIT 126: 10: Kernel Debugging with WinDbg
CNIT 126: 10: Kernel Debugging with WinDbg
Device drivers and their applications
Device Driver in WinCE 6.0 R2
Blackfin Device Drivers
Solaris Kernel Debugging V1.0
Acceleration of Statistical Detection of Zero-day Malware in the Memory Dump ...
unit 5.pptx
WinCE
Understanding Windows NT Internals - Part 3
EclipseCon 2011: Deciphering the CDT debugger alphabet soup
Windows guest debugging presentation from KVM Forum 2012
Embedded I/O Management
Practical Malware Analysis: Ch 10: Kernel Debugging with WinDbg
Linux on System z the Toolchain in a Nutshell
Troubleshooting
Defeating Windows memory forensics
Faults inside System Software
Device drivers by prabu m
ACPI and FreeBSD (Part 1)

More from CrowdStrike (9)

PDF
State of Endpoint Security: The Buyers Mindset
PDF
Understanding Fileless (or Non-Malware) Attacks and How to Stop Them
PDF
Cyber Security Extortion: Defending Against Digital Shakedowns
PDF
An Inside Look At The WannaCry Ransomware Outbreak
PDF
Proactive Threat Hunting: Game-Changing Endpoint Protection Beyond Alerting
PDF
DEFENDING AGAINST THREATS TARGETING THE MAC PLATFORM
PDF
CrowdStrike CrowdCast: Is Ransomware Morphing Beyond The Ability Of Standard ...
PDF
You Can't Stop The Breach Without Prevention And Detection
PDF
TOR... ALL THE THINGS Whitepaper
State of Endpoint Security: The Buyers Mindset
Understanding Fileless (or Non-Malware) Attacks and How to Stop Them
Cyber Security Extortion: Defending Against Digital Shakedowns
An Inside Look At The WannaCry Ransomware Outbreak
Proactive Threat Hunting: Game-Changing Endpoint Protection Beyond Alerting
DEFENDING AGAINST THREATS TARGETING THE MAC PLATFORM
CrowdStrike CrowdCast: Is Ransomware Morphing Beyond The Ability Of Standard ...
You Can't Stop The Breach Without Prevention And Detection
TOR... ALL THE THINGS Whitepaper

Recently uploaded (20)

PDF
cuic standard and advanced reporting.pdf
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PPTX
MYSQL Presentation for SQL database connectivity
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
KodekX | Application Modernization Development
PDF
Empathic Computing: Creating Shared Understanding
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PPTX
Spectroscopy.pptx food analysis technology
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Encapsulation theory and applications.pdf
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
Machine learning based COVID-19 study performance prediction
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
cuic standard and advanced reporting.pdf
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
MYSQL Presentation for SQL database connectivity
The Rise and Fall of 3GPP – Time for a Sabbatical?
Building Integrated photovoltaic BIPV_UPV.pdf
KodekX | Application Modernization Development
Empathic Computing: Creating Shared Understanding
Digital-Transformation-Roadmap-for-Companies.pptx
Network Security Unit 5.pdf for BCA BBA.
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Spectroscopy.pptx food analysis technology
Per capita expenditure prediction using model stacking based on satellite ima...
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Chapter 3 Spatial Domain Image Processing.pdf
Encapsulation theory and applications.pdf
Review of recent advances in non-invasive hemoglobin estimation
Machine learning based COVID-19 study performance prediction
Mobile App Security Testing_ A Comprehensive Guide.pdf
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf

I/O, You Own: Regaining Control of Your Disk in the Presence of Bootkits

  • 1. I/O, YOU OWN: REGAINING CONTROL OF YOUR DISK IN THE PRESENCE OF BOOTKITS Aaron LeMasters @lilhoser
  • 2. Introduction 2  My background  Your background  Brief history of this presentation  Disclaimer: some of this might be wrong…  Please read white paper for details
  • 3. Agenda 3  Technical Background  What is the crash dump stack in Windows?  How the operating system initializes and uses the crash dump stack (post Windows Vista)  Pre Vista is in Appendix A  Bootkit Defeat Technique for SCSI drives  How we can use this stack outside of the operating system’s normal activity  IDE drive technique in Appendix B  Sneak peak at Windows 8 Release Preview changes  Demo – Defeating TDL4
  • 4. 4 Technical Background Terminology and Concepts
  • 5. Basics 5  Port driver – abstraction interface provided by OS, hides underlying protocol details from class driver  Miniport driver – manufacturer-supplied driver to interface with hardware (Host Bus Adapter/HBA); linked against port driver for specific transport technology  Class driver – a driver that abstracts the underlying technology of a category of devices that share similar qualities (e.g., cdrom.sys)  Normal I/O path – the route an I/O request takes during regular system operation  Crash dump I/O path – the route the kernel uses to write a crash dump file to disk during a crash
  • 7. Crash Dump I/O Path 7
  • 8. Why two paths? 8  When a bugcheck occurs, the OS has no idea where the problem occurred – it could have happened inside a driver in the normal I/O path.  What differs between the two paths? Normal I/O Path Crash Dump I/O Path Primary drivers Many, layered Modified port and miniport Filter drivers Many, layered Crash dump filters only Controlled by I/O manager Kernel or crashdmp.sys Documented? Yes *cough*
  • 9. The Crash Dump Mechanism 9  Encompasses the entire crash dump process  Fromwhen it is initialized during system boot up to when it is used after KeBugCheck2()  Primary components:  The kernel  Crashdmp.sys (Vista+)  The crash dump driver stack or just “crash dump stack”  Goal: Write a crash dump file to boot device or save state in a hibernation file
  • 10. The Crash Dump Stack 10  A “stack” of drivers, consisting of:  A dump port driver  A dump miniport driver  One or more crash dump filter drivers  Initialized in two phases:  System startup/page file creation (pre-initialization)  System crash (post-initialization)  Used when:  A bug check occurs  The system is about to hibernate
  • 11. The Crash Dump Stack – Common Drivers 11 Driver Name On Disk Driver Base Name in Purpose Memory diskdump.sys dump_diskdump SCSI/Storport dump port driver with required exports from scsiport.sys and storport.sys. This driver is unloaded. dumpata.sys dump_dumpata IDE/ATA dump port driver with required ataport.sys exports. This driver is unloaded. scsiport.sys dump_scsiport The final SCSI/Storport dump port driver. ataport.sys dump_ataport The final IDE/ATA dump port driver. atapi.sys dump_atapi An older, generic ATAPI miniport driver provided by the OS for IDE/ATA drives vmscsi.sys dump_vmscsi The miniport driver provided by VMWare for SCSI drives. LSI_SAS.sys dump_LSI_SAS The miniport driver provided by LSI Corporation for serial- attached storage drives. dumpfve.sys dump_dumpfve Windows full volume encryption crash dump filter driver
  • 12. Crash Dump Environment 12  Normal I/O path is disabled  All processors are disabled except the one the current thread is executing on  Active CPU becomes single-threaded (IRQL is raised to HIGH_LEVEL) and uninterruptible  I/O sent to the crash dump stack is synchronous  If IDE controller, only the channel containing the device with the paging file is enabled
  • 13. 13 Technical Background Crash Dump Stack Initialization and Usage after Windows Vista
  • 14. Crash Dump Stack Configuration 14  Crash dump is configured via IoConfigureCrashDump()  Reads in registry settings to control dump behavior  Passes handle to system paging file to IopInitializeCrashDump()  Triggered via NtSetSystemInformation() or PoBroadcastSystemState() or PoShutdownBugCheck()
  • 16. Load and Call Entry Point of 16 Crashdmp.sys  Nearly all of crash dump code was removed from kernel and put in crashdmp.sys  KiInitializeKernel()  IoInitSystem() OR NtCreatePagingFile()  IoInitializeCrashDump(HANDLE PageFile)  IopLoadCrashDumpDriver() – loads crashdmp.sys  Crashdmp!DriverEntry() – fills crash dump call table  Entry point called with two arguments:  Name of the arc boot device  Pointer to a global crashdmp callback table
  • 17. Crashdmp.sys Call Table 17 Table Offset* Value 0x0 1 0x4 1 0x8 CrashdmpInitialize 0xC CrashdmpLoadDumpStack 0x10 CrashdmpInitDumpStack 0x14 CrashdmpFreeDumpStack 0x18 CrashdmpDisable 0x1C CrashdmpNotify 0x20 CrashdmpWrite 0x24 CrashdmpUpdatePhysicalRange *Pointer width is 8 bytes on 64-bit systems
  • 18. Identify and Initialize Crash Dump 18 Drivers  KiInitializeKernel()  IoInitSystem() OR NtCreatePagingFile()  IoInitializeCrashDump()  Crashdmp!CrashDmpInitialize():  Crashdmp!CrashdmpLoadDumpStack():  Crashdump!QueryPortDriver()  Crashdmp!LoadPortDriver()  Crashdmp!LoadFilterDrivers()  Crashdmp!InitializeFilterDrivers()
  • 19. CrashdmpInitialize() 19  References boot device’s FILE_OBJECT  Read registry for crash dump settings  Stored in local crashdump control block  Initializes crashdump control block  Registers a KbCallbackSecondaryDumpData bugcheck callback  Calls CrashdmpLoadDumpStack()…
  • 20. CrashdmpLoadDumpStack() 20  Queries port driver capabilities using IOCTL_SCSI_GET_DUMP_POINTERS, IOCTL_SCSI_GET_ADDRESS, IOCTL_SCSI_GET_PARTITION_INFO, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, IOCTL_SCSI_GET_DRIVE_GEOMETRY_EX  Locates all crash dump drivers: port, miniport and crash dump filter drivers  Copies them into memory with “dump_” prefix  No DRIVER_OBJECT or DEVICE_OBJECT!  Port driver will be one of dump_scsiport, dump_ataport or dump_storport; on disk either diskdump.sys (scsi/storport) or dumpata.sys (ataport)  Miniport can be named anything
  • 22. Call Dump Driver Entry Points 22  KeBugCheck2()  IoWriteCrashDump():  Calls the eighth entry in the CrashDmpCallTable table, CrashDmpNotify() - displays the string “collecting data for crash dump”  Fills dump block with bug check codes and other debug information  Appends a triage dump if necessary
  • 23. Call Dump Driver Entry Points and 23 Dump Port Driver Callbacks  KeBugCheck2()  IoWriteCrashDump():  Callsthe ninth entry in the CrashDmpCallTable table, CrashDmpWrite():  CrashdmpInitDumpStack():  StartFilterDrivers() – calls the DumpStart callback of each crash dump filter driver  InitializeDumpDriver() – calls the dump driver entry point; calls the DiskDumpOpen callback provided by the dump port driver; fills dump context structure with callback pointers CrashdmpWriteRoutine, CrashdmpWritePendingRoutine, CrashdmpFinishRoutine
  • 24. Data Written to Dump File 24  KeBugCheck2()  IoWriteCrashDump():  CrashDmpWrite():  CrashdmpInitDumpStack():  DumpWrite() – creates dump file based on configuration:  FillDumpHeader()  Calls one of:  WriteFullDump()  WriteKernelDump()  WriteMiniDump()  InvokeSecondaryDumpCallbacks() - Invokes all BugCheckSecondaryDumpDataCallback callbacks to allow drivers to append data to the completed crash dump file.  InvokeDumpCallbacks() - Invokes all BugCheckDumpIoCallback callbacks, informing them crash dump is complete.
  • 25. 25 Bootkit Defeat Technique How to bypass the Normal I/O Path and use the Crash Dump I/O Path to read and write to disk
  • 26. Inspiration 26 Restrictions on Miniport Drivers that Manage the Boot Drive: “A storage miniport driver that manages an adapter for a boot device is subject to special restrictions during a system crash. While dumping the system's memory image to disk, the miniport driver must operate within a different environment. The usual communication between the miniport driver, the port driver, and disk class driver is interrupted. The kernel does disk I/O by direct calls to the disk dump port driver (diskdump.sys for SCSI adapters or dumpata.sys for ATA controllers), bypassing file systems, and the normal I/O stack. The disk dump driver, in turn, calls the boot device's miniport driver to handle all I/O operations, and the disk dump driver intercepts all of the miniport driver's calls to the port driver.” [1]
  • 27. Leveraging the Crash Dump I/O 27 Path  The crash dump mechanism provides a pristine path to disk  But it only provides write capabilities  Leverage knowledge of the crash dump mechanism and internals of the port/miniport relationship to coerce read/write  Here’s how…
  • 28. ..sort of like the O/S does… 28
  • 29. …but more like this 29
  • 30. Identify Crash Dump Port/Miniport 30 Drivers  Walk loaded module list  Single out dump drivers easily via “dump_” prefix  Port driver will be one of dump_scsiport, dump_storport or dump_ataport  Miniport driver name:  open a handle to the class driver’s device object, walk attached devices to the lowest one  Vista+ DUMP_POINTERS_EX.DriverList  Once drivers have been found, call their entry points with the appropriate arguments  Dump port: DriverEntry(NULL, DumpInit*)  Dump miniport: DriverEntry(NULL, NULL)
  • 31. Get Boot Device Information 31  IOCTL to get hardware register mapping and port configuration information (IOCTL_SCSI_GET_DUMP_POINTERS); data returned in DUMP_POINTERS or DUMP_POINTERS_EX structure  IOCTL to get boot device location such as Target id, path Id, and Lun (IOCTL_GET_SCSI_ADDRESS); data returned in a SCSI_ADDRESS structure  Resulting information is stored in the DUMP_INITIALIZATION_CONTEXT structure before calling the dump port driver’s DriverEntry
  • 32. Find StartIo or DispatchCrb 32  How do we send I/O requests?  There is no device object for dump port driver  Use internal functions  StartIo (SCSI) – accepts a single SCSI_REQUEST_BLOCK (SRB) as argument  DispatchCrb (IDE) – accepts a single argument, a channel extension structure  Find functions by scanning dump port driver’s image’s text section for “magic bytes”
  • 33. Find the Dump Port Driver’s 33 Device Extension (1/2)  Can’t simply call the internal functions, more initialization required  Port/miniport share a device extension structure that must be properly initialized  An internal variable of the port driver  Most critical fields are filled in by dump port driver/miniport driver’s DriverEntry routines  Two methods to find Device Extension  Call a dump port function that leaks a pointer to it  Use DumpInit.MemoryBlock + 16  Dump port’s DriverEntry()assigns Device Extension to DumpInit->MemoryBlock+16, which we control and pass as second argument to DriverEntry() when we call it  Both methods work for all transports all the way through Windows 8
  • 34. Find the Dump Port Driver’s 34 Device Extension (2/2)  Function pointer leak example: Diskdump.sys leaks in ecx register in DiskDumpOpen() Transport Leaking Function Leaked in Register Architecture SCSI/Storoprt DiskDumpOpen ecx x86 (diskdump.sys) SCSI/Storport DriverEntry rdx x64 (diskdump.sys) IDE (dumpata.sys)* IdeDumpOpen ecx x86 IDE (dumpata.sys)* IdeDumpOpen rcx x64
  • 35. Send SRB (SCSI) (1/2) 35  Mimic DiskDumpWrite() an MDL at offset 0xD0 (0x118 x64) into the  Allocate device extension structure – MDL describes the SRB.DataBuffer  Call StartIo()
  • 36. Send SRB (SCSI) (2/2) 36  After MDL is created, send an SRB as follows:  SRB.Function - SRB_FUNCTION_EXECUTE_SCSI  SRB.PathId, SRB.TargetId, SRB.Lun – set to corresponding fields in SCSI_ADDRESS  SRB.CdbLength - 10 for 10-byte SCSI-2 command  SRB.SrbFlags - specify flags for a read operation  SRB.DataTransferLength - 512  SRB.DataBuffer - allocate 512 bytes NonPagedPool – result stored here  SRB.Cdb – the SCSI-2 command descriptor block (cdb)  Describes the location on disk to read
  • 37. 37 Demo Overview
  • 38. Recent Bootkits 38  Alureon/TDL4 has gained popularity in the last few years  Abuses driver trust chain by hooking the port and miniport drivers, which are at the bottom of the disk driver stack trust chain  Modifies I/O requests in various ways to hide its rootkit file system, as well as return a clean MBR  Similar MBR/VBR rootkits include Popureb, Stoned, Hasta La Vista, Zeroaccess  Completely new strains, as well as variants, emerging constantly
  • 39. TDL4 Bootkit Infection 39  Modifies the miniport’s device object and driver object  DRIVER_OBJECT.DriverStartIo  hooked  DEVICE_OBJECT.DriverObject  hooked  Lowest attached device is unlinked from the miniport device by hooking DEVICE_OBJECT.NextDevice  Monitors for read or write attempts to the boot sector and its hidden file system  If boot sector, return original, clean MBR  If hidden file system, return zeroes  For more info, see [2]
  • 40. 40 Demo Defeating TDL4
  • 41. Results – Full Disclosure! 41  SCSI – working from Windows XP – 7 (tested)  IDE – polling is hard   Method 1: IRB sent, garbage returned   Either the port driver is messing up the IRB somewhere during polling or we are missing a field in dump extension  Method 2: IRB sent, nothing returned , IRB status 2 (data length mismatch), ATA status 0x20 (?)  IRB.TaskFile might have invalid values  IDE_TASK_FILE: No examples anywhere!  Dump extension field missing – data length?
  • 42. PoC Improvements 42  POCs for both transports can cause momentary lag or event deadlock, because normal I/O path is not properly “shutdown”  Solution:  SCSIPort (push model, port driver controls queuing I/O) - Need to send flush and lock request SRB’s  StorPort – (pull model, miniport driver controls queuing I/O) – StorPortPauseDevice()
  • 43. 43 Windows 8 Release Preview A Sneak Peak at Exciting New Changes
  • 44. Core Kernel Changes 44  Synchronization changes suggest crash dump stack can be used in multiple places  New function IopInitializeCrashDump()  Contents of IoInitializeCrashDump() moved here  only called if a prior initialize attempt fails and it guards call to IopInitializeCrashDump()with critical region  IopCrashDumpLock previously only used when crash dump stack is (re)configured; now additionally used when (re)initialized
  • 45. Crashdmp Call Table Changes 45 Table Offset* Windows 7 Value Windows 8 RP Value 0x0 1 1 0x4 1 4 0x8 CrashdmpInitialize 0xC CrashdmpLoadDumpStack 0x10 CrashdmpInitDumpStack 0x14 CrashdmpFreeDumpStack 0x18 CrashdmpDisable 0x1C CrashdmpNotify 0x20 CrashdmpWrite 0x24 CrashdmpUpdatePhysicalRange 0x28 CrashdmpResumeCapable 0x2C CrashdmpGetTransferSizes 0x30 CrashdmpLogStatusData 0x34 CrashdmpReady *Pointer width is 8 bytes on 64-bit systems
  • 46. Crashdmp.sys Changes (1/6) 46  GetLegacyPortDriverName() no longer uses static dump port driver names (e.g, “diskdump.sys”, “storport.sys”, “scsiport.sys”)  After loading a crash dump driver in CrashdmpLoadDriver()via MmLoadSystemImage(), it uses RtlImageNtHeader on imageBase instead of direct return value – possible bug fix  New hiber functions, ResumeCapable  ETW tracing, performance counters  Enhanced logging in c:DumpStack.log.tmp  Crashdmp.sys “drive telemetry” callback  New dump type: bitmap dump
  • 47. Crashdmp.sys Changes (2/6) 47  New security checks using __fastfail intrinsic [3]  CORRUPT_LIST_ENTRY cases  DumpWrite function used by call table’s CrashdmpWrite is not handled by IDA auto analysis – you must undefine bogus data/code, restart analysis or force code generation on block, and recreate the function  Several other functions have this issue
  • 49. Crashdmp.sys Changes (4/6) 49  CrashdmpWrite behavior changed:  Checks that dump device is ready (eg, supported firmware); if so, call DumpWrite; if not, call DumpWriteCapsule which simulates the write by calling special “dump capsule” dump filters but does not write actual dump to disk  “Dump capsule” concept not documented
  • 50. Crashdmp.sys Changes (5/6) 50  Dump port driver DriverEntry() prototype has changed  Old:DriverEntry(NULL, DumpInit*)  New: DriverEntry(NULL, CrashdmpContext*)  This will affect our PoC (it won’t work on Win8)  New PoC coming soon…
  • 51. Crashdmp.sys Changes (6/6) 51  New CrashdmpReadRoutine populated in dump context structure by InitializeDumpDriver()  Wrapper around a call to new dump port driver function Diskdump!DiskDumpRead()  Calls new function DiskDumpIoIssue() which sets up SCSI read SRB and performs all of the hard tasks that the POC in this paper had to hack 
  • 52. Why a New Read Capability? 52  Not to make my research irrelevant   Internally: supports logging and new hibernation resume feature  Externally: crash dump filter drivers now have the ability to filter read requests to dump port driver  Define a DUMP_READ callback [4]  Provide a pointer to the callback in FILTER_INITIALIZATION_CONTEXT [5]  “Filter drivers can modify the contents of the data buffer contained in Mdl to revert any changes made to the data when it was written to disk” [4]  Probably to support hibernation resume; for example, encryption drivers need to decrypt
  • 53. How to Use It (1/3) 53  Filter read callback is cool, but not helpful to the goal of this research  We can only see read requests initiated by kernel/dump port driver; not useful for controlling what is read  But the point is the Crash Dump I/O Path now supports reading – we don’t need to hack it  At least not as bad as before  Contention issues with normal I/O path still exist
  • 54. How to Use It (2/3) 54  We have two options: 1. CrashdmpReadRoutine(Type, Offset, Mdl): just a wrapper for port read routine; only adds functionality to call filter read callbacks 2. Diskdump!DumpRead(Type, Offset, Mdl): does the actual work with miniport to complete I/O  The first option adds no value for us  Best option: call the port driver’s DumpRead() routine directly  Determine any pre-requisites
  • 55. How to Use It (3/3) 55  The dump port driver read routine is a simple wrapper:  DiskDumpIoIssue() kindly handles the entire I/O issuing process for us (i.e, our POC’s hack):  SRB initialization for a read operation  Mapping the MDL if required  Calling StartIo(), which calls the dump miniport  Polling to wait on result  Can we call DiskDumpRead() directly?  Stay tuned…
  • 56. 56 Conclusions
  • 57. Takeaways 57  Why is this important?  We have a separate path to disk which is not currently hooked by any malware I am aware of  Tampering with the crash dump mechanism could destabilize the system  We can read AND write to disk this way  The crash dump port driver only provides callbacks to write to disk, but the StartIo function lets us issue any arbitrary SRB  The ability to write to disk with this technique provides us unique remediation (file cleaning) opportunities  New read functionality in Windows 8 makes reading disk via dump port driver officially supported (sort of)!
  • 58. Stay Tuned… 58  Keep an eye on blog.crowdstrike.com  New series on Windows 8 coming soon  Alex Ionescu (author of Windows Internals) covers new security features and how to break them  I will be posting about crash dump changes related to this research  Whitepapercoming soon  Windows 8 PoC coming soon
  • 59. References 59 [1] http://msdn.microsoft.com/en- us/library/ff564084(v=VS.85).aspx [2] http://go.eset.com/us/resources/white- papers/The_Evolution_of_TDL.pdf [3] http://www.alex-ionescu.com/?m=201110 [4] http://msdn.microsoft.com/en- us/library/windows/hardware/hh439713(v=vs.85).aspx [5] http://msdn.microsoft.com/en- us/library/windows/hardware/ff553865(v=vs.85).aspx Special thanks to Alex Ionescu
  • 60. Thanks for listening! Questions ??? lilhoser@gmail.com @lilhoser 60
  • 61. 61 Appendix A Crash Dump Stack Initialization and Usage before Windows Vista
  • 63. Initialize IopDumpControlBlock 63  KiInitializeKernel()  IoInitSystem() OR NtCreatePagingFile():  IoInitializeCrashDump():  IopInitializeDCB():  Allocate IopDumpControlBlock structure  Fill in basic debug information - # CPUs, architecture, OS version, etc  Read registry settings for crash dump configuration
  • 64. IopDumpControlBlock 64 IopDumpControlBlock – global kernel variable typedef struct _DUMP_CONTROL_BLOCK { UCHAR Type; CHAR Flags; USHORT Size; CHAR NumberProcessors; CHAR Reserved; USHORT ProcessorArchitecture; PDUMP_STACK_CONTEXT DumpStack; PPHYSICAL_MEMORY_DESCRIPTOR MemoryDescriptor; ULONG MemoryDescriptorLength; PLARGE_INTEGER FileDescriptorArray; ULONG FileDescriptorSize; … }DUMP_CONTROL_BLOCK, *PDUMP_CONTROL_BLOCK;
  • 65. Identify and Initialize Crash Dump 65 Drivers  IoInitializeCrashDump():  IoGetDumpStack()  IopGetDumpStack():  Fills IopDumpControlBlock.DumpInit:  Boot device type, geometry and hardware attributes  Locates all crash dump drivers: port, miniport and crash dump filter drivers  Copies them into memory with “dump_” prefix  No DRIVER_OBJECT or DEVICE_OBJECT!  Port driver will be one of dump_scsiport, dump_ataport or dump_storport; on disk either diskdump.sys (scsi/storport) or dumpata.sys (ataport)  Miniport can be named anything  Fills IopDumpControlBlock.DumpStack with linked list of copied drivers
  • 66. IopDumpControlBlock.DumpStack 66 typedef struct _DUMP_STACK_CONTEXT { DUMP_INITIALIZATION_CONTEXT Init; LARGE_INTEGER PartitionOffset; PVOID DumpPointers; ULONG PointersLength; PWCHAR ModulePrefix; LIST_ENTRY DriverList; ANSI_STRING InitMsg; ANSI_STRING ProgMsg; ANSI_STRING DoneMsg; PVOID FileObject; enum _DEVICE_USAGE_NOTIFICATION_TYPE UsageType; } DUMP_STACK_CONTEXT, *PDUMP_STACK_CONTEXT;
  • 67. IopDumpControlBlock.DumpStack 67  DumpPointers - contains hardware-specific information about the disk drive (via IOCTL_SCSI_GET_DUMP_POINTERS) which is used during write I/O operations to the crash dump file.  DriverList - contains a linked list of data structures that describe the driver image of each driver in the crash dump stack; used at actual crash dump time to initialize each driver  Init - of type DUMP_INITIALIZATION_CONTEXT (undocumented but exported), shown below, is only partially filled in during the 1st phase of initialization.
  • 69. Call Dump Driver Entry Points (1/3) 69  During pre-initialization, drivers were only mapped into memory - no management blocks created, no entry points called  Each driver in the dump stack will now have its entry point called  The first driver in the stack is always the dump port and it is always called first  Two arguments: 1. NULL 2. IopDumpControlBlock.DumpInit
  • 70. Call Dump Driver Entry Points (2/3) 70 typedef struct _DUMP_INITIALIZATION_CONTEXT { ULONG Length; ULONG Reserved; PVOID MemoryBlock; PVOID CommonBuffer[2]; PHYSICAL_ADDRESS PhysicalAddress[2]; PSTALL_ROUTINE StallRoutine; PDUMP_DRIVER_OPEN OpenRoutine; PDUMP_DRIVER_WRITE WriteRoutine; PDUMP_DRIVER_FINISH FinishRoutine; struct _ADAPTER_OBJECT *AdapterObject; PVOID MappedRegisterBase; PVOID PortConfiguration; … } DUMP_INITIALIZATION_CONTEXT,*PDUMP_INITIALIZATION_CONTEXT;
  • 71. Call Dump Driver Entry Points (3/3) 71  OpenRoutine, WriteRoutine and FinishRoutine fields are populated:  pointers to functions exported by the dump port driver which provide the kernel the ability to write the crash dump data to the crash dump file  The dump miniport driver’s DriverEntry is called  registers with the dump port driver  All other dump driver’s DriverEntry are called with NULL arguments  According to MSDN, this notifies them to operate in “crash dump mode”
  • 72. Call Dump Port Driver Callbacks 72  KeBugCheck2()  IoWriteCrashDump():  IoInitializeDumpStack() – performs post-initialization of crash dump drivers  DiskDumpOpen() – this port driver export is called to prepare the crash dump file  Displays the dump string “Beginning dump of physical memory”, stored in the DUMP_CONTROL_BLOCK structure  Calculates the dump storage space required based on configuration  Fills a dump header with bug check codes and other debug information  Invokes all BugCheckDumpIoCallback callbacks registered with the kernel via KeRegisterBugCheckReasonCallback(), passing the dump header
  • 73. Data Written to Dump File 73  KeBugCheck2()  IoWriteCrashDump():  IoInitializeDumpStack() – performs post- initialization of crash dump drivers  One of the following functions calls DiskDumpWrite() until all crash dump data is written:  IopWriteSummaryHeader()  IopWriteSummaryDump()  IopWriteTriageDump()  Invokes all BugCheckSecondaryDumpDataCallback callbacks to allow drivers to append data to the completed crash dump file  Calls DiskDumpFinish() to close crash dump file  Invokes all BugCheckDumpIoCallback callbacks, informing them crash dump is complete.
  • 74. 74 Appendix B Bootkit Defeat Technique for IDE Drives
  • 75. Send IRB (IDE) – General Idea 75
  • 76. Send IRB (IDE) – Method 1 76  Relies on calling port driver internal functions  Mimic IdeDumpWritePending()  Allocate a CRB in DUMP_INITIALIZATION_CONTEXT.MemoryBlock at the correct offset (0x120 for x86, 0x1C0 for x64)  Allocate and fill in an IRB at offset 0x288 (0x3E8 for x64) in the CRB  Store a pointer to a callback function in the CRB at offset 0x4, which will be invoked when the dump port driver is notified that the I/O request is complete  Allocate an MDL at offset 0x50 (0x88 for x64) in the CRB  Send the CRB to DispatchCrb()  Wait via IdeDumpWaitOnRequest()function
  • 77. Send IRB (IDE) – Method 2 77  Completely bypass dump port driver  Mimic IdeDumpWritePending()  Allocate a CRB in DUMP_INITIALIZATION_CONTEXT.MemoryBlock at the correct offset (0x120 for x86, 0x1C0 for x64)  Store a pointer to a callback function in the CRB at offset 0x4, which will be invoked when the dump port driver is notified that the I/O request is complete  Allocate and fill in an IRB at offset 0x288 (0x3E8 for x64) in the CRB  Replace DispatchCrb() with Call the miniport’s HwStartIo routine, which is stored at offset 0x2E in the  device extension, passing the device extension and the IRB  Replace IdeDumpWaitOnRequest() with:  Poll the device until the IRB status changes from zero by calling the miniport’s HwInterrupt routine which is stored at offset 0x2F in the device extension, passing the device extension only
  • 78. Send IRB (IDE) 78  IRB.Function - IRB_FUNCTION_ATA_COMMAND  IRB.Channel - should be set to the value stored in the channel extension’s Channel field which is at offset 0x8A (0xEA for x64) from the start of the CRB  IRB.TargetId - should be set to the value stored in the channel extension’s TargetId field which is at offset 0x45D (0x6A9 for x64) from the start of the CRB  IRB.Lun - should be set to the value stored in the channel extension’s Lun field which is at offset 0x45E (0x6AA for x64) from the start of the CRB