Como prueba de mi interés...
Me gustaría disponer de ese código delphi al completo, como prueba no mostraré mis desastres en delphi, mostraré un medio éxito en fasm(si se me permite) que es a propósito del tema en cuestión, debido a las múltiples pruebas que realicé puede contener comentarios de lineas de código ya extintas, asi como variables que no se usan, creo que este era el código que era capaz de inyectar una función en la api drawtextw(tengo varias pruebas), aunque no parece cambiar los textos antes de ser escritos, ... para muestra un botón...
Api Hooking por inyección de código, aproximación en fasm.
Código:
include 'd:\fasm\include\win32ax.inc'
.data
HookApi db 'DrawTextW' , 0 ; Nombre del api a hookear
HookDll db 'user32.dll' , 0 ; Nombre de la dll que contiene el api a hookear
dirapi dd ? ; Dirección del api a hookear
texto db 'hello'
process dd ? ; El handle del proceso donde inyectaremos
pid dd 1240 ; El pid del proceso donde inyectaremos--estesalio del taskmanager y fue notepad
;PONER PID ADECUADO Y COMPILAR DE NUEVO
x dd 5
; --------------------api DrawTextW
;
;-------------------------------------- total 5 bytes si esta es la teoría lo dijo ollydbg y punto.
; El número de bytes que tiene al principio el api a hookear (suelen ser 5 ó 7)
buffercall dd ? ; Puntero al buffer para llamar al api (en nuestro propio proceso)
inibuffer dd ? ; siempre guardada la direccion original del inicio del buffer
inidirapi dd ? ; siempre guardado el inicio del api
inifun dd ? ; siempre guardado el inicio de mi funcion
tamfun dd ? ; Tamaño de la función que suplantará al api
;----------------------------------------------------------------------------------------------
dircode dd ? ; La dirección donde esta escribe la estructura una vez INYECTADA
Prote dd ? ; Necesario para VirtualProtect
saltoapi dd ? ; la direccion calculada a la api+5
buffsaltoami dd ?
tamtotal dd ? ;1+tamfun+1+5+5
.code
start:
; Obtenemos el handle del proceso donde inyectaremos
mov eax, PROCESS_VM_OPERATION
or eax, PROCESS_VM_WRITE
; mov eax,PROCESS_ALL_ACCESS
invoke OpenProcess, eax, FALSE, [pid]
mov [process], eax ;
; Obtenemos la dirección del api a Hookear
invoke GetModuleHandle, HookDll
invoke GetProcAddress, eax, HookApi
mov [dirapi], eax ; vale la dir de la api
mov [inidirapi],eax ; siempre guardado sin alterar el inicio
;Vamos a ver , reservamos espacio para pushad+(tamaño de mi funcion)+popad+(5 bytes de la api)+jmp dirapi+5 =
; 1+tamfun+1+5+5
;ahi es na
;a ver el tamaño de la función
; Calculamos el tamaño de la función a inyectar
mov eax, FIN_drawtextexw
sub eax, Mydrawtextexw
mov [tamfun], eax
;pues eso
; 1+tamfun+1+5+5
;
mov eax, 1
add eax, [tamfun]
add eax,1
add eax,[x]
add eax,5
mov [tamtotal],eax ; tamtotal tiene el tamaño del buffer
invoke LocalAlloc, LPTR, [tamtotal] ; espacio local reservado para escritura del buffer
mov [buffercall], eax ; aqui la direccion inicio del buffer
mov [inibuffer],eax ;aqui también para no perderla, por variables va a ser
mov eax,[buffercall]
mov byte [eax],0x90 ; 60 pushad 90 es nop
inc eax
mov [buffercall],eax ;puesto el opcode e incrementado el buffer
;ahora a copiar aqui la funcion
mov ebx,CAMBIO ;direccion de la funcion
mov [inifun],ebx ;aqui tambien, no perderla
invoke RtlMoveMemory, [buffercall],ebx,[tamfun]; la función al buffer
mov eax,[buffercall]
add eax,[tamfun] ; incrementamos el buffer hasta el fin de la funcion
mov [buffercall],eax
; copia la funcion y ademas incrementa buffercall
;ahora el opcode de popad 61 90 es nop
mov eax,[buffercall]
mov byte [eax],0x90 ;despues de la funcion pues popad o noP
inc eax
mov [buffercall],eax ;uno mas para empezar con la api
;ahora vienen los 5 bytes de la api
;los bytes del api al final del buffer, pero le resto 4, si no no rula
mov eax, [buffercall]
sub eax,4
mov [buffercall],eax
; visto con ollydbg
invoke WaitForInputIdle,[process],1000 ; si señor, esto ya es otra cosa, si no peta.
; desde dirapi 5 bytes al buffer
invoke RtlMoveMemory, [buffercall], [dirapi], [x] ; Copiamos los x primeros bytes del api
mov eax, [buffercall]
add eax, [x] ;entonces incrementamos el buffer en x bytes
mov [buffercall],eax
; se supone que ahora lo que falta es el salto a la api+5 (o +4?)
;para esto necesito la direccion donde voy a inyectar el codigo
mov eax, MEM_RESERVE
or eax, MEM_COMMIT
invoke VirtualAllocEx, [process], NULL, [tamtotal], eax, PAGE_EXECUTE_READWRITE
mov [dircode],eax ;direccion para inyectar el codigo en proceso remoto
;dirapi debe estar mas arriba
mov eax,[dirapi];no ha cambiado, la seguimos usando entonces
add eax,5 ; ya cambio, dirapi es ahora dirapi+5
mov ebx,[dircode]
add ebx,[tamtotal] ; ja! el salto es desde el final del jmp o justo desde antes?
; que problema no saberlo, intentemos asi y si no decremento 4 o 5, 4 despues del jmp
; antes de los 4 bytes del salto, 5, antes del jmp y los 4 bytes del salto.
sub eax,ebx
; a ver si... (dirapi+5)-(dircode+tamaño total buffer)=direccion del salto a api+5
mov [saltoapi],eax
mov eax,[buffercall]
mov byte [eax],0xE9
inc eax
mov [buffercall],eax ;insertado opcode jmp e incrementado buffer
mov ebx,[saltoapi]
; coño, el salto se queda 4 bytes corto!!!!!!!
;
add ebx,4 ;asi supongo que salte donde debe
mov dword [eax],ebx; con esto se suponen 4 bytes del dword del salto
;ahora podemos escribir el buffer en el espacio de la aplicacion
;que previamente reservamos
;debemos indicar el tamaño total claro
;el buffer se supone escrito, ahora lo volcamos en el proceso remoto
;invoke VirtualProtect, [dircode-5],[tamtotal+5],PAGE_EXECUTE_READWRITE,NULL
invoke WriteProcessMemory, [process],[dircode],[inibuffer],[tamtotal],NULL
; y ahora claro esta tendremos que insertar el salto en la api
; a nuestro codigo
; si dirapi esta por encima como coño hago un salto negativo?
; y además permisos a los 5 bytes de la api claro esta
invoke LocalAlloc, LPTR, 5
mov [buffsaltoami],eax
mov eax,[dircode]
mov ebx,[dirapi]
sub eax,ebx
sub eax,5; por algun motivo que no se, salta a la dirección
;no entiendo yo este problema con los... si lo pongo salta desde api a pushad
;sino lo pongo salta bytes mas allá. Asi que ...
mov [saltoapi],eax ;mmmmmmm dir del salto
mov eax,[buffsaltoami]
mov byte [eax],0xE9
inc eax
; mov [buffsaltoami],eax
mov ebx,[saltoapi]
mov dword [eax],ebx
mov eax, MEM_RESERVE ; eax = MEM_RESERVE | MEM_COMMIT
or eax, MEM_COMMIT
invoke VirtualAllocEx, [process], [dirapi], 5, eax, PAGE_EXECUTE_READWRITE
invoke WriteProcessMemory, [process], [dirapi], [buffsaltoami], 5, NULL
; y colorin colorado...
invoke ExitProcess,0
CAMBIO:
proc Mydrawtextexw dc, lpstring,ncount,lprect,uformat
nop
mov byte [lpstring],0x41
mov byte [ncount],1
nop ;referencias mias en la inyección
endp
FIN_drawtextexw:
.end start
- Se supone que la filosofia de esto es:
-en el inicio de la función api se inserta un salto a una función propia.
-después de ejecutar la nueva función, se inserta en esta otro salto a la
api original posterior al salto a nuestra función.
|