@网络老鼠技术小屋

网络老鼠技术小屋-涂飞平的博客空间

简版防火墙完成了^_^

10 年前 1

今天完成了“Sundy简易防火墙”(暂时这么叫吧)的前端和后端的开发,总共只有两个文件:
图片:spi6.jpg
spi6.jpg
其中SundyFireWall文件是主要的前端设置界面,而SundyFW.dll是LSP链接库文件。所有的配置信息都放置在注册表中,无需安装,使用也比较简单。下面是设置界面:
图片:spi7.jpg
spi7.jpg
其中SundyFW.dll中的WSPStartup函数采用的就是上篇文章中介绍的方法,直接操作注册表,使用过程证明这个理论的正确性^_^
下面是WSPStartup的主要代码,没有注释,请将就着看吧:
=================================================================

    ZeroMemory(@opt, sizeof(TOptRecord));
if Reg.OpenKey('SOFTWARESundyFW', FALSE) then
begin
reg.ReadBinaryData('SetItem', opt, sizeof(TOptRecord));
if opt.SoftMode = 1 then
Allowed := FALSE
else
Allowed := TRUE;
FileName := strpas(@opt.SoftList[0]);
if fileexists(filename) then
begin
StrList.LoadFromFile(filename);
for j := 0 to StrList.Count - 1 do
begin
if StrList.Strings[j] = AppPath then
begin
if opt.SoftMode = 1 then
Allowed := TRUE
else
Allowed := FALSE;
break;
end;
end;
end;
end;
Reg.CloseKey;
if not Reg.OpenKey('SystemCurrentControlSetServicesWinSock2ParametersProtocol_Catalog9Catalog_Entries', FALSE) then exit;
Reg.GetKeyInfo(reginfo);
lspcount := reginfo.NumSubKeys;
GetMem(ltmp, lspcount * sizeof(WSAPROTOCOL_INFOW));
Reg.GetKeyNames(namelist);
k := 0;
for i := 0 to lspcount - 1 do
begin
Reg.CloseKey;
if not Reg.OpenKey('SystemCurrentControlSetServicesWinSock2ParametersProtocol_Catalog9Catalog_Entries' + namelist[i], FALSE) then exit;
ZeroMemory(@tmp, sizeof(tmp));
Reg.ReadBinaryData('PackedCatalogItem', tmp, sizeof(tmp));
if tmp.WI.dwCatalogEntryId = lprotoinfo^.ProtocolChain.ChainEntries[1] then
begin
k := 1;
CopyMemory(@zmwi, @tmp, sizeof(tmp));
end;
CopyMemory(Pointer(integer(ltmp) + i * sizeof(WSAPROTOCOL_INFOW)), @tmp.WI, sizeof(WSAPROTOCOL_INFOW));
end;
if k <> 1 then exit;
for i := 0 to lspcount - 1 do
begin
tmpl := LPWSAPROTOCOL_INFOW(integer(ltmp) + i * sizeof(WSAPROTOCOL_INFOW));
if tmpl^.dwCatalogEntryId = lprotoinfo^.ProtocolChain.ChainEntries[1] then
goto found;
end;
// not found
exit;

found:
DllPath := strpas(@zmwi.DLLPATH[0]);
ZeroMemory(@exdllpath[0], MAX_PATH);
if pos('%', DllPath) <> 0 then
ExpandEnvironmentStrings(pchar(DllPath), @exdllpath[0], MAX_PATH);
DllPath := StrPas(@exdllpath[0]);
Lib := LoadLibrary(pchar(DllPath));
if Lib = 0 then exit;
func := GetProcAddress(Lib, pchar('WSPStartup'));
if func = nil then exit;
result := TWSPStartup(func)(wVersionRequest, pwspdata, tmpl, upcalltbl, proctbl);
CopyMemory(@oldproc, proctbl, sizeof(WSPPROC_TABLE));
proctbl^.lpWSPRecvFrom := @wspRecvFrom;
proctbl^.lpWSPSendTo := @wspSendTo;
proctbl^.lpWSPConnect := @wspConnect;
proctbl^.lpWSPAccept := @wspAccept;

