Jump to content


Photo

Cómo controlar el acceso de clientes a mi server por ip y clave maestra.

APP Cliente - Servidor

13 replies to this topic

#1 retxel

retxel

    Newbie

  • Miembros
  • Pip
  • 2 posts

Posted 08 November 2016 - 01:04 AM

   Hola, Podría realizarse un par de sencillas aplicaciones Cliente - Servidor con el objetivo de intermediar en el acceso o no entre una PC cliente y PC servidor (como función de server, no un server oficial, cliente de win normal como win7 8, etc), chequeando la ip del cliente y una clave maestra encriptada. Si una pc cliente tiene ejecutada la app cliente el app servidor  del pc servidor chequea dicha clave y registra en un listado la ip autorizada dejándola pasar para realizar sus peticiones, si otra pc cliente quiere acceder a dicho servidor y no tiene ejecutada esta app cliente será denegado su acceso por su ip, hasta que la ejecute. Las Pc clientes que hayan sido autorizadas a seguir hacia el pc servidor se chequerán cada 30 seg que tenga abierta la app cliente, si alguna cierra dicha app será expulsada de la lista y se denegará el acceso al servidor pc hasta que ejecute nuevamente la app cliente.

 

    El objetivo de esta pareja de app Cliente - Servidor es validar el acceso de una pc a otra mediante una condición. Estas se pueden utilizar en miles de casos, sobre todos entre aplicaciones de terceros como intermediario imponiendo una condición.


  • 0

#2 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 08 November 2016 - 07:30 PM

Sin más información del "servidor oficial" que es el que debe o no aceptar la IP del cliente en cuestión y no sabemos si disponemos del código fuente ni el protocolo que usa, se me ocurre hacer un Hook a dos APIs para controlar los protocolos TCP y UDP. Para el primero será a recv de la que obtendremos la IP del cliente a través del soket de comunicación. Para el segundo caso a recvfrom de la que obtendremos la IP en cuestión sin problemas. La IP del cliente la buscaremos en la lista blanca y si no existe denegamos la lectura de datos devolviendo -1.

 

Otra posibilidad es jugar con la tabla ARP.

 

Saludos.


  • 1

#3 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 13 November 2016 - 06:11 PM

Voy a poner un ejemplo de un sistema de bloqueo de IPs.
 
El protocolo será del cliente-servidor TCP para que sea seguro.
 
Hay que diseñar un cliente que se ejecutará en la máquina que deseamos bloquear si durante un tiempo no se conecta, para ello, el cliente enviará un mensaje a su servidor con una palabra clave cada cierto tiempo. He elegido algo simple: "HOLA" cada 500 milisegundos.
El servidor estará atendiendo conexiones, leyendo la palabra clave y si es correcta añadirá la IP del cliente a una lista junto con la hora de conexión. Tras esto cierra la conexión y espera otra nueva para hacer lo mismo.
Será necesaria una dll que se inyectará en el "servidor oficial" para dotarle de la capacidad de bloquear las conexiones de las IP que cierran su cliente. Daremos un margen de 30 segundos tras el cierre del cliente.
Para cumplir su labor, la dll hace un Hook a las APis siguientes:
  recv
  recvfrom
  WSARecv
  WSARecvEx
  WSARecvFrom

Si bien a las dos primeras, recv y recvfrom, no haría falta pues terminan en sus correspondientes WSA y de hecho no son hookeables, las dejo como muestra didáctica.
 
Cada Hook comprueba si la IP de procedencia concuerda con una en la lista blanca de permitidas, las que alguna vez se conectaron. A su vez, comprueba la hora de última conexión, si pasaron más de 30 segundos bloquea la API devolviendo un error  WSAETIMEDOUT, esto provocará que el servidor cierre dicha conexión. El sistema es válido para protocolo TCP y UDP del "servidor oficial"

Aclarar que el cliente del ejemplo se conecta al localhost, en pruebas reales habrá que resolver la dirección del servidor allí donde esté.

Ahora un poco de código:
 
El cliente:

delphi
  1. Unit UPassClient;
  2.  
  3. interface
  4.  
  5. uses
  6. SysUtils,
  7. Windows,
  8. Messages,
  9. winsock;
  10.  
  11. procedure Client;
  12.  
  13. const
  14. Port: DWORD = 9999;
  15. Server: PCHAR = 'localhost';
  16. var
  17. Terminated: BOOL = false;
  18.  
  19. implementation
  20.  
  21. function Recv_(Sock: TSOCKET; var Buffer; Size, flags, TimeOut: integer): integer;
  22. var
  23. FDSet: WinSock.TFDSET;
  24. TimeVal: WinSock.TTIMEVAL;
  25. begin
  26. TimeVal.tv_sec:= TimeOut div 1000;
  27. TimeVal.tv_usec:= TimeOut mod 1000;
  28. FD_ZERO(FDSet);
  29. FD_SET(Sock, FDSet);
  30.  
  31. Result:= 0;
  32. // Comprobamos si ha recibido algun mensaje
  33. if Winsock.select(0, @FDSet, nil, nil, @TimeVal) > 0 then
  34. Result:= recv(Sock, Buffer, Size, flags)
  35. else
  36. WSASetLastError(WSAETIMEDOUT);
  37. end;
  38.  
  39. function Send_(Sock: TSOCKET; var Buffer; Size, flags, TimeOut: integer): integer;
  40. var
  41. FDSet: WinSock.TFDSET;
  42. TimeVal: WinSock.TTIMEVAL;
  43. begin
  44. TimeVal.tv_sec:= TimeOut div 1000;
  45. TimeVal.tv_usec:= TimeOut mod 1000;
  46. FD_ZERO(FDSet);
  47. FD_SET(Sock, FDSet);
  48.  
  49. Result:= 0;
  50. // Comprobamos si se puede enviar el mensaje
  51. if select(0, nil, @FDSet, nil, @TimeVal) > 0 then
  52. Result:= send(Sock, Buffer, Size, flags)
  53. else
  54. WSASetLastError(WSAETIMEDOUT);
  55. end;
  56.  
  57. function Connect_(IP: PCHAR; Port: DWORD): TSOCKET;
  58. var
  59. host: Phostent;
  60. direc: sockaddr_in;
  61. Error: boolean;
  62. begin
  63. Error:= true;
  64. Result:= Winsock.socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  65. if(Result <> -1) then
  66. begin
  67. //Dirección IP del servidor y Puerto
  68. host:= gethostbyname(IP);
  69. if host <> nil then
  70. begin
  71. direc.sin_family:= AF_INET;
  72. direc.sin_port:= htons(Port);
  73. direc.sin_addr.S_addr:= PInAddr(host.h_addr_list^)^.S_addr;
  74. ZeroMemory(@direc.sin_zero[0], 8);
  75. if Winsock.Connect(Result, direc, sizeof(direc)) <> -1 then
  76. Error:= false;
  77. end;
  78. if Error then
  79. begin
  80. closesocket(Result);
  81. Result:= -1;
  82. end;
  83. end;
  84. end;
  85.  
  86. procedure Client;
  87. var
  88. Wsa: WSADATA;
  89. Socket: TSOCKET;
  90. Buffer: array [0..123] of CHAR;
  91. begin
  92. // Inicializamos
  93. if WSAStartup(MAKEWORD(2, 0), Wsa) <> 0 then exit;
  94.  
  95. // Bucle de comunicación
  96. repeat
  97. Socket:= Connect_(PCHAR(Server), Port);
  98. if Socket <> -1 then
  99. lstrcpy(Buffer, 'HOLA'); //Palabra clave de ejemplo
  100. Send_(Socket, Buffer, lstrlen(Buffer)+1, 0, 1000);
  101. Sleep(500);
  102. closesocket(Socket);
  103. until Terminated;
  104. closesocket(Socket);
  105. WSACleanup;
  106. end;
  107.  
  108. end.

