BY SUDAMI
为了能够调试多点还原软件"雨过天晴" 的启动代码,目前有2种方式:
引用:
(1) 在Bochs调试器上装Windows XP系统,然后用Bochs单步调试. 不过光安装操作系统就得花20个小时以上
(2) 用Wnhex克隆整个磁盘,配置Bochs的*.bxrc文件.用这个克隆的磁盘来调试MBR
方案二较简单,故我选择此方式调试. 在一个干净的Vmvare上装上雨过天晴,用Winhex克隆整个磁盘,Bochs调起来,发现根本没有进入ygtq的MBR,而是原始的引导代码. 这才意识到ygtq在驱动中做了手脚,对MBR的读写操作进行了重定向.于是开始分析起来. 经过几小时的战斗,终于搞定. 下面是一些调试分析的细节,希望对各位有所帮助! ----------------------------------------------------------------------- 雨过天晴拦截了对磁盘扇区的读写操作,会重新定位MBR,使得Winhex读取的MBR是原始的.这样用Bochs就没法调试ygtq的启动过程代码了.我们在调试器中恢复掉其在disk.sys 和 atapi.sys上的HOOK,再进行磁盘克隆. 雨过天晴在Shdbus.sys的分发例程中会检测disk.sys上的 0x4 和 0xf号派遣函数是否被恢复.若是,则恢复disk.sys的0x4 & 0xf为自己的地址,并全部替换掉atapi.sys的分发例程. #define IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0f #define IRP_MJ_WRITE 0x04 在Windbg中观察: kd> !drvobj /driver/disk 3 Driver object (81b7df38) is for: /Driver/Disk Driver Extension List: (id , addr) (f99e33be 81b7dd38) Device Object list: 81b7a7b0 81b7a030 81bc4030 DriverEntry: f99d38ab disk!GsDriverEntry DriverStartIo: 00000000 DriverUnload: f99e353a CLASSPNP!ClassUnload AddDevice: f99e4ec0 CLASSPNP!ClassAddDevice Dispatch routines: [00] IRP_MJ_CREATE f9785cd6 Shield+0x3cd6 [01] IRP_MJ_CREATE_NAMED_PIPE f9785cd6 Shield+0x3cd6 [02] IRP_MJ_CLOSE f9785cd6 Shield+0x3cd6 [03] IRP_MJ_READ f9785cd6 Shield+0x3cd6 [04] IRP_MJ_WRITE f9785cd6 Shield+0x3cd6 [05] IRP_MJ_QUERY_INFORMATION f9785cd6 Shield+0x3cd6 [06] IRP_MJ_SET_INFORMATION f9785cd6 Shield+0x3cd6 [07] IRP_MJ_QUERY_EA f9785cd6 Shield+0x3cd6 [08] IRP_MJ_SET_EA f9785cd6 Shield+0x3cd6 [09] IRP_MJ_FLUSH_BUFFERS f9785cd6 Shield+0x3cd6 [0a] IRP_MJ_QUERY_VOLUME_INFORMATION f9785cd6 Shield+0x3cd6 [0b] IRP_MJ_SET_VOLUME_INFORMATION f9785cd6 Shield+0x3cd6 [0c] IRP_MJ_DIRECTORY_CONTROL f9785cd6 Shield+0x3cd6 [0d] IRP_MJ_FILE_SYSTEM_CONTROL f9785cd6 Shield+0x3cd6 [0e] IRP_MJ_DEVICE_CONTROL f9785cd6 Shield+0x3cd6 [0f] IRP_MJ_INTERNAL_DEVICE_CONTROL f9785cd6 Shield+0x3cd6 [10] IRP_MJ_SHUTDOWN f9785cd6 Shield+0x3cd6 [11] IRP_MJ_LOCK_CONTROL f9785cd6 Shield+0x3cd6 [12] IRP_MJ_CLEANUP f9785cd6 Shield+0x3cd6 [13] IRP_MJ_CREATE_MAILSLOT f9785cd6 Shield+0x3cd6 [14] IRP_MJ_QUERY_SECURITY f9785cd6 Shield+0x3cd6 [15] IRP_MJ_SET_SECURITY f9785cd6 Shield+0x3cd6 [16] IRP_MJ_POWER f9785cd6 Shield+0x3cd6 [17] IRP_MJ_SYSTEM_CONTROL f9785cd6 Shield+0x3cd6 [18] IRP_MJ_DEVICE_CHANGE f9785cd6 Shield+0x3cd6 [19] IRP_MJ_QUERY_QUOTA f9785cd6 Shield+0x3cd6 [1a] IRP_MJ_SET_QUOTA f9785cd6 Shield+0x3cd6 [1b] IRP_MJ_PNP f99e2d15 CLASSPNP!ClassDispatchPnp 而原始的地址函数名如下: Dispatch routines: [00] IRP_MJ_CREATE f7668c30 CLASSPNP!ClassCreateClose [01] IRP_MJ_CREATE_NAMED_PIPE 804f5282 nt!IopInvalidDeviceRequest [02] IRP_MJ_CLOSE f7668c30 CLASSPNP!ClassCreateClose [03] IRP_MJ_READ f7662d9b CLASSPNP!ClassReadWrite [04] IRP_MJ_WRITE f7662d9b CLASSPNP!ClassReadWrite // [05] IRP_MJ_QUERY_INFORMATION 804f5282 nt!IopInvalidDeviceRequest [06] IRP_MJ_SET_INFORMATION 804f5282 nt!IopInvalidDeviceRequest [07] IRP_MJ_QUERY_EA 804f5282 nt!IopInvalidDeviceRequest [08] IRP_MJ_SET_EA 804f5282 nt!IopInvalidDeviceRequest [09] IRP_MJ_FLUSH_BUFFERS f7663366 CLASSPNP!ClassShutdownFlush [0a] IRP_MJ_QUERY_VOLUME_INFORMATION 804f5282 nt!IopInvalidDeviceRequest [0b] IRP_MJ_SET_VOLUME_INFORMATION 804f5282 nt!IopInvalidDeviceRequest [0c] IRP_MJ_DIRECTORY_CONTROL 804f5282 nt!IopInvalidDeviceRequest [0d] IRP_MJ_FILE_SYSTEM_CONTROL 804f5282 nt!IopInvalidDeviceRequest [0e] IRP_MJ_DEVICE_CONTROL f766344d CLASSPNP!ClassDeviceControlDispatch[0f] IRP_MJ_INTERNAL_DEVICE_CONTROL f7666fc3 CLASSPNP!ClassInternalIoControl // [10] IRP_MJ_SHUTDOWN f7663366 CLASSPNP!ClassShutdownFlush [11] IRP_MJ_LOCK_CONTROL 804f5282 nt!IopInvalidDeviceRequest [12] IRP_MJ_CLEANUP 804f5282 nt!IopInvalidDeviceRequest [13] IRP_MJ_CREATE_MAILSLOT 804f5282 nt!IopInvalidDeviceRequest [14] IRP_MJ_QUERY_SECURITY 804f5282 nt!IopInvalidDeviceRequest [15] IRP_MJ_SET_SECURITY 804f5282 nt!IopInvalidDeviceRequest [16] IRP_MJ_POWER f7664ef3 CLASSPNP!ClassDispatchPower [17] IRP_MJ_SYSTEM_CONTROL f7669a24 CLASSPNP!ClassSystemControl [18] IRP_MJ_DEVICE_CHANGE 804f5282 nt!IopInvalidDeviceRequest [19] IRP_MJ_QUERY_QUOTA 804f5282 nt!IopInvalidDeviceRequest [1a] IRP_MJ_SET_QUOTA 804f5282 nt!IopInvalidDeviceRequest [1b] IRP_MJ_PNP f7668d15 CLASSPNP!ClassDispatchPnp 现在在调试器中手工修改函数地址: kd> ln CLASSPNP!ClassInternalIoControl (f99e0fc3) CLASSPNP!ClassInternalIoControl | (f99e0fc3) CLASSPNP!ClassInternalIoControl Exact matches: CLASSPNP!ClassInternalIoControl = <no type information> kd> ed 81b7dfac f99e0fc3 kd> !drvobj /driver/disk 3 Driver object (81b7df38) is for: /Driver/Disk Driver Extension List: (id , addr) (f99e33be 81b7dd38) Device Object list: 81b7a7b0 81b7a030 81bc4030 DriverEntry: f99d38ab disk!GsDriverEntry DriverStartIo: 00000000 DriverUnload: f99e353a CLASSPNP!ClassUnload AddDevice: f99e4ec0 CLASSPNP!ClassAddDevice Dispatch routines: [00] IRP_MJ_CREATE f9785cd6 Shield+0x3cd6 [01] IRP_MJ_CREATE_NAMED_PIPE f9785cd6 Shield+0x3cd6 [02] IRP_MJ_CLOSE f9785cd6 Shield+0x3cd6 [03] IRP_MJ_READ f9785cd6 Shield+0x3cd6 [04] IRP_MJ_WRITE f9785cd6 Shield+0x3cd6 [05] IRP_MJ_QUERY_INFORMATION f9785cd6 Shield+0x3cd6 [06] IRP_MJ_SET_INFORMATION f9785cd6 Shield+0x3cd6 [07] IRP_MJ_QUERY_EA f9785cd6 Shield+0x3cd6 [08] IRP_MJ_SET_EA f9785cd6 Shield+0x3cd6 [09] IRP_MJ_FLUSH_BUFFERS f9785cd6 Shield+0x3cd6 [0a] IRP_MJ_QUERY_VOLUME_INFORMATION f9785cd6 Shield+0x3cd6 [0b] IRP_MJ_SET_VOLUME_INFORMATION f9785cd6 Shield+0x3cd6 [0c] IRP_MJ_DIRECTORY_CONTROL f9785cd6 Shield+0x3cd6 [0d] IRP_MJ_FILE_SYSTEM_CONTROL f9785cd6 Shield+0x3cd6 [0e] IRP_MJ_DEVICE_CONTROL f9785cd6 Shield+0x3cd6[0f] IRP_MJ_INTERNAL_DEVICE_CONTROL f99e0fc3 CLASSPNP!ClassInternalIoControl // 更改后 [10] IRP_MJ_SHUTDOWN f9785cd6 Shield+0x3cd6 [11] IRP_MJ_LOCK_CONTROL f9785cd6 Shield+0x3cd6 [12] IRP_MJ_CLEANUP f9785cd6 Shield+0x3cd6 [13] IRP_MJ_CREATE_MAILSLOT f9785cd6 Shield+0x3cd6 [14] IRP_MJ_QUERY_SECURITY f9785cd6 Shield+0x3cd6 [15] IRP_MJ_SET_SECURITY f9785cd6 Shield+0x3cd6 [16] IRP_MJ_POWER f9785cd6 Shield+0x3cd6 [17] IRP_MJ_SYSTEM_CONTROL f9785cd6 Shield+0x3cd6 [18] IRP_MJ_DEVICE_CHANGE f9785cd6 Shield+0x3cd6 [19] IRP_MJ_QUERY_QUOTA f9785cd6 Shield+0x3cd6 [1a] IRP_MJ_SET_QUOTA f9785cd6 Shield+0x3cd6 [1b] IRP_MJ_PNP f99e2d15 CLASSPNP!ClassDispatchPnp 然后下断点观察: kd> ba w 4 81b7dfac kd> bl 0 e 81b7dfac w 4 0001 (0001) kd> g Breakpoint 0 hit Shdbus+0x56e: f9ea056e a1200eeaf9 mov eax,dword ptr [Shdbus+0xe20 (f9ea0e20)] kd> kvn # ChildEBP RetAddr Args to Child00 f9e2fb3c 804eedf9 81b7d8b8 81b7c828 81731530 Shdbus+0x56e 01 f9e2fb4c f99dd061 81bc5000 81439500 81731530 nt!IopfCallDriver+0x31 02 81b7d8b8 00000000 81b7f888 81bd6040 81bc4030 CLASSPNP!SubmitTransferPacket+0x82 kd> !thread THREAD 81bc4da8 Cid 0004.006c Teb: 00000000 Win32Thread: 00000000 RUNNING on processor 0 Not impersonating DeviceMap e1006008 Owning Process 81bbd7c0 Image: System Wait Start TickCount 18821 Ticks: 3 (0:00:00:00.046) Context Switch Count 12678 UserTime 00:00:00.000 KernelTime 00:00:02.281 Start Address Shield (0xf9782886) Stack Init f9e30000 Current f9e2fd38 Base f9e30000 Limit f9e2d000 Call 0 Priority 16 BasePriority 8 PriorityDecrement 0 DecrementCount 0 ChildEBP RetAddr Args to Child f9e2fb3c 804eedf9 81b7d8b8 81b7c828 81731530 Shdbus+0x56e f9e2fb4c f99dd061 81bc5000 81439500 81731530 nt!IopfCallDriver+0x31 (FPO: [0,0,0]) 81b7d8b8 00000000 81b7f888 81bd6040 81bc4030 CLASSPNP!SubmitTransferPacket+0x82 (FPO: [Non-Fpo]) IDA打开雨过天晴的boot0驱动shdbus.sys ,定位到+0x1056e 处,位于分发函数IrpInternalDeviceControl 内,代码如下:
代码:
NTSTATUS IrpInternalDeviceControl (int DeviceObject, PIRP Irp)
{
int DeviceExtension, srb, atapi_driver_object, disk_driver_object, srb_cdb, IoControlCode ;
HANDLE CurrentTID;
struct _IRP::$::$::$::$A02EC6A2CE86544F716F4825015773AC::_IO_STACK_LOCATION *CurrentStackLocation;
char OperationCode;
DeviceExtension = *(DWORD *)(DeviceObject + 0x28);
CurrentTID = PsGetCurrentThreadId();
PsGetCurrentProcessId();
srb = 0;
if ( g_disk_internal_device_control_dispatch )
{
disk_driver_object = *(DWORD *)(g_disk_device_object + 8);
if ( *(DWORD *)(disk_driver_object + 0x74) != g_disk_internal_device_control_dispatch
|| *(DWORD *)(disk_driver_object + 0x48) != g_disk_internal_device_control_dispatch
)
{//
// #define IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0f
// #define IRP_MJ_SCSI 0x0f
// 雨过天晴会不断检查自己的 HOOK点 ,并恢复之 .若 2个程序同时在同一点
// 循环检查并恢复自己的钩子 ,会导致系统启动后及其缓慢 . 而且 "雨过天晴 "会结束
// 掉与其竞争的系统线程 ,导致系统出现异常错误 .BSOD.
//
*(DWORD *)(disk_driver_object + 0x74) = g_disk_internal_device_control_dispatch;
*(DWORD *)(disk_driver_object + 0x48) = g_disk_internal_device_control_dispatch;
// disk 分发例程往下发的时候 ,起扩展设备偏移 +0x008的地方是 atapi.sys的设备对象 ,"雨过天晴 "在此进行验证 .
if ( *(DWORD *)(DeviceExtension + 8) == g_atapi_device_object )
{
if ( g_allowed_TID_1_0000006c
&& CurrentTID != *(HANDLE *)g_allowed_TID_1_0000006c
&& g_allowed_TID_2_ffffffff
&& CurrentTID != *(HANDLE *)g_allowed_TID_2_ffffffff
&& g_allowed_TID_3_00000070
&& CurrentTID != *(HANDLE *)g_allowed_TID_3_00000070
&& g_allowed_TID_4_00000240
&& CurrentTID != *(HANDLE *)g_allowed_TID_4_00000240 )
{
// 不是以上 4个系统线程 ,便会被 "雨过 "结束掉 ,并且阻止当前 IRP的下发 .于是就 BSOD了 .
ZwTerminateProcess((HANDLE)0xFFFFFFFF, 0);
denny:
Irp->IoStatus.Status = 0;
IofCompleteRequest(Irp, 0);
return 0;
}
}
}
atapi_driver_object = *(DWORD *)(g_atapi_device_object + 8);
if ( *(DWORD *)(atapi_driver_object + 0x74) != (DWORD)atapi_Proxy_dispatch ) // 在此处恢复对 atapi.sys分发例程的 HOOK
memset((void *)(atapi_driver_object + 0x38), (int)atapi_Proxy_dispatch, 0x6Cu);
}
CurrentStackLocation = Irp->Tail.Overlay.CurrentStackLocation;
IoControlCode = *((DWORD *)CurrentStackLocation + 3);
srb_cdb = 0;
if ( IoControlCode == 0x1B0012 || IoControlCode == 0x1B0011 )
{
srb = *((DWORD *)CurrentStackLocation + 1);
srb_cdb = srb + 0x30;
}
if ( *(DWORD *)(DeviceExtension + 8) == g_atapi_device_object )
{
if ( g_allowed_TID_1_0000006c )
{
if ( CurrentTID != *(HANDLE *)g_allowed_TID_1_0000006c )
{
if ( !g_allowed_TID_2_ffffffff || CurrentTID != *(HANDLE *)g_allowed_TID_2_ffffffff )
{
if ( !g_allowed_TID_3_00000070 || CurrentTID != *(HANDLE *)g_allowed_TID_3_00000070 )
{
if ( !g_allowed_TID_4_00000240 || CurrentTID != *(HANDLE *)g_allowed_TID_4_00000240 )
{
if ( srb )
{
if ( !*(BYTE *)(srb + 2) )
{
if ( srb_cdb )
{
OperationCode = *(BYTE *)srb_cdb;
if ( *(BYTE *)srb_cdb == SCSIOP_WRITE
|| OperationCode == SCSIOP_SEND
|| OperationCode == SCSIOP_FLUSH_BUFFER
|| OperationCode == SCSIOP_WRITE_VERIFY
|| OperationCode == SCSIOP_READ
|| OperationCode == SCSIOP_RECEIVE )
goto denny;
}
}
}
}
}
}
}
}
}
return IrpReadWrite_dep(DeviceObject, Irp);
}
(1) 现在调试器中将 jnz 改成 Jmp , 即 0F 84 à 90 E9 (2) 经过初步分析 ,雨过天晴大致在 Disk.sys和 Atapi.sys层做了过滤 ,为了验证这一想法 ,我恢复掉其钩子后 ,自己写程序不经过文件系统层 ,构建 IRP发到 DR0上读取 MBR,看是否成功 .现要恢复 Disk.sys的 IRP_MJ_READ & IRP_MJ_INTERNAL_DEVICE_CONTROL 例程 和 Atapi.sys的 IRP_MJ_INTERNAL_DEVICE_CONTROL 例程 : (因为我的程序是自己构建 IRP, 填充 0xf 号控制码 , 即 isl->MajorFunction = IRP_MJ_SCSI, 然后发送到 DR0 设备上 , 那么 IRP 往下走的过程中就会调用 DR0 对应的驱动对象的分发例程 , 也就是 Disk.sys 的 0xf 号分发例程 , 而非 IRP_MJ_READ, 所以根据我的程序特性 , 应该恢复 Disk.sys 的 IRP_MJ_INTERNAL_DEVICE_CONTROL 历程 ) kd> ln CLASSPNP!ClassInternalIoControl (f99e0fc3) CLASSPNP!ClassInternalIoControl | (f99e0fc3) CLASSPNP!ClassInternalIoControl Exact matches: CLASSPNP!ClassInternalIoControl = <no type information> kd> ln CLASSPNP!ClassReadWrite (f99dcd9b) CLASSPNP!ClassReadWrite | (f99dcd9b) CLASSPNP!ClassReadWrite Exact matches: CLASSPNP!ClassReadWrite = <no type information> kd> ed 81b7df38+0x38+0x3c f99e0fc3 kd> ed 81b7df38+0x38+0xc f99dcd9b kd> !drvobj /driver/disk 3 … Dispatch routines: [00] IRP_MJ_CREATE f9785cd6 Shield+0x3cd6 [01] IRP_MJ_CREATE_NAMED_PIPE f9785cd6 Shield+0x3cd6 [02] IRP_MJ_CLOSE f9785cd6 Shield+0x3cd6[03] IRP_MJ_READ f99dcd9b CLASSPNP!ClassReadWrite [04] IRP_MJ_WRITE f9785cd6 Shield+0x3cd6 … [0f] IRP_MJ_INTERNAL_DEVICE_CONTROL f99e0fc3 CLASSPNP!ClassInternalIoControl … 原始的 Atapi.sys的分发例程如下 : Dispatch routines: [00] IRP_MJ_CREATE bae6d572 atapi!IdePortAlwaysStatusSuccessIrp [01] IRP_MJ_CREATE_NAMED_PIPE 804f5282 nt!IopInvalidDeviceRequest [02] IRP_MJ_CLOSE bae6d572 atapi!IdePortAlwaysStatusSuccessIrp [03] IRP_MJ_READ 804f5282 nt!IopInvalidDeviceRequest [04] IRP_MJ_WRITE 804f5282 nt!IopInvalidDeviceRequest [05] IRP_MJ_QUERY_INFORMATION 804f5282 nt!IopInvalidDeviceRequest [06] IRP_MJ_SET_INFORMATION 804f5282 nt!IopInvalidDeviceRequest [07] IRP_MJ_QUERY_EA 804f5282 nt!IopInvalidDeviceRequest [08] IRP_MJ_SET_EA 804f5282 nt!IopInvalidDeviceRequest [09] IRP_MJ_FLUSH_BUFFERS 804f5282 nt!IopInvalidDeviceRequest [0a] IRP_MJ_QUERY_VOLUME_INFORMATION 804f5282 nt!IopInvalidDeviceRequest [0b] IRP_MJ_SET_VOLUME_INFORMATION 804f5282 nt!IopInvalidDeviceRequest [0c] IRP_MJ_DIRECTORY_CONTROL 804f5282 nt!IopInvalidDeviceRequest [0d] IRP_MJ_FILE_SYSTEM_CONTROL 804f5282 nt!IopInvalidDeviceRequest [0e] IRP_MJ_DEVICE_CONTROL bae6d592 atapi!IdePortDispatchDeviceControl [0f] IRP_MJ_INTERNAL_DEVICE_CONTROL bae697b4 atapi!IdePortDispatch [10] IRP_MJ_SHUTDOWN 804f5282 nt!IopInvalidDeviceRequest [11] IRP_MJ_LOCK_CONTROL 804f5282 nt!IopInvalidDeviceRequest [12] IRP_MJ_CLEANUP 804f5282 nt!IopInvalidDeviceRequest [13] IRP_MJ_CREATE_MAILSLOT 804f5282 nt!IopInvalidDeviceRequest [14] IRP_MJ_QUERY_SECURITY 804f5282 nt!IopInvalidDeviceRequest [15] IRP_MJ_SET_SECURITY 804f5282 nt!IopInvalidDeviceRequest [16] IRP_MJ_POWER bae6d5bc atapi!IdePortDispatchPower [17] IRP_MJ_SYSTEM_CONTROL bae74164 atapi!IdePortDispatchSystemControl [18] IRP_MJ_DEVICE_CHANGE 804f5282 nt!IopInvalidDeviceRequest [19] IRP_MJ_QUERY_QUOTA 804f5282 nt!IopInvalidDeviceRequest [1a] IRP_MJ_SET_QUOTA 804f5282 nt!IopInvalidDeviceRequest [1b] IRP_MJ_PNP bae74130 atapi!IdePortDispatchPnp kd> ln atapi!IdePortDispatch (f97d87b4) atapi!IdePortDispatch | (f97d8ccc) atapi!IdePortTickHandler Exact matches: atapi!IdePortDispatch = <no type information> kd> ed 81b87b30+0x38+0x3c f97d87b4 kd> !drvobj /driver/atapi 3 Driver object (81b87b30) is for: /Driver/atapi Driver Extension List: (id , addr) (f97e68d8 81bef140) Device Object list: 81b7e030 81b872f8 81b85030 81b86030 DriverEntry: f97e75f7 atapi!GsDriverEntry DriverStartIo: f97d97c6 atapi!IdePortStartIo DriverUnload: f97e3204 atapi!IdePortUnload AddDevice: f97e1300 atapi!ChannelAddDevice Dispatch routines: [00] IRP_MJ_CREATE f97dc572 atapi!IdePortAlwaysStatusSuccessIrp [01] IRP_MJ_CREATE_NAMED_PIPE f9ea0c14 Shdbus+0xc14 [02] IRP_MJ_CLOSE f9ea0c14 Shdbus+0xc14 [03] IRP_MJ_READ f9ea0c14 Shdbus+0xc14 [04] IRP_MJ_WRITE f9ea0c14 Shdbus+0xc14 [05] IRP_MJ_QUERY_INFORMATION f9ea0c14 Shdbus+0xc14 [06] IRP_MJ_SET_INFORMATION f9ea0c14 Shdbus+0xc14 [07] IRP_MJ_QUERY_EA f9ea0c14 Shdbus+0xc14 [08] IRP_MJ_SET_EA f9ea0c14 Shdbus+0xc14 [09] IRP_MJ_FLUSH_BUFFERS f9ea0c14 Shdbus+0xc14 [0a] IRP_MJ_QUERY_VOLUME_INFORMATION f9ea0c14 Shdbus+0xc14 [0b] IRP_MJ_SET_VOLUME_INFORMATION f9ea0c14 Shdbus+0xc14 [0c] IRP_MJ_DIRECTORY_CONTROL f9ea0c14 Shdbus+0xc14 [0d] IRP_MJ_FILE_SYSTEM_CONTROL f9ea0c14 Shdbus+0xc14 [0e] IRP_MJ_DEVICE_CONTROL f9ea0c14 Shdbus+0xc14[0f] IRP_MJ_INTERNAL_DEVICE_CONTROL f97d87b4 atapi!IdePortDispatch [10] IRP_MJ_SHUTDOWN f9ea0c14 Shdbus+0xc14 [11] IRP_MJ_LOCK_CONTROL f9ea0c14 Shdbus+0xc14 [12] IRP_MJ_CLEANUP f9ea0c14 Shdbus+0xc14 [13] IRP_MJ_CREATE_MAILSLOT f9ea0c14 Shdbus+0xc14 [14] IRP_MJ_QUERY_SECURITY f9ea0c14 Shdbus+0xc14 [15] IRP_MJ_SET_SECURITY f9ea0c14 Shdbus+0xc14 [16] IRP_MJ_POWER f9ea0c14 Shdbus+0xc14 [17] IRP_MJ_SYSTEM_CONTROL f9ea0c14 Shdbus+0xc14 [18] IRP_MJ_DEVICE_CHANGE f9ea0c14 Shdbus+0xc14 [19] IRP_MJ_QUERY_QUOTA f9ea0c14 Shdbus+0xc14 [1a] IRP_MJ_SET_QUOTA f9ea0c14 Shdbus+0xc14 [1b] IRP_MJ_PNP f9ea0c14 Shdbus+0xc14 (3) 经过以下 3步终于成功 .步骤一 : 废掉 ygtq 对 disk & atapi 分发例程的循环保护 步骤二 : 恢复 disk.sys 和 atapi.sys 的 0xf 号分发例程 步骤三 : 自己构建 IRP, 发送到 DR0 设备对象上 , 获取 MBR kd> !devstack 0x81b874e0 !DevObj !DrvObj !DevExt ObjectName 81bc4918 /Driver/PartMgr 81bc49d0 81b7d878 /Driver/Shield 81b7d930 // ß 注意这里 , 雨过天晴在 Shildf.sys 中循环恢复这个 Attach 在 DR0 上的过滤设备 , // 用 Winhex 读 MBR 时 , 到这里就被重定向了 . 81bc4030 /Driver/Disk 81bc40e8 DR0 // ß 我的 IRP发到此处 ,终于可以读到原始的 MBR了 // 若不恢复 Disk.sys的 0xf号分发例程 ,就会被 ygtq拒绝掉 ,使得我构建的 IRP完全失效 , // 读到的 MBR内容为空 .见下图 81b7d9b0 /Driver/Shdbus 81b7da68 > 81b874e0 /Driver/atapi 81b87598 IdeDeviceP0T0L0-3 !DevNode 81b85ee8 : DeviceInst is "IDE/DiskVMware_Virtual_IDE_Hard_Drive___________00000001/3030303030303030303030303030303030303130" ServiceName is "disk" 但是 ,这仅仅是开始 ,因为我们的目的是用 Winhex 克隆安装有 ” 雨过天晴 ”(非过期 ; 因为过期后系统不走 ygtq的 MBR了 ) 的整个系统 ,以便用 Bochs 动态调试 含有雨过天晴系统的 MBR .但 Winhex用标准的 ReadFile & WriteFile 函数来读写扇区 ,被 ygtq在文件系统层面拦截了 .我用XueTr.exe摘掉雨过天晴的文件过滤设备(ygtq没有对其进行循环恢复),但是其附着在DR0上的过滤设备无法摘除(ygtq开了线程循环恢复), 所以当我用Winhex读取MBR时,到 /Driver/Shield 这层 就被重定向了. 现在要做的工作是 找到并废除ygtq的那个循环恢复的线程,删除DR0上的Shield设备 ,然后就可以用Winhex克隆磁盘了. kd> !object /driver/disk Object: 81b7e360 Type: (81ba9900) Driver ObjectHeader: 81b7e348 (old version) HandleCount: 0 PointerCount: 5 Directory Object: e12bbd10 Name: Disk kd> dt nt!_device_object 81bc4030 nt!_DEVICE_OBJECT +0x000 Type : 3 +0x002 Size : 0x518 +0x004 ReferenceCount : 0 +0x008 DriverObject : 0x81b7e360 _DRIVER_OBJECT +0x00c NextDevice : (null) +0x010 AttachedDevice : 0x81b7d878 _DEVICE_OBJECT kd> !devstack 0x81b7d878 !DevObj !DrvObj !DevExt ObjectName 81bc4918 /Driver/PartMgr 81bc49d0 > 81b7d878 /Driver/Shield 81b7d930 81bc4030 /Driver/Disk 81bc40e8 DR0 81b7d9b0 /Driver/Shdbus 81b7da68 81b874e0 /Driver/atapi 81b87598 IdeDeviceP0T0L0-3 !DevNode 81b85ee8 : DeviceInst is "IDE/DiskVMware_Virtual_IDE_Hard_Drive___________00000001/3030303030303030303030303030303030303130" ServiceName is "disk" kd> ba w 4 81bc4030+0x010 // 下硬件断点 , 然后用 XueTr.exe 删除这个设备 , 观察雨过天晴的线程是如何循环恢复的 . kd> bl 0 e f93f1660 0001 (0001) srb!Scsi_read_file_by_sector 1 e f93f14de 0001 (0001) srb!AtapiReadWriteDisk+0x2fe 2 e 81bc4040 w 4 0001 (0001) kd> g Breakpoint 2 hit // 第一次断住 , 是因为我用 XueTr.exe 删除了这个设备 , 属于写操作 *** ERROR: Module load completed but symbols could not be loaded for XueTr.sys XueTr+0x2b21: f72c9b21 b301 mov bl,1 kd> !thread THREAD 81402020 Cid 034c.04a4 Teb: 7ffdd000 Win32Thread: e129ed00 RUNNING on processor 0 IRP List: 814032a8: (0006,0094) Flags: 00000070 Mdl: 00000000 Not impersonating DeviceMap e1859328 Owning Process 813f1020 Image: XueTr.exe Wait Start TickCount 106353 Ticks: 0 Context Switch Count 3482 LargeStack UserTime 00:00:00.875 KernelTime 00:00:01.921 Win32 Start Address 0x00446e16 Start Address 0x7c810867 Stack Init f9460000 Current f945fcb8 Base f9460000 Limit f945a000 Call 0 Priority 10 BasePriority 8 PriorityDecrement 0 DecrementCount 16 ChildEBP RetAddr Args to Child WARNING: Stack unwind information not available. Following frames may be wrong. f945fbac f72ca325 81b7d878 0012da20 81725828 XueTr+0x2b21 f945fbec f72fe0c0 0012da20 00000008 00000000 XueTr+0x3325 f945fc34 804eedf9 81475978 814032a8 806d12d0 XueTr+0x370c0 f945fc44 80574b42 81403318 8166b660 814032a8 nt!IopfCallDriver+0x31 (FPO: [0,0,0]) f945fc58 805759d1 81475978 814032a8 8166b660 nt!IopSynchronousServiceTail+0x60 (FPO: [Non-Fpo]) f945fd00 8056e33c 00000138 00000000 00000000 nt!IopXxxControlFile+0x5e7 (FPO: [Non-Fpo]) f945fd34 8053d808 00000138 00000000 00000000 nt!NtDeviceIoControlFile+0x2a (FPO: [Non-Fpo]) f945fd34 7c92eb94 00000138 00000000 00000000 nt!KiFastCallEntry+0xf8 (FPO: [0,0] TrapFrame @ f945fd64) 0012d96c 7c92d8ef 7c801671 00000138 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0]) 0012d970 7c801671 00000138 00000000 00000000 ntdll!ZwDeviceIoControlFile+0xc (FPO: [10,0,0]) 0012d9d0 00414d7f 00000138 006e0160 0012da28 0x7c801671 0012d9d4 00000000 006e0160 0012da28 00000018 0x414d7f kd> g Breakpoint 2 hit // 过了大概半秒钟 , 系统被 Windbg 第二次断住 , 为雨过天晴的行为 . 观察之 . *** ERROR: Module load completed but symbols could not be loaded for Shieldf.sys Shieldf+0x3b4: f9c2c3b4 c9 leave kd> !thread THREAD 8143b520 Cid 06ec.06f0 Teb: 7ffdf000 Win32Thread: e1abc730 RUNNING on processor 0 IRP List: 814da538: (0006,01d8) Flags: 00000884 Mdl: 00000000 Not impersonating DeviceMap e1859328 Owning Process 8143b798 Image: shieldtray.exe Wait Start TickCount 107179 Ticks: 0 Context Switch Count 352 LargeStack UserTime 00:00:00.015 KernelTime 00:00:00.140 Win32 Start Address shieldtray (0x0044a981) Start Address kernel32!BaseProcessStartThunk (0x7c810867) Stack Init f7ada000 Current f7ad9968 Base f7ada000 Limit f7ad7000 Call 0 Priority 8 BasePriority 8 PriorityDecrement 0 DecrementCount 0 ChildEBP RetAddr Args to Child WARNING: Stack unwind information not available. Following frames may be wrong. f7ad99fc f9c2da17 814da548 814da538 805452fe Shieldf+0x3b4 f7ad9a4c f9c2de7b 814cf368 814da548 81bd3030 Shieldf+0x1a17 f7ad9b50 805b465e 81b79a20 00000000 816f4228 Shieldf+0x1e7b // 雨过天晴的文件过滤驱动 f7ad9bd8 805b0b3f 00000000 f7ad9c18 00000040 nt!ObpLookupObjectName+0x56a (FPO: [Non-Fpo]) f7ad9c2c 8056b133 00000000 00000000 4b31f001 nt!ObOpenObjectByName+0xeb (FPO: [Non-Fpo]) f7ad9ca8 8056baaa 0012fc04 00100001 0012fbd0 nt!IopCreateFile+0x407 (FPO: [Non-Fpo]) f7ad9d04 8056f291 0012fc04 00100001 0012fbd0 nt!IoCreateFile+0x8e (FPO: [Non-Fpo]) f7ad9d44 8053d808 0012fc04 00100001 0012fbd0 nt!NtOpenFile+0x27 (FPO: [Non-Fpo]) f7ad9d44 7c92eb94 0012fc04 00100001 0012fbd0 nt!KiFastCallEntry+0xf8 (FPO: [0,0] TrapFrame @ f7ad9d64) 0012fb80 7c92dd09 7c81e74a 0012fc04 00100001 ntdll!KiFastSystemCallRet (FPO: [0,0,0]) 0012fb84 7c81e74a 0012fc04 00100001 0012fbd0 ntdll!NtOpenFile+0xc (FPO: [6,0,0]) 0012fbfc 7c82744d 00000000 0012fc34 0012fc3c kernel32!GetDiskFreeSpaceExW+0x7d (FPO: [Non-Fpo]) 0012fc14 0042cbe8 0012fc74 0012fc34 0012fc3c kernel32!GetDiskFreeSpaceExA+0x2f (FPO: [Non-Fpo]) 0012fc40 0041180e 0012fc74 0012fc80 0012fc84 shieldtray+0x2cbe8 00000000 00000000 00000000 00000000 00000000 shieldtray+0x1180e 打开 IDA,载入 Shiedlf.sys ,定位到 0x103b4 处 ,即可看出其具体的流程 :于是在 Windbg中 ,强行将其改成如下图所示的代码 :此时再用 XueTr.exe删除雨过天晴的设备 ,调用 Winhex成功读取到更改后的 MBR. 若我们不做这些更改 ,用 Winhex得到的内容如下 :现在开启 Bochs,即可调试雨过天晴的启动代码了 .结合 IDA静态看 ,很容易了解它的 MBR所做的工作 .通过这次调试跟踪 ,对自己是个小小的锻炼 .其实用调试器改还不如写个驱动来的容易 ,不过最终目的达到了 , 嘿嘿 . 接下来我准备写个驱动 ,一劳永逸 …. 此实例旨在告诉大家遇到问题如何一步一步跟踪解决 ,灵活变通 ,重在积累调试经验 !