XCTF-攻防世界CTF平台-Crypto类——4flag_in_your_hand1

Posted 大灬白

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了XCTF-攻防世界CTF平台-Crypto类——4flag_in_your_hand1相关的知识,希望对你有一定的参考价值。

下载文件之后,发现是一道前端的题目:有一个index.html文件和一个script-min.js文件:

运行html文件:

要求输入一个Token,然后点Get flag!按钮:

代码逻辑就是输入一个字符串,然后经过计算对比得到正确的flag
我们先查看源代码:

<html>
	<head>
		<title>Flag in your Hand</title>
		<style type="text/css">
			body {
				padding-left: 30%;
			}

			#flag {
				font-family: Garamond, serif;
				font-size: 36px;
			}

			#flagtitle {
				font-family: Garamond, serif;
				font-size: 24px;
			}

			.rightflag {
				color: green;
			}

			.wrongflag {
				color: red;
			}
		</style>
		<script src="script-min.js"></script>
		<script type="text/javascript">
			var ic = false;
			var fg = "";

			function getFlag() {
				var token = document.getElementById("secToken").value;
				ic = checkToken(token);
				fg = bm(token);
				showFlag()
			}

			function showFlag() {
				var t = document.getElementById("flagTitle");
				var f = document.getElementById("flag");
				//!!判断ic是否为空,为空则t.innerText赋为第一个值
				t.innerText = !!ic ? "You got the flag below!!" : "Wrong!";
				t.className = !!ic ? "rightflag" : "wrongflag";
				f.innerText = fg;
			}
		</script>
	</head>
	<body>
		<h1>Flag in your Hand</h1>
		<p>Type in some token to get the flag.</p>
		<p>Tips: Flag is in your hand.</p>
		<div>
			<p>
				<span>Token:</span>
				<span><input type="text" id="secToken"/></span>
			</p>
			<p>
				<input type="button" value="Get flag!" onclick="getFlag()" />
			</p>
		</div>
		<div>
			<p id="flagTitle"></p>
			<p id="flag"></p>
		</div>
	</body>
</html>

输入框的id=“secToken”,值保存在token变量中,先调用checkToken(token)函数检查token
查看checkToken()函数:

它在script-min.js只有这一处声明,是个假的TOKEN返回给ic变量,下面showFlag()函数也是根据ic变量的值判断输出flag的
之后的fg = bm(token);就是根据输入的字符串计算得到一个最终的结果,之后在前端最下面显示出来
注意这里的ic变量的值和fg变量的值是没有关系的,但是最终输出flag的时候他们都要求是正确的值
先求flag字符串的内容的过程:fg变量
查看bm(token)函数:

它层层嵌套,调用了3个函数str2rstr_utf8(s)、rstr()、rb()来处理输入的字符串
先看str2rstr_utf8(s)函数:

这个函数只是将我们输入的字符串转换成utf-8编码格式
直接在控制台输入str2rstr_utf8(s)函数的代码之后
str2rstr_utf8(“123”);调用函数对字符"123"处理之后输入的结果是"123"

也可以直接在chrome浏览器里面新增js代码来调用原有的str2rstr_utf8(s)函数
在chrome浏览器的Sources->Snippets中

选择New snippet就能新建一个js文件
输入str2rstr_utf8(“abcd”);调用str2rstr_utf8(s)函数

之后点击Ctrl+Enter就能运行js代码:

之后就是rstr()函数:

依次调用了rstr2binl(s)、binl()、binl2rstr()函数
同样调用三个函数查看输出:

发现他们对输入字符串做了复杂的处理,
查看rstr2binl(s)函数源代码:

function rstr2binl(input) {
    var output = Array(input.length >> 2);
    for (var i = 0; i < output.length; i++)
        output[i] = 0;
    for (var i = 0; i < input.length * 8; i += 8)
        output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32);
    return output;
}

从代码我们可以看到根据输入的字符串,决定了输出的字符串,所以现在我们无法直接逆向这部分的代码。
接下来只能从ic变量去找突破口了,因为当我们输入的字符串是正确的字符串的时候,ic变量的值会被赋为true

可以看到ic变量的初始值被设为了false,但最后输出正确的flag的时候,要求它的值是true,所以我们去看ic变量的值在哪被更改了:

只有在ck(s)函数中有4次更改,也就是要输出正确的flag,ic的值就要在这被修改成true。
实际上ck(s)函数是被binl(x, len)调用的:

也就是上面的计算flag的值的过程中,调用了ck(s)函数去验证输入的字符串s,如果符合要求,就把ic的值设为true,然后在输出计算得到的flag。
我们接着分析ck(s)函数:

function ck(s) {
    try {
        ic
    } catch (e) {
        return;
    }
    var a = [118, 104, 102, 120, 117, 108, 119, 124, 48,123,101,120];
    if (s.length == a.length) {
        for (i = 0; i < s.length; i++) {
            if (a[i] - s.charCodeAt(i) != 3)
                return ic = false;
        }
        return ic = true;
    }
    return ic = false;
}

就是把输入的字符串的字符的ASCII码和a[]数组中的数逐个比较,一旦出现不是相差3的字符就返回
return ic = false;
所有的字符和数字都相差3时就返回
return ic = true;
我们根据代码逻辑,写出逆向求输入字符串的代码:

var a = [118, 104, 102, 120, 117, 108, 119, 124, 48,123,101,120];
var s="";
for (i = 0; i < a.length; i++) {
	s += String.fromCharCode(a[i] - 3);
}

console.log(“结果是:%s”,s);
运行结果:

得到输入的字符串就是security-xbu
将字符串输入到Token输入框中

得到flag:RenIbyd8Fgg5hawvQm7TDQ

以上是关于XCTF-攻防世界CTF平台-Crypto类——4flag_in_your_hand1的主要内容,如果未能解决你的问题,请参考以下文章

XCTF-攻防世界CTF平台-Web类——14supersqli

XCTF-攻防世界CTF平台-Reverse逆向类——31hackme

XCTF-攻防世界CTF平台-Web类——6warmup

XCTF-攻防世界CTF平台-Web类——7NewsCenter

XCTF-攻防世界CTF平台-Reverse逆向类——53easyCpp

XCTF-攻防世界CTF平台-Web类——11upload1