【JS逆向】咪咕视频登录RSA | 每日JS

已迁移平台:segmentfault,搜索 erma0
换平台了,发什么都锁定,广告一堆,趁早倒闭吧。


第二天

JavaScript逆向练习2

0x01 目标网址

http://www.miguvideo.com/

抓包或者右键查看框架源代码可以看到,弹出的登录框URL为:

https://passport.migu.cn/login?sourceid=203021&apptype=2&forceAuthn=true&isPassive=false&authType=&display=&nodeId=70027513&relayState=login&weibo=1&callbackURL=http%3A%2F%2Fwww.miguvideo.com%2Fmgs%2Fwebsite%2Fprd%2Findex.html%3FisIframe%3Dweb

0x02 定位JS

1. 随便输入账号密码验证码,,有验证码要输入正确的验证码,点击登录,查看提交的参数

1.png

可以看到,发出了两个请求,第一个是获取key,第二个是登录,在登录包里有加密过 的参数,密码enpassword、伪指纹fingerPrintfingerPrintDetail

2. Ctrl+Shift+F调出搜索面板,搜索enpassword,看到只要一个结果,而且是网页源码。

2.png

乍一看没有头绪,其实这里是通过Class来定位取值的,也就是说,这里可以试试再搜索一次Class的值:J_RsaPsd,可以看到有两条结果,第二个是我们上一次搜索的结果,肯定不是加密点,所以应该是在第一个结果里。

3.png

点进第一个结果,点花括号格式化一下,Ctrl+F搜索J_RsaPsd,发现有三个结果,稍作分析,在每一个可疑的地方都下断点。

4.png

3. 重新输入账号密码验证码,点击登录,JS被断了下来,我们要的加密点是在328-338行的位置,代码扣下来备用。

