记一次酣畅淋漓的js逆向

摘要

本文记录了对一个混淆后的js脚本的逆向过程,并介绍了过程中遇到的两种js混淆策略与应对方式;与此同时,本文还记录了对于禁止F12调试的站点的破解方法;最后,本文对js逆向与这过程中的AI工具使用情况进行了一些感受分享与讨论。

背景介绍

今天在写爬虫的练习题时遇到了这样一个难题:目标资源是一个图片的url,但是不同于以往的情况,我在http响应记录里搜索这个图片的url,发现并不能搜到。从逻辑上来讲,这个url被展示到浏览器上了,那么只可能是之前的请求中带有和这个url相关的信息,如果这个信息不是直接给出的url,那么只可能是编码或者加密过的url。

顺着这个思路,我继续翻响应记录,果然,在一个html的script标签内发现了一个对象,里面就包含使用base64编码的url。但是尝试解密后发现解密出来是乱码,并且对象里还有个名为key的字符串,如下所示

/* by yours.tools - online tools website : yours.tools/zh/keyboardtest.html */
{        
  "url": "HZM84hjXwDewS4cjMZ4w/bSUfXugYnglcxAKE2sCrsAf4J6oQ......",
  "key": "110f8cf1f11e48c13dab209976c1821d"
}

那么很显然,这里是进行了加密的。再考虑到base64解码后的数据长度为64,且key也是32个字符,所以可以很合理的怀疑这里使用了aes加密,但是不知道具体的填充方式和iv,在尝试了一些组合之后还是无果,于是只能从解密的js代码入手。

一路追踪这个对象的使用情况,最后定位到了一个名为crypto.js的脚本,其中有一个名为decrypt的函数,可以确认url就是在这里完成解密的,但是线上的js脚本一般都是经过了混淆的,这次的也不例外,经过加密的js完全就是天书,根本不可读。于是便有了本文的重头戏:对经过混淆的js的还原。考虑到还原js是个很无聊的工作,所以这里就不提及具体的细节了,只记录一下大致的方法,以及这次遇到的混淆手段。

js逆向

尝试偷懒:fail

这次是我第一次接触混淆后的js逆向,所以我先在网上查了一下,看看有没有可以自动解混淆的方法,不过我也清楚这些工具也只能够帮部分的忙,毕竟混淆时已经把变量名等信息都丢掉了,要把这些还原出来是不可能的。在搜索结果中我找到了 https://deobfuscate.io/ 这个网站,把js丢进去之后,输出了一份看起来整洁了许多的代码,但是decrypt部分仍然是天书,但是至少也聊胜于无了。

峰回路转:字符串解密函数的破解

字符串解密函数的破解是整个逆向过程的核心。这里首先说明一下js逆向的难点在哪:js逆向的难度来自于js语言自身,js是使用解释型语言,这一特性使得js可以在运行时对一个对象做很多调整,例如动态的添加和删除对象的属性,动态的访问一个对象的属性和方法等。

一个在js混淆里经常用的的trick就是把函数调用变成获取函数的方法+调用方法的方式,即如下所示:

/* by yours.tools - online tools website : yours.tools/zh/keyboardtest.html */
CryptoJS.AES.enc(data, key)

// 上述代码等价于
CryptoJS["AES"]["enc"](data, key)

其中AES和enc两个字符串是可以通过其他函数来获得。所以,在混淆后的js代码里,我们经常会见到这种写法

_0x3c22fb = CryptoJS_0x154728[_0x4328d(0x216, ']2%*'](0x10))

对于java和binary,虽然看不懂函数名,但是至少可以整理出明确的调用链;而反观js,如果不能破解0x4328d这个字符串解密函数,我们甚至都无法指出这是在调用哪个函数。

要通过静态分析摸清楚字符串解密函数的算法是很麻烦的,这里我们可以取个巧,把js放到本地运行起来,然后在某个位置调用0x4328d这个字符串解密函数,例如,如果我们想要知道_0x4328d(0x226, 'xbaC')代表什么,我们只需要执行一次这个函数即可。

这里可能会有小伙伴有疑问:为什么不直接执行到decrypt呢?这样就可以直接打断点读出具体的值了。这里不这么做的原因是:本地运行时发现,js脚本执行中会报错,无法执行到decrypt的位置,所以我只能在报错点之前调用字符串解密函数来完成间接的解密。

