#pragma once
#include <ntddk.h>
#include <windef.h>
VOID Unload(__in struct _DRIVER_OBJECT *DriverObject);
NTSTATUS Dispatch_func(__in PDEVICE_OBJECT pDevObj, __in PIRP pIrp);
//定义ssdt表结构体
typedef struct _ServiceDescriptorTable {
PVOID ServiceTableBase;
PVOID ServiceCounterTable;
unsigned int NumberOfServices;
PVOID ParamTableBase;
}*PServiceDescriptorTable;
extern PServiceDescriptorTable KeServiceDescriptorTable;
//extern LONG KeServiceDescriptorTable;
#pragma pack(1)
typedef struct _JmpCode{
BYTE E9;
DWORD JmpAddr;
}JCode, *pJCode;
#pragma pack()
ULONG cur, old;
JCode HookJC;
//获取NtClose当前在ssdt中的地址
ULONG GetCurrentAddr() {
LONG t_addr, SSDT_Adr;
t_addr = KeServiceDescriptorTable->ServiceTableBase;
SSDT_Adr = t_addr + 0x19 * 4;
KdPrint(("NtClose在0环中当前的地址是%x \n", *(PLONG)SSDT_Adr));
return (ULONG)(*(PLONG)SSDT_Adr);
}
//获取NtClose当前在ssdt中的地址(汇编)
ULONG GetCurrentAddr_asm() {
ULONG Addr;
KdPrint(("PServiceDescriptorTable = %x", KeServiceDescriptorTable));
__asm
{
push ebx
push eax
int 3
mov ebx, KeServiceDescriptorTable //ssdt的位置
mov ebx, [ebx]
mov eax, 19h
shl eax, 2
mov ebx, [ebx+eax]
mov Addr, ebx
pop eax
pop ebx
}
KdPrint(("(汇编)NtClose在0环中当前的地址是%x \n", Addr));
return Addr;
}
//获取NtClose在ssdt中的原始地址
ULONG GetOldAddr()
{
UNICODE_STRING Old_NtClose;
ULONG Old_addr;
RtlInitUnicodeString(&Old_NtClose, L"NtClose");
//MmGetSystemRoutineAddress只能查被导出了的函数,未被导出的函数查不到。
Old_addr = MmGetSystemRoutineAddress(&Old_NtClose);
KdPrint(("NtClosede在0环中原始的地址是%x \n", Old_addr));
return Old_addr;
}
//脱钩
VOID UnHook()
{
pJCode pJC_cur, pJC_old;
pJC_cur = (pJCode)cur;
pJC_old = (pJCode)old;
//修改cr0寄存器,关闭页写保护;CR0的第17位,1表示保护,0表示为保护。
/*这段代码加了之后运行会蓝屏。去掉就好了。
__asm
{
cli
push eax
mov eax, cr0
and eax, not 10000h
mov cr0, eax
pop eax
}*/
HookJC.E9 = pJC_cur->E9;
HookJC.JmpAddr = pJC_cur->JmpAddr;
pJC_cur->E9 = 0xE9;
pJC_cur->JmpAddr = (DWORD)pJC_old - (DWORD)pJC_cur - 5;
//恢复cr0寄存器,开启页写保护。
__asm
{
push eax
mov eax, cr0
or eax, 10000h
mov cr0, eax
pop eax
}
}
//恢复脱钩
VOID ReHook()
{
pJCode pJC_cur;
pJC_cur = (pJCode)cur;
//修改cr0寄存器,关闭页写保护;CR0的第17位,1表示保护,0表示为保护。
__asm
{
cli
push eax
mov eax, cr0
and eax, not 10000h
mov cr0, eax
pop eax
}
pJC_cur->E9 = HookJC.E9;
pJC_cur->JmpAddr = HookJC.JmpAddr;
//恢复cr0寄存器,开启页写保护。
__asm
{
push eax
mov eax, cr0
or eax, 10000h
mov cr0, eax
pop eax
}
}
//修改指定内存的数据
VOID ModifyMem()
{
}
#include "my_ssdt.h"
NTSTATUS DriverEntry(
__in PDRIVER_OBJECT DriverObject,
__in PUNICODE_STRING RegistryPathName
)
{
KdBreakPoint();
KdPrint(("DriverEntry"));
//DbgPrint(("DriverEntry")); KdPrint和DbgPrint的区别是,KdPrint在Release版本中会被忽略。
old = GetOldAddr();
cur = GetCurrentAddr();
//GetCurrentAddr_asm();
if (old != cur)
{
KdPrint(("NtClose已经被Hook了 \n"));
KdPrint(("现在来将这个函数脱钩 \n"));
UnHook();
KdPrint(("改完了,看一下 \n"));
}
DriverObject->DriverUnload = Unload;
DriverObject->MajorFunction[IRP_MJ_CREATE] = Dispatch_func;
DriverObject->MajorFunction[IRP_MJ_READ] = Dispatch_func;
DriverObject->MajorFunction[IRP_MJ_WRITE] = Dispatch_func;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Dispatch_func;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = Dispatch_func;
return STATUS_SUCCESS;
}
VOID Unload(
__in struct _DRIVER_OBJECT *DriverObject
)
{
KdBreakPoint();
KdPrint(("Unload"));
//GetCurrentAddr_asm();
ReHook();
}
NTSTATUS Dispatch_func(__in PDEVICE_OBJECT pDevObj, __in PIRP pIrp)
{
//对响应的IRP进行处理
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
KdPrint(("完成派遣函数"));
return STATUS_SUCCESS;
}
帮忙看下UnHook函数,这段代码把cr0的第17位改成0,然后修改了被hook的函数让它跳到正常的位置。功能是把被procmon24.sys钩住的ntclose函数还原。
但是加上第88到第100行这段代码后运行会蓝屏,去掉就好了。
这是为啥?
我查过了pde和pte,要修改的地址的物理页是可以写的,理论上不需要改cr0页可以写。但是为什么我加了这段代码会蓝屏呢?
这是!analyze -v现实的信息
1: kd> !analyze -v
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
PAGE_FAULT_IN_NONPAGED_AREA (50)
Invalid system memory was referenced. This cannot be protected by try-except,
it must be protected by a Probe. Typically the address is just plain bad or it
is pointing at freed memory.
Arguments:
Arg1: d9234d57, memory referenced.
Arg2: 00000001, value 0 = read operation, 1 = write operation.
Arg3: ee133f61, If non-zero, the instruction address which referenced the bad memory
address.
Arg4: 00000000, (reserved)
Debugging Details:
------------------
*************************************************************************
*** ***
*** ***
*** Your debugger is not using the correct symbols ***
*** ***
*** In order for this command to work properly, your symbol path ***
*** must point to .pdb files that have full type information. ***
*** ***
*** Certain .pdb files (such as the public OS symbols) do not ***
*** contain the required information. Contact the group that ***
*** provided you with these symbols if you need this command to ***
*** work. ***
*** ***
*** Type referenced: kernel32!pNlsUserInfo ***
*** ***
*************************************************************************
*************************************************************************
*** ***
*** ***
*** Your debugger is not using the correct symbols ***
*** ***
*** In order for this command to work properly, your symbol path ***
*** must point to .pdb files that have full type information. ***
*** ***
*** Certain .pdb files (such as the public OS symbols) do not ***
*** contain the required information. Contact the group that ***
*** provided you with these symbols if you need this command to ***
*** work. ***
*** ***
*** Type referenced: kernel32!pNlsUserInfo ***
*** ***
*************************************************************************
WRITE_ADDRESS: d9234d57
FAULTING_IP:
PROCMON24+8f61
ee133f61 ff85ff0f84ea inc dword ptr [ebp-157BF001h]
MM_INTERNAL_CODE: 0
IMAGE_NAME: PROCMON24.SYS
DEBUG_FLR_IMAGE_TIMESTAMP: 5a8222fc
MODULE_NAME: PROCMON24
FAULTING_MODULE: ee12b000 PROCMON24
DEFAULT_BUCKET_ID: DRIVER_FAULT
BUGCHECK_STR: 0x50
PROCESS_NAME: services.exe
TRAP_FRAME: ee9f3cd0 -- (.trap 0xffffffffee9f3cd0)
ErrCode = 00000002
eax=00000019 ebx=ee133f50 ecx=00000000 edx=ee9ecfa0 esi=00ccf7c8 edi=64804dd2
eip=ee133f61 esp=ee9f3d44 ebp=ee9f3d58 iopl=0 nv up ei ng nz ac po nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010292
PROCMON24+0x8f61:
ee133f61 ff85ff0f84ea inc dword ptr [ebp-157BF001h] ss:0010:d9234d57=????????
Resetting default scope
LAST_CONTROL_TRANSFER: from 804f9df9 to 8052c5dc
STACK_TEXT:
ee9f3804 804f9df9 00000003 d9234d57 00000000 nt!RtlpBreakWithStatusInstruction
ee9f3850 804fa9e4 00000003 00000000 c06c91a0 nt!KiBugCheckDebugBreak+0x19
ee9f3c30 804faf33 00000050 d9234d57 00000001 nt!KeBugCheck2+0x574
ee9f3c50 8052136a 00000050 d9234d57 00000001 nt!KeBugCheckEx+0x1b
ee9f3cb8 80545578 00000001 d9234d57 00000000 nt!MmAccessFault+0x9a8
ee9f3cb8 ee133f61 00000001 d9234d57 00000000 nt!KiTrap0E+0xd0
WARNING: Stack unwind information not available. Following frames may be wrong.
ee9f3d58 8054261c 000003c8 00ccf7dc 7c92e4f4 PROCMON24+0x8f61
ee9f3d58 7c92e4f4 000003c8 00ccf7dc 7c92e4f4 nt!KiFastCallEntry+0xfc
00ccf7b8 7c92cfdc 010075da 000003c8 00000000 ntdll!KiFastSystemCallRet
00ccf7bc 010075da 000003c8 00000000 006c60dc ntdll!ZwClose+0xc
00ccf7dc 010074e9 00000000 00000000 006c6068 services!ScGetClientSid+0xc3
00ccf860 01006991 0000001d 006c60dc 00000000 services!ScLogControlEvent+0x68
00ccf880 01005e0d 000cd260 00000000 00000000 services!RStartServiceW+0xa0
00ccf8cc 77e599f4 000cd260 00000000 00000000 services!RStartServiceA+0xbd
00ccf8ec 77ed421a 01005de7 00ccf900 00000003 RPCRT4!Invoke+0x30
00ccfcf4 77ed46ee 00000000 00000000 000c89cc RPCRT4!NdrStubCall2+0x297
00ccfd10 77e594bd 000c89cc 000af078 000c89cc RPCRT4!NdrServerCall2+0x19
00ccfd44 77e59422 01002579 000c89cc 00ccfdec RPCRT4!DispatchToStubInC+0x38
00ccfd98 77e5934e 0000001f 00000000 0101a150 RPCRT4!RPC_INTERFACE::DispatchToStubWorker+0x113
00ccfdbc 77e5be64 000c89cc 00000000 0101a150 RPCRT4!RPC_INTERFACE::DispatchToStub+0x84
00ccfdf8 77e5bcc1 000ceed0 000a5940 000cc160 RPCRT4!LRPC_SCALL::DealWithRequestMessage+0x2db
00ccfe1c 77e5bc05 000a597c 00ccfe38 000cc160 RPCRT4!LRPC_ADDRESS::DealWithLRPCRequest+0x16d
00ccff80 77e56caf 00ccffa8 77e56ad1 000a5940 RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls+0x310
00ccff88 77e56ad1 000a5940 00000000 01001906 RPCRT4!RecvLotsaCallsWrapper+0xd
00ccffa8 77e56c97 000ab378 00ccffec 7c80b713 RPCRT4!BaseCachedThreadRoutine+0x79
00ccffb4 7c80b713 000cdf18 00000000 01001906 RPCRT4!ThreadStartRoutine+0x1a
00ccffec 00000000 77e56c7d 000cdf18 00000000 kernel32!BaseThreadStart+0x37
STACK_COMMAND: kb
FOLLOWUP_IP:
PROCMON24+8f61
ee133f61 ff85ff0f84ea inc dword ptr [ebp-157BF001h]
SYMBOL_STACK_INDEX: 6
SYMBOL_NAME: PROCMON24+8f61
FOLLOWUP_NAME: MachineOwner
FAILURE_BUCKET_ID: 0x50_PROCMON24+8f61
BUCKET_ID: 0x50_PROCMON24+8f61
Followup: MachineOwner
---------
看样子是procmon24.sys这个驱动程序导致的蓝屏,但是我不知道为什么。