Hola!,
quienes me conocen, saben que continuamente estoy intentando hacer algo, escribiendo algun tutorial, programando alguna toolcita, etc; ahora, quiero hacer una cosa: por cada nuevo plugin de FUU que haga voy a escribir un post comentando un poco los trucos que utiliza el packer para poder facilmente identificar las zonas importantes a la hora de desempacar.
En este primer post, vamos a hablar de un packer sencillo, exeFog, mas particularmente, nos centraremos en exeFog v1.x, desconozco si existe alguna version 2.x, si alguno tiene un exe, dll, ocx o lo que sea packeado con alguna otra version de exeFog, no tiene mas que enviarla para que la pueda estudiarla y agregarle soporte al correspondiente plugin.
La idea de este y los siguientes post no es la de realizar un analisis detallado sobre el packer como suelo realizar en los tutoriales, sino que veremos las partes importantes nada mas como para vencerlo y que son utilizadas luego en el plugin.
Voy a basarme en este crackme:
http://www.tuts4you.com/request.php?1093Por ejemplo, si cargamos el programa packeado en Olly (sin plugins) y le damos a F9 (Run), veremos que Olly se detiene en una exception, mas especificamente, un DIVISION_BY_ZERO:
Esto se debe a un viejo y conocido truco anti-debug conocido como IsDebuggerPresent pero en este caso, el truco no invocando explicitamente a la API IsDebuggerPresent, sino realizando un inline de esta funcion.
Si comenzamos a tracear, veremos que primeramente, llegamos a un loop en el cual se desexorea codigo, este codigo no es mas que otra parte del stub de desempacado del programa:
Como vemos, primero coloca en EBX un puntero a una zona un poco mas abajo de la instruccion "loopd", coloca en ECX un offset, en este caso "0x3c8" y en AL la key para xorear, en este caso "0x8c", luego, solo va indexando en EBX+ECX y xoreando cada byte, luego, vuelve a tomar otro byte en AL y a repetir la operacion.
Una vez que pasamos esto, si llegamos a la zona del inline IsDebuggerPresent:
Como pueden observar, solo esta accediendo al flag "BeingDebugged" que se encuentra en la PEB:
typedef struct _PEB {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
PVOID Reserved3[2];
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
BYTE Reserved4[104];
PVOID Reserved5[52];
PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
BYTE Reserved6[128];
PVOID Reserved7[1];
ULONG SessionId;
} PEB, *PPEB;
Se encuentra en el campo [2] de la PEB del proceso (movzx eax, byte ptr ds:[eax+2]).
Como vemos, a ese byte, primero le aplica un NOT y luego un AND con 1, con lo cual, si ese byte esta en 1 (quiere decir que el proceso esta siendo debuggeado), el resultado de esas dos operaciones sera 0 y si el byte esta en 0 (quiere decir que el proceso no esta siendo debuggeado) pues el resultado de esas dos operaciones dara 1.
Cual es el truco en todo esto? pues que este valor es utilizado como divisor y dividendo en una division un poco mas adelante:
Como vimos, el resultado del NOT y AND lo colocaba en EBX pero a su vez quedaba en EAX tambien, con lo cual si el resultado del NOT y AND es 0 pues sera 0 / 0 = ERROR!!!.
Para solucionar esto, simplemente debemos de setear ese byte a 0 para que el resultado del NOT y AND sea 1. Podemos hacerlo de varias maneras, la mas rapida es: cuando estemos en el EP (EntryPoint) del packer, simplemente hacemos CTRL+G y ponemos "EBX" y cambiamos el valor del segundo byte a 0. Por que asi? pues porque EBX siempre apunta a la PEB cuando estamos parados en el EP:
Luego, tenemos dos partes importantes mas:
1) Donde resuelve los imports.
2) Donde salta al OEP (Original Entry Point)
Ambas zonas son facil de encontrar, miremos un poco el codigo y vamos a ver que aqui resuelve las dlls importadas por el programa:
Si miramos los registros en este momento, podremos ver que EBX contiene un puntero al string de la dll importada:
Luego, en esta zona, veremos que resuelve las funciones importadas por cada dll:
y si miramos los registros, veremos que EAX contiene el puntero al string de la funcion importada y EDI el puntero al lugar en la IAT donde esa funcion deberia de encontrarse en el programa original:
Ah, antes de continuar, queria comentarles que ademas, exeFog, realiza comprobaciones en los primeros bytes de las APIs a las cuales va a llamar para ver si hay un breakpoint colocado ahi:
Ahi pueden ver un ejemplo de como, luego de resolver la funcion y colocar el puntero en EAX, verifica que el primer byte de esa funcion no contenga un breakpoint (0xCC). Con colocar hardware breakpoints o colocar los breakpoints por software en la segunda instruccion de la API (o en el RET) bastara para bypassear la comprobacion.
Bien, finalmente, el lugar en el cual se salta al OEP es este:
Llegado al "ADD", ESP contiene el offset al EP y EBP la ImageBase del programa, con lo cual, al sumarlo dara como resultado el OEP y al tomar el RET quedaremos parados ahi:
Para realizar el plugin, los pasos que realice fueron los siguientes:
1) Buscar el patron del loop que desexorea el codigo.
2) Pasar el loop anterior y realizar una busqueda de los patrones de codigo que resuelven la IAT, nos dan el salto al OEP y realizan la verificacion de BeingDebugged. Esto lo hago seteando callbacks para cada una de las tareas.
3) Cuando salta el callback en el truco anti-dbg lo unico que hago es colocar EAX en 1 luego el AND y antes del MOV EBX, EAX, con eso me aseguro de que EAX siempre es 1.
2) Cuando salta el callback de LoadLibraryA solo tomo el valor de EAX y lo voy agregando a la IAT.
4) Cuando salta el callback de GetProcAddress simplemente tomo los valores de EAX y EDI y los agrego en la IAT.
La el plugin (dll) lo pueden conseguir aca:
http://tinyurl.com/2arrnctEl source code del plugin lo pueden conseguir aca:
http://tinyurl.com/2wz5btyHasta el proximo post!.