defcon 29就这一道Web题目,说实话也没学到啥东西,唯一学到的就是勿钻牛角尖,及时调整策略。
此题严格来说算一道逆向题,只不过逆向的目标是混淆过JavaScript,我方法就是硬逆,等过几天看看其他人writeup,也许会有更简单的方法。先不讨论这些方法了,仅说下我自己的流水账。
PS. 本文没有做过题目的同学也可以看看。
0x01 确定考点
拿到题目:
This is the end of phishing. The Order of the Overflow is introducing the ultimate authentication factor, the most important one, the final one. To help the web transition to this new era of security, we are introducing a 3FA tool for testing your webpages completely isolated on our admin's browser.
http://threefactooorx.challenges.ooo:4017
Files:
3factooorx.crx b40cabadcdbf1d0a8868121d184fcb9d5355c688045dc5a2e91fe870e846ff1d
首先看一下给出的URL,里面就是一个上传HTML的页面,上传一个HTML后,有个Bot会访问这个页面,并把截图发回来。再就是,给了一个crx格式的附件,说明这道题和浏览器插件有关。
下载这个crx,解压后,查看最重要的menifest.json,这是浏览器插件的配置文件:
{
"manifest_version": 2,
"name": "3FACTOOORX",
"description": "description",
"version": "0.0.1",
"icons": {
"64": "icons/icon.png"
},
"background": {
"scripts": [
"background_script.js"
]
},
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"run_at": "document_start",
"js": [
"content_script.js"
]
}
],
"page_action": {
"default_icon": {
"64": "icons/icon.png"
},
"default_popup": "pageAction/index.html",
"default_title": "3FACTOOORX"
}
}
两个重要的文件:
background_script.js 这个脚本会运行在插件后台
content_script.js 这个脚本会插入到用户访问的每一个页面中并执行
其中,background_script.js比较简单:
// Put all the javascript code here, that you want to execute in background.
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.getflag == "true")
sendResponse({flag: "OOO{}"});
}
);
增加了一个事件监听器,在收到消息后,如果request.getflag
为true
,则调用回调函数sendResponse
,把flag传进去。大概这样的逻辑,所以猜测content_script.js中应该会有发送消息的函数,然后我需要想办法调用到,这样拿flag。
那么,看下content_script.js……是一个混淆过的JavaScript。基本可以确定这道题的考点就是反混淆了。
0x02 一些失败的尝试
defcon第一天去公司和其他同学一块做,但是一整天都没有Web题,做Misc没啥头绪,Pwn直接不会做,于是打了一天酱油,第二天就没去公司。结果第二天下午在家吃完饭上去看到别人说出来一道Web题目,我就自己在家做了。
自己一个人做题最大的问题就是容易钻牛角尖,我拿到大段混淆的代码想的第一件事不是调试,而是优化一下(其实作用不大)。
代码里面有很多类似0x2186+-0x1*-0x1523+-0x36a9
这样的纯数字表达式,另外还有一些'return\x20/\x22\x20'+'+\x20this\x20+\x20\x22'+'/'
这样的字符串表达式,其实都是可以优化成一个简单表达式的。
美化的思路其实比较简单,就是对代码的AST树进行遍历,遇到BinaryExpression
节点就执行这个表达式,然后用结果生成一个新的Literal
节点替换掉原来的BinaryExpression
节点,最后生成新的代码。
以前给X-Ray做XSS扫描器用的比较多的AST Parser是Esprima,但是esprima中缺少几个东西:
esprima自带的walker(
parseScript
第三个参数),不支持替换节点替换后的新AST树,无法还原为代码
所以,还需要我自己解决一下这两个问题。第一个问题,可以编写一个遍历AST树的函数,这里直接用递归做就行了。调用回调后,如果有返回值,则将这个返回值替换掉原本的节点,并停止继续递归;如果没有返回值,则继续递归,代码如下:
function walk(ast, fn) {
for (let i in ast) {
&nbs