Level 7 – scriptures

Level 7 – scriptures

Scriptures was the last level in the Web challenges from RootedCON’2010 CTF list but the first I resolved.

Just a textbox and a button to check the user input.

Let’s go through the textbox and we take a look inside…

The source code:

source code

A simple form, named “pepe” (as my uncle), with an input field of type “text”, named “pass” (as my dog), and a button, named “ok” (as my grandmother), which uses javascript to validate the text you write into the textbox.

The javascript code is packed:

eval(function(p,a,c,k,e,d){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--){d[e(c)]=k||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k)}}return p}('k r(f){u(!f)j\'\';h p=\'\';x(i=f["\\c\\9\\8\\v\\4\\a"]-1;i>=0;i--)p+=f["\\s\\a\\7\\6\\y\\4"](i);j p}k D(E){h o="\\8\\m\\q\\H\\d\\q\\8\\w\\J\\q\\w\\I";h l="";x(i=0;i<o["\\c\\9\\8\\v\\4\\a"];i++){l+=e["\\G\\4\\6\\d\\8\\v"]["\\L\\6\\2\\Q\\n\\a\\7\\6\\n\\2\\g\\9"]((o["\\s\\a\\7\\6\\n\\2\\g\\9\\y\\4"](i)-(5*i)%3)%M)}h F=r(l);u(E==F){j K}B{j P}}k N(t){u(D(t)){e["\\7\\c\\9\\6\\4"]("\\A\\7\\b\\b\\z\\2\\6\\g \\d\\b \\2\\m");e["\\c\\2\\s\\7\\4\\d\\2\\8"]=t+"\\O\\C\\a\\C"}B{e["\\7\\c\\9\\6\\4"]("\\A\\7\\b\\b\\z\\2\\6\\g \\d\\b \\8\\2\\4 \\2\\m")}}',53,53,'||x6f||x74||x72|x61|x6e|x65|x68|x73|x6c|x69|window|qye1|x64|var||return|function|d5|x6b|x43|DZr4|WXXJ2|x75||x63|wFLbnl7|if|x67|x32|for|x41|x77|x50|else|x70|cp|tspaQc3|Gd_6|x53|x33|x7a|x78|true|x66|256|validate|x2e|false|x6d'.split('|'),0,{}));

Searching the web for unpackers, I’ve found this one: Unpack packed Javascript code

The unpacked code is ugly and difficult to read:

function r(qye1) {
  if (!qye1) return '';
  var WXXJ2 = '';
  for (i = qye1['\x6c\x65\x6e\x67\x74\x68'] - 1; i >= 0; i--) WXXJ2 += qye1['\x63\x68\x61\x72\x41\x74'](i);
  return WXXJ2
}
function cp(tspaQc3) {
  var DZr4 = '\x6e\x6b\x75\x33\x69\x75\x6e\x32\x78\x75\x32\x7a';
  var d5 = '';
  for (i = 0; i < DZr4['\x6c\x65\x6e\x67\x74\x68']; i++) {
    d5 += window['\x53\x74\x72\x69\x6e\x67']['\x66\x72\x6f\x6d\x43\x68\x61\x72\x43\x6f\x64\x65']((DZr4['\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74'](i) - (5 * i) % 3) % 256)
  }
  var Gd_6 = r(d5);
  if (tspaQc3 == Gd_6) {
    return true
  } else {
    return false
  }
}
function validate(wFLbnl7) {
  if (cp(wFLbnl7)) {
    window['\x61\x6c\x65\x72\x74']('\x50\x61\x73\x73\x77\x6f\x72\x64 \x69\x73 \x6f\x6b');
    window['\x6c\x6f\x63\x61\x74\x69\x6f\x6e'] = wFLbnl7 + '\x2e\x70\x68\x70'
  } else {
    window['\x61\x6c\x65\x72\x74']('\x50\x61\x73\x73\x77\x6f\x72\x64 \x69\x73 \x6e\x6f\x74 \x6f\x6b')
  }
}

By using the print function from python to print out that code as a whole string, the hex-obfuscated strings become clear:

function r(qye1) {
	if (!qye1) return '';
	var WXXJ2 = '';
	for (i = qye1['length'] - 1; i >= 0; i--) WXXJ2 += qye1['charAt'](i);
	return WXXJ2
}
function cp(tspaQc3) {
	var DZr4 = 'nku3iun2xu2z';
	var d5 = '';
	for (i = 0; i < DZr4['length']; i++) {
		d5 += window['String']['fromCharCode']((DZr4['charCodeAt'](i) - (5 * i) % 3) % 256)
	}
	var Gd_6 = r(d5);
	if (tspaQc3 == Gd_6) {
		return true
	} else {
		return false
	}
}
function validate(wFLbnl7) {
	if (cp(wFLbnl7)) {
		window['alert']('Password is ok');
		window['location'] = wFLbnl7 + '.php'
	} else {
		window['alert']('Password is not ok')
	}
}

The validate function take our input as argument and calls the cp function passing our input again as parameter. The cp function calculates a hash and call the r function with that hash and return it reversed, this reversed-hash (the right password) is compared to our input and if they are equals returns true or false otherwise.

If cp returns false we get the “Password is not ok” message :(
But if it returns true we’re redirected to “our-input.php” page that tell us how great we are.
The right password doesn’t depend on our input. It’s fixed! So, we can alter the javascript code to tell it: “Bring me the right password”.

The Gd_6 variable holds it. It would be enough to insert a line like:

var Gd_6 = r(d5);
 alert("The right password is: " + Gd_6)
 if (tspaQc3 == Gd_6) {
 ...

But I did it this way:

...
  if (tspaQc3 == Gd_6) {
    return true
  } else {
    return Gd_6
  }
}
function validate(wFLbnl7) {
  if (r=cp(wFLbnl7)) {
    window['alert'](r + ' - Password is ok');
...

I’ve changed the value returned by cp function when the if sentence is false:
Before the change, it returned false, now it returns the value of Gd_6 var (the right password).
Assigning that value to a variable, we can display it into a popup alert window.

solved

I’ve used the excellent firebug add-on for Firefox to edit the javascript code.

Flag captured: y0uw0ntg3tin

Challenge – Level 7 difficulty: almost easy.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Antes de enviar el formulario: