Inyecciones de código en memoria
Conocimientos previos:
-ASM
-WinApi
-WinApi
Contenido:
1- ¿Qué es la inyección de código en memoria?
2- ¿Cómo realizarla?
2.1- Teoría
2.2 -Práctica
3- Ejemplos de inyecciones
4- Despedida
1- ¿Qué es la inyección de código en memoria?
La inyección de código en memoria consiste en que otro proceso ejecute el código que nosotros queramos.
2- ¿Cómo realizarla?
2.1 - Teoria
Para realizar la inyección lo que haremos será crear un espacio en el proceso donde queremos inyectar el código con la api VirtualAllocEx a continuación escribiremos nuestro código con WriteProcessMemory y finalmente lanzamos el hilo con CreateRemoteThread
2.2- Práctica
Para poner en práctica la teoría anterior vamos a inyectar nuestra funcion en el proceso del buscaminas y haremos que nuestra función haga un MessageBox:
Código
format PE GUI 4.0 entry start include 'win32ax.inc' Ventana db 'Buscaminas',0 idproc dd ? ID dd ? TamFun dd ? DirFun dd ? start: invoke FindWindow,NULL,Ventana invoke GetWindowThreadProcessId,eax,addr idproc ;idproc = identficador del proceso invoke OpenProcess,PROCESS_ALL_ACCESS,0,[idproc] mov [ID],eax invoke LoadLibrary,"user32.dll" ;cargamos user32.dll invoke GetProcAddress,eax,"MessageBoxA" ;obtenemos la dirección de la api mov [mMessageBoxA],eax ; movemos la dirección de la api a la variable que hay dentro de la funcion qeu inyectaremos mov eax,final ;Obtenemos el tamaño de la función sub eax,Inyectado mov [TamFun],eax invoke VirtualAllocEx,[ID],0,[TamFun],MEM_COMMIT+MEM_RESERVE,PAGE_EXECUTE_READWRITE ;generamos el espacio dentro del proceso mov [DirFun],eax invoke WriteProcessMemory,[ID],eax,Inyectado,[TamFun],0 ;escribimos nuestro código en el proceso invoke CreateRemoteThread,[ID],0,0,[DirFun],0,0,0 ;Lanzamos el hilo. ret proc Inyectado call offset ;Técnica del offset delta. offset: pop ebx sub ebx,offset push ebx ebx pop ecx edx add ecx,titulo add edx,cuerpo push 0 push ecx push edx push 0 call [ebx+mMessageBoxA] ret titulo db 'Me inyecte!',0 cuerpo db 'Este Mensage sale del buscaminas ^^',0 mMessageBoxA dd ? ;variable que contiene la dirección de MessageBoxA@user32.dll endp final: data import library kernel32,'Kernel32.dll',\ user32,'user32.dll' import user32,MessageBoxA,'MessageBoxA',\ FindWindow,'FindWindowA',\ GetWindowThreadProcessId,'GetWindowThreadProcessId' import kernel32,OpenProcess,'OpenProcess',\ GetModuleHandle,'GetModuleHandleA',\ GetProcAddress,'GetProcAddress',\ VirtualAllocEx,'VirtualAllocEx',\ WriteProcessMemory,'WriteProcessMemory',\ CreateRemoteThread,'CreateRemoteThread',\ LoadLibrary,'LoadLibraryA' end data
Como se puede apreciar no es muy difícil pero si plantea un problema grande y es que nuestro ejecutable sabe en que dirección se encuentra la variable mMessageBoxA cuando compilamos pero al inyectar el código la dirección de la variable cambiara… y nuestra función fallara -_- para eso se usa la tecnica del Delta Offset para recalcular la dirección de las variables y que nuestro código se ejecute bien este en la dirección que este. Para entender que hace el delta Offset pinchar Aquí
3- Ejemplo de inyecciónes
Un simple ejemplo que lanza la calculadora, se inyecta en su proceso cambia el nombre a la ventana y hace un MessageBox
Código
Format PE GUI 4.0 entry start include 'win32ax.inc' calc db 'c:\windows\system32\calc.exe',0 pi PROCESS_INFORMATION ? sin STARTUPINFO ? TamFun dd ? ;tamaño de la funcion... DirFun dd ? ; dirección de la funcion DirUser dd ? start: invoke CreateProcessA,0,calc,0,0,0,0,0,0,sin,pi invoke Sleep,2000 invoke LoadLibrary,"user32.dll" mov [DirUser],eax invoke GetProcAddress,[DirUser],"MessageBoxA" mov [mMessageBoxA],eax invoke GetProcAddress,[DirUser],"FindWindowA" mov [mFindWindow],eax invoke GetProcAddress,[DirUser],"SetWindowTextA" mov [mSetWindowTextA],eax mov ebx,final ;obtenemos el Tamaño de la función sub ebx,Inyectada mov [TamFun],ebx invoke VirtualAllocEx,[pi.hProcess],0,[TamFun],MEM_COMMIT+MEM_RESERVE,PAGE_EXECUTE_READWRITE mov [DirFun],eax invoke WriteProcessMemory,[pi.hProcess],eax,Inyectada,[TamFun],0 invoke CreateRemoteThread,[pi.hProcess],0,0,[DirFun],0,0,0 ret proc Inyectada call offset offset: pop ebx sub ebx,offset push ebx pop ecx add ecx,Calculadora push ecx push NULL call [ebx+mFindWindow] push ebx pop ecx add ecx, TituloVen push ecx push eax call [ebx+mSetWindowTextA] push ebx ebx pop edx ecx add ecx,TituloMsg add edx,CuerpoMsg push 0 push ecx push edx push 0 call [ebx+mMessageBoxA] ret TituloMsg db 'Inyectado!',0 CuerpoMsg db 'El código inyectado Cambio el nombre a la ventana',0 TituloVen db 'Este es un título falso',0 Calculadora db 'Calculadora',0 mMessageBoxA dd ? ;Dirección MessageBox mFindWindow dd ? ;dirección fundwindow mSetWindowTextA dd ? ;Dirección de SetWindowText endp final: data import library kernel32,'kernel32.dll' import kernel32,CreateProcessA,'CreateProcessA',\ Sleep,'Sleep',\ GetModuleHandle,'GetModuleHandleA',\ GetProcAddress,'GetProcAddress',\ VirtualAllocEx,'VirtualAllocEx',\ WriteProcessMemory,'WriteProcessMemory',\ CreateRemoteThread,'CreateRemoteThread',\ LoadLibrary,'LoadLibraryA' end data
4- Despedida
Bueno, ya solo queda la despedida…. Jajaja pues eso que espero que les sea utíl el tuto, la barrera de lo que podais hacer con las inyecciones de código la poneis vosotros Saludos.