Category: CTF
Posted at: Jan 28, 2024
7 Minutes Read
We will walk through HackThisSite's JavaScript challenges and try to solve them. Spoiler alert, they are easy and fun. LET'S DO THIS!
So, there's this button that screams "Click me!" It calls a function named "check"
<button onclick="javascript:check(document.getElementById('pass').value)">Check Password</button
I peeked into the source code and found the function:
function check(x) {
if (x == "cookies") {
alert("win!");
window.location += "?lvl_password=" + x;
} else {
alert("Fail D:");
}
}
Easy-peasy, just type in "cookies" and bam! 🍪
Next up, it says "Disable JavaScript and click the link." Simple! JavaScript off, link clicked! ✅
Got hit with some math equations
var foo = 5 + 6 * 7;
var bar = foo % 8;
var moo = bar * 2;
var rar = moo / 3;
function check(x) {
if (x.length == moo) {
alert("win!");
window.location += "?lvl_password=" + x;
} else {
alert("fail D:");
}
}
I crunched those numbers and found out I needed a password with a length of 14:
(6*7) + 5 = 47
47 mod 8 = 7
7 * 2 = 14
So just type anything with a length of 14 characters or numbers.
They threw some JavaScript lingo at me, checking if my input matched the variable "RawrRawr" that holds the string "moo”
RawrRawr = "moo";
function check(x) {
"+RawrRawr+" == "hack_this_site";
if (x == "" + RawrRawr + "") {
alert("Rawr! win!");
window.location = "../../../missions/javascript/4/?lvl_password=" + x;
} else {
alert("Rawr, nope, try again!");
}
}
The 'unescape' function simply decodes the URL string, resulting in 'ilovemoo' 🐄❤️.
moo = unescape("%69%6C%6F%76%65%6D%6F%6F");
function check(x) {
if (x == moo) {
alert("Ahh.. so that's what she means");
window.location = "../../../missions/javascript/5/?lvl_password=" + x;
} else {
alert("Nope... try again!");
}
}
In this challenge the script was in an external file:
dairycow = "moo";
moo = "pwns";
rawr = "moo";
function checkpass(pass) {
if (pass == rawr + " " + moo) {
alert("How did you do that??? Good job!");
window.location = "../../../missions/javascript/6/?lvl_password=" + pass;
} else {
alert("Nope, try again");
}
}
As you can notice the password is a concatenation of the two variables rawr+" "+moo = moo pwns
This time the script was obfuscated
var _0x4e9d=["\\x66\\x72\\x6F\\x6D\\x43\\x68\\x61\\x72\\x43\\x6F\\x64\\x65","\\x77\\x72\\x69\\x74\\x65"];document[_0x4e9d[0x1]](String[_0x4e9d[0x0]](0x3c,0x62,0x75,0x74,0x74,0x6f,0x6e,0x20,0x6f,0x6e,0x63,0x6c,0x69,0x63,0x6b,0x3d,0x27,0x6a,0x61,0x76,0x61,0x73,0x63,0x72,0x69,0x70,0x74,0x3a,0x69,0x66,0x20,0x28,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x22,0x70,0x61,0x73,0x73,0x22,0x29,0x2e,0x76,0x61,0x6c,0x75,0x65,0x3d,0x3d,0x22,0x6a,0x30,0x30,0x77,0x31,0x6e,0x22,0x29,0x7b,0x61,0x6c,0x65,0x72,0x74,0x28,0x22,0x59,0x6f,0x75,0x20,0x57,0x49,0x4e,0x21,0x22,0x29,0x3b,0x77,0x69,0x6e,0x64,0x6f,0x77,0x2e,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x2b,0x3d,0x20,0x22,0x3f,0x6c,0x76,0x6c,0x5f,0x70,0x61,0x73,0x73,0x77,0x6f,0x72,0x64,0x3d,0x22,0x2b,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x22,0x70,0x61,0x73,0x73,0x22,0x29,0x2e,0x76,0x61,0x6c,0x75,0x65,0x7d,0x65,0x6c,0x73,0x65,0x20,0x7b,0x61,0x6c,0x65,0x72,0x74,0x28,0x22,0x57,0x52,0x4f,0x4e,0x47,0x21,0x20,0x54,0x72,0x79,0x20,0x61,0x67,0x61,0x69,0x6e,0x21,0x22,0x29,0x7d,0x27,0x3e,0x43,0x68,0x65,0x63,0x6b,0x20,0x50,0x61,0x73,0x73,0x77,0x6f,0x72,0x64,0x3c,0x2f,0x62,0x75,0x74,0x74,0x6f,0x6e,0x3e));
JavaScript obfuscation transforms easy-to-read code into another form that is more complex and harder to understand and reverse engineer
I used an online Deobfuscator and got this:
document.write(String.fromCharCode(60, 98, 117, 116, 116, 111, 110, 32, 111, 110, 99, 108, 105, 99, 107, 61, 39, 106, 97, 118, 97, 115, 99, 114, 105, 112, 116, 58, 105, 102, 32, 40, 100, 111, 99, 117, 109, 101, 110, 116, 46, 103, 101, 116, 69, 108, 101, 109, 101, 110, 116, 66, 121, 73, 100, 40, 34, 112, 97, 115, 115, 34, 41, 46, 118, 97, 108, 117, 101, 61, 61, 34, 106, 48, 48, 119, 49, 110, 34, 41, 123, 97, 108, 101, 114, 116, 40, 34, 89, 111, 117, 32, 87, 73, 78, 33, 34, 41, 59, 119, 105, 110, 100, 111, 119, 46, 108, 111, 99, 97, 116, 105, 111, 110, 32, 43, 61, 32, 34, 63, 108, 118, 108, 95, 112, 97, 115, 115, 119, 111, 114, 100, 61, 34, 43, 100, 111, 99, 117, 109, 101, 110, 116, 46, 103, 101, 116, 69, 108, 101, 109, 101, 110, 116, 66, 121, 73, 100, 40, 34, 112, 97, 115, 115, 34, 41, 46, 118, 97, 108, 117, 101, 125, 101, 108, 115, 101, 32, 123, 97, 108, 101, 114, 116, 40, 34, 87, 82, 79, 78, 71, 33, 32, 84, 114, 121, 32, 97, 103, 97, 105, 110, 33, 34, 41, 125, 39, 62, 67, 104, 101, 99, 107, 32, 80, 97, 115, 115, 119, 111, 114, 100, 60, 47, 98, 117, 116, 116, 111, 110, 62));
As you can see we have UTF-16 codes as parameter to the function fromCharCode() which is simply returns a string created from the specified sequence of UTF-16 code units:
`<button onclick='javascript:if (document.getElementById("pass").value=="j00w1n"){alert("You WIN!");window.location += "?lvl_password="+document.getElementById("pass").value}else {alert("WRONG! Try again!")}'>Check Password</button>`
Simple right?