Warning: This challenge is still active and therefore should not be resolved using this information. Aviso: Este reto sigue en activo y por lo tanto no se debería resolver utilizando esta información.
Intro
This crackme is for the crack challenge 6 of canyouhack.it.
In this crackme the goal is to turn on all the lights. Note that a light off to the next, so if we interrupt this, we win.
Tools
Exeinfo (For crackme info)
Delphi Decompiler (For decompile)
OllyDbg (For debug)
Decompiling
With Delphi Decompiler we can found easy the buttons and his offsets.
Go to the offset 401A64 in OllyDbg and analyze the code.
We view two jumps, one turn ON the light and the other Turn OFF the next light. Patching the call from offset 401A8B we get the serial.
Introducción A quien va dirigido Comprobaciones previas Lo que necesitamos Presupuesto Ejemplo de instalación Preguntas frecuentes Glosario Notas finales Introducción
Un día cualquiera se te ocurre comprarte un disco duro de red NAS para centralizar todo tu contenido multimedia. Lo conectas y todo va genial, pero de repente vas a copiar unos cuantos gigas de fotos y te encuentras con que la operación va a tardar días. En ese mismo instante te planteas sacar el máximo provecho a tu red doméstica y la solución se llama gigabit.
A quién va dirigido
Esta guía va dirigida a todo el mundo que esté pensando en hacer o mejorar la red LAN doméstica. Si eres un amante del WIFI, olvídate de esto, ya que para conseguir altas velocidades se necesita cablear la casa. Además, de lo que trata esta guía es de que se conecte un ordenador portátil o sobremesa de la forma más rápida posible al disco duro de red.
Comprobaciones previas
Probablemente dispongas de un Modem / Router proporcionado por tu compañia y que seguramente no sea gigabit (10/100/1000), esto es lo primero que debes comprobar. Busca tu modelo en internet y cerciorate.
También necesitas que la tarjeta de red del portátil o sobremesa sean gigabit, en este caso lo más probable es que lo sean pero asegúrate.
Lo que necesitamos
Tras hacer las comprobaciones previas ya podemos hacer una lista de los materiales que necesitamos.
Router gigabit (en caso del que tu compañia no lo sea).
Si el nuestro no es gigabit existen soluciones económicas como el TP-Link TL-WR1043ND que lo tenemos por 44€ en pccomponentes. Os recomiendo esta tienda por rapidez, seriedad y no abusan con los gastos de envío.
Switch gigabit (para ampliar puertos)
En caso de que los cuatro puertos que vienen con el router se nos queden cortos, la solución más economica y acertada es un Switch ethernet gigabit como el TP-LINK TL-SG1005D que lo tenemos por 16€. Este dispositivo es una maravilla ya que nos brinda 4 puertos más y no requiere configuración alguna.
Tarjeta de red gigabit (para pc sobremesa en caso de no ser o no disponer)
Para interconexionado de equipos recomiento estos de 50cm por 1,5€. Para conexión del pc tienes otras larguras más apropiadas. También podéis haceros vosotros los cables con lo sobrante de la bobina, para ello necesitaréis una crimpadora y terminales rj45.
Tomas RJ45 categoría 6.
Esto depende de tu instalación y la gama que elijas. En mi caso utilizo tomas Niessen que solo el conector vale 16€, pero tienes tomas más económicas. De superficie por 2,75€ y empotrable por 8,25€.
Esto es una recomendación personal ya que la elección puede variar en función de las necesidades de almacenamiento y conexiones. Una solución barata y con espacio suficiente para uso doméstico es el disco WD My Cloud 3TB que lo podeis adquirir por 159€.
Presupuesto (Precios Octubre 2014)
Router = 44€
Switch = 16€
Tarjeta de red = 15€
Bobina de cable = 42€
Cables interconexionado 50cm x4 = 6€
Cable conexión pc / switch o router 1,8m = 2,95€
Tomas RJ45 x 2 = 16,5€
Disco duro de red NAS = 159€
TOTAL = 345,45€ + gastos de envío.
Esto puede variar en función de los componentes que elijas comprar pero el coste oscilará entre 250 y 350€, algo bastante asequible para centralizar contenido multimedia. Digo asequible por que la mitad del presupuesto se lo lleva el disco de red, los componentes son más bien baratos.
Ejemplo de instalación
Esquema inicial
En mi esquema disponemos del router proporcionado por el proveedor de internet que en mi caso sí es gigabit pero que solo lo utilizo para dar internet al router neutro.El router neutro junto con el switch me proporcionan 8 puertos gigabit. El router neutro además gestiona el wifi de la casa, pero en el mejor de los casos (Wifi n) estos dispositivos solo podrán mover datos a 300mbps. Utilizo como media center mis amadas Raspberry Pi que en este caso no se benefician de la velocidad ya que disponen de conexión 10/100.
Configurar router neutro
Lo primero a conectar es el router neutro y en este caso, TP-Link te lo pone fácil si no te defiendes muy bien con las redes, ya que proporciona un CD que se encarga de guiarte paso a paso. Lo más importante es la asignación de la IP privada, por defecto es 192.168.2.1 y a no ser que el router de la compañia tenga esa misma IP lo podéis dejar como está.
Disco duro de red NAS
Para configurar el disco de red normalmente viene un CD para ayudar al usuario novel. Lo único que tenéis que tener en cuenta es que la IP debe estar en consonancia con la del router neutro, si el router neutro es 192.168.2.1 al disco NAS podéis asignarle 192.168.2.150. Para más información aquí tenéis la guía de instalación.
Preguntas frecuentes. FAQ
¿El cable normal o cruzado?
Podéis usar cable normal, también llamado conexión Pin a Pin ó 1:1, para toda la instalación ya que los dispositivos de hoy en día aceptan cualquier cable y resuelven internamente en función del cable conectado. Pero si nos ponemos quisquillosos, para conectar elementos pasivos entre sí (router a switch, etc) se utiliza cable normal 1:1. Para conectar elementos activos (PC a router/switch) cable cruzado.
¿Qué norma de colores uso?
Mi consejo es que uses el standard EIA/TIA 568B tanto en la conexión de las cajas como en la creación de los cables.
Cada roseta o toma en su interior tiene definido el orden que debes seguir para conectar los cables según el standard A o B, esto es una aproximación y puede no coincidir con tu toma.
Tengo todo instalado y es categoría 6 pero mi pc me marca que me conecta a 100mbps ¿qué pasa?
Si estás seguro de que las rosetas están bien conectadas, que has usado los cables correctos, que todos los dispositivos son gigabit y tu pc hace de las suyas, quizás debas de forzar a tu tarjeta de red a trabajar en modo gigabit ó 100 full duplex ó 100FD. Esto es debido a que el driver de la tarjeta de red por defecto viene con la opción de «autonegociación» activada y a veces necesita que le «obligues» a trabajar en gigabit.
En cada tarjeta de red puede venir diferente, yo os muestro mi caso desde windows 7:
Diríjete a Inicio > Panel de control > Ver el estadoy las tareas de red > conexión de area local
En mi caso marca 1 Gbps pero si estais teniendo problemas os marcará 100 mbps. A continuación pulsa Propiedades.
Pulsa Configurar.
En la pestaña Opciones avanzadas busca la opción de la velocidad, en mi caso «Speed/duplex settings» y selecciona 100 mb Full Duplex. De este modo le forzais a la tarjeta de red a trabajar en modo gigabit. Si no lo consiguiera trabajará en el modo que pueda pero no os dejará sin conexión.
Glosario
NAS – del inglés Network Attached Storage, es el nombre dado a una tecnología de almacenamiento dedicada a compartir la capacidad de almacenamiento a través de una red. Estos discos vienen equipados como mínimo con una conexión RJ45 para integrarlo en una red de forma rápida y sencilla.
Full Duplex – Que transmite y recibe en ambas direcciones al mismo tiempo por cables independientes.
Switch – Un conmutador o switch es un dispositivo digital lógico de interconexión de equipos que opera en la capa de enlace de datos del modelo OSI. Su función es interconectar dos o más segmentos de red, de manera similar a los puentes de red, pasando datos de un segmento a otro de acuerdo con la dirección MAC de destino de las tramas en la red.
Gigabit Ethernet – también conocida como GigaE, es una ampliación del estándar Ethernet (concretamente la versión 802.3ab y 802.3z del IEEE) que consigue una capacidad de transmisión de 1 gigabit por segundo, correspondientes a unos 1000 megabits por segundo de rendimiento contra unos 100 de Fast Ethernet (También llamado 100BASE-TX).
Notas finales
Soy consciente de que me he dejado muchas cosas en el tintero pero mi pretensión es que el lector de un vistazo rápido tenga una idea clara de lo que necesita para lograr una red decente en casa.
Aquí tenemos un Crackme clásico creado por Scarebyte hallá por el año 2000 y que cuenta con varias fases siendo un crackme muy interesante para iniciarse o simplemente para divertirse. Al estar realizado en Delphi, los apartados de las checkboxes y de las trackbars se simplifican y mucho, pero aún así hay que currarselo un poco para dejar todo bien atado. Si os fijáis en las soluciones que aparecen en crackmes.de, en aquellos años se usaba DEDE y aunque yo usaré otra herramienta, DEDE sigue siendo igual de útil.
Desempacado
PEiD nos dice que nos enfrentamos a ASPack 1.08.03 -> Alexey Solodovnikov, así que vamos al lío.
Eliminar la NAG
Tan sencillo como poner un Breakpoint a User32.MessageBoxA. La llamada a NOPear está en la dirección 441CF2.
Password
Desde las string references localizamos los mensajes de chico bueno y chico malo que nos llevan al código a analizar.
0044C3CD |. E8 5294FDFF CALL CrackMe_.00425824
0044C3D2 |. 8B45 FC MOV EAX,[LOCAL.1]
0044C3D5 |. E8 9A76FBFF CALL CrackMe_.00403A74
0044C3DA |. 83F8 0C CMP EAX,0C ; Lengh C = 12
0044C3DD |. 0F85 53010000 JNZ CrackMe_.0044C536 ; Salto a chico malo
0044C3E3 |. 8D55 FC LEA EDX,[LOCAL.1]
0044C3E6 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C3EC |. E8 3394FDFF CALL CrackMe_.00425824
0044C3F1 |. 8B45 FC MOV EAX,[LOCAL.1]
0044C3F4 |. 8038 43 CMP BYTE PTR DS:[EAX],43 ; 1º dígito serial = C
0044C3F7 |. 0F85 27010000 JNZ CrackMe_.0044C524 ; Salto a chico malo
0044C3FD |. 8D55 F8 LEA EDX,[LOCAL.2]
0044C400 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C406 |. E8 1994FDFF CALL CrackMe_.00425824
0044C40B |. 8B45 F8 MOV EAX,[LOCAL.2]
0044C40E |. 8078 03 6F CMP BYTE PTR DS:[EAX+3],6F ; 4º dígito serial = o
0044C412 |. 0F85 0C010000 JNZ CrackMe_.0044C524 ; Salto a chico malo
0044C418 |. 8D55 F4 LEA EDX,[LOCAL.3]
0044C41B |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C421 |. E8 FE93FDFF CALL CrackMe_.00425824
0044C426 |. 8B45 F4 MOV EAX,[LOCAL.3]
0044C429 |. 8078 08 6F CMP BYTE PTR DS:[EAX+8],6F ; 9º dígito serial = o
0044C42D |. 0F85 F1000000 JNZ CrackMe_.0044C524 ; Salto a chico malo
0044C433 |. 8D55 F0 LEA EDX,[LOCAL.4]
0044C436 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C43C |. E8 E393FDFF CALL CrackMe_.00425824
0044C441 |. 8B45 F0 MOV EAX,[LOCAL.4]
0044C444 |. 8078 01 6C CMP BYTE PTR DS:[EAX+1],6C ; 2º dígito serial = l
0044C448 |. 0F85 D6000000 JNZ CrackMe_.0044C524 ; Salto a chico malo
0044C44E |. 8D55 EC LEA EDX,[LOCAL.5]
0044C451 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C457 |. E8 C893FDFF CALL CrackMe_.00425824
0044C45C |. 8B45 EC MOV EAX,[LOCAL.5]
0044C45F |. 8078 04 20 CMP BYTE PTR DS:[EAX+4],20 ; 5º dígito serial = espacio
0044C463 |. 0F85 BB000000 JNZ CrackMe_.0044C524 ; Salto a chico malo
0044C469 |. 8D55 E8 LEA EDX,[LOCAL.6]
0044C46C |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C472 |. E8 AD93FDFF CALL CrackMe_.00425824
0044C477 |. 8B45 E8 MOV EAX,[LOCAL.6]
0044C47A |. 8078 0A 52 CMP BYTE PTR DS:[EAX+A],52 ; 11º dígito serial = R
0044C47E |. 0F85 A0000000 JNZ CrackMe_.0044C524 ; Salto a chico malo
0044C484 |. 8D55 E4 LEA EDX,[LOCAL.7]
0044C487 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C48D |. E8 9293FDFF CALL CrackMe_.00425824
0044C492 |. 8B45 E4 MOV EAX,[LOCAL.7]
0044C495 |. 8078 07 75 CMP BYTE PTR DS:[EAX+7],75 ; 8º dígito serial = u
0044C499 |. 0F85 85000000 JNZ CrackMe_.0044C524 ; Salto a chico malo
0044C49F |. 8D55 E0 LEA EDX,[LOCAL.8]
0044C4A2 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C4A8 |. E8 7793FDFF CALL CrackMe_.00425824
0044C4AD |. 8B45 E0 MOV EAX,[LOCAL.8]
0044C4B0 |. 8078 09 6E CMP BYTE PTR DS:[EAX+9],6E ; 10º dígito serial = n
0044C4B4 |. 75 6E JNZ SHORT CrackMe_.0044C524 ; Salto a chico malo
0044C4B6 |. 8D55 DC LEA EDX,[LOCAL.9]
0044C4B9 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C4BF |. E8 6093FDFF CALL CrackMe_.00425824
0044C4C4 |. 8B45 DC MOV EAX,[LOCAL.9]
0044C4C7 |. 8078 02 6E CMP BYTE PTR DS:[EAX+2],6E ; 3º dígito serial = n
0044C4CB |. 75 57 JNZ SHORT CrackMe_.0044C524 ; Salto a chico malo
0044C4CD |. 8D55 D8 LEA EDX,[LOCAL.10]
0044C4D0 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C4D6 |. E8 4993FDFF CALL CrackMe_.00425824
0044C4DB |. 8B45 D8 MOV EAX,[LOCAL.10]
0044C4DE |. 8078 05 69 CMP BYTE PTR DS:[EAX+5],69 ; 6º dígito serial = i
0044C4E2 |. 75 40 JNZ SHORT CrackMe_.0044C524 ; Salto a chico malo
0044C4E4 |. 8D55 D4 LEA EDX,[LOCAL.11]
0044C4E7 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C4ED |. E8 3293FDFF CALL CrackMe_.00425824
0044C4F2 |. 8B45 D4 MOV EAX,[LOCAL.11]
0044C4F5 |. 8078 0B 6E CMP BYTE PTR DS:[EAX+B],6E ; 12º dígito serial = n
0044C4F9 |. 75 29 JNZ SHORT CrackMe_.0044C524 ; Salto a chico malo
0044C4FB |. 8D55 D0 LEA EDX,[LOCAL.12]
0044C4FE |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C504 |. E8 1B93FDFF CALL CrackMe_.00425824
0044C509 |. 8B45 D0 MOV EAX,[LOCAL.12]
0044C50C |. 8078 06 67 CMP BYTE PTR DS:[EAX+6],67 ; 7º dígito serial = g
0044C510 |. 75 12 JNZ SHORT CrackMe_.0044C524 ; Salto a chico malo
0044C512 |. BA 78C54400 MOV EDX,CrackMe_.0044C578 ; ASCII "Right Password"
0044C517 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C51D |. E8 3293FDFF CALL CrackMe_.00425854
0044C522 |. EB 22 JMP SHORT CrackMe_.0044C546
0044C524 |> BA 90C54400 MOV EDX,CrackMe_.0044C590 ; ASCII "Wrong Password"
0044C529 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C52F |. E8 2093FDFF CALL CrackMe_.00425854
0044C534 |. EB 10 JMP SHORT CrackMe_.0044C546
0044C536 |> BA 90C54400 MOV EDX,CrackMe_.0044C590 ; ASCII "Wrong Password"
Chequeo rápido
ABCD EFGHIJK
Clno iguonRn
; 1º dígito serial = C
; 4º dígito serial = o
; 9º dígito serial = o
; 2º dígito serial = l
; 5º dígito serial = espacio
; 11º dígito serial = R
; 8º dígito serial = u
; 10º dígito serial = n
; 3º dígito serial = n
; 6º dígito serial = i
; 12º dígito serial = n
; 7º dígito serial = g
Básicamente chequea la frase «Cool Running» de forma desordenada como se ve justo encima, siendo el password correcto «Clno iguonRn«. Os dejo el código para que lo analicéis.
Nº serie asociado a un nombre
De nuevo con las string references localizamos el código.
0044C648 /. 55 PUSH EBP
0044C649 |. 8BEC MOV EBP,ESP
0044C64B |. 83C4 F8 ADD ESP,-8
0044C64E |. 53 PUSH EBX
0044C64F |. 56 PUSH ESI
0044C650 |. 33C9 XOR ECX,ECX
0044C652 |. 894D F8 MOV [LOCAL.2],ECX
0044C655 |. 8BF0 MOV ESI,EAX
0044C657 |. 33C0 XOR EAX,EAX
0044C659 |. 55 PUSH EBP
0044C65A |. 68 83C74400 PUSH CrackMe_.0044C783
0044C65F |. 64:FF30 PUSH DWORD PTR FS:[EAX]
0044C662 |. 64:8920 MOV DWORD PTR FS:[EAX],ESP
0044C665 |. 33C0 XOR EAX,EAX
0044C667 |. 8945 FC MOV [LOCAL.1],EAX
0044C66A |. A1 80F84400 MOV EAX,DWORD PTR DS:[44F880] ; Eax = Nombre
0044C66F |. E8 0074FBFF CALL CrackMe_.00403A74
0044C674 |. 83F8 06 CMP EAX,6 ; Cmp lengh nombre con 6
0044C677 |. 0F8E F0000000 JLE CrackMe_.0044C76D ; Salta si <= 6
0044C67D |. A1 80F84400 MOV EAX,DWORD PTR DS:[44F880] ; Eax = Nombre
0044C682 |. E8 ED73FBFF CALL CrackMe_.00403A74
0044C687 |. 83F8 14 CMP EAX,14 ; Cmp lengh nombre con 20 (14h)
0044C68A |. 0F8D DD000000 JGE CrackMe_.0044C76D ; salta si >= 20
0044C690 |. A1 80F84400 MOV EAX,DWORD PTR DS:[44F880]
0044C695 |. E8 DA73FBFF CALL CrackMe_.00403A74
0044C69A |. 85C0 TEST EAX,EAX
0044C69C |. 7E 17 JLE SHORT CrackMe_.0044C6B5
0044C69E |. BA 01000000 MOV EDX,1
0044C6A3 |> 8B0D 80F84400 /MOV ECX,DWORD PTR DS:[44F880] ; Bucle in
0044C6A9 |. 0FB64C11 FF |MOVZX ECX,BYTE PTR DS:[ECX+EDX-1]
0044C6AE |. 014D FC |ADD [LOCAL.1],ECX ; Suma dig nombre y guarda en 12FBC4
0044C6B1 |. 42 |INC EDX
0044C6B2 |. 48 |DEC EAX
0044C6B3 |.^ 75 EE \JNZ SHORT CrackMe_.0044C6A3 ; Bucle out
0044C6B5 |> A1 84F84400 MOV EAX,DWORD PTR DS:[44F884] ; Eax = Compañia
0044C6BA |. E8 B573FBFF CALL CrackMe_.00403A74
0044C6BF |. 83F8 02 CMP EAX,2 ; Cmp lengh compañia con 2
0044C6C2 |. 7E 18 JLE SHORT CrackMe_.0044C6DC ; Salta si <= 2
0044C6C4 |. A1 84F84400 MOV EAX,DWORD PTR DS:[44F884] ; Eax = Compañia
0044C6C9 |. E8 A673FBFF CALL CrackMe_.00403A74
0044C6CE |. 83F8 08 CMP EAX,8 ; Cmp lengh compañia con 8
0044C6D1 |. 7D 09 JGE SHORT CrackMe_.0044C6DC ; Salta si >= 8
0044C6D3 |. 8B45 FC MOV EAX,[LOCAL.1] ; Eax = sum nombre
0044C6D6 |. 6BC0 02 IMUL EAX,EAX,2 ; Sum nombre * 2
0044C6D9 |. 8945 FC MOV [LOCAL.1],EAX
0044C6DC |> 68 98C74400 PUSH CrackMe_.0044C798 ; ASCII "I Love Cracking and "
0044C6E1 |. 8D55 F8 LEA EDX,[LOCAL.2]
0044C6E4 |. 8B45 FC MOV EAX,[LOCAL.1]
0044C6E7 |. E8 68B0FBFF CALL CrackMe_.00407754
0044C6EC |. FF75 F8 PUSH [LOCAL.2] ; sum del nombre
0044C6EF |. 68 B8C74400 PUSH CrackMe_.0044C7B8 ; ASCII " Girls ;)"
0044C6F4 |. B8 8CF84400 MOV EAX,CrackMe_.0044F88C
0044C6F9 |. BA 03000000 MOV EDX,3
0044C6FE |. E8 3174FBFF CALL CrackMe_.00403B34 ; Concatena 1º frase + sum nombre + 2ºfrase
0044C703 |. 33C0 XOR EAX,EAX
0044C705 |. 8945 FC MOV [LOCAL.1],EAX
0044C708 |. A1 88F84400 MOV EAX,DWORD PTR DS:[44F888] ; Eax = Serial
0044C70D |. E8 6273FBFF CALL CrackMe_.00403A74
0044C712 |. 8BD8 MOV EBX,EAX
0044C714 |. A1 8CF84400 MOV EAX,DWORD PTR DS:[44F88C]
0044C719 |. E8 5673FBFF CALL CrackMe_.00403A74
0044C71E |. 3BD8 CMP EBX,EAX ; Compara tamaño frase con tamaño serial
0044C720 |. 75 4B JNZ SHORT CrackMe_.0044C76D
0044C722 |. A1 88F84400 MOV EAX,DWORD PTR DS:[44F888]
0044C727 |. E8 4873FBFF CALL CrackMe_.00403A74
0044C72C |. 85C0 TEST EAX,EAX
0044C72E |. 7E 27 JLE SHORT CrackMe_.0044C757
0044C730 |. BA 01000000 MOV EDX,1
0044C735 |> 8B0D 88F84400 /MOV ECX,DWORD PTR DS:[44F888] ; Bucle in -->
0044C73B |. 0FB64C11 FF |MOVZX ECX,BYTE PTR DS:[ECX+EDX-1]
0044C740 |. 034D FC |ADD ECX,[LOCAL.1]
0044C743 |. 8B1D 8CF84400 |MOV EBX,DWORD PTR DS:[44F88C]
0044C749 |. 0FB65C13 FF |MOVZX EBX,BYTE PTR DS:[EBX+EDX-1] ; Compara dígito a dígito nuestro serial
0044C74E |. 2BCB |SUB ECX,EBX ; con la concatenación anterior
0044C750 |. 894D FC |MOV [LOCAL.1],ECX
0044C753 |. 42 |INC EDX
0044C754 |. 48 |DEC EAX
0044C755 |.^ 75 DE \JNZ SHORT CrackMe_.0044C735 ; <-- Bucle out
0044C757 |> 837D FC 00 CMP [LOCAL.1],0
0044C75B |. 75 10 JNZ SHORT CrackMe_.0044C76D ; Salta si algo ha ido mal
0044C75D |. 8B86 14030000 MOV EAX,DWORD PTR DS:[ESI+314]
0044C763 |. BA CCC74400 MOV EDX,CrackMe_.0044C7CC ; "You have found the correct Serial :)"
En resumen
Tamaño del nombre entre 7 y 19.
Tamaño de la compañía entre 3 y 7 aunque no interviene en el serial.
Suma los valores ascii de los dígitos del nombre y lo multiplica por 2.
Concatena «I Love Cracking and » + «sum del nombre» + » Girls ;)».
Checkbox
Para afrontar esta parte del reto vamos a usar una herramienta llamada Interactive Delphi Reconstructoro IDR. En su día la mejor herramienta era DEDE, pero IDR a mi parecer es algo más potente.
Básicamente IDR nos permite sin quebraderos de cabeza localizar el código del botón que comprueba la secuencia de checkboxes correcta. Cargamos el crackme en IDR y dentro de la pestaña «Units (F2)«, abajo del todo hacemos doble click sobre «F Crack» y vemos que nos muestra todos los controles del formulario. El botón que nos interesa se llama «SpeedButton3«.
Si hacemos doble click sobre el nos muestra el código que se muestra a continuación.
Como podéis apreciar, las checkboxes involucradas son la 3, 5, 6, 9, 11, 12, 13, 15, 19 y 20. Solo nos falta saber cuales se corresponden con esa numeración y aquí ya depende de cada uno, yo en su día saqué los números a mano mediante el orden de tabulación, pero ya que tenemos IDR, el nos va a dar la solución de una forma sencilla y rápida.
Vamos a la pestaña «Forms (F5)«, seleccionamos la opción Form y hacemos doble click sobre el formulario.
Veréis que aparece el formulario con todos los recursos, incluso los puedes modificar. Localizar los checkboxes ahora es un juego de niños.
Os dejo un vídeo.
Trackbar
De nuevo, con la ayuda de IDR, localizamos la parte del código y analizamos su funcionamiento. Esta parte es la más divertida ya que requiere de un keygen pero en vez de coger el número de serie de una caja de texto lo obtiene de 5 trackbars como muestra la siguiente imagen.
1) Siendo nuestro serial : 1 2 3 4 5
a b c d e
2) Realiza las operaciones matemáticas:
Round(((Cos(sqrt(b^3+5)) + (-sqrt(a+1)) + Ln(c*3+1) + (-sqrt(d+2)) + ((e*3)/2))+0.37)*1000))
3) Obtenemos un hash resultante de 5415
4) XORea los dígitos de la siguiente manera:
(5)35 xor 86 = B6
(4)34 xor 83 = BD
(1)31 xor 86 = B7
(5)35 xor 8D = B8
De modo que tenemos B6BDB7B8
5) Compara B6BDB7B8 con B5BAB2BA
6) Revertimos el XOR para obtener el hash bueno
B5 xor 86 = 36(6)
BA xor 83 = 33(3)
B2 xor 86 = 34(4)
BA xor 8D = 37(7)
Luego el hash bueno es 6347
7) Debemos hacer fuerza bruta buscando:
Round(((Cos(sqrt(b^3+5)) + (-sqrt(a+1)) + Ln(c*3+1) + (-sqrt(d+2)) + ((e*3)/2))+0.37)*1000)) = 6347
Para obtener los seriales válidos podemos hacer bucles recursivos hasta recorrer las 10^5 opciones posibles. Una forma de hacerlo en VBNet es la siguiente.
Dim tmp As Double
Dim an, bn, cn, dn, en As Integer
For an = 0 To 9
For bn = 0 To 9
For cn = 0 To 9
For dn = 0 To 9
For en = 0 To 9
tmp = Round(((Cos(Sqrt((Pow(bn, 3)) + 5)) + (-Sqrt(an + 1)) + Log(cn * 3 + 1) + (-Sqrt(dn + 2)) + ((en * 3) / 2) + 0.37) * 1000))
txtdebug.Text = "a-b-c-d-e = Hash || " & an & "-" & bn & "-" & cn & "-" & dn & "-" & en & " = " & tmp
If tmp = 6347 Then
ListBox1.Items.Add("Serial: " & an & bn & cn & dn & en)
End If
Application.DoEvents()
Next
Next
Next
Next
Next
Os dejo como siempre el crackme y el keygen en los enlaces.
El reto consiste en dos imágenes (v1.png y v2.png) que, a simple vista, parecen contener ruido aleatorio. Sin embargo, ambas forman parte de un sistema de criptografía visual en la que cada imagen contiene información parcial que no es interpretable por separado, pero que al combinarse correctamente revelan informaciónoculta.
La trampa está en que la combinación no se hace con operaciones normales como suma, resta o multiplicación. El autor del reto espera que el jugador use una herramienta como StegSolve y pruebe distintas operaciones tipo XOR, AND o MUL hasta encontrar una transformación en la que uno de los métodos muestre algo significativo. El truco está en llegar a la conclusión de que una de las imágenes hay que invertirla antes de combinar ambas imágenes. Todo esto se puede hacer con StegSolve sin necesidad de utilizar ninguna herramienta adicional, pero voy a aprovechar para hacerlo con python y así de paso entendemos como realiza las operaciones StegSolve. En resumen, para resolver el reto basta con:
Invertir (Colour Inversion XOR) una de las imágenes.
Combinar ambas imágenes mediante Analyse > Combine images.
Operación MUL del combinador.
La operación MUL no es una multiplicación normalizada, sino una multiplicación de enteros de 24 bits (0xRRGGBB) con overflow, algo que la mayoría de herramientas no replican correctamente.
¿Por qué aparece la solución con esa combinación
Las imágenes están preparadas para que ciertos bits de color en una imagen sean el complemento de los de la otra. Por tanto:
Si se muestran tal cual → parecen ruido
Si se combinan mediante XOR → parte de la estructura aparece, pero no se ve el resultado correcto
Si se combinan mediante MUL «normal» → tampoco aparece
Si se aplica la multiplicación bitwise exacta usada por StegSolve → se alinean las partes ocultas
La operación MUL de StegSolve no es una multiplicación de píxeles, es decir, no hace:
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.
En una entrada anterior sobre cómo Expediente X abordó la tecnología de vanguardia, comenté que dedicaría un espacio a esos tres personajes tan peculiares y entrañables que, desde el segundo plano, se ganaron un hueco en el corazón de los seguidores de la serie: los Pistoleros Solitarios. Pues bien, ha llegado el momento.
Estos tres tipos —John Fitzgerald Byers, Melvin Frohike y Richard “Ringo” Langly— no necesitaban armas ni placas del FBI. Su poder estaba en los teclados, los cables enredados y los monitores de tubo que parpadeaban en un sótano lleno de conspiraciones y café frío. Eran los outsiders de Expediente X, tres hackers con alma de periodistas que luchaban por algo tan simple y tan enorme como la verdad.
Su primera aparición fue en E.B.E. (temporada 1), casi como un alivio cómico: tres frikis que ayudaban a Mulder a rastrear información sobre ovnis. Pero pronto quedó claro que había algo especial en ellos. No solo eran fuente de datos, sino conciencia crítica en un mundo plagado de mentiras digitales y gobiernos con demasiados secretos. Con el tiempo se convirtieron en aliados imprescindibles de Mulder y Scully, y también en el reflejo más humano de lo que significa ser hacker: curiosos, testarudos, torpes a veces, pero con un sentido moral inquebrantable.
Byers era el idealista, el que aún creía en la decencia y en las instituciones (al menos en teoría). Frohike, el cínico veterano con corazón de oro, siempre dispuesto a arriesgarse por una buena causa… o por impresionar a Scully. Y Langly, el genio rebelde que parecía vivir en permanente conversación con su módem de 56 k. Juntos formaban un trío excéntrico, pero perfectamente equilibrado.
Mientras Mulder y Scully perseguían abducciones y virus extraterrestres, los pistoleros combatían en otra trinchera: la digital. Hackeaban redes gubernamentales, interceptaban comunicaciones cifradas y desmantelaban cortafuegos que, en los noventa, parecían pura ciencia ficción. Lo suyo no era la acción física, sino la resistencia informativa. Y aunque muchas veces eran el chiste del capítulo, también representaban algo muy real: la gente corriente que lucha contra el poder desde el conocimiento.
Su lema no declarado podría haber sido el clásico “la información quiere ser libre”, y en eso se mantuvieron firmes hasta el final. Si había que elegir entre la seguridad o la verdad, ellos siempre elegían la verdad, aunque les costara caro.
Langly como conciencia digital en un servidor. Debate sobre IA y trascendencia del código.
Morir por la verdad
El final de los pistoleros fue tan inesperado como heroico. En el episodio “Jump the Shark” de la novena temporada, descubren un complot bioterrorista que amenaza con liberar un virus mortal. No hay tiempo para avisar a nadie, ni margen para escapar. Así que, fieles a su estilo, deciden sacrificarse para salvar a otros. Sellan el laboratorio desde dentro, sabiendo que no volverán a salir.
Lo reconozco, este desenlace mi cogió completamente por sorpresa. No hay épica de Hollywood, ni música grandilocuente. Solo tres hombres anónimos haciendo lo correcto. Mueren juntos, sin reconocimiento, sin medallas, pero con la serenidad de quienes saben que su causa era justa. Y en ese silencio final, Expediente X nos recordó algo que las grandes historias suelen olvidar: que los verdaderos héroes a veces no llevan traje ni pistola, solo convicción.
Años después, Mulder vuelve a verlos —o cree verlos— en The Truth. Ya no están en este mundo, pero siguen a su lado, como fantasmas digitales de la conciencia hacker. Es un homenaje discreto a quienes siempre pelearon desde las sombras por liberar la verdad.
Para cerrar el círculo, Langly reaparece de forma inesperada en la temporada 11, dentro del episodio This. Su mente, o más bien su copia digital, sobrevive atrapada en un servidor, reclamando ser liberada. Es el epílogo perfecto: el hacker que muere físicamente, pero cuya conciencia sigue inmortal. Una vez más me volvió a sorprender Chris Carter con este homenaje.
Me gusta pensar que los pistoleros solitarios representaban algo más que tres hackers secundarios en una serie de los noventa. Fueron el reflejo de una época en la que creíamos que la tecnología podía liberar al ser humano, antes de que las redes sociales y la hiperconectividad lo diluyeran todo. Byers, Frohike y Langly no luchaban por fama ni por dinero: luchaban por entender el sistema para exponerlo, por esa curiosidad genuina que hoy apenas sobrevive entre líneas de código y algoritmos opacos. Quizá por eso seguimos recordándolos y mola tanto volver a ver los capítulos. Porque, de algún modo, todos los que amamos el conocimiento libre llevamos dentro un pequeño pistolero solitario, buscando la verdad entre los bits.
Los retos de Javascript son los retos más sencillos que podemos encontrar. Muchas veces solamente mirando el código fuente obtenemos la respuesta. Suponen una mala implementación de seguridad debido a que el código se ejecuta del lado del cliente, por lo que el código fuente es accesible y por lo tanto, javascript no garantiza seguridad alguna. En estos cinco casos haremos un recorrido por lo más básico, cinco retos fáciles de superar y que nos proporcionan los conocimientos base para Javascript. Dicho esto os puedo asegurar que en ocasiones he encontrado retos javascript realmente complicados que requieren de horas descifrarlos y en los que es fácil tirar la toalla.
Cuando el reto lo requiera, es buena idea utilizar un compilador online para obtener de forma rápida el valor de una variable o realizar una prueba concreta. Yo utilizo Jsfiddle para realizar pruebas pero existen muchos más.
Javascript 1
Este primer reto es lo básico, en el código fuente se pueden apreciar directamente el usuario y la clave.
<script language=JavaScript>
function Verify(name,pass)
{
if (name=="admin" & pass=="3***3")
{
location.href = name + pass + '.htm';
}
else
{
alert("Si ya fallamos el primero...");
};
}
</script>
Javascript 2
Este segundo reto es bastante sencillo pero ya te obliga a conocer la función charAt() de Javascript. Dicha función lo que hace es coger el caracter indicado mediante un índice que comienza en cero. Por ejemplo si nombre = deurus y hacemos letra = nombre.charAt(3), estariámos extrayendo la cuarta letra, es decir, la letra r de la variable nombre.
function Verify(name,pass)
{
var name1 = "CrawlinG", pass1 = "capriccio"
if (name==name1 & pass==pass1)
{
location.href = name + ".htm";
}
else
{
var x = name1.charAt(7) + pass1.charAt(3)+ name1.charAt(2) + pass1.charAt(5) + name1.charAt(5) + pass1.charAt(1);x = x.toLowerCase();
var y = name.charAt(3) + name.charAt(1) + pass.charAt(1)+ pass.charAt(6) + pass.charAt(7) + name.charAt(2);var x1 = "des" + y;
if (x==y){location.href = x1 + ".htm"}else{alert("Esto no va bien");location.href = "js2.htm"}
}
}
Lo interesante está en la formación de las variables x e y. La variable x se forma de las variables name1 y pass1, formando la palabra gracia. Por otro lado, la variable y se forma con el nombre y clave que introduzcamos nosotros. Vemos que la variable x e y deben ser iguales, por lo tanto debemos construir un nombre (name) y una clave (pass) que cumpla con lo siguiente:
4ª letra del nombre = 1ª letra de la palabra «gracia»
2ª letra del nombre = 2ª letra de la palabra «gracia»
2ª letra de la clave = 3ª letra de la palabra «gracia»
7ª letra de la clave = 4ª letra de la palabra «gracia»
8ª letra de la clave = 5ª letra de la palabra «gracia»
3ª letra del nombre = 6ª letra de la palabra «gracia«
Como véis simplemente se trata de interpretar correctamente la función charAt() y de fijarse bien en los nombres de las variables.
Javascript 3
Este reto nos muestra diálogo donde nos pide la contraseña para validar el reto. Al fallar o cancelar vuelve al índice para no dejarnos ver el código fuente. Aquí se pueden seguir varios caminos como bloquear el uso de javascript en el navegador o instalar un plugin en chrome o firefox para habilitar/deshabilitar de forma rápida el uso de javascript.
Una vez deshabilitado javascript vemos lo siguiente:
<script language="JavaScript" src="js3.gif" type=text/javascript>
<!--
function verify()
{
var pass="thebest";
var password=prompt("Introduce el password para superar el nivel","");
if (password==pass)
{
location.href = pass + ".htm";
}
else
{
alert("No vamos bien...");
location.href = "index.htm";
}
}
//-->
</script>
Aquí el truco es darse cuenta que el código que se está ejecutando esta en «js3.gif» y no el código que nos muestra como válida la clave thebest. Si descargamos el archivo js3.gif y lo abrimos con un archivo de texto vemos nuestra querida clave.
function verify()
{
var pass="mo****ver";
var password=prompt("Introduce el password para superar el nivel","");
if (password==pass)
{
location.href = pass + ".htm";
}
else
{
alert("No vamos bien...");
location.href = "index.htm";
}
}
Javascript 4
En este reto ya entramos con que la clave no es reversible y la debemos obtener por fuerza bruta. En este reto utiliza una nueva función como charCodeAt() que lo que hace es obtener el valor ascii del caracter indicado.
function Verify(pass1)
{
var cont1= 2, cont2= 6
var suma1 = 0, suma2 = 0
var pass2 = "FDRLF"
for(i = 0; i < pass1.length; i++)
{
suma1 += (pass1.charCodeAt(i) * cont1);
cont1++
}
for(i = 0; i < pass2.length; i++)
{
suma2 += (pass2.charCodeAt(i) * cont2);
cont2++
}
if (suma1==suma2)
{
window.location=suma1+".htm";
}
else
{
alert ("Algo no va bien...");
}
}
Vemos dos bucles en los que se calculan sendos valores suma que finalmente se comparan. la variable suma1 se calcula mediante nuestro password y la variable suma2 la obtiene de la palabra «FDRLF». Con el script que os muestro a continuación obtenemos que usando como clave deurus, suma1 = 3048 y suma2 = 2936. Nuestro punto de referencia es suma2 = 2936, de modo que vamos alterando con paciencia la variable pass1 obteniendo valores cercanos a 2936. Por ejemplo «deurua» nos da suma1 = 2922, un valor bastante cercano.
var pass1 = "deurus";
var cont1= 2, cont2= 6
var suma1 = 0, suma2 = 0
var pass2 = "FDRLF"
for(i = 0; i < pass1.length; i++)
{
suma1 += (pass1.charCodeAt(i) * cont1);
cont1++
}
for(i = 0; i < pass2.length; i++)
{
suma2 += (pass2.charCodeAt(i) * cont2);
cont2++
}
alert (suma1);
alert (suma2);
La solución a este reto es múltiple. Dos claves válidas son por ejemplo dfurqf y zwfabz.
Javascript 5
Este último reto es similar al anterior pero ya nos obliga a crearnos una pequeña herramienta que nos busque el serial válido.
function Verify(pass)
{
var suma=0
var cadena = "abcdefghijklmnopqrstuvwxyz"
for (var i = 0; i < pass.length; i++)
{
var letra = pass.charAt(i)
var valor = (cadena.indexOf(letra))
valor++
suma *= 26
suma += valor
}
if (suma==6030912063)
{
window.location=pass+".htm";
}
else
{
alert ("Algo no va bien...");
}
}
Para esta ocasión utiliza una nueva función llamada indexOf() que lo que hace es devolver un número entero que representa la posición en la que se encuentra el parámetro pasado a la función. Por ejemplo, si tengo variable = deurus y realizo posición = variable.indexOf(«s»), obtengo como resultado 5 (se empieza a contar desde cero).
Las operaciones que realiza el bucle son las siguientes:
Coge las letras del nombre una a una.
valor = posición de nuestra letra dentro de la variable de texto llamada cadena.
valor = valor + 1.
Multiplica la variable suma por 26.
Suma = suma + valor.
Aunque el proceso de recuperación de esta clave es algo más largo, podemos acortarlo introduciendo una clave de inicio de fuerza bruta próxima al objetivo. Al ser una función bastante lineal podemos rápidamente mediante pruebas con nuestro código de fuerza bruta o con un compilador online, establecer que la clave tendrá 7 caracteres e incluso que para ahorrar tiempo podemos aproximar la clave para que su valor suma esté cercano al valor suma buscado 6030912063.
Realizando pruebas obtenemos:
Clave = aaaaaaa -> suma = 321272407
Clave = zzzzzzz -> suma = 8353082582
Clave = smaaaaa -> suma = 6024332887
Clave = smkkkkk -> suma = 6029085437
Como vemos, la clave smkkkkk ya está bastante próxima al objetivo y será un buen punto para lanzar la fuerza bruta.
Os dejo el código de fuerza bruta en .Net
Module Module1
Sub Main()
inicio:
Console.WriteLine("-------------------------")
Console.WriteLine("Modo [1] Prueba password")
Console.WriteLine("Modo [2] Fuerza bruta")
Console.WriteLine("-------------------------")
Dim modo = Console.ReadLine()
'
If modo = 2 Then
Console.WriteLine("¿Password para comenzar?")
Dim pass = Console.ReadLine()
inicio2:
Dim cadena As String = "abcdefghijklmnopqrstuvwxyz"
Dim valor As Integer = 0
Dim suma As Long = 0
Dim letra As String
For i = 0 To pass.Length - 1
letra = Mid(pass, i + 1, 1)
valor = cadena.IndexOf(letra)
valor += 1
suma *= 26
suma += valor
Next
Console.WriteLine("Password: " & pass & " - Sum: " & suma.ToString)
pass = IncrementString(pass)
If suma = 6030912063 Then
MsgBox("Password is " & pass)
Else
If pass = "aaaaaaaa" Then
Console.WriteLine("pass not found")
Console.ReadKey()
Else
GoTo inicio2
End If
End If
End If
'------------------------------------------------
If modo = 1 Then
Console.WriteLine("Password:")
Dim pass = Console.ReadLine()
Dim cadena As String = "abcdefghijklmnopqrstuvwxyz"
Dim valor As Integer = 0
Dim suma As Long = 0
Dim letra As String
For i = 0 To pass.Length - 1
letra = Mid(pass, i + 1, 1)
valor = cadena.IndexOf(letra)
valor += 1
suma *= 26
suma += valor
Next
Console.WriteLine("Password: " & pass & " - Sum: " & suma.ToString)
Console.WriteLine(".......")
Console.WriteLine("Good = 6030912063")
Console.WriteLine("Suma = " & suma.ToString)
Console.ReadKey()
Console.Clear()
GoTo inicio
End If
End Sub
Function IncrementString(ByVal strString As String) As String
'
' Increments a string counter
' e.g. "a" -> "b"
' "az" -> "ba"
' "zzz" -> "aaaa"
'
' strString is the string to increment, assumed to be lower-case alphabetic
' Return value is the incremented string
'
Dim lngLenString As Long
Dim strChar As String
Dim lngI As Long
lngLenString = Len(strString)
' Start at far right
For lngI = lngLenString To 0 Step -1
' If we reach the far left then add an A and exit
If lngI = 0 Then
strString = "a" & strString
Exit For
End If
' Consider next character
strChar = Mid(strString, lngI, 1)
If strChar = "z" Then
' If we find Z then increment this to A
' and increment the character after this (in next loop iteration)
strString = Left$(strString, lngI - 1) & "a" & Mid(strString, lngI + 1, lngLenString)
Else
' Increment this non-Z and exit
strString = Left$(strString, lngI - 1) & Chr(Asc(strChar) + 1) & Mid(strString, lngI + 1, lngLenString)
Exit For
End If
Next lngI
IncrementString = strString
Exit Function
End Function
End Module