【记录】猿人学js逆向第2题补环境

2024-01-28 02:40

本文主要是介绍【记录】猿人学js逆向第2题补环境,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目网址:https://match.yuanrenxue.com/match/2

本文比较新手向,大佬可能会觉得看着比较墨迹,如果有错误的地方欢迎指出。

全文手把手扣代码补环境,几乎包含了绝大部分可能会踩的坑。

土豪通道:

https://download.csdn.net/download/weixin_45608294/85427606?spm=1001.2014.3001.5503icon-default.png?t=M4ADhttps://download.csdn.net/download/weixin_45608294/85427606?spm=1001.2014.3001.5503不过建议还是自己动手扣一下,下面是正文


这道题的题目要求是获取前五页的热度值并求得累加和,首先抓包看一下数据请求方式

可以看到请求数据的就只有一个get请求,本题的题目就是动态cookie,从实际请求中也可以看出m就是那个加密的参数,所以完成这道题的关键就是如何获取m。

 清除缓存重新加载界面遇到了无限debugger,直接鼠标右键停用断点过掉。刷新页面

 

可以看到两个一样的请求,但是一个没有cookie,看不到响应,且响应头没有setcookie,另一个带有cookie m 并且正好是网页的几面内容。由此可以看出,cookie m的值是第一次请求后由js生成出来的。

使用postman尝试发送第一个get请求

可以看到是将js代码以script标签的形势放入了html文档中,进一步验证了cookie是由js生成的猜想。知道了大概位置,就可以开始找具体代码了。

在源代码选项卡中找到事件监听断点, 勾选脚本,这样在遇到js时会自动断下,清除浏览器中保存的cookie,刷新界面

成功将页面断下,不过可以看到此处的代码与postman收到的不一样,点击继续运行

成功来到postman验证的代码,格式化以后尝试寻找cookie生成位置, 发现代码混淆严重,只能动态调试。

现在在控制台输入hook cookie的代码(这里我是在控制台手工hook,有条件的话也可以用油猴脚本等浏览器插件或者fiddler插件之类的进行hook),

(function () {Object.defineProperty(document, 'cookie', {set: function (val) {debugger;return val;},});
})();

hook好以后 让网页继续运行,成功断在cookie生成位置

此时的m已经生成出来了,不过可以通过调用堆栈找到生成的位置。

将代码格式化以后可以看到,cookie的生成位置在4922行这一超长的代码中

document[$dbsm_0x42c3(qqLQOq, iOiqII) + $dbsm_0x42c3(q1IoqQ, QQlLlq)] = _0x5500bb['\x4e\x74\x44' + '\x72\x43'](_0x5500bb[$dbsm_0x42c3(qqqQoq, oqQiiO) + '\x6d\x65'](_0x5500bb[$dbsm_0x42c3(Ioo0ql, olq0Oq) + '\x6d\x65'](_0x5500bb[$dbsm_0x42c3(qOIqQi, OOqIQi) + '\x72\x44'](_0x5500bb[$dbsm_0x42c3(Q1qoqQ, lILOOq) + '\x72\x44'](_0x5500bb[$dbsm_0x42c3(qOO1Q0, oiqlQQ) + '\x72\x44'](Ql1OO0, _0x5500bb['\x7a\x76\x67' + '\x6c\x77'](_0x3c9ca8)), Qoqq0I), _0x5500bb[$dbsm_0x42c3(iqOiQ0, QOiq0Q) + '\x47\x6b'](_0x313b78, _0x160e3a)), lOo0QQ), _0x160e3a), _0x5500bb[$dbsm_0x42c3(qiOOiO, liQIoQ) + '\x4e\x5a']),

将等号右边的一大长串代码放到控制台中查看,可以确定一大长串代码就是m的生成位置 。

仔细看看这一大对代码的结构,可以看出虽然很长,但是也是由一部分一部分拼接出来的。

将代码拆解一下得到如下结果

_0x5500bb['\x4e\x74\x44' + '\x72\x43'](_0x5500bb[$dbsm_0x42c3(qqqQoq, oqQiiO) + '\x6d\x65']
(_0x5500bb[$dbsm_0x42c3(Ioo0ql, olq0Oq) + '\x6d\x65']
(_0x5500bb[$dbsm_0x42c3(qOIqQi, OOqIQi) + '\x72\x44']
(_0x5500bb[$dbsm_0x42c3(Q1qoqQ, lILOOq) + '\x72\x44']
(_0x5500bb[$dbsm_0x42c3(qOO1Q0, oiqlQQ) + '\x72\x44']
(Ql1OO0, _0x5500bb['\x7a\x76\x67' + '\x6c\x77'](_0x3c9ca8)), Qoqq0I),_0x5500bb[$dbsm_0x42c3(iqOiQ0, QOiq0Q) + '\x47\x6b'](_0x313b78, _0x160e3a)), lOo0QQ), _0x160e3a), 
_0x5500bb[$dbsm_0x42c3(qiOOiO, liQIoQ) + '\x4e\x5a'])

