bugkuctf

bugkuctf: https://ctf.bugku.com

Target address: http://123.206.31.85:1616/

After entering the drone, select the character attribute you want and start the game

After looking at other game functions, I found that we need to defeat the old demon through crusade to clear the level

You can buy Tathagata Palms from the mall, but you need to use silver taels to buy them. Do we still have that much money to buy cheats?


You can earn 100 taels every 5 seconds through the earning function


By making money, we can see that in the cookie returned to us by the server set-cookie, only one letter has changed.


Of course, we can write a python script to automatically match the setcookie of the returned package to replace our own cookie, and then swipe the money, but I did a calculation, the Tathagata Palm is 100,000 silver taels, we need to swipe 1,000 times, every 5 seconds, that is 5000 seconds, it will take about 1 hour to brush out.

It's not practical, then looked at the html source and didn't find anything ok, but there are 3 js files.


When I clicked script.js and found some abnormal characters, then I set the browser encoding to unicode, and the following characters were displayed.


I made the code js beautification , and perform code analysis:

function getCookie(cname) {#In the following function, a variable user is passed in
    var name = cname + "=";#name = "user="
    var ca = document.cookie.split(';');#Cut the cookie with a semicolon and assign it to the ca variable
    for (var i = 0; i < ca.length; i++) {#Execute a for loop once there is a cookie
        var c = ca[i].trim();#The trim function is empty, and the first cookie is empty and assigned to the c variable
        if (c.indexOf(name) == 0) # Find the string name (uname is the character like "user=") from the variable c (c is our cookie), if the string "uname=" is found at the top, it will return 0
        	return c.substring(name.length, c.length)
        	# c.length (for the length of the cookie) The length of the name is the length of the string "user="
        	# Returns the content of the equal sign and later in the cookie
    }
    return "" #otherwise return empty
}# This function is to intercept the content of the user variable in the cookie

function decode_create(temp) {#temp is the cookie after url decoding
    var base = new Base64();#Instantiate base64 into base variable
    var result = base.decode(temp);# base64 decode temp variable (temp is cookie)
    var result3 = "";
    for (i = 0; i < result.length; i++) {
        var num = result[i].charCodeAt();#Returns the Unicode encoding of the string
        num = num ^ i;#bit XOR
        num = num - ((i % 10) + 2);
        result3 += String.fromCharCode(num)#Convert Unicode encoding to a character
    }
    return result3
}

function ertqwe() {
    var temp_name = "user";
    var temp = getCookie(temp_name);#Intercept the content of the user variable in the cookie
    temp = decodeURIComponent(temp);#Decode the cookie url and reassign it to the temp variable
    var mingwen = decode_create(temp);#Pass in decode_create, and reassign it to the mingwen variable after one encryption. I will explain the execution process here in the following analysis.
    var ca = mingwen.split(';');#Cut, cut with a semicolon, assign it to the ca variable
    var key = "";
    for (i = 0; i < ca.length; i++) {
        if (-1 < ca[i].indexOf("flag")) {
            key = ca[i + 1].split(":")[2]
        }
    }
    key = key.replace('"', "").replace('"', "");
    document.write('<img id="attack-1" src="image/1-1.jpg">');
    setTimeout(function () {
        document.getElementById("attack-1").src = "image/1-2.jpg"
    }, 1000);
    setTimeout(function () {
        document.getElementById("attack-1").src = "image/1-3.jpg"
    }, 2000);
    setTimeout(function () {
        document.getElementById("attack-1").src = "image/1-4.jpg"
    }, 3000);
    setTimeout(function () {
        document.getElementById("attack-1").src = "image/6.png"
    }, 4000);
    setTimeout(function () {
        alert("You used the Tathagata Palm to defeat the old demon, but you don't know if it's the real body or the fake one. Submit it for a try.!flag{" + md5(key) + "}")
    }, 5000)
}

In the ertqwe() function, the content obtained by the mingwen variable

#original code
var mingwen = decode_create(temp);

The above analysis temp is our own cookie. I bring my own cookie into the decode_create() function to execute, and get the following content

O:5:\"human\":10:{s:8:\"xueliang\";i:758;s:5:\"neili\";i:758;s:5:\"lidao\";i:61;s:6:\"dingli\";i:60;s:7:\"waigong\";i:0;s:7:\"neigong\";i:0;s:7:\"jingyan\";i:0;s:6:\"yelian\";i:0;s:5:\"money\";i:0;s:4:\"flag\";s:1:\"0\";}

Then I go to click earn function again


Bring the cookie into the script again to run and find the change.

The idea now is to change the cookie, let us learn the hand of the Tathagata while making money

The way to change the cookie is to reverse-encode the plaintext:

At the beginning, I wrote reverse decryption for a long time, and found that when calling encode in base64, it could not solve the original encryption code, and encode could not encrypt the original cookie.


Guess there must be a problem with base64.js:

It is found that the encryption process does not correspond, and encode calls _utf8_encode
but decode does not call _utf8_encode


As long as we comment out the input = _utf8_encode(input); in encode, the plaintext can be de-encrypted, and we will copy the base64 to the local for testing:

//1.html
<script>

