JavaScript逆向必学姿势JSRPC"

admin 2026-10-22 03:40:32 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

cover_image

JavaScript 逆向必学姿势 JSRPC

Gh0xE9
Gh0xE9

Gh0xE9

2026年6月23日 08:46
北京

在小说阅读器读本章

去阅读

语法基础可以看看 JavaScript

JsRPC

仓库地址:GitHub - jxhczhl/JsRpc: 远程调用(rpc)浏览器方法,免去抠代码补环境

在网站的控制台新建一个WebScoket客户端链接到服务器通信,调用服务器的接口 服务器会发送信息给客户端 客户端接收到要执行的方法执行完js代码后把获得想要的内容发回给服务器,服务器接收到后再显示出来
api 简介

  • • /list :查看当前连接的ws服务 (get)
  • • /ws :浏览器注入ws连接的接口 (ws | wss)
  • • /wst :ws测试使用-发啥回啥 (ws | wss)
  • • /go :获取数据的接口 (get | post)
  • • /execjs :传递jscode给浏览器执行 (get | post)
  • • /page/cookie :直接获取当前页面的cookie (get)
  • • /page/html :获取当前页面的html (get)
    服务端 ./jsrpc 启动

浏览器进行注入

// 先复制
var rpc_client_id, Hlclient = function (wsURL) {
    this.wsURL = wsURL;
    this.handlers = {
        _execjs: function (resolve, param) {
            try {
                var fn = newFunction('return (async () => { ' + param + ' })()');
                var result = fn();
                if (result && typeof result.then === 'function') {
                    result.then(function(res) {
                        resolve(res !== undefined ? res : \"执行成功(无返回值)\");
                    }).catch(function(err) {
                        resolve(\"执行错误: \" + (err.message || err));
                    });
                } else {
                    resolve(result !== undefined ? result : \"执行成功(无返回值)\");
                }
            } catch (err) {
                resolve(\"语法错误: \" + (err.message || err));
            }
        }
    };
    this.socket = undefined;
    if (!wsURL) {
        thrownewError('wsURL can not be empty!!')
    }
    this.connect()
}
Hlclient.prototype.connect = function () {
    if (this.wsURL.indexOf(\"clientId=\") === -1 && rpc_client_id) {
        this.wsURL += \"&clientId=\" + rpc_client_id
    }
    console.log('begin of connect to wsURL: ' + this.wsURL);
    var _this = this;
    try {
        this.socket = newWebSocket(this.wsURL);
        this.socket.onmessage = function (e) {
            _this.handlerRequest(e.data)
        }
    } catch (e) {
        console.log(\"connection failed,reconnect after 10s\");
        setTimeout(function () {
            _this.connect()
        }, 10000)
    }
    this.socket.onclose = function () {
        console.log('rpc已关闭');
        setTimeout(function () {
            _this.connect()
        }, 10000)
    }
    this.socket.addEventListener('open', (event) => {
        console.log(\"rpc连接成功\");
        this._reportActions();
    });
    this.socket.addEventListener('error', (event) => {
        console.error('rpc连接出错,请检查是否打开服务端:', event.error);
    })
};
Hlclient.prototype.send = function (msg) {
    this.socket.send(msg)
}
Hlclient.prototype.regAction = function (func_name, func) {
    if (typeof func_name !== 'string') {
        thrownewError(\"an func_name must be string\");
    }
    if (typeof func !== 'function') {
        thrownewError(\"must be function\");
    }
    console.log(\"register func_name: \" + func_name);
    this.handlers[func_name] = func;
    this._reportActions();
    returntrue
}
Hlclient.prototype._reportActions = function () {
    var actions = Object.keys(this.handlers);
    if (this.socket && this.socket.readyState === WebSocket.OPEN) {
        this.send(JSON.stringify({
            \"action\": \"_registerActions\",
            \"message_id\": \"\",
            \"response_data\": JSON.stringify(actions)
        }));
    }
}
Hlclient.prototype.handlerRequest = function (requestJson) {
    var _this = this;
    try {
        var result = JSON.parse(requestJson)
    } catch (error) {
        console.log(\"请求信息解析错误\", requestJson);
        return
    }
    if (result[\"registerId\"]) {
        rpc_client_id = result['registerId']
        return
    }
    if (!result['action'] || !result[\"message_id\"]) {
        console.warn('没有方法或者消息id,不处理');
        return
    }
    var action = result[\"action\"], message_id = result[\"message_id\"]
    var theHandler = this.handlers[action];
    if (!theHandler) {
        this.sendResult(action, message_id, 'action没找到');
        return
    }
    try {
        if (!result[\"param\"]) {
            const async_result = theHandler(function (response) {
                _this.sendResult(action, message_id, response);
            })
            if (async_result && typeof async_result.then === \"function\") {
                async_result.catch(e => {
                    _this.sendResult(action, message_id, \"\" + e);
                });
            }
            return
        }
        var param = result[\"param\"]
        try {
            param = JSON.parse(param)
        } catch (e) {
        }
        theHandler(function (response) {
            _this.sendResult(action, message_id, response);
        }, param)
    } catch (e) {
        console.log(\"error: \" + e);
        _this.sendResult(action, message_id, \"\" + e);
    }
}
Hlclient.prototype.sendResult = function (action, message_id, e) {
    if (typeof e === 'object' && e !== null) {
        try {
            e = JSON.stringify(e)
        } catch (v) {
            console.log(v)
        }
    }
    this.send(JSON.stringify({\"action\": action, \"message_id\": message_id, \"response_data\": e}));
}
// 注入环境后连接通信
var demo = newHlclient(\"ws://127.0.0.1:12080/ws?group=zzz\");
// 可选
//var demo = new Hlclient(\"ws://127.0.0.1:12080/ws?group=zzz&clientId=hliang/\"+new Date().getTime())

然后浏览器进行链接

Python代码打开进行 hook

import requests

js_code = \"\"\"
console.log(add(1,2))
\"\"\"

url = \"http://localhost:12080/execjs\"
data = {
    \"group\": \"zzz\",
    \"code\": js_code
}
res = requests.post(url, data=data)
print(res.text)

记录加密函数

例如现在有一个btoa函数,我想要使用jsrpc来调用这个函数

测试一下

然后需要向JsRPC中注册这些函数

// 有参函数
demo.regAction(\"mybtoa\", function (resolve, param) {
    var res = mybtoa(String(param));
    resolve(res);
})

说明一下参数

接着发送get请求, 或post请求到本机的12080端口, 即可获取调用结果

[127.0.0.1:12080/go?group=zzz&action=mybtoa&param=asdsadasdsad](http://127.0.0.1:12080/go?group=zzz&action=mybtoa&param=asdsadasdsad)

举个例子,例如我们要调试一些带加密参数的代码,先在控制台进行记录,然后打上断点

//时间戳
window.time = Date.parse
//requestId
window.id = p
//v函数
window.v1 = v
//签名
window.m = a.a.MD5
//加密
window.enc = l

接着注册函数

//md5函数
demo.regAction(\"req\", function (resolve,param) {
    //请求头
    let timestamp = time(newDate());
    let requestid = id();
    let v_data = JSON.stringify(v1(param));
    let sign = m(v_data + requestid + timestamp).toString();
    //加密请求体
    let encstr = enc(v_data);

    let res = {
        \"timestamp\":timestamp,
        \"requestid\":requestid,
        \"encstr\":encstr,
        \"sign\":sign
    };
    resolve(res);
})

然后发送数据包

http://127.0.0.1:12080/go
group=zzz&action=req&param={
    \"password\": \"123\",
    \"username\": \"test\",
    \"validCode\": \"p5zk\"
}

JavaScript逆向必学姿势JSRPC" 网络安全文章

JavaScript逆向必学姿势JSRPC"

本文介绍JsRPC工具实现浏览器JavaScript方法远程调用的技术方案,通过WebSocket连接使服务器能调用客户端注册的JS函数。关键步骤包括服务端启动、浏览器环境注入、函数注册及HTTP接口调用,并演示了加密函数调试等逆向工程实战场景。文档提供完整的代码示例和操作流程,具备较强的实践指导价值。
2026五部门联合启动新能源汽车下乡叠加乡村以旧换新政策" 网络安全文章

2026五部门联合启动新能源汽车下乡叠加乡村以旧换新政策"

2026年6月五部门启动新能源汽车下乡政策,包含155款车型免税、县域充换电配套及以旧换新补贴,旨在提振内需。周度数据显示新能源渗透率超60%,行业聚焦电动化安全标准升级、L3/L4智驾国标制定及车企出海产能落地。报告推荐整车、零部件、商用车三条投资主线,并提示政策落地不及预期等风险。
反对初中平面几何辅助线的神秘主义" 网络安全文章

反对初中平面几何辅助线的神秘主义"

本文通过一道等腰直角三角形双动点最值问题,演示了如何自然推导辅助线添加过程,强调通过构造定点(如点H、点K)将动点问题转化为定点间线段最短问题。作者反对不解释思路来源的`神秘主义`解法,指出解题关键在于根据题干条件寻找定点并严格证明,并建议学生坚持追问解题思路的由来。
评论:0   参与:  0