Solución al reto 10 del patrón de desbloqueo

Si recordáis, nuestro último reto consistía en obtener un patrón de desbloqueo similar al utilizado en Android a partir de una emulación en flash. A continuación explicamos cómo se desarrolló el reto y cómo solucionarlo.

Desarrollo del reto

El actionscript está basado en una modificación del
código de Carlos Yanez en Active Tuts+ y fundamentalmente tiene tres niveles de protección:

1.- Chequeo de dominio para prevenir la ejecución del swf desde otros sitios que no sean "googlegroups.com" o "sites.google.com", superponiendo un cuadro de texto "Protegido" para impedir el MOUSE_OVER sobre los puntos del patrón:


if ( checkDomain.indexOf("googlegroups.com" ) == -1  ) {
if ( checkDomain.indexOf("sites.google.com" ) == -1 ) {
var myText:TextField = new TextField();
var myFormat:TextFormat = new TextFormat();
myFormat.font = "Verdana";
myFormat.size = 26;
addChildAt(myText, (0 + this.numChildren) );
myText.width = 600;
myText.height = 800;
myText.textColor = 0xCD7F32;
myText.multiline =true;
myText.wordWrap =true;
myText.x = 40 ;
myText.y = 70;
myText.text = " Protegido" ;
TextField(myText).setTextFormat( myFormat );
}
}

2.- Cifrado en
TEA (Tiny Encryption Algorithm) por medio de la librería ASCrypt3 del string correspondiente al patrón de desbloqueo, que posteriormente es convertido a un array por medio de un split (","):


Main.as:
import com.hpys.utils.*;

var texto_descifrado:String = EncryptUtils.decryptString("80112730378015a38252f57d3201e40b");
var pass:Array = texto_descifrado.split(",");

EncryptUtils.as:
package com.hpys.utils
{
import com.meychi.ascrypt3.TEA;

//-------------------------------------------------------------
public class EncryptUtils
{
internal static const ENCRYPTION_KEY:String = "siluros";
//-------------------------------------------------------------
public static function encryptString(s:String):String
{
var tea:TEA = new TEA();
var encryptedString:String = tea.encrypt(s, ENCRYPTION_KEY);
return encryptedString;
}
public static function decryptString(s:String):String
{
var tea:TEA = new TEA();
var decryptedString:String = tea.decrypt(s, ENCRYPTION_KEY);
return decryptedString;
}
}
}

3.- Y finalmente la protección/ofuscación del código Flash AS3 con
AS3Obfuscator:



El camino fácil

Si os fijáis en la pantalla anterior u observáis el código decompilado, veréis que todas las variables y cadenas se han renombrado con 10 caracteres aleatorios y un sufijo '666' excepto las dos siguientes:

var th4t1s:String = r3oAjJpsMZ666.k1TNULc6Sk666("80112730378015a38252f57d3201e40b");
var teatime_siluros:String = ("teatime_siluros");
Con estas dos pistas y el nombre del paquete 'MLOSVylCb1666.meychi.ascrypt3' podíamos deducir que el string correspondiente a la variable th4t1s (That is!) está cifrado con el algoritmo TEA (teatime) de la ASCrypt3 y la contraseña 'siluros'.

Por medio de
Flashdevelop y Flex SDK podemos compilar un programa que descifre el string:


package
{
import flash.display.Sprite;
import flash.events.Event;
import com.meychi.ascrypt3.*;

/**
* ...
* @author vmotos
*/
public class Main extends Sprite
{

public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}

private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
var texto_descifrado:String = decryptString("80112730378015a38252f57d3201e40b");
trace (texto_descifrado);

}

public static function decryptString(s:String):String
{
var tea:TEA = new TEA();
var decryptedString:String = tea.decrypt(s, "siluros");
return decryptedString;
}

}

}

Lo compilamos/ejecutamos...


...y obtenemos "5,3,2,1,4,8,6", ¡el patrón de desbloqueo!



Solucionario por Mauro Vietri


Otra opción sería ejecutar directamente las funciones ofuscadas para obtener el valor descifrado de la cadena. A continuación veremos cómo nuestro ganador del reto Mauro Vietri (@R34dTh1s) lo soluciona ingeniosamente:

1) Obtuve el archivo swf revisando el código fuente de la web:

<embed src="http://sites.google.com/site/h4ckpl4y3s/reto10hpys.swf" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" align="middle" height="400" width="298"></embed>


