martes, 17 de agosto de 2021

Introduccion a Arquitectura x86 y x64


CPU

Se encarga de procesar todas las instrucciones del dispositivo, que son interpretadas en lenguaje maquina (binarios), para facilitar el entendimiento de estas instrucciones es necesario traducirlo a un lenguaje mnemotécnico llamado Assembly (ASM).

 

Los assembler más populares son:

    NASM (Netwide Assembler).

    MASM (Microsoft Macro Assembler).

    GAS (GNU Assembler).

    FASM (Flat Assembler).

 Este post será muy interesante para entender cómo se compila programas.

 

Diferencias entre AT&T e Intel

A medida que se bajando de nivel, se va notando algunas cosas que no se necesitaba preocupar al momento de trabajar con lenguajes de alto nivel. Al trabajar con sistemas basados en Unix, tradicionalmente se tiene una sintaxis AT&T, en muchas herramientas se tiene la opción de obtener la sintaxis Intel. Ahora voy a nombrar algunas de las diferencias más significativas para identificar la sintaxis del ensamblador.

En algunas instrucciones donde se especifica el origen y el destino se invierten, mientras que para AT&T va primero el origen y luego el destino, en Intel es lo contrario primero el destino y luego en origen

AT&T

<instrucción> <origen><destino>

Intel

<instrucción> <destino><origen>

Un indicador de que se está trabajando con AT&T es que cada operando es precedido por un "%", mientras que Intel no lo utiliza.

 

Arquitectura 32

Endians:

Describe como es el orden de la secuencia de bytes se guardará en la memoria. Cuando se quiere representar un numero decimal con 2 bytes, por ejemplo, el 6, aquí entra el concepto del byte más significativo y el menos significativo. En este ejemplo el byte (0000) es el más significativo (MSB) y el byte (0110) menos significativo (LSB), y esto está dado porque si agregáramos un byte al primer byte (0001 0110 = 22) variaría más que si se lo agregáramos al segundo byte (0000 0111 = 7).  En Big Endian, el byte más significativo es el primero, en cambio en Little Endian el ultimo byte es el más significante.

Conocer la Endian es importante a la hora de interpretar los registros.

                                Binario                  Hex          Decimal

Big Endian           0101 0010            0x52           82

Little Endian       0101 0010            0x25            37

 

En procesadores modernos existe, registros de propósito general, registro de segmento, registros de banderas y un registro de puntero.


Registros GPR

Los registros GPR(General Purpose Register) almacenan direcciones de memoria o datos, que serán utilizados durante la ejecución del programa.

Abr Nombre Descripción
EAX Extended Accumulator
Register
Es responsable de manejar el resultado de
operaciones de llamada al sistema
EBX Extended Base
Register
Es usada para almacenar la dirección de
los datos en el segmento de registro DS
ECX Extended Counter
Register
Sirve como contador para strings y
operaciones cíclicas
EDX Extended Data
Register
Es usado para almacenar direcciones para
operaciones de entrada y salida
EBP Extended Base
Pointer
Apunta a la dirección de la base del Stack
EDI Extended Destination
Index
Es usado como el puntero de destino para
las operaciones de strings
ESI Extended Source
Index
Es usado como puntero de origen para las
operaciones de strings
ESP Extended Stack
Pointer
Apunta a la dirección de la parte superior
del Stack
EIP Extended Instruction
Pointer
Tiene 32 bits de ancho, apunta a la dirección
de la siguiente instrucción

 

 Estos registros tiene un tamaño específico que se pueden dividir en registros con tamaño mucho más pequeño, por ejemplo EAX tiene un tamaño de 32 bits, y a su vez puedo tener 2 registros AX de tamaño de 16 bits, un registro AX de 16 bits puede tener un 2 registros de 8 bits, llamados AH(high bit) y AL(low bit). En arquitecturas mas modernas como x64, se duplicó el espacio de memoria, por ejemplo un registro RAX es equivalente a 2 registros EAX.