=================================================================
这个防火墙还包含一个很有效的小工具,它可以用来备份/还原系统LSP信息

图片:spi8.jpg
spi8.jpg
工具界面
图片:spi9.jpg
spi9.jpg
安装后所得到LSP信息:
序号:1
LSP名称:SUNDY[TCP]
DLL路径:D:BorlandDelphi7Projects简版防火墙SundyFW.dll
提供者GUID:{D3CD7AFC-E1C7-4F95-B544-E18EBFE95B07}
WinSock目录入口:1188
ChainLen:2
WinSock目录顺序0:1187
WinSock目录顺序1:1001
协议:IPPROTO_TCP

序号:2
LSP名称:SUNDY[UDP]
DLL路径:D:BorlandDelphi7Projects简版防火墙SundyFW.dll
提供者GUID:{D3CD7AFC-E1C7-4F95-B544-E18EBFE95B07}
WinSock目录入口:1189
ChainLen:2
WinSock目录顺序0:1187
WinSock目录顺序1:1002
协议:IPPROTO_UDP

序号:3
LSP名称:SUNDY[RAW]
DLL路径:D:BorlandDelphi7Projects简版防火墙SundyFW.dll
提供者GUID:{D3CD7AFC-E1C7-4F95-B544-E18EBFE95B07}
WinSock目录入口:1190
ChainLen:2
WinSock目录顺序0:1187
WinSock目录顺序1:1003
协议:IPPROTO_RAW

序号:4
LSP名称:MSAFD Tcpip [TCP/IP]
DLL路径:%SystemRoot%system32msafd.dll
提供者GUID:{E70F1AA0-AB8B-11CF-8CA3-00805F48A192}
WinSock目录入口:1001
ChainLen:1
协议:IPPROTO_TCP
......(省略无数行^_^)
下面的代码是安装LSP的代码,没有使用WSCInstallProvider之类的代码,而是直接操作注册表,一样可以很好的工作!通过这个防火墙在两个平台的使用,发现WinXP/Win2000下都可以安全使用,但它们内部的基础服务提供者是不同的。WinXP是wswsock.dll而Win2000是msafd.dll,但是它们的入口ID是不变的(TCP为1001,UDP为1002,RAW为1003),而且提供者GUID也是不变的({E70F1AA0-AB8B-11CF-8CA3-00805F48A192}),而我们的安装代码正是通过ID来操作的。

