Web_XCTF_WriteUp | simple_js
题目
提示:
小宁发现了一个网页,但却一直输不对密码。(Flag格式为 Cyberpeace{xxxxxxxxx} )
题目:
分析
F12 打开查看器找到一串 JS 代码:
分析一下大致意思:
function dechiffre(pass_enc){ var pass = "70,65,85,88,32,80,65,83,83,87,79,82,68,32,72,65,72,65"; // 变量pass赋值 var tab = pass_enc.split(','); // 变量tab接受pass_enc参数按“,”拆分返回的新数组 // 变量tab2接受pass参数按“,”返回的新数组 // 定义变量 i、j、k、l(初始化为0)、m、n、o、p(初始化为空字符串 // i初始化为0 // j初始化为tab中拆分数组的个数(即pass_enc被拆分的个数) var tab2 = pass.split(',');var i,j,k,l=0,m,n,o,p = "";i = 0;j = tab.length; k = j + (l) + (n=0); // n赋值为0,计算j+l+n的值赋给k n = tab2.length; // n赋值为tab2中拆分数组的个数(即pass被拆分的个数) // 变量o赋值为0,变量j接收变量n的赋值,变量k接收变量j的赋值。循环n次 // tab第i-l个元素赋给o // tab2第i个元素赋值给o,p尾部拼接o创建的字符串 for(i = (o=0); i < (k = j = n); i++ ){o = tab[i-l];p += String.fromCharCode((o = tab2[i])); // 当i等于5时跳出循环 if(i == 5)break;} // 变量o赋值为0,变量j接收变量n的赋值,变量k接收变量j的赋值。循环n次 for(i = (o=0); i < (k = j = n); i++ ){ // tab第i-l个元素赋给o o = tab[i-l]; // 如果i大于5且小于k-1 if(i > 5 && i < k-1) // tab2第i个元素赋值给o,p尾部拼接o创建的字符串 p += String.fromCharCode((o = tab2[i])); } p += String.fromCharCode(tab2[17]); // p尾部拼接tab2第17个元素 pass = p;return pass; // p赋值给pass。返回pass } // 调用dechiffre,将返回值转为字符 String["fromCharCode"](dechiffre("\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30")); h = window.prompt('Enter password'); // 打开显示提示文本为“Enter password”的提示窗口 alert( dechiffre(h) ); // h作为参数调用函数dechiffre,弹窗显示
这个排版真是…(吸气)
整体看下来,dechiffre 函数里有两个字符串,分别是输入的 pass_enc 和原有的 pass。运行过程中,pass_enc 和 pass 按 “,” 被拆分,分别放在 tab 和 tab2 两个变量中。
在两个 for 循环中,变量 p 不断拼接 o 的字符串形式,并最终作为返回值传递。
变量 o 在被赋值为 tab 的第 i-l 个元素后没有进行任何操作,很快被赋值为 tab2 的第 i 个元素。
也就是说,我们输入的 pass_enc 值其实并没有参与运行,即输入的 Enter password 对输出结果不造成影响,而浏览器实际输出的是将 70,65,85,88,32,80,65,83,83,87,79,82,68,32,72,65,72,65
转化为字符串的结果。
同时,String["fromCharCode"](dechiffre("\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30"));
似乎只是调用了 dechiffre 函数,结果并没有作为输出显示,很奇怪。
综上,我们需要将 tab2 和 tab 的地位进行替换,即将代码第 3 行的 tab 改为 tab2,第 8 行的 tab2 改为 tab,第 10 行的循环次数 n 的由 tab2.length 改为 tab.length。
但更改后的代码依旧需要在弹窗中输入密码,我们手头仅有的可能就是调用了 dechiffre 但没有输出的那串字符。尝试将这串字符作为输入直接填入代码。
一番摸索后,我们找到了将更改后的代码运行在浏览器上的方式,更改后的代码内容如下:
<html><body><script> function dechiffre(pass_enc){ var pass = "70,65,85,88,32,80,65,83,83,87,79,82,68,32,72,65,72,65"; var tab2 = pass_enc.split(','); var tab = pass.split(',');var i,j,k,l=0,m,n,o,p = "";i = 0;j = tab.length; k = j + (l) + (n=0); n = tab.length; for(i = (o=0); i < (k = j = n); i++ ){o = tab[i-l];p += String.fromCharCode((o = tab2[i])); if(i == 5)break;} for(i = (o=0); i < (k = j = n); i++ ){ o = tab[i-l]; if(i > 5 && i < k-1) p += String.fromCharCode((o = tab2[i])); } p += String.fromCharCode(tab2[17]); pass = p;return pass; } h = window.prompt('Enter password'); alert(dechiffre("\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30") ); </script></body></html>
将代码保存为 html 文件,用浏览器打开,点击确定后得到一串十位字符:
看字符串内容不像某种类型的编码,尝试作为 flag 提交,确定为 flag 内容。
Flag
Cyberpeace{786OsErtk12}
参考
JavaScript 教程-菜鸟教程
js中的连续赋值-瓶盖的盖-CSDN博客
JavaScript中字符串连接/拼接的四种方式-Colbyzn-CSDN
JavaScript String 对象-菜鸟教程
HTML(.htm或.html)文件怎么打开?-柚子-知乎.html
html基本格式-yzyggu-CSDN博客
HTML<script>标签-菜鸟教程
本文作者:Guanz
本文链接:https://www.cnblogs.com/Guanz/p/17857826.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步