【JS逆向】X咕视频 登录 RSA加密

注意:文章内容仅用于学习和技术交流,如有侵权请联系我删除。

学者应洁身自好,切勿做出违法的事情,旨在提供逆向思路。

➣➣欢迎关注本人信微公众号:Anonymous NoteBook➣➣

分享好玩有趣的网络资源&软件工具~

分享各种技术性PDF资源/付费查询PDF资源~

分享各种编程语言、开发技术、分布式事务、大数据与云计算技术~

分享有关网络爬虫(Web爬虫逆向 | 安卓逆向)案例、数据挖掘、技术心得等~

aHR0cHM6Ly93d3cubWlndS5jbi8=

登陆分析:

点击右上角登录按钮,弹出登录输入框:

【Ps: 手机号为随意填写。】 

打开F12调试工具,点击登录按钮,查看登录接口:

 会发现,每点击一次登录,都会出现两个接口。

第一个含有publickey的接口,顾名思义,应该是和公钥有关,想必登录加密为rsa,看下返回结果:

 有过rsa加密经验的人一眼都能看出,返回的result结果中的参数正是rsa加密所需的参数,其中’modulus‘就是公钥。记好这两个参数,后面的所有加密都和result中的字段有关。

我们再看第二个接口,url中包含’authn‘, 顾名思义,这个接口即为登录认证接口,具体看下:

请求参数有四个加密参数:

 既然前面分析中发现有公钥出现,这些参数确实为rsa加密。

返回结果:

 分析总结:

1、首先在登录认证之前,程序会自动请求一个包含公钥的url,返回公钥以及其他参数。

2、通过上一步得到的参数,使用rsa进行对明文参数进行加密,得到加密参数。

3、请求登录认证接口,返回响应。

到此,我们把流程和加密捋了一遍,下面开始逆向分析:

逆向分析:

首先,既然我们知道加密手段为rsa,我们就先以RSA为关键词搜索下,看看是否有关键信息出现:

通过搜索发现,有两条重要信息"J_RsaPsd", "J_RsaAccout" ,点进去其中一条看下:

这里就是密码、账号的加密所在。

往下面翻,你又会发现一个重要的加密参数逻辑:

 我们全局搜索下loginID加密参数,你会发现:

后面分析一下,就可以知道loginID的值其实就是账号加密后的值。

此时,我们打上几个关键的断点,进行下调试:

 参数a为公钥接口的返回值:

 另外,所有的加密函数x.excrypt 调用的都是gb函数,我们跟一下gb函数:

跳进来的这个文件就是该网站所有的加密逻辑所在,边执行、边调试,找到关键代码复制粘贴到本地js文件中。

此时到这里,我们就把loginID和enpassword 加密分析完成了。

下面分析指纹相关的参数:fingerPrint 和 fingerPrintDetail :

我们再次回到第一次进去的文件里:

可以直接看出, fingerPrint的值为变量b的result参数, fingerPrintDetail 的值为变量b的details参数。

变量b的结果是调用了加密函数q.page.rsaFingerprint得到,通过调试可知,q.page.rsaFingerprint调用的是rsaFingerprint(a,b)函数:

 参数a和b分别为上一步请求得到的数据:

分析 到这里,心里想必对加密逻辑很清晰了吧。

跟进去rsaFingerprint函数,返回两个字段:

 再次声明下:fingerPrint的值为变量b的result参数, fingerPrintDetail 的值为变量b的details参数。

走到这里,逆向完成度为95%。

接下来就是根据上面的分析,找到关键js函数,拷贝复制到本地,补全变量,运行调试:

 完美运行。

但是我们仍需验证正确性,通过py文件进行模拟请求下:

 结果与网页返回的结果一样。

本人注册了一个真实账号,再次模拟下:

登陆成功。

到此,逆向结束!!!!

var lb, mb, nb = "0123456789abcdefghijklmnopqrstuvwxyz", ob = new Array;

var navigator = {
    appName: "Netscape",
}
var window = global;

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))
}

function h(a, b, c, d, e, f) {
        ..................
    //此处省略多行代码
    return e
}

function E(a) {
    this.m = a
}

function F(a) {
    return a.s < 0 || a.compareTo(this.m) >= 0 ? a.mod(this.m) : a
}

function G(a) {
    return a
}

function H(a) {
    a.divRemTo(this.m, null, a)
}

