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¶m=asdsadasdsad](http://127.0.0.1:12080/go?group=zzz&action=mybtoa¶m=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¶m={
\"password\": \"123\",
\"username\": \"test\",
\"validCode\": \"p5zk\"
}
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。








评论