Today I encountered a
very pleasant 'crackme' challenge from
Paweł Goleń. The purpose is to find out what is the purpose of
demo page set up by Paweł.
Visiting this page with e.g. Firebug enabled (or with any HTTP proxy) quickly shows that a POST request is sent upon visiting. You didn't submit any form manually so it must be JavaScript sending it. So, you just need to view the source of the page to find the JS code. And this is where the fun starts. The code looks like this:
Obfuscation
Not really readable... This code is
obfuscated - modifed to make its analysis difficult. This is the technique widely
used with malware software.
The encoded software usually tries to hack into the machine, so it can:
- download even more code from a remote URL
- send some data to a remote (attacker) server
- exploit a browser vulnerability to execute a code on the machine
- scan the internal network
- hack into your router and convert it to a spam server
Obfuscating code sometimes prevents the software from being detected by antivirus/malware scans, but it is mainly used to make it harder to determine what the script actually does (and e.g. prepare antivirus signature for it).
In JavaScript obfuscation is usually based on heavy usage of
unescape,
String.fromCharCode and
eval functions.
Luckily, JavaScript itself, with the help of Firebug, has tools that enable you to decode such obfuscated script, so it is only a matter of time to
reverse engineer it.
Function overloading
JavaScript is a
functional language, so - in plain words - the function itself can be written to variable, passed as an argument etc. And - as a variable - it can be reassigned. So it is possible to change the behaviour of any JavaScript function. Example:
<html><head>
</head>
<body><div id="alert"></div>
<script type="text/javascript">
window.alert = function() {
document.getElementById('alert').innerHTML = arguments[0]
};
alert('hello world');
</script>
</body></html>
Here we overload widely used
alert function - instead of a message box it will insert a given message to a
<div id="alert"> element. Two things to note:
- alert is in fact window.alert because JS in browsers has a global object named window
- arguments is an array-like object containing parameters passed to the function, so in this case it's ['hello world']
Let's decode
Analysing any obfuscated script will be much easier if you overloaded the key functions:
unescape,
String.fromCharCode and
eval. But, for the script to actually work, our overloaded functions must call the original ones:
var oldunescape = window.unescape;
window.unescape = function() {
var u = oldunescape.apply(this,arguments); // this calls the old function
console.log('unescape ', arguments, u);
return u;
}
var oldCharCode = String.fromCharCode;
String.fromCharCode = function() {
var u = oldCharCode.apply(this,arguments);
console.log('charcode ', arguments, u);
return u;
}
var oldeval = window.eval;
window.eval = function() {
var args = arguments;
console.log('eval ', arguments, u);
var u = oldeval.apply(this,arguments);
debugger; // here the debugger (e.g. Firebug) will kick in
return u;
}
With this code you may start decoding the script, consistently replacing obfuscated code in HTML with decoded one coming from Firebug console. You can also insert the
debugger; line anywhere in a JS to add a breakpoint.
One thing to note - when debugging malware, be sure to make it in a safe environment (e.g. a separate virtual machine, some sort of sandbox), because otherwise there is a risk you'll become its victim.
We're finished...?
Unfortunately, that's only the first part of analyzing the software. After getting the plaintext version we need to understand what it actually does (and that's usually intentionally hidden in many functions, variables, exceptions, browser differences and strange program flow). It is hard and requires both patience and a bit of JavaScript knowledge, but it is, I think, one of the fastest and most exciting ways to learn. So, go grab your Firebugs and try for yourself -
what does this page do?