function I(a, b, c) {
    a.multiplyTo(b, c),
        this.reduce(c)
}

function J(a, b) {
    a.squareTo(b),
        this.reduce(b)
}

function K() {
        ..................
    //此处省略多行代码
}

function k(a) {
       ..................
    //此处省略多行代码
}

function l(a) {
    this.t = 1,
        this.s = 0 > a ? -1 : 0,
        a > 0 ? this[0] = a : -1 > a ? this[0] = a + this.DV : this.t = 0
}

function j(a, b) {
    var c = ob[a.charCodeAt(b)];
    return null == c ? -1 : c
}

function n(a, b) {
        ..................
    //此处省略多行代码
}

function o() {
    for (var a = this.s & this.DM; this.t > 0 && this[this.t - 1] == a;)
        --this.t
}

function i(a) {
    return nb.charAt(a)
}

function p(a) {
        ..................
    //此处省略多行代码
    return e ? f : "0"
}

function q() {
    var a = e();
    return d.ZERO.subTo(this, a),
        a
}

function r() {
    return this.s < 0 ? this.negate() : this
}

function s(a) {
       ..................
    //此处省略多行代码
}

..................
//此处省略多个函数
..................

function db() {
        ..................
    //此处省略多行代码
}

function eb(a, b) {
    null != a && null != b && a.length > 0 && b.length > 0 ? (this.n = bb(a, 16),
        this.e = parseInt(b, 16)) : alert("网络异常,请点击登录重试")
}

function fb(a) {
    return a.modPowInt(this.e, this.n)
}

function gb(a) {
        ..................
    //此处省略多行代码
}

ab.prototype.nextBytes = _,
    db.prototype.doPublic = fb,
    db.prototype.setPublic = eb,
    db.prototype.encrypt = gb,
    RSAKey = db


function rsaFingerprint(a, b) {
    ..................
    //此处省略多行代码
    g = new 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
    }
}


function FP(a) {
    var b = rsaFingerprint(a.result.modulus, a.result.publicExponent);
    return {
        FingerPrint: b.result,
        FingerPrintDetail: b.details,
    }
    // e.filter(".J_FingerPrint").val(b.result).end().filter(".J_FingerPrintDetail").val(b.details)
}


function rsaPWD(pwd){
    var  c = new RSAKey;
    c.setPublic(resp.result.modulus, resp.result.publicExponent)
    return c.encrypt(pwd)
}

function rsaloginID(account){
    var  c = new RSAKey;
    c.setPublic(resp.result.modulus, resp.result.publicExponent)
    return c.encrypt(account)
}


var resp = {
    "status": 2000, "message": "", "header": {},
    "result":
        {
            "publicExponent": "010001",
            "modulus": "00833c4af965ff7a8409f8b5d5a83d87f2f19d7c1eb40dc59a98d2346cbb145046b2c6facc25b5cc363443f0f7ebd9524b7c1e1917bf7d849212339f6c1d3711b115ecb20f0c89fc2182a985ea28cbb4adf6a321ff7e715ba9b8d7261d1c140485df3b705247a70c28c9068caabbedbf9510dada6d13d99e57642b853a73406817"
        }
}

function main(phone, pwd){

    var FingerPrint = FP(resp).FingerPrint,
        FingerPrintDetail = FP(resp).FingerPrintDetail
    return {
        fingerPrint:FingerPrint,
        FingerPrintDetail: FingerPrintDetail,
        rsaloginID: rsaloginID(phone),
        enpassword: rsaPWD(pwd)
    }
}

console.log(main('158xxxxxxxx','123456'))
// console.log('loginID: ',rsaloginID('158xxxxxxxx'))
// console.log('enpassword: ',rsaPWD('123456'))
// console.log('fingerPrint: ', FP(resp).FingerPrint)
// console.log('fingerPrintDetail: ', FP(resp).FingerPrintDetail)


import requests
import execjs

def get_encry_js():
    with open(r'D:\xxxxx.js','r',encoding='utf-8') as f:
        data = f.read()
    return data


def get_resp(phone, pwd):
    com_ = execjs.compile(get_encry_js())
    result = com_.call('main',phone, pwd)
    headers = {...}
    data = {...}
    response = requests.post('登陆认证url', headers=headers, data=data)
    print(response.text)





if __name__ == '__main__':
    get_resp('158xxxxxxxx','123456')

完事~~~~收工~~~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值