ACPI调试
Linux内核调试
Windows内核调试
 
  调试战役
调试原理
新工具观察
 
  Linux
Windows Vista
Windows
 
  Linux驱动
WDF
WDM
 
  PCI Express
PCI/PCI-X
USB
无线通信协议
 
  64位CPU
ARM
IA-32
  CPU Info Center
 
  ACPI标准
系统认证
Desktop
服务器
 
  Embedded Linux
嵌入式开发工具
VxWorks
WinCE
嵌入式Windows
沪ICP备05041459号
About AdvDbg Consult Train Services Products Tools Community Contact   登录 | 注册

摘链大法

SECTION [.写在前面的话]
最近日子过的比较颠狂
写篇随笔记录一下

这次想聊的是DKOM技术,换言之也就是KillVXK前辈经常挂在嘴边的所谓“摘链大法”。  ^_^
那么我们今天“摘”什么呢?
答曰:今天我们摘驱动,换言之我们想用DKOM技术隐藏驱动。
最后还附上了KillVXK前辈的代码片断,用于绕开老版本的Darkspy。
 
今天8.1
本人水平差,仅以此随笔献给伟大的中国人民解放军建军80周年。

 
SECTION [.基础知识]
_DRIVER_OBJECT 结构:
   +0x000 Type                  : Int2B
   +0x002 Size                  : Int2B
   +0x004 DeviceObject          : Ptr32  _DEVICE_OBJECT
   +0x008 Flags                 : Uint4B
   +0x00c DriverStart           : Ptr32  Void
   +0x010 DriverSize            : Uint4B
   +0x014 DriverSection         : Ptr32  Void
   +0x018 DriverExtension       : Ptr32  _DRIVER_EXTENSION
   +0x01c DriverName            : _UNICODE_STRING
   +0x024 HardwareDatabase      : Ptr32  _UNICODE_STRING
   +0x028 FastIoDispatch        : Ptr32  _FAST_IO_DISPATCH
   +0x02c DriverInit            : Ptr32       long
   +0x030 DriverStartIo         : Ptr32       void
   +0x034 DriverUnload          : Ptr32       void
   +0x038 MajorFunction         : [28] Ptr32  long



SECTION [.关键点]
   +0x014 DriverSection         : Ptr32 Void

    这个可爱的Void小指针指向哪里呢?关于这点,我觉得《Rootkits - Subverting the Windows Kernel》根本就没打算讲清楚,胡乱说了一气,想胡弄谁呀?
    实际上,这个Void要强制转换成“_LDR_DATA_TABLE_ENTRY”,再看下子:

LDR_DATA_TABLE_ENTRY 结构:

   +0x000 InLoadOrderLinks               : _LIST_ENTRY
   +0x008 InMemoryOrderLinks             : _LIST_ENTRY
   +0x010 InInitializationOrderLinks     : _LIST_ENTRY
   +0x018 DllBase                        : Ptr32 Void
   +0x01c EntryPoint                     : Ptr32 Void
   +0x020 SizeOfImage                    : Uint4B
   +0x024 FullDllName                    : _UNICODE_STRING
   +0x02c BaseDllName                    : _UNICODE_STRING
   +0x034 Flags                          : Uint4B
   +0x038 LoadCount                      : Uint2B
   +0x03a TlsIndex                       : Uint2B
   +0x03c HashLinks                      : _LIST_ENTRY
   +0x03c SectionPointer                 : Ptr32 Void
   +0x040 CheckSum                       : Uint4B
   +0x044 TimeDateStamp                  : Uint4B
   +0x044 LoadedImports                  : Ptr32 Void
   +0x048 EntryPointActivationContext    : Ptr32 Void
   +0x04c PatchInformation               : Ptr32 Void
 
了解到这个程度,基础知识就基本够用了。
 

 
SECTION [.实验 && 实践]
    前段时间刚写过8254的代码,就用Win32的 \Driver\Beep 驱动开始实验,看着似乎亲切些~

kd> !object  \Driver\beep
Object: 852d9400  Type: (85fa33b0) Driver
    ObjectHeader: 852d93e8
    HandleCount: 0  PointerCount: 3
    Directory Object: e1008c40  Name: Beep
 
 
