在 ring3 调用的那些 WSASend 、WSARecv 等 socket 的函数,他们最终都是调用 ZwDeviceIoControlFile 来和驱动程序通讯的,所以只要 hook 了这个函数,判断一下句柄的类型,如果和网络有关的就直接返回,这样 ring3 的程序就不能访问网络了,本例子中还 hook 了 ZwCreateFile ZwOpenFile 等函数,因为之前只是想禁止打开这些对象,但比如 qq 等程序会一直打开着 socket ,这样只 hook ZwCreateFile ,ZwOpenFile 就不能完全的禁止 qq 这类程序访问网络了,所以把 ZwDeviceIoControlFile 都 hook 了`
代码写的很烂,可以在 windows 7 运行
///////////////////////////////////////////////////////////////////////////////
///
/// Copyright (c) 2012 - <company name here>
///
/// Original filename: hookZwCreateFilefilter.cpp
/// Project : hookZwCreateFilefilter
/// Date of creation : 2012-02-07
/// Author(s) :
///
/// Purpose : <description>
///
/// Revisions:
/// 0000 [2012-02-07] Initial revision.
///
///////////////////////////////////////////////////////////////////////////////
// $Id$
#ifdef __cplusplus
extern "C" {
#endif
#include <ntddk.h>
#include <string.h>
#include <ntifs.h>
#ifdef __cplusplus
}; // extern "C"
#endif
#include "hookZwCreateFilefilter.h"
#ifdef __cplusplus
namespace { // anonymous namespace to limit the scope of this global variable!
#endif
PDRIVER_OBJECT pdoGlobalDrvObj = 0;
#ifdef __cplusplus
}; // anonymous namespace
#endif
unsigned long old_ZwCreateFile = 0;
unsigned long old_ZwOpenFile = 0;
unsigned long old_ZwDeleteFile = 0;
unsigned long old_ZwDeviceIoControlFile = 0;
unsigned char *copyknbase = 0;
unsigned char *sysknbase = 0;
void *hookfun_ld = 0;
void *hookssdt(unsigned char callid, void *afun);
void * __stdcall my_filter_ObjectName(unsigned long unicode_string);
void * __stdcall my_query_Object_string(void *handle);
void close_cr0_wp();
void open_cr0_wp();
////switch function
void __declspec(naked) switch_my_hook_ZwCreateFile()
{
__asm
{
push eax;
mov eax, [esp+12+4]; //eax 指向 ObjectAttributes
pushad;
pushfd;
mov eax, [eax+8];//eax 指向 ObjectAttributes->ObjectName 类型是 UNICODE_STRING
push eax;
call my_filter_ObjectName;
cmp eax, 0;
jne nocallold;
popfd;
popad;
pop eax;
jmp old_ZwCreateFile;
nocallold:
popfd;
popad;
pop eax;
ret 11*4;
}
}
void __declspec(naked) switch_my_hook_ZwOpenFile()
{
__asm
{
push eax;
mov eax, [esp+12+4]; //eax 指向 ObjectAttributes
pushad;
pushfd;
mov eax, [eax+8];//eax 指向 ObjectAttributes->ObjectName 类型是 UNICODE_STRING
push eax;
call my_filter_ObjectName;
cmp eax, 0;
jne nocallold;
popfd;
popad;
pop eax;
jmp old_ZwOpenFile;
nocallold:
popfd;
popad;
pop eax;
ret 6*4;
}
}
void __declspec(naked) switch_my_hook_ZwDeleteFile()
{
__asm
{
push eax;
mov eax, [esp+4+4]; //eax 指向 UNICODE_STRING
pushad;
pushfd;
push eax;
call my_filter_ObjectName;
cmp eax, 0;
jne nocallold;
popfd;
popad;
pop eax;
jmp old_ZwDeleteFile;
nocallold:
popfd;
popad;
pop eax;
ret 4;
}
}
void __declspec(naked) switch_my_hook_ZwDeviceIoControlFile()
{
__asm
{
push eax;
mov eax, [esp+8];
pushad;
pushfd;
push eax;
call my_query_Object_string;
cmp eax, 0;
jne nocallold;
popfd;
popad;
pop eax;
jmp old_ZwDeviceIoControlFile;
nocallold:
popfd;
popad;
pop eax;
ret 10*4;
}
}
void __declspec(naked) switch_my_hook_ZwLoadDriver()
{
__asm
{
//ret 4;
mov eax, hookfun_ld;
sub eax, sysknbase;
add eax, copyknbase;
jmp eax;
}
}
NTSTATUS HOOKZWCREATEFILEFILTER_DispatchCreateClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
NTSTATUS status = STATUS_SUCCESS;
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS HOOKZWCREATEFILEFILTER_DispatchDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
switch(irpSp->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_HOOKZWCREATEFILEFILTER_OPERATION:
// status = SomeHandlerFunction(irpSp);
break;
default:
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Information = 0;
break;
}
status = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
VOID HOOKZWCREATEFILEFILTER_DriverUnload(
IN PDRIVER_OBJECT DriverObject
)
{
PDEVICE_OBJECT pdoNextDeviceObj = pdoGlobalDrvObj->DeviceObject;
IoDeleteSymbolicLink(&usSymlinkName);
// Delete all the device objects
while(pdoNextDeviceObj)
{
PDEVICE_OBJECT pdoThisDeviceObj = pdoNextDeviceObj;
pdoNextDeviceObj = pdoThisDeviceObj->NextDevice;
IoDeleteDevice(pdoThisDeviceObj);
}
}
#ifdef __cplusplus
extern "C" {
#endif
NTSTATUS DriverEntry(
IN OUT PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
PDEVICE_OBJECT pdoDeviceObj = 0;
NTSTATUS status = STATUS_UNSUCCESSFUL;
pdoGlobalDrvObj = DriverObject;
// Create the device object.
if(!NT_SUCCESS(status = IoCreateDevice(
DriverObject,
0,
&usDeviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&pdoDeviceObj
)))
{
// Bail out (implicitly forces the driver to unload).
return status;
};
// Now create the respective symbolic link object
if(!NT_SUCCESS(status = IoCreateSymbolicLink(
&usSymlinkName,
&usDeviceName
)))
{
IoDeleteDevice(pdoDeviceObj);
return status;
}
// NOTE: You need not provide your own implementation for any major function that
// you do not want to handle. I have seen code using DDKWizard that left the
// *empty* dispatch routines intact. This is not necessary at all!
DriverObject->MajorFunction[IRP_MJ_CREATE] =
DriverObject->MajorFunction[IRP_MJ_CLOSE] = HOOKZWCREATEFILEFILTER_DispatchCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HOOKZWCREATEFILEFILTER_DispatchDeviceControl;
DriverObject->DriverUnload = HOOKZWCREATEFILEFILTER_DriverUnload;
UNICODE_STRING ZwCreateFile_string_name = {0};
UNICODE_STRING ZwOpenFile_string_name = {0};
UNICODE_STRING ZwDeleteFile_string_name = {0};
UNICODE_STRING ZwDeviceIoControlFile_string_name = {0};
UNICODE_STRING NtLoadDriver_string_name = {0};
::RtlInitUnicodeString(&ZwCreateFile_string_name, L"ZwCreateFile");
::RtlInitUnicodeString(&ZwOpenFile_string_name, L"ZwOpenFile");
::RtlInitUnicodeString(&ZwDeleteFile_string_name, L"ZwDeleteFile");
::RtlInitUnicodeString(&ZwDeviceIoControlFile_string_name, L"ZwDeviceIoControlFile");
::RtlInitUnicodeString(&NtLoadDriver_string_name, L"ZwLoadDriver");
void *paddr_1 = ::MmGetSystemRoutineAddress(&ZwCreateFile_string_name);
void *paddr_2 = ::MmGetSystemRoutineAddress(&ZwOpenFile_string_name);
void *paddr_3 = ::MmGetSystemRoutineAddress(&ZwDeleteFile_string_name);
void *paddr_4 = ::MmGetSystemRoutineAddress(&ZwDeviceIoControlFile_string_name);
void *paddr_5 = ::MmGetSystemRoutineAddress(&NtLoadDriver_string_name);
//__asm int 3;
old_ZwCreateFile = (unsigned long)::hookssdt(*(char*)((unsigned long)(paddr_1)+1), switch_my_hook_ZwCreateFile);
old_ZwOpenFile = (unsigned long)::hookssdt(*(char*)((unsigned long)(paddr_2)+1), switch_my_hook_ZwOpenFile);
old_ZwDeleteFile = (unsigned long)::hookssdt(*(char*)((unsigned long)(paddr_3)+1), switch_my_hook_ZwDeleteFile);
old_ZwDeviceIoControlFile = (unsigned long)::hookssdt(*(char*)((unsigned long)(paddr_4)+1), switch_my_hook_ZwDeviceIoControlFile);
unsigned long sysfunadr = 0;
void *ke_ssdt_ = ::KeServiceDescriptorTable;
ke_ssdt_ = (void*)*(unsigned long*)ke_ssdt_;
unsigned char callid = 0;
callid = (*(unsigned char*)((unsigned long)(paddr_5)+1));
sysfunadr = (unsigned long)ke_ssdt_+callid*(unsigned char)4;
//不会有羡慕、不会有嫉妒、只会有那种最真至的关心
hookfun_ld = (void*)*(ULONG*)sysfunadr;
//::DbgPrint("%x callid=%x\r\n", hookfun_ld, *(char*)((unsigned long)(paddr_5)+1));
ULONG retsize = 0;
SYSTEM_MODULE_INFORMATION *sys_mod = 0;
char *buf = 0;
::ZwQuerySystemInformation((SYSTEM_INFORMATION_CLASS)11, 0, 0, &retsize);
buf = (char*)ExAllocatePool(NonPagedPool, retsize);
::ZwQuerySystemInformation((SYSTEM_INFORMATION_CLASS)11, (void*)buf, retsize, &retsize);
sys_mod = (SYSTEM_MODULE_INFORMATION*)(buf+sizeof(ULONG));
sysknbase = (unsigned char*)sys_mod[0].Base;
copyknbase = (unsigned char*)ExAllocatePool(NonPagedPool, sys_mod[0].Size);
unsigned char rtmp = *(unsigned char*)sys_mod[0].Base;
//__asm int 3;
//::close_cr0_wp();
//::RtlCopyMemory(copyknbase, sys_mod[0].Base, sys_mod[0].Size);
MDL *kmdl = MmCreateMdl(0, sys_mod[0].Base, sys_mod[0].Size);
MmBuildMdlForNonPagedPool(kmdl);
kmdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA;
unsigned char *sysknbase_mdl = (unsigned char*)::MmMapLockedPages(kmdl, KernelMode);
for(unsigned long i = 0; i < sys_mod[0].Size; i++)
*(unsigned char*)(copyknbase+i) = *(unsigned char*)(((unsigned long)(sysknbase_mdl))+i);
//rtmp = *(unsigned char*)(((unsigned long)(sys_mod[i].Base))+i);
//::open_cr0_wp();
/////::RtlCopyMemory((void*)copyknbase, (void*)copyknbase, sys_mod[0].Size);
//::MmUnmapLockedPages((unsigned char*)sysknbase_mdl, kmdl);
//::MmUnlockPages(kmdl);
//*(int*)sys_mod[0].Base = 0;
::DbgPrint("new kernel address = %x\r\n", copyknbase);
::close_cr0_wp();
*(char*)hookfun_ld = (char)0x68;
*(ULONG*)((ULONG)(hookfun_ld)+1) = (ULONG)switch_my_hook_ZwLoadDriver;
*(char*)((ULONG)(hookfun_ld)+1+4) = (char)0xc3;
::open_cr0_wp();
::ExFreePool(buf);
return STATUS_SUCCESS;
}
#ifdef __cplusplus
}; // extern "C"
#endif
void *hookssdt(unsigned char callid, void *afun)
{
///__asm int 3;
///::DbgPrint("hook ssdt callid:%d\r\n", callid);
unsigned long sysfunadr = 0;
unsigned long oldsysfunadr = 0;
void *ke_ssdt_ = ::KeServiceDescriptorTable;
ke_ssdt_ = (void*)*(unsigned long*)ke_ssdt_;
sysfunadr = (unsigned long)ke_ssdt_;
//ke_ssdt_ = (void*)*(unsigned long*)ke_ssdt_;
sysfunadr += (unsigned long)(callid*(unsigned char)4);
oldsysfunadr = *(unsigned long*)sysfunadr;
::close_cr0_wp();
*(unsigned long*)sysfunadr = (unsigned long)afun;
::open_cr0_wp();
return (void*)oldsysfunadr;
}
void close_cr0_wp()
{
__asm {
cli;
mov eax,cr0;
and eax, 0xfffeffff;
mov cr0,eax;
}
}
void open_cr0_wp()
{
__asm {
mov eax,cr0;
or eax, 0x10000
mov cr0,eax;
sti;
}
}
void * __stdcall my_filter_ObjectName(unsigned long unicode_string)
{
#define dn 6
UNICODE_STRING *us;
ANSI_STRING ansistring_objname = {0};
char filtertxt[dn][20] = {"\\Device\\Afd", "\\Device\\Ip", "\\Device\\Tcp6", "\\Device\\Tcp", "\\Device\\Tcpip", "\\Nsi"};
//int fl = ::strlen(filtertxt);
us = (UNICODE_STRING*)unicode_string;
int i_retd = 0;
::RtlUnicodeStringToAnsiString(&ansistring_objname, us, 1);
//::DbgPrint("%s\r\n", ansistring_objname.Buffer);
for(int j = 0; j < dn; j++ ) {
for(int i = 0; i < ansistring_objname.Length; i++) {
if( *(ansistring_objname.Buffer+i) == filtertxt[j][0]) {
if(::RtlCompareMemory(filtertxt[j], ansistring_objname.Buffer+i, strlen(filtertxt[j])) == strlen(filtertxt[j])) {
//::DbgPrint("rj....%s\r\n", ansistring_objname.Buffer);
i_retd = 1;
}
}
}
}
::RtlFreeAnsiString(&ansistring_objname);
return (void*)i_retd;
}
void * __stdcall my_query_Object_string(void *handle)
{
#define t_1 100
char wstr[t_1] = {0};
UNICODE_STRING *usObjectName = (UNICODE_STRING*)wstr;
ANSI_STRING anObjectName = {0};
unsigned long rl = 0;
unsigned long filter_retval = 0;
if(!NT_SUCCESS(ZwQueryObject(handle, (OBJECT_INFO_CLASS)1, (void*)wstr, t_1, &rl))) return 0;
::RtlUnicodeStringToAnsiString(&anObjectName, usObjectName, 1);
///DbgPrint("ZwDeviceIoControlFile handle type_string = %s\r\n", anObjectName.Buffer);
filter_retval = (unsigned long)::my_filter_ObjectName((unsigned long)usObjectName);
if(filter_retval != 0) ::ZwClose(handle);
::RtlFreeAnsiString(&anObjectName);
return (void*)filter_retval;
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课