謝秀維
中國人民銀行滄州中心支行科技科 河北 061001
隨著Internet不斷的發展和普及,網絡信息安全問題越來越受到人的關注,時常讓人擔憂。攻擊者利用計算機硬件、軟件、網絡設備等安全漏洞進行攻擊。攻擊事件一旦發生就可能導致有關的服務中斷、重要商業信息失竊、研究機構的重要數據丟失甚至涉及到國家機密等,其災難性后果不言而喻。防火墻是網絡信息安全的主要技術手段之一,個人防火墻得到了廣泛應用。
由于防火墻涉及系統文件SYS、動態連接庫DLL和用戶界面應用程序EXE,因此,不同進程間數據共享就變得至關重要。DLL安裝在應用程序和驅動程序之間,為上層應用程序提供網絡連接服務。
DLL與EXE及其它調用它的進程都需要共享控管規則數據,但這些數據都不是固定長度的,因此選用了內存映射的方法。此外,由于DLL和SYS都是對截獲的封包緩沖區進行操作,如采用全局變量則會降低模塊的獨立性,而采用內存映射正好解決了這一問題。
因為 Windows2000不允許應用層的程序直接訪問系統內存的地址空間,為了在EXE,DLL和SYS之間共享內存,實現內存共享的原理是:首先用驅動程序(SYS)申請內存空間,SYS中申請的內存在系統地址空間(>=0x80000000),為了讓EXE和DLL能夠訪問這個空間,需要將系統地址空間映射到用戶地址空間(<0x80000000),具體的步驟是:
(1) 在SYS中申請內存空間,代碼如下:
SystemVirtualAddress=MmAllocateContiguousMemory(NumberOfBytes,HighestAcceptableAddress );
(2) 申請一個MDL結構,代碼如下:
Mdl = IoAllocateMdl (SystemVirtualAddress, NumberOfBytes,FALSE,FALSE, NULL);
(3) 在MDL結構中標識內存頁
①如果申請內存時使用了非分頁池(non-paged pool),使用下面的代碼:
MmBuildMdlForNonPagedPool (Mdl);
②如果申請內存時使用了分頁池(paged pool),使用下面的代碼:
MmProbeAndLockPages (Mdl, KernelMode, IoWriteAccess);
(4) 將鎖定的內存頁映射到應用層(EXE或DLL)的用戶地址空間,代碼如下:
UserVirtualAddress=MmMapLockedPages (Mdl, UserMode);
上面的4個步驟可以在DriverEntry或者DispatchRoutine中運行。
釋放內存大致是執行與上面相反的過程。步驟如下:
(1) 在用戶進程上下文環境中執行下面的代碼,解除到用戶地址空間的映射:
MmUnmapLockedPages (UserVirtualAddress, Mdl);
(2) 如果使用MmProbleAndLockPages鎖定了內存空間,使用下面的代碼解鎖:
MmUnlockPages (Mdl);
(3) 釋放MDL,代碼如下: IoFreeMdl (Mdl);
(4) 釋放系統空間,代碼如下:
MmFreeContiguousMemory (SystemVirtualAddress);
或者:ExFreePool (SystemVirtualAddress);
在上述四個步驟中,第一步必須在用戶進程上下文環境中執行,2, 3, 4步可以在DriverEntry或者DispatchRoutine中運行。
NETLAB.EXE與NETLAB.DLL主要需要進行控管規則數據和封包數據的共享,另外需要一些其它輔助操作。它之間的接口函數為XfIoControl,此函數在NETLAB.DLL的TCPIPDOG.CPP模塊。
NETLAB.EXE通過LoadLibrary打開NETLAB.DLL,然后通過GetProcAddress得到XfIoControl函數的地址,以后NETLAB.EXE便通過XfIoControl函數完成與NETLAB.DLL的通信。XfIoControl支持的操作如下:
(1) 控制代碼:IO_CONTROL_SET_NETLAB_PROCESS_ID
參數含義:IoControl->DWord:進程ID
IoControl->DWord2:進程完整路徑指針
(2) 控制代碼:IO_CONTROL_SET_WORK_MODE
參數含義:IoControl->Byte:總工作模式
(3) 控制代碼:IO_CONTROL_GET_SESSION_FILE_HANDLE
參數含義:IoControl->DWord:返回封包緩沖區的地址
作用:NETLAB.EXE從NETLAB.DLL得到封包緩沖區的地址,由于內存映射文件不同進程映射的地址不同,所以此參數不能真正作為地址來用,只是用來區分NETLAB.DLL是否成功創建了封包緩沖區,等于0表示否定,大于0表示肯定。
驅動程序模塊或者NETLABPCK.SYS與NETLAB.EXE和NETLAB.DLL之間主要需要進行控管規則數據、封包數據、網上鄰居名字列表等數據的共享,另外需要一些其它輔助操作。它們之間的接口函數為OnW32DeviceIoControl,此函數在NETLABPCK 的NETLABPCK.C模塊。
NETLAB.EXE通過CreateFile打開NETLABPCK.SYS,然后通過DeviceIoControl完成與NETLABPCK的通信。
Typedef struct tagIOCTLParams {
DWORD dioc_IOCtICode;
PVOID dioc_InBuf;
DWORD dioc_c_cblnBuf;
PVOID dioc_OutBuf;
DWORD dioc_c_bOutBuf;
} IOCTLPARAMS,* PIOCTLPARAMS
設備輸入輸出處理函數為OnW32Deviceiocontrol(PIOCT LPARAMS,pVtoolsD),根據pVtoolsD-> dioc_IOCtICode不同而進行不同操作,具體分為以下情況:
(1) 控制代碼:IOCTL_NETLABPCK_MALLOC_ACL_BUFFER
參數含義:
pVtoolsD->dioc_InBuf: 指向DWORD的指針,需要申請的控管規則內存空間大小。
(2) 控制代碼:IOCTL_NETLABPCK_FREE_ACL_BUFFER
作用:NETLAB.EXE通知NETLABPCK釋放為控管規則申請的內存空間。
(3)控制代碼:IOCTL_NETLABPCK_GET_BUFFER_POINT
參數含義:
pVtoolsD->dioc_dioc_OutBuf:指向 PACKET_BUFFER_POINT結構的緩沖區指針,用來返回封包緩沖區的地址、讀/寫緩沖區的索引地址和封包緩沖區能容納封包記錄的最大個數。
作用:NETLAB.EXE通過這個控制代碼,從NETLABPCK取得封包緩沖區的地址。封包緩沖區由NETLABPCK生成和維護,NETLAB.EXE負責提取信息并用來顯示、詢問、報警和保存日志。
(4) 控制代碼:IOCTL_NETLABPCK_DELETE_SPI_PORT
參數含義:
pVtoolsD->dioc_InBuf:指向WORD類型的指針,保存要刪除的SPI端口。
作用:NETLAB.DLL通過NETLABPCK刪除共享內存的端口列表。當經過NETLAB.DLL過濾的端口完成通信而釋放時,通過這個控制代碼刪除共享內存的端口列表,告訴驅動程序,這個端口已經不再被NETLAB.DLL過濾,驅動程序需要負責對這個端口進行過濾。
(5) 控制代碼:IOCTL_NETLABPCK_GET_NAME_F ROM_IP
參數含義:pVtoolsD->dioc_InBuf: 要查詢的IP地址;
pVtoolsD->dioc_OutBuf: 用來返回查詢得到的網上鄰居名字。
作用:FITLER.EXE通過這個控制代碼,從IP地址查詢得到網上鄰居的名字。
隨著Internet技術的發展,網絡安全將會面臨更加嚴峻的挑戰。本文從技術角度出發,對防火墻內部主要模塊間的通訊技術進行了詳細的分析和介紹,希望能對不同的用戶提供參考。
[1] Keith E.Strassberg,Richard J.Gondek,Gary Rollie等著.李昂等譯.防火墻技術大全.北京:機械工業出版社.2003.
[2] Terry William Ogletree 著.李之棠等譯.防火墻的原理與實施.北京:電子工業出版社.2001.
[3] 博嘉科技.LINUX防火墻技術探秘.北京:國防工業出版社.2002.
[4] 周宏,劉克勤.新型主機防火墻模型的研究.現代電力.2003.