可以看到,出现最多的东西,就是_0x5500bb

 通过控制台验证可以看到,这个_0x5500bb里面包含了很多字符串和函数,也就是说上面的代码都是在调用它里面的函数。

那么只需要验证里面的东西都是什么,就可以找到m的生成位置了。

利用控制台将内容简单还原方便后续观察,得到如下结果

_0x5500bb['NtDrC'](_0x5500bb['KGBme']
=(_0x5500bb['KGBme']
(_0x5500bb['mQKrD']
(_0x5500bb['mQKrD']
(_0x5500bb['mQKrD']
(Ql1OO0, _0x5500bb['zvglw'](_0x3c9ca8)), Qoqq0I),_0x5500bb['wWbGk'](_0x313b78, _0x160e3a)), lOo0QQ), _0x160e3a), 
_0x5500bb['TfZNZ'])

可以看出,这是一个函数套函数的大套娃,接下来进行逐一验证

可以看出,最后一个调用的函数结果是cookie中最后的部分,而_0x160e3a则是一个时间戳(_0x313b78, _0x160e3a)的结果仍然是一个时间戳,而_0x5500bb['wWbGk'](_0x313b78, _0x160e3a)的值就是cookie的前半部分。还记得之前找到的cookie是什么样的嘛?

 综上所述,我们可以得出

Cookie = _0x5500bb['wWbGk'](_0x313b78,_0x160e3a)+lOo0QQ+_0x160e3a

再通过控制台看一下这个wWbGk是个什么东西

原来是一个函数,里面有两个参数,就是用第一个参数调用第二个参数 。进一步简化上面的等式

Cookie = _0x313b78(_0x160e3a)+"|"+_0x160e3a
// _0x160e3a为时间戳
//此时值为: 1653183600000

找到了生成逻辑以后,就可以开始补环境大法了。

我这里使用装了NodeJs插件的Pycharm进行调试,当然,都是根据个人喜好自由选择。

 这里提示了_0x313b78没有找到,我们去控制台看看它是怎么定义的

可以看到这是一个函数,在源代码中搜索找到它的位置,将其完完整整的抠出来,再次调试js。

 又提示_0x5500bb没有定义,接下来只需要不停的重复上面的步骤,什么没有定义,就去源代码里面找到它并将其扣下来。

这里还有一个需要注意的小技巧,就是你将扣下来的代码放到自己的js文件中时,要注意它提示not defined的行是哪一行,找到它然后放在那一行所在的函数的前面即可。一味的放到文件开头有时候可能也会出错。

 这里可以看到_0x5500bb是一个大列表,而它的实质则是上面的_0x443ddb,所以这里要赋值的这一行,到上面的整个_0x443ddb都给扣下来。

补完以后又开始提示未定义了,通过控制台确定是什么东西以后继续补。

这里碰到个乱码没有定义,去控制台看是什么发现报错了。但是不要慌,在源码里面先搜一下看看

可以看到这个东西是在一个自执行函数里面定义的,为了防止多余的变量污染,秉持着缺啥补啥的原则,这里我只把这一大串乱码扣下来补了上去,而不是整个函数都扣。在扣的时候还发现这串定义的乱码正好接在了前面补的代码头上,抠出来的代码也随着原来的样子拼了上去。(这个和前面提到的将抠出来的代码放到报错行前面并不冲突)

再次运行调试

 出现了新的未定义,继续开始扣扣补补。

在补完一个大数组以后,猛的发现NodeJs报错了,运行不了?遇到这个问题的时候,把整个代码拿出来放到真实的浏览器去debug一下先。

 新开一个 标签页打开开发人员工具,避免前面补环境用的标签页出现意外。

在源代码选项卡中找到代码段(找不到的话可以点那个向右的>>然后再进代码段),新建一个代码段将刚才抠出来的所有代码复制进去。

为了方便调试,咱们在所有代码的最前面,也就是第一行加上一个debugger,来手动执行代码。

 在代码段上右键运行代码,成功进入debug状态,然后点击按钮一个函数一个函数的来执行。