function Base64() {
 
	// private property
	_keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
 
	// public method for encoding
	this.encode = function (input) {
		var output = "";
		var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
		var i = 0;
		//input = _utf8_encode(input); (comment out this function call)
		while (i < input.length) {
			chr1 = input.charCodeAt(i++);
			chr2 = input.charCodeAt(i++);
			chr3 = input.charCodeAt(i++);
			enc1 = chr1 >> 2;
			enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
			enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
			enc4 = chr3 & 63;
			if (isNaN(chr2)) {
				enc3 = enc4 = 64;
			} else if (isNaN(chr3)) {
				enc4 = 64;
			}
			output = output +
			_keyStr.charAt(enc1) + _keyStr.charAt(enc2) +
			_keyStr.charAt(enc3) + _keyStr.charAt(enc4);
		}
		return output;
	}
 
	// public method for decoding
	this.decode = function (input) {
		var output = "";
		var chr1, chr2, chr3;
		var enc1, enc2, enc3, enc4;
		var i = 0;
		input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
		while (i < input.length) {
			enc1 = _keyStr.indexOf(input.charAt(i++));
			enc2 = _keyStr.indexOf(input.charAt(i++));
			enc3 = _keyStr.indexOf(input.charAt(i++));
			enc4 = _keyStr.indexOf(input.charAt(i++));
			chr1 = (enc1 << 2) | (enc2 >> 4);
			chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
			chr3 = ((enc3 & 3) << 6) | enc4;
			output = output + String.fromCharCode(chr1);
			if (enc3 != 64) {
				output = output + String.fromCharCode(chr2);
			}
			if (enc4 != 64) {
				output = output + String.fromCharCode(chr3);
			}
		}
		//output = _utf8_decode(output);
		return output;
	}
 
	// private method for UTF-8 encoding
	_utf8_encode = function (string) {
		string = string.replace(/\r\n/g,"\n");
		var utftext = "";
		for (var n = 0; n < string.length; n++) {
			var c = string.charCodeAt(n);
			if (c < 128) {
				utftext += String.fromCharCode(c);
			} else if((c > 127) && (c < 2048)) {
				utftext += String.fromCharCode((c >> 6) | 192);
				utftext += String.fromCharCode((c & 63) | 128);
			} else {
				utftext += String.fromCharCode((c >> 12) | 224);
				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
				utftext += String.fromCharCode((c & 63) | 128);
			}
 
		}
		return utftext;
	}
 
	// private method for UTF-8 decoding
	_utf8_decode = function (utftext) {
		var string = "";
		var i = 0;
		var c = c1 = c2 = 0;
		while ( i < utftext.length ) {
			c = utftext.charCodeAt(i);
			if (c < 128) {
				string += String.fromCharCode(c);
				i++;
			} else if((c > 191) && (c < 224)) {
				c2 = utftext.charCodeAt(i+1);
				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
				i += 2;
			} else {
				c2 = utftext.charCodeAt(i+1);
				c3 = utftext.charCodeAt(i+2);
				string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
				i += 3;
			}
		}
		return string;
	}
}


//It turns out my cookie
var temp = "UTw7PCxqe3FjcC42OThOjWtSUFYwbm99amlzbG0wI3MeHBsUZ1liZxQMWEFDXl8EdUUOCgACd016B34WUlFWWTVoATEAAXF5P3Z2CmYgPTY5Pj90FSUUaGUfL2ZnYnYhCRMTGRQPQCcHKFIvEShXUlYCGQMbDQ4FXEcXREo/BTzBxKbu6fbrB+H+ps3nsLrP6dCs0LgR8fj1/+6y3+/apJ3XnJnkjNPf0NnRjpPD7pjzzfaMiJDcxt/XkP/B+I2C5vTqgUE=";
//Encrypt, get plaintext

var base = new Base64();
var result = base.decode(temp);
var result3 = "";
for (i = 0; i < result.length; i++) {
	var num = result[i].charCodeAt();
	num = num ^ i;
	num = num - ((i % 10) + 2);
	result3 += String.fromCharCode(num);
}
document.write("Original plaintext:"+result3+'<br/>');
document.write('<br/>');
//Modify plaintext
var result3 = 'O:5:"human":10:{s:8:"xueliang";i:830;s:5:"neili";i:602;s:5:"lidao";i:95;s:6:"dingli";i:63;s:7:"waigong";i:0;s:7:"neigong";i:0;s:7:"jingyan";i:0;s:6:"yelian";i:0;s:5:"money";i:200000;s:4:"flag";s:1:"0";}';

//Reverse encoding to get cookie s
var result = "";
for (i = 0;i<result3.length;i++){
	num = result3[i].charCodeAt();
	num = num + ((i % 10) + 2);
	num = num ^ i;
	result += String.fromCharCode(num);
}
var temp= base.encode(result);

//url-encode cookie s
temp = encodeURIComponent(temp);
document.write("cookie:"+temp+"</br>");
</script>

The de-encoded cookie will be output to the browser,

UTw7PCxqe3FjcC42OThOjWtSUFYwbm99amlzbG0wI3MeHBsUZ1liZxQMWEFDXl8EdUUOCgACd016B34WUlFWWTVoATEAAXF5P3Z2CmYgPTY5Pj90FSUUaGUfL2ZnYnYhCRMTGRQPQCcHKFIvEShXUlYCGQMbDQ4FXEcXREo%2FBTzBxKbu6fbrB%2BH%2Bps3nsLrP6dCs0LgR8fj1%2F%2B6y3%2B%2FapJ3XnJnkjNPf0NnRjpPD7paIiIiIhovBiIL4kNTK0dea%2F7mC%2B4bu%2FOr1SQ%3D%3D


Copy it directly into our cookie, and you can see that we now have 20W silver taels, which is beautiful.

Then go to the store to buy the Tathagata Palm and slay the old demon.

Tags: Javascript security CTF

Posted by Mirge on Mon, 09 May 2022 00:24:45 +0300