//index标示安装的TCP、UDP还是RAW
procedure TMainForm.InstallSPI(index: integer);
var
reg: TRegistry;
reginfo: TRegKeyInfo;
namelist: TStringList;
i, lspcount: integer;
tmp: TSundyWI;
dllpath: string;
begin
if SPIInstalled(index) then exit;//如果已经安装了就退出
reg := TRegistry.Create;
reg.RootKey := HKEY_LOCAL_MACHINE;
try
if not Reg.OpenKey('SystemCurrentControlSetServicesWinSock2ParametersProtocol_Catalog9Catalog_Entries', FALSE) then exit;
namelist := TStringList.Create;
Reg.GetKeyInfo(reginfo);
Reg.GetKeyNames(namelist);
lspcount := reginfo.NumSubKeys;
for i := lspcount - 1 downto 0 do//反向遍历,便于生成新键并复制值
begin
Reg.CloseKey;
if not Reg.OpenKey('SystemCurrentControlSetServicesWinSock2ParametersProtocol_Catalog9Catalog_Entries' + namelist[i], FALSE) then exit;
ZeroMemory(@tmp, sizeof(tmp));
Reg.ReadBinaryData('PackedCatalogItem', tmp, sizeof(tmp));
//读出健值
Reg.CloseKey;
Reg.OpenKey('SystemCurrentControlSetServicesWinSock2ParametersProtocol_Catalog9Catalog_Entries' + ExpentString(namelist[i], 0), TRUE);
//生成新键,ExpentString函数自动将传入的字符串加1,比如传入//000000000011,生成000000000012
Reg.WriteBinaryData('PackedCatalogItem', tmp, sizeof(tmp));
//写入上面读出来的值
//相当于将所有的键都往后面移一个
end;
dllpath := ExtractFilePath(ParamStr(0)) + 'SundyFW.dll';
CopyMemory(@tmp.DllPath[0], pchar(dllpath), length(dllpath));
tmp.DLLPATH[length(dllpath)] := #0;
case index of
0: begin //TCP
tmp.WI.ProviderId := SundyFWGUID;
tmp.WI.dwCatalogEntryId := 1188;//入口ID
tmp.WI.ProtocolChain.ChainLen := 2;//协议链
tmp.WI.ProtocolChain.ChainEntries[0] := 1187;
tmp.WI.ProtocolChain.ChainEntries[1] := 1001;//上层协议入口
tmp.WI.iAddressFamily := AF_INET;
tmp.WI.iProtocol := IPPROTO_TCP;
tmp.WI.szProtocol[0] := 'S';
tmp.WI.szProtocol[1] := 'U';
tmp.WI.szProtocol[2] := 'N';
tmp.WI.szProtocol[3] := 'D';
tmp.WI.szProtocol[4] := 'Y';
tmp.WI.szProtocol[5] := '[';
tmp.WI.szProtocol[6] := 'T';
tmp.WI.szProtocol[7] := 'C';
tmp.WI.szProtocol[8] := 'P';
tmp.WI.szProtocol[9] := ']';
tmp.WI.szProtocol[10] := #0;
end;
1: begin//UDP
tmp.WI.ProviderId := SundyFWGUID;
tmp.WI.dwCatalogEntryId := 1189;
tmp.WI.ProtocolChain.ChainLen := 2;
tmp.WI.ProtocolChain.ChainEntries[0] := 1187;
tmp.WI.ProtocolChain.ChainEntries[1] := 1002;
tmp.WI.iAddressFamily := AF_INET;
tmp.WI.iProtocol := IPPROTO_UDP;
tmp.WI.szProtocol[0] := 'S';
tmp.WI.szProtocol[1] := 'U';
tmp.WI.szProtocol[2] := 'N';
tmp.WI.szProtocol[3] := 'D';
tmp.WI.szProtocol[4] := 'Y';
tmp.WI.szProtocol[5] := '[';
tmp.WI.szProtocol[6] := 'U';
tmp.WI.szProtocol[7] := 'D';
tmp.WI.szProtocol[8] := 'P';
tmp.WI.szProtocol[9] := ']';
tmp.WI.szProtocol[10] := #0;
end;
2: begin//RAW
tmp.WI.ProviderId := SundyFWGUID;
tmp.WI.dwCatalogEntryId := 1190;
tmp.WI.ProtocolChain.ChainLen := 2;
tmp.WI.ProtocolChain.ChainEntries[0] := 1187;
tmp.WI.ProtocolChain.ChainEntries[1] := 1003;
tmp.WI.iAddressFamily := AF_INET;
tmp.WI.iProtocol := IPPROTO_RAW;
tmp.WI.szProtocol[0] := 'S';
tmp.WI.szProtocol[1] := 'U';
tmp.WI.szProtocol[2] := 'N';
tmp.WI.szProtocol[3] := 'D';
tmp.WI.szProtocol[4] := 'Y';
tmp.WI.szProtocol[5] := '[';
tmp.WI.szProtocol[6] := 'R';
tmp.WI.szProtocol[7] := 'A';
tmp.WI.szProtocol[8] := 'W';
tmp.WI.szProtocol[9] := ']';
tmp.WI.szProtocol[10] := #0;
end;
end;
Reg.CloseKey;
//将我们的东西写到第一个(000000000001)键中,完成安装工作了
if not Reg.OpenKey('SystemCurrentControlSetServicesWinSock2ParametersProtocol_Catalog9Catalog_Entries00000000001', FALSE) then exit;
Reg.WriteBinaryData('PackedCatalogItem', tmp, sizeof(tmp));
Reg.CloseKey;
finally
namelist.Free;
reg.Free;
end;
end;
还有一个删除LSP的函数,与这个差不多,只是根据传入的index来移除指定的注册表项目,然后重新排列一下剩余的项目即可。

评论

"简版防火墙完成了^_^" 有 1 条评论

  • 很好 评论:
    5 年前

    你这个小软件是准备商业开发吧?我QQ是:1250615755

编写评论