当然,也可以直接在线上的站点调试js,但是站点本身还做了防调试的处理,这个的破解方法我会在文末介绍一下。

攻坚夺旗:完成js逆向目标

在能够理清楚每一行代码是在调用什么之后,就可以开始正是破解decrypt函数了。具体的破解过程并没有什么值得说的地方,就只是使用字符串解密函数不停的解密字符串而已。

这其中遇到了js加密的另一个比较常见的trick:即使用一个对象来继续混淆函数调用,例子如下所示:

const _0xacf5f1 = {
        'Y2aK': _0x4328d(0x213, 'oXQv'),
        'JaxMs': function (_0xaabd93, _0x57327b) {
            return _0xaabd93 == _0x57327b;
        },
        'e33Ahs': function (_0x26743c, _0x1d7c34) {
            return _0x26743c === _0x1d7c34;
        },
        'woszh': 'JaxMs',
        'vYmge': _0x4328d(0x15f, 'by3O')
    };

这个对象里面封装了2个字符串和2个函数,这两个函数都只是起到判断相等的作用。在需要混淆判断相等的操作时,可以把等号换成在这个对象里面取某个元素并进行调用,之后再用字符串加密的方式把key混淆掉,就能进一步加大破解难度。

最终在完成了破解之后,发现脚本使用的是cbc模式,pkcs7填充。特别的,密钥是之前的key取sha256之后的结果,也难怪之前一直都没尝试出来。有了这些信息之后,我让AI基于这个算法用python写了一个解密脚本,经测试,脚本能够成果解密url。

至此,这个js逆向任务完成。

基于在线调试的方法

这次的目标站点使用了禁止调试的技术,具体表现是,页面加载完成后按F12没有反应,如果在页面加载前就按F12唤起了调试菜单,那么调试会断在一个代码为debugger的地方,并且页面上会显示Paused in debugger。

禁止调试的破解方法我参考了这篇文章 https://blog.youkuaiyun.com/shisanxiang_/article/details/143328204 ,只需要添加日志点,并将其设为false就能够破解。
image
image

在完成禁止调试的破解之后,只需要在左侧Page里找到crypto.js,然后打断点,就能够摸清楚decrypt的执行情况了。这一点是我在事后才摸索出来的,如果一开始就用这个方法的话,应该是能够节省不少时间的。
image

一些主观感受

关于js逆向

虽然这篇文章里提到的点并不多,但是这个逆向破解确实是实打实的卡了我三个多小时。之前我也做过一些java和纯binary的逆向,从这次经历来看,js逆向是稍微简单一些的。

这么说主要是因为:js虽然经过了混淆,但是还是保留了完整的函数结构,使得我们能够很方便的在运行时调用某个函数。例如,能够在js运行时打断点,然后调用字符串解密函数直接获取解密后的结果。这一点是纯binary和java都比较难实现的(真要实现肯定也能行,就是会复杂很多)。

从整个流程的感觉上来看,字符串解密函数的破解就像是横亘在我和目标之间的唯一一座大山:在想办法破解了字符串解密函数之后,一切都豁然开朗了,剩下的部分就只需要按图索骥慢慢摸索,最终就能还原出这个函数出来。

AI工具使用感受

AI是个非常好用的搜索引擎和助手,尤其是在今天这种需要快速编写原型代码来验证猜想的场景。例如,我对CryptoJS这个库并不是很熟悉,如果按照传统的方法,我需要查官方文档,这会耗费大量的时间;但是在使用AI之后,我可以直接让AI生成与之等价的python代码,并在我熟悉的环境里完成对这个想法的验证。

同时,对于某些我不是很确定的语法,例如substring只传一个参数代表什么,也可以直接通过AI获取答案,这会比传统的搜索引擎要快上很多。

最最重要的是,这种方法并不会打断我们工作时的思路。在过去,如果我对某个库的用法不了解,只能去查文档,这会打断我原有的思路;但在使用AI之后,我可以像随口问小助手一样,把问题描述清楚之后就能直接得到回答,而不需要打断思路去学习其他东西。

可以想象这会是一个怎样灾难的画面:在逆向这种本身就很消耗精力和耐心的场景,如果要验证一个猜想还得去从头开始学CryptoJS这个库的用法,以及python里AES加解密库的用法。可以说,这一次我是真真切切地感受到了AI带来的工作效率提升。