kd> !strct DRIVER_OBJECT  852d9400
struct   _DRIVER_OBJECT (sizeof=168)
+00 int16    Type =                               0004
+02 int16    Size =                               00a8
+04 struct   _DEVICE_OBJECT *DeviceObject =       852D98A8
+08 uint32   Flags =                              00000012
+0c void     *DriverStart =                       F7C45000
+10 uint32   DriverSize =                         00001080
+14 void     *DriverSection =                     85EBA008
+18 struct   _DRIVER_EXTENSION *DriverExtension = 852D94A8
+1c struct   _UNICODE_STRING DriverName
+1c    uint16   Length =                         0018
+1e    uint16   MaximumLength =                  0018
+20    uint16   *Buffer =                        E18A0960
+24 struct   _UNICODE_STRING *HardwareDatabase = 8068EB10
+28 struct   _FAST_IO_DISPATCH *FastIoDispatch = 00000000
+2c function *DriverInit =                       F7C4566C
+30 function *DriverStartIo =                    F7C4551A
+34 function *DriverUnload =                     F7C45620
+38 function *MajorFunction[28] =                F7C4546A
                                                 804FC8DE
                                                 F7C454B8
                                                 804FC8DE
                                                 804FC8DE
                                                 804FC8DE
                                                 804FC8DE
                                                 804FC8DE
                                                 804FC8DE
                                                 804FC8DE
                                                 804FC8DE
                                                 804FC8DE
                                                 804FC8DE
                                                 804FC8DE
                                                 F7C45400
                                                 804FC8DE
                                                 804FC8DE
                                                 804FC8DE
                                                 F7C45354
                                                 804FC8DE
                                                 804FC8DE
                                                 804FC8DE
                                                 804FC8DE
                                                 804FC8DE
                                                 804FC8DE
                                                 804FC8DE
                                                 804FC8DE
                                                 804FC8DE
 
 
还可以让显示更清楚些,而且还方便对比:
kd> dt  nt!_DRIVER_OBJECT  852d9400
   +0x000 Type              : 4
   +0x002 Size              : 168
   +0x004 DeviceObject      : 0x852d98a8 _DEVICE_OBJECT
   +0x008 Flags             : 0x12
   +0x00c DriverStart       : 0xf7c45000
   +0x010 DriverSize        : 0x1080
   +0x014 DriverSection     : 0x85eba008
   +0x018 DriverExtension   : 0x852d94a8 _DRIVER_EXTENSION
   +0x01c DriverName        : _UNICODE_STRING "\Driver\Beep"
   +0x024 HardwareDatabase  : 0x8068eb10 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"
   +0x028 FastIoDispatch    : (null)
   +0x02c DriverInit        : 0xf7c4566c       long  Beep!DriverEntry+0
   +0x030 DriverStartIo     : 0xf7c4551a       void  Beep!BeepStartIo+0
   +0x034 DriverUnload      : 0xf7c45620       void  Beep!BeepUnload+0
   +0x038 MajorFunction     : [28] 0xf7c4546a  long  Beep!BeepOpen+0
 
 
关键的一步分析:
kd> dt  nt!_LDR_DATA_TABLE_ENTRY  85eba008
   +0x000 InLoadOrderLinks             : _LIST_ENTRY [ 0x85677008 - 0x85625008 ]
   +0x008 InMemoryOrderLinks           : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x010 InInitializationOrderLinks   : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x018 DllBase                      : 0xf7c45000
   +0x01c EntryPoint                   : 0xf7c4566c
   +0x020 SizeOfImage                  : 0x2000
   +0x024 FullDllName                  : _UNICODE_STRING "\SystemRoot\System32\Drivers\Beep.SYS"
  
+0x02c BaseDllName                  : _UNICODE_STRING "Beep.SYS"
   +0x034 Flags                        : 0x9104000
   +0x038 LoadCount                    : 1
   +0x03a TlsIndex                     : 0
   +0x03c HashLinks                    : _LIST_ENTRY [ 0xffffffff - 0xc82c ]
   +0x03c SectionPointer               : 0xffffffff
   +0x040 CheckSum                     : 0xc82c
   +0x044 TimeDateStamp                : 0xfffffffe
   +0x044 LoadedImports                : 0xfffffffe
   +0x048 EntryPointActivationContext  : (null)
   +0x04c PatchInformation             : 0x00650042
 
好的,到现在您看到了什么?我反正看到了非常多的有用信息,足够我理解摘链用的数据结构了~
 
 
当然,还可以再细化一下:
kd> dt nt!_LIST_ENTRY 85eba008
 [ 0x8562f008 - 0x85eba008 ]
   +0x000 Flink       : 0x8562f008 _LIST_ENTRY  [ 0x8562f008 - 0x85eba008 ]   // 前一个结构的前后 //
   +0x004 Blink       : 0x85eba008 _LIST_ENTRY  [ 0x85eba008 - 0x8561abe8 ]   // 后一个结构的前后 //
 
