PDA

Ver la Versión Completa : Hook a la API Createprocess


l30
03-07-2007, 23:12:07
Bueno antes de empezar, gracias a todos por la ayuda en los otro hilos, con personas como ustedes si que da ganas de aprender y estudiar.

Quiero que sapan que este tema ya lo e buscado en google y no e encontrado nada en español, a lo mejor no lo e buscado bien, pero bueno allí va:

Quisiera aprender hacer un Hook, a la API Createprocess, para controlar las aplicaciones que se ejecutan en la maquina. Me explico mejor, tengo una lista negra de aplicaciones que no quiero que se ejecuten en la maquina y quisiera controlar eso de esa forma, ya que me parece la mas segura aunque mas difícil.

De antemano gracias por la ayuda que me puedan brindar.

Keiso
05-07-2007, 15:33:49
En trucomania encontrarás la respuesta.

http://www.q3.nu/trucomania/

Ve a 'buscar trucos' y coloca 'CreateProcess' y te aparecerán tres trucos con esta función.

Saludos.

l30
06-07-2007, 04:58:31
Gracias Keiso por tu respuesta, voy a revisar a ver si me sirve.

rounin
08-07-2007, 18:12:28
Hola,

Un ejemplo simple de Hook a la CreateProcess.
Contiene dos proyectos - hook.dll y test.exe.

seoane
08-07-2007, 18:32:25
Muy bueno el ejemplo rounin

dec
08-07-2007, 19:54:47
Hola,

Coincido con seoane; curioso ejemplo rounin. :)

l30
08-07-2007, 22:27:19
El ejemplo esta de maravillas, pero yo pensaba que todo lo que se ejecutaba en la maquina pasaba por el API Createprocess, y por lo tanto podía controlarlo todo desde allí. Me paso lo siguiente, por ejemplo tengo un listado (md5) de aplicaciones que no quiero que se ejecuten en mi maquina, pero por ejemplo pueden hacer un software en delphi.


Edit1.text := ‘Aplicacion no permitida.exe’;
WinExec(pansichar(Edit1.text), SW_SHOWNORMAL);


Y así, ni se entera el programa que se ejecuto esta aplicación, es que tengo que hacerle algún cambio al código o es otra API la que tengo que hacerle el hook.
Por adelantado muchas gracias.

rounin
09-07-2007, 13:17:57
Parece que WinExec esta realizado sin CreateProcess.
Puede ser llama NtCreateProcessEx? No lo se...

