Ir al contenido



Foto

Encriptando funciones


  • Por favor identifícate para responder
7 respuestas en este tema

#1 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.844 mensajes
  • LocationMadrid - España

Escrito 19 noviembre 2016 - 08:39

Voy a tratar de explicar como proteger una app encriptando una función vital para el programa. La clave de descifrado dependerá de la clave de la licencia.
 
Imaginemos un código como este en el que una función es vital porque importa dinámicamente un procedimiento esencial de una dll:


delphi
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7. Dialogs, StdCtrls;
  8.  
  9. type
  10. TForm1 = class(TForm)
  11. Edit1: TEdit;
  12. Button1: TButton;
  13. procedure FormCreate(Sender: TObject);
  14. private
  15. { Private declarations }
  16. public
  17. { Public declarations }
  18. end;
  19.  
  20. var
  21. Form1: TForm1;
  22.  
  23. type PLogueado = procedure; stdcall;
  24.  
  25. implementation
  26.  
  27. {$R *.dfm}
  28. var
  29. Logueado: PLogueado;
  30.  
  31.  
  32. procedure Vital;
  33. var
  34. hLib: HMODULE;
  35. begin
  36. hLib:= LoadLibrary('UnaDll.dll');
  37. Logueado:= GetProcAddress(hLib, 'Logueado');
  38. if @Logueado <> nil then
  39. Logueado;
  40. end;}
  41.  
  42. procedure TForm1.FormCreate(Sender: TObject);
  43. begin
  44. Vital;
  45. end;
  46.  
  47. end.

Para el ejemplo, esta será la dll:


delphi
  1. library UnaDll;
  2.  
  3. uses
  4. Windows;
  5.  
  6. {$R *.res}
  7.  
  8.  
  9. procedure Logueado;
  10. begin
  11. MessageBox(0, 'El programa funcionará correctamente', 'Eureca', MB_OK);
  12. end;
  13.  
  14. exports
  15. Logueado;
  16.  
  17. begin
  18. end.

 
 
Ahora vamos a cambiar las cosas para encriptar el procedimiento Vital. Añadimos una función o procedimiento de cifrado, otro de descifrado y otro para guardar el binario cifrado de Vital. El procedimiento FinVital hay que dejarlo justo al final de Vital:


delphi
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7.   Dialogs, StdCtrls;
  8.  
  9. type
  10.   TForm1 = class(TForm)
  11.     Edit1: TEdit;
  12.     Button1: TButton;
  13.     procedure FormCreate(Sender: TObject);
  14.   private
  15.     { Private declarations }
  16.   public
  17.     { Public declarations }
  18.   end;
  19.  
  20. var
  21.   Form1: TForm1;
  22.  
  23. type PLogueado = procedure; stdcall;
  24.  
  25. implementation
  26.  
  27. {$R *.dfm}
  28. var
  29. Logueado: PLogueado;
  30.  
  31. // Una función de cifrado simétrico...
  32. procedure Crypt(Source: Pointer; Size: Cardinal; Password: PCHAR; _Mod: integer);
  33. var
  34.   S: PCHAR;
  35.   len, n: integer;
  36. begin
  37.    S:= Source;
  38.    len:= lstrlen(Password);
  39.    for n:=0 to Size-1 do
  40.    begin
  41.      S[n]:= CHAR(integer(S[n]) xor integer(Password[_Mod mod len]));
  42.      inc(_Mod);
  43.    end;
  44. end;
  45.  
  46. procedure Vital;
  47. var
  48.   hLib: HMODULE;
  49. begin
  50.   hLib:= LoadLibrary('UnaDll.dll');
  51.   Logueado:= GetProcAddress(hLib, 'Logueado');
  52.   if @Logueado <> nil then
  53.     Logueado;
  54. end;}
  55. // Este procedimiento inservible nos ayudará a encontrar el tamaño asm de Vital
  56. procedure FinVital; begin end;
  57.  
  58. // Este procedimiento copia Vital en un buffer, lo encripta y lo guarda en un archivo binario.
  59. procedure ExtraeVital;
  60. var
  61.   hFile: THANDLE;
  62.   Size: integer;
  63.   Buffer: PBYTE;
  64. begin
  65.   hFile:= CreateFile('Vital.bin', GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0);
  66.   if hFile <> INVALID_HANDLE_VALUE then
  67.   begin
  68.     //Calculamos el tamaño de Vital
  69.     Size:= UINT(@FinVital) - UINT(@Vital);
  70.     Buffer:= GetMemory(Size);
  71.     CopyMemory(Buffer, @Vital, Size);
  72.     Crypt(Buffer, Size, 'escafandra', 0);
  73.     _lwrite(hFile, PAnsiChar(Buffer), Size);
  74.     CloseHandle(hFile);
  75.     FreeMemory(Buffer);
  76.   end;
  77. end;
  78.  
  79. // Descifra Vital en su propia localización
  80. procedure DescifraVital;
  81. var
  82.   Size: integer;
  83.   OldProtect: DWORD;
  84. begin
  85.   //Calculamos el tamaño de Vital
  86.   Size:= UINT(@FinVital) - UINT(@Vital);
  87.   VirtualProtectEx(DWORD(-1), @Vital, Size, PAGE_EXECUTE_READWRITE, @OldProtect);
  88.   Crypt(@Vital, Size, PCHAR(Form1.Edit1.Text), 0);
  89.   VirtualProtectEx(DWORD(-1), @Vital, Size, OldProtect, nil);
  90. end;
  91.  
  92. procedure TForm1.FormCreate(Sender: TObject);
  93. begin
  94.   ExtraeVital;
  95.   DescifraVital;
  96.   Vital;
  97. end;
  98.  
  99. end.

Ahora, con ayuda de alguna app que nos pase un binario a texto (FileToCode) hardcodeamos Vital con el resultado obtenido:


delphi
  1. unit Vital_;
  2.  
  3. interface
  4.  
  5. uses Windows;
  6.  
  7. var
  8. Vital_Size: integer = 80;
  9.  
  10. Vital_Bytes: array [0..79] of BYTE =
  11. (
  12. $30, $F8, $8F, $30, $0E, $65, $9F, $20, $72, $89, $2B, $1D, $98, $9E, $EF, $24,
  13. $92, $0C, $62, $90, $21, $73, $E8, $24, $9A, $31, $86, $C1, $1F, $9A, $9A, $D0,
  14. $BB, $4A, $23, $61, $ED, $59, $AA, $4A, $20, $73, $63, $15, $60, $9E, $7B, $BC,
  15. $59, $24, $65, $2A, $3E, $A2, $66, $61, $3B, $0A, $13, $25, $09, $1F, $4D, $05,
  16. $0A, $0D, $6E, $64, $3E, $0E, $02, $06, $06, $00, $02, $0E, $6E, $64, $72, $61
  17. );
  18. implementation
  19. end.

