Afinador

Se nos entrega un ELF que decompilado presenta este aspecto:
/* This file was generated by the Hex-Rays decompiler version 8.4.0.240320.
Copyright (c) 2007-2021 Hex-Rays <info@hex-rays.com>
Detected compiler: GNU C++
*/
#include <defs.h>
//-------------------------------------------------------------------------
// Function declarations
__int64 (**init_proc())(void);
__int64 sub_401020();
__int64 sub_401030(); // weak
__int64 sub_401040(); // weak
__int64 sub_401050(); // weak
__int64 sub_401060(); // weak
__int64 sub_401070(); // weak
// int puts(const char *s);
// int printf(const char *format, ...);
// __int64 __isoc99_scanf(const char *, ...); weak
// void __noreturn exit(int status);
void __fastcall __noreturn start(__int64 a1, __int64 a2, void (*a3)(void));
void dl_relocate_static_pie();
char *deregister_tm_clones();
__int64 register_tm_clones();
char *_do_global_dtors_aux();
__int64 frame_dummy();
int __fastcall main(int argc, const char **argv, const char **envp);
_BYTE *__fastcall encode(__int64 a1);
__int64 __fastcall validar(const char *a1);
int banner();
int comprar();
void _libc_csu_fini(void); // idb
void term_proc();
// int __fastcall _libc_start_main(int (__fastcall *main)(int, char **, char **), int argc, char **ubp_av, void (*init)(void), void (*fini)(void), void (*rtld_fini)(void), void *stack_end);
// __int64 _gmon_start__(void); weak
//-------------------------------------------------------------------------
// Data declarations
_UNKNOWN _libc_csu_init;
const char a31mparaSeguirU[43] = "\x1B[31mPara seguir usando este producto deber"; // idb
const char a32myaPuedesSeg[61] = "\x1B[32mYa puedes seguir afinando tus instrumentos (y tus flags "; // idb
const char aDirigaseANuest[21] = "\nDirigase a nuestra p"; // idb
__int64 (__fastcall *_frame_dummy_init_array_entry)() = &frame_dummy; // weak
__int64 (__fastcall *_do_global_dtors_aux_fini_array_entry)() = &_do_global_dtors_aux; // weak
__int64 (*qword_404010)(void) = NULL; // weak
char _bss_start; // weak
//----- (0000000000401000) ----------------------------------------------------
__int64 (**init_proc())(void)
{
__int64 (**result)(void); // rax
result = &_gmon_start__;
if ( &_gmon_start__ )
return (__int64 (**)(void))_gmon_start__();
return result;
}
// 404090: using guessed type __int64 _gmon_start__(void);
//----- (0000000000401020) ----------------------------------------------------
__int64 sub_401020()
{
return qword_404010();
}
// 404010: using guessed type __int64 (*qword_404010)(void);
//----- (0000000000401030) ----------------------------------------------------
__int64 sub_401030()
{
return sub_401020();
}
// 401030: using guessed type __int64 sub_401030();
//----- (0000000000401040) ----------------------------------------------------
__int64 sub_401040()
{
return sub_401020();
}
// 401040: using guessed type __int64 sub_401040();
//----- (0000000000401050) ----------------------------------------------------
__int64 sub_401050()
{
return sub_401020();
}
// 401050: using guessed type __int64 sub_401050();
//----- (0000000000401060) ----------------------------------------------------
__int64 sub_401060()
{
return sub_401020();
}
// 401060: using guessed type __int64 sub_401060();
//----- (0000000000401070) ----------------------------------------------------
__int64 sub_401070()
{
return sub_401020();
}
// 401070: using guessed type __int64 sub_401070();
//----- (00000000004010D0) ----------------------------------------------------
// positive sp value has been detected, the output may be wrong!
void __fastcall __noreturn start(__int64 a1, __int64 a2, void (*a3)(void))
{
__int64 v3; // rax
int v4; // esi
__int64 v5; // [rsp-8h] [rbp-8h] BYREF
char *retaddr; // [rsp+0h] [rbp+0h] BYREF
v4 = v5;
v5 = v3;
_libc_start_main(
(int (__fastcall *)(int, char **, char **))main,
v4,
&retaddr,
(void (*)(void))_libc_csu_init,
_libc_csu_fini,
a3,
&v5);
__halt();
}
// 4010DA: positive sp value 8 has been found
// 4010E1: variable 'v3' is possibly undefined
//----- (0000000000401100) ----------------------------------------------------
void dl_relocate_static_pie()
{
;
}
//----- (0000000000401110) ----------------------------------------------------
char *deregister_tm_clones()
{
return &_bss_start;
}
// 404050: using guessed type char _bss_start;
//----- (0000000000401140) ----------------------------------------------------
__int64 register_tm_clones()
{
return 0LL;
}
//----- (0000000000401180) ----------------------------------------------------
char *_do_global_dtors_aux()
{
char *result; // rax
if ( !_bss_start )
{
result = deregister_tm_clones();
_bss_start = 1;
}
return result;
}
// 404050: using guessed type char _bss_start;
//----- (00000000004011B0) ----------------------------------------------------
__int64 frame_dummy()
{
return register_tm_clones();
}
//----- (00000000004011B6) ----------------------------------------------------
int __fastcall main(int argc, const char **argv, const char **envp)
{
int v4; // [rsp+10h] [rbp-10h] BYREF
int v5; // [rsp+14h] [rbp-Ch]
unsigned __int64 v6; // [rsp+18h] [rbp-8h]
v6 = __readfsqword(0x28u);
v5 = 0;
puts("\n\x1B[31m -----------Se le ha acabado el periodo de prueba gratuito-----------\n");
puts(a31mparaSeguirU);
do
{
banner();
__isoc99_scanf("%d", &v4);
if ( v4 == 3 )
exit(0);
if ( v4 > 3 )
goto LABEL_10;
if ( v4 == 1 )
{
comprar();
continue;
}
if ( v4 == 2 )
v5 = validar("%d");
else
LABEL_10:
puts("Opcion invalida, pruebe otra vez");
}
while ( !v5 );
puts(a32myaPuedesSeg);
return 0;
}
// 4010B0: using guessed type __int64 __isoc99_scanf(const char *, ...);
//----- (0000000000401291) ----------------------------------------------------
_BYTE *__fastcall encode(__int64 a1)
{
_BYTE *result; // rax
int i; // [rsp+14h] [rbp-4h]
for ( i = 0; i <= 33; ++i )
{
if ( *(char *)(i + a1) <= 96 || *(char *)(i + a1) > 122 )
{
if ( *(char *)(i + a1) <= 64 || *(char *)(i + a1) > 90 )
{
result = (_BYTE *)*(unsigned __int8 *)(i + a1);
*(_BYTE *)(i + a1) = (_BYTE)result;
}
else
{
result = (_BYTE *)(i + a1);
*result = (5 * ((char)*result - 65) + 8) % 26 + 65;
}
}
else
{
result = (_BYTE *)(i + a1);
*result = (5 * ((char)*result - 97) + 8) % 26 + 97;
}
}
return result;
}
//----- (00000000004013DB) ----------------------------------------------------
__int64 __fastcall validar(const char *a1)
{
int i; // [rsp+Ch] [rbp-64h]
char v3[48]; // [rsp+10h] [rbp-60h] BYREF
__int64 v4[6]; // [rsp+40h] [rbp-30h] BYREF
v4[5] = __readfsqword(0x28u);
qmemcpy(v4, "RisgAv{rIU_ihHwvIxA_sAppCsziq3vzC}", 34);
printf("\nIntroduce tu licencia: ");
__isoc99_scanf("%s", v3);
encode((__int64)v3);
for ( i = 0; i <= 33; ++i )
{
if ( v3[i] != *((_BYTE *)v4 + i) )
{
puts("\n\x1B[31mTu licencia es incorrecta\x1B[37m\n");
return 0LL;
}
}
puts("\n\x1B[32mEres un crack, lo conseguiste\x1B[37m");
return 1LL;
}
// 4010B0: using guessed type __int64 __isoc99_scanf(const char *, ...);
// 4013DB: using guessed type char var_60[48];
//----- (00000000004014CE) ----------------------------------------------------
int banner()
{
puts(" ___________OPCIONES___________");
puts(" | 1: Comprar licencia premium |");
puts(" | 2: Validar clave de licencia |");
puts(" | 3: Salir |");
puts(" ------------------------------");
return printf("> ");
}
//----- (0000000000401526) ----------------------------------------------------
int comprar()
{
return puts(aDirigaseANuest);
}
//----- (0000000000401540) ----------------------------------------------------
void __fastcall _libc_csu_init(unsigned int a1, __int64 a2, __int64 a3)
{
signed __int64 v3; // rbp
__int64 i; // rbx
init_proc();
v3 = &_do_global_dtors_aux_fini_array_entry - &_frame_dummy_init_array_entry;
if ( v3 )
{
for ( i = 0LL; i != v3; ++i )
(*(&_frame_dummy_init_array_entry + i))();
}
}
// 403E10: using guessed type __int64 (__fastcall *_frame_dummy_init_array_entry)();
// 403E18: using guessed type __int64 (__fastcall *_do_global_dtors_aux_fini_array_entry)();
//----- (00000000004015B0) ----------------------------------------------------
void _libc_csu_fini(void)
{
;
}
//----- (00000000004015B8) ----------------------------------------------------
void term_proc()
{
;
}
// nfuncs=33 queued=21 decompiled=21 lumina nreq=0 worse=0 better=0
// ALL OK, 21 function(s) have been successfully decompiled
Para resolver el juego y obtener una licencia válida, nos fijamos en el proceso de validación que se encuentra en la función validar (líneas 237 a 258). Esta función compara una entrada de licencia codificada con una licencia codificada almacenada en el programa.
La licencia almacenada es "RisgAv{rIU_ihHwvIxA_sAppCsziq3vzC}", y se utiliza la función encode (líneas 207 a 234) para codificar la entrada del usuario antes de compararla. La función encode aplica un cifrado simple a la entrada, alterando los caracteres alfabéticos según una fórmula específica.
La función de cifrado encode realiza lo siguiente:
- Si el carácter es una letra minúscula (a-z), se convierte según la fórmula
(5 * (char - 97) + 8) % 26 + 97. - Si el carácter es una letra mayúscula (A-Z), se convierte según la fórmula
(5 * (char - 65) + 8) % 26 + 65.
Nos construimos una función en Python para decodificar la Flag y reto superado.
def decode(encoded_char):
if 'a' <= encoded_char <= 'z':
original_char = chr(((ord(encoded_char) - 97 - 8) * 21) % 26 + 97)
elif 'A' <= encoded_char <= 'Z':
original_char = chr(((ord(encoded_char) - 65 - 8) * 21) % 26 + 65)
else:
original_char = encoded_char
return original_char
encoded_license = "RisgAv{rIU_ihHwvIxA_sAppCsziq3vzC}"
decoded_license = "".join(decode(char) for char in encoded_license)
print("Licencia descifrada:", decoded_license)
WinFan’s NETCrackMe#1 Keygen

