js逆向系列09-WPS

js逆向系列09-WPS

直接输入随机账号密码,查看网络请求,主要有两个数据包:

js逆向系列09-WPS

请求passkey接口,返回pass_key和ssid。


js逆向系列09-WPS

还有一个safe_verify请求,请求体中包含ssid,password,account等参数,其中ssid与第一个请求中返回的ssid一致,这里主要关注password的加密方式。

关键的请求包为XHR的形式:

js逆向系列09-WPS

首先还是下一个XHR断点:

js逆向系列09-WPS

刷新,重新登录,从栈顶依次往下看:

js逆向系列09-WPS

先看到send,可以看到e.data里已经包含了加密之后的各参数,继续往前:

js逆向系列09-WPS

同样,b.data中的数据已经是加密之后的。

直到第三个匿名函数,已经无法跟到与password相关的值,下断点:

js逆向系列09-WPS

刷新后发现,直接会在验证码加载时就断住,暂时放弃XHR跟栈,下面通过搜索password来找加密的部分。

共有9处结果:

js逆向系列09-WPS

很容易定位到common.19c277c4.js中的a.password = c.encrypt(b),行.

下断:

js逆向系列09-WPS

右侧能够看到,a中的各参数值即为请求体中的内容,而a.password=c.encrypt(b),b的值为明文密码,即123456.

代码如下:

success: function(a) {                if ("ok" == a.result) {                    var c = new JSEncrypt;                    c.setPublicKey(a.pass_key),                    a.password = c.encrypt(b),                    "undefined" != typeof $ && $("body").trigger("encryptPassword", a)                }            },

跟进encrypt:

js逆向系列09-WPS

继续下断点,步入:

js逆向系列09-WPS

选中的部分即为加密代码,这两处均在jsencrypt.js中。

直接将整个js文件复制,本地尝试运行:

js逆向系列09-WPS

navigator is not defined。

直接在文件开头加上var navigator = {};,运行继续报错window is not defined,加上var window = {};

至此能够成功运行:

js逆向系列09-WPS

再把前面的加密代码补上:

js逆向系列09-WPS

JSEncrypt is not defined,而原来的js中将db赋值给window.JSEncrypt,修改js代码并删除无关部分:

js逆向系列09-WPS

得到加密的password,但是每次运行的结果都不同。

先加几个console.log看看哪里会变化:

js逆向系列09-WPS

问题在b中,每次运行都会返回一个看起来随机的值。在function(a,b)的最后一行,new J(c),打个断点跟进去查看J函数:

js逆向系列09-WPS

里面有近1000行代码,进行了各类运算,其中看到下面一行:

js逆向系列09-WPS

f.fromInt(H[Math.floor(Math.random() * H.length)]);,存在Math.random(),每次都会获取一个随机值,因此每次加密的结果都是不同的。


原文始发于微信公众号(Crush Sec):js逆向系列09-WPS

版权声明:admin 发表于 2024年6月6日 下午3:34。
转载请注明:js逆向系列09-WPS | CTF导航

相关文章