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
Hook a CreateProcessInternalW con APIHook64
#1
Posted 26 December 2016 - 03:36 PM
#2
Posted 26 December 2016 - 05:05 PM
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.
library Hook64; {$mode objfpc}{$H+} uses Windows, APIHook64, ShellAPI; type PCreateProcessInternalW = function(hToken: THANDLE; pApplicationName, lpCommandLine: PWCHAR; lpProcessAttributes, lpThreadAttributes: PSECURITYATTRIBUTES; bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer; lpCurrentDirectory: PWCHAR; lpStartupInfo: PSTARTUPINFOW; lpProcessInformation: PPROCESSINFORMATION; hNewToken: PHANDLE): BOOL; stdcall; var OldCreateProcessInternalW: PCreateProcessInternalW = nil; function NewCreateProcessInternalW(hToken: THANDLE; pApplicationName, lpCommandLine: PWCHAR; lpProcessAttributes, lpThreadAttributes: PSECURITYATTRIBUTES; bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer; lpCurrentDirectory: PWCHAR; lpStartupInfo: PSTARTUPINFOW; lpProcessInformation: PPROCESSINFORMATION; hNewToken: PHANDLE): BOOL; stdcall; begin Result:= FALSE; Windows.Beep(500, 100); MessageBoxW(0, 'No te dejo ejecutar el proceso', pApplicationName, MB_OK); exit; Result:= OldCreateProcessInternalW(hToken, pApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation, hNewToken); end; //---------------------------------------------------------------------------- // Instalando los Hooks a las API procedure InstallHooks; begin InstallHook(@NewCreateProcessInternalW, Pointer(OldCreateProcessInternalW), 'Kernelbase.dll', 'CreateProcessInternalW', true); end; procedure UnInstallHooks; begin UnInstallHook(Pointer(OldCreateProcessInternalW), 'KernelBase.dll', 'CreateProcessInternalW'); end; begin InstallHooks; 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:
Pointer(OldCreateProcessInternalW):= MyPointer;
En modo compatibilidad con delphi si podremos escribir esto, como estamos acostumbrados:
@OldCreateProcessInternalW:= MyPointer;
La dll debe ser inyectada en el proceso con un código como este COMPILADO EN 64bits:
// Inject con CreateRemoteThread // Inyecta en el proceso abierto con el PID dado function InjectCRT(Pid: integer; dll: PAnsiCHAR): BOOL; var hThread: THANDLE; ExitCode: DWORD; hLib: LPTHREAD_START_ROUTINE; hProc: THANDLE; Buffer: Pointer; begin Result:= false; if(dll^ = #0) then exit; hThread:= 0; ExitCode:= 0; hProc:= OpenProcess(PROCESS_ALL_ACCESS, false, Pid); if hProc<>0 then begin Buffer:= VirtualAllocEx(hProc, nil, lstrlen(dll)+1, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE); if Buffer<>nil then begin if(WriteProcessMemory(hProc, Buffer, dll, lstrlen(dll)+1, nil)) then begin hLib:= GetProcAddress(GetModuleHandleA('Kernel32.dll'), 'LoadLibraryA'); if hLib <> nil then begin hThread:= CreateRemoteThread(hProc, nil, 0, hLib, Buffer, 0, PDWORD(0)^); if hThread <> 0 then begin // libero la memoria localizada... WaitForSingleObject(hThread, INFINITE); // Espero a que se cree y termine el Thread GetExitCodeThread(hThread, ExitCode); // Termino el Thread CloseHandle(hThread); // Cierro el Handle hThread end; end; end; VirtualFreeEx(hProc, Buffer, 0, MEM_RELEASE); // Libero memoria end; CloseHandle(hProc); // Cierro el Handle hProc end; Result:= (ExitCode <> 0); 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.
Attached Files
#3
Posted 26 December 2016 - 05:50 PM
function NewCreateProcessInternalW(hToken: THANDLE; pApplicationName, lpCommandLine: PWCHAR; lpProcessAttributes, lpThreadAttributes: PSECURITYATTRIBUTES; bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer; lpCurrentDirectory: PWCHAR; lpStartupInfo: PSTARTUPINFOW; lpProcessInformation: PPROCESSINFORMATION; hNewToken: PHANDLE): BOOL; stdcall; begin Result:= FALSE; Windows.Beep(800, 100); Windows.Beep(1000, 100); Windows.Beep(2000, 100); if IDYES <> MessageBoxW(0, 'HAS SIDO HOOCKEADO'#10#10'De verdad quieres ejecutar proceso?', pApplicationName, MB_YESNO or MB_ICONWARNING) then exit else Result:= OldCreateProcessInternalW(hToken, pApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation, hNewToken); end;
Subo el código y binario para pruebas.
Saludos.
Attached Files
#4
Posted 27 December 2016 - 09:15 AM
muchisimas grasias, ahora una pregunta, q funcion existe para saber si un proceso se ejecuta a 64 o 32 bits
#5
Posted 27 December 2016 - 11:39 AM
Para contestar tu pregunta, acabo de publicar este truco: Saber si una aplicación corre como 32 bits en Windows 64
Saludos.
#6
Posted 27 December 2016 - 04:16 PM
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
unit Unit1; {$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,windows; type { TForm1 } TForm1 = class(TForm) Button1: TButton; Edit1: TEdit; procedure Button1Click(Sender: TObject); private { private declarations } public { public declarations } end; function InjectCRT(Pid: integer; dll: PAnsiCHAR): BOOL; var Form1: TForm1; implementation {$R *.lfm} { TForm1 } function InjectCRT(Pid: integer; dll: PAnsiCHAR): BOOL; var hThread: THANDLE; ExitCode: DWORD; hLib: LPTHREAD_START_ROUTINE; hProc: THANDLE; Buffer: Pointer; begin Result:= false; if(dll^ = #0) then exit; hThread:= 0; ExitCode:= 0; hProc:= OpenProcess(PROCESS_ALL_ACCESS, false, Pid); if hProc<>0 then begin Buffer:= VirtualAllocEx(hProc, nil, lstrlen(dll)+1, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE); if Buffer<>nil then begin if(WriteProcessMemory(hProc, Buffer, dll, lstrlen(dll)+1, nil)) then begin hLib:= GetProcAddress(GetModuleHandleA('Kernel32.dll'), 'LoadLibraryA'); if hLib <> nil then begin hThread:= CreateRemoteThread(hProc, nil, 0, hLib, Buffer, 0, PDWORD(0)^); if hThread <> 0 then begin // libero la memoria localizada... WaitForSingleObject(hThread, INFINITE); // Espero a que se cree y termine el Thread GetExitCodeThread(hThread, ExitCode); // Termino el Thread CloseHandle(hThread); // Cierro el Handle hThread end; end; end; VirtualFreeEx(hProc, Buffer, 0, MEM_RELEASE); // Libero memoria end; CloseHandle(hProc); // Cierro el Handle hProc end; Result:= (ExitCode <> 0); end; procedure TForm1.Button1Click(Sender: TObject); begin if InjectCRT(StrToInt(Edit1.Text),'Hook64.dll') then MessageBox(0,'inyectado','',0); end; end.
#7
Posted 27 December 2016 - 04:26 PM
En principio necesitar un inyector de 32 bits y otro de 64, compilados en sus plataformas respectivas.Preguntas:
-Como mi aplicacion esta realizada en 32 bit, tengo q realizar una aplicacion intermedia en 64 q inyecte los procesos?
Puedes crear una app no GUI a la que le pasas los parámetros apropiados desde otra.En ese caso cual seria la mejor forma de comunicarme con esta aplicacion para pasarle los procesos q debe inyectar?
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.-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
Saludos.
#8
Posted 03 January 2017 - 08:30 AM
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?
#9
Posted 03 January 2017 - 11:38 AM
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:
procedure DllMain(reason: PtrInt); begin case reason of DLL_PROCESS_ATTACH: begin InstallHooks; end; DLL_PROCESS_DETACH: begin UnInstallHooks; end; end; end; procedure Process_Detach_Hook(dllparam: PtrInt); begin DllMain(DLL_PROCESS_DETACH); end; procedure Thread_Attach_Hook(dllparam: PtrInt); begin DllMain(DLL_THREAD_ATTACH); end; procedure Thread_Detach_Hook(dllparam: PtrInt); begin DllMain(DLL_THREAD_DETACH); end; begin Dll_Process_Detach_Hook:= @Process_Detach_Hook; Dll_Thread_Attach_Hook := @Thread_Attach_Hook; Dll_Thread_Detach_Hook := @Thread_Detach_Hook; DllMain(DLL_PROCESS_ATTACH); end.
Saludos.