success: function(a) {
   if (a.status = g.ajax.SUCCESS) {
       c.each(function() {
           var b = $(this),
               c = new j.RSAKey;
           c.setPublic(a.result.modulus, a.result.publicExponent);
           var d = c.encrypt(b.val());
           b.siblings(".J_RsaPsd").val(d)
       });
       var b = i.page.rsaFingerprint(a.result.modulus, a.result.publicExponent);
       d.filter(".J_FingerPrint").val(b.result).end().filter(".J_FingerPrintDetail").val(b.details)
   }

这段代码就是当异步请求Key(就是1中抓包看到的两条请求中的第一个)成功后,根据Key进行加密操作。

其中b.val()是明文密码,a.result.modulus, a.result.publicExponent是第一条请求得到的Key,直接固定,i.page.rsaFingerprint是计算另外两个加密参数。

鼠标悬停在j.RSAKey上(这里是new出来的对象,先要找到来源),点击弹出的内容,直接跳转进去。

5.png

4. 进入对象的定义函数中,发现全是this,那就直接把整个上一层全拿走,一直翻,找出的上层代码是3916行开始,到4521行结束。

define("lib/rsa/rsa", [], function(a, b, c) {
    function d(a, b, c) {
        null != a && ("number" == typeof a ? this.fromNumber(a, b, c) : null == b && "string" != typeof a ? this.fromString(a, 256) : this.fromString(a, b))
    }
***
省略
***
    ab.prototype.nextBytes = _,
    db.prototype.doPublic = fb,
    db.prototype.setPublic = eb,
    db.prototype.encrypt = gb,
    c.exports = {
        RSAKey: db
    }
}),

5. 到这里已经可以开始改写密码加密部分的内容了,但是还有两个参数也有加密,我还是一起扣出来再改写。

同上,在337行下个断点,再运行到这里。鼠标悬停在rsaFingerprint上,点击弹出的内容,直接跳转进去。

6.png

直接把定义函数扣出来就可以。

        rsaFingerprint: function(a, b) {
            if (!$.fingerprint)
                return {
                    details: "",
                    result: ""
                };
            var c = $.fingerprint.details
              , d = $.fingerprint.result
              , e = c.length
              , f = ""
              , g = new l.RSAKey;
            g.setPublic(a, b);
            for (var h = g.encrypt(d), i = 0; e > i; i += 117)
                f += g.encrypt(c.substr(i, 117));
            return {
                details: f,
                result: h
            }
        }

这其中参数a,b是第一条请求的Key,可以直接固定;$.fingerprint可以到console输出看一下,是浏览器、请求头相关的信息,可以说是伪指纹,暂且固定,最后return的是个对象,正好是登录包里的另外两个参数。

0x03 改写JS

1. 先写一个调用函数。

var p1 = "00833c4af965ff7a8409f8b5d5a83d87f2f19d7c1eb40dc59a98d2346cbb145046b2c6facc25b5cc363443f0f7ebd9524b7c1e1917bf7d849212339f6c1d3711b115ecb20f0c89fc2182a985ea28cbb4adf6a321ff7e715ba9b8d7261d1c140485df3b705247a70c28c9068caabbedbf9510dada6d13d99e57642b853a73406817",
    p2 = "010001";//因为另一个加密也要调用这两个值,所以定义在函数外面,作为全局变量用。

function getP(pass) {//密码加密计算函数,仿照加密点代码写的。
    var c = new RSAKey;
    c.setPublic(p1, p2);
    var d = c.encrypt(pass);
    return d;
}

2. 改写RSAKey对象定义处

window = this;
navigator = {}; //把需要用到的值先定义空对象

//把第一行删掉,把内部的函数暴露出来(对应的结尾部分的括号也删掉)
//define("lib/rsa/rsa", [], function(a, b, c) {
    function d(a, b, c) {
        null != a && ("number" == typeof a ? this.fromNumber(a, b, c) : null == b && "string" != typeof a ? this.fromString(a, 256) : this.fromString(a, b))
    }
***
省略
***
    ab.prototype.nextBytes = _,
    db.prototype.doPublic = fb,
    db.prototype.setPublic = eb,
    db.prototype.encrypt = gb;
    //把原来的逗号换成分号结束掉语句。

    //,
    //c.exports = {
    //    RSAKey: db
    //}
    //本来是用exports来对外导出,现在直接定义对象就可以。
    var RSAKey = db;
//}),

现在就可以通过getP(pass)来加密明文密码了。

3. 改写rsaFingerprint定义

先把之前console里输出的浏览器信息定义成变量,再把函数部分改成正常的定义就可以了。

把开始的if判断给删除,另外这里还要把对应的值都给换一下,如*.RSAKey换成RSAKey。

var details = '{"user_agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safa","language":"zh-CN","color_depth":"24","pixel_ratio":"1.25","hardware_concurrency":"4","resolution":"1536,864","available_resolution":"1536,824","timezone_offset":"-480","session_storage":"1","local_storage":"1","indexed_db":"1","open_database":"1","cpu_class":"unknown","navigator_platform":"Win32","do_not_track":"unknown","regular_plugins":"Chromium PDF Plugin::Portable Document Format::application/x-google-chrome-pdf~pdf,Chromium PDF View","webgl_vendor":"Google Inc.~ANGLE (Intel(R) HD Graphics 530 Direct3D9Ex vs_3_0 ps_3_0)","adblock":"true","has_lied_languages":"false","has_lied_resolution":"false","has_lied_os":"false","has_lied_browser":"false","touch_support":"0,false,false","js_fonts":"Arial,Arial Black,Arial Narrow,Book Antiqua,Bookman Old Style,Calibri,Cambria,Cambria Math,Century,C"}',
    result = "2754353484e6bed2ec7cf41dddba8bce"
rsaFingerprint = function() {
    var c = details,
        d = result,
        e = c.length,
        f = "",
        g = new RSAKey;
    g.setPublic(aaaa, "010001");
    for (var h = g.encrypt(d), i = 0; e > i; i += 117)
    f += g.encrypt(c.substr(i, 117));
    return {
        details: f,
        result: h
    }
}

此时就可以运行了。

0x04 代码

省略

PS

如果在加密后的登陆过程中出现异常,那可能是浏览器信息的问题,仔细对照看看哪里不一样就知道了。

你可能感兴趣的:(【JS逆向】咪咕视频登录RSA | 每日JS)