【JS逆向】新浪二手房登录RSA | 每日JS

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

第四天

JavaScript逆向练习4

0x01 目标网址

http://j.esf.leju.com/ucenter/login

0x02 定位JS

1. 随便输入账号密码(经纪人账号登录),点击登录,查看提交的参数

1.png

可以看到,在登录包http://j.esf.leju.com/ucenter/login里有加密过 的password参数。这个就是下面要找的加密。

这个包还有一个参数ckey,是在网页源码里生成的,每次请求都会更新这个值,做登录的话,每次都去取一下就行了。

2. Ctrl+Shift+F调出搜索面板,搜索password,结果中稍作分析,发现有前面几个结果都不是目标域名下的js文件,剩下两个打开看看。

2.png

在所有可疑的地方都下断点,当然,自信一点可以直接定位到图中这个地方,毕竟一眼可以看到$("#password"),找到这是用来取明文密码的值,而且还有RSA这样的关键字。

3. 直接在可疑的地方都下断点,重新输入账号密码验证码,点击登录,JS被断了下来(就是上图中的位置)。

var t = $("#password")
    , i = $.trim(t.val());
if (i.length < 100) {
    (0,
        l.setMaxDigits)(129);
    var n = new c.RSAKeyPair("10001", "", $("#pubkey").val())
        , s = (0,
            c.encryptedString)(n, i);
    $("input[name='password']").val(s)

加密函数就是encryptedString,两个参数,第一个是RSAKeyPair返回的对象,第二个是明文密码。

而前一行的RSAKeyPair参数$("#pubkey").val()就是公钥了,直接console里输出一下,复制出来。

F11跟进,再或者鼠标悬停在断点处函数名RSAKeyPair上,点击弹出的内容,也能跳转进去。

3.png

加密函数的核心就是在这里,把这段整个290函数全部拿走。

4. 上一步进去之后,发现同时调用了291217两个函数,直接在这里搜数字+冒号,就能定位到这两个函数定义处,全部拿走就完事儿了。

0x03 改写JS

1. 仿照图2的位置,写一个调用函数。

function test() {
    setMaxDigits(129);
    var n = RSAKeyPair("10001", "", "BC087C7C00848CE8A349C9072C3229E0D595F817EDDE9ABF6FC72B41942A759E97956CE9CB7D1F2E99399EADBACC0531F16EAE8EFCB68553DE0E125B2231ED955ADBF5208E65DC804237C93EB23C83E7ECDA0B586ECF31839038EE6B640E0EEC5FF17D219FDEA33E730F287F0D384C74A53DFE1F91ACC63C7C92039A43AC6E97")
    //第三个参数就是上文提的公钥,console里输出复制来的,直接替换在这了。
    var enPass = encryptedString(n, pass);
    return enPass
}

2. 把扣出来的290、291、217三个函数放到调试工具里,再开始改写。

先把三个函数改成标准的函数定义的格式。

function i_217(e, t, i) {
***
代码
***
}
function i_291(e, t, i) {
***
代码
***
}
function i_290(e, t, i) {
***
代码
***
}

同时把每个函数内部的

        "use strict";
        Object.defineProperty(t, "__esModule", {
            value: !0
        }),

这段代码删掉。

其中290里有217 291的调用、291里有217的调用,改成正常格式。

//290里的
var m = i_217(e, t, i)
    , s = i_291(e, t, i)
//291里的
var c = i_217(e, t, i);

3. 此时加载运算,会出现各种未定义和对象不存在,因为现在的代码里并没有调用加密代码,而且抠下来的3个函数都没有返回值。

所以先给每个函数加一个返回值:在函数尾部加上return t(因为函数都是在操作t

再在一开始写的调用函数里,调用290,因为没有参数可以传,所以顺手把290的参数给删掉。

function i_290() {
    t = this
    e = ""
    i = ""
    //其他代码
}

function test(pass) {
    t=i_290()//调用加密核心:290
    //往下的所有函数、对象的调用,都是对象`t`里面的了
    t.setMaxDigits(129);
    var n = t.RSAKeyPair("10001", "", "BC087C7C00848CE8A349C9072C3229E0D595F817EDDE9ABF6FC72B41942A759E97956CE9CB7D1F2E99399EADBACC0531F16EAE8EFCB68553DE0E125B2231ED955ADBF5208E65DC804237C93EB23C83E7ECDA0B586ECF31839038EE6B640E0EEC5FF17D219FDEA33E730F287F0D384C74A53DFE1F91ACC63C7C92039A43AC6E97")
    var enPass = t.encryptedString(t, pass);//这里如果传入n的话,会提示'chunkSize' 为 null 或不是对象
    //传入t的话就OK了,因为所有函数、属性都在`t`里面,同时上面的`var n =`也可以删掉了,因为没有调用,当然不删也没有影响,慢慢熟悉JS语法。
    return enPass
}

此时就能正常运行了

4. 调试结果

0x04 Python代码

PS. 其实可以尝试直接调用Python的RSA加密库,如果这个JS没改过,结果应该是能用的(也就是另一个思路:JS功能可以通过所使用的语言直接实现)。

# -*- encoding: utf-8 -*-
'''
@File    :   0x04-j.esf.leju.com.py
@Time    :   2019/12/10 20:19:22
@Author  :   独孤孤独嘟咕噜犊子
@Version :   1.0
@Link    :   https://www.jianshu.com/u/6a4c6ef97be7
@Desc    :   新浪二手房登录rsa
'''

# start

import execjs
import requests

# 初始化参数
HEADERS = {
    'User-Agent':
    'Mozilla/5.0 (Linux; Android 8.0; DUK-AL20 Build/HUAWEIDUK-AL20; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/6.2 TBS/044353 Mobile Safari/537.36 MicroMessenger/6.7.3.1360(0x26070333) NetType/WIFI Language/zh_CN Process/tools'
}
s = requests.Session()
s.headers.update(HEADERS)
loginURL = 'http://j.esf.leju.com/ucenter/login'

# 登录参数
username = '15555555555'
password = '[email protected]'

# 加载js
with open('js/0x04-j.esf.leju.com.js') as f:  # 坑0x01 相对路径前面不带/,带/不报错但读不出数据
    jscode = f.read()
ctx = execjs.compile(jscode)  # execjs载入js代码


def get_ckey():
    url = 'http://j.esf.leju.com/ucenter/login'
    res = s.get(url).text
    ckey = res.split('name="ckey" value="')[1].split('" />')[0]
    return ckey


def login(user, password):
    enPass = ctx.call('test', password)  # 通过call调用js代码里的函数
    ckey = get_ckey()
    data = {
        'username': username,
        'password': enPass,
        'imgcode': '',
        'ckey': ckey
    }
    result = s.post(loginURL, data=data).json()
    print(result)
    return result


if __name__ == "__main__":
    login(username, password)

你可能感兴趣的:(【JS逆向】新浪二手房登录RSA | 每日JS)