tdifw是windows防火墙软件(TDI层驱动过滤),负责监控网络监听与连接、以及过滤信息。
源码在src目录, 程序在Bin目录,执行根目录下的批处理文件也可以,
具体步骤如下:
1. 运行install.bat
2. 根据你机器的配置情况,编辑%SystemRoot%\system32\drivers\etc\tdifw.conf配置文件
3. 重新启动计算机
主程序源码是win32的,就9个目标文件,不包含驱动部分,项目如图:
程序主要源码分析:
int main(int argc, char **argv) { static SERVICE_TABLE_ENTRY dispatch_table[] = { {"tdifw", service_main}, {NULL, NULL} }; _LEAK_CHECK; //模拟参数 argc = 3; argv[0]="tdifw"; argv[1]="install"; argv[2]="tdifw_drv.sys"; if (argc >= 2) { const char *param = argv[1]; if (strcmp(param, "install") == 0) { if (argc < 3) { fprintf(stderr, "Use: tdifw install <config>\n"); return -1; } //加载驱动服务 install_service(argv[2]); } else if (strcmp(param, "remove") == 0) { //移除驱动服务 remove_service(); } else if (strcmp(param, "debug") == 0) { if (argc < 3) { fprintf(stderr, "Use: tdifw debug <config>\n"); return -1; } if (start(argv[2])) { printf("press enter to exit...\n"); getchar(); printf("exiting...\n"); //停止 释放资源 stop(); } } else if (strcmp(param, "listen") == 0) { // tdifw specific //枚举监听 enum_listen(); } else if (strcmp(param, "conn") == 0) { // tdifw specific //枚举连接 enum_connect(); } else { fprintf(stderr, "Use: tdifw install|remove|debug|listen|conn\n"); } } else { g_console = FALSE; // 连接程序主线程到服务控制管理程序 if (!StartServiceCtrlDispatcher(dispatch_table)) winerr("main: StartServiceCtrlDispatcher"); } return 0; }
//获得驱动文件所在路径 则开启 否则退出 void install_service(const char *config) { SC_HANDLE schService; SC_HANDLE schSCManager; CHAR szPath[MAX_PATH]; //从注册表中获得信息 AddEventSource("tdifw"); if (GetModuleFileName(NULL, szPath, sizeof(szPath)) == 0) { winerr("install_service: GetModuleFileName"); return; } //建立了一个连接到服务控制管理器,并打开指定的数据库。 schSCManager = OpenSCManager( NULL, // machine (NULL == local) NULL, // database (NULL == default) SC_MANAGER_ALL_ACCESS); // access required if (schSCManager != NULL) { //创建一个服务对象并且把它加入到服务管理数据库中 schService = CreateService( schSCManager, // SCManager database "tdifw", // name of service "TDI-based open source personal firewall", // name to display SERVICE_ALL_ACCESS, // desired access SERVICE_WIN32_OWN_PROCESS, // service type SERVICE_AUTO_START, // start type SERVICE_ERROR_NORMAL, // error control type szPath, // service's binary NULL, // no load ordering group NULL, // no tag identifier NULL, // dependencies NULL, // LocalSystem account NULL); // no password if (schService != NULL) { printf("tdifw service has been installed\n"); if (!add_config_info(schService, config)) fprintf(stderr, "Can't store config info! Service will use defaults.\n"); CloseServiceHandle(schService); } else winerr("install_service: CreateService"); CloseServiceHandle(schSCManager); } else winerr("install_service: OpenSCManager"); }
//移除服务 关闭驱动 void remove_service(void) { SC_HANDLE schService; SC_HANDLE schSCManager; schSCManager = OpenSCManager( NULL, // machine (NULL == local) NULL, // database (NULL == default) SC_MANAGER_ALL_ACCESS); // access required if (schSCManager != NULL) { schService = OpenService(schSCManager, "tdifw", SERVICE_ALL_ACCESS); if (schService != NULL) { // try to stop the service if (ControlService(schService, SERVICE_CONTROL_STOP, &ssStatus)) { printf("stopping..."); Sleep(1000); while(QueryServiceStatus( schService, &ssStatus)) { if (ssStatus.dwCurrentState == SERVICE_STOP_PENDING) { printf("."); Sleep( 1000 ); } else break; } printf("\n"); if (ssStatus.dwCurrentState == SERVICE_STOPPED) printf("stopped\n"); else printf("failed to stop\n"); } // now remove the service if (DeleteService(schService)) printf("service has been removed\n"); else winerr("install_service: DeleteService"); CloseServiceHandle(schService); } else winerr("install_service: OpenService"); CloseServiceHandle(schSCManager); } else winerr("install_service: OpenSCManager"); }
// 从驱动程序中获得网络监听对象 void enum_listen(void) { ULONG size; struct listen_nfo *ln = NULL; int i, n; // 从 psapi.dll 中获得链接EnumProcesses、EnumProcessModules、GetModuleFileNameExW函数地址 link_psapi(); /* connect with driver */ g_device = CreateFile(g_nfo_device_name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (g_device == INVALID_HANDLE_VALUE) { winerr(g_nfo_device_name); goto done; } /* get list of listening objects */ size = sizeof(*ln) * 0x10000 * 3; // this size is good enough :-) ln = (struct listen_nfo *)malloc(size); if (ln == NULL) { perror("malloc"); goto done; } //与驱动交流 枚举监听操作 获取监听信息 if (!DeviceIoControl(g_device, IOCTL_CMD_ENUM_LISTEN, NULL, 0, ln, size, &size, NULL)) { winerr("DeviceIoControl"); goto done; } n = size / sizeof(*ln); // sort this list! qsort(ln, n, sizeof(*ln), compare_ln); printf("IPProto\tAddress:Port\tProcess (pid)\n"); printf("-------\t------------\t---------------------------------------------\n"); //显示 for (i = 0; i < n ; i++) { char *proto, pname[MAX_PATH]; if (ln[i].ipproto == IPPROTO_TCP) proto = "TCP"; else if (ln[i].ipproto == IPPROTO_UDP) proto = "UDP"; else if (ln[i].ipproto == IPPROTO_IP) proto = "RawIP"; else proto = "?"; // resolve pid! if (!get_pname_by_pid(ln[i].pid, pname, sizeof(pname))) pname[0] = '\0'; printf("%s\t%d.%d.%d.%d:%d\t%s (%d)\n", proto, PRINT_IP_ADDR(ln[i].addr), ntohs(ln[i].port), pname, ln[i].pid); } done: free(ln); if (g_device != INVALID_HANDLE_VALUE) CloseHandle(g_device); }
// 从驱动程序中获得网络连接信息 void enum_connect(void) { ULONG size; struct tcp_conn_nfo *tn = NULL; int i, n; unsigned __int64 traffic[TRAFFIC_MAX]; // 从 psapi.dll 中获得链接EnumProcesses、EnumProcessModules、GetModuleFileNameExW函数地址 link_psapi(); /* connect with driver */ g_device = CreateFile(g_nfo_device_name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (g_device == INVALID_HANDLE_VALUE) { winerr(g_nfo_device_name); goto done; } /* get list of listening objects */ size = sizeof(*tn) * 0x10000 * 3; // this size is good enough :-) tn = (struct tcp_conn_nfo *)malloc(size); if (tn == NULL) { perror("malloc"); goto done; } //与驱动交流 枚举监听操作 获取连接信息 if (!DeviceIoControl(g_device, IOCTL_CMD_ENUM_TCP_CONN, NULL, 0, tn, size, &size, NULL)) { winerr("DeviceIoControl"); goto done; } n = size / sizeof(*tn); // sort this list! qsort(tn, n, sizeof(*tn), compare_tn); //顺序输出 for (i = 0; i < n ; i++) { char pname[MAX_PATH]; if (tn[i].state >= TCP_STATE_MAX) tn[i].state = 0; // resolve pid! if (!get_pname_by_pid(tn[i].pid, pname, sizeof(pname))) pname[0] = '\0'; printf("%s\t%d.%d.%d.%d:%d\t%d.%d.%d.%d:%d\t%s (%d)\t%u/%u\n", g_tcp_states[tn[i].state], PRINT_IP_ADDR(tn[i].laddr), ntohs(tn[i].lport), PRINT_IP_ADDR(tn[i].raddr), ntohs(tn[i].rport), pname, tn[i].pid, tn[i].bytes_out, tn[i].bytes_in); } // output traffic counters get_traffic_stats(traffic); printf( "\n" "Traffic counters (out/in):\n" " Total: %I64u/%I64u\n" " Counted: %I64u/%I64u\n", traffic[TRAFFIC_TOTAL_OUT], traffic[TRAFFIC_TOTAL_IN], traffic[TRAFFIC_COUNTED_OUT], traffic[TRAFFIC_COUNTED_IN]); done: free(tn); if (g_device != INVALID_HANDLE_VALUE) CloseHandle(g_device); }
/* 驱动入口 */ NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath) { NTSTATUS status = STATUS_SUCCESS; int i; UNICODE_STRING name, linkname; //内存跟踪初始化 调用了KeInitializeSpinLock(&guard); memtrack_init(); //初始化锁 KeInitializeSpinLock(&g_traffic_guard); #ifdef USE_TDI_HOOKING KdPrint(("[tdi_fw] WARNING! Using unstable working mode: TDI hooking!\n")); #endif status = ot_init(); if (status != STATUS_SUCCESS) { KdPrint(("[tdi_fw] DriverEntry: ot_init: 0x%x\n", status)); goto done; } //过滤器初始化 status = filter_init(); if (status != STATUS_SUCCESS) { KdPrint(("[tdi_fw] DriverEntry: filter_init: 0x%x\n", status)); goto done; } //连接状态初始化 status = conn_state_init(); if (status != STATUS_SUCCESS) { KdPrint(("[tdi_fw] DriverEntry: conn_state_init: 0x%x\n", status)); goto done; } //分发函数 for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) theDriverObject->MajorFunction[i] = DeviceDispatch; #if DBG // register UnLoad procedure theDriverObject->DriverUnload = OnUnload; #endif /* create control device and symbolic link */ RtlInitUnicodeString(&name, L"\\Device\\tdifw"); status = IoCreateDevice(theDriverObject, 0, &name, 0, 0, TRUE, // exclusive! &g_devcontrol); if (status != STATUS_SUCCESS) { KdPrint(("[tdi_fw] DriverEntry: IoCreateDevice(control): 0x%x!\n", status)); goto done; } RtlInitUnicodeString(&linkname, L"\\??\\tdifw"); //创建了一个符号连接 status = IoCreateSymbolicLink(&linkname, &name); if (status != STATUS_SUCCESS) { KdPrint(("[tdi_fw] DriverEntry: IoCreateSymbolicLink: 0x%x!\n", status)); goto done; } RtlInitUnicodeString(&name, L"\\Device\\tdifw_nfo"); //创建设备对象 status = IoCreateDevice(theDriverObject, 0, &name, 0, 0, FALSE, // not exclusive! &g_devnfo); if (status != STATUS_SUCCESS) { KdPrint(("[tdi_fw] DriverEntry: IoCreateDevice(nfo): 0x%x!\n", status)); goto done; } RtlInitUnicodeString(&linkname, L"\\??\\tdifw_nfo"); //创建了一个符号连接 status = IoCreateSymbolicLink(&linkname, &name); if (status != STATUS_SUCCESS) { KdPrint(("[tdi_fw] DriverEntry: IoCreateSymbolicLink: 0x%x!\n", status)); goto done; } #ifndef USE_TDI_HOOKING //绑定设备 status = c_n_a_device(theDriverObject, &g_tcpfltobj, &g_tcpoldobj, L"\\Device\\Tcp"); if (status != STATUS_SUCCESS) { KdPrint(("[tdi_fw] DriverEntry: c_n_a_device: 0x%x\n", status)); goto done; } //绑定设备 status = c_n_a_device(theDriverObject, &g_udpfltobj, &g_udpoldobj, L"\\Device\\Udp"); if (status != STATUS_SUCCESS) { KdPrint(("[tdi_fw] DriverEntry: c_n_a_device: 0x%x\n", status)); goto done; } //绑定设备 status = c_n_a_device(theDriverObject, &g_ipfltobj, &g_ipoldobj, L"\\Device\\RawIp"); if (status != STATUS_SUCCESS) { KdPrint(("[tdi_fw] DriverEntry: c_n_a_device: 0x%x\n", status)); goto done; } #else /* USE_TDI_HOOKING */ /* get device objects for tcp/udp/ip */ //获得tcp设备对象 status = get_device_object(L"\\Device\\Tcp", &g_tcpfltobj); if (status != STATUS_SUCCESS) { KdPrint(("[tdi_fw] DriverEntry: get_device_object(tcp): 0x%x\n", status)); goto done; } //获得Udp设备对象 status = get_device_object(L"\\Device\\Udp", &g_udpfltobj); if (status != STATUS_SUCCESS) { KdPrint(("[tdi_fw] DriverEntry: get_device_object(udp): 0x%x\n", status)); goto done; } //获得RawIp设备对象 status = get_device_object(L"\\Device\\RawIp", &g_ipfltobj); if (status != STATUS_SUCCESS) { KdPrint(("[tdi_fw] DriverEntry: get_device_object(ip): 0x%x\n", status)); goto done; } /* hook tcpip */ //针对tcp下钩子 status = hook_tcpip(&g_old_DriverObject, TRUE); if (status != STATUS_SUCCESS) { KdPrint(("[tdi_fw] DriverEntry: hook_driver: 0x%x\n", status)); goto done; } g_hooked = TRUE; #endif /* USE_TDI_HOOKING */ status = STATUS_SUCCESS; done: if (status != STATUS_SUCCESS) { // cleanup OnUnload(theDriverObject); } return status; }
//TDI Hook过滤模式 case IRP_MJ_CREATE: /* create fileobject */ result = tdi_create(irp, irps, &completion); status = tdi_dispatch_complete(DeviceObject, irp, result, completion.routine, completion.context); break; case IRP_MJ_DEVICE_CONTROL: KdPrint(("[tdi_fw] DeviceDispatch: IRP_MJ_DEVICE_CONTROL, control 0x%x for 0x%08X\n", irps->Parameters.DeviceIoControl.IoControlCode, irps->FileObject)); if (KeGetCurrentIrql() == PASSIVE_LEVEL) { /* * try to convert it to IRP_MJ_INTERNAL_DEVICE_CONTROL * (works on PASSIVE_LEVEL only!) */ status = TdiMapUserRequest(DeviceObject, irp, irps); } else status = STATUS_NOT_IMPLEMENTED; // set fake status if (status != STATUS_SUCCESS) { void *buf = (irps->Parameters.DeviceIoControl.IoControlCode == IOCTL_TDI_QUERY_DIRECT_SEND_HANDLER) ? irps->Parameters.DeviceIoControl.Type3InputBuffer : NULL; // send IRP to original driver status = tdi_dispatch_complete(DeviceObject, irp, FILTER_ALLOW, NULL, NULL); if (buf != NULL && status == STATUS_SUCCESS) { g_TCPSendData = *(TCPSendData_t **)buf; KdPrint(("[tdi_fw] DeviceDispatch: IOCTL_TDI_QUERY_DIRECT_SEND_HANDLER: TCPSendData = 0x%x\n", g_TCPSendData)); *(TCPSendData_t **)buf = new_TCPSendData; } break; } // don't break! go to internal device control! case IRP_MJ_INTERNAL_DEVICE_CONTROL: { /* * Analyze ioctl for TDI driver */ int i; for (i = 0; g_tdi_ioctls[i].MinorFunction != 0; i++) if (g_tdi_ioctls[i].MinorFunction == irps->MinorFunction) { #if DBG // print description KdPrint(("[tdi_fw] DeviceDispatch: %s (0x%x) for 0x%x\n", g_tdi_ioctls[i].desc, irps->MinorFunction, irps->FileObject)); #endif if (g_tdi_ioctls[i].fn == NULL) { // send IRP to original driver status = tdi_dispatch_complete(DeviceObject, irp, FILTER_ALLOW, NULL, NULL); break; } // call dispatch function result = g_tdi_ioctls[i].fn(irp, irps, &completion); // complete request status = tdi_dispatch_complete(DeviceObject, irp, result, completion.routine, completion.context); break; } // if dispatch function hasn't been found if (g_tdi_ioctls[i].MinorFunction == 0) { // send IRP to original driver status = tdi_dispatch_complete(DeviceObject, irp, FILTER_ALLOW, NULL, NULL); } break; } case IRP_MJ_CLEANUP: /* cleanup fileobject */ result = tdi_cleanup(irp, irps, &completion); status = tdi_dispatch_complete(DeviceObject, irp, result, completion.routine, completion.context); break; case IRP_MJ_CLOSE: KdPrint(("[tdi_fw] DeviceDispatch: IRP_MJ_CLOSE fileobj 0x%x\n", irps->FileObject)); // passthrough IRP status = tdi_dispatch_complete(DeviceObject, irp, FILTER_ALLOW, completion.routine, completion.context); break;
//设备过滤操作模式 if (irps->MajorFunction == IRP_MJ_CREATE) { // initialize for user-mode part (exclusive access - 1 user-mode logging part) filter_init_2(); g_got_log = TRUE; } else if (irps->MajorFunction == IRP_MJ_CLOSE) { // cleanup for user-mode logging part filter_free_2(); g_got_log = FALSE; } if (irps->MajorFunction == IRP_MJ_DEVICE_CONTROL) { /* * control request */ ULONG ioctl = irps->Parameters.DeviceIoControl.IoControlCode, len = irps->Parameters.DeviceIoControl.InputBufferLength, size = irps->Parameters.DeviceIoControl.OutputBufferLength; char *out_buf; if (IOCTL_TRANSFER_TYPE(ioctl) == METHOD_NEITHER) { // this type of transfer unsupported out_buf = NULL; } else out_buf = (char *)irp->AssociatedIrp.SystemBuffer; // process control request status = process_request(ioctl, out_buf, &len, size); irp->IoStatus.Information = len; } irp->IoStatus.Status = status; IoCompleteRequest(irp, IO_NO_INCREMENT);
学习的目的是成熟!~
源码包下载