Ir al contenido


Foto

Hook a CreateProcessInternalW con APIHook64


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

#1 Dante

Dante

    Advanced Member

  • Miembros
  • PipPipPip
  • 89 mensajes

Escrito 26 diciembre 2016 - 03:36

Hola  a todos, hace dias q estaba tratando de poder controlar las aplicaciones q se ejecunte un la pc, lo cual me llevo a los ejemplos de hook a la api  CreateProcessInternalW, prero todos estos solo trabajan en 32bits y yo tengo puesto W10 64. Gracias a escafandra  q creo  APIHook64 estoy viendo algo de luz en este proyecto, pero no e podido crear una dll con esta funcion  para q me hookee todos los procesos abiertos sean de 32 o 64, me e apollado en   Client+Hook.rar y AntiInject.rar  para tratar de crear la dll pero no e podido pasar estas a lazaro. si alguien tiene idea de como hacer este hook  le agradeceria mucho


  • 0

#2 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 26 diciembre 2016 - 05:05

No puedes crear una sola dll, debes crear dos, una para procesos de 32bits y otra para 64bits. Ello es debido a que no puedes inyectar cruzando ambas plataformas.
 
Voy a poner un ejemplo de una dll de 64bits, compilada con Lazarus, que realiza un Hook64 al proceso que la carga o que es inyectado, ni que decir tiene que dicho proceso ha de ser de 64bits.
 


delphi
  1. library Hook64;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6. Windows, APIHook64, ShellAPI;
  7.  
  8.  
  9. type
  10. PCreateProcessInternalW = function(hToken: THANDLE; pApplicationName, lpCommandLine: PWCHAR;
  11. lpProcessAttributes, lpThreadAttributes: PSECURITYATTRIBUTES; bInheritHandles: BOOL;
  12. dwCreationFlags: DWORD; lpEnvironment: Pointer; lpCurrentDirectory: PWCHAR;
  13. lpStartupInfo: PSTARTUPINFOW; lpProcessInformation: PPROCESSINFORMATION; hNewToken: PHANDLE): BOOL; stdcall;
  14. var
  15. OldCreateProcessInternalW: PCreateProcessInternalW = nil;
  16.  
  17. function NewCreateProcessInternalW(hToken: THANDLE; pApplicationName, lpCommandLine: PWCHAR;
  18. lpProcessAttributes, lpThreadAttributes: PSECURITYATTRIBUTES; bInheritHandles: BOOL;
  19. dwCreationFlags: DWORD; lpEnvironment: Pointer; lpCurrentDirectory: PWCHAR;
  20. lpStartupInfo: PSTARTUPINFOW; lpProcessInformation: PPROCESSINFORMATION; hNewToken: PHANDLE): BOOL; stdcall;
  21. begin
  22. Result:= FALSE;
  23. Windows.Beep(500, 100);
  24. MessageBoxW(0, 'No te dejo ejecutar el proceso', pApplicationName, MB_OK);
  25. exit;
  26. Result:= OldCreateProcessInternalW(hToken, pApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles,
  27. dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation, hNewToken);
  28. end;
  29.  
  30. //----------------------------------------------------------------------------
  31. // Instalando los Hooks a las API
  32. procedure InstallHooks;
  33. begin
  34. InstallHook(@NewCreateProcessInternalW, Pointer(OldCreateProcessInternalW), 'Kernelbase.dll', 'CreateProcessInternalW', true);
  35. end;
  36.  
  37. procedure UnInstallHooks;
  38. begin
  39. UnInstallHook(Pointer(OldCreateProcessInternalW), 'KernelBase.dll', 'CreateProcessInternalW');
  40. end;
  41.  
  42.  
  43.  
  44. begin
  45. InstallHooks;
  46. end.

 
Aclaraciones sobre la sintaxis Lazarus y asignación de funciones/procedimientos:
En modo estándar {$mode objfpc}, no hay compatibilidad con la sintaxis delphi, de forma que para poder asignar un puntero a una función hay que hacerlo con esta sintaxis:


delphi
  1. Pointer(OldCreateProcessInternalW):= MyPointer;

 
 En modo compatibilidad con delphi si podremos escribir esto, como estamos acostumbrados:


delphi
  1. @OldCreateProcessInternalW:= MyPointer;

 