l30
09-07-2007, 16:37:51
Muchas gracias rounin (http://www.clubdelphi.com/foros/member.php?u=6918), voy a buscar en google a ver que encuentro de todas maneras si alguien sabes, le estaré muy agradecido.

cHackAll
09-07-2007, 18:39:09
En realidad l30, concuerdo con seoane y dec; este ejemplo esta muy bueno... un saludo al autor ¿? !!!

Te explico de la forma más digerible lo que hace para lo utilices; Todos los procesos tienen una copia en su contexto de las librerías que utiliza, por tal motivo la solución del hilo que iniciaste esta dada por el reemplazo de la API CreateProcess en todos los procesos habidos y por haber. El autor del anterior ejemplo se valió ingeniosamente de la API SetWindowsHookEx para cargarse en todos los procesos que manejen mensajes, de ésta forma casi todos los procesos cargan indirectamente dicha librería... cargada la librería, reemplaza los 32 bits que apuntan a la llamada de la API CreateProcess para parámetros ansi y unicode. Este es el motivo por el que cuando uno corre una consola (cmd.exe), y en ésta ejecuta el chkdsk, no aparece en la aplicación de prueba, la misma eventualidad es apreciable cuando uno crea una aplicación en Delphi que no procesa mensajes.

y bueno como la implementas? sencillo, en la unidad HookCrPr.pas, añade tu línea de comprobación de hash antes de procesar las antiguas APIs por ejemplo:


...
function NewCreateProcessA(lpApplicationName: PChar; lpCommandLine: PChar;
lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
lpCurrentDirectory: PChar; const lpStartupInfo: TStartupInfo;
var lpProcessInformation: TProcessInformation): BOOL; stdcall;
var i: Integer;
begin
if not Allowed(lpCommandLine) then // en el otro hilo induje que utilizabas una función como ésta.
Result := False
else
Result := OldCreateProcessA(lpApplicationName, lpCommandLine,
lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags,
lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
// las restantes lineas hasta las puedes obviar por ser una aplicacion "a medida"
end;
...


// Espero que el autor esté de acuerdo con la modificación de su unidad.

Para que dicha librería funcione en los casos excepcionales comentados anteriormente aconsejo modifiques el tipo de hook en Hook.dpr (WH_MOUSE por ejemplo), pero no creo que sea la solución más efectiva para incluir dichos casos. Personalmente lo que yo haría es listar todos los procesos eventualmente como te mostre en tu anterior hilo, y reemplazar la entrada de llamada de la API en cada uno de éstos al ser necesario, mejor aún; dicho reemplazo solo debe hacerse la primera vez, luego al correr un proceso (puesto que "tu" lo corres), debes reemplazarlas entradas del nuevo procesos creado.

TODOS las llamadas de creacion de procesos (CreateProcess, WinExec y ShellExecute*) llaman en algún momento a la API CreateProcessInternal; GüinDOS trabaja internamente con unicode así que la API que debes reemplazar es la CreateProcessInternalW. ShellExecute llama a una serie de funciones para dar soporte a la función en si, la funcion en la que me quedé en el proceso de debugging es la ShellExecuteExW, sin embargo puedo asegurar que acaba en las "manos" de CreateProcessInternalW.

PD: Claro que llevando el proceso de debugging más a fondo podríamos obtener algo como ésto:

ntdll.dll!_ZwCreateProcessEx@36()
kernel32.dll!CreateProcessInternalW()
advapi32.dll!CreateProcessAsUserW()
wlnotify.dll!ProcessExecRequest()
wlnotify.dll!ExecServerThread()
kernel32.dll!BaseThreadStart()

y pasar por NtCreateProcessEx, pero mientras más nos acercamos al kernel aumentamos el riesgo de nuestra aplicacion, y necesitamos un conocimiento de "bajo nivel" no muy bien documentado. Revisa ésto (http://forums.spybot.info/showthread.php?t=14548&page=4); tambien en otros (http://www.osronline.com/showThread.cfm?link=5102) foros comentan que la API que debemos reemplazar es NtCreateProcessEx, pero eso ya lo dejo a tu propio análisis.

Suerte!

l30
09-07-2007, 22:13:59
Muchas gracias cHackAll (http://www.clubdelphi.com/foros/member.php?u=13492) y a rounin (http://www.clubdelphi.com/foros/member.php?u=6918)e aprendido mucho con ustedes, voy a ver porque me esta dando error esta parte del codigo

if not Allowed(lpCommandLine) then


Me dice que la funcion Allowed no esta definida, voy a revisar a ver que tengo mal.

De nuevo muchas gracias.

No e podido ver los link que me diste porque tengo problemas con la Internet, solo puedo ver algunas paginas mi proveedor de Internet no me a dado respuesta bueno como es gratis se da todo el lujo de hacerme esperar jejejjeje.

cHackAll
09-07-2007, 22:36:06
Amigo l30, la funcion Allowed me la invente (http://www.clubdelphi.com/foros/showthread.php?t=45287) yo en ausencia del conocimiento de tu código... Allowed es una funcion que retorna True cuando se puede correr la aplicacion introducida como parámetro, y retorna False cuando NO se puede correr la aplicacion...

function Allowed(lpFileName: PChar): LongBool;
begin
// Donde abres el archivo en lpFileName, calculas su hash y buscas dicho valor en tu lista de procesos "negros", si la encuentras tu funcion debería retornar False.
end;

Un saludo

l30
09-07-2007, 23:03:25
Disculpa cHackAll por no haberme dado cuanta, te estoy muy agradecido por la ayuda. Voy a probar ahora mismo.

cHackAll
23-07-2007, 17:24:03
Y bueno, no podía quedarme con los brazos cruzados por más tiempo. Alguien inició un hilo pidiendo ayuda para hacer tal cosa osada; no me vino más a la mente que dejarlo pasar pues no es algo que pueda enseñarse como usar una simple API… ahora aprovecho mi tiempo de ocio para dar a las futuras generaciones tal enseñanza del modo mas digerible posible.

Todavía no me queda muy claro cuál fue el motivo para desperdiciar de una forma tan descarada los recursos (me refiero a la forma en que el Güindos administra los procesos y su contexto). Sin embargo funciona independientemente de que sea la forma mas optima en que pueda haber sido realizado (desde mi humilde punto de vista), el funcionamiento no a cambiado substancialmente, pues hasta ahora se siguen explotando fallas lógicas que datan desde el desde el Güindos95.

Al ser cargado (ejecutado) un proceso en memoria, éste carga a su ves las librerías que necesita para funcionar adecuadamente, significa que cada proceso tiene una copia “privada” de las librerías utilizadas. Cada librería tiene funciones, y en una determinada zona tiene una lista de los punteros de las funciones exportadas; una de las formas de realizar un hook, es modificar dichos punteros de una determinada librería para que el proceso en ves de llamar la función exportada, llame a una definida por nosotros, sin embargo las funciones internamente llaman a otras funciones de la misma librería por motivos específicos, y tales llamadas se realizan directamente. Lo que permite hacer otro tipo de hook, realizar un proceso de des-ensamblado a dicha librería y modificar también las llamadas internas. Finalmente se puede realizar un proceso de Debug, sin embargo y como los anteriores requieren un amplio conocimiento y varias horas de dedicación. Esto sin tomar en cuenta a aquellos que explican la realización de un hook al mismo núcleo (kernel):

function NtCreateProcess(lpProcessHandle: PCardinal; dwDesiredAccess: Cardinal; lpObjectAttributes: Pointer; dwParentProcess: Cardinal; InheritObjectTable: LongBool; dwSectionHandle, dwDebugPort, dwExceptionPort: Cardinal): Cardinal; stdcall; external 'ntdll.dll';

Mi hermoso ejemplo funciona de la forma más sencilla posible, y procura no develar directamente sus encantos. Básicamente cuela una llamada al IternalHook, en la misma librería kernel32.dll la API CreateProcessInternalW, sin saber lo que hace llama a nuestra función antes de crear el nuevo proceso. Finalmente la función Decide, recibe los dos parámetros que nos importan; y como esta escrito en el ejemplo escoge cuál de ellos contiene el nombre de la aplicación, por lo que debe ser modificada para detener la creación del nuevo proceso.

library Hook; uses Windows; // by cHackAll

procedure Validate(lpFileName: PWideChar);
begin
if MessageBoxW(0, lpFileName, 'Deseas ejecutar esta aplicacion?', MB_YESNO) = IDNO then
lpFileName[0] := #0;
end;

procedure Decide(lpApplicationName, lpCommandLine: PWideChar); stdcall; // Don't change this declaration!
var
Char: WideChar;
len, pos: Cardinal;
begin
if Assigned(lpApplicationName) then
Validate(lpApplicationName)
else
begin
Char := lpCommandLine[0];
if Char = '"' then
Inc(lpCommandLine)
else
Char := ' ';
Pos := 0;
len := lstrlenW(lpCommandLine);
lstrlenW(lpApplicationName);
while (pos <> len) and (lpCommandLine[Pos] <> Char) do Inc(Pos);
lpCommandLine[Pos] := #0;
Validate(lpCommandLine);
if pos <> len then
lpCommandLine[pos] := Char;
end;
end;

procedure InternalHook; // Don't change!
asm
db 059h,0E8h,000h,000h,000h,000h,051h,08Bh,045h,010h,050h,08Bh,045h,00Ch,050h call Decide
end;

procedure Inject(api, hook: Pointer; var Dummy: Cardinal); // Don't change!
asm
db 083h,0C0h,00Bh,042h,042h,050h,052h,051h,06Ah,040h,06Ah,004h,050h,06Ah,0FFh,051h,06Ah,040h,06Ah,004h, 052h,06Ah,0FFh,08Bh,01Dh
dd VirtualProtectEx+2 db 0FFh,013h,0FFh,013h,05Ah,058h,089h,0C1h,003h,008h,029h,0D1h,089h,00Ah,029h,0C2h,083h,0EAh,006h,089h, 010h
end;

var Dummy: Cardinal;
begin
Inject(GetProcAddress(GetModuleHandle('kernel32.dll'), 'CreateProcessInternalW'), @InternalHook, Dummy); // Dont't use with other APIs
end.

La librería esta exclusivamente diseñada para realizar hook a la API CreateProcessInternalW, pues ésta es la API previa a la creación de un nuevo proceso, y ha sido escrito de tal forma que es un poco más difícil modificarlo.

La forma de puede probar la librería es la siguiente:

uses Windows;
var
si: TStartupInfo = (cb: SizeOf(TStartupInfo));
pi: TProcessInformation;
begin
LoadLibrary('hook.dll');
WinExec('explorer', SW_SHOW);
CreateProcess(nil, 'notepad', nil, nil, False, 0, nil, nil, si, pi);
end.

Probado con Delphi 6, 7se, 2007. bajo Güindos eQuispe & Vista

l30
13-08-2007, 19:20:12
Descúlame cHackAll por no haberte contestado antes, estaba de viaje y no pude acercarme al ordenador ni por un momento. E visto el post y me a dejado con la boca abierta, te estoy muy agradecido por la ayuda.

fide
16-02-2008, 15:45:54
Oyeme, verdad que lo que no esta en clubdelphi no esta en ningun otro lado. Es por eso que lo recomiendo tanto a todos mis amigos...

Lepe
16-02-2008, 18:43:34
Mi hermoso ejemplo funciona de la forma más sencilla posible,

Si, sí, estoy de acuerdo, muy sencillo e intuitivo :D :D

Saludos

jw4v32
29-02-2008, 00:46:56
http://img514.imageshack.us/img514/5192/dibujobh5.jpg

hola a todos esta muy bueno el ejemplo, resulta que tengo un problema lo que yo quiero interceptar es otra API no la de CreateProcess, la de GetDesktopWindow, y resulta que no tengo las habilidades ni los conocimientos de como hacerlo, ademas de eso cuando dicha fucnion sea llamada hacer un windows.beep y guardar el log de la ruta en C:\log.txt, ya se como hacer para que la aplicacion corra sin ventana y demas.



es que creo que tengo algo en la Pc y necesito saberlo, junto con la ruta y ademas, mi antivirus no me sirve (NOD32)


alguien me puede hechar una mano:confused:

cHackAll
29-02-2008, 14:51:57
...yo quiero interceptar ... la de GetDesktopWindow ... cuando dicha fucnion sea llamada hacer un windows.beep y guardar el log de la ruta en C:\log.txt...
...es que creo que tengo algo en la Pc y necesito saberlo, junto con la ruta y ademas, mi antivirus no me sirve (NOD32)...

Hola jw4v32, entiendo lo que deseas hacer pero no entiendo que tiene que ver la API GetDesktopWindow con tener "algo" (por favor explicalo), tampoco entiendo eso de guardar la ruta... de qué, del ejecutable que llama a dicha API?

jw4v32
29-02-2008, 18:07:34
gracias por responder no se si sera posible hacer lo que digo, ps si no no importa, lo de la API GetDesktopWindow andube investigando en una pagina de ayudavirus donde dice que el 99 % de los troyanos actuales usan dicha funcion para capturar el escritorio de la victima (en este caso yo) y mandarla de vuelta (en formato de imagen) al atacante, ps yo tengo varios cartelitos que me aperecen que se que no son de window y que alguien me los manda por ej ("boludo, boludo deja de ver paginas porno Jajajajaja"), se me cierran las ventanas por asi al toque, etc. Pero estoy seguro de que mas de un programa debe de interactuar con dicha API cada 2 por 3 como es el caso del Explorer.exe, pero si el virus esta en formato de libreria (DLL), de proceso ya anlize todo y segun mi son normales, si podria sacarle la ruta a la dll que realiza dicha llamada a la api, entonces podria borrarla normalmente (si estoy 100% seguro de que es esa)entrando a window en modo consola (F8), no se si me explico bien esta ves.:)

FENIXadr
06-04-2014, 03:38:29
Hola gente... voy a quitarle un poco de polvo a este hilo porque me hace mucha falta y no me funciona el ejemplo de rounin... he buscado por muchos lugares y no he encontrado nada que me saque del paso.. el ejemplo de cHackAll me va de mil maravillas .. pero claro ese es para casos puntuales.. necesitaria monitorear todos los procesos (de ser posible) que se crean.. tengo win 7 con delphi 7SE y cuando corro el ejemplo de rounin no hace nada.. no me detecta absolutamente nada... encima el link a la pagina de trucos ya no funciona (http://www.q3.nu/trucomania/).. alguna ayuda por ahi??

desde ya muchas gracias..