El programa cliente completo:

delphi
  1. program PassClient;
  2.  
  3. uses
  4. UPassClient in 'UPassClient.pas';
  5.  
  6.  
  7. begin
  8. Client;
  9. end.

Para no sobrecargar el post, sigo en el siguiente.
 
 
Saludos.
  • 1

#4 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 13 November 2016 - 06:21 PM

El servidor que tiene una función login que, por el momento y para este ejemplo, siempre devuelve true. Deberá implementarse para descifrar la clave y actuar en consecuencia.

 

Cada IP que se conecte se introduce en una Array junto con la hora de conexión en una estructura como esta:


delphi
  1. type
  2. TIPData = record
  3. IP: DWORD;
  4. Time: TDateTime;
  5. end;
  6.  
  7. const
  8. SizeList = 1024*sizeof(TIPData);
  9.  
  10. type
  11. PWhiteList = ^TWhiteList;
  12. TWhiteList = array [0..1023] of TIPData;

El array tiene 1024 entradas, IPs a controlar. Aunque se puede hacer mas largo, no creo que sea muy necesario para una red local. Este array se enviará como un archivo de memoria compartida a la dll que se encarga del bloqueo.

 

Esta es el código del servidor:


delphi
  1. program PassServer;
  2.  
  3. uses
  4. SysUtils,
  5. Windows,
  6. Messages,
  7. winsock,
  8. APIHook,
  9. SharedMemory;
  10.  
  11. //procedure GlobalHook; stdcall external 'ServerHook.dll';
  12.  
  13. type
  14. TIPData = record
  15. IP: DWORD;
  16. Time: TDateTime;
  17. end;
  18.  
  19. const
  20. SizeList = 1024*sizeof(TIPData);
  21.  
  22. type
  23. PWhiteList = ^TWhiteList;
  24. TWhiteList = array [0..1023] of TIPData;
  25.  
  26. const
  27. Port: DWORD = 9999;
  28.  
  29. var
  30. Memory: TSharedMemory;
  31. WhiteList: PWhiteList;
  32. IPCount: integer = 0;
  33. Terminated: BOOL = false;
  34.  
  35. // Obtener la IP desde el Socket
  36. function GetIPFromSoket(Sock: TSOCKET): DWORD;
  37. var
  38. addr: WinSock.sockaddr_in;
  39. addr_size: integer;
  40. begin
  41. addr_size:= sizeof(sockaddr_in);
  42. getpeername(Sock, addr, addr_size);
  43. Result:= addr.sin_addr.S_addr;
  44. end;
  45.  
  46. function Recv_(Sock: TSOCKET; var Buffer; Size, flags, TimeOut: integer): integer;
  47. var
  48. FDSet: WinSock.TFDSET;
  49. TimeVal: WinSock.TTIMEVAL;
  50. begin
  51. TimeVal.tv_sec:= TimeOut div 1000;
  52. TimeVal.tv_usec:= TimeOut mod 1000;
  53. FD_ZERO(FDSet);
  54. FD_SET(Sock, FDSet);
  55.  
  56. Result:= 0;
  57. // Comprobamos si ha recibido algun mensaje
  58. if Winsock.select(0, @FDSet, nil, nil, @TimeVal) > 0 then
  59. Result:= recv(Sock, Buffer, Size, flags)
  60. else
  61. WSASetLastError(WSAETIMEDOUT);
  62. end;
  63.  
  64. function Send_(Sock: TSOCKET; var Buffer; Size, flags, TimeOut: integer): integer;
  65. var
  66. FDSet: WinSock.TFDSET;
  67. TimeVal: WinSock.TTIMEVAL;
  68. begin
  69. TimeVal.tv_sec:= TimeOut div 1000;
  70. TimeVal.tv_usec:= TimeOut mod 1000;
  71. FD_ZERO(FDSet);
  72. FD_SET(Sock, FDSet);
  73.  
  74. Result:= 0;
  75. // Comprobamos si se puede enviar el mensaje
  76. if select(0, nil, @FDSet, nil, @TimeVal) > 0 then
  77. Result:= send(Sock, Buffer, Size, flags)
  78. else
  79. WSASetLastError(WSAETIMEDOUT);
  80. end;
  81.  
  82. procedure AddIP(IP: DWORD);
  83. var
  84. n: integer;
  85. begin
  86. if IPCount < (sizeof(TWhiteList) div sizeof(TIPData))-1 then
  87. begin
  88. for n:= 0 to IPCount-1 do if WhiteList[n].IP = IP then break;
  89. if n >= IPCount then
  90. begin
  91. WhiteList[IPCount].IP:= IP;
  92. WhiteList[IPCount].Time:= Now;
  93. inc(IPCount);
  94. end
  95. else WhiteList[n].Time:= Now;
  96. end;
  97. end;
  98.  
  99. function login(Buffer: PCHAR): BOOL;
  100. begin
  101. result:= true;
  102. end;
  103.  
  104. var
  105. Wsa: WSADATA;
  106. Sock_e, Sock_c: TSOCKET; // Sock de escucha y comunicación
  107. Addr_s, Addr_c: sockaddr_in;
  108. Len: integer;
  109. Buffer: array [0..123] of CHAR;
  110. hLib: HMODULE;
  111. API: Pointer;
  112. begin
  113. IPCount:= 0;
  114. Terminated:= false;
  115.  
  116. Len:= 0;
  117. Memory:= TSharedMemory.Create('_WhiteList_', sizeof(TWhiteList));
  118. WhiteList:= Memory.Buffer;
  119.  
  120. // Inicializamos
  121. if WSAStartup(MAKEWORD(2, 0), Wsa) <> 0 then exit;
  122. //Creamos el socket
  123. Sock_e:= socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  124. if Sock_e <> INVALID_SOCKET then
  125. begin
  126. // Dirección IP y puerto
  127. Addr_s.sin_family:= AF_INET;
  128. Addr_s.sin_addr.s_addr:= INADDR_ANY;
  129. Addr_s.sin_port:= htons(Port);
  130.  
  131. // Asociamos el socket al puerto
  132. if bind(Sock_e, Addr_s, sizeof(sockaddr_in)) <> -1 then
  133. begin
  134. // Bucle principal del servidor
  135. while not Terminated do
  136. begin
  137. // Escuchando puerto
  138. if listen(Sock_e, 1) <> -1 then
  139. begin
  140. //hay una conexión entrante y la aceptamos
  141. Len:= sizeof(sockaddr_in);
  142. Sock_c:= accept(Sock_e, @Addr_c, @Len);
  143. if Sock_c <> INVALID_SOCKET then
  144. begin
  145. //Len:= recv(Sock_c, Buffer, sizeof(Buffer)-1, 0);
  146. Len:= Recv_(Sock_c, Buffer, sizeof(Buffer)-1, 0, 1000);
  147. if Len>0 then
  148. begin
  149. Buffer[Len]:= #0;
  150. if login(Buffer) then
  151. AddIP(GetIPFromSoket(Sock_c));
  152. end;
  153. closesocket(Sock_c);
  154. end;
  155. end;
  156. end; // listen
  157. end; // if(bind)
  158. closesocket(Sock_e);
  159. end; // if(Sock_e)
  160. WSACleanup;
  161. end.

