安卓 逆向高级-人均瑞数

安卓 逆向高级-人均瑞数

码农世界 2024-05-18 前端 54 次浏览 0个评论

引言:

JS 爬虫,绕不过瑞数这道坎,卡的死死的。一般网上的教程就是补环境什么的,我尝试了,可以但是比较麻烦。 今天说一种,秒过的方式,抗并发。那就是牛逼的RPC,hook JS 技术。

前期准备:

  1. 安装nodejs

下载地址:

Node.js — Run JavaScript Everywhere

安装依赖

npm install ws

npm  install express

  1. Google浏览器

F12 调试,会反反调试

  1. 代码1,NodeJS 端

完成1,组装http服务,提供对外接口,方便其他地方直接调用. 2 ,监控websocket 服务,与hook 的js 交互,http服务连接websocket,websocket 连接hookjs, js 直接调用网站的协议。

代码:

global.navigator = {appName: 'nodejs'}; // fake the navigator object

global.window = {}; // fake the window object

const express=require('express');

const server=express();

const bodyParser = require('body-parser');

server.listen(8093,'0.0.0.0',function(){

    console.log('http://localhost:8093');

});

server.use(bodyParser.urlencoded({ extended: false })); //调用中间件

server.use(bodyParser.json())

 //import * as WebSocket from 'ws';

const WebSocket = require('ws')

const server1 = new WebSocket.Server({ port: 8013 });

console.log('begin')

server1.on('connection', (socket) => {

  console.log('New client connected');

  socket.on('message', (message) => {

    console.log(`Received message: ${message}`);

try {

    // 向所有客户端广播消息

    if(message.indexOf("ping") >=0 ) {

        server1.clients.forEach((client) => {

        if (client.readyState === WebSocket.OPEN) {

            client.send("ping");

        }

        });

    }else if(message.indexOf("rep") >=0 ) {

       // global.retmsg = message;

       str = ` ${message}`

       var args = str.split('|');

       uuid = args[2]

       var tmpjs = JSON.parse(args[1])

       global.resps[uuid].json({code:1,message:'',data:tmpjs,uuid:uuid})

       global.resps[uuid] = null;

       // global.resp.json({code:1,message:'',data:str})

    }

}catch(error) {

console.log(error);

}

  });

  socket.on('close', () => {

    console.log('Client disconnected');

  });

});

global.resps = {}

function guid() {

    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {

        var r = Math.random() * 16 | 0,

            v = c == 'x' ? r : (r & 0x3 | 0x8);

        return v.toString(16);

    });

}

global.server = server1

server.post('/list',function(req,resp){

    console.log("list 接收参数:" + req.body + new Date());

    //global.resp = undefined;

   // uuid = guid();

   uuid = req.body.uuid;

    server1.clients.forEach((client) => {

        if (client.readyState === WebSocket.OPEN) {

            global.retmsg = "";

            client.send("list|"+JSON.stringify(req.body) +"|" + uuid);

        }

        });       

        global.resps[uuid] =  resp

    }

 );

const WebSocket = require('ws')

const server1 = new WebSocket.Server({ port: 8013 });

监听 websocket 端口 8013

这个是心跳包,网页js 与 nodejs 保持连接,保持心跳用

  // 向所有客户端广播消息

    if(message.indexOf("ping") >=0 ) {

        server1.clients.forEach((client) => {

        if (client.readyState === WebSocket.OPEN) {

            client.send("ping");

        }

        });

    }

// 这个是定义的websocket 返回,接收到websocket 返回,然后发送给 http 客户端。

}else if(message.indexOf("rep") >=0 ) {

       // global.retmsg = message;

       str = ` ${message}`

       var args = str.split('|');

       uuid = args[2]

       var tmpjs = JSON.parse(args[1])

       global.resps[uuid].json({code:1,message:'',data:tmpjs,uuid:uuid})

       global.resps[uuid] = null;

       // global.resp.json({code:1,message:'',data:str})

    }

// 这里定义一个对外http 服务,list就是 http://localhost:8093/list , 参数json格式

{ “data”:”11”,”uuid”:”333”}, 有一个全局变量   global.resps, 他这样存储   global.resps[uuid] =  resp 一个uuid 即一个http客户端的变量,方便从websocke他得到返回之后,直接给他发送消息。

  client.send("list|"+JSON.stringify(req.body) +"|" + uuid); ,这个是http 收到数据,直接发送给websocket 即js 客户端就行。

server.post('/list',function(req,resp){

    console.log("list 接收参数:" + req.body + new Date());

   uuid = req.body.uuid;

    server1.clients.forEach((client) => {

        if (client.readyState === WebSocket.OPEN) {

            global.retmsg = "";

            client.send("list|"+JSON.stringify(req.body) +"|" + uuid);

        }

        });       

        global.resps[uuid] =  resp

    }

 );

  1. 代码2, js hook 端
  1. 1 先来看下一个实例网站。

启动器,定位到请求位置所在。

//跟踪进去代码,是直接发送ajax,那一分钟就搞定。瑞数就是说他会hook ajax send 函数,添加头,添加cookie 之类的。我们搞不顶瑞数,但是可以写ajax 请求啊

2.2 js 端代码:

function patch_ruishu(url){

    console.log("RPC args:"+url);

    var v = [];

    v.push(window.hc_url(url));

    v.push(window.hc_cook(945, 10,false));

    return v;

}

// 闭包

