米游社登陆参数解析(RSA、webpack、RCP)

一.分析负载参数

        我们来到登录的界面,然后输入账号密码,再观察这个登录的网络请求。

能很清楚看到,我们输出的账号密码(123456,123456)被加密成了两串密文进行传送,如果我们要实现模拟登录的话,必须要能够复现它的加密逻辑。

二.堆栈分析

        我们利用启动器来进行堆栈分析,在最后发送网络请求的地方打上一个断点。

然后重新登录,来到右边的堆栈进行分析。

在u的这个堆栈里面,我们发现了很可能是开始加密的地方,我们尝试在这里打上断点,重新登录。

于是,我们可以确定了,这里就是对账号密码进行加密的地方了。另外如果有经验的话,我们从这个文件里面就能够看出,这里的登录是使用的webpack。我们再单步跟进去看看,我们就能得知,加密方法应当使用的是RSA加密。

RSA的一个重要关键字就是setpublickey,我们以此进行全局搜索,看看能不能找到加密的公钥。

非常简单,很显然MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDvekdPMHN3AYhm/vktJT+YJr7\ncI5DcsNKqdsx5DZX0gDuWFuIjzdwButrIYPNmRJ1G8ybDIF7oDW2eEpm5sMbL9zs\n9ExXCdvqrn51qELbqj0XxtMTIpaCHFSI50PfPpTFV9Xt/hmyVwokoOXFlAEgCn+Q\nCgGs52bFoYMtyi+xEQIDAQAB就是加密的公钥了。

根据上面的分析,我们有以下几种方法来实现加密方法,第一中是利用现成的库来实现RSA加密,第二种是通过抠webpack的方式实现调用加密函数,得到加密结果,第三种是利用RCP的方式来调用加密函数得到加密结果。

三.套库实现加密

        这种方式最为简单,这里就不再赘述,需要注意的是密钥的格式。

import base64
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import requests
account='你的账号'
password='你的密码'
key='-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDvekdPMHN3AYhm/vktJT+YJr7\ncI5DcsNKqdsx5DZX0gDuWFuIjzdwButrIYPNmRJ1G8ybDIF7oDW2eEpm5sMbL9zs\n9ExXCdvqrn51qELbqj0XxtMTIpaCHFSI50PfPpTFV9Xt/hmyVwokoOXFlAEgCn+Q\nCgGs52bFoYMtyi+xEQIDAQAB\n-----END PUBLIC KEY-----'

def RSA_jiami(data,key):
    publicKey = RSA.importKey(key)
    cipher = PKCS1_v1_5.new(publicKey)
    output_data = base64.b64encode(cipher.encrypt(data.encode('utf-8'))).decode('utf-8')
    return output_data

