ndis_hook.c

来源:互联网 发布:网络彩票代理 编辑:程序博客网 时间:2024/06/12 22:45

ndis_hook.c

00004 00014 #include <ntddk.h>00015 00016 #include "adapters.h"00017 #include "av.h"00018 #include "memtrack.h"00019 #include "ndis_hk.h"00020 #include "filter.h"00021 #include "ndis_hk_ioctl.h"00022 #include "nt.h"00023 #include "pe.h"00024 #include "except.h"00025 00026 /* globals */00027 00029 #define HOOK_FN_ENTRY(name) /00030     {#name, NULL, new_##name}00031 00032 struct hook_fn g_hook_fn[MAX_HOOK_FN] = {00033     // see hooked_fn.c00034     HOOK_FN_ENTRY(NdisRegisterProtocol),00035     HOOK_FN_ENTRY(NdisDeregisterProtocol),00036     HOOK_FN_ENTRY(NdisOpenAdapter),00037     HOOK_FN_ENTRY(NdisCloseAdapter)00038 };00039 00040 NDIS_HANDLE g_buffer_pool = NULL;00041 NDIS_HANDLE g_packet_pool = NULL;00042 00044 static PDEVICE_OBJECT g_devcontrol = NULL;00045 00047 static const struct ndis_hk_interface g_interface = {00048     NDIS_HK_INTERFACE_VER,00049     get_adapter_list,00050     attach_filter00051 };00052 00053 /* prototypes */00054 00055 static NTSTATUS     DeviceDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp);00056 static VOID         OnUnload(IN PDRIVER_OBJECT DriverObject);00057 00058 static NTSTATUS     hook_ndis(int unhook);00059 00060 static void         *find_system_dll(const char *name);00061 static void         *fix_export(char *base, const char *fn, void *new_fn);00062 00063 static BOOLEAN      replace_value_safe(ULONG *addr, ULONG value);00064 00068 NTSTATUS00069 DriverEntry(IN PDRIVER_OBJECT theDriverObject,00070             IN PUNICODE_STRING theRegistryPath)00071 {00072     NTSTATUS status;00073     int i;00074     UNICODE_STRING devname;00075 00076     memtrack_init();00077     init_adapter_list();00078     init_filter();00079     00080     __try {00081         00082         // allocate NDIS packet & buffer pools00083         NdisAllocatePacketPool(&status, &g_packet_pool, 100, sizeof(struct protocol_reserved));00084         if (status != NDIS_STATUS_SUCCESS) {00085             KdPrint(("[ndis_hk] DriverEntry: NdisAllocatePacketPool: 0x%x/n", status));00086             __leave;00087         }00088         00089         NdisAllocateBufferPool(&status, &g_buffer_pool, 100);00090         if (status != NDIS_STATUS_SUCCESS) {00091             KdPrint(("[ndis_hk] DriverEntry: NdisAllocateBufferPool: 0x%x/n", status));00092             __leave;00093         }00094         00095         status = init_av();00096         if (status != STATUS_SUCCESS) {00097             KdPrint(("[ndis_hk] DriverEntry: init_av: 0x%x/n", status));00098             __leave;00099         }00100         00101         for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)00102             theDriverObject->MajorFunction[i] = DeviceDispatch;00103         00104         // create control device00105         RtlInitUnicodeString(&devname, L"//Device//ndis_hk");00106         00107         status = IoCreateDevice(theDriverObject,00108             0,00109             &devname,00110             0,00111             0,00112             FALSE,00113             &g_devcontrol);00114         if (status != STATUS_SUCCESS) {00115             KdPrint(("[ndis_hk] DriverEntry: IoCreateDevice(control): 0x%x!/n", status));00116             __leave;00117         }00118         00119 #if DBG00120         // register UnLoad procedure00121         theDriverObject->DriverUnload = OnUnload;00122 #endif00123         00124         status = hook_ndis(FALSE);00125         if (status != STATUS_SUCCESS)00126             KdPrint(("[ndis_hk] DriverEntry: hook_ndis: 0x%x!/n", status));00127         00128     } __except((status = GetExceptionCode(), EXCEPTION_EXECUTE_HANDLER)) {00129         KdPrint(("[ndis_hk] DriverEntry: exception 0x%x!/n", status));00130     }00131     00132     if (status != STATUS_SUCCESS)00133         OnUnload(theDriverObject);00134     00135     return status;00136 }00137 00142 NTSTATUS00143 DeviceDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp)00144 {00145     NTSTATUS status;00146 00147     // set irp with defaults00148     irp->IoStatus.Information = 0;00149 00150     if (DeviceObject == g_devcontrol) {00151         PIO_STACK_LOCATION irps = IoGetCurrentIrpStackLocation(irp);00152 00153         switch (irps->MajorFunction) {00154         case IRP_MJ_CREATE:00155         case IRP_MJ_CLEANUP:00156         case IRP_MJ_CLOSE:00157             status = STATUS_SUCCESS;00158             break;00159 00160         case IRP_MJ_INTERNAL_DEVICE_CONTROL:00161             if (irps->Parameters.DeviceIoControl.IoControlCode == IOCTL_CMD_GET_KM_IFACE) {00162                 00163                 if (irps->Parameters.DeviceIoControl.OutputBufferLength == sizeof(struct ndis_hk_interface *)) {00164 00165                     // return pointer to interface structure00166                     *(const struct ndis_hk_interface **)(irp->AssociatedIrp.SystemBuffer) = &g_interface;00167                     irp->IoStatus.Information = sizeof(struct ndis_hk_interface *);00168 00169                     status = STATUS_SUCCESS;00170 00171                 } else00172                     status = STATUS_INFO_LENGTH_MISMATCH;00173 00174             } else00175                 status = STATUS_NOT_SUPPORTED;00176             00177             break;00178 00179         default:00180             status = STATUS_NOT_SUPPORTED;00181         }00182     } else00183         status = STATUS_NOT_SUPPORTED;00184 00185     irp->IoStatus.Status = status;00186     IoCompleteRequest(irp, IO_NO_INCREMENT);00187 00188     return status;00189 }00190 00191 /*00192  * Unload procedure00193  * Driver can't be unloaded due to security reasons.00194  * This function only for memory leak testing00195  */00196 VOID00197 OnUnload(IN PDRIVER_OBJECT DriverObject)00198 {00199     // unhook NDIS00200     hook_ndis(TRUE);00201 00202     free_av();00203     free_adapter_list();00204 00205     memtrack_free();00206 }00207 00213 NTSTATUS00214 hook_ndis(int unhook)00215 {00216     void *ndis_sys;00217     int i;00218 00219     // 1. find ndis.sys00220     ndis_sys = find_system_dll("NDIS.sys");00221     if (ndis_sys == NULL) {00222         KdPrint(("[ndis_hk] hook_ndis: find_system_dll!/n"));00223         return STATUS_OBJECT_NAME_NOT_FOUND;00224     }00225 00226     // 2. (un)hook all of the functions00227     for (i = 0; i < MAX_HOOK_FN; i++) {00228         if (!unhook) {00229             void *old_fn = fix_export((char *)ndis_sys, g_hook_fn[i].name, g_hook_fn[i].new_fn);00230 00231             if (old_fn == NULL) {00232                 KdPrint(("[ndis_hk] hook_ndis: fix_export!/n"));00233 00234                 // replace them back!00235                 hook_ndis(TRUE);00236 00237                 return STATUS_OBJECT_NAME_NOT_FOUND;00238             }00239             00240             KdPrint(("[ndis_hk] hook_ndis: %s: old: 0x%x new: 0x%x/n", 00241                 g_hook_fn[i].name,00242                 old_fn,00243                 g_hook_fn[i].new_fn));00244 00245             g_hook_fn[i].old_fn = old_fn;00246         00247         } else {00248             if (g_hook_fn[i].old_fn != NULL)00249                 fix_export((char *)ndis_sys, g_hook_fn[i].name, g_hook_fn[i].old_fn);00250         }00251     }00252 00253     return STATUS_SUCCESS;00254 }00255 00263 void *00264 find_system_dll(const char *name)00265 {00266     ULONG i, n, *q;00267     PSYSTEM_MODULE_INFORMATION p;00268     void *base;00269 00270     ZwQuerySystemInformation(SystemModuleInformation, &n, 0, &n);00271     q = (ULONG *)ExAllocatePool(PagedPool, n);00272     ZwQuerySystemInformation(SystemModuleInformation, q, n * sizeof (*q), 0);00273     00274     p = (PSYSTEM_MODULE_INFORMATION)(q + 1);00275     base = NULL;00276     for (i = 0; i < *q; i++) {00277         if (_stricmp(p[i].ImageName + p[i].ModuleNameOffset, name) == 0) {00278             base = p[i].Base;00279             KdPrint(("[ndis_hk] find_system_dll: %s; base = 0x%x; size = 0x%x/n", name, base, p[i].Size));00280             break;00281         }00282     }00283         00284     ExFreePool(q);00285     return base;00286 }00287 00295 void *00296 fix_export(char *base, const char *fn, void *new_fn)00297 {00298     PIMAGE_DOS_HEADER dos_hdr;00299     PIMAGE_NT_HEADERS nt_hdr;00300     PIMAGE_EXPORT_DIRECTORY export_dir;00301     ULONG *fn_name, *fn_addr, i;00302 00303     dos_hdr = (PIMAGE_DOS_HEADER)base;00304 00305     if (dos_hdr->e_magic != IMAGE_DOS_SIGNATURE)00306         return NULL;00307 00308     nt_hdr = (PIMAGE_NT_HEADERS)(base + dos_hdr->e_lfanew);00309 00310     export_dir = (PIMAGE_EXPORT_DIRECTORY)(base + nt_hdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);00311 00312     fn_name = (ULONG *)(base + export_dir->AddressOfNames);00313     fn_addr = (ULONG *)(base + export_dir->AddressOfFunctions);00314 00315     for (i = 0; i < export_dir->NumberOfNames; i++, fn_name++, fn_addr++) {00316         if (strcmp(fn, base + *fn_name) == 0) {00317             void *old_addr = base + *fn_addr;00318 00319             // replace value safe00320             replace_value_safe(fn_addr, (char *)new_fn - base);00321 00322             return old_addr;00323         }00324     }00325 00326     return NULL;00327 }00328 00335 BOOLEAN00336 replace_value_safe(ULONG *addr, ULONG value)00337 {00338     MDL *mdl;00339     ULONG *virt_addr;00340 00341     mdl = IoAllocateMdl(addr, sizeof(value), FALSE, FALSE, NULL);00342     if (mdl == NULL)00343         return FALSE;00344 00345     __try {00346     00347         MmProbeAndLockPages(mdl, KernelMode, IoModifyAccess);00348 00349     } __except(EXCEPTION_EXECUTE_HANDLER) {00350         KdPrint(("[ndis_hk] replace_value_safe: MmProbeAndLockPages!/n"));00351         return FALSE;00352     }00353 00354     virt_addr = (ULONG *)MmGetSystemAddressForMdl(mdl);00355 00356     *(ULONG *)virt_addr = value;00357 00358     MmUnlockPages(mdl);00359     IoFreeMdl(mdl);00360     return TRUE;00361 }