2) Un simple comando para obtenerlo:

wget http://sites.google.com/site/h4ckpl4y3s/reto10hpys.swf

3) Fui a http://www.showmycode.com/, subí el archivo SWF (se puede escribir directamente la URL)
y me bajé el código ActionScript: 'reto10.code'

package yXS3nfxGc0666.hpys.utils {
import yXS3nfxGc0666.meychi.ascrypt3.*;

public class _jaJyJkb3H666 {

static const gS5LEgVh_f666:String = D0SBFxdImh666.wn8ZM7OZfg666(30, 21);

public static function tRT3g22kYU666(_arg1:String):String{
var _local2:D3S1SVZ_2J666 = new D3S1SVZ_2J666();
var _local3:String = _local2.Yx1Nuy11jo666(_arg1, gS5LEgVh_f666);
return (_local3);
}
public static function DK62qYPfxF666(_arg1:String):String{
var _local2:D3S1SVZ_2J666 = new D3S1SVZ_2J666();
var _local3:String = _local2.ONZXJeBY7V666(_arg1, gS5LEgVh_f666);
return (_local3);
}

}
}//package yXS3nfxGc0666.hpys.utils
package yXS3nfxGc0666.meychi.ascrypt3 {

public class D3S1SVZ_2J666 {

private static function tkeYG2PRKi666(_arg1:String):Array{
var _local2:Array = new Array();
var _local3:Number = ((_arg1.substr(0, 2))==D0SBFxdImh666.wn8ZM7OZfg666(28, 8)) ? 2 : 0;
while (_local3 < _arg1.length) {
_local2.push(parseInt(_arg1.substr(_local3, 2), 16));
_local3 = (_local3 + 2);
};
return (_local2);
}
private static function N6IbvZaQDt666(_arg1:Array):String{
var _local2:String = new String(D0SBFxdImh666.wn8ZM7OZfg666(11, 6));
var _local3:Array = new Array(D0SBFxdImh666.wn8ZM7OZfg666(12, 15), D0SBFxdImh666.wn8ZM7OZfg666(13, 17), D0SBFxdImh666.wn8ZM7OZfg666(14, 16), D0SBFxdImh666.wn8ZM7OZfg666(15, 11), D0SBFxdImh666.wn8ZM7OZfg666(16, 2), D0SBFxdImh666.wn8ZM7OZfg666(17, 10), D0SBFxdImh666.wn8ZM7OZfg666(18, 14), D0SBFxdImh666.wn8ZM7OZfg666(19, 22), D0SBFxdImh666.wn8ZM7OZfg666(20, 23), D0SBFxdImh666.wn8ZM7OZfg666(21, 20), D0SBFxdImh666.wn8ZM7OZfg666(22, 17), D0SBFxdImh666.wn8ZM7OZfg666(23, 18), D0SBFxdImh666.wn8ZM7OZfg666(24, 12), D0SBFxdImh666.wn8ZM7OZfg666(25, 1), D0SBFxdImh666.wn8ZM7OZfg666(26, 9), D0SBFxdImh666.wn8ZM7OZfg666(27, 11));
var _local4:Number = 0;
while (_local4 < _arg1.length) {
_local2 = (_local2 + (_local3[(_arg1[_local4] >> 4)] + _local3[(_arg1[_local4] & 15)]));
_local4++;
};
return (_local2);
}
private static function TqLFEIK3so666(_arg1:Array):Array{
var _local2:Array = new Array(Math.ceil((_arg1.length / 4)));
var _local3:Number = 0;
while (_local3 < _local2.length) {
_local2[_local3] = (((_arg1[(_local3 * 4)] + (_arg1[((_local3 * 4) + 1)] << 8)) + (_arg1[((_local3 * 4) + 2)] << 16)) + (_arg1[((_local3 * 4) + 3)] << 24));
_local3++;
};
return (_local2);
}
private static function rv35oY_jdV666(_arg1:Array):String{
var _local2:String = new String(D0SBFxdImh666.wn8ZM7OZfg666(29, 4));
var _local3:Number = 0;
while (_local3 < _arg1.length) {
_local2 = (_local2 + String.fromCharCode(_arg1[_local3]));
_local3++;
};
return (_local2);
}
private static function VuI79EKPoM666(_arg1:String):Array{
var _local2:Array = new Array();
var _local3:Number = 0;
while (_local3 < _arg1.length) {
_local2.push(_arg1.charCodeAt(_local3));
_local3++;
};
return (_local2);
}
private static function mqrmVGm1TY666(_arg1:Array):Array{
var _local2:Array = new Array();
var _local3:Number = 0;
while (_local3 < _arg1.length) {
_local2.push((_arg1[_local3] & 0xFF), ((_arg1[_local3] >>> 8) & 0xFF), ((_arg1[_local3] >>> 16) & 0xFF), ((_arg1[_local3] >>> 24) & 0xFF));
_local3++;
};
return (_local2);
}

public function ONZXJeBY7V666(_arg1:String, _arg2:String):String{
var _local10:Number;
var _local11:Number;
var _local14:Number;
var _local3:Array = TqLFEIK3so666(VuI79EKPoM666(_arg1));
var _local4:Array = TqLFEIK3so666(VuI79EKPoM666(_arg2));
var _local5 = "teatime_siluros";
var _local6:Number = _local3.length;
if (_local6 == 0){
return (D0SBFxdImh666.wn8ZM7OZfg666(9, 12));
};
if (_local6 == 1){
var _temp1 = _local6;
_local6 = (_local6 + 1);
var _local15 = _temp1;
_local3[_local15] = 0;
};
var _local7:Number = _local3[(_local6 - 1)];
var _local8:Number = _local3[0];
var _local9:Number = 2654435769;
var _local12:Number = Math.floor((6 + (52 / _local6)));
var _local13:Number = 0;
while (_local12-- > 0) {
_local13 = (_local13 + _local9);
_local11 = ((_local13 >>> 2) & 3);
_local14 = 0;
while (_local14 < (_local6 - 1)) {
_local8 = _local3[(_local14 + 1)];
_local10 = ((((_local7 >>> 5) ^ (_local8 << 2)) + ((_local8 >>> 3) ^ (_local7 << 4))) ^ ((_local13 ^ _local8) + (_local4[((_local14 & 3) ^ _local11)] ^ _local7)));
_local7 = (_local3[_local14] = (_local3[_local14] + _local10));
_local14++;
};
_local8 = _local3[0];
_local10 = ((((_local7 >>> 5) ^ (_local8 << 2)) + ((_local8 >>> 3) ^ (_local7 << 4))) ^ ((_local13 ^ _local8) + (_local4[((_local14 & 3) ^ _local11)] ^ _local7)));
_local7 = (_local3[(_local6 - 1)] = (_local3[(_local6 - 1)] + _local10));
};
return (N6IbvZaQDt666(mqrmVGm1TY666(_local3)));
}
public function Yx1Nuy11jo666(_arg1:String, _arg2:String):String{
var _local9:Number;
var _local10:Number;
var _local13:Number;
var _local3:Array = TqLFEIK3so666(tkeYG2PRKi666(_arg1));
var _local4:Array = TqLFEIK3so666(VuI79EKPoM666(_arg2));
var _local5:Number = _local3.length;
if (_local5 == 0){
return (D0SBFxdImh666.wn8ZM7OZfg666(10, 19));
};
var _local6:Number = _local3[(_local5 - 1)];
var _local7:Number = _local3[0];
var _local8:Number = 2654435769;
var _local11:Number = Math.floor((6 + (52 / _local5)));
var _local12:Number = (_local11 * _local8);
while (_local12 != 0) {
_local10 = ((_local12 >>> 2) & 3);
_local13 = (_local5 - 1);
while (_local13 > 0) {
_local6 = _local3[(_local13 - 1)];
_local9 = ((((_local6 >>> 5) ^ (_local7 << 2)) + ((_local7 >>> 3) ^ (_local6 << 4))) ^ ((_local12 ^ _local7) + (_local4[((_local13 & 3) ^ _local10)] ^ _local6)));
_local7 = (_local3[_local13] = (_local3[_local13] - _local9));
_local13--;
};
_local6 = _local3[(_local5 - 1)];
_local9 = ((((_local6 >>> 5) ^ (_local7 << 2)) + ((_local7 >>> 3) ^ (_local6 << 4))) ^ ((_local12 ^ _local7) + (_local4[((_local13 & 3) ^ _local10)] ^ _local6)));
_local7 = (_local3[0] = (_local3[0] - _local9));
_local12 = (_local12 - _local8);
};
return (rv35oY_jdV666(mqrmVGm1TY666(_local3)));
}

}
}//package yXS3nfxGc0666.meychi.ascrypt3
package {
import flash.display.*;

public dynamic class SecondView extends MovieClip {

}
}//package
package {
import flash.events.*;
import yXS3nfxGc0666.hpys.utils.*;
import flash.display.*;
import flash.text.*;
import flash.geom.*;
import flash.utils.*;

public class xNHtKFEbue666 extends Sprite {

public var seven:MovieClip;
public var eight:MovieClip;
public var two:MovieClip;
public var three:MovieClip;
public var texto:TextField;
public var one:MovieClip;
public var six:MovieClip;
private var OwKk07yArG666:Array;
public var four:MovieClip;
public var five:MovieClip;
public var nine:MovieClip;
private var Rr9sScVR2g666:Array;
private var nFD2T1aXTZ666:Array;
private var EicsUMNFob666:Array;

public function xNHtKFEbue666():void{
var _local2:TextField;
var _local3:TextFormat;
this.EicsUMNFob666 = [];
this.Rr9sScVR2g666 = [];
this.OwKk07yArG666 = [];
this.nFD2T1aXTZ666 = [];
super();
var _local1:String = getChildAt(0).loaderInfo.url;
if (_local1.indexOf(D0SBFxdImh666.wn8ZM7OZfg666(0, 15)) == -1){
if (_local1.indexOf(D0SBFxdImh666.wn8ZM7OZfg666(1, 11)) == -1){
_local2 = new TextField();
_local3 = new TextFormat();
_local3.font = D0SBFxdImh666.wn8ZM7OZfg666(2, 19);
_local3.size = 26;
addChildAt(_local2, (0 + this.numChildren));
_local2.width = 600;
_local2.height = 800;
_local2.textColor = 13467442;
_local2.multiline = true;
_local2.wordWrap = true;
_local2.x = 40;
_local2.y = 70;
_local2.text = D0SBFxdImh666.wn8ZM7OZfg666(3, 13);
TextField(_local2).setTextFormat(_local3);
};
};
this.texto.text = D0SBFxdImh666.wn8ZM7OZfg666(4, 1);
this.EicsUMNFob666 = [this.one, this.two, this.three, this.four, this.five, this.six, this.seven, this.eight, this.nine];
this.JENVEue6Pb666();
}
private function u2QBK668Ch666(_arg1:MouseEvent):void{
var _local2:int = this.EicsUMNFob666.length;
var _local3:int;
while (_local3 < _local2) {
this.EicsUMNFob666[_local3].addEventListener(MouseEvent.MOUSE_OVER, this.Dv0nEgK1yA666);
_local3++;
};
this.Rr9sScVR2g666.push((this.EicsUMNFob666.indexOf(_arg1.target) + 1));
this.u_YVJZq5US666(_arg1.target, 0x7CFC00);
this.OwKk07yArG666.push(_arg1.target.x);
this.nFD2T1aXTZ666.push(_arg1.target.y);
}
private function ckFXNFqgds666():void{
var HFbBsPa_5t666:* = 0;
var NuPcncOJYZ666:* = null;
var fp4hrTC0V4666:* = null;
var oeyYSOk6Vr666:* = 0;
var H4qK33L5JV666:* = null;
var avIjJ6TidD666:* = null;
var th4t1s:* = _jaJyJkb3H666.tRT3g22kYU666("80112730378015a38252f57d3201e40b");
var NH4yRkTRCq666:* = th4t1s.split(D0SBFxdImh666.wn8ZM7OZfg666(6, 4));
var CfBQTDDHt4666:* = NH4yRkTRCq666.length;
var SMvilih6IF666:* = 0;
HFbBsPa_5t666 = 0;
while (HFbBsPa_5t666 < CfBQTDDHt4666) {
if (NH4yRkTRCq666[HFbBsPa_5t666] == this.Rr9sScVR2g666[HFbBsPa_5t666]){
SMvilih6IF666 = (SMvilih6IF666 + 1);
};
HFbBsPa_5t666 = (HFbBsPa_5t666 + 1);
};
if (SMvilih6IF666 == CfBQTDDHt4666){
NuPcncOJYZ666 = new SecondView();
addChild(NuPcncOJYZ666);
} else {
avIjJ6TidD666 = function (_arg1:TimerEvent):void{
texto.text = D0SBFxdImh666.wn8ZM7OZfg666(8, 9);
H4qK33L5JV666.removeEventListener(TimerEvent.TIMER, avIjJ6TidD666);
fp4hrTC0V4666.parent.removeChild(fp4hrTC0V4666);
};
this.texto.text = D0SBFxdImh666.wn8ZM7OZfg666(7, 29);
fp4hrTC0V4666 = new Shape();
fp4hrTC0V4666.graphics.lineStyle(10, 0xFFD700, 1, false, LineScaleMode.VERTICAL, CapsStyle.NONE, JointStyle.MITER, 10);
oeyYSOk6Vr666 = this.OwKk07yArG666.length;
fp4hrTC0V4666.graphics.moveTo(this.OwKk07yArG666[0], this.nFD2T1aXTZ666[0]);
HFbBsPa_5t666 = 0;
while (HFbBsPa_5t666 < oeyYSOk6Vr666) {
fp4hrTC0V4666.graphics.lineTo(this.OwKk07yArG666[HFbBsPa_5t666], this.nFD2T1aXTZ666[HFbBsPa_5t666]);
HFbBsPa_5t666 = (HFbBsPa_5t666 + 1);
};
this.addChild(fp4hrTC0V4666);
H4qK33L5JV666 = new Timer(1500);
H4qK33L5JV666.start();
H4qK33L5JV666.addEventListener(TimerEvent.TIMER, avIjJ6TidD666);
};
this.OwKk07yArG666 = [];
this.nFD2T1aXTZ666 = [];
this.Rr9sScVR2g666 = [];
}
private function Dv0nEgK1yA666(_arg1:MouseEvent):void{
this.u_YVJZq5US666(_arg1.target, 0x7CFC00);
this.Rr9sScVR2g666.push((this.EicsUMNFob666.indexOf(_arg1.target) + 1));
this.OwKk07yArG666.push(_arg1.target.x);
this.nFD2T1aXTZ666.push(_arg1.target.y);
}
private function u_YVJZq5US666(_arg1:Object, _arg2:uint):void{
var _local3:ColorTransform = _arg1.transform.colorTransform;
_local3.color = _arg2;
_arg1.transform.colorTransform = _local3;
}
private function JENVEue6Pb666():void{
var _local1:int = this.EicsUMNFob666.length;
var _local2:int;
while (_local2 < _local1) {
this.EicsUMNFob666[_local2].addEventListener(MouseEvent.MOUSE_DOWN, this.u2QBK668Ch666);
this.EicsUMNFob666[_local2].addEventListener(MouseEvent.MOUSE_UP, this.n217_i6jX9666);
_local2++;
};
}
private function n217_i6jX9666(_arg1:MouseEvent):void{
var _local2:int = this.EicsUMNFob666.length;
var _local3:int;
while (_local3 < _local2) {
this.EicsUMNFob666[_local3].removeEventListener(MouseEvent.MOUSE_OVER, this.Dv0nEgK1yA666);
this.u_YVJZq5US666(this.EicsUMNFob666[_local3], 0xFFFFFF);
_local3++;
};
this.ckFXNFqgds666();
}

}
}//package
package {

public class D0SBFxdImh666 {

static var ar:Array = [[118, 126, 126, 118, 123, 116, 118, 129, 126, 132, 127, 130, 61, 114, 126, 124], [126, 116, 127, 112, 126, 57, 114, 122, 122, 114, 119, 112, 57, 110, 122, 120], [105, 120, 133, 119, 116, 129, 116], [45, 45, 45, 45, 45, 93, 127, 124, 129, 114, 116, 118, 113, 124], [69, 106, 99, 118, 107, 102, 33, 102, 109, 33, 113, 98, 117, 115, 244, 111, 33, 113, 98, 115, 98, 33, 101, 102, 116, 99, 109, 112, 114, 118, 102, 98, 115], [73, 65, 66, 66, 67, 72, 68, 65, 68, 72, 73, 65, 66, 70, 114, 68, 73, 67, 70, 67, 119, 70, 72, 117, 68, 67, 65, 66, 118, 69, 65, 115], [48], [105, 140, 61, 144, 130, 139, 145, 134, 138, 140, 144, 73, 61, 134, 139, 145, 262, 139, 145, 130, 137, 140, 61, 129, 130, 61, 139, 146, 130, 147, 140], [77, 114, 107, 126, 115, 110, 41, 110, 117, 41, 121, 106, 125, 123, 252, 119, 41, 121, 106, 123, 106, 41, 109, 110, 124, 107, 117, 120, 122, 126, 110, 106, 123], [], [], [], [63], [66], [66], [62], [54], [63], [68], [77], [79], [77], [114], [116], [120, 61, 79, 112, 88, 84, 122, 131, 110, 87, 66, 66, 66], [101], [87, 83, 115, 116, 79, 79, 81, 121, 114, 58, 63, 63, 63], [113], [56, 128], [], [136, 126, 129, 138, 135, 132, 136]];

public static function wn8ZM7OZfg666(_arg1:int, _arg2:int):String{
var _local3 = "";
var _local4:Array = ar[_arg1];
var _local5:int;
while (_local5 < _local4.length) {
_local3 = (_local3 + String.fromCharCode((_local4[_local5] - _arg2)));
_local5++;
};
return (_local3);
}

}
}//package