La dll que se encargará del control de bloqueo la mando en la siguiente entrega.

 

 

Saludos.


  • 1

#5 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 13 November 2016 - 06:35 PM

La dll que habilita el bloqueo de IPs no permitidas
 


delphi
  1. library ServerHook;
  2.  
  3. uses
  4. SysUtils,
  5. Windows,
  6. winsock,
  7. APIHook,
  8. SharedMemory;
  9.  
  10. type
  11. TIPData = record
  12. IP: DWORD;
  13. Time: TDateTime;
  14. end;
  15. PWhiteList = ^TWhiteList;
  16. TWhiteList = array [0..1023] of TIPData;
  17.  
  18. const
  19. SizeMemory: DWORD = sizeof(TWhiteList);
  20. TimeBlock: WORD = 30; //segundos sin conexión -> Bloqueo
  21.  
  22. type
  23.  
  24. Precv = function(S: TSOCKET; var buf: CHAR; len, flags: integer): integer; stdcall;
  25. Precvfrom = function(s: TSOCKET; var buf: CHAR; len, flags: integer; var from: Tsockaddr; fromlen: integer): integer; stdcall;
  26. PWSARECV = function (s: TSOCKET; lpBuffers: Pointer; dwBufferCount: DWORD; lpNumberOfBytesRecvd: LPDWORD; lpFlags: LPDWORD; lpOverlapped: Pointer; lpCompletionRoutine: Pointer): integer; stdcall;
  27. PWSARECVFROM = function(s: TSOCKET; lpBuffers: Pointer; dwBufferCount: DWORD; lpNumberOfBytesRecvd: LPDWORD; lpFlags: LPDWORD; lpfrom: Psockaddr; lpFromlen: PINT; lpOverlapped, lpCompletionRoutine: Pointer): integer; stdcall;
  28. PWSARECVEX = function(s: TSOCKET; buf: PCHAR; len: integer; flags: Pinteger): integer; PASCAL;
  29.  
  30. var
  31. Oldrecv: Precv = nil;
  32. Oldrecvfrom : Precvfrom = nil;
  33. OldWSARecv: PWSARECV = nil;
  34. OldWSARecvEx: PWSARECVEX = nil;
  35. OldWSARecvFrom: PWSARECVFROM = nil;
  36.  
  37. WinHook: HHOOK = 0;
  38. Memory: TSharedMemory;
  39. WhiteList: PWhiteList;
  40.  
  41. //----------------------------------------------------------------------------
  42. // Obtener la IP desde el Socket
  43. function GetIPFromSoket(Sock: TSOCKET): DWORD;
  44. var
  45. addr: WinSock.sockaddr_in;
  46. addr_size: integer;
  47. begin
  48. addr_size:= sizeof(sockaddr_in);
  49. getpeername(Sock, addr, addr_size);
  50. Result:= addr.sin_addr.S_addr;
  51. end;
  52.  
  53. // Busca un IP con más de un tiempo determinado sin conexión
  54. function BlockIP(IP: DWORD): BOOL;
  55. var
  56. n: integer;
  57. IPCount: integer;
  58. begin
  59. Result:= TRUE;
  60. WhiteList:= Memory.Buffer;
  61. IPCount:= sizeof(TWhiteList) div sizeof(TIPData);
  62. for n:= 0 to IPCount-1 do
  63. begin
  64. if WhiteList[n].IP = 0 then break;
  65. if WhiteList[n].IP = IP then
  66. // Si hace más de 30 segundos que no se conecta lo bloqueo
  67. if Now - WhiteList[0].Time < TimeBlock/(24*3600) then
  68. begin
  69. Result:= FALSE;
  70. Exit;
  71. end;
  72. end;
  73. end;
  74.  
  75. //----------------------------------------------------------------------------
  76. // La APIs Hookeadas
  77. function NewWSARecv(s: TSOCKET; lpBuffers: Pointer; dwBufferCount: DWORD; lpNumberOfBytesRecvd: LPDWORD; lpFlags: LPDWORD; lpOverlapped: Pointer; lpCompletionRoutine: Pointer): integer; stdcall;
  78. begin
  79. if BlockIP(GetIPFromSoket(S)) then
  80. begin
  81. Result:= WSAETIMEDOUT;
  82. WSASetLastError(WSAETIMEDOUT);
  83. lpNumberOfBytesRecvd^:= DWORD(-1);
  84. end
  85. else
  86. Result:= OldWSARecv(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine);
  87. end;
  88.  
  89. function NewWSARecvEx(S: TSOCKET; buf: PCHAR; len: integer; flags: Pinteger): integer; PASCAL;
  90. begin
  91. Result:= SOCKET_ERROR;
  92. if BlockIP(GetIPFromSoket(S)) then
  93. WSASetLastError(WSAETIMEDOUT)
  94. else
  95. Result:= OldWSARecvEx(S, buf, len, flags);
  96. end;
  97.  
  98. function NewWSARecvFrom(s: TSOCKET; lpBuffers: Pointer; dwBufferCount: DWORD; lpNumberOfBytesRecvd: LPDWORD; lpFlags: LPDWORD; lpfrom: Psockaddr; lpFromlen: PINT; lpOverlapped, lpCompletionRoutine: Pointer): integer; stdcall;
  99. begin
  100. if (lpfrom.sin_addr.S_addr <> 0) and BlockIP(lpfrom.sin_addr.S_addr) then
  101. begin
  102. Result:= WSAETIMEDOUT;
  103. WSASetLastError(WSAETIMEDOUT);
  104. lpNumberOfBytesRecvd^:= DWORD(-1);
  105. end
  106. else
  107. Result:= OldWSARecvFrom(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpfrom, lpFromlen, lpOverlapped, lpCompletionRoutine);
  108. end;
  109.  
  110. function NewRecv(S: TSOCKET; var buf: CHAR; len, flags: integer): integer; stdcall;
  111. begin
  112. Result:= SOCKET_ERROR;
  113. if BlockIP(GetIPFromSoket(S), ) then
  114. WSASetLastError(WSAETIMEDOUT)
  115. else
  116. Result:= OldRecv(S, buf, len, flags);
  117. end;
  118.  
  119. function NewRecvfrom(s: TSOCKET; var buf: CHAR; len, flags: integer; var from: Tsockaddr; fromlen: integer): integer; stdcall;
  120. begin
  121. Result:= SOCKET_ERROR;
  122. if BlockIP(from.sin_addr.S_addr) then
  123. WSASetLastError(WSAETIMEDOUT)
  124. else
  125. Result:= OldRecvfrom(s, buf, len, flags, from, fromlen);
  126. end;
  127.  
  128.  
  129. //----------------------------------------------------------------------------
  130. // Instalando los Hooks a las API
  131. procedure InstallHooks;
  132. begin
  133. InstallHook(@NewRecv, @OldRecv, 'Ws2_32.dll', 'recv', true);
  134. InstallHook(@NewRecvfrom, @OldRecvfrom, 'Ws2_32.dll', 'recvfrom', true);
  135. InstallHook(@NewWSARecv, @OldWSARecv, 'Ws2_32.dll', 'WSARecv', true);
  136. InstallHook(@NewWSARecvEx, @OldWSARecvEx, 'Mswsock.dll', 'WSARecvEx', true);
  137. InstallHook(@NewWSARecvFrom, @OldWSARecvFrom, 'Ws2_32.dll', 'WSARecvFrom', true);
  138. end;
  139.  
  140. //----------------------------------------------------------------------------
  141. // Desinstalando todos los Hooks
  142. procedure UnInstallHooks;
  143. begin
  144. UnInstallHook(@OldRecv, 'Ws2_32.dll', 'recv');
  145. UnInstallHook(@OldRecvfrom, 'Ws2_32.dll', 'recvfrom');
  146. UnInstallHook(@OldWSARecv, 'Ws2_32.dll', 'WSARecv');
  147. UnInstallHook(@OldWSARecvEx, 'Mswsock.dll', 'WSARecvEx');
  148. UnInstallHook(@OldWSARecvFrom, 'Ws2_32.dll', 'WSARecvFrom');
  149. end;
  150.  
  151. procedure DllMain(reason: integer);
  152. begin
  153. case reason of
  154. DLL_PROCESS_ATTACH:
  155. begin
  156. Memory:= TSharedMemory.Create('_WhiteList_', sizeof(TWhiteList));
  157. InstallHooks;
  158. end;
  159. DLL_PROCESS_DETACH:
  160. begin
  161. UnInstallHooks;
  162. Memory.Free;
  163. end;
  164. end;
  165. end;
  166.  
  167. begin
  168. DllProc := @DllMain;
  169. DllProc(DLL_PROCESS_ATTACH);
  170. end.

 
