Using WhatsMyIP.org Without JavaScript: Deobfusticating Code

29 Jul 2011

I'll start this post off by saying if you are someone who polls a site constantly for your IP use: http://whatismyip.akamai.com and not http://www.whatsmyip.org not only is the on the worlds largest CDN but it is just the IP nothing more.

I've been annoyed for a long time, I regular use whatsmyip.org to check my IP for various reasons, I have a bit of trust in the site, but I do not trust the transport (HTTP) so I don't allow JavaScript by default. Especially if there is an unpatched flaw in my browser you won't see me enable JavaScript/Flash/whatever until it's fixed unless it's for a site I trust and it over HTTPS.

That out of the way whatsmyip.org did two things:

Your IP Address is <span id="ip">123.123.123.123</span>

Made the IP in the HTML just something random but valid and added obfuscated JavaScript with a weak cipher to protect it.
Of course there is no point going crazy about this as anyone with enough time to decode it can easily use the address I provided above.

After a quick look at the HTML I saw something of interest

<script type="text/javascript" src="tech/addthis.php"></script>

http://www.whatsmyip.org/tech/addthis.php provides your IP with a bit of obfuscation, I was procrastinating on the book I'm writing so I gave it a shot.
Decoding the hex encoded elements of the array was easy.

With my rule to never reinvent the wheel I did a quick Google search and found

String.prototype.decodeEscapeSequence = function() {
    return this.replace(/\\x([0-9A-Fa-f]{2})/g, function() {
        return String.fromCharCode(parseInt(arguments[1], 16));
    });
};

Source: https://stackoverflow.com/questions/4209104/decoding-hex-string-in-javascript

After making the code look nicer and deobfuscating it I came up with:

function thisIP(data, key, iv)
{
	var something=0;
	data = data-key;
	data = data/iv;

	ip = Math.floor(data/16777216)+'.'
	+Math.floor((data%16777216)/65536)+'.'
	+Math.floor(((data%16777216)%65536)/256)+'.'
	+Math.floor((((data%16777216)%65536)%256));
	return ip;
}

I gave it a go and bingo my IP was decoded, so I quickly whipped up a Greasemonkey script.

// ==UserScript==
// @name           What's My IP.org Without JavaScript
// @namespace      stevenroddis.whatsmyiporg
// @author         Steven Roddis
// @copyright      stevenroddis.com
// @description    Decrypts the IP so you don't need to enable JavaScript.
// @include        http://www.whatsmyip.org/*
// @include        http://*.whatsmyip.org/*
// ==/UserScript==
function thisIP(data, key, iv)
{
	var something=0;
	data = data-key;
	data = data/iv;

	ip = Math.floor(data/16777216)+'.'
	+Math.floor((data%16777216)/65536)+'.'
	+Math.floor(((data%16777216)%65536)/256)+'.'
	+Math.floor((((data%16777216)%65536)%256));
	return ip;
}

GM_xmlhttpRequest({
	method:"GET",
	url:'http://www.whatsmyip.org/tech/addthis.php',
	onload:function(r) {
		data = r.responseText.match(/\[.+?,.+?,([0-9]+),.+?,.+?,.+?,.+?,.+?,.+?,([0-9]+),([0-9]+)/);
		document.getElementById('ip').innerHTML = thisIP(data[1], data[2], data[3]); //so what's on the page is a fake IP
		document.getElementById('ip').style.display = 'inline';
	}
});

And now whatsmyip.org is usable again. :)