4) Luego de varias horas de frustración y de intentos fallidos, me concentré en:

Linea 235:
var th4t1s:* = _jaJyJkb3H666.tRT3g22kYU666("80112730378015a38252f57d3201e40b");

Más allá del lenguaje l33t (th4t1s = that is = esto es), un hash siempre está por algo.

5) En la siguiente línea (236) hay una llamada a una función:

var NH4yRkTRCq666:* = th4t1s.split(D0SBFxdImh666.wn8ZM7OZfg666(6, 4));

La función 'wn8ZM7OZfg666' la llamé 'crack' en el archivo 'reto10.py'

#!/usr/bin/env python2

#Array sacado del SWF
list = [[118, 126, 126, 118, 123, 116, 118, 129, 126, 132, 127, 130, 61, 114, 126, 124], [126, 116, 127, 112, 126, 57, 114, 122, 122, 114, 119, 112, 57, 110, 122, 120], [105, 120, 133, 119, 116, 129, 116], [45, 45, 45, 45, 45, 93, 127, 124, 129, 114, 116, 118, 113, 124], [69, 106, 99, 118, 107, 102, 33, 102, 109, 33, 113, 98, 117, 115, 244, 111, 33, 113, 98, 115, 98, 33, 101, 102, 116, 99, 109, 112, 114, 118, 102, 98, 115], [73, 65, 66, 66, 67, 72, 68, 65, 68, 72, 73, 65, 66, 70, 114, 68, 73, 67, 70, 67, 119, 70, 72, 117, 68, 67, 65, 66, 118, 69, 65, 115], [48], [105, 140, 61, 144, 130, 139, 145, 134, 138, 140, 144, 73, 61, 134, 139, 145, 262, 139, 145, 130, 137, 140, 61, 129, 130, 61, 139, 146, 130, 147, 140], [77, 114, 107, 126, 115, 110, 41, 110, 117, 41, 121, 106, 125, 123, 252, 119, 41, 121, 106, 123, 106, 41, 109, 110, 124, 107, 117, 120, 122, 126, 110, 106, 123], [], [], [], [63], [66], [66], [62], [54], [63], [68], [77], [79], [77], [114], [116], [120, 61, 79, 112, 88, 84, 122, 131, 110, 87, 66, 66, 66], [101], [87, 83, 115, 116, 79, 79, 81, 121, 114, 58, 63, 63, 63], [113], [56, 128], [], [136, 126, 129, 138, 135, 132, 136]]

