HackIt! 2010: Level 4. Solución

Realmente una prueba que superamos en menos tiempo que la anterior. Basta con un pequeño script o programa para solucionar. Yo me he decantado por esto último, algo quick & dirty en Java: un bucle recorre el fichero, guardando en una tabla hash el número de apariciones de cada carácter que aparece en el enorme texto que nos plantea el reto 4.

import java.util.*;
import java.io.*;
 
public class Lector {
     public static void main(String[] args) throws Exception{
 
            HashMap<Character, Integer> h = new LinkedHashMap<Character,Integer>();
 
           Scanner s = new Scanner(new File("level4"));
 
           while (s.hasNext()){
 
               String line = s.next();
               for (int i= 0; i < line.length(); i++){
                    if (h.get(line.charAt(i))!=null){
                        h.put(line.charAt(i), h.get(line.charAt(i))+1);
                    }else{
                        h.put(line.charAt(i), 1);
                    }
               } 
           }
               System.out.println(h);
     }
}

Es una tabla hash especial, una LinkedHashMap en concreto. Especial dado que al recorrerla quiero hacerlo en el mismo orden en el que inserté las claves. Si compilamos y ejecutamos el programa que os muestro en la imagen, aparece en los resultados un conjunto de caracteres con una única instancia en el texto. En orden: 8675309. Buscando en Google, la primera aparición de esa cadena es un artículo de la Wikipedia, indicando que es el nombre de de una canción del cantante Tommy Tutone. Y así llegamos al level 5.

Solución al HackIt’2010: level 3