Introducción
Desempaquetado
Decompilado
Links
Retos de Criptografía

Los retos de criptografía pueden ser muy variados como he dicho anteriormente. El secreto suele estar en saber a que te enfrentas y posteriormente construir una herramienta para descifrarlo o usar una ya existente (la mayoría de los casos).
Una web con la que suelo resolver la mayoría de retos es dcode.fr. Si os fijáis en el enlace, la lista de categorías asciende a 48 y disponéis de unos 800 algoritmos para rebanaros los sesos.
A continuación veamos unos cuantos retos que podéis encontrar por la red. Cabe destacar que normalmente el título del reto dice mucho del algoritmo.
- Enunciado: Not K9 But ?
- Texto encriptado: 8430727796730470662453
- Solución: ¿Te has fijado en el teclado de tu móvil alguna vez?
- Enunciado: The grass is always greener on the other side
- Texto encriptado: TSDLN ILHSY OGSRE WOOFR OPOUK OAAAR RIRID
- Solución: César
- Enunciado: Prove you’re not drunk?
- Texto encriptado: gsv kzhh blfi ollprmt uli rh zoxlslo
- Solución: Atbash
- Enunciado: ¿?
- Texto encriptado: 4C240DDAB17D1796AAD3B435B51404EE
- Solución: Aquí nuestro primer impulso es utilizar fuerza bruta a MD5, pero cuando nos damos contra la pared el siguiente candidato es LAN Manager. Aquí la opción que más os guste, Cain, John The Ripper, etc.
Con John The Ripper tenemos que preparar un archivo de texto del estilo: deurus.info:1011:4C240DDAB17D1796AAD3B435B51404EE:4C240DDAB17D1796AAD3B435B51404EE:::
y ejecutar el comando: john –format=lm LM.txt
- Enunciado: a lot harder than SMS
- Texto encriptado: .- -. . .- … -.– — -. . – …. . .–. .- … … .– — .-. -.. .. … -.. — – -.. .- … …. -.. .- … …. -.. — –
- Solución: Morse
- Enunciado: Now I see!
- Solución: Braille
- Enunciado: Polly the parrot loves to square dance?
- Texto encriptado: 442315 3511434352344214 2443 442432154411123115
- Solución: Polybios
- Enunciado: Aquí hay problemas de base.
- Texto encriptado: VGhlIHBhc3N3b3JkIGlzIG9qZXRlIG1vcmVubw==
- Solución: Base64
- Enunciado: Conversión
- Texto encriptado: 6c6120736f6c756369c3b36e2065733a20366533303664333137333734333337323739
- Solución: Hexadecimal
- Enunciado: Método de encriptación de los más antiguos que se conocen.
- Texto encriptado: ozhlofxrlmvhxzorulimrz
- Solución: Cifrado Afín
- Enunciado: /_vti_pvt/administrators.pwd
- Texto encriptado: admin:dut4HlQyu4dSA
- Solución: Creamos un archivo de texto con el texto encriptado y ponemos a John The Ripper a trabajar con el comando john –show administrators.pwd
- Enunciado: En ocasiones veo en binario
- Texto encriptado:0111001101110101011100000110010101110010
0001001110011000111110100100110010010001 - Solución: Para la primera parte la conversión es directa. Para la segunda, la dificultad reside en darse cuenta que hay que separar en grupos de cinco y decodificar por separado.
- Enunciado: Un clásico
- Texto encriptado: WLYGUKVAIIXAVGLRWCHVDRWC
- Solución: Vigenere
- Solución: Código Templario
- Enunciado: eXORcism
- Texto encriptado: 7d5313525e52475713544113414046025052
- Solución: XOR. La clave la podéis obtener por fuerza bruta. Mira este artículo par saber como.
- Enunciado: Edgar Allan Poe
- Texto encriptado: 05-05¶88)8)-5(525,‡
- Solución: Escarabajo de oro
- Enunciado: MD encryption
- Texto encriptado: 6FBCF7B5CE6637C28EEDC43988A9509B
- Solución: MD5
- Enunciado: American coding system used in the context of World War II
- Texto encriptado: A-WOH LIN AH-JAH CLA-GI-AIH BE-LA-SANA KLESH DIBEH GLOE-IH NE-AHS-JAH GAH BE YEH-HES DIBEH A-CHIN WOL-LA-CHEE A-KEH-DI-GLINI TSE-NILL YIL-DOI A-KHA
- Solución: Código Navajo
- Enunciado: Run, run, run
- Texto encriptado: T1H1E1P1A1S2W1O1R1D1I1S1R1U1N2I1N1G1
- Solución: Run-length encoding
Conversiones, cifra clásica, hash, simétricos, asimétricos, combinaciones de varios algoritmos y un largo etcetera. Como veis los hay para todos los gustos, ten en cuenta que aquí os muestro una pequeñísima parte de lo que os encontrareis en las webs de retos, pero para despertar la curiosidad es suficiente.
¡Hala, a decodificar!
Enlaces
VideoTutorial – KeyGen para el Crackme#2 de AfKayAs

Reto forense de HackThis!!

Intro
We require your services once again. An employee from our company had recently been identified as a known criminal named Brett Thwaits. He is considered to have stolen missile launch codes from the US navy which unfortunately were handed to us for a brief period of time. As of now, we are accussed of the theft and unless we do something about it, we’re gonna end in some serious trouble. Before Brett left, he formatted the thumbdrive which used to store the launch codes. Fortunately, our system had made a backup image of the drive. See if you can recover the fourth launch code. Good luck!
Requerimos una vez más sus servicios. Un empleado de nuestra empresa había sido identificado recientemente como el conocido criminal Brett Thwaites. Se considera que ha robado los códigos de lanzamiento de misiles de la Armada de Estados Unidos, que por desgracia fueron entregados a nosotros por un breve período de tiempo. A partir de ahora, se nos acusa del robo y a menos que hagamos algo al respecto, vamos a tener serios problemas. Antes de que Brett se fuera formateó el dispositivo que se usa para almacenar los códigos de lanzamiento. Afortunadamente, nuestro sistema había hecho una copia de seguridad de la unidad. Mira a ver si puedes recuperar los cuatro códigos de lanzamiento. ¡Buena suerte!
Análisis del archivo
- Fichero: forensics1
- Extensión: img
- Tamaño: 25 MB (26.214.400 bytes)
- Hash MD5: 56e4cd5b8f076ba8b7c020c7339caa2b
Echamos un vistazo al archivo con un editor hexadecimal y vemos encabezados de tipos de archivos conocidos, por lo que la unidad no está encriptada. Al no estar encriptada la imagen, usaremos una herramienta de creación propia, Ancillary. En esta ocasión usaremos la versión 2 alpha, que actualmente está en desarrollo, pero podéis usar tranquilamente la versión 1.x.
Ancillary nos muestra lo que ha encontrado en el archivo por lo que pasamos a analizarlo.
Como siempre os digo en este tipo de retos, es difícil discriminar unos ficheros en favor de otros, ya que no sabemos si lo que buscamos va a estar en una imagen, documento u otro tipo de fichero codificado o no.
Tras analizar todos los ficheros, rápidamente suscitan nuestro interés los ficheros RAR, y más cuando el fichero que contienen es un fichero de audio y su nombre es tan sugerente como «conversation_dtmf.wav«. Como podéis apreciar en la imagen, el fichero RAR está protegido con clave por lo que necesitamos esquivar ese obstaculo.
Recuperando una clave de un archivo RAR
En este caso el software que voy a utilizar es cRARk, pero podéis utilizar cualquier otro. Como se muestra en la imagen de abajo, mi procesador es más bien modesto pero la clave no tiene más que tres dígitos por lo que no supone ninguna dificultad recuperarla.
DTMF (Dual-Tone Multi-Frequency)
Una vez recuperado el archivo WAV, al reproducirlo escuchamos 16 tonos telefónicos que inmediatamente me recuerdan las aventuras del mítico «Capitán Crunch«. Os animo a leer la historia de John Draper y su famosa «Blue Box» ya que no tiene desperdicio y forma parte de la historia del Phreaking.
Por si no conocías la historia, el propio nombre del fichero wav nos da la pista clave de qué buscar al contener las siglas «DTMF«.
Al ser pulsada en el teléfono la tecla correspondiente al dígito que quiere marcar, se envían dos tonos, de distinta frecuencia: uno por columna y otro por fila en la que esté la tecla, que la central decodifica a través de filtros especiales, detectando qué dígito se marcó.
No tenemos más que buscar un decodificador de tonos para obtener los preciados códigos de lanzamiento.
Links
Reto Stego 1 de Hacker Games

Cambio de extensión (paso opcional)
Al descargar la imagen de la web del reto vemos que tiene la extensión php y lo más probable es que no nos abra correctamente.
... <br/> <img src="steg1img.php"/> <br/> ...
Abrimos la imagen con nuestro editor hexadecimal favorito y nos fijamos en la cabecera.
00000000h: 89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 ; ‰PNG........IHDR
Renombramos entonces la extensión a png y continuamos.
Imagen oculta
Esta parte la afrontaremos con Steganabara, una herramienta muy útil que siempre uso cuando me enfrento a un reto «stego». En esta ocasión utilizaremos el análisis de color. Para ello pulsamos sobre «Analyse > Color table«.
En la tabla de colores tenemos la descomposición de colores RGBA y su frecuencia de aparición. Ordenamos por frecuencia descendiente y hacemos doble clic sobre la fila para abrir la imagen resultante.
A continuación un resumen de las imágenes obtenidas.
Como podéis observar, la imagen oculta es un código QR. Lo escaneamos con nuestra app preferida y obtenemos un texto encriptado.
dtsfwqutisvqtesymkuvabbujwhfecuvlshwopcyeghguywjvlaibflcacyahckyqvypjntfhihgtvyxeqakjwouldltuiuhbhjumgkxuugqahvwhotduqtahcknheypjetxpvlhxtlrpjagyjzcgijgfjmcupsslkzpuxegaillytlfbygeptzjtuzlvlwkzdznxqwpabbe
Descifrando el mensaje
A partir de aquí el reto pasa a ser de encriptación. Con el tiempo diferenciareis fácilmente el tipo de cifrado con sólo ver el texto. En este caso lo primero que se nos ocurre es comprobar dos cifrados clásicos como son el cifrado César y el Vigenere.
Tras desestimar el cifrado César realizamos un ataque de «fuerza bruta» al cifrado Vigenere mediante análisis estadístico. En la imagen que muestro a continuación se puede ver que la clave está cerca de ser «HPHQTC» pero todavía no se lee correctamente.
Ya que la fuerza bruta de por sí no termina de darnos la respuesta correcta, pasamos a probar algo muy útil, esto es, descifrar por fuerza bruta pero dándole una palabra para comparar. En este caso en concreto vemos que una posible palabra que pudiera estar en el texto encriptado es «PASSWORD», probamos y reto terminado.