def crack(arg1, arg2):
a = ""
b = list[arg1]
c = 0
while (c < len(b)):
a = a + chr(b[c] - arg2)
c = c +1
return a



a = crack(30,21) #=> siluros (Funcion foo)
b = crack(10,19) #=> "" (Funcion func8)
c = crack(28,8) #=> 0x (Funcion func1)
d = crack(29,4) #=> "" (Funcion func4)

print ("A: %s, B: %s, C: %s, D: %s" %(a,b,c,d))

Si bien lo podía haber hecho junto a lo demás en JS, lo separé en Python. Las llamadas
a esta función en 'reto10.html' están eliminadas y en su lugar está directamente el texto
desencriptado.

6) Centré mi atención en la función donde se encuentra el hash (function ckFXNFqgds666()) y
armé el archivo 'reto10.html' con un script en javascript:

<script>

function func1($arg1) {
var v2 = new Array();
var v3 = (($arg1.substr(0, 2))== "0x" ) ? 2 : 0;
while (v3 < $arg1.length) {
v2.push(parseInt($arg1.substr(v3, 2), 16));
v3 = (v3 + 2);
};
return v2;
}


function func3($arg1) {
var v2 = new Array(Math.ceil(($arg1.length / 4)));
var v3 = 0;
while (v3 < v2.length) {
v2[v3] = ((($arg1[(v3 * 4)] + ($arg1[((v3 * 4) + 1)] << 8)) + ($arg1[((v3 * 4) + 2)] << 16)) + ($arg1[((v3 * 4) + 3)] << 24));
v3++;
};
return v2;
}


