ndis_hook.c

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.c
00034     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_filter
00051 };
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 NTSTATUS
00069 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 pools
00083         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 device
00105         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 DBG
00120         // register UnLoad procedure
00121         theDriverObject->DriverUnload = OnUnload;
00122 #endif
00123         
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 NTSTATUS
00143 DeviceDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp)
00144 {
00145     NTSTATUS status;
00146 
00147     // set irp with defaults
00148     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 structure
00166                     *(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                 } else
00172                     status = STATUS_INFO_LENGTH_MISMATCH;
00173 
00174             } else
00175                 status = STATUS_NOT_SUPPORTED;
00176             
00177             break;
00178 
00179         default:
00180             status = STATUS_NOT_SUPPORTED;
00181         }
00182     } else
00183         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 procedure
00193  * Driver can't be unloaded due to security reasons.
00194  * This function only for memory leak testing
00195  */
00196 VOID
00197 OnUnload(IN PDRIVER_OBJECT DriverObject)
00198 {
00199     // unhook NDIS
00200     hook_ndis(TRUE);
00201 
00202     free_av();
00203     free_adapter_list();
00204 
00205     memtrack_free();
00206 }
00207 
00213 NTSTATUS
00214 hook_ndis(int unhook)
00215 {
00216     void *ndis_sys;
00217     int i;
00218 
00219     // 1. find ndis.sys
00220     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 functions
00227     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 safe
00320             replace_value_safe(fn_addr, (char *)new_fn - base);
00321 
00322             return old_addr;
00323         }
00324     }
00325 
00326     return NULL;
00327 }
00328 
00335 BOOLEAN
00336 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 }

你可能感兴趣的:(exception,object,struct,null,interface,hook)