Inline Patching Themida 2 Por Torrescrack
Inline Patching Themida 2 Por Torrescrack
Inline Patching Themida 2 Por Torrescrack
patching
themida
2.1.6.0
March 5
2014
torrescrack.blogspot.com
Hace un tiempo Ivinson escribi acerca de unpack/themida de un software hecho en VB, del cual
yo anteriormente haba escrito solo que en esos tiempos estaba empacado con visual protect
segn recuerdo, prob con ese mismo software el mtodo de inline patching que vena
trabajando y vaya que me sirvi para hacer pruebas y mejorar algunos detalles que se me haban
pasado, pero no los aburro y vayamos con eso.
Bien lo primero que haremos para inlinear nuestro binario, ser crear una seccin de cdigo vacia
dentro del mismo, existen varias herramientas para ello, pero en este caso usaremos TOPO,
recuerden que topo creas secciones nuevas y tiene opciones de buscar huecos y usarlos, pero
nosotros crearemos una seccin nueva, tambin tildamos algunas casillas que me facilitan el labor:
Es esencial tildar que nos guarde un backup por si hacemos algo mal y que nos rediriga el EP para
que inicie desde nuestro injerto..
Page 1
Comenzaremos y explicare breve y es un mtodo algo viejo y simple; les cuento, al iniciar una
aplicacin el sistema operativo para cargar un proceso utiliza la API CreateProcess, por lo tanto al
cargar el debugger la primer direccin en el stack o pila ser de retorno a kernel32.dll, bastara en
buscar la direccin donde inicia en memoria la librera y el resto solo es buscar la API
GetProcAddress..
Como muestro al cargar en este caso software dentro del debugger puedo notar que la primer
lnea del stack es una direccin de retorno a kernel32 que es este caso es 0x76823c45 en otro
ordenador las direcciones pueden cambiar.
Ahora bien lo que necesitamos es encontrar el inicio de la librera kernel32, para eso es muy
sencillo pues recodemos que dll y .exe tienen cabecera PE por lo tanto inician con MZ
Ahora si abrimos nuestro IDE RADASM y empezamos a escribir este pequeo cdigo:
Page 2
El cdigo esta comentado, pero bueno primero guardamos todo a la pila para despus recuperarlo
al terminar el meollo, limpiamos el registro ecx y como se desacomodo la pila por el pushad es por
eso que movemos esp +20h, despus lo que se est haciendo es buscar el inicio de la librera y por
ello se descartan los ltimos bytes con and eax, 0fffff000h" y se va restando en 1000h ya que
como todo programa debe estar alineado sea que deben iniciar en una direccin mltiplo de mil,
ahora bien podemos probar con olly carguemos nuestro compilado en olly y veamos:
Page 3
Podemos observar que coloque un BreakPoint al terminar el loop para poder detener el control
cuando pare su ejecucin al terminar la bsqueda corremos el debugger con f9 y veamos el
resultado en EAX y veamos si concuerda con la direccin de kernel32:
Si vamos a esa direccin de memoria para ver el contenido podemos observar lo que estamos
buscando:
Page 4
Ya que estamos ubicados al inicio de la librera, debemos saber que sabemos que 03Ch lugares
mas adelante encontraremos la direccin (RVA) de la cabecera PE. Cambiamos la vista
haciendo click derecho y buscamos 03ch lugares mas adelante:
Como podemos observar 03ch lugares mas adelante, vemos nos indica que el offset de la
cabecera es + F0 lugares mas delante del inicio de la libreria por lo tanto vamos a esa direccin
y vemos el inicio de la cabecera, ahora debemos meter esto en el cdigo conforme vayamos
avanzando:
Page 5
En los comentarios del cdigo explico todo, que bsicamente es lo que hicimos a mano pero
plasmado en el cdigo
lo que nos interesa es la tabla de exportacin lo cual est ubicada siempre a 78h a partir del
PE podramos ver:
0000
Dword
Characteristics
0004
Dword
TimeDateStamp
0008
Word
MajorVersion
000A
Word
MinorVersion
As above
000C
Dword
Name
0010
Dword
Base
0014
Dword
NumberOfFunctions
0018
Dword
NumberOfNames
Page 6
Dword
AddressOfFunctions
0020
Dword
AddressOfNames
0024
Dword
AddressOfNameOrdinals
Tenemos que empezar por la tabla AddressOfNames, la cual contiene un listado de punteros a
direcciones de memoria (RVAs) donde estn guardados lo nombres de las funciones
exportadas:
Dos acotaciones, AddressOfNames contiene una RVA que apunta a un listado de RVAs, no
directamente a los nombres. Adems recordemos que cada una de estas RVA tiene un tamao
double word.
Page 7
En el tercer lugar de esta tabla tenemos un valor (en este caso hipottico es 4) que nos servir
de puntero a la ltima tabla, la AddressOfFunctions:
En el caso de esta tabla, los valores son del tipo Word, esto tambin lo vamos a necesitar luego
cuando realicemos nuestro cdigo.
Vemos que en la cuarta posicin tenemos el valor 005020, esto nos indica la RVA donde vamos
a encontrar el inicio de la funcin buscada en memoria, para que podamos hacer algo como
esto:
call 405020
Recordemos que es una RVA, por lo que tendremos que sumarle la direccin base antes de
utilizarla.
Para que quede un poco mas claro, veamos todo esto en un solo paso:
Page 8
Es un esquema un poco complejo, pero una vez que lo analicemos y luego cuando veamos el
cdigo va a quedar mas claro.
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::
Primero:
Como vemos el cdigo est muy comentado, bsicamente lo que se hace es sumar la direccin
del PE + 78 que es donde se encuentra la ExportTable, obtenemos el RVA y lo sumamos con
20h que segn la descripcin con la tabla de arriba es la direccin de AddressOfNames, y
Page 9
Preparamos dos contadores ponindolos a cero, lo primero que har para ir sumando cada 4
bytes y buscar el nombre de cada api, el segundo (EBP) es para tener un ndice para
posteriormente usarla en la siguientes tablas; lo que se hace en esta parte del cdigo que igual
esta muy comentado para que no se queden con dudas, pero les explico, bsicamente lo que se
hace es comparar cada 4 bytes dentro de AddressOfNames el nombre de la API
GetProcAddress lo cual lo hace por medio de la instruccin cmpsb. Esta instruccin sirve
para comparar cadenas de un byte, donde la primer cadena la tenemos que tener referenciada
con el registro esi y la segunda con el registro edi. (se muestra en el cdigo como se colocan en
edi y esi lo correspondiente)
Por ejemplo si queremos comparar una cadena C con otra D, tenemos que tener lo siguiente:
Page 10
La vamos a utilizar para comparar byte a byte lo que tenemos en memoria con una variable que
definimos con el nombre de la API buscada, de la forma:
GPA
db GetProcAddress ,0
Como solo compara un byte la tenemos que ponerla dentro de otra instruccin: rep (o repe), la
cual repite la instruccin que le sigue la cantidad de veces que le indiquemos en el registro ecx.
Por eso debemos inicializar a ecx con el largo de la cadena a comparar, en este caso
GetProcAddress tiene 14 bytes, o sea que inicializamos a ecx con el valor 0Eh (14 en
hexadecimal).
De toda la rutina anterior lo nico que nos va a importar es justamente el contador que esta
ubicado en el registro EBP, el cual vamos a utilizar como ndice para la prxima tabla.
Si seguimos esta rutina dentro de ollydebugger al finalizar la rutina podramos observar que el
registro EBP (nuestro ndice) guardo lo que queremos:
Page 11
Recuperamos con POP edi,ebx los datos guardados anteriormente en la PILA, sacamos el RVA
de AddresaOfNamesOrdinals y lo sumamos con EDI que contiene el inicio del kernel32 y asi
obtenemos el offset de AddressOfNameOrdinals.
Ahora prepararemos el ndice para acceder al valor de la tabla, para eso tenemos que
multiplicar el contador EBP por dos, esto es porque cada direccin de esta tabla ocupa 2 bytes,
o sea que por ejemplo el cuarto valor de esta tabla lo vamos a encontrar en la posicin 4 * 2.
Es casi lo mismo que las anteriores rutinas, le sumamos a 01ch que es donde est el RVA de
AddressOfFunctions y le sumamos el inicio del kernel32 que est en EDI y luego muevo el
valor del puntero que obtuvimos anteriormente (eax) a esi y lo multiplico por cuatro. Esto es
similar a lo que vimos anteriormente, pero como ahora la tabla es de valores doubleword, debo
multiplicar por cuatro.
En edx tena la direccin obtenida, como es un puntero a otra direccin, lo que hago es obtener
el contenido de esa direccin y luego normalizarla. Al finalizar eax contendr la direccin de
la API que tanto buscbamos
Page 12
Algunos se preguntaran porque me complique tanto la vida si pudo ser mas corto el codigo,
pues es que la idea era que tuviramos un codigo de tal forma que solo haciendo cambios
minimos podramos utiliarlo en cualquier otro inline a themida.
los nicos cambios que deberemos hacer al copiar y pegar el cdigo es cambiar la direccin
donde se encuentra el string GetProcAddress como muestro adelante:
Page 13
Bajamos y casi al final del cdigo injertado podremos ver el jmp que nos agreg topo para
redirigir a la zona donde estaba el punto de entrada y como no usaremos esa parte metemos el
string GetProcAddress en esa direccin y modificamos muestra la imagen de arriba.
Page 14
Bien ahora guardamos los cambios y listo empecemos con lo dems que es la parte interesante,
como sabrn este cdigo lo que hace es que al terminar nos devuelva el offset de
GetProcAddress y lo que hace esa API es devolvernos la direccin de cualquier API que le
pidamos, con eso podemos sacar mas apis, que en este caso la nica que quiero es
CreateThread que bsicamente nos sirve para crear un hilo y se preguntaran que haremos
con ese hilo?, sencillo un hilo que vaya buscando los bytes ya descifrados en memoria (pues
recordemos est cifrado) conforme sigue la ejecucin del software y ya una vez encontrados
procedemos a parchear, algo similar lo explique en el cdigo de un loader simple, que mostr
en el elladodelmal, segn recuerdo;
http://www.elladodelmal.com/2014/02/loader-simple-acceder-al-binario.html
veamos la informacin de los parmetros que necesitamos meter para usar GetProcAddress:
Solo son dos parmetros, el primero es la direccin de la dll que contiene a la API que en este
caso es kernel32.dll lo cual esa direccin ya la tengo por algn lado del stack guardada, el
segundo parmetro es el nombre de la API que esa la ubicaremos cerca de donde ubicamos el
nombre de GetProcAddress veamos cmo quedara:
Page 15
Aqu movemos al registro ECX la direccin del kernel32 que como vemos en la pila quedo
ubicado en ESP-8, despus metemos los parmetro que ya haba comentado y hacemos una
llamada a EAX que contiene la direccin de GetProcAddress, si pasamos esas instrucciones
podemos observar que el resultado est en el registro EAX devolvindonos la direccin de la
API que necesitamos:
Vaya ahora bien en cdigo les explico los parmetros que debemos meter como lo hicimos
anteriormente pero ahora para cargar nuestro hilo:
Todo es NULL o 0 y lo nico que debe importarnos es ubicar en algn registro la direccin
donde queremos poner nuestro hilo y quedara algo as en el cdigo injertado:
Page 16
Como vern meti en el registro ECX un offset que ser donde ubicaremos nuestro loop para
buscar cdigo y ser nuestro hilo (ignoren el ultimo JMP lo ubique para probar si el hilo
era tomado) por lo tanto con esto avanzado podramos recuperar los valores de la pila a como
estaban con la instruccin POPAD (recuerden que al inicio colocamos un pushad para salvar
los registro en la pila) y regresar a donde originalmente iniciaba el programa y tendramos un
hilo corriendo en paralelo buscando los bytes a parchear que adelante mostrare, mientras
pongamos el cdigo restante para devolver la ejecucin al inicio del programa como
normalmente comenzara:
Recuperamos los registros y ponemos un salto a donde iniciaba el programa antes de agregar la
seccin con topo, antes de guardar los cambios que ya hemos hecho, pasemos al offset donde se
encontrara el hilo y metamos el cdigo, pero antes recordemos algo en qu direccin se
ubicaba el salto que queramos cambiar (no tocare detalles de crackeo del software) , pero
quiero mostrarles como luce cuando an no es ejecutado el programa y el cdigo est cifrado:
Page 17
Cifrado:
Descifrado:
Ahora bien, los bytes descifrados son los siguientes y por lo tanto los que deberamos buscar en
nuestro loop son los siguientes:
Como ven se marcan en rojo los cambios que hice cambie el salto JE (condicional) por un JMP
para que salte siempre sin excepcin, solo cambia un byte (EB) con el parche que queremos
colocar, por lo tanto una vez encontrado en memoria cuando se ha descifrado el programa
parchearemos ese byte y colocaremos EB y listo.
Page 18
Como vimos hace una bsqueda de los bytes y sigue repitindose el loop hasta que los
encuentra y pasa guardar lo bytes nuevos en esa direccin que como vern solo cambia el EB
y mas abajo coloque un loop infinito (solo para probar lo que ya hemos hecho, si dejamos esto
asi el loop infinito consumira muchos recursos) podramos hacer mas cosas como cerrar el
hilo, poner un sleep o demas cosas, el tema es que ya terminamos de hacer toda la mquina de
un inline patching y esto era bsicamente lo que quera mostrarles! Y ojala que les sirva de algo
esto ya que me tomo muchas horas armarlo .
Antes de terminar, les cuento que hace un rato hable con guan de dio y le platique la idea de
hacer una tool con un mtodo general para hacer inline patching a themida, osea automatizar
todo esto que hice a mano en una herramienta que bsicamente haga lo siguiente: nos pida
offset y bytes nuevos a colocar en la direccin y listo hara todo lo que tarde horas en 2
segundos, creo que podra ser una excelente herramienta para inlinear a themida, cabe
mencionar que ya he probado el cdigo con diferentes sistemas operativos y repare detalles que
causaban problemas, sin mas les mando un saludo y si alguien se quiere unir al proyecto espero
sus comentarios! , saludos a todos!
Alejandro (torrescrack)
Page 19