Esta dll debe ser inyectada en el "servidor oficial" dotándole de la capacidad de bloquear las IPs que no estén en la lista blanca o que haga más de 30 segundos desde su última conexión, es decir, las díscolas que eliminaron su cliente validador. Ahora queda pensarse que más cosas hará el cliente validador y la verdadera razón de su existencia en el PC que queremos validar.

 

Todo el sistema esta probado en un WinXP y Win10 contra un "servidor oficial" compilado a 32 bits para los protocolos TCP y UDP.

 

Espero que esta estrategia y su código, de respuesta a la necesidad que hizo abrir el tema y que sea de interés general.

 

 

 

Saludos.


  • 1

#6 Dante

Dante

    Advanced Member

  • Miembros
  • PipPipPip
  • 89 posts

Posted 14 November 2016 - 09:00 AM

Eres un genio


  • 0

#7 Dante

Dante

    Advanced Member

  • Miembros
  • PipPipPip
  • 89 posts

Posted 16 November 2016 - 10:47 AM

Ya probe el codigo pero al llebarlo a una GUI me conjela la ventana y no puedo hacer mas nada, intente hacer un hilo de ejecucion aparte para esto pero me da un error al  tratar de detener el server.


delphi
  1. unit Hilo;
  2.  
  3. interface
  4. uses
  5. Windows, Messages, SysUtils, Variants, Graphics, Controls, Forms,
  6. Dialogs, StdCtrls,
  7. Classes, winsock, APIHook, SharedMemory;
  8.  
  9. type
  10. TServerStar = class(TThread)
  11. private
  12. port: DWORD;
  13.  
  14. protected
  15. procedure Execute; override;
  16.  
  17. public
  18. procedure Salir;
  19. constructor Create(Ports :DWORD);
  20. end;
  21.  
  22.  
  23.  
  24.  
  25.  
  26. implementation
  27.  
  28. type
  29. TIPData = record
  30. IP: DWORD;
  31. Time: TDateTime;
  32. end;
  33.  
  34. PWhiteList = ^TWhiteList;
  35. TWhiteList = array [0..1023] of TIPData;
  36. const
  37. SizeList = 1024*sizeof(TIPData);
  38.  
  39. var
  40. Memory: TSharedMemory;
  41. WhiteList: PWhiteList;
  42. IPCount: integer = 0;
  43. terminar: Boolean;
  44.  
  45.  
  46. constructor TServerStar.Create(PortS: DWORD);
  47. begin
  48. inherited Create(True);
  49. port := PortS;
  50. end;
  51.  
  52.  
  53.  
  54. // Obtener la IP desde el Socket
  55. function GetIPFromSoket(Sock: TSOCKET): DWORD;
  56. var
  57. addr: WinSock.sockaddr_in;
  58. addr_size: integer;
  59. begin
  60. addr_size:= sizeof(sockaddr_in);
  61. getpeername(Sock, addr, addr_size);
  62. Result:= addr.sin_addr.S_addr;
  63. end;
  64.  
  65. function Recv_(Sock: TSOCKET; var Buffer; Size, flags, TimeOut: integer): integer;
  66. var
  67. FDSet: WinSock.TFDSET;
  68. TimeVal: WinSock.TTIMEVAL;
  69. begin
  70. TimeVal.tv_sec:= TimeOut div 1000;
  71. TimeVal.tv_usec:= TimeOut mod 1000;
  72. FD_ZERO(FDSet);
  73. FD_SET(Sock, FDSet);
  74.  
  75. Result:= 0;
  76. // Comprobamos si ha recibido algun mensaje
  77. if Winsock.select(0, @FDSet, nil, nil, @TimeVal) > 0 then
  78. Result:= recv(Sock, Buffer, Size, flags)
  79. else
  80. WSASetLastError(WSAETIMEDOUT);
  81. end;
  82.  
  83. function Send_(Sock: TSOCKET; var Buffer; Size, flags, TimeOut: integer): integer;
  84. var
  85. FDSet: WinSock.TFDSET;
  86. TimeVal: WinSock.TTIMEVAL;
  87. begin
  88. TimeVal.tv_sec:= TimeOut div 1000;
  89. TimeVal.tv_usec:= TimeOut mod 1000;
  90. FD_ZERO(FDSet);
  91. FD_SET(Sock, FDSet);
  92.  
  93. Result:= 0;
  94. // Comprobamos si se puede enviar el mensaje
  95. if select(0, nil, @FDSet, nil, @TimeVal) > 0 then
  96. Result:= send(Sock, Buffer, Size, flags)
  97. else
  98. WSASetLastError(WSAETIMEDOUT);
  99. end;
  100.  
  101. procedure AddIP(IP: DWORD);
  102. var
  103. n: integer;
  104. begin
  105. if IPCount < (sizeof(TWhiteList) div sizeof(TIPData))-1 then
  106. begin
  107. for n:= 0 to IPCount-1 do if WhiteList[n].IP = IP then break;
  108. if n >= IPCount then
  109. begin
  110. WhiteList[IPCount].IP:= IP;
  111. WhiteList[IPCount].Time:= Now;
  112. inc(IPCount);
  113. end
  114. else WhiteList[n].Time:= Now;
  115. end;
  116. end;
  117.  
  118. function login(Buffer: PCHAR): BOOL;
  119. begin
  120. result:= True;
  121. end;
  122.  
  123.  
  124. procedure TServerStar.Execute;
  125. var
  126. Wsa: WSADATA;
  127. Sock_e, Sock_c: TSOCKET; // Sock de escucha y comunicación
  128. Addr_s, Addr_c: sockaddr_in;
  129. Len: integer;
  130. Buffer: array [0..123] of CHAR;
  131. hLib: HMODULE;
  132. API: Pointer;
  133.  
  134. begin
  135. IPCount:= 0;
  136. Len:= 0;
  137. terminar:=False;
  138. Memory:= TSharedMemory.Create('_WhiteList_', sizeof(TWhiteList));
  139. WhiteList:= Memory.Buffer;
  140.  
  141. // Inicializamos
  142. if WSAStartup(MAKEWORD(2, 0), Wsa) <> 0 then exit;
  143. //Creamos el socket
  144. Sock_e:= socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  145. if Sock_e <> INVALID_SOCKET then
  146. begin
  147. // Dirección IP y puerto
  148. Addr_s.sin_family:= AF_INET;
  149. Addr_s.sin_addr.s_addr:=INADDR_ANY;
  150. Addr_s.sin_port:= htons(port);
  151.  
  152. // Asociamos el socket al puerto
  153. if bind(Sock_e, Addr_s, sizeof(sockaddr_in)) <> -1 then
  154. begin
  155. // Bucle principal del servidor
  156. //MessageBox(0,'hola','terminar',MB_OK);
  157.  
  158. while not terminar do
  159. begin
  160.  
  161. // MessageBox(0,'hola','111',MB_OK);
  162. // Escuchando puerto
  163. if listen(Sock_e, 1) <> -1 then
  164. begin
  165. //hay una conexión entrante y la aceptamos
  166. Len:= sizeof(sockaddr_in);
  167. Sock_c:= accept(Sock_e, @Addr_c, @Len);
  168. if Sock_c <> INVALID_SOCKET then
  169. begin
  170. //Len:= recv(Sock_c, Buffer, sizeof(Buffer)-1, 0);
  171. Len:= Recv_(Sock_c, Buffer, sizeof(Buffer)-1, 0, 1000);
  172. if Len>0 then
  173. begin
  174. Buffer[Len]:= #0;
  175. if login(Buffer) then
  176. AddIP(GetIPFromSoket(Sock_c));
  177. end;
  178. closesocket(Sock_c);
  179. end;
  180. end;
  181.  
  182. // MessageBox(0,'hola1','mio',MB_OK);
  183. end; // listen
  184.  
  185. end; // if(bind)
  186.  
  187. closesocket(Sock_e);
  188. end; // if(Sock_e)
  189. WSACleanup;
  190. end;
  191.  
  192.  
  193. procedure TServerStar.Salir();
  194. begin
  195. terminar := true;
  196. if terminar then MessageBox(0,'Salir','si',MB_OK);
  197.  
  198. end;
  199.  
  200.  
  201. end.


  • 0

