Finding the M.I.R.A.C.L.
Hola a todos, puede parecer que voy a encarar un tema religioso en las proximas lineas pero a no equivocarse. Lo que sigue va a ser una serie de articulos dedicados a la criptografia en diferentes crackmes.
Lo primero que note es que cuando me meti con RSA todos me decian: “usa la funcion tatata de euler que sale” y me tiraban una funcion copy/pasteada del tipo
esto me dio la pauta de que muy bien nadie sabe como funciona esto del crypto, y cada vez que preguntas algo te contestan con mas preguntas….. calculo que esa fue la primera piedra en el camino que me encontre, en unos dias le voy a dedicar un post enterito a Euler, pero por ahora vamos con otra cosa.
Si han leido algun tute por ahi sobre crackmes con criptografia RSA habran aunque sea oido de la libreria M.I.R.A.C.L. esta libreria nos ayuda a trabajar con numeros muy grandotes conocidos como BIGNUM, permitiendonos usar los numeros gigantes que manejan en este tipo de retos.
Si nos encontramos con algun programa que use esta libreria, veremos que tiene un monton de funciones inlineadas bastante complicadas de tracear, dichas funciones son de la libreria estatica miracl
basta con ir un rato a http://crackmes.de/ bajarse un reto con crypto echo en MASM y me juego la cabeza a que usaron miracl para algo
estas librerias que se añaden al ejecutable no tienen ningun nombre cuando las vemos con nuestros debuggers favoritos
un ejemplo seria ese CALL que tenemos ahi, si nosotros estariamos reverseando este programa para crackearlo, al ver esa funcion le mandamos F7 y estariamos tratando de entender una funcion de una libreria que ya conocemos. Yo me pregunto:
¿No seria mucho mas bonito que esas funciones tengan nombres y nosotros desligarnos de tener que reconocer esas funciones a mano?
Me parece que ganariamos mucho tiempo al no tener que reversear (y ni siquiera mirar) las 10 o 15 funciones que usa el programa
Nose ustedes pero yo prefiero verlo asi
ya con eso y la documentacion de MIRACL en la mano me parece que es un poquito mas facil, o por lo menos cambia un poco el panorama
Una primera opcion seria abrir el programa con IDA y usar FLIRT para obtener los nombres de las funciones, exportar el map y cargarlo en olly con algun plugin. Pero este acercamiento no me convencia por las siguientes causas:
- si el programa esta packeado, lo tenemos que desempacar 😦
- abrirlo con IDA y dejar que lo analize ya son 2 minutos de vida que se te van 😛
- exportar el map y abrir el olly. ¡Tomatelas! yo estoy haciendo esto para ganar tiempo, no para perderlo
si esto fuera un reto de alguna empresa por algun tipo de premio no darian muchas ganas de perder tiempo. Es por eso que busque otras alternativas y me encontre con un texto olvidado que escribio black-eye en el 2004 sobre como reconocer las funciones de miracl
para ser sinceros el texto no dice nada que el manual no diga, de echo la introduccion es un vivo copy/paste de una parte de la documentacion. Pero me sirvio en su momento para ver que usos podria tener
por ultimo termina el texto diciendo que si alguien escribe un plugin para IDA que use la tecnica esa para reconocer los nombres que lo pase, pero mirando aca y alla se ve que nadie se puso a laburar en 7 años o nadie lo hizo publico
la tecnica se basa en lo siguiente, cuando nosotros llamamos a mirsys, uno de los trabajitos de esta funcion es levantar una especie de tracer que tiene el paquete, el cual en caso de algun error en alguna funcion te avisa en cual fue. Mucho no mire esta parte, pero segun dicen los entendidos en la materia hasta se puede activar una ventana en caso de error, si alguno sabe como que se ponga en contacto asi lo añadimos 😉
ahora llego el momento de la verdad, si no les gusta lo que ven, los invito a cerrar el navegador o irse para otro lado, pero por favor ¡no a los comentarios mala leche!
mirsys retorna un puntero a una estructura de datos que muestra diferentes valores que nos pueden llegar a interesar
a no asustarse, como no tengo muchas ganas de colgar 10 screenshots se los puse todo en uno, la historia es la siguiente:
- puse un BP luego de la llamada a mirsys para mirar el puntero que retorna (valor de EAX), el cual dijimos que tiene la info que nos nutrira en nuestro arte
- puse un “BP on Write Memory” en el 1D, este valor siempre va a estar, creanme…
- corro y veo como para en el “MOV DWORD PTR[EDX+EAX*4+20], 17” para el despabilado se esta moviendo el 17 suplantando el 1D que habia
¿Pero que es este valor? eso valores son unos numeritos que miracl le asigna a cada funcion y lo usa para el tracer de errores en caso de que casquee. Miremos alguna parte del codigo fuente para entenderlo
void fpack(_MIPD_ big n,big d,flash x) { /* create floating-slash number x=n/d from *</em>* big integer numerator and denominator */ mr_lentype s; int i,ld,ln; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif</em> if (mr_mip->ERNUM) return; MR_IN(31)
la linea marcada es la que nos interesa, cada funcion exportada por la libreria tiene un numero asociado, en este caso seria 31 para fpack. Gracias a andrew, Black-Eye and Bart XT tenemos la lista entera.
<pre>MIRACL MAGIC NUMBERS TABLE:</pre> by bLaCk-eye from an original ideea by bF!^k23 innum equ 01h otnum equ 02h jack equ 03h normalise equ 04h multiply equ 05h divide equ 06h incr equ 07h decr equ 08h premult equ 09h subdiv equ 0Ah fdsize equ 0Bh egcd equ 0Ch cbase equ 0Dh cinnum equ 0Eh cotnum equ 0Fh nroot equ 10h power equ 11h powmod equ 12h bigdig equ 13h bigrand equ 14h nxprime equ 15h isprime equ 16h mirvar equ 17h mad equ 18h multi_inverse equ 19h putdig equ 1Ah add equ 1Bh subtract equ 1Ch mirsys equ 1Dh xgcd equ 1Eh fpack equ 1Fh dconv equ 20h mr_shift equ 21h mround equ 22h fmul equ 23h fdiv equ 24h fadd equ 25h fsub equ 26h fcomp equ 27h fconv equ 28h frecip equ 29h fpmul equ 2Ah fincr equ 2Bh ftrunc equ 2Dh frand equ 2Eh sftbit equ 2Fh build equ 30h logb2 equ 31h expint equ 32h fpower equ 33h froot equ 34h fpi equ 35h fexp equ 36h flog equ 37h fpowf equ 38h ftan equ 39h fatan equ 3Ah fsin equ 3Bh fasin equ 3Ch fcos equ 3Dh facos equ 3Eh ftanh equ 3Fh fatanh equ 40h fsinh equ 41h fasinh equ 42h fcosh equ 43h facosh equ 44h flop equ 45h gprime equ 46h powltr equ 47h fft_mult equ 48h crt_init equ 49h crt equ 4Ah otstr equ 4Bh instr equ 4Ch cotstr equ 4Dh cinstr equ 4Eh powmod2 equ 4Fh prepare_monty equ 50h nres equ 51h redc equ 52h nres_modmult equ 53h nres_powmod equ 54h nres_moddiv equ 55h nres_powltr equ 56h divisible equ 57h remain equ 58h fmodulo equ 59h nres_modadd equ 5Ah nres_modsub equ 5Bh nres_negate equ 5Ch ecurve_init equ 5Dh ecurve_add equ 5Eh ecurve_mult equ 5Fh epoint_init equ 60h epoint_set equ 61h epoint_get equ 62h nres_powmod2 equ 63h nres_sqroot equ 64h sqroot equ 65h nres_premult equ 66h ecurve_mult2 equ 67h ecurve_sub equ 68h trial_division equ 69h nxsafeprime equ 6Ah nres_lucas equ 6Bh lucas equ 6Ch brick_init equ 6Dh pow_brick equ 6Eh set_user_function equ 6Fh nres_powmodn equ 70h powmodn equ 71h ecurve_multn equ 72h ebrick_init equ 73h mul_brick equ 74h epoint_norm equ 75h nres_multi_inverse equ 76h nres_dotprod equ 78h epoint_negate equ 79h ecurve_multi_add equ 7Ah ecurve2_init equ 7Bh epoint2_init equ 7Ch epoint2_set equ 7Dh epoint2_norm equ 7Eh epoint2_get equ 7Fh epoint2_comp equ 80h ecurve2_add equ 81h epoint2_negate equ 82h ecurve2_sub equ 83h ecurve2_multi_add equ 84h ecurve2_mult equ 85h ecurve2_multn equ 86h ecurve2_mult2 equ 87h ebrick2_init equ 88h mul2_brick equ 89h prepare_basis equ 8Ah strong_bigrand equ 8Bh bytes_to_big equ 8Ch big_to_bytes equ 8Dh set_io_buffer_size equ 8Eh
Lo que yo hice es cumplir la peticion de black-eye, me hice un script que reconoce las funciones de miracl y le pone el nombre, esta echo en python para Immunity debugger (es un pyCommand), a lo primero trate de hacerlo con OllyScript pero tenia que hacer 1 compare y un salto por cada funcion de miracl, imaginense que son como 200 funciones asi que quedaba un poquito grande.
Solo comento lo que hace y lo cuelgo por si alguno lo necesita:
- Busca todas las funciones.
- Mira si tiene los opcodes “C7 44 ?? 86 ??” ese es el MOV que vimos
- en caso afirmativo agarra el numerito magico y lo usa para indexar un array con los nombres, nos podemos dar ese lujo porque los numeros son consecutivos 😀
- cambia el nombre de la funcion y te avisa a vos
tengan en cuenta que para buscar las funciones use imm.getAllFunctions, esta funcion solo encontrara algo si el codigo esta analizado “Click derecho–>Analisys–>Analize code”
veamos al script haciendo su trabajo
este es un crackme que me encontre por ahi, llegar a la zona caliente es una pavada (en algun otro post lo veremos), ahora carguemos nuestro pyCommand
donde le damos click ahi, se nos abre esta ventana
veamos el codigo ahora
ya tenemos reconocidas las funciones 😀 me parece que ahora esta mucho mas facil la cosa
aca les dejo el pyCommand, no lo cuelgo porque WP no me deja, pero un copy/paste y lo tiran en el pyCommands como cualquiercosa.py
#!/usr/bin/env python __VERSION__ = '0.1' import immlib import re DESC= "locate all function of miracl package" def main(args): imm = immlib.Debugger() miracl = [] miracl.extend(["innum","otnum","jack","normalise","multiply","divide","incr"]) miracl.extend(["decr","premult","subdiv","fdsize","egcd","cbase","cinnum","cotnum"]) miracl.extend(["nroot","power","powmod","bigdig","bigrand","nxprime","isprime"]) miracl.extend(["mirvar","mad","multi_inverse","putdig","add","subtract","mirsys"]) miracl.extend(["xgcd","fpack","dconv","mr_shift","mround","fmul","fdiv","fadd"]) miracl.extend(["fsub","fcomp","fconv","frecip","fpmul","fincr",0,"ftrunc","frand"]) miracl.extend(["sftbit","build","logb2","expint","fpower","froot","fpi","fexp","flog"]) miracl.extend(["fpowf","ftan","fatan","fsin","fasin","fcos","facos","ftanh","fatanh"]) miracl.extend(["fsinh","fasinh","fcosh","facosh","flop","gprime","powltr","fft_mult"]) miracl.extend(["crt_init","crt","otstr","instr","cotstr","cinstr","powmod2"]) miracl.extend(["prepare_monty","nres","redc","nres_modmult","nres_powmod","nres_moddiv"]) miracl.extend(["nres_powltr","divisible","remain","fmodulo","nres_modadd","nres_modsub"]) miracl.extend(["nres_negate","ecurve_init","ecurve_add","ecurve_mult","epoint_init"]) miracl.extend(["epoint_set","epoint_get","nres_powmod2","nres_sqroot","sqroot"]) miracl.extend(["nres_premult","ecurve_mult2","ecurve_sub","trial_division","nxsafeprime"]) miracl.extend(["nres_lucas","lucas","brick_init","pow_brick","set_user_function"]) miracl.extend(["nres_powmodn","powmodn","ecurve_multn","ebrick_init","mul_brick"]) miracl.extend(["epoint_norm","nres_multi_inverse",";null entry","nres_dotprod"]) miracl.extend(["epoint_negate","ecurve_multi_add","ecurve2_init","epoint2_init"]) miracl.extend(["epoint2_set","epoint2_norm","epoint2_get","epoint2_comp","ecurve2_add"]) miracl.extend(["epoint2_negate","ecurve2_sub","ecurve2_multi_add","ecurve2_mult"]) miracl.extend(["ecurve2_multn","ecurve2_mult2","ebrick2_init","mul2_brick"]) miracl.extend(["prepare_basis","strong_bigrand","bytes_to_big","big_to_bytes"]) miracl.extend(["set_io_buffer_size"]) target = imm.getDebuggedName() target_base = imm.getModule(target).getBase() lista = imm.getAllFunctions(target_base) imm.log("PASTAFR0LA FINDING THE MIRACL",highlight=1) imm.log("usage: only run and see the 'M.I.R.A.C.L.E. Functions' windows for information") table = imm.createTable('M.I.R.A.C.L. Functions', ['Address', 'Function']) n = 0 for i in lista: funcion = imm.getFunction(i) ret = max(funcion.getFunctionEnd()) # k = "U8\x90\xCC\x0B\xADf0o\x0D" <-- raw_data # l = ['79','90','CC','0B','AD','70','30','76','0D'] # s = '79-90-CC-0B-AD-70-30-76-0D' <-- opcodes k = imm.readMemory(i, (ret - funcion.getStart())) l = map(lambda x: hex(ord(x)).replace('0x', ''), k) s = " ".join(l) s = s.upper() m = re.search('C7 44 [A-F\d]+ 2[04] ([A-F\d]+)', s) if m is None: continue # -1 porque el arreglo comienza en zero magicnumber = m.group(1) table.add(0,["%X"%(funcion.getStart()),"%s"%(miracl[ int(magicnumber, 16)-1 ])]) imm.setLabel(funcion.getStart(), miracl[ int(magicnumber, 16)-1 ]) n += 1 imm.log("located %d functions of the miracl package"%(n)) return "Done.."
esto es todo amigos, espero que les haya gustado y cualquier sugerencia o critica aqui estoy
Groso! no habia visto este post! buenisimo!.
vos si que sabes apreciar lo bueno jeje
Muy útil. Buen trabajo Joe!.