function func4($arg1) {
var v2 = "";
var v3 = 0;
while (v3 < $arg1.length) {
v2 = (v2 + String.fromCharCode($arg1[v3]));
v3++;
};
return v2;
}


function func5($arg1) {
var v2 = new Array();
var v3 = 0;
while (v3 < $arg1.length) {
v2.push($arg1.charCodeAt(v3));
v3++;
};
return v2;
}


function func6($arg1) {
var v2 = new Array();
var v3 = 0;
while (v3 < $arg1.length) {
v2.push(($arg1[v3] & 0xFF), (($arg1[v3] >>> 8) & 0xFF), (($arg1[v3] >>> 16) & 0xFF), (($arg1[v3] >>> 24) & 0xFF));
v3++;
};
return v2;
}

function func8($_arg1, $_arg2) {
var v9;
var v10;
var v13;
var v3 = func3(func1($_arg1));
var v4 = func3(func5($_arg2));
var v5 = v3.length;
if (v5 == 0){
return ("");
};
var v6 = v3[(v5 - 1)];
var v7 = v3[0];
var v8 = 2654435769;
var v11 = Math.floor((6 + (52 / v5)));
var v12 = (v11 * v8);
while (v12 != 0) {
v10 = ((v12 >>> 2) & 3);
v13 = (v5 - 1);
while (v13 > 0) {
v6 = v3[(v13 - 1)];
v9 = ((((v6 >>> 5) ^ (v7 << 2)) + ((v7 >>> 3) ^ (v6 << 4))) ^ ((v12 ^ v7) + (v4[((v13 & 3) ^ v10)] ^ v6)));
v7 = (v3[v13] = (v3[v13] - v9));
v13--;
};
v6 = v3[(v5 - 1)];
v9 = ((((v6 >>> 5) ^ (v7 << 2)) + ((v7 >>> 3) ^ (v6 << 4))) ^ ((v12 ^ v7) + (v4[((v13 & 3) ^ v10)] ^ v6)));
v7 = (v3[0] = (v3[0] - v9));
v12 = (v12 - v8);
};
return (func4(func6(v3)));
}