此时,驱动信息的双向链表已体现的淋漓尽致。
 
 
Beep.sys的前一项是vga.sys:
kd> dt nt!_LDR_DATA_TABLE_ENTRY 85677008
   +0x000 InLoadOrderLinks             : _LIST_ENTRY [ 0x8562f008 - 0x85eba008 ]
   +0x008 InMemoryOrderLinks           : _LIST_ENTRY [ 0xf7a298b0 - 0x1 ]
   +0x010 InInitializationOrderLinks   : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x018 DllBase                      : 0xf7a29000
   +0x01c EntryPoint                   : 0xf7a2d642
   +0x020 SizeOfImage                  : 0x6000
   +0x024 FullDllName                  : _UNICODE_STRING "\SystemRoot\System32\drivers\vga.sys"
   +0x02c BaseDllName                  : _UNICODE_STRING "vga.sys"
   +0x034 Flags                        : 0x9104000
   +0x038 LoadCount                    : 1
   +0x03a TlsIndex                     : 0
   +0x03c HashLinks                    : _LIST_ENTRY [ 0xffffffff - 0x1265e ]
   +0x03c SectionPointer               : 0xffffffff
   +0x040 CheckSum                     : 0x1265e
   +0x044 TimeDateStamp                : 0x85fde361
   +0x044 LoadedImports                : 0x85fde361
   +0x048 EntryPointActivationContext  : (null)
   +0x04c PatchInformation             : 0x00670076
 
 
