library ServerHook;
uses
SysUtils,
Windows,
winsock,
APIHook,
SharedMemory;
type
TIPData = record
IP: DWORD;
Time: TDateTime;
end;
PWhiteList = ^TWhiteList;
TWhiteList = array [0..1023] of TIPData;
const
SizeMemory: DWORD = sizeof(TWhiteList);
TimeBlock: WORD = 30; //segundos sin conexión -> Bloqueo
type
Precv = function(S: TSOCKET; var buf: CHAR; len, flags: integer): integer; stdcall;
Precvfrom = function(s: TSOCKET; var buf: CHAR; len, flags: integer; var from: Tsockaddr; fromlen: integer): integer; stdcall;
PWSARECV = function (s: TSOCKET; lpBuffers: Pointer; dwBufferCount: DWORD; lpNumberOfBytesRecvd: LPDWORD; lpFlags: LPDWORD; lpOverlapped: Pointer; lpCompletionRoutine: Pointer): integer; stdcall;
PWSARECVFROM = function(s: TSOCKET; lpBuffers: Pointer; dwBufferCount: DWORD; lpNumberOfBytesRecvd: LPDWORD; lpFlags: LPDWORD; lpfrom: Psockaddr; lpFromlen: PINT; lpOverlapped, lpCompletionRoutine: Pointer): integer; stdcall;
PWSARECVEX = function(s: TSOCKET; buf: PCHAR; len: integer; flags: Pinteger): integer; PASCAL;
var
Oldrecv: Precv = nil;
Oldrecvfrom : Precvfrom = nil;
OldWSARecv: PWSARECV = nil;
OldWSARecvEx: PWSARECVEX = nil;
OldWSARecvFrom: PWSARECVFROM = nil;
WinHook: HHOOK = 0;
Memory: TSharedMemory;
WhiteList: PWhiteList;
//----------------------------------------------------------------------------
// Obtener la IP desde el Socket
function GetIPFromSoket(Sock: TSOCKET): DWORD;
var
addr: WinSock.sockaddr_in;
addr_size: integer;
begin
addr_size:= sizeof(sockaddr_in);
getpeername(Sock, addr, addr_size);
Result:= addr.sin_addr.S_addr;
end;
// Busca un IP con más de un tiempo determinado sin conexión
function BlockIP(IP: DWORD): BOOL;
var
n: integer;
IPCount: integer;
begin
Result:= TRUE;
WhiteList:= Memory.Buffer;
IPCount:= sizeof(TWhiteList) div sizeof(TIPData);
for n:= 0 to IPCount-1 do
begin
if WhiteList[n].IP = 0 then break;
if WhiteList[n].IP = IP then
// Si hace más de 30 segundos que no se conecta lo bloqueo
if Now - WhiteList[0].Time < TimeBlock/(24*3600) then
begin
Result:= FALSE;
Exit;
end;
end;
end;
//----------------------------------------------------------------------------
// La APIs Hookeadas
function NewWSARecv(s: TSOCKET; lpBuffers: Pointer; dwBufferCount: DWORD; lpNumberOfBytesRecvd: LPDWORD; lpFlags: LPDWORD; lpOverlapped: Pointer; lpCompletionRoutine: Pointer): integer; stdcall;
begin
if BlockIP(GetIPFromSoket(S)) then
begin
Result:= WSAETIMEDOUT;
WSASetLastError(WSAETIMEDOUT);
lpNumberOfBytesRecvd^:= DWORD(-1);
end
else
Result:= OldWSARecv(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine);
end;
function NewWSARecvEx(S: TSOCKET; buf: PCHAR; len: integer; flags: Pinteger): integer; PASCAL;
begin
Result:= SOCKET_ERROR;
if BlockIP(GetIPFromSoket(S)) then
WSASetLastError(WSAETIMEDOUT)
else
Result:= OldWSARecvEx(S, buf, len, flags);
end;
function NewWSARecvFrom(s: TSOCKET; lpBuffers: Pointer; dwBufferCount: DWORD; lpNumberOfBytesRecvd: LPDWORD; lpFlags: LPDWORD; lpfrom: Psockaddr; lpFromlen: PINT; lpOverlapped, lpCompletionRoutine: Pointer): integer; stdcall;
begin
if (lpfrom.sin_addr.S_addr <> 0) and BlockIP(lpfrom.sin_addr.S_addr) then
begin
Result:= WSAETIMEDOUT;
WSASetLastError(WSAETIMEDOUT);
lpNumberOfBytesRecvd^:= DWORD(-1);
end
else
Result:= OldWSARecvFrom(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpfrom, lpFromlen, lpOverlapped, lpCompletionRoutine);
end;
function NewRecv(S: TSOCKET; var buf: CHAR; len, flags: integer): integer; stdcall;
begin
Result:= SOCKET_ERROR;
if BlockIP(GetIPFromSoket(S), ) then
WSASetLastError(WSAETIMEDOUT)
else
Result:= OldRecv(S, buf, len, flags);
end;
function NewRecvfrom(s: TSOCKET; var buf: CHAR; len, flags: integer; var from: Tsockaddr; fromlen: integer): integer; stdcall;
begin
Result:= SOCKET_ERROR;
if BlockIP(from.sin_addr.S_addr) then
WSASetLastError(WSAETIMEDOUT)
else
Result:= OldRecvfrom(s, buf, len, flags, from, fromlen);
end;
//----------------------------------------------------------------------------
// Instalando los Hooks a las API
procedure InstallHooks;
begin
InstallHook(@NewRecv, @OldRecv, 'Ws2_32.dll', 'recv', true);
InstallHook(@NewRecvfrom, @OldRecvfrom, 'Ws2_32.dll', 'recvfrom', true);
InstallHook(@NewWSARecv, @OldWSARecv, 'Ws2_32.dll', 'WSARecv', true);
InstallHook(@NewWSARecvEx, @OldWSARecvEx, 'Mswsock.dll', 'WSARecvEx', true);
InstallHook(@NewWSARecvFrom, @OldWSARecvFrom, 'Ws2_32.dll', 'WSARecvFrom', true);
end;
//----------------------------------------------------------------------------
// Desinstalando todos los Hooks
procedure UnInstallHooks;
begin
UnInstallHook(@OldRecv, 'Ws2_32.dll', 'recv');
UnInstallHook(@OldRecvfrom, 'Ws2_32.dll', 'recvfrom');
UnInstallHook(@OldWSARecv, 'Ws2_32.dll', 'WSARecv');
UnInstallHook(@OldWSARecvEx, 'Mswsock.dll', 'WSARecvEx');
UnInstallHook(@OldWSARecvFrom, 'Ws2_32.dll', 'WSARecvFrom');
end;
procedure DllMain(reason: integer);
begin
case reason of
DLL_PROCESS_ATTACH:
begin
Memory:= TSharedMemory.Create('_WhiteList_', sizeof(TWhiteList));
InstallHooks;
end;
DLL_PROCESS_DETACH:
begin
UnInstallHooks;
Memory.Free;
end;
end;
end;
begin
DllProc := @DllMain;
DllProc(DLL_PROCESS_ATTACH);
end.