Título: [Script]Generic OEP Finder por UND3R
Publicado por: .:UND3R:. en 5 Septiembre 2011, 10:29 am
Este es mi primer script, está orientado en la búsqueda del OEP de manera genérica, una serie de métodos que están basados en el tutorial de introducción de ricardo narvaja, el objetivo de este script es poder optimizar la búsqueda de script, evitando realizar comandos repetitivos que ralentizan y demoran el trabajo de obtener un OEP, los métodos de este script son los siguientes: -PUSHAD-POPADuna vez realizado este método, podemos buscar los siguientes Opcodes: push ebp,push 0 -EXCEPCIONESEste método consiste en colocar un BPM después de pasar por la última excepción nos da la posibilidad de que si no sabemos cual es, el script en el registro (log)nos mostrará una vez que estemos en la última excepción, nos da la posibilidad de dirigirnos en el retorno de la excepción para luego poder combinarlo con el método de bpmx(opcional) -BPMX(Memory Breakpoint on execution)este nos pedirá como requerimiento tener nuestro ollydbg parcheado (parcheado 4),nos preguntará en cual sección deseamos colocar el memory breakpoint on execution -API COMÚN POR PACKERColoca un BP GetProcAddress la última vez que es llamada desde el packer, si no sabemos nos da la posibilidad de logear las veces que son llamadas (el address a colocar no necesariamente debe ser el último, si no el último que es llamado desde la sección del packer) -API COMÚN POR PROGRAMAEste nos da la posibilidad de poder colocar un bp en 2 apis muy usadas al inicio de los programas: GetModuleHandleA,GetVersion una vez que se detiene el programa se debe buscar el retorno y subir unas cuantas lineas Script: /* -=================================================================- .:[CracksLatinoS]:. Script realizado por :UND3R Script para : Generic OEP finder Configuracion: Plugins Break on Execution o OllyDbg parcheado (cuando sea requerido por el script) Fecha : 05/09/2011 -=[ Comentario del Script ]=- Agradecimientos:Apuromafo,Karmany,MCKSys Argentina,Tinkipinki por brindarme siempre ayuda cuando la necesito y a todos los de CracksLatinoS -=================================================================- */ START: ASK "Métodos:Pushad-Popad(1),Excepciones(2),BPMX(3),API packer(4),API programa(5),Salir(x)" cmp 1,$RESULT //compara el resultado de ask con 1 je PUSHADPOPAD //si el resultado es 1 se dirijirá al label PUSHADPOPAD CMP 2,$RESULT //compara el resultado de ask con 2 JE EXCEPCIONES //si el resultado es 2 se dirijirá al label EXCEPCIONES CMP 3,$RESULT //compara el resultado de ask con 3 JE METODOBPMR //si el resultado es 3 se dirije al label METODOBPMR CMP 4,$RESULT JE MUY_USADA_PACKER CMP 5,$RESULT JE MUY_USADA_PROGRAMA CMP "x",$RESULT //compara el resultado de ask con x JE SALIRDELSCRIPT //si el resultado es x terminará el script CMP 0,$RESULT JE SALIRDELSCRIPT
PUSHADPOPAD: VAR AUX2 //declara una variable VAR AUX //declara una variable VAR KIUSER //declara una variable VAR ZWCONT //declara una variable VAR entrypoint //declara una variable GPA "KiUserExceptionDispatcher", "ntdll.dll" //devuelve el address de una api MOV KIUSER, $RESULT //mueve el resultado de la operacion anterior a KIUSER BP KIUSER //coloca un bp en la address que apunta KIUSER GPA "ZwContinue", "ntdll.dll" //devuelve el address de una api MOV ZWCONT, $RESULT // mueve el resultado de la operación anterior a ZWCONT BP ZWCONT //coloca un bp en la address que apunta ZWCONT MOV entrypoint,[eip],1 //mueve el primer byte de eip a la variable entrypoint CMP entrypoint,60 //compara entrypoint con 60 (equivale a un pushad) JE PASO1 //si el primer opcode es pushad salta TICND "byte [eip]==60" //tracea hasta encontrar un pushad PASO1: STI //Step into (F7), para ejecutar el pushad MOV AUX,esp //mueve el valor de esp dentro de la variable AUX INICIO: BPHWS AUX, "r" //coloca un hadware breakpoint on access en AUX TRABAJO: EOB COMPROBAR // si ocurre una excepción o un bp se dirije a COMPROBAR RUN //se ejecuta ollydbg (f9) COMPROBAR: CMP eip,KIUSER //compara eip con KIUSER JE QUITAR //si estamos en KiUserExceptionDispatcher irá a quitar BPHWS CMP eip,ZWCONT //compara eip con ZWCONT JE RESTAURAR //si estamos en ZwContinue irá a restaurar CMP eip,AUX2 //compara eip con el retorno de una excepción JE RESTAURAR2 //si estamos en el retorno irá a restaurar2 JMP SALIR //terminado todo se dirige a salir QUITAR: BPHWC //quita el BPHWS JMP TRABAJO //salta a trabajo RESTAURAR: MOV AUX2,[ESP+4] //introduce el valor de CONTEXT a AUX2 ADD AUX2,0b8 //le suma 0b8 para saber a que lugar retomará una vez pasada la excepción BP AUX2 //sabiendo el retorno coloca un BP en ella JMP TRABAJO //salta a trabajo RESTAURAR2: BC AUX2 //elimina el BP del retorno de la excepción JMP INICIO //salta a INICIO para volver a colocar el BPHWS SALIR: BPHWC //limpia todos los BPHWS BC //limpia todos los bp MSGYN "Aproximación terminada,desea buscar OPcodes?" CMP 1,$RESULT //compara resultado con 1(YES) JZ BUSCAR_PUSH_EBP //si la comparación anterior se cumple salta al laber BUSCAR_PUSH_EBP JMP START //retorna al menú principal
EXCEPCIONES: VAR BORRARZWCONTINUE //declara una variable VAR ZWCONTINUAR //declara una variable VAR COMPRO_MSG //declara una variable VAR EXCEPCION_ENCONTRADA //declara una variable VAR ZXCVAR //declara una variable VAR ZWCONTIN //declara una variable VAR ESP14 //declara una variable VAR EXCEP //declara una variable VAR KIUSEREXCEP //declara una variable GPA "KiUserExceptionDispatcher", "ntdll.dll" //devuelve el address de una api MOV KIUSEREXCEP,$RESULT //mueve el address de la api a la variable KIUSEREXCEP ASK "Introduzca la última excepción, si no sabe cual es introduzca 0" MOV EXCEP,$RESULT CMP 0,EXCEP //compara con 0 JZ BUSCADOREX //si es 0 irá a BUSCADOREX
BUSCADORCOND1: BP KIUSEREXCEP //coloca un bp en la variable KIUSEREXCEP BUSCADORCOND2: EOB BUSCADORCOND3 //si existe una excepción o bp se dirige a BUSCADORCOND3 RUN //F9 BUSCADORCOND3: MOV ESP14,[esp+14] //Mueve el valor de [esp+14] en ESP14 CMP ESP14,EXCEP //Compara si el valor es el mismo que la excepción introducida en el ask JE ZXC //si se cumple se dirijirá al label ZXC JMP BUSCADORCOND2
BUSCADOREX: MSG " El programa se ejecutará,una vez ejecutado se debe reiniciar (Control+F2)" MSGYN "Las excepciones serán registradas en el log de OllyDBG,desea que estas también aparescan como MSG?" MOV COMPRO_MSG,$RESULT BP KIUSEREXCEP //Coloca un BreakPoint KIUSEREXCEP BUSCADOREX2: EOB BUSCADOREX3 //Si existe una excepción o un Breakpoint va a BUSCADOREX3 RUN BUSCADOREX3: MOV EXCEPCION_ENCONTRADA,[esp+14] cmp COMPRO_MSG,0 JE BUSCADOREX4 EVAL "La última excepción por el momento es en la dirección:{EXCEPCION_ENCONTRADA}" MSG $RESULT BUSCADOREX4: LOG EXCEPCION_ENCONTRADA JMP BUSCADOREX2
ZXC: EVAL "El programa se ha detenido en la excepción: {EXCEP}" MSG $RESULT MSGYN "Desea continuar en el retorno de la excepción?" CMP 1,$RESULT JE RETORNOEXCEP BPHWC BC JMP START RETORNOEXCEP: BC GPA "ZwContinue", "ntdll.dll" BP $RESULT MOV BORRARZWCONTINUE,$RESULT RETORNOEXCEP2: EOB RETORNOEXCEP3 RUN RETORNOEXCEP3: CMP eip,$RESULT JZ RETORNOEXCEP4 CMP eip,[ZWCONTINUAR] JZ RETORNOEXCEP5 JMP RETORNOEXCEP2 RETORNOEXCEP4: MOV ZWCONTINUAR,[esp+4] LOG ZWCONTINUAR ADD ZWCONTINUAR,0b8 BP [ZWCONTINUAR] JMP RETORNOEXCEP2 RETORNOEXCEP5: BC BORRARZWCONTINUE EVAL "Retorno de la excepción EIP:({eip})" MSG $RESULT JMP START
METODOBPMR: MSG "Este método consiste en colocar un MemoryBreakPoint on EXECUTION,Se requiere el plugins Break On Execution o un OllyDbg parcheado para continuar"
VAR CONTADORBPM2 //establece una variable VAR CONTADORBPM //establece una variable VAR MODULOPESIGNA3 //establece una variable VAR VIRTUAL_ADDRESS //establece una variable VAR SIZE_OF_SECCION //establece una variable VAR NAME_OF_SECCION //establece una variable VAR MODULOPESIGNA2 //establece una variable VAR MODULOPESIGNA //establece una variable VAR MEMORYBREAKPOINT //establece una variable VAR MEMORYBREAKPOINT2 //establece una variable VAR MEMORYBREAKPOINT3 //establece una variable VAR NSECCIONES //establece una variable VAR PESIGNA //establece una variable VAR MODULO //establece una variable VAR MODULO2 //establece una variable VAR MODULOP //establece una variable /////////////////////////////////////// GMI eip,MODULEBASE //obtiene el MODULEBASE MOV MODULO,$RESULT //el resultado de la operación anterior se guarda en la var MODULO MOV MODULOP,MODULO //mueve lo que está en MODULO a MODULOP MOV MODULO2,MODULO ADD MODULOP,3c //a MODULOP se le suma 3c MOV PESIGNA,[MODULOP] //lo que está dentro de MODULEBASE+3C se guarda en PESIGNA ADD MODULO,PESIGNA //suma MODULO con PESIGNA MOV MODULOPESIGNA,MODULO //suma MODULOPESIGNA con MODULO ADD MODULO,6 //MODULO se le suma 6 para saber el número de secciones MOV NSECCIONES,[MODULO],1 //mueve un byte de lo que está dentro de [MODULO] a NSECCIONES ADD MODULOPESIGNA,F8 //suma F8 a MODULOPESIGNA,para dirigirse al primer nombre de las secciones MOV MODULOPESIGNA3,MODULOPESIGNA LOG "*|--Informacion de secciones--|:" //logea lo que está en comillas EVAL "Total de secciones:{NSECCIONES}" LOG $RESULT NMOFSEC: MOV MODULOPESIGNA2,MODULOPESIGNA //mueve lo que está en MODULOPESIGNA a MODULOPESIGNA2 MOV SIZE_OF_SECCION,MODULOPESIGNA ADD SIZE_OF_SECCION,8 MOV VIRTUAL_ADDRESS,SIZE_OF_SECCION ADD VIRTUAL_ADDRESS,4 MOV NAME_OF_SECCION,[MODULOPESIGNA2] BUF NAME_OF_SECCION //Convierte una String o dword a buffer STR NAME_OF_SECCION //Convierte un buffer a STRING LOG NAME_OF_SECCION //logea NOMBRE_DE_SECCION LOG [VIRTUAL_ADDRESS] LOG [SIZE_OF_SECCION] LOG "______________________________" ADD MODULOPESIGNA,28 //suma 28 a MODULOPESIGNA CMP [MODULOPESIGNA],0 //compara lo que está dentro de [MODULOPESIGNA] con 0 JZ MENSAJEDESEC //si es 0 es por que ya no hay más secciones JMP NMOFSEC //si hay más secciones salta a NMOFSEC MENSAJEDESEC: EVAL "Numero de secciones encontradas:({NSECCIONES})más información ir al log" MSG $RESULT PREGNUMSEC: ASK "Introduzca el nº de sección en donde desea colocar un memory breakpoint ej:1,2,3" MOV MEMORYBREAKPOINT,$RESULT //mueve el resultada a una variable MOV CONTADORBPM,MEMORYBREAKPOINT //mueve una variable a otra CMP MEMORYBREAKPOINT,NSECCIONES //compara el nº de la sección con el introducido JA ERRORSEC //si es mayor se dirijirá a errorsec CMP MEMORYBREAKPOINT,0 //compara nº introducido con 0 JZ ERRORSEC //si es 0 este irá a errorsec CMP MEMORYBREAKPOINT,1 //compara con 1 JE MEMORYBREAK //si se comple se dirije a MEMORYBREAKPOINT DEC CONTADORBPM //toma el resultado del ASK anterior y lo disminuye en 1 MOV CONTADORBPM2,0 //CONTADORBPM2 toma el valor de 0 CONTADORBPMA: //la finalidad de este loop está hecho para que modulopesigna se encuentre en el nombre de la sección elejida CMP CONTADORBPM,CONTADORBPM2 //compara 0 con la sección elegida-1 ej:sec 3 cmp 0,2 JZ MEMORYBREAK //si se cumple se dirige a MEMORYBREAK ADD MODULOPESIGNA3,28 //si no se dirije a la segunda sección sumándole 28 INC CONTADORBPM2 //incrementa el contador en 1 JMP CONTADORBPMA //salta nuevamente a CONTADORBPMA MEMORYBREAK: ADD MODULOPESIGNA3,8 //estando en la sección elejida se le suma 8 para obtenr el size MOV MEMORYBREAKPOINT2,[MODULOPESIGNA3] //guarda el (size) en MEMORYBREAKPOINT2 ADD MODULOPESIGNA3,4 //Le suma 4 para obtener el virtualadress MOV MEMORYBREAKPOINT3,[MODULOPESIGNA3] //guarda el (virtualadress) en MEMORYBREAKPOINT3 ADD MEMORYBREAKPOINT3,MODULO2 //le suma la base a virtualadress BPRM MEMORYBREAKPOINT3, MEMORYBREAKPOINT2 //coloca un BPRM con los parámetros obtenidos anteriormente EVAL "Se ha colocado un BPM en:({MEMORYBREAKPOINT3}),con un tamaño de:({MEMORYBREAKPOINT2})" MSG $RESULT MSGYN "Desea Iniciar el programa(F9)?" CMP 1,$RESULT //compara el resultado con yes(1) JZ ARRANCAR //si se cumple se dirije al label ARRANCAR JMP START //si no se dirije al menú principal ARRANCAR: RUN //arranca el programa ERRORSEC: MSG "El nº de sección introducida es incorrecta, intente nuevamente" JMP PREGNUMSEC //salta a preguntar el número de secciones
MUY_USADA_PACKER: VAR ULTIMA_GETPROC //establece una variable VAR COUNT //establece una variable VAR RESP_GET //establece una variable VAR ADDRESS_GET_PROC //establece una variable MOV COUNT,0 GPA "GetProcAddress", "kernel32.dll" //obtiene el address de GetProcAddress MOV ADDRESS_GET_PROC,$RESULT //El Address es movida a ADDRESSGETPROC BP ADDRESS_GET_PROC //Coloca un BP en GetProcAddress ASK "Introduzca el address de retorno de la última call Realizada por el packer,si no sabe introduzca 0" MOV ULTIMA_GETPROC,$RESULT CMP 0,ULTIMA_GETPROC JE BUSCADOR_API_PACKER COMP_GET_PROC_ADDRES: BP ADDRESS_GET_PROC //coloca un bp en la variable ADDRESS_GET_PROC COMP_GET_PRO_ADDRESS2: EOB COMP_GET_PROC //si existe una excepción o bp se dirige a COMP_GET_PROC RUN //F9 COMP_GET_PROC: CMP [esp],ULTIMA_GETPROC //Compara si el valor es el mismo que la excepción introducida en el ask JE FINALIZAR_GET_PROC //si se cumple se dirijirá al label FINALIZAR_GET_PROC JMP COMP_GET_PRO_ADDRESS2
BUSCADOR_API_PACKER: MSG "El programa se ejecutará,una vez ejecutado se debe reiniciar (Control+F2)" BPL ADDRESS_GET_PROC,"[esp]" RUN
FINALIZAR_GET_PROC: MSG "Estado:Completado" MSGYN "Desea colocar un MemoryBreakPoint on execution?" CMP 1,$RESULT JE METODOBPMR BC JMP START
MUY_USADA_PROGRAMA: VAR APIUSADAPROGRAMA //establece una variable ASK "Opciones:GetVersion(1),GetModuleHandle(2)" CMP 1,$RESULT JE GETVERSION CMP 2,$RESULT JE GETMODULE CMP 0,$RESULT GETVERSION: GPA "GetVersion","kernel32.dll" MOV APIUSADAPROGRAMA,$RESULT JMP MUY_USADA_PROGRAMA2 GETMODULE: GPA "GetModuleHandleA","kernel32.dll" MOV APIUSADAPROGRAMA,$RESULT MUY_USADA_PROGRAMA2: BP APIUSADAPROGRAMA //coloca un bp en la API elegida por ASK EOB MUY_USADA_PROGRAMA3 //si encuentra una excepción o un breakpoint se dirije al label RUN //inicia el programa (F9) MUY_USADA_PROGRAMA3: MSG "Estado:Completado" BC //limpia todos los bp JMP START //salta al menu principal
BUSCAR_PUSH_EBP: ASK "OPcode: PUSH EBP(1),PUSH 0(2)" CMP 2,$RESULT JE BUSCAR_PUSH_EBP3 CMP 1,$RESULT JE BUSCAR_PUSH_EBP2 JMP ERROR_OPCODE BUSCAR_PUSH_EBP2: TICND "byte [eip]==55" //tracea hasta encontrar un push ebp JMP BUSCAR_PUSH_EBP4 BUSCAR_PUSH_EBP3: TICND "byte [eip]==6a" //tracea hasta encontrar un push 0 BUSCAR_PUSH_EBP4: MSGYN "OPcode encontrado,desea continuar" //muestra un mensaje al ser encontrado CMP 1,$RESULT JE BUSCAR_PUSH_EBP JMP START
ERROR_OPCODE: MSG "La opción introducida es incorrecta,por favor intente nuevamente" JMP BUSCAR_PUSH_EBP SALIRDELSCRIPT: ret //Sale del script
Espero que les sea de gran ayuda al momento de crackear,Saludos
Título: Re: [Script]Generic OEP Finder por UND3R
Publicado por: Tinkipinki en 5 Septiembre 2011, 20:28 pm
Pedazo de script..... :P Lo he probado y funciona correctamente.
Saludos
Título: Re: [Script]Generic OEP Finder por UND3R
Publicado por: .:UND3R:. en 5 Septiembre 2011, 20:54 pm
Excelente, que bueno que haya servido, una duda tinkipinki, que configuraciones usaste? y con que crackme lo probaste?,creo que sirve con el reto que te envié
Título: Re: [Script]Generic OEP Finder por UND3R
Publicado por: Tinkipinki en 5 Septiembre 2011, 21:10 pm
Efectivamente, lo he probado con dos crakme's en UPX y en los dos ha funcionado. El reto....... haber quien lo hace con la mitad de codigo y claro esta que funcione :laugh:
Saludos
Título: Re: [Script]Generic OEP Finder por UND3R
Publicado por: MCKSys Argentina en 5 Septiembre 2011, 21:23 pm
Efectivamente, lo he probado con dos crakme's en UPX y en los dos ha funcionado. El reto....... haber quien lo hace con la mitad de codigo y claro esta que funcione :laugh:
Saludos
Tinkipinki el script para UPX ocupa muy pocas lineas. Este script hace mas que desempacar UPX solamente.... :P
Título: Re: [Script]Generic OEP Finder por UND3R
Publicado por: .:UND3R:. en 5 Septiembre 2011, 22:10 pm
Tinkipinki el script para UPX ocupa muy pocas lineas. Este script hace mas que desempacar UPX solamente.... :P
eso es verdad de hecho para el OEP del UPX fue lo que menos me demoré, jeje Tinkipinki:aun espero la correción del script, ya te di las pistas por privado PUSHADPOPAD: VAR AUX2 //declara una variable VAR AUX //declara una variable VAR KIUSER //declara una variable VAR ZWCONT //declara una variable VAR entrypoint //declara una variable GPA "KiUserExceptionDispatcher", "ntdll.dll" //devuelve el address de una api MOV KIUSER, $RESULT //mueve el resultado de la operacion anterior a KIUSER BP KIUSER //coloca un bp en la address que apunta KIUSER GPA "ZwContinue", "ntdll.dll" //devuelve el address de una api MOV ZWCONT, $RESULT // mueve el resultado de la operación anterior a ZWCONT BP ZWCONT //coloca un bp en la address que apunta ZWCONT MOV entrypoint,[eip],1 //mueve el primer byte de eip a la variable entrypoint CMP entrypoint,60 //compara entrypoint con 60 (equivale a un pushad) JE PASO1 //si el primer opcode es pushad salta TICND "byte [eip]==60" //tracea hasta encontrar un pushad PASO1: STI //Step into (F7), para ejecutar el pushad MOV AUX,esp //mueve el valor de esp dentro de la variable AUX INICIO: BPHWS AUX, "r" //coloca un hadware breakpoint on access en AUX TRABAJO: EOB COMPROBAR // si ocurre una excepción o un bp se dirije a COMPROBAR RUN //se ejecuta ollydbg (f9) COMPROBAR: CMP eip,KIUSER //compara eip con KIUSER JE QUITAR //si estamos en KiUserExceptionDispatcher irá a quitar BPHWS CMP eip,ZWCONT //compara eip con ZWCONT JE RESTAURAR //si estamos en ZwContinue irá a restaurar CMP eip,AUX2 //compara eip con el retorno de una excepción JE RESTAURAR2 //si estamos en el retorno irá a restaurar2 JMP SALIR //terminado todo se dirige a salir QUITAR: BPHWC //quita el BPHWS JMP TRABAJO //salta a trabajo RESTAURAR: MOV AUX2,[ESP+4] //introduce el valor de CONTEXT a AUX2 ADD AUX2,0b8 //le suma 0b8 para saber a que lugar retomará una vez pasada la excepción BP AUX2 //sabiendo el retorno coloca un BP en ella JMP TRABAJO //salta a trabajo RESTAURAR2: BC AUX2 //elimina el BP del retorno de la excepción JMP INICIO //salta a INICIO para volver a colocar el BPHWS SALIR: BPHWC //limpia todos los BPHWS BC //limpia todos los bp MSGYN "Aproximación terminada,desea buscar OPcodes?" CMP 1,$RESULT //compara resultado con 1(YES) JZ BUSCAR_PUSH_EBP //si la comparación anterior se cumple salta al laber BUSCAR_PUSH_EBP JMP START //retorna al menú principal Este es de hecho un poco más completo ya que no tan solo coloca un hadwarebreakpoint, si no que mientras se ejecuta el programa, este los quita en las excepciones,volviéndose a colocar en el retorno de ellas para así evitar de alguna u otra forma la detección del hadware breakpointademás dándo la posibilidad que una vez ejecutado el popad,este tracea hasta encontrar uno de los op codes más usados al inicio del programa
|