function foo($arg) {
var v3 = func8($arg, "siluros");
return v3;
}


var f = foo("80112730378015a38252f57d3201e40b");
document.write("El patron es: " + f);


</script>

Consta de 6 funciones siendo 'func8' la principal y la que origina llamadas a func1, func3, func4,
func5 y func6

7) Una vez pasado dichas funciones a Javascript, lo ejecuté y obtuve:

'5,3,2,1,4,8,6'

Hice el patrón en la animación y ha salido un "Bien Hecho!"


Agradecimientos

No podíamos despedir esta entrada sin daros las gracias a todos los que habéis intentado resolver este reto, con especial mención a Mauro Vietri por ser el ganador y a Miguel Gesteiro por incluirlo en el h4ckc0nt3st que tuvo lugar durante las jornadas de seguridad del GSIC.
En dicho concurso también lo resolvieron ramandi2, BatchDrake, telmat1 y skastro. Si publican sus writes-up actualizaremos esta entrada con su contenido o enlaces.

3 comentarios :

  1. Gracias a ti por cedernos este magnífico reto para el h4ckc0nt3st de las Jornadas GSIC.

    Espero poder enviarte los solucionarios en cuanto me los proporcionen!

    ResponderEliminar
  2. El ganador del h4ckc0ntest fue el usuario ramandi2; éramos el grupo PentSec. Tenéis nuestra solución aquí: http://www.pentsec.com/2011/04/writeup-desafio-11-h4ckc0nt3st-gsic.html Un saludo y gracias por todo ;-)

    ResponderEliminar
  3. @pentsec muchas gracias por el excelente solucionario y enhorabuena por ganar el h4ckc0nt3st. Sois unas maquinas!

    ResponderEliminar