El procedimiento VItal quedará como sigue:


delphi
  1. procedure Vital;
  2. asm
  3. db $30, $F8, $8F, $30, $0E, $65, $9F, $20, $72, $89, $2B, $1D, $98, $9E, $EF, $24;
  4. db $92, $0C, $62, $90, $21, $73, $E8, $24, $9A, $31, $86, $C1, $1F, $9A, $9A, $D0;
  5. db $BB, $4A, $23, $61, $ED, $59, $AA, $4A, $20, $73, $63, $15, $60, $9E, $7B, $BC;
  6. db $59, $24, $65, $2A, $3E, $A2, $66, $61, $3B, $0A, $13, $25, $09, $1F, $4D, $05;
  7. db $0A, $0D, $6E, $64, $3E, $0E, $02, $06, $06, $00, $02, $0E, $6E, $64, $72, $61;
  8. end;

Solo quede hacer tres cosas, sustituir el el código fuente Vital por su nueva implementación "justo en su mismo lugar", trucar ExtraeVital para que no guarde archivos y cambiar la cadena de cifrado por otra cosa de un carácter, ¡no debemos dejarla expuesta!. Este paso es crucial, no debemos alterar mucho el código porque hay que recordar los saltos relativos asm. Cuando recompilemos al gún salto o llamada call puede cambiar su dirección relativa, por lo tanto el código final no puede alterarse mucho.Hay que tener cuidado de dejar todos los procedimientos donde están:
 
Este es el resultado final:


delphi
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7. Dialogs, StdCtrls;
  8.  
  9. type
  10. TForm1 = class(TForm)
  11. Edit1: TEdit;
  12. Button1: TButton;
  13. procedure FormCreate(Sender: TObject);
  14. private
  15. { Private declarations }
  16. public
  17. { Public declarations }
  18. end;
  19.  
  20. var
  21. Form1: TForm1;
  22.  
  23. type PLogueado = procedure; stdcall;
  24.  
  25. implementation
  26.  
  27. {$R *.dfm}
  28. var
  29. Logueado: PLogueado;
  30.  
  31. procedure Crypt(Source: Pointer; Size: Cardinal; Password: PCHAR; _Mod: integer);
  32. var
  33. S: PCHAR;
  34. len, n: integer;
  35. begin
  36. S:= Source;
  37. len:= lstrlen(Password);
  38. for n:=0 to Size-1 do
  39. begin
  40. S[n]:= CHAR(integer(S[n]) xor integer(Password[_Mod mod len]));
  41. inc(_Mod);
  42. end;
  43. end;
  44.  
  45.  
  46. procedure Vital;
  47. asm
  48. db $30, $F8, $8F, $30, $0E, $65, $9F, $20, $72, $89, $2B, $1D, $98, $9E, $EF, $24;
  49. db $92, $0C, $62, $90, $21, $73, $E8, $24, $9A, $31, $86, $C1, $1F, $9A, $9A, $D0;
  50. db $BB, $4A, $23, $61, $ED, $59, $AA, $4A, $20, $73, $63, $15, $60, $9E, $7B, $BC;
  51. db $59, $24, $65, $2A, $3E, $A2, $66, $61, $3B, $0A, $13, $25, $09, $1F, $4D, $05;
  52. db $0A, $0D, $6E, $64, $3E, $0E, $02, $06, $06, $00, $02, $0E, $6E, $64, $72, $61;
  53. end;
  54. {
  55. procedure Vital;
  56. var
  57.   hLib: HMODULE;
  58. begin
  59.   hLib:= LoadLibrary('UnaDll.dll');
  60.   Logueado:= GetProcAddress(hLib, 'Logueado');
  61.   if @Logueado <> nil then
  62.   Logueado;
  63. end;
  64. }
  65. procedure FinVital; begin end;
  66.  
  67. procedure ExtraeVital;
  68. var
  69. hFile: THANDLE;
  70. Size: integer;
  71. Buffer: PBYTE;
  72. begin
  73. hFile:= 0; // Un Handle de archivo nulo evita que se ejecute este procedimiento
  74. CreateFile('Vital.bin', GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0);
  75. if hFile <> INVALID_HANDLE_VALUE then
  76. begin
  77. //Calculamos el tamaño de Vital
  78. Size:= UINT(@FinVital) - UINT(@Vital);
  79. Buffer:= GetMemory(Size);
  80. CopyMemory(Buffer, @Vital, Size);
  81. Crypt(Buffer, Size, '?', 0);
  82. _lwrite(hFile, PAnsiChar(Buffer), Size);
  83. CloseHandle(hFile);
  84. FreeMemory(Buffer);
  85. end;
  86. end;
  87.  
  88. procedure DescifraVital;
  89. var
  90. Size: integer;
  91. OldProtect: DWORD;
  92. begin
  93. //Calculamos el tamaño de Vital
  94. Size:= UINT(@FinVital) - UINT(@Vital);
  95. VirtualProtectEx(DWORD(-1), @Vital, Size, PAGE_EXECUTE_READWRITE, @OldProtect);
  96. Crypt(@Vital, Size, PCHAR(Form1.Edit1.Text), 0);
  97. VirtualProtectEx(DWORD(-1), @Vital, Size, OldProtect, nil);
  98. end;
  99.  
  100. procedure TForm1.FormCreate(Sender: TObject);
  101. begin
  102. ExtraeVital;
  103. DescifraVital;
  104. Vital;
  105. end;
  106.  
  107. end.

No hay condicionales, sólo una dependencia. Si Vital no es desencriptada correctamente la app dará una excepción o se colgará. Vital no se ejecutará alterando definitivamente el programa.
 
Para implementarlo en una app, habra que hacerlo en la versión liberada y probar que funciona.
 
Recordar que si falla es que no hemos tenido cuidado con los JMP y CALL relativos.
 
La fortaleza de la protección la dará el sistema de cifrado ejegido, yo he usado para el ejemplo un método simétrico XOR, no es el más apropiado pero para el ejemplo sirve.
 
Ahora os reto a cojer el ejecutable y crakearlo para que funcione la función Vital. No valen las trampas, sólo se puede usar el ejecutable.    :dlaug: *-) :D :D :D
Espero que os sirva u os de nuevas ideas para vuestras protecciones.
 
 
Subo el ejemplo que he escrito.
 
 
 
Saludos.