vga.sys再往前一项是mnmdd.sys(what's this?):
kd> dt nt!_LDR_DATA_TABLE_ENTRY 0x8562f008 
   +0x000 InLoadOrderLinks             : _LIST_ENTRY [ 0x85498548 - 0x85677008 ]
   +0x008 InMemoryOrderLinks           : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x010 InInitializationOrderLinks   : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x018 DllBase                      : 0xf7c47000
   +0x01c EntryPoint                   : 0xf7c47646
   +0x020 SizeOfImage                  : 0x2000
   +0x024 FullDllName                  : _UNICODE_STRING "\SystemRoot\System32\Drivers\mnmdd.SYS"
 
  +0x02c BaseDllName                  : _UNICODE_STRING "mnmdd.SYS"
   +0x034 Flags                        : 0x9104000
   +0x038 LoadCount                    : 1
   +0x03a TlsIndex                     : 0
   +0x03c HashLinks                    : _LIST_ENTRY [ 0xffffffff - 0xf3f7 ]
   +0x03c SectionPointer               : 0xffffffff
   +0x040 CheckSum                     : 0xf3f7
   +0x044 TimeDateStamp                : 0x85fde361
   +0x044 LoadedImports                : 0x85fde361
   +0x048 EntryPointActivationContext  : (null)
   +0x04c PatchInformation             : 0x006e006d
 
Beep.sys的后一项是:
kd> dt nt!_LDR_DATA_TABLE_ENTRY 0x85625008
   +0x000 InLoadOrderLinks             : _LIST_ENTRY [ 0x85eba008 - 0x8561abe8 ]
   +0x008 InMemoryOrderLinks           : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x010 InInitializationOrderLinks   : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x018 DllBase                      : 0xf7d15000
   +0x01c EntryPoint                   : 0xf7d1559a
   +0x020 SizeOfImage                  : 0x1000
   +0x024 FullDllName                  : _UNICODE_STRING "\SystemRoot\System32\Drivers\Null.SYS"
   +0x02c BaseDllName                  : _UNICODE_STRING "Null.SYS"
   +0x034 Flags                        : 0x9104000
   +0x038 LoadCount                    : 1
   +0x03a TlsIndex                     : 0
   +0x03c HashLinks                    : _LIST_ENTRY [ 0xffffffff - 0x8483 ]
   +0x03c SectionPointer               : 0xffffffff
   +0x040 CheckSum                     : 0x8483
   +0x044 TimeDateStamp                : 0xfffffffe
   +0x044 LoadedImports                : 0xfffffffe
   +0x048 EntryPointActivationContext  : (null)
   +0x04c PatchInformation             : 0x0075004e
 

 
SECTION [.小结]

这一段驱动链表大致是这样的:
          0x8562f008              0x85677008             0x85eba008              0x85625008
          mnmdd.sys                vga.sys                beep.sys                null.sys
.. <------        ------>  <------        ------>  <------        ------>  <------        ------> ..
   0x85498548  0x85677008  0x8562f008  0x85eba008  0x85677008  0x85625008  0x85eba008 
0x8561abe8


完全没有什么神秘的了,想摘什么就摘什么吧!~
 

 
SECTION [.扩展]
    现在再回过来看《Rootkits - Subverting the Windows Kernel》第七章,你就会觉得,他们所说的“MODULE_ENTRY”结构纯粹是给狗熊的玉米,因为我Google了所谓的“_MODULE_ENTRY”(DDK、Symbols中均没有这样的东西),它的定义大致是这样的:
/* MODULE_ENTRY struct */
typedef struct _MODULE_ENTRY {
    LIST_ENTRY  le_mod;
    DWORD       unknown[4];
    DWORD       base;
    DWORD       driver_start;
    DWORD       sectionsize;
    UNICODE_STRING  driver_Path;
    UNICODE_STRING  driver_Name;
} MODULE_ENTRY,  *PMODULE_ENTRY;


    其实就是一个简化的“_LDR_DATA_TABLE_ENTRY”,搞出这种东西的意义也就是:“熊~ 给你一个玉米,吃去吧,你就别打破沙锅问到底了。”
    我们答曰:想的美!
 

 
SECTION [.KillVXK前辈的“谈谈欺骗Darkspy 1.0.5非fix版的驱动隐藏方法”]
代码是这样的:
// 处理模块,欺骗darkspy //
// 传入参数drvobj //

void ProModule(PDRIVER_OBJECT drvobj)
{
      PLDR_MODULE section = (PLDR_MODULE)drvobj->DriverSection;
      if (section != NULL)
      {
            section->DllBase = 0;
            section->EntryPoint = 0;
            section->SizeOfImage = 0;
            section->CheckSum = 0;
            memzero(section->BaseDllName.Buffer,  section->BaseDllName.MaximumLength);
            memzero(section->FullDllName.Buffer,  section->FullDllName.MaximumLength);
            drvobj->DriverSection = 0;
      }
 
      return ;
}

代码和我们上面说的东西很紧密,瞎猜都能猜出是在干什么,最后一个 drvobj->DriverSection = 0,从此抹平了许多东西~
没有反汇编过Darkspy 1.0.5 的非Fix版本,不知道它内部是怎么偷的这个懒最终被KillVXK发现了,嘿嘿......
继续练习反汇编。

 

最后打点信息,收功。
PLDR_DATA_TABLE_ENTRY Section = DriverObject->DriverSection;

if(Section != NULL)
{
      DPRINT("DriverObject->DriverSection = 0x%x\n", DriverObject->DriverSection);
      DPRINT("Section->BaseAddress = 0x%x\n", Section->BaseAddress);
      DPRINT("Section->EntryPoint = 0x%x\n", Section->EntryPoint);
      DPRINT("Section->SizeOfImage = 0x%x\n", Section->SizeOfImage);
      DPRINT("Section->CheckSum = 0x%x\n", Section->CheckSum);
      DPRINT("Section->BaseDllName [%ws]\n", Section->BaseDllName.Buffer);
      DPRINT("Section->FullDllName [%ws]\n", Section->FullDllName.Buffer);
}



最后来张图,怎么样,是不是和 IS 的感觉很像?   : P





NUPT  - WANG yu








posted on Wednesday, August 01, 2007 12:27 PM 由 WANGyu

# re: 摘链大法 @ Wednesday, August 01, 2007 10:39 PM

文笔和内容都非常棒!

Raymond

# re: 摘链大法 @ Thursday, August 02, 2007 8:37 AM

向张老师学习! ^_^

WANGyu

# re: 摘链大法 @ Monday, February 18, 2008 2:27 PM

KdpNtosImageBase = CONTAINING_RECORD(
(LoaderBlock->LoadOrderListHead.Flink),
LDR_DATA_TABLE_ENTRY,
InLoadOrderLinks)->DllBase;

WANGyu

# re: 摘链大法 @ Saturday, February 23, 2008 4:38 PM

又学到东西了,呵呵.顺便问下张老师的书什么时候能买到啊

llx571030

 
Legal Notice Privacy Statement Corporate Governance Corporate Governance
(C)2004-2005 Advanced Debugging Ltd. All Rights Reserved.