Los registros EFLAGS tienen un tamaño de 32 bits y contiene varios diferentes flags que son usadas para varias operaciones, algunos de estos bits están reservados como lo son 1,3,5,15, 22 al 31. En arquitectura x64 son denominados RFLAGS.

Algunos EFLAGS:

Carry Flag (CF): Se encuentra en el bit 0 y este flag indica una condición de desbordamiento para operaciones aritmética de enteros sin signo.

Parity Flag (PF): Se encuentra en el bit 2 y se coloca si el bit más significativo contiene incluso un número de un solo bit.

Auxiliary Carry Flag (AF): Se encuentra en el bit 4 y es usado en operaciones matemáticas si la operación resultante es llevar y pedir prestado.

Zero Flag (ZF): Se encuentra en el bit 6,  tiene el valor de 1 y si es colocado 0 despejados. 

Sign Flag (SF): Se encuentra en el bit 7 y es usado para demarcar el signo de un entero.

Direccion Flag (DF): Se encuentra en el bit 10 y se usa para determinar la dirección de operaciones de string, si se pasa un 1, las instrucciones de string operan desde la dirección más alta a la más baja y si se pasa 0 viceversa.

Overflow Flag(OF): Se encuentra en el bit 11 y se establece si el resultado entero es un número positivo demasiado grande o pequeño para caber en el operando de destino o una condición de desbordamiento en una operación matemática.


lunes, 9 de agosto de 2021

CTF Crypto - I


 

Hace poco me encontre con unos cuantos retos de captura la bandera, estos estaban orientados a criptografía. Aunque no son los retos mas dificiles que hay fueron bastante interesantes para los que recien se enfrentan a este tipo de retos.


RETO 1: 


Este trataba de como trabaja los propiedades del la compuerta XOR.

El problema era el siguiente, te daban una serie de llaves que te ayudaran a encontrar la bandera la pista esta en los nombres de las llaves.

KEY1 = ...

KEY2^KEY1 = ...

KEY2^KEY3 = ...

FLAG^KEY2^KEY3^KEY1 = ...


La solucion esta en la pista y en las propiedades de la compuerta XOR, del siguente modo para obtener la segunda llave:

c =  a ^  b

b = a ^ c

KEY2 = KEY1  ^  KEY2^KEY1   

Asi se podra obtener la segunda llave xoreando las primeras 2 llaves. Del mismo modo se puede hallar la tercer llave y la bandera.

flag = k1  ^  k2  ^  k3  ^  f_k2_k3_k1

El truco es que como ya teniamos xoreado una de las llaves simplificaba la operacion y obtener la bandera.

flag = k1  ^  k2^k3  ^  f_k2_k3_k1
 

 

RETO 2: 

En este reto, te dan una larga cadena en hexadecimal que dentro de esta se halla la bandera y la unica pista que se dio fue que el formato de la bandera podria ayudar a solucionar el reto.

En realidad funciono bastante bien al xorear la misma cantidad de datos de la cadena encriptada con la longitud del formato, mostrando la clave con la que lo habian cifrado. Al intentar xorear toda la cadena con la llave que encontre, no funciono. 

flag = cadena ^ ( formatformat...)

Agregando una llave abierta ({) al formato, que es el siguiente caracter conocido, xorear toda la cadena, solo esta primer parte mostraba que habia funcionado. Asi que por fuerza bruta intente obtener el siguiente caracter, obteneniendo algunas opciones viables para ser la llave.

flag = cadena ^ ( format{format{...)

Al xorear el primer intento, note que tenia la longitud correcta de la llave y solo faltaba dar con el caracter correcto.

flag = cadena ^ ( format{cformat{c...)


RETO 3:

 En este reto dieron la cadena, la unica pista era que se habia xoreado con un solo byte. Asi que teniendo encunta que un byte tiene 128 valores diferentes, es factible obtener la bandera a travez de fuerza bruta, xoreando cada bite la cadena por el valor con el que se estaba probando.


NOTA: Algunos ctfs tienen prohibido publicar la solucion de los retos, por este motivo algunos aspectos fueron modificados para dar solo una vision ilustrativa del reto...