Archivos adjuntos


  • 4

#2 seoane

seoane

    Advanced Member

  • Administrador
  • 1.246 mensajes
  • LocationEspaña

Escrito 20 noviembre 2016 - 04:56

Interesante propuesta. (y)

 

Basicamente se trataria de hacer un "shellcode" con una funcion vistal del programa y solamente descifralo en memoria si se tiene la clave.

 

Ya hay protecciones que funcionan asi, solo veo dos problemas, que a los antivirus no les gusta demasiado (les recuerda demasiado a los crypters) y que si el piratilla se hace con una clave valida del producto tan solo tiene que ejecutarlo y hacer un "dump" de la memoria para tener el codigo bueno.

 

Al final todo se basa en complicarlo lo bastante para que el tipo "malo" pierda el interes, pero si hubiera tecnicas infalibles el windows, el autocad, el office, juegos, ... etc ya la habrian implementado hace años.

 

De todas formas un gran código escafandra  :ap:

 

Saludos


  • 0

#3 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.844 mensajes
  • LocationMadrid - España

Escrito 20 noviembre 2016 - 08:19

Basicamente se trataria de hacer un "shellcode" con una funcion vistal del programa y solamente descifralo en memoria si se tiene la clave.


Así es aunque en este caso no es un shellcode propiamente dicho, por eso el ejemplo depende mucho del resto del código compilado, Si fuera un shellcode, se podría hacer, sería totalmente rehubicable e independiente del resto del código asm de la app.
 

Ya hay protecciones que funcionan asi, solo veo dos problemas, que a los antivirus no les gusta demasiado (les recuerda demasiado a los crypters) y que si el piratilla se hace con una clave valida del producto tan solo tiene que ejecutarlo y hacer un "dump" de la memoria para tener el codigo bueno.

Los AV pueden protestar pero es posible que no se enteren, mi ejemplo se lo tragaron. La clave no puede ser única, aquí hay que ingeniárselas. Una forma puede ser una versión por licencia.

 

Al final todo se basa en complicarlo lo bastante para que el tipo "malo" pierda el interes, pero si hubiera tecnicas infalibles el windows, el autocad, el office, juegos, ... etc ya la habrian implementado hace años.

Esa es la idea, nada es infalible.  (y)

 

 

Saludos.


  • 0

#4 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.844 mensajes
  • LocationMadrid - España

Escrito 20 noviembre 2016 - 04:32

Convirtiendo Vital en un sencillo ShellCode
 
Continuando con el tema, para conseguir la independencia de Vital la convertiremos en un sencillo shellcode pues estará en nuestro entorno de memoria.

Con esto ganamos que sea completamente rehubicable pudiendo eliminar del ejecutable final lo que nos interese. También podremos seguir escribiendo más código en nuestra aplicación pues Vital seguirá funcionando aún encriptada, cosa que no pasaba con el primer ejemplo. También escondemos las cadenas de los nombres de la dll y el procedimiento que usa Vital, puesto que irá encriptada.

 
Para convertir Vital en un shellcode hacen falta dos cosas:
1.- Hacerla independiente de variables en la pila de la app.
2.- Hacerla independiente de las API usadas.
 
La primera la conseguimos llevando las variables en el propio código y la segunda pasándole como parámetros las direcciones de las API que usa.En realidad, las variables también pueden pasarse como parámetros, simplifica las cosas, pero damos más pistas al craker pues las dejemos a la vista, así que no lo vamos a hacer. Así concebido, nuestro shellcode va a funcionar como tal en nuestra app pero no es estrictamente no lo es. Un verdadero shellcode no necesita que le pasen los punteros a las API que usa, las encuentra, si me animo en la siguiente entrega será así. De momento y para entender mejor todo lo haremos pasando las API.
 
El procedimiento Vital queda como sigue:



delphi
  1. type
  2. PLogueado = procedure; stdcall;
  3. PGetProcAddress = function(hModule: HMODULE; lpProcName: LPCSTR): Pointer; stdcall;
  4. PLoadLibrary = function(lpFileName: PCHAR): HMODULE; stdcall;
  5.  
  6. procedure Vital(GetProcAddress: PGetProcAddress; LoadLibrary: PLoadLibrary);
  7. var
  8. hLib: HMODULE;
  9. DllName: PCHAR;
  10. DllProc: PCHAR;
  11. begin
  12. asm
  13. call @sigue
  14. db 'UnaDll.dll',0;
  15. db 'Logueado',0;
  16. @sigue:
  17. pop eax; // Ahora eax apunta a 'UnaDll.dll'
  18. mov DllName, eax; // Guardo en la pila de la función en la variable DllName
  19. add eax, 11; // tamaño de UnaDll.dll + 0
  20. mov DllProc, eax; // Guardo en la pila de la función en la variable DllName
  21. end;
  22.  
  23. hLib:= LoadLibrary(DllName);
  24. if hLib <> 0 then
  25. begin
  26. Logueado:= GetProcAddress(hLib, DllProc);
  27. if @Logueado <> nil then
  28. Logueado;
  29. end;
  30. end;
  31. procedure FinVital; begin end;

El fragmento asm se encarga de recuperar las cadenas en las variables diseñadas a su efecto para poder seguir usando código delphi.
Las API GetProcAddress y LoadLibrary han sido pasadas como punteros al procedimiento que llamaremos así:


delphi
  1. Vital(GetProcAddress(GetModuleHandle('Kernel32.dll'), 'GetProcAddress'),
  2. GetProcAddress(GetModuleHandle('Kernel32.dll'), 'LoadLibraryA'));

¿Por qué hacemos esto? porque delphi no usa los verdaderos punteros a esas API, sino los que encuentra en la IAT y no son los que nos hacen falta si queremos que Vital sea completamente rehubicable en nuestro código.
 
El resto del ejemplo sigue con la misma filosofía que el anterior, Ciframos Vital, lo guardamos en un archivo y de éste obtenemos su binario cifrado para nuestra nueva Vital.
 
El código final queda como sigue:


delphi
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7. Dialogs, StdCtrls;
  8.  
  9. type
  10. TForm1 = class(TForm)
  11. Edit1: TEdit;
  12. Button1: TButton;
  13. procedure FormCreate(Sender: TObject);
  14. private
  15. { Private declarations }
  16. public
  17. { Public declarations }
  18. end;
  19.  
  20. var
  21. Form1: TForm1;
  22.  
  23. type
  24. PLogueado = procedure; stdcall;
  25. PGetProcAddress = function(hModule: HMODULE; lpProcName: LPCSTR): Pointer; stdcall;
  26. PLoadLibrary = function(lpFileName: PCHAR): HMODULE; stdcall;
  27. implementation
  28.  
  29. {$R *.dfm}
  30. var
  31. Logueado: PLogueado;
  32.  
  33. procedure Crypt(Source: Pointer; Size: Cardinal; Password: PCHAR; _Mod: integer);
  34. var
  35. S: PCHAR;
  36. len, n: integer;
  37. begin
  38. S:= Source;
  39. len:= lstrlen(Password);
  40. for n:=0 to Size-1 do
  41. begin
  42. S[n]:= CHAR(integer(S[n]) xor integer(Password[_Mod mod len]));
  43. inc(_Mod);
  44. end;
  45. end;
  46.  
  47.  
  48.  
  49. procedure Vital(GetProcAddress: PGetProcAddress; LoadLibrary: PLoadLibrary);
  50. asm
  51. db $30, $F8, $8F, $E2, $A2, $99, $3D, $32, $F9, $91, $8D, $67, $63, $61, $66, $34;
  52. db $00, $05, $36, $0D, $09, $5D, $07, $0D, $0A, $61, $22, $0B, $15, $14, $00, $12;
  53. db $07, $0E, $66, $39, $E7, $21, $8E, $E2, $A5, $78, $EA, $24, $9E, $EA, $2B, $98;
  54. db $22, $9E, $B7, $F8, $BB, $E4, $BD, $15, $75, $EF, $37, $99, $35, $20, $9C, $B7;
  55. db $C5, $B9, $45, $21, $72, $E2, $58, $AB, $48, $24, $66, $61, $1A, $62, $8D, $74;
  56. db $BD, $58, $26, $61, $38, $3A, $37, $3D, $2F, $A2, $EE, $B3, $A0, $EC, $26, $61;
  57. end;
  58. procedure FinVital; begin end;
  59.  
  60. {
  61. procedure Vital(GetProcAddress: PGetProcAddress; LoadLibrary: PLoadLibrary);
  62. var
  63.   hLib: HMODULE;
  64.  
  65.   DllName: PCHAR;
  66.   DllProc: PCHAR;
  67. begin
  68.   asm
  69.   call @sigue
  70.   db 'UnaDll.dll',0;
  71.   db 'Logueado',0;
  72.   @sigue:
  73.   pop eax;
  74.   mov DllName, eax;
  75.   add eax, 11; // tamaño de UnaDll.dll + 0
  76.   mov DllProc, eax;
  77.   end;
  78.  
  79.   hLib:= LoadLibrary(DllName);
  80.   if hLib <> 0 then
  81.   begin
  82.   Logueado:= GetProcAddress(hLib, DllProc);
  83.   if @Logueado <> nil then
  84.   Logueado;
  85.   end;
  86. end;
  87. procedure FinVital; begin end;
  88.  
  89. procedure ExtraeVital;
  90. var
  91.   hFile: THANDLE;
  92.   Size: integer;
  93.   Buffer: PBYTE;
  94. begin
  95.   hFile:= CreateFile('Vital.bin', GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0);
  96.   if hFile <> INVALID_HANDLE_VALUE then
  97.   begin
  98.   //Calculamos el tamaño de Vital
  99.   Size:= UINT(@FinVital) - UINT(@Vital);
  100.   Buffer:= GetMemory(Size);
  101.   CopyMemory(Buffer, @Vital, Size);
  102.   Crypt(Buffer, Size, 'escafandra', 0);
  103.   _lwrite(hFile, PAnsiChar(Buffer), Size);
  104.   CloseHandle(hFile);
  105.   FreeMemory(Buffer);
  106.   end;
  107. end;
  108. }
  109.  
  110. procedure DescifraVital;
  111. var
  112. Size: integer;
  113. OldProtect: DWORD;
  114. begin
  115. //Calculamos el tamaño de Vital
  116. Size:= UINT(@FinVital) - UINT(@Vital);
  117. VirtualProtectEx(DWORD(-1), @Vital, Size, PAGE_EXECUTE_READWRITE, @OldProtect);
  118. Crypt(@Vital, Size, PCHAR(Form1.Edit1.Text), 0);
  119. VirtualProtectEx(DWORD(-1), @Vital, Size, OldProtect, nil);
  120. end;
  121.  
  122. procedure TForm1.FormCreate(Sender: TObject);
  123. begin
  124. // ExtraeVital;
  125. DescifraVital;
  126. Vital(GetProcAddress(GetModuleHandle('Kernel32.dll'), 'GetProcAddress'),
  127. GetProcAddress(GetModuleHandle('Kernel32.dll'), 'LoadLibraryA'));
  128. end;
  129.  
  130. end.

Observar que ExtraeVital ya no hace falta que permanezca, directamente lo comentamos o lo borramos sin que afecte al funcionamiento de Vital tras la nueva compilación.
 
Ahora todo es mucho mas sencillo a la hora de trabajar, sin miedo a que algo corrompa el resultado. Sólo hay un problema, dejamos a la vista del cracker las API que usa Vital, GetProcAddress y LoadLibraryA. ¿Si hacemos un verdadero shellcode se puede evitar?. Si.

 
 
Saludos

Archivos adjuntos


  • 2

#5 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.844 mensajes
  • LocationMadrid - España

Escrito 22 noviembre 2016 - 04:43

Convirtiendo Vital en un completo shellcode
 
Me animé...
 
Si en la anterior entrega Vital ya era un shellcode, en el sentido que era totalmente independiente del código adyacente, carecía de la total capacidad de autonomía pues precisaba que le comunicaran los punteros a la API que necesitaba usar. Comentaba que esto podía dar pistas de lo que hacía a algún curioso. Ahora Vital va a ser completamente independiente hasta el punto que podría ser inyectada en un proceso remoto y funcionaría.
 
¿Que le faltaba a nuestro anterior shellcode? Le faltaba localizar por sí mismo una API vital: GetProcAddress mediante la que será capaz de encontrar cualquier otra. Veamos:

delphi
  1. procedure Vital;
  2. type
  3. TAWORD = array [0..0] of WORD;
  4. PAWORD = ^TAWORD;
  5. TAPCHAR = array [0..0] of PCHAR;
  6. PAPCHAR = ^TAPCHAR;
  7. TAUINT = array [0..0] of UINT;
  8. PAUINT = ^TAUINT;
  9. var
  10. hLib: HMODULE;
  11. SGetProcAddress: PCHAR;
  12. SLoadLibraryA: PCHAR;
  13. DllName: PCHAR;
  14. DllProc: PCHAR;
  15. KB: UINT; // hModule de Kernel32.dll
  16. IED: PImageExportDirectory;
  17. _GetProcAddress: PGetProcAddress;
  18. _LoadLibrary: PLoadLibrary;
  19. Logueado: PLogueado;
  20. Names: PAPCHAR;
  21. Name: PCHAR;
  22. EntryPoints: PAUINT;
  23. Index: PAWORD;
  24. i,n: UINT;
  25. begin
  26. asm
  27. call @sigue
  28. db 'GetProcAddress',0
  29. db 'LoadLibraryA',0
  30. db 'UnaDll.dll',0;
  31. db 'Logueado',0;
  32. @sigue:
  33. pop EAX;
  34. mov SGetProcAddress, EAX;
  35. add eax, 15 // tamaño de _GetProcAddress + 0
  36. mov SLoadLibraryA, eax
  37. add eax, 13 // tamaño de _LoadLibraryA + 0
  38. mov DllName, eax;
  39. add eax, 11; // tamaño de UnaDll.dll + 0
  40. mov DllProc, eax;
  41.  
  42. mov eax, fs:[$30] // Puntero al PEB
  43. mov eax, [eax + $0C] // Puntero a PPEB_LDR_DATA
  44. mov eax, [eax + $0C] // Puntero a InLoadOrderModuleList
  45. mov eax, [eax] // InLoadOrderModuleList de ntdll.dll
  46. mov eax, [eax] // InLoadOrderModuleList de kernel32.dll
  47. mov eax, [eax + $18] // BaseAddress de kernel32.dll
  48. mov KB, eax
  49.  
  50. // Encuentro PIMAGE_EXPORT_DIRECTORY
  51. mov eax, [eax + $3C]
  52. add eax, $78
  53. add eax, KB
  54. mov eax, [eax]
  55. add eax, KB
  56. mov IED, eax
  57. end;
  58.  
  59. // Buscando GetProcAddress
  60. Names:= PAPCHAR(PCHAR(IED.AddressOfNames) + KB);
  61. EntryPoints:= PAUINT(PCHAR(IED.AddressOfFunctions )+ KB);
  62. Index:= PAWORD(PCHAR(IED.AddressOfNameOrdinals) + KB);
  63. i:= 0;
  64. n:= 0;
  65. while (n < IED.NumberOfNames) and (i <> 14) do
  66. begin
  67. if Index[n] >= IED.NumberOfFunctions then continue;
  68. Name:= Names[n] + KB;
  69. @_GetProcAddress:= Pointer(EntryPoints[Index[n]] + KB);
  70. inc(n);
  71. i:= 0;
  72. while (SGetProcAddress[i] <> #0) and (Name[i] = SGetProcAddress[i]) do inc(i);
  73. end;
  74. @_LoadLibrary:= _GetProcAddress(KB, SLoadLibraryA);
  75. hLib:= _LoadLibrary(DllName);
  76. if hLib <> 0 then
  77. begin
  78. Logueado:= _GetProcAddress(hLib, DllProc);
  79. if @Logueado <> nil then
  80. Logueado;
  81. end;
  82. end;

La primera parte en asm comienza siendo similar a nuestra anterior Vital, luego navega por una estructura especial de cualquier ejecutable, el formato PE, del que ya hablamos en este enlace: Shellcode en C compatible con distintas inyecciones y explicaba como funciona esto con detalle y código delphi. Una primera cosa hace falta, Encontrat el hModule de Kernel32.dll que está representado por la variable KB. Esa dll exporta la API que buscamos: GetProcAddress y para navegar por Kernel32.dll necesitamos conocer ImageExportDirectory: IED. Con esto ya podemos encontrar GetProcAddress.
 
Conocido el puntero de la ansiada GetProcAddress, encontramos LoadLibrary o cualquier otra API.
 
Comentarios finales:
Incidir en la necesidad de escribir todas las cadenas en el propio código, de otra forma estarían en la pila y no las encontraríamos en las direcciones que nos propone delphi.
 
Es muy importante que cuando guardemos el shellcode en su archivo binario, no hayamos puesto ningún punto de interrupción en el código pues si compilamos con él, se trasladará con una instrucción asm int3 que estropeará el shellcode
 
El resto del programa es igual que los anteriores:

delphi
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7. Dialogs, StdCtrls;
  8.  
  9. type
  10. TForm1 = class(TForm)
  11. Edit1: TEdit;
  12. Button1: TButton;
  13. procedure FormCreate(Sender: TObject);
  14. private
  15. { Private declarations }
  16. public
  17. { Public declarations }
  18. end;
  19.  
  20. var
  21. Form1: TForm1;
  22.  
  23. type
  24. PLogueado = procedure; stdcall;
  25. PGetProcAddress = function(hModule: HMODULE; lpProcName: LPCSTR): Pointer; stdcall;
  26. PLoadLibrary = function(lpFileName: PCHAR): HMODULE; stdcall;
  27. implementation
  28.  
  29. {$R *.dfm}
  30.  
  31. procedure Crypt(Source: Pointer; Size: Cardinal; Password: PCHAR; _Mod: integer);
  32. var
  33. S: PCHAR;
  34. len, n: integer;
  35. begin
  36. S:= Source;
  37. len:= lstrlen(Password);
  38. for n:=0 to Size-1 do
  39. begin
  40. S[n]:= CHAR(integer(S[n]) xor integer(Password[_Mod mod len]));
  41. inc(_Mod);
  42. end;
  43. end;
  44. {
  45. procedure Vital;
  46. type
  47.   TAWORD = array [0..0] of WORD;
  48.   PAWORD = ^TAWORD;
  49.   TAPCHAR = array [0..0] of PCHAR;
  50.   PAPCHAR = ^TAPCHAR;
  51.   TAUINT = array [0..0] of UINT;
  52.   PAUINT = ^TAUINT;
  53. var
  54.   hLib: HMODULE;
  55.   SGetProcAddress: PCHAR;
  56.   SLoadLibraryA: PCHAR;
  57.   DllName: PCHAR;
  58.   DllProc: PCHAR;
  59.   KB: UINT; // hModule de Kernel32.dll
  60.   IED: PImageExportDirectory;
  61.   _GetProcAddress: PGetProcAddress;
  62.   _LoadLibrary: PLoadLibrary;
  63.   Logueado: PLogueado;
  64.   Names: PAPCHAR;
  65.   Name: PCHAR;
  66.   EntryPoints: PAUINT;
  67.   Index: PAWORD;
  68.   i,n: UINT;
  69. begin
  70.   asm
  71.   call @sigue
  72.   db 'GetProcAddress',0
  73.   db 'LoadLibraryA',0
  74.   db 'UnaDll.dll',0;
  75.   db 'Logueado',0;
  76.   @sigue:
  77.   pop EAX;
  78.   mov SGetProcAddress, EAX;
  79.   add eax, 15 // tamaño de _GetProcAddress + 0
  80.   mov SLoadLibraryA, eax
  81.   add eax, 13 // tamaño de _LoadLibraryA + 0
  82.   mov DllName, eax;
  83.   add eax, 11; // tamaño de UnaDll.dll + 0
  84.   mov DllProc, eax;
  85.  
  86.   mov eax, fs:[$30] // Puntero al PEB
  87.   mov eax, [eax + $0C] // Puntero a PPEB_LDR_DATA
  88.   mov eax, [eax + $0C] // Puntero a InLoadOrderModuleList
  89.   mov eax, [eax] // InLoadOrderModuleList de ntdll.dll
  90.   mov eax, [eax] // InLoadOrderModuleList de kernel32.dll
  91.   mov eax, [eax + $18] // BaseAddress de kernel32.dll
  92.   mov KB, eax
  93.  
  94.   // Encuentro PIMAGE_EXPORT_DIRECTORY
  95.   mov eax, [eax + $3C]
  96.   add eax, $78
  97.   add eax, KB
  98.   mov eax, [eax]
  99.   add eax, KB
  100.   mov IED, eax
  101.   end;
  102.  
  103.   // Buscando GetProcAddress
  104.   Names:= PAPCHAR(PCHAR(IED.AddressOfNames) + KB);
  105.   EntryPoints:= PAUINT(PCHAR(IED.AddressOfFunctions )+ KB);
  106.   Index:= PAWORD(PCHAR(IED.AddressOfNameOrdinals) + KB);
  107.   i:= 0;
  108.   n:= 0;
  109.   while (n < IED.NumberOfNames) and (i <> 14) do
  110.   begin
  111.   if Index[n] >= IED.NumberOfFunctions then continue;
  112.   Name:= Names[n] + KB;
  113.   @_GetProcAddress:= Pointer(EntryPoints[Index[n]] + KB);
  114.   inc(n);
  115.   i:= 0;
  116.   while (SGetProcAddress[i] <> #0) and (Name[i] = SGetProcAddress[i]) do inc(i);
  117.   end;
  118.   @_LoadLibrary:= _GetProcAddress(KB, SLoadLibraryA);
  119.   hLib:= _LoadLibrary(DllName);
  120.   if hLib <> 0 then
  121.   begin
  122.   Logueado:= _GetProcAddress(hLib, DllProc);
  123.   if @Logueado <> nil then
  124.   Logueado;
  125.   end;
  126. end;
  127. procedure FinVital; begin end;
  128. }
  129. procedure Vital;
  130. asm
  131. db $30, $F8, $8F, $E2, $A2, $A1, $86, $54, $72, $61, $65, $34, $06, $15, $36, $13;
  132. db $01, $07, $33, $05, $01, $01, $06, $12, $15, $61, $22, $0B, $13, $05, $29, $1A;
  133. db $01, $13, $07, $13, $17, $25, $72, $34, $0B, $12, $27, $0D, $0A, $4F, $0A, $08;
  134. db $1E, $61, $29, $1C, $04, $14, $03, $00, $0A, $0B, $72, $39, $EC, $36, $9F, $E2;
  135. db $A6, $6E, $E7, $21, $8A, $E2, $A5, $7E, $EA, $24, $92, $E2, $AE, $6F, $FB, $24;
  136. db $95, $17, $E8, $64, $56, $61, $6E, $64, $F9, $21, $69, $F8, $23, $6D, $ED, $61;
  137. db $E5, $64, $F9, $21, $7D, $FA, $26, $8D, $ED, $21, $52, $E7, $B2, $19, $66, $36;
  138. db $8F, $EA, $66, $62, $2B, $88, $FB, $24, $8D, $F8, $26, $89, $ED, $21, $4E, $67;
  139. db $37, $8D, $EC, $36, $B7, $EA, $23, $89, $E5, $24, $6E, $62, $20, $9F, $EA, $24;
  140. db $AA, $EA, $2B, $8C, $F9, $21, $41, $70, $26, $8D, $EF, $24, $A6, $57, $B2, $E8;
  141. db $20, $B7, $50, $A1, $EF, $24, $AE, $8F, $16, $EA, $20, $BB, $E8, $34, $A6, $6E;
  142. db $D9, $60, $22, $EA, $30, $9B, $58, $23, $72, $12, $3C, $EF, $37, $B5, $EE, $26;
  143. db $A3, $EA, $62, $F1, $6D, $21, $9E, $E8, $20, $A3, $E8, $24, $AE, $EA, $3B, $A4;
  144. db $7D, $D6, $61, $23, $E8, $34, $AA, $EA, $6A, $E6, $71, $24, $89, $FA, $26, $81;
  145. db $99, $24, $AE, $57, $B2, $E8, $20, $B7, $88, $62, $99, $24, $AA, $EF, $37, $9D;
  146. db $EE, $26, $A7, $E1, $5A, $71, $6E, $10, $66, $EA, $20, $A3, $E8, $34, $A2, $EB;
  147. db $6A, $74, $F9, $34, $99, $F8, $2E, $A5, $5C, $65, $64, $10, $AF, $EA, $20, $9B;
  148. db $E8, $21, $7E, $5A, $2B, $A4, $04, $67, $E6, $0E, $A7, $6F, $13, $EA, $E5, $21;
  149. db $8A, $31, $EE, $36, $8F, $31, $99, $34, $8E, $ED, $37, $BD, $EE, $36, $97, $31;
  150. db $99, $34, $B2, $ED, $37, $85, $E6, $0E, $87, $61, $12, $76, $E5, $21, $82, $31;
  151. db $EE, $36, $87, $31, $99, $34, $8E, $ED, $37, $B9, $E6, $0E, $BB, $61, $12, $62;
  152. db $91, $31, $AA, $EA, $80, $2E, $A0, $F1;
  153.  
  154. end;
  155. procedure FinVital; begin end;
  156.  
  157.  
  158. procedure ExtraeVital;
  159. var
  160. hFile: THANDLE;
  161. Size: integer;
  162. Buffer: PBYTE;
  163. begin
  164. hFile:= CreateFile('Vital.bin', GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0);
  165. if hFile <> INVALID_HANDLE_VALUE then
  166. begin
  167. //Calculamos el tamaño de Vital
  168. Size:= UINT(@FinVital) - UINT(@Vital);
  169. Buffer:= GetMemory(Size);
  170. CopyMemory(Buffer, @Vital, Size);
  171. Crypt(Buffer, Size, 'escafandra', 0);
  172. _lwrite(hFile, PAnsiChar(Buffer), Size);
  173. CloseHandle(hFile);
  174. FreeMemory(Buffer);
  175. end;
  176. end;
  177.  
  178. procedure DescifraVital;
  179. var
  180. Size: integer;
  181. OldProtect: DWORD;
  182. begin
  183. //Calculamos el tamaño de Vital
  184. Size:= UINT(@FinVital) - UINT(@Vital);
  185. VirtualProtectEx(DWORD(-1), @Vital, Size, PAGE_EXECUTE_READWRITE, @OldProtect);
  186. Crypt(@Vital, Size, PCHAR(Form1.Edit1.Text), 0);
  187. VirtualProtectEx(DWORD(-1), @Vital, Size, OldProtect, nil);
  188. end;
  189.  
  190. procedure TForm1.FormCreate(Sender: TObject);
  191. begin
  192. // ExtraeVital;
  193. DescifraVital;
  194. Vital;
  195. end;
  196.  
  197. end.

Adjunto los archivos y una nueva versión de FileToCode.exe (escrito en C) que nos da el asm del binario para experimentar con más comodidad.
 
 
Ya solo resta ver si los AV detectan cosas raras para proceder a modificar cosas. *-) *-)
 