#8 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 16 November 2016 - 10:59 AM

Efectivamente hay que colocarlo en un hilo distinto al principal y establecer un Mutex para acceder a un área y de memoria con las aplicaciones a proteger. En cuanto tenga un rato te muestro un ejemplo de como llevarlo a un GUI con un thread a bajo nivel.

 

El programa permitirá elegir en un entorno gráfico lis nombres de aplicaciones a protegerente que enviará a la red local.  Los clientes recibirán la información y actuarán en consecuencia.

 

Saludos.


  • 1

#9 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 16 November 2016 - 06:57 PM

No he compilado tu código pero la solución viene por aquí:
 


delphi
  1. procedure TServerStar.Salir();
  2. begin
  3. if MessageBox(0,'Server','¿Salir?',MB_YESNO) = IDOK then
  4. begin
  5. terminar := true;
  6. WSACleanup;
  7. end;
  8. end;

Ha preparado un ejemplo funcional de una aplicación que permite elegir una serie de ejecutables que queremos protejer y un "Servidor Oficial" que bloquearemos si el cliente no se conecta por más de 30 segundos. El programa inyectará una dll que permite el bloqueo del servidor y lo desinyecta al salir.

 

Dispone de un hilo con un servidor que se comunica con los clientes y les envía una lista de programas que deben proteger, los clientes deberán hacer su tarea.

 