Tras rompernos la cabeza con el acertijo de Einstein y no obtener nada en claro, nos decantamos por analizar todo lo que el servidor nos enviaba (cookies, cabeceras, gráficos…) Y héte aquí que analizando el código fuente de la página, vimos que en la hoja de estilos CSS que se cargaba (en concreto en la URL: http://hackit2010.marcansoft.com/default.css ) aparecía una bonita imagen de fondo: img/background.png . La que acompaña a este artículo… y así llegamos al nivel 4, que no es complicado (uy! he dicho la palabra mágica ;-P

El acertijo de Einstein

Hey_Neken nos quiso volver locos con el level3 del HackIt!2010. Para ello nos pasó como enunciado el conocido como «acertijo de Einstein»:

Tenemos las siguientes claves:

  • El británico vive en la casa roja.
  • El sueco tiene un perro.
  • El danés toma té.
  • La casa verde esta a la izquierda de la blanca.
  • El dueño de la casa verde toma café.
  • La persona que fuma Pall Mall tiene un pájaro.
  • El dueño de la casa amarilla fuma Dunhill.
  • El que vive en la casa del centro toma leche.
  • El noruego vive en la primera casa.
  • La persona que fuma Brends vive junto a la que tiene un gato.
  • La persona que tiene un caballo vive junto a la que fuma Dunhill.
  • El que fuma Bluemasters bebe cerveza.
  • El alemán fuma prince.
  • El noruego vive junto a la casa azul.
  • El que fuma Brends tiene un vecino que toma agua.

Y por ultimo la pregunta:
¿Quién es el dueño del pececito?

Bien, el acertijo tiene solución, y la podéis encontrar detallada aquí. El problema es que esa no era la solución al level3…   Una pista: analizad todo lo que nos envía el servidor…

HackIt’2010: Level 2

Más de lo mismo 🙂 Aunque ahora el código Javascript está ofuscado con un empaquetador (packer).
Basta con abrir el level2.js y analizar la primera línea:

eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\b'+e(c)+'\b','g'),k[c]);return p}('C D(){f a=q.t('u').w;f r=z A(8);f x="";B(f i=0;i<r.g;i++){r[i]=z A()}c(a.g==8){c(a.b(5)=="n"){r[7]=["l","j","k","j","9","1","l","m"];c(a.b(4)=="0"){r[2]=["x","d","e","j"];c(a.b(0)=="3"){r[8]=["s","s","3","j","o","E","k"];c(a.b(3)=="y"){r[6]=["7","5","k","j","n","v","k"];r[0]=["l","j","k","j"];c(a.b(1)=="4"){r[3]=["l","j","4","j"];r[1]=["l","j","k","j"];c(a.b(2)=="s"){r[5]=["l","j","k","j","h","o","p"];c(a.b(6)=="3"){r[4]=["l","j","k","j","2","8","h"];B(f j=0;j<r[7].g;j++){x=x+r[j][j]}c(x.F("e","3")==r[7][0]+r[2][3]+a.b(6)+r[5][3]+"2"+r[8][4]+r[1][2]+r[7][7]){q.t('u').w=a.b(0)+a.b(1)+a.b(2)+a.b(3)+a.b(4)+a.b(5)+a.b(6);G()}}}}}}}}}}',43,43,'|||||||||||charAt|if|||var|length||||||||||document|||getElementById|password||value|||new|Array|for|function|check|S|replace|Login'.split('|'),0,{}))

Busando packers de Javascript en Google, llegamos a éste (usando «eval(function(p,a,c,k,e,r)» como cadena de búsqueda).

Desempaquetamos y obtenemos código mucho más clarito (donde vemos también que hey_neken metió líneas de código espurio)

function check() {
	var a = document.getElementById('password').value;
	var r = new Array(8);
	var x = "";
	for (var i = 0; i < r.length; i++) {
		r[i] = new Array()
	}
	if (a.length == 8) {
		if (a.charAt(5) == "n") {
			r[7] = ["l", "j", "k", "j", "9", "1", "l", "m"];
			if (a.charAt(4) == "0") {
				r[2] = ["x", "d", "e", "j"];
				if (a.charAt(0) == "3") {
					r[8] = ["s", "s", "3", "j", "o", "S", "k"];
					if (a.charAt(3) == "y") {
						r[6] = ["7", "5", "k", "j", "n", "v", "k"];
						r[0] = ["l", "j", "k", "j"];
						if (a.charAt(1) == "4") {
							r[3] = ["l", "j", "4", "j"];
							r[1] = ["l", "j", "k", "j"];
							if (a.charAt(2) == "s") {
								r[5] = ["l", "j", "k", "j", "h", "o", "p"];
								if (a.charAt(6) == "3") {
									r[4] = ["l", "j", "k", "j", "2", "8", "h"];
									for (var j = 0; j < r[7].length; j++) {
										x = x + r[j][j]
									}
									if (x.replace("e", "3") == r[7][0] + r[2][3] + a.charAt(6) + r[5][3] + "2" + r[8][4] + r[1][2] + r[7][7]) {
										document.getElementById('password').value = a.charAt(0) + a.charAt(1) + a.charAt(2) + a.charAt(3) + a.charAt(4) + a.charAt(5) + a.charAt(6);
										Login()
									}
								}
							}
						}
					}
				}
			}
		}
	}
}

Siguiendo las comprobaciones de las ramas if, llegamos a:

     0 1 2 3 4 5 6 7
     3 4 s y 0 n e .

Donde la longitud ha de ser de 8 caracteres, siendo el último de ellos uno cualquiera. Y con esto, llegamos al level3 donde estuvimos un buen rato atascados… a ver qué tal se os da a vosotros 😉

HackIt 2010: Solución al level 1

SPOILER! Si quieres resolverlo por tu cuenta, no sigas leyendo (Edit: recuerda que el HackIt! 2010 está disponible en la web de Marcan)

Tú lo has querido, estabas avisado…

Analizando el código fuente veremos la siguiente función Javascript (que he desplegado para que el código se vea mejor):

 
function check(){
...
    if(pass.charCodeAt(0) == "102"){
        if(pass.charCodeAt(1) == "52"){
             if(pass.charCodeAt(6) == "115"){
                  if(pass.charCodeAt(3) == "49"){
                      if(pass.charCodeAt(8) == "109"){
                         if(pass.charCodeAt(5) == "49"){
                               pass2 = pass.replace("i","1").replace("a","4").replace("o","0");
                               if(pass.charCodeAt(2) == "99"){
                                     if(pass.charCodeAt(7) == "49"){
                                         if(pass.charCodeAt(4) == "108"){
                                              if(pass.charCodeAt(9) == "111"){
                                                       Login();

Es decir, se comprueba letra a letra la cadena que hayas metido como password. Para que no sea trivial, en lugar de comprobar el carácter en sí, se comprueba su código ASCII. Y en una línea especial se busca que todas las i se sustituyan por el número 1, las a por el 4 y las o por el número 0 (esta última sustitución es una pequeña trampa, porque en la última rama del if se comprueba que la última letra sea realmente una o – y no un 0 – )

Así pues:

Posición: 0    1    2    3     4    5    6     7       8     9
ASCII    102   52   99   49   108   49   115  49     109   111
carácter  f    4   c    1     l     1    s    1      m     o

El autor del level (hey_neken) lo decía en el propio enunciado, el password es f4c1l1s1mo .