La dll debe ser inyectada en el proceso con un código como este COMPILADO EN 64bits:


delphi
  1. // Inject con CreateRemoteThread
  2. // Inyecta en el proceso abierto con el PID dado
  3. function InjectCRT(Pid: integer; dll: PAnsiCHAR): BOOL;
  4. var
  5. hThread: THANDLE;
  6. ExitCode: DWORD;
  7. hLib: LPTHREAD_START_ROUTINE;
  8. hProc: THANDLE;
  9. Buffer: Pointer;
  10. begin
  11. Result:= false;
  12. if(dll^ = #0) then exit;
  13.  
  14. hThread:= 0;
  15. ExitCode:= 0;
  16. hProc:= OpenProcess(PROCESS_ALL_ACCESS, false, Pid);
  17. if hProc<>0 then
  18. begin
  19. Buffer:= VirtualAllocEx(hProc, nil, lstrlen(dll)+1, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE);
  20. if Buffer<>nil then
  21. begin
  22. if(WriteProcessMemory(hProc, Buffer, dll, lstrlen(dll)+1, nil)) then
  23. begin
  24. hLib:= GetProcAddress(GetModuleHandleA('Kernel32.dll'), 'LoadLibraryA');
  25. if hLib <> nil then
  26. begin
  27. hThread:= CreateRemoteThread(hProc, nil, 0, hLib, Buffer, 0, PDWORD(0)^);
  28. if hThread <> 0 then
  29. begin
  30. // libero la memoria localizada...
  31. WaitForSingleObject(hThread, INFINITE); // Espero a que se cree y termine el Thread
  32. GetExitCodeThread(hThread, ExitCode); // Termino el Thread
  33. CloseHandle(hThread); // Cierro el Handle hThread
  34. end;
  35. end;
  36. end;
  37. VirtualFreeEx(hProc, Buffer, 0, MEM_RELEASE); // Libero memoria
  38. end;
  39. CloseHandle(hProc); // Cierro el Handle hProc
  40. end;
  41. Result:= (ExitCode <> 0);
  42. end;

 
Hay que tener en cuenta que lo ideal para poder inyectar a los procesos es corriendo el inyector como administrador, si no, solo inyectará a los procesos del usuario que no corran como adm.
 
El principal creador de procesos es el shell (explorer.exe) al que habrá que inyectar, sabiendo que si la inyección tiene éxito, habrá que matarlo para deshacer la inyección. En este punto, estoy investigando como realizar inyección directa de código para provocar la desinyección en 64bits, tema que está bien resuelto en 32bits. De momento el sistema está fallando para 64bits y me temo que puede ser por una carga de la API en localizaciones distintas a las esperadas, para solventar el problema estoy preparando un shellcode64 parecido al que publiqué aquí, pero con las conversiones a las estructuras del PE64, el tema está bastante avanzado y no descarto publicar algo cuando esté más pulido.

 

La dll la he probado, pero no he inyectado a explorer.exe por lo antes comentado.

 

Subo el proyecto que, como es mínimo, adjunta el binario de la dll de prueba.

 

 

 

Saludos.

Archivos adjuntos


  • 1

#3 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 26 diciembre 2016 - 05:50

Para dar una idea mejor de lo que se puede hacer con el Hook a CreateProcessInternalW, he realizado un pequeño cambio en NewCreateProcessInternalW:

delphi
  1. function NewCreateProcessInternalW(hToken: THANDLE; pApplicationName, lpCommandLine: PWCHAR;
  2. lpProcessAttributes, lpThreadAttributes: PSECURITYATTRIBUTES; bInheritHandles: BOOL;
  3. dwCreationFlags: DWORD; lpEnvironment: Pointer; lpCurrentDirectory: PWCHAR;
  4. lpStartupInfo: PSTARTUPINFOW; lpProcessInformation: PPROCESSINFORMATION; hNewToken: PHANDLE): BOOL; stdcall;
  5. begin
  6. Result:= FALSE;
  7. Windows.Beep(800, 100);
  8. Windows.Beep(1000, 100);
  9. Windows.Beep(2000, 100);
  10. if IDYES <> MessageBoxW(0, 'HAS SIDO HOOCKEADO'#10#10'De verdad quieres ejecutar proceso?', pApplicationName, MB_YESNO or MB_ICONWARNING) then
  11. exit
  12. else
  13. Result:= OldCreateProcessInternalW(hToken, pApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles,
  14. dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation, hNewToken);
  15. end;


Subo el código y binario para pruebas.


Saludos.

Archivos adjuntos


  • 1

#4 Dante

Dante

    Advanced Member

  • Miembros
  • PipPipPip
  • 89 mensajes

Escrito 27 diciembre 2016 - 09:15

muchisimas grasias, ahora una pregunta, q funcion existe para saber  si un proceso  se ejecuta a 64 o 32 bits


  • 0

#5 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 27 diciembre 2016 - 11:39

Para contestar tu pregunta, acabo de publicar este truco: Saber si una aplicación corre como 32 bits en Windows 64


Saludos.


  • 0

#6 Dante

Dante

    Advanced Member

  • Miembros
  • PipPipPip
  • 89 mensajes

Escrito 27 diciembre 2016 - 04:16

Preguntas:

-Como mi aplicacion esta realizada en 32 bit, tengo q realizar una aplicacion intermedia en 64 q inyecte los procesos?

En ese caso cual seria la mejor forma de comunicarme con esta aplicacion para pasarle los procesos q debe inyectar?

-Como llamo a la dll pues no tiene ninguna funcion  exportada, y intente crear un ejemplo en lazaro para inyectar una aplicacion por el pid y no me funciono


php
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8. Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,windows;
  9.  
  10. type
  11.  
  12. { TForm1 }
  13.  
  14. TForm1 = class(TForm)
  15. Button1: TButton;
  16. Edit1: TEdit;
  17. procedure Button1Click(Sender: TObject);
  18. private
  19. { private declarations }
  20. public
  21. { public declarations }
  22. end;
  23.  
  24. function InjectCRT(Pid: integer; dll: PAnsiCHAR): BOOL;
  25. var
  26. Form1: TForm1;
  27.  
  28. implementation
  29.  
  30. {$R *.lfm}
  31.  
  32. { TForm1 }
  33.  
  34. function InjectCRT(Pid: integer; dll: PAnsiCHAR): BOOL;
  35. var
  36. hThread: THANDLE;
  37. ExitCode: DWORD;
  38. hLib: LPTHREAD_START_ROUTINE;
  39. hProc: THANDLE;
  40. Buffer: Pointer;
  41. begin
  42. Result:= false;
  43. if(dll^ = #0) then exit;
  44.  
  45. hThread:= 0;
  46. ExitCode:= 0;
  47. hProc:= OpenProcess(PROCESS_ALL_ACCESS, false, Pid);
  48. if hProc<>0 then
  49. begin
  50. Buffer:= VirtualAllocEx(hProc, nil, lstrlen(dll)+1, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE);
  51. if Buffer<>nil then
  52. begin
  53. if(WriteProcessMemory(hProc, Buffer, dll, lstrlen(dll)+1, nil)) then
  54. begin
  55. hLib:= GetProcAddress(GetModuleHandleA('Kernel32.dll'), 'LoadLibraryA');
  56. if hLib <> nil then
  57. begin
  58. hThread:= CreateRemoteThread(hProc, nil, 0, hLib, Buffer, 0, PDWORD(0)^);
  59. if hThread <> 0 then
  60. begin
  61. // libero la memoria localizada...
  62. WaitForSingleObject(hThread, INFINITE); // Espero a que se cree y termine el Thread
  63. GetExitCodeThread(hThread, ExitCode); // Termino el Thread
  64. CloseHandle(hThread); // Cierro el Handle hThread
  65. end;
  66. end;
  67. end;
  68. VirtualFreeEx(hProc, Buffer, 0, MEM_RELEASE); // Libero memoria
  69. end;
  70. CloseHandle(hProc); // Cierro el Handle hProc
  71. end;
  72. Result:= (ExitCode <> 0);
  73.  
  74. procedure TForm1.Button1Click(Sender: TObject);
  75. begin
  76. if InjectCRT(StrToInt(Edit1.Text),'Hook64.dll') then
  77. MessageBox(0,'inyectado','',0);
  78.  


  • 0

#7 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 27 diciembre 2016 - 04:26

Preguntas:
-Como mi aplicacion esta realizada en 32 bit, tengo q realizar una aplicacion intermedia en 64 q inyecte los procesos?

En principio necesitar un inyector de 32 bits y otro de 64, compilados en sus plataformas respectivas.

En ese caso cual seria la mejor forma de comunicarme con esta aplicacion para pasarle los procesos q debe inyectar?

Puedes crear una app no GUI a la que le pasas los parámetros apropiados desde otra.

-Como llamo a la dll pues no tiene ninguna funcion exportada, y intente crear un ejemplo en lazaro para inyectar una aplicacion por el pid y no me funciono

La dll expuesta no exporta funciones. realiza el Hook al proceso en el que se inyecta. Puedes copiar la técnica de SetWindowsHookEx para que se inyecte automáticamente como te mostré otras veces, y puedes añadirle funciones exportadas.


Saludos.
  • 0

#8 Dante

Dante

    Advanced Member

  • Miembros
  • PipPipPip
  • 89 mensajes

Escrito 03 enero 2017 - 08:30

Trate de pasar Hookdll del antiyect q usted creo para lazaro en modo compativilidad con delphi para agregarle a  esta el hook a CREATEPROCESSINTERNALW, en la unidad APIHook tuve problemas de compativilidad con LongWord y PDWord en la funcion VirtualProtectEx , lo resolvi convirtiendo asi donde me daba error PDWord(OldProtect), tambien en esa funcion me dio problemas el  "PDWORD(nil)^", y lo deje PDWORD(nil), pero en la unit principal de la dll me da un error  en  DllProc := @DllMain; pues no reconose DLLProc, cual es la solucion para esto?


  • 0

#9 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 03 enero 2017 - 11:38

Trate de pasar Hookdll del antiyect q usted creo para lazaro en modo compativilidad con delphi para agregarle a  esta el hook a CREATEPROCESSINTERNALW, en la unidad APIHook tuve problemas de compativilidad con LongWord y PDWord en la funcion VirtualProtectEx , lo resolvi convirtiendo asi donde me daba error PDWord(OldProtect), tambien en esa funcion me dio problemas el  "PDWORD(nil)^", y lo deje PDWORD(nil), pero en la unit principal de la dll me da un error  en  DllProc := @DllMain; pues no reconose DLLProc, cual es la solucion para esto?

Hay que tener cuidado con esos cambios. Lazarus tiene sobrecargadas las definiciones de algunas API que admiten pasar parámetros por referencia o por puntero, hay que saber lo que se hace. No se puede hacer el casting PDWord(OldProtect) alegremente, se debe poner @OldProtect para pasar un puntero. La unidad que publiqué aquí compila bien en Lazarus, de hecho la desarrollé con él y no con Berin. Fíjate que no está {$mode objfpc}{$H+} , precisamente es para obligar la compatibilidad con delphi.

 

Sobre el tema de DllMain, en Lazarus no existe porque es propio de Windows, pero tiene una forma de compatibilizar. Te muestro una fracción de código:


delphi
  1. procedure DllMain(reason: PtrInt);
  2. begin
  3. case reason of
  4. DLL_PROCESS_ATTACH:
  5. begin
  6. InstallHooks;
  7. end;
  8. DLL_PROCESS_DETACH:
  9. begin
  10. UnInstallHooks;
  11. end;
  12. end;
  13. end;
  14.  
  15. procedure Process_Detach_Hook(dllparam: PtrInt);
  16. begin
  17. DllMain(DLL_PROCESS_DETACH);
  18. end;
  19.  
  20. procedure Thread_Attach_Hook(dllparam: PtrInt);
  21. begin
  22. DllMain(DLL_THREAD_ATTACH);
  23. end;
  24.  
  25. procedure Thread_Detach_Hook(dllparam: PtrInt);
  26. begin
  27. DllMain(DLL_THREAD_DETACH);
  28. end;
  29.  
  30.  
  31. begin
  32. Dll_Process_Detach_Hook:= @Process_Detach_Hook;
  33. Dll_Thread_Attach_Hook := @Thread_Attach_Hook;
  34. Dll_Thread_Detach_Hook := @Thread_Detach_Hook;
  35. DllMain(DLL_PROCESS_ATTACH);
  36. end.

Saludos.


  • 0




IP.Board spam blocked by CleanTalk.