if __name__=="__main__":
    url='https://passport-api.miyoushe.com/account/ma-cn-passport/web/loginByPassword'
    headers = {
    "Accept": "application/json, text/plain, */*",
    "Accept-Encoding": "gzip, deflate, br, zstd",
    "Accept-Language": "zh-CN,zh;q=0.9,en-GB;q=0.8,en-US;q=0.7,en;q=0.6",
    "Cache-Control": "no-cache",
    "Connection": "keep-alive",
    "Content-Length": "372",
    "Content-Type": "application/json",
    "Cookie": "_MHYUUID=9c9aca85-7087-4af2-8542-94860eff21b2; DEVICEFP_SEED_ID=9b75d0123731369d; DEVICEFP_SEED_TIME=1714528737065; DEVICEFP=38d7f9f285deb; _ga=GA1.1.1351865754.1714528738; aliyungf_tc=7aced00f801d605acaa574cdc7906fb0737d5662bf1899633fe3c8306d67d9c7; _ga_KS4J8TXSHQ=GS1.1.1717463999.8.1.1717464259.0.0.0; MIHOYO_LOGIN_PLATFORM_LIFECYCLE_ID=43278ee300",
    "Host": "passport-api.miyoushe.com",
    "Origin": "https://user.miyoushe.com",
    "Pragma": "no-cache",
    "Referer": "https://user.miyoushe.com/",
    "Sec-Fetch-Dest": "empty",
    "Sec-Fetch-Mode": "cors",
    "Sec-Fetch-Site": "same-site",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36",
    "sec-ch-ua": "\"Google Chrome\";v=\"123\", \"Not:A-Brand\";v=\"8\", \"Chromium\";v=\"123\"",
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": "\"Windows\"",
    "x-rpc-app_id": "bll8iq97cem8",
    "x-rpc-client_type": "4",
    "x-rpc-device_fp": "38d7f9f285deb",
    "x-rpc-device_id": "9c9aca85-7087-4af2-8542-94860eff21b2",
    "x-rpc-device_model": "Chrome%20123.0.0.0",
    "x-rpc-device_name": "Chrome",
    "x-rpc-device_os": "Windows%2010%2064-bit",
    "x-rpc-game_biz": "bbs_cn",
    "x-rpc-lifecycle_id": "43278ee300",
    "x-rpc-mi_referrer": "https://user.miyoushe.com/login-platform/index.html?app_id=bll8iq97cem8&theme=&token_type=4&game_biz=bbs_cn&message_origin=https%253A%252F%252Fwww.miyoushe.com&succ_back_type=message%253Alogin-platform%253Alogin-success&fail_back_type=message%253Alogin-platform%253Alogin-fail&ux_mode=popup&iframe_level=1#/login/password",
    "x-rpc-sdk_version": "2.27.0",
    "x-rpc-source": "v2.webLogin"
}
    response=requests.post(url=url,headers=headers,json={
        'account':RSA_jiami(account,key),
        'password':RSA_jiami(password,key)
    })
    print(response.text)


        

四.抠webpack的方式

        我们回到加密方法的地方分析一下。

可以看出,想要调用加密方法encrypt的话,就需要构造出i这个对象,那么这个i哪里来的呢?我们不断往上面找,最终可以找到生成i的地方。

在这里打上断点,我们刷新页面。

进入到这个n函数定义的地方看看。

很显然这是一个标准的加载器。我们把整个该文件扣下来,并利用全局变量的方式导出这个加载器。

然后我们利用原JS里面的调用加密函数的方式尝试调用输出:

可以看到缺少了一些环境,我们尝试手动补充。再次运行。

这次报的错误是抠webpack里面非常常见的一个错误,也就是缺少一些模块,但是如果你一个一个去补充这些模块的话,将会非常费时,于是我们干脆将所有模块全部扣下来,放在一起。再次运行。

加密生成成功,并且没有很深度的检测环境,利用这个生成结果,可以验证我们的生成是正确的。

五.RCP法

        我们找到调用加密函数的地方,进行文件替换,然后在这里插入一段websocket代码,

var ws;
 // 检查ws是否存在且连接处于打开状态
if(ws && ws.readyState === WebSocket.OPEN) {
    console.log("已存在一个打开的连接");
     return;
  }

 ws = new WebSocket("ws://127.0.0.1:5678");
  
 ws.onmessage = function (evt) {
    console.log("成功连接到服务器");
    ws.send(i.Z.encrypt(evt));
 };

然后我们在本地利用python编写一段简单的websocket服务端代码

import asyncio
import websockets
import aioconsole

async def receive_massage(websocket):
    while True:
        send_text = await aioconsole.ainput("请输入要加密的字符串: ")  # 改用 aioconsole
        if send_text.strip() == "exit":
            print("Exit, goodbye!")
            await websocket.send(send_text)
            await websocket.close()
            break
        else:
            await websocket.send(send_text)
            response_text = await websocket.recv()
            print("返回的结果是:", response_text)

start_server = websockets.serve(receive_massage, '127.0.0.1', 5678)  # 自定义端口
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

当然,这些代码都可以改进,这里写的不是很好,不过能用就行。

随后我们先运行本地代码,然后需要打开浏览器执行一遍登录。然后回到本地,输入待加密的字符串,这样就能成功获得加密结果了。

RCP是一种比较万能的方法,一般别的方法行不通的话,可以尝试这个方法。

  • 20
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值