还没点几下,在执行到乱码这里时突然整个标签页都卡死了,开发者工具也无法操作,基本上可以确定问题就是出现在这里了。

刷新刚才新建的标签页重新来到开发者工具。将第一行的debugger删除掉在乱码前面重新加上。 重新运行代码段,在进入debug状态后,点击进入函数调用进一步查看出错的地方。

 点着点着你就会发现当执行到这里的时候,进入了死循环,怎么也出不去。这里就是NodeJs执行报错的原因了。

向上翻看一下源码可以看到,只要来到了这个函数就会必然进入这个死循环,所以我们必须想办法将其绕过。

从代码和和调用堆栈中都可以看出,在WjJIeN函数中有一个if语句,如果!Boolean(~_0x4859ef)为真的话就会返回一个_0x4859ef为假的话则会调用这个死循环函数。

所以我们需要让这个布尔值变成是真,但是这个布尔值是通过判断参数来决定的。通过调用关系可以看出这个参数是由上一个函数提供的。

分析到这里就已经很明显了,是否进入这个死循环就是由vnuqco函数中的_0x3fba94决定的。而它则是由下面这个三元表达式决定的

_0x2940ac['test'](this['XxpyjG']['toString']()) ? --this['yHmSUE'][0x1] : --this['yHmSUE'][0x0];

 使用控制台验证判断的表达式

可以看到,是调用_0x2940ac的test方法。如果你仔细看前面的代码,就会发现这个_0x2940ac其实是定义的一个正则表达式,而被检测的内容,也恰好就是上面的函数定义。

正则表达式的内容如下:

/\w+ *\(\) *{\w+ *['|"].+['|"];? *}/

就是用这个正则表达式去匹配上面定义的XxpyjG的函数代码。匹配成功则返回true否则返回false。

其实如果毕竟懂正则表达式的话,应该可以看出这个表达式就是验证代码是否被格式化过。我这里在控制台验证一下

调试的时候默认情况下是false的,但是把格式化代码生成的空格和换行符删掉后再次匹配就变成了true。

修改好函数定义以后,清除掉所有的debugger和断点。重新尝试运行脚本,一定要主要这里的函数定义必须把所有的换行和多余的空格(return后面那一个不算)全部清理干净,可以参考我的图片。

 系统提示有东西未定义,而不是直接卡死,说明刚才那个格式化检测已经过掉了。

此时将Pycharm中的js文件对应修改好后,进行调试

也是提示未定义,没有问题。继续重复之前的步骤,准备扣代码补环境。

但是此时你再仔细观察一下,会发现报错的这行代码的上面不是有一个已经定义的_0x313b78吗?怎么会提示还提示没有定义呢。其实在这里是因为前面补的一大长串代码的最后面是一个逗号,我们将其改成语句结束的分号再调试一下。

成功通过,但是又报了一个新的无定义。但是这个报错的内容怎么好像找不到?其实是因为上面的字符串被转码后导致的,你可以根据报错的行号和错误提示上面的原代码来找到具体的内容。

找到以后在控制台查看这是个什么东西

可以看到这是调用的_0x5500bb里面的KNqZI函数。

利用之前过格式化检测的方法,将代码放到浏览器中进行调试

 可以看到函数显示未定义,而且里面调用的函数也和原版中的不一样。

 通过比较可以看出,所有的参数都是没问题一致的,所以问题只能出在$dbsm_0x42c3上面

这里可以看到这个函数虽然是已经补过的,但是上面的自执行函数的参数却是这个函数。

其实这里是一个比较常见的混淆套路,一个大数组保存16进制的函数名,然后有一个在代码里出现频率极高的解密函数(此处就是$dbsm_0x42c3),除了解密函数以外,还有一个用于将16进制字符串还原的移位函数(也就是上面那个参数是解密函数的自执行函数)。

在上次补解密函数的时候,没有补上这个移位函数,所以解密函数解密出来的内容出了错(乱码),自然也就找不到正确的函数,也就会报函数未定义了。

解决办法很简单,只要把移位函数补上去即可。

成功通过,然后继续开始扣代码补环境。

在补移位函数的时候需要注意下里面还存在格式化检测,有兴趣了解具体原因的可以参考上次过格式化检测的方法来搞定。如果懒得调试可以直接将移位函数压缩,然后再补上即可。

补完移位函数后会有非常多的函数要一个一个补,一定要有耐心,自行参考前面补环境的方法,此处不再详解。

当补到_0x1316f4的时候你可能会发现调试js文件时,node会一直执行,其实这里是因为你扣代码的时候把最后的自执行括号给加上去了,实质上这里应该是一个函数

在补环境的时候要注意与原版的要保持一致,不清楚时可在debugger的控制台中查看。

补环境的途中你可能会碰到如下报错:

 提示这个是因为要用到浏览器的属性,而我们用NodeJs没有这个环境导致的,只需要在文件开头补上即可,环境代码如下:

window = global;
window.navigator = {};

补到最后,你会发现,程序直接运行结束了

这说明环境已经补的差不多了。在底下console.log一下看看

又报了一个未定义,但是这个报错的确实console.log,看来是上面的环境代码为了防止调试把console.log给改掉了。我们在文件的最开头把console.log保存一下然后再调用咱们自己保存的来调试。

成功打印出m的值。

至此,整个补环境已经完成,接下来只需要调用这个js就可以获取到m的值

 

这篇关于【记录】猿人学js逆向第2题补环境的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/652226

相关文章

Node.js net模块的使用示例

《Node.jsnet模块的使用示例》本文主要介绍了Node.jsnet模块的使用示例,net模块支持TCP通信,处理TCP连接和数据传输,具有一定的参考价值,感兴趣的可以了解一下... 目录简介引入 net 模块核心概念TCP (传输控制协议)Socket服务器TCP 服务器创建基本服务器服务器配置选项服

mac安装nvm(node.js)多版本管理实践步骤

《mac安装nvm(node.js)多版本管理实践步骤》:本文主要介绍mac安装nvm(node.js)多版本管理的相关资料,NVM是一个用于管理多个Node.js版本的命令行工具,它允许开发者在... 目录NVM功能简介MAC安装实践一、下载nvm二、安装nvm三、安装node.js总结NVM功能简介N

前端原生js实现拖拽排课效果实例

《前端原生js实现拖拽排课效果实例》:本文主要介绍如何实现一个简单的课程表拖拽功能,通过HTML、CSS和JavaScript的配合,我们实现了课程项的拖拽、放置和显示功能,文中通过实例代码介绍的... 目录1. 效果展示2. 效果分析2.1 关键点2.2 实现方法3. 代码实现3.1 html部分3.2

关于Spring @Bean 相同加载顺序不同结果不同的问题记录

《关于Spring@Bean相同加载顺序不同结果不同的问题记录》本文主要探讨了在Spring5.1.3.RELEASE版本下,当有两个全注解类定义相同类型的Bean时,由于加载顺序不同,最终生成的... 目录问题说明测试输出1测试输出2@Bean注解的BeanDefiChina编程nition加入时机总结问题说明

JS 实现复制到剪贴板的几种方式小结

《JS实现复制到剪贴板的几种方式小结》本文主要介绍了JS实现复制到剪贴板的几种方式小结,包括ClipboardAPI和document.execCommand这两种方法,具有一定的参考价值,感兴趣的... 目录一、Clipboard API相关属性方法二、document.execCommand优点:缺点:

在Mysql环境下对数据进行增删改查的操作方法

《在Mysql环境下对数据进行增删改查的操作方法》本文介绍了在MySQL环境下对数据进行增删改查的基本操作,包括插入数据、修改数据、删除数据、数据查询(基本查询、连接查询、聚合函数查询、子查询)等,并... 目录一、插入数据:二、修改数据:三、删除数据:1、delete from 表名;2、truncate

VScode连接远程Linux服务器环境配置图文教程

《VScode连接远程Linux服务器环境配置图文教程》:本文主要介绍如何安装和配置VSCode,包括安装步骤、环境配置(如汉化包、远程SSH连接)、语言包安装(如C/C++插件)等,文中给出了详... 目录一、安装vscode二、环境配置1.中文汉化包2.安装remote-ssh,用于远程连接2.1安装2

将sqlserver数据迁移到mysql的详细步骤记录

《将sqlserver数据迁移到mysql的详细步骤记录》:本文主要介绍将SQLServer数据迁移到MySQL的步骤,包括导出数据、转换数据格式和导入数据,通过示例和工具说明,帮助大家顺利完成... 目录前言一、导出SQL Server 数据二、转换数据格式为mysql兼容格式三、导入数据到MySQL数据

关于rpc长连接与短连接的思考记录

《关于rpc长连接与短连接的思考记录》文章总结了RPC项目中长连接和短连接的处理方式,包括RPC和HTTP的长连接与短连接的区别、TCP的保活机制、客户端与服务器的连接模式及其利弊分析,文章强调了在实... 目录rpc项目中的长连接与短连接的思考什么是rpc项目中的长连接和短连接与tcp和http的长连接短

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI