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_filter00051 };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 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 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 DBG00120 00121 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 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 } 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 00193 00194 00195 00196 VOID00197 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 NTSTATUS00214 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 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 }