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


Published on

Published in: Technology
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

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

  2. 2. Introduction2  My background  Your background  Brief history of this presentation  Disclaimer: some of this might be wrong…  Please read white paper for details
  3. 3. Agenda3  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. 4 Technical Background Terminology and Concepts
  5. 5. Basics5  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
  6. 6. Normal I/O Path6
  7. 7. Crash Dump I/O Path7
  8. 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. 9. The Crash Dump Mechanism9  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. 10. The Crash Dump Stack10  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. 11. The Crash Dump Stack – Common Drivers11 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. 12. Crash Dump Environment12  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. 13 Technical Background Crash Dump Stack Initialization and Usage after Windows Vista
  14. 14. Crash Dump Stack Configuration14  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()
  15. 15. Initialization15
  16. 16. Load and Call Entry Point of16 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. 17. Crashdmp.sys Call Table17 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. 18. Identify and Initialize Crash Dump18 Drivers  KiInitializeKernel()  IoInitSystem() OR NtCreatePagingFile()  IoInitializeCrashDump()  Crashdmp!CrashDmpInitialize():  Crashdmp!CrashdmpLoadDumpStack():  Crashdump!QueryPortDriver()  Crashdmp!LoadPortDriver()  Crashdmp!LoadFilterDrivers()  Crashdmp!InitializeFilterDrivers()
  19. 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. 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
  21. 21. Usage21
  22. 22. Call Dump Driver Entry Points22  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. 23. Call Dump Driver Entry Points and23 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. 24. Data Written to Dump File24  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. 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. 26. Inspiration26 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 systems 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 devices miniport driver to handle all I/O operations, and the disk dump driver intercepts all of the miniport drivers calls to the port driver.” [1]
  27. 27. Leveraging the Crash Dump I/O27 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. 28. ..sort of like the O/S does…28
  29. 29. …but more like this29
  30. 30. Identify Crash Dump Port/Miniport30 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. 31. Get Boot Device Information31  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. 32. Find StartIo or DispatchCrb32  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. 33. Find the Dump Port Driver’s33 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. 34. Find the Dump Port Driver’s34 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. 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. 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. 37 Demo Overview
  38. 38. Recent Bootkits38  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. 39. TDL4 Bootkit Infection39  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. 40 Demo Defeating TDL4
  41. 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. 42. PoC Improvements42  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. 43 Windows 8 Release Preview A Sneak Peak at Exciting New Changes
  44. 44. Core Kernel Changes44  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. 45. Crashdmp Call Table Changes45 Table Offset* Windows 7 Value Windows 8 RP Value0x0 1 10x4 1 40x8 CrashdmpInitialize0xC CrashdmpLoadDumpStack0x10 CrashdmpInitDumpStack0x14 CrashdmpFreeDumpStack0x18 CrashdmpDisable0x1C CrashdmpNotify0x20 CrashdmpWrite0x24 CrashdmpUpdatePhysicalRange0x28 CrashdmpResumeCapable0x2C CrashdmpGetTransferSizes0x30 CrashdmpLogStatusData0x34 CrashdmpReady*Pointer width is 8 bytes on 64-bit systems
  46. 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. 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
  48. 48. Crashdmp.sys Changes (3/6)48
  49. 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. 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. 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. 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. 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. 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. 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. 56 Conclusions
  57. 57. Takeaways57  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. 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. 59. References59 [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. 60. Thanks for listening! Questions ??? lilhoser@gmail.com @lilhoser60
  61. 61. 61 Appendix A Crash Dump Stack Initialization and Usage before Windows Vista
  62. 62. Initialization62
  63. 63. Initialize IopDumpControlBlock63  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. 64. IopDumpControlBlock64 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. 65. Identify and Initialize Crash Dump65 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. 66. IopDumpControlBlock.DumpStack66 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. 67. IopDumpControlBlock.DumpStack67  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.
  68. 68. Usage68
  69. 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. 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. 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. 72. Call Dump Port Driver Callbacks72  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. 73. Data Written to Dump File73  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. 74 Appendix B Bootkit Defeat Technique for IDE Drives
  75. 75. Send IRB (IDE) – General Idea75
  76. 76. Send IRB (IDE) – Method 176  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. 77. Send IRB (IDE) – Method 277  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. 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