Flynn me mando este texto explicando esta proteccion que lleva el Cobra, espero que sirva para abrir los ojos a aquellos interesados en reversar los dumps.
COBRA RTOC TRICK EXPLAINEDEl JIG Cobra posee diversas medidas de proteccion para asegurar que su codigo no podria ser utilizado de forma correcta aun en el caso de que su codigo pudiera ser dumpeado.
Este truco en el registro rtoc es el primero utilizado para este fin aparte de dificultar el analisis.
El registro rtoc es inicialmente guardado en la pila para conservar el rtoc del lv2 y poder recuperarlo posteriormente:
# =============== S U B R O U T I N E
cobra_syscall_sm_shutdown_hook: # CODE XREF: syscall_379 j
.set arg_20, 0x20
.set arg_28, 0x28
.set arg_30, 0x30
.set arg_38, 0x38
.set arg_40, 0x40
mflr %r0
std %r0, arg_20(%sp)
std %rtoc, arg_28(%sp)
En este punto tenemos que explicar que es el DELTA OFFSET.
El DELTA OFFSET es un metodo usado en el x86, en sus momentos originales en la creacion de virus informaticos,
para poder calcular la direccion de memoria en la que nos encontramos dentro del mar de bytes en la RAM.
En los momentos originales un virus informatico no sabia cuando arrancaba donde se encontraba dentro de un ejecutable,
pues dependiendo del ejecutable podia estar en un sitio inicial u otro, para ello se invento el DELTA OFFSET.
El DELTA OFFSET puede ser usado en cualquier sistema, el procedimiento es:
- Usando el registro que indica la direccion actual de ejecucion (o la siguiente dependiendo del sistema)
- Restandole el tamaño del codigo previo que usamos a este valor obtenido desde el registro.
Sabiendo esto, y tomando por ejemplo el procesador x86 donde el registro EIP no puede ser leido directamente se invento el truco
de hacer una llamada a una "subfuncion" que es simplemente la siguiente linea a la llamada:
call x
x:
pop eax
La instruccion call en x86 guarda en la parte superior de la pila la direccion de la instruccion siguiente asi misma.
De esta forma usando pop extraemos de la parte superior de la pila este valor, y se guarda en eax por ejemplo, ya teniendo la direccion de memoria
en donde estamos, solo faltaria restar lo anterior y ya tenemos el calculo exacto.
En el PowerPPC podemos usar este truco usando la instruccion equivalente que es BL (BRANCH LINK), la cual salta a una "subfuncion" pero antes guarda
en el registro LR la direccion siguiente al BL.
bl _delta_offset
_delta_offset:
En este punto vemos el truco usado para la creacion del rtoc del cobra en este momento.
Si nos fijamos tanto r0 como rtoc son pasados a 0:
li %r0, 0
li %rtoc, 0
Posteriormente se le da el valor 0x11DE0 a rtoc:
oris %rtoc, %rtoc, 1
ori %rtoc, %rtoc, 0x1DE0
A r0 se le da el valor 0x920:
oris %r0, %r0, 0
ori %r0, %r0, 0x920
Se le resta a r0 el valor de rtoc:
subf %r0, %r0, %rtoc
A diferencia del x86 en PowerPPC el registro LR se puede leer directamente con la instruccion mflr, ponemos en rtoc el valor obtenido por el delta offset:
mflr %rtoc
Para calcular el delta offset final restamos las instrucciones anteriores ejecutadas al delta offset, que eran 4, es decir 16 bytes:
addi %rtoc, %rtoc, -0x10
Por ultimo le sumamos el valor de r0 al rtoc final del delta offset, guardando el resultado en el rtoc, siendo este ya el rtoc cobra adecuado para este hook, :) :
add %rtoc, %rtoc, %r0
Ya teniendo el cobra rtoc se guardan en la pila los 3 argumentos que el hook recibio:
std %r3, arg_30(%sp)
std %r4, arg_38(%sp)
std %r5, arg_40(%sp)
Se llama a la funcion del cobra en donde se chequeara el primer argumento en busca del comando 0x8202 (un comando especial a lo habitual, :)) :
bl cobra_syscall_sm_shutdown
Tras hacer lo necesario en el cobra, se recupera de la pila el rtoc original, al igual que los argumentos que el hook recibio, se ejecuta la instruccion original
que fue sobreescrita en la entrada de la syscall 379 (en este caso) para tener nuestro hook, y se llama a la syscall original del lv2:
ld %rtoc, arg_28(%sp)
ld %r3, arg_30(%sp)
ld %r4, arg_38(%sp)
ld %r5, arg_40(%sp)
mfcr %r12
bl original_syscall_sm_shutdown
Al volver se recupera el LR original desde la pila y se vuelve a lo que el indique, :)
ld %r0, arg_20(%sp)
mtlr %r0
blr
# End of function cobra_syscall_sm_shutdown_hook