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
00027
00029 #define HOOK_FN_ENTRY(name) /
00030 {#name, NULL, new_##name}
00031
00032 struct hook_fn g_hook_fn[MAX_HOOK_FN] = {
00033
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
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
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
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
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
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
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
00193
00194
00195
00196 VOID
00197 OnUnload(IN PDRIVER_OBJECT DriverObject)
00198 {
00199
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
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
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
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
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 }