Saludos.

Archivos adjuntos


  • 3

#6 LuKas

LuKas

    Newbie

  • Miembros
  • Pip
  • 7 mensajes

Escrito 08 diciembre 2016 - 05:18

Hola,se ve muy bueno todo esto para estudiar,pero no funciona en Delphi Berlin,podrias hacerlo compatible con Delphi Berlin por favor tu código.

  • 0

#7 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.844 mensajes
  • LocationMadrid - España

Escrito 08 diciembre 2016 - 07:07

Hola,se ve muy bueno todo esto para estudiar,pero no funciona en Delphi Berlin,podrias hacerlo compatible con Delphi Berlin por favor tu código.

 
El problema es el UNICODE. Se soluciona cambiando CHAR y PCHAR de delphi7 por AnsiCHAR y PAnsiCHAR. También he adaptado la función Crypt para que funcione correctamente, además de los cambios señalados hay que cambiar lstrlen por lstrlenA .
 
Este sería el equivalente para Berlin de la última entrega de código:

delphi
  1. nit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7. Dialogs, StdCtrls;
  8.  
  9. type
  10. TForm1 = class(TForm)
  11. Edit1: TEdit;
  12. Button1: TButton;
  13. procedure FormCreate(Sender: TObject);
  14. private
  15. { Private declarations }
  16. public
  17. { Public declarations }
  18. end;
  19.  
  20. var
  21. Form1: TForm1;
  22.  
  23. type
  24. PLogueado = procedure; stdcall;
  25. PGetProcAddress = function(hModule: HMODULE; lpProcName: LPCSTR): Pointer; stdcall;
  26. PLoadLibrary = function(lpFileName: PAnsiCHAR): HMODULE; stdcall;
  27. implementation
  28.  
  29. {$R *.dfm}
  30.  
  31. procedure Crypt(Source: Pointer; Size: Cardinal; Password: PAnsiCHAR; _Mod: integer);
  32. var
  33. S: PAnsiChar;
  34. len, n: integer;
  35. begin
  36. S:= Source;
  37. len:= lstrlenA(Password);
  38. for n:=0 to Size-1 do
  39. begin
  40. S[n]:= AnsiCHAR(BYTE(S[n]) xor BYTE(Password[_Mod mod len]));
  41. inc(_Mod);
  42. end;
  43. end;
  44. {
  45. procedure Vital;
  46. type
  47.   TAWORD = array [0..0] of WORD;
  48.   PAWORD = ^TAWORD;
  49.   TAPAnsiCHAR = array [0..0] of PAnsiCHAR;
  50.   PAPAnsiCHAR = ^TAPAnsiCHAR;
  51.   TAUINT = array [0..0] of UINT;
  52.   PAUINT = ^TAUINT;
  53. var
  54.   hLib: HMODULE;
  55.   SGetProcAddress: PAnsiCHAR;
  56.   SLoadLibraryA: PAnsiCHAR;
  57.   DllName: PAnsiCHAR;
  58.   DllProc: PAnsiCHAR;
  59.   KB: UINT; // hModule de Kernel32.dll
  60.   IED: PImageExportDirectory;
  61.   _GetProcAddress: PGetProcAddress;
  62.   _LoadLibrary: PLoadLibrary;
  63.   Logueado: PLogueado;
  64.   Names: PAPAnsiCHAR;
  65.   Name: PAnsiCHAR;
  66.   EntryPoints: PAUINT;
  67.   Index: PAWORD;
  68.   i,n: UINT;
  69. begin
  70.   asm
  71.   call @sigue
  72.   db 'GetProcAddress',0
  73.   db 'LoadLibraryA',0
  74.   db 'UnaDll.dll',0;
  75.   db 'Logueado',0;
  76.   @sigue:
  77.   pop EAX;
  78.   mov SGetProcAddress, EAX;
  79.   add eax, 15 // tamaño de _GetProcAddress + 0
  80.   mov SLoadLibraryA, eax
  81.   add eax, 13 // tamaño de _LoadLibraryA + 0
  82.   mov DllName, eax;
  83.   add eax, 11; // tamaño de UnaDll.dll + 0
  84.   mov DllProc, eax;
  85.  
  86.   mov eax, fs:[$30] // Puntero al PEB
  87.   mov eax, [eax + $0C] // Puntero a PPEB_LDR_DATA
  88.   mov eax, [eax + $0C] // Puntero a InLoadOrderModuleList
  89.   mov eax, [eax] // InLoadOrderModuleList de ntdll.dll
  90.   mov eax, [eax] // InLoadOrderModuleList de kernel32.dll
  91.   mov eax, [eax + $18] // BaseAddress de kernel32.dll
  92.   mov KB, eax
  93.  
  94.   // Encuentro PIMAGE_EXPORT_DIRECTORY
  95.   mov eax, [eax + $3C]
  96.   add eax, $78
  97.   add eax, KB
  98.   mov eax, [eax]
  99.   add eax, KB
  100.   mov IED, eax
  101.   end;
  102.  
  103.   // Buscando GetProcAddress
  104.   Names:= PAPAnsiCHAR(PAnsiCHAR(IED.AddressOfNames) + KB);
  105.   EntryPoints:= PAUINT(PAnsiCHAR(IED.AddressOfFunctions )+ KB);
  106.   Index:= PAWORD(PAnsiCHAR(IED.AddressOfNameOrdinals) + KB);
  107.   i:= 0;
  108.   n:= 0;
  109.   while (n < IED.NumberOfNames) and (i <> 14) do
  110.   begin
  111.   if Index[n] >= IED.NumberOfFunctions then continue;
  112.   Name:= Names[n] + KB;
  113.   @_GetProcAddress:= Pointer(EntryPoints[Index[n]] + KB);
  114.   inc(n);
  115.   i:= 0;
  116.   while (SGetProcAddress[i] <> #0) and (Name[i] = SGetProcAddress[i]) do inc(i);
  117.   end;
  118.   @_LoadLibrary:= _GetProcAddress(KB, SLoadLibraryA);
  119.   hLib:= _LoadLibrary(DllName);
  120.   if hLib <> 0 then
  121.   begin
  122.   Logueado:= _GetProcAddress(hLib, DllProc);
  123.   if @Logueado <> nil then
  124.   Logueado;
  125.   end;
  126. end;
  127. procedure FinVital; begin end;
  128. }
  129. procedure Vital;
  130. asm
  131. db $30, $F8, $8F, $E2, $A2, $A1, $86, $54, $72, $61, $65, $34, $06, $15, $36, $13;
  132. db $01, $07, $33, $05, $01, $01, $06, $12, $15, $61, $22, $0B, $13, $05, $29, $1A;
  133. db $01, $13, $07, $13, $17, $25, $72, $34, $0B, $12, $27, $0D, $0A, $4F, $0A, $08;
  134. db $1E, $61, $29, $1C, $04, $14, $03, $00, $0A, $0B, $72, $39, $EC, $36, $9F, $E2;
  135. db $A6, $6E, $E7, $21, $8A, $E2, $A5, $7E, $EA, $24, $92, $E2, $AE, $6F, $FB, $24;
  136. db $95, $17, $E8, $64, $56, $61, $6E, $64, $F9, $21, $69, $F8, $23, $6D, $ED, $61;
  137. db $E5, $64, $F9, $21, $7D, $FA, $26, $8D, $ED, $21, $52, $E7, $B2, $19, $66, $36;
  138. db $8F, $EA, $66, $62, $2B, $88, $FB, $24, $8D, $F8, $26, $89, $ED, $21, $4E, $67;
  139. db $37, $8D, $EC, $36, $B7, $EA, $23, $89, $E5, $24, $6E, $62, $20, $9F, $EA, $24;
  140. db $AA, $EA, $2B, $8C, $F9, $21, $41, $70, $26, $8D, $EF, $24, $A6, $57, $B2, $E8;
  141. db $20, $B7, $50, $A1, $EF, $24, $AE, $8F, $16, $EA, $20, $BB, $E8, $34, $A6, $6E;
  142. db $D9, $60, $22, $EA, $30, $9B, $58, $23, $72, $12, $3C, $EF, $37, $B5, $EE, $26;
  143. db $A3, $EA, $62, $F1, $6D, $21, $9E, $E8, $20, $A3, $E8, $24, $AE, $EA, $3B, $A4;
  144. db $7D, $D6, $61, $23, $E8, $34, $AA, $EA, $6A, $E6, $71, $24, $89, $FA, $26, $81;
  145. db $99, $24, $AE, $57, $B2, $E8, $20, $B7, $88, $62, $99, $24, $AA, $EF, $37, $9D;
  146. db $EE, $26, $A7, $E1, $5A, $71, $6E, $10, $66, $EA, $20, $A3, $E8, $34, $A2, $EB;
  147. db $6A, $74, $F9, $34, $99, $F8, $2E, $A5, $5C, $65, $64, $10, $AF, $EA, $20, $9B;
  148. db $E8, $21, $7E, $5A, $2B, $A4, $04, $67, $E6, $0E, $A7, $6F, $13, $EA, $E5, $21;
  149. db $8A, $31, $EE, $36, $8F, $31, $99, $34, $8E, $ED, $37, $BD, $EE, $36, $97, $31;
  150. db $99, $34, $B2, $ED, $37, $85, $E6, $0E, $87, $61, $12, $76, $E5, $21, $82, $31;
  151. db $EE, $36, $87, $31, $99, $34, $8E, $ED, $37, $B9, $E6, $0E, $BB, $61, $12, $62;
  152. db $91, $31, $AA, $EA, $80, $2E, $A0, $F1;
  153. end;
  154. procedure FinVital; begin end;
  155.  
  156. {
  157. procedure ExtraeVital;
  158. var
  159.   hFile: THANDLE;
  160.   Size: integer;
  161.   Buffer: PBYTE;
  162. begin
  163.   hFile:= CreateFile('Vital.bin', GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0);
  164.   if hFile <> INVALID_HANDLE_VALUE then
  165.   begin
  166.   //Calculamos el tamaño de Vital
  167.   Size:= UINT(@FinVital) - UINT(@Vital);
  168.   Buffer:= GetMemory(Size);
  169.   CopyMemory(Buffer, @Vital, Size);
  170.   Crypt(Buffer, Size, 'escafandra', 0);
  171.   _lwrite(hFile, PAnsiChar(Buffer), Size);
  172.   CloseHandle(hFile);
  173.   FreeMemory(Buffer);
  174.   end;
  175. end;
  176. }
  177.  
  178. procedure DescifraVital;
  179. var
  180. Size: integer;
  181. OldProtect: DWORD;
  182. begin
  183. //Calculamos el tamaño de Vital
  184. Size:= UINT(@FinVital) - UINT(@Vital);
  185. VirtualProtectEx(DWORD(-1), @Vital, Size, PAGE_EXECUTE_READWRITE, @OldProtect);
  186. Crypt(@Vital, Size, PAnsiCHAR(AnsiString(Form1.Edit1.Text)), 0);
  187. VirtualProtectEx(DWORD(-1), @Vital, Size, OldProtect, nil);
  188. end;
  189.  
  190. procedure TForm1.FormCreate(Sender: TObject);
  191. begin
  192. // ExtraeVital;
  193. DescifraVital;
  194. Vital;
  195. end;
  196.  
  197. end.

Subo el proyecto completo de esta última parte, que es la más compleja y completa. Lo he compilado y funciona correctamente en Berlin. Haz los cambios el las otras partes, son más sencillas.

 
Saludos.

Archivos adjuntos


  • 2

#8 LuKas

LuKas

    Newbie

  • Miembros
  • Pip
  • 7 mensajes

Escrito 08 diciembre 2016 - 09:54

muchas gracias por tomate el tiempo de portarlo a Berlin.(y)


  • 0