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);
}
以上是主要程序的源码,驱动部分共有32个目标文件,如图:
/* 驱动入口 */
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;
}
针对tcp或udp、ip等设备对象时的操作,操作分两种:设备过滤模式 和 TDI Hook模式。源码如下:
//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);
学习的目的是成熟!~