!function (a) {

    // Promise是一种用于处理异步操作的机制

    // 该函数接受两个参数:resolve和reject。

    // resolve是一个函数,用于将Promise从挂起状态转换为已解决状态(fulfilled),并返回解决结果(通常是异步操作的结果)。

    // reject是一个函数,用于将Promise从挂起状态转换为已拒绝状态(rejected),并返回拒绝原因(通常是异步操作的错误信息)。

    new Promise((e, s) => {

            e(a)

        }

    ).then((myFunction) => {

            var cbb_MyId = "1001";

            // 执行下面语句之后,客户端就会与服务器进行连接。

            ws = new WebSocket("ws://127.0.0.1:8013");

            // 指定连接成功后的回调函数

            ws.onopen = function () {

                console.log("服务器连接成功!");

                // send 向服务器发送数据

             

                

               

                setInterval(function () {

                    ws.send(cbb_MyId+'ping---'+"connect");

                }, 5000)

                

            }

            ;

            window.ws = ws;

            // 收到服务器数据后的回调函数。

            ws.onmessage = function (evt) {

                if (evt.data.indexOf("ping") >= 0) {

                    console.log('ping')

                    return;

                }

                console.log('传入数据: ' + evt.data);

                if(evt.data.indexOf("list") >=0 ) {

                    //调用方法

                    var args = evt.data.split('|');

                    console.log(args[1]);

                    var reqdata = JSON.parse(args[1]);

                   try {

                    var serviceNbr = reqdata.mobile;

                    var param ="userInfo.loginType=4&userInfo.serviceNbr="+serviceNbr+"&flag=0&chargeType=undefined"

                    

                    var code = mycode(serviceNbr.replace(/ /g,""),"7");

                    param=param+"&key="+code;

                    $.ajax({

                        type:'POST',

                        url:"https://ah.189.cn/service/pay/findByUser.action",

                        data:param,

                        dataType:'json',

                        cache:false,

                        //async:false,

                        success:function (data) {

                       

                            if(data.flag == '0'){

                                ws.send("rep|"+ JSON.stringify(data)+ "|" + args[2])

                            }else {

                                ws.send("rep|"+ JSON.stringify(data)+ "|" + args[2])

                            }

                        }

                        });

                    }catch(e) {

                        console.log(e)

                    }

                   

$.ajax({

                    type: "POST",

                    contentType: "application/x-www-form-urlencoded;charset=utf-8",

                    url: path + "/service/index/getDistrictBargain.action",

                    dataType: "json",

                    success: function(data) {

                        var listDistrictBargain = data.listDistrictBargain;

                        var page = data.page;

                        ws.send("rep|"+ JSON.stringify(page)+ "|" + args[2])

                    },

                    error: function() {

                    }

                });

                }

            };

            // 连接关闭后的回调函数

            ws.onclose = function () {

                console.log("rpc已经断开了哦");

            };

            // 连接错误后的回调函数

            ws.onerror = function () {

                console.log("rpc已经断开了哦");

            };

        }

    )

    ;

}(patch_ruishu)  // 这里填返回加密数据的js函数名字

初始化websocket ,然后连上刚才的nodejs

   ws = new WebSocket("ws://127.0.0.1:8013");

            // 指定连接成功后的回调函数

            ws.onopen = function () {

                console.log("服务器连接成功!");

                // send 向服务器发送数据

             

                

               

                setInterval(function () {

                    ws.send(cbb_MyId+'ping---'+"connect");

                }, 5000)

                

            }

            ;

  1. 收到请求:

   if(evt.data.indexOf("list") >=0 ) {

                    //调用方法

                    var args = evt.data.split('|');

                    console.log(args[1]);

                    var reqdata = JSON.parse(args[1]);

                   try {

                    var serviceNbr = reqdata.mobile;

                    var param ="userInfo.loginType=4&userInfo.serviceNbr="+serviceNbr+"&flag=0&chargeType=undefined"

                    

                    var code = mycode(serviceNbr.replace(/ /g,""),"7");

                    param=param+"&key="+code;

                    $.ajax({

                        type:'POST',

                        url:"https://ah.189.cn/service/pay/findByUser.action",

                        data:param,

                        dataType:'json',

                        cache:false,

                        //async:false,

                        success:function (data) {

                       

                            if(data.flag == '0'){

                                ws.send("rep|"+ JSON.stringify(data)+ "|" + args[2])

                            }else {

                                ws.send("rep|"+ JSON.stringify(data)+ "|" + args[2])

                            }

                        }

                        });

                    }catch(e) {

                        console.log(e)

                    }

                   

$.ajax({

                    type: "POST",

                    contentType: "application/x-www-form-urlencoded;charset=utf-8",

                    url: path + "/service/index/getDistrictBargain.action",

                    dataType: "json",

                    success: function(data) {

                        var listDistrictBargain = data.listDistrictBargain;

                        var page = data.page;

                        ws.send("rep|"+ JSON.stringify(page)+ "|" + args[2])

                    },

                    error: function() {

                    }

                });

                }

  1. Node js 远程
  2. C# 远程。
  3. Js websocket 注意事项 如何hook, 如何页面reload ,如何替换js

高级防止 掉线问题,Ip 问题 ,浏览器指纹问题 抗并发,抗造。 如何生产部署,快速集成到csharpcef  框架

转载请注明来自码农世界,本文标题:《安卓 逆向高级-人均瑞数》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,54人围观)参与讨论

还没有评论,来说两句吧...

Top