考虑柔性负荷的综合能源系统低碳经济优化调度【考虑碳交易机制】(Matlab代码实现)内容概要:本文围绕“考虑柔性负荷的综合能源系统低碳经济优化调度”展开,重点研究在碳交易机制下如何实现综合能源系统的低碳化与经济性协同优化。通过构建包含风电、光伏、储能、柔性负荷等多种能源形式的系统模型,结合碳交易成本与能源调度成本,提出优化调度策略,以降低碳排放并提升系统运行经济性。文中采用Matlab进行仿真代码实现,验证了所提模型在平衡能源供需、平抑可再生能源波动、引导柔性负荷参与调度等方面的有效性,为低碳能源系统的设计与运行提供了技术支撑。; 适合人群:具备一定电力系统、能源系统背景,熟悉Matlab编程,从事能源优化、低碳调度、综合能源系统等相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①研究碳交易机制对综合能源系统调度决策的影响;②实现柔性负荷在削峰填谷、促进可再生能源消纳中的作用;③掌握基于Matlab的能源系统建模与优化求解方法;④为实际综合能源项目提供低碳经济调度方案参考。; 阅读建议:建议读者结合Matlab代码深入理解模型构建与求解过程,重点关注目标函数设计、约束条件设置及碳交易成本的量化方式,可进一步扩展至多能互补、需求响应等场景进行二次开发与仿真验证。
C++代码: 调制多夫林 题目描述 正如人们常说的,考虑事情要在醉后,而做决断需待酒醒。黛米·波本一方面渴望活得酣畅淋漓,对人生报以最大的热情与乐观,但另一方面,她不得不清醒过来,面对所追寻的希冀早已变成无力挽回的不幸这一事实。 黛米正在调制多夫林酒。 她共有 n n 个酒杯,每个酒杯容量均为 C C,目前第 i i 个酒杯的酒量为 a i a i ​ 。接下来她可以进行零次或若干次以下操作: 选择两个不同的酒杯 A 和 B,把 A 中的酒倒入 B 中,直到 A 变空或者 B 变满。 在操作过后,若一个酒杯最终酒量为 x x,那么黛米可以获得 p x p x ​ 的收益。黛米想知道她的最大收益。 输入格式 第一行两个整数 n , C n,C。 接下来一行 n n 个整数 a 1 , . . . , a n a 1 ​ ,...,a n ​ 。 接下来一行 C + 1 C+1 个整数 p 0 , . . . , p C p 0 ​ ,...,p C ​ 。 输出格式 输出一个整数表示黛米的最大收益。 样例 #1 样例输入 #1 12 15 12 3 0 13 7 13 7 14 1 7 8 0 825388380 39329271 704245737 469411876 894272239 799865388 563849970 137788523 970936429 196783269 948567904 516224087 659169362 386843765 378066614 966337758 样例输出 #1 2145332184 样例 #2 样例输入 #2 15 48 5 20 14 43 23 41 5 10 27 7 34 46 3 15 1 716901902 790775700 931767706 793466030 340583152 181480156 146379677 577589230 313714903 690875439 291000126 510953025 19533032 7601507 209536988 97715345 465963730 422599693 499903070 129835717 91160437 420348995 329600929 561846103 559637771 509776622 630409032 303233543 547994414 718330983 207865481 677096734 691825880 910730634 125099574 320847998 189852265 67917516 275551745 150668630 602909908 450932595 509368116 288712864 86953411 53380124 644285386 437830956 552388029 样例输出 #2 2147074615 提示 对于所有测试点,满足 2 ≤ n ≤ 15 2≤n≤15, 1 ≤ C ≤ 49 1≤C≤49, 0 ≤ a i ≤ C 0≤a i ​ ≤C, 0 ≤ p i ≤ 10 9 0≤p i ​ ≤10 9 。 每个测试点的具体限制见下表: 测试点编号 n n C C 1 ∼ 2 1∼2 ≤ 3 ≤3 3 3 ≤ 5 ≤5 ≤ 6 ≤6 4 4 ≤ 8 ≤8 ≤ 12 ≤12 5 ∼ 6 5∼6 ≤ 12 ≤12 ≤ 15 ≤15 7 ∼ 10 7∼10 ≤ 15 ≤15 ≤ 49 ≤49
08-03
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值