Para comunicar el hilo principal de la aplicación con el servidor, uso un mutex que permite acceder a ambos a la lista de programas de manera sincronizada. El servidor envía a la dll una lista blanca de IPs con cliente activo y la dll habilita al "Servidor Oficial" para bloquear a las que no estén en esa lista.

 

Así hace el hilo principal:


delphi
  1. procedure TForm1.Send;
  2. var
  3. i: integer;
  4. Name: PCHAR;
  5. begin
  6. // Mandamos al sistema de protección los ejecutables a protejer
  7. // Esperamos a tener control del Mutex antes de aceder a datos del hilo principal
  8. if WaitForSingleObject(Mutex, INFINITE) = WAIT_OBJECT_0 then
  9. begin
  10. Name:= NamesToProtect;
  11. for i:= 0 to ListView1.Items.Count -1 do
  12. begin
  13. lstrcpy(Name, PCHAR(ListView1.Items[i].Caption));
  14. inc(Name, lstrlen(Name)+1);
  15. end;
  16. Name^:= #0;
  17. end;
  18. // Cedemos el control del Mutex
  19. ReleaseMutex(Mutex);
  20. end;

Y esto hace el servidor:


delphi
  1. procedure SendProcessNames(Socket: TSOCKET);
  2. var
  3. i: DWORD;
  4. Name: PCHAR;
  5. begin
  6. if WaitForSingleObject(Mutex, INFINITE) = WAIT_OBJECT_0 then
  7. begin
  8. Name:= NamesToProtect;
  9. i:= 0;
  10. while (Name^ <> #0) and (i < MAX_PID) do
  11. begin
  12. Send_(Socket, Name^, lstrlen(Name)+1, 0, 1000);
  13. inc(i);
  14. inc(Name, lstrlen(Name)+1);
  15. end;
  16. end;
  17. ReleaseMutex(Mutex);
  18. end;

La lista de programas se guarda en el PC servidor de forma encriptada en un archivo

Todo está escrito a bajo nivel excepto la parte visual.

 

El código de la unidad servidor es este:


delphi
  1. Unit UPassServer;
  2.  
  3. interface
  4.  
  5. uses
  6. SysUtils,
  7. Windows,
  8. Messages,
  9. winsock,
  10. Usend,
  11. SharedMemory;
  12.  
  13. const
  14. Port: DWORD = 6666;
  15.  
  16. type
  17. PWhiteList = ^TWhiteList;
  18. TWhiteList = array [0..1023] of TIPData;
  19.  
  20. var
  21. Memory: TSharedMemory;
  22. MemorySend: TSharedMemory;
  23. WhiteList: PWhiteList;
  24. IPCount: integer = 0;
  25. Terminated: BOOL = false;
  26. hThread: THANDLE = 0;
  27. ThreadId: DWORD = 0;
  28. Mutex: THANDLE;
  29.  
  30. procedure Server;
  31. procedure StopServer;
  32. procedure StartThServer;
  33.  
  34. implementation
  35.  
  36.  
  37. // Obtener la IP desde el Socket
  38. function GetIPFromSoket(Sock: TSOCKET): DWORD;
  39. var
  40. addr: WinSock.sockaddr_in;
  41. addr_size: integer;
  42. begin
  43. addr_size:= sizeof(sockaddr_in);
  44. getpeername(Sock, addr, addr_size);
  45. Result:= addr.sin_addr.S_addr;
  46. end;
  47.  
  48. function Recv_(Sock: TSOCKET; var Buffer; Size, flags, TimeOut: integer): integer;
  49. var
  50. FDSet: WinSock.TFDSET;
  51. TimeVal: WinSock.TTIMEVAL;
  52. begin
  53. TimeVal.tv_sec:= TimeOut div 1000;
  54. TimeVal.tv_usec:= TimeOut mod 1000;
  55. FD_ZERO(FDSet);
  56. FD_SET(Sock, FDSet);
  57.  
  58. Result:= 0;
  59. // Comprobamos si ha recibido algun mensaje
  60. if Winsock.select(0, @FDSet, nil, nil, @TimeVal) > 0 then
  61. Result:= recv(Sock, Buffer, Size, flags)
  62. else
  63. WSASetLastError(WSAETIMEDOUT);
  64. end;
  65.  
  66. function Send_(Sock: TSOCKET; var Buffer; Size, flags, TimeOut: integer): integer;
  67. var
  68. FDSet: WinSock.TFDSET;
  69. TimeVal: WinSock.TTIMEVAL;
  70. begin
  71. TimeVal.tv_sec:= TimeOut div 1000;
  72. TimeVal.tv_usec:= TimeOut mod 1000;
  73. FD_ZERO(FDSet);
  74. FD_SET(Sock, FDSet);
  75.  
  76. Result:= 0;
  77. // Comprobamos si se puede enviar el mensaje
  78. if select(0, nil, @FDSet, nil, @TimeVal) > 0 then
  79. Result:= send(Sock, Buffer, Size, flags)
  80. else
  81. WSASetLastError(WSAETIMEDOUT);
  82. end;
  83.  
  84. procedure AddIP(IP: DWORD);
  85. var
  86. n: integer;
  87. begin
  88. if IPCount < (sizeof(TWhiteList) div sizeof(TIPData))-1 then
  89. begin
  90. for n:= 0 to IPCount-1 do if WhiteList[n].IP = IP then break;
  91. if n >= IPCount then
  92. begin
  93. WhiteList[IPCount].IP:= IP;
  94. WhiteList[IPCount].Time:= Now;
  95. inc(IPCount);
  96. end
  97. else WhiteList[n].Time:= Now;
  98. end;
  99. end;
  100.  
  101. function login(Buffer: PCHAR): BOOL;
  102. begin
  103. result:= true;
  104. end;
  105.  
  106. procedure SendProcessNames(Socket: TSOCKET);
  107. var
  108. i: DWORD;
  109. Name: PCHAR;
  110. begin
  111. if WaitForSingleObject(Mutex, INFINITE) = WAIT_OBJECT_0 then
  112. begin
  113. Name:= NamesToProtect;
  114. i:= 0;
  115. while (Name^ <> #0) and (i < MAX_PID) do
  116. begin
  117. Send_(Socket, Name^, lstrlen(Name)+1, 0, 1000);
  118. inc(i);
  119. inc(Name, lstrlen(Name)+1);
  120. end;
  121. end;
  122. ReleaseMutex(Mutex);
  123. end;
  124.  
  125. procedure Server;
  126. var
  127. Wsa: WSADATA;
  128. Sock_e, Sock_c: TSOCKET; // Sock de escucha y comunicación
  129. Addr_s, Addr_c: sockaddr_in;
  130. Len: integer;
  131. Buffer: array [0..123] of CHAR;
  132. hLib: HMODULE;
  133. API: Pointer;
  134. begin
  135. IPCount:= 0;
  136. Terminated:= false;
  137.  
  138. Len:= 0;
  139. Memory:= TSharedMemory.Create('_WhiteList_', sizeof(TWhiteList));
  140. MemorySend:= TSharedMemory.Create('_AntiInjector_', MemSize);
  141. WhiteList:= Memory.Buffer;
  142.  
  143. // Inicializamos
  144. if WSAStartup(MAKEWORD(2, 0), Wsa) <> 0 then exit;
  145. //Creamos el socket
  146. Sock_e:= socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  147. if Sock_e <> INVALID_SOCKET then
  148. begin
  149. // Dirección IP y puerto
  150. Addr_s.sin_family:= AF_INET;
  151. Addr_s.sin_addr.s_addr:= INADDR_ANY;
  152. Addr_s.sin_port:= htons(Port);
  153.  
  154. // Asociamos el socket al puerto
  155. if bind(Sock_e, Addr_s, sizeof(sockaddr_in)) <> -1 then
  156. begin
  157. // Bucle principal del servidor
  158. while not Terminated do
  159. begin
  160. // Escuchando puerto
  161. if listen(Sock_e, 1) <> -1 then
  162. begin
  163. //hay una conexión entrante y la aceptamos
  164. Len:= sizeof(sockaddr_in);
  165. Sock_c:= accept(Sock_e, @Addr_c, @Len);
  166. if Sock_c <> INVALID_SOCKET then
  167. begin
  168. //Len:= recv(Sock_c, Buffer, sizeof(Buffer)-1, 0);
  169. Len:= Recv_(Sock_c, Buffer, sizeof(Buffer)-1, 0, 1000);
  170. if Len>0 then
  171. begin
  172. Buffer[Len]:= #0;
  173. if login(Buffer) then
  174. begin
  175. AddIP(GetIPFromSoket(Sock_c));
  176. SendProcessNames(Sock_c);
  177. end;
  178. end;
  179. closesocket(Sock_c);
  180. end;
  181. end;
  182. end; // listen
  183. end; // if(bind)
  184. closesocket(Sock_e);
  185. end; // if(Sock_e)
  186. WSACleanup;
  187. end;
  188.  
  189. function ThServer(Param: Pointer): DWORD; stdcall;
  190. begin
  191. Server;
  192. Result:= 0;
  193. end;
  194.  
  195. procedure StopServer;
  196. begin
  197. Terminated:= true;
  198. WSACleanup;
  199. WaitForSingleObject(hThread, INFINITE);
  200. CloseHandle(hThread);
  201. end;
  202.  
  203. procedure StartThServer;
  204. begin
  205. hThread:= CreateThread(nil, 0, @ThServer, nil, 0, ThreadId);
  206. end;
  207.  
  208. end.

El de la parte visual es más largo, solo decir que para arrancar el servidor hace esto:


delphi
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. //.......................
  3. // Creamos un Mutex para sincronización de hilos
  4. Mutex:= CreateMutex(nil, false, '_AntiInjectorProtect_');
  5.  
  6. // Ponemos en marcha el servidor
  7. StartThServer;
  8.  
  9. // Enviamos los archivos a la dll
  10. Send;
  11. end;

Al cerrarse hace esto:


delphi
  1. procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
  2. begin
  3. SortIcon.Free;
  4. StopServer;
  5. CloseHandle(Mutex);
  6. UnInyectServer(Edit2.Text);
  7. end;

post-12294-0-22176100-1479344242.jpg

 

Subo el código funcional.

 

 

Saludos.

Attached Files


  • 1

#10 Dante

Dante

    Advanced Member

  • Miembros
  • PipPipPip
  • 89 posts

Posted 17 November 2016 - 07:26 AM

nunca dejas de sorprenderme


  • 0

#11 Dante

Dante

    Advanced Member

  • Miembros
  • PipPipPip
  • 89 posts

Posted 17 November 2016 - 10:10 AM

Quiero ponerle una bd embebida q complemento puedo usar en delphi7 para esto
  • 0

#12 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 17 November 2016 - 10:37 AM

Para una app tan pequeña quizás mejor que una bd, es una tabla plana cómo la que ya usa, aunque en el ejemplo está encriptada. Además te aporta la ventaja de no depender de motores externos.

 

Saludos.


  • 1

#13 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 17 November 2016 - 06:08 PM

Como complemento a todo lo anterior el sistema puede usarse para inyectar desde el cliente una dll similar a la expuesta aquí. Para esconderla, la hardcodeamos previamente. Al ejecutar el cliente, éste la libera y provoca la inyección.

 

Este sería el código del truco:


delphi
  1. program PassClient;
  2.  
  3. uses
  4. Windows,
  5. UPassClient in 'UPassClient.pas',
  6. Hookdll_ in 'Hookdll_.pas';
  7.  
  8. const
  9. DllName: PCHAR = 'Hookdll.dll';
  10.  
  11. procedure GlobalHook; stdcall external 'HookDll';
  12. procedure GlobalUnHook; stdcall external 'HookDll';
  13.  
  14.  
  15. procedure ExtractHookdll;
  16. var
  17. hFile: THANDLE;
  18. begin
  19. hFile:= CreateFile(DllName, GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0);
  20. if hFile <> INVALID_HANDLE_VALUE then
  21. begin
  22. _lwrite(hFile, @Hookdll_Bytes[0], Hookdll_Size);
  23. CloseHandle(hFile);
  24. end;
  25. end;
  26.  
  27. begin
  28. ExtractHookdll;
  29. GlobalHook;
  30. Client;
  31. end.

Con esto tenemos un sistema completo de vigilancia Cliente-Servidor con apoyo de anti-inyecciones en el cliente

 

Subo el código funcional y en armas.

 

 

Saludos.


  • 2

#14 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 18 November 2016 - 06:37 PM

Demos un poco de seguridad al sistema cliente:

 

1.- La dll irá hardcodeada con su Hash MD5, el Hash se comprobará tras crear la dll y si coincide arrancará el cliente.

2.- El nombre de la dll estará encriptado en el código fuente y se desencriptará cuando haga falta.

3.- Dado que la dll puede no estar presente, a la hora de arrancar la app cliente, las funciones usadas de la dll se importan dinámicamente, si falla, no arranca el cliente


delphi
  1. program PassClient;
  2.  
  3. uses
  4.   Windows,
  5.   UPassClient in 'UPassClient.pas',
  6.   Hookdll_ in 'Hookdll_.pas',
  7.   UMD5 in 'UMD5.pas';
  8.  
  9. type
  10.   PGlobalHook   = procedure; stdcall;
  11.   PGlobalUnHook = procedure; stdcall;
  12.  
  13.  
  14. var
  15.  Clave: PCHAR  = '76349714';
  16.  DllName: array [0..11] of CHAR = (#127, #89, #92, #95, #93, #91, #93, #26, #83, #90, #95, #0);
  17.  
  18. //procedure GlobalHook; stdcall external 'HookDll';
  19. //procedure GlobalUnHook; stdcall external 'HookDll';
  20.  
  21. procedure Crypt(Source: Pointer; Size: Cardinal; Password: PCHAR; _Mod: integer);
  22. var
  23.   S: PCHAR;
  24.   len, n: integer;
  25. begin
  26.    S:= Source;
  27.    len:= lstrlen(Password);
  28.    for n:=0 to Size-1 do
  29.    begin
  30.      S[n]:= CHAR(integer(S[n]) xor integer(Password[_Mod mod len]));
  31.      inc(_Mod);
  32.    end;
  33. end;
  34.  
  35. function ExtractHookdll: BOOL;
  36. var
  37.   hFile: THANDLE;
  38.   MD5: TMD5;
  39. begin
  40.   Result:= FALSE;
  41.   hFile:= CreateFile(DllName, GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0);
  42.   if hFile <> INVALID_HANDLE_VALUE then
  43.   begin
  44.     _lwrite(hFile, @Hookdll_Bytes[0], Hookdll_Size);
  45.     CloseHandle(hFile);
  46.     GetMD5FromFile(DllName, MD5);
  47.     Result:= lstrcmpi(Hookdll_MD5, MD5) = 0;
  48.   end;
  49. end;
  50.  
  51.  
  52.  
  53. var
  54.   hLib: HMODULE;
  55.   GlobalHook: PGlobalHook;
  56. begin
  57.   Crypt(@DllName[0], sizeof(DllName)-1, Clave, 0);
  58.   if ExtractHookdll then
  59.   begin
  60.     hLib:= LoadLibrary(DllName);
  61.     if hLib <> 0 then
  62.     begin
  63.       GlobalHook:= GetProcAddress(hLib, 'GlobalHook');
  64.       if @GlobalHook <> nil then
  65.       begin
  66.         GlobalHook;
  67.         Client;
  68.       end;
  69.     end;
  70.   end;
  71. end.

4.- Si queremos añadir otro punto más de seguridad, podemos incluir en la dll una función o procedimiento vital para el cliente que no podrá ejecutarse sin ella presente he íntegra, de esta forma prescindimos de condicionales, Al tener por un lado condicionales y por otro, dependencias, confundimos al cracker y complicamos su trabajo.

 

 

Saludos.

Attached Files


  • 1



Reply to this topic



  


IP.Board spam blocked by CleanTalk.