v_jstools
常用在分析js的算法的时候的一个非常好用的工具 他可以根据程序的循序和加密的数据帮你分析 js加密算法的位置
演示的web
http://39.98.108.20:8085/#/login
先进行逆向分析
登录抓包发现一登录的数据包不是账号密码分开的而是一长串的加密 这个和之前做的 那个 param 参数传递 passwd的项目非常相似 所以我们猜测这个 加密的其实就是 json数据
手搓算法还是太麻烦了 我们直接使用 插件
基本配置 除了js算法 他还能使用基本的ast 进行反混淆代码
演示 :
控制台出现这个表示插件在启动
登录查看插件的提示
在函数的最下面进行打断点
发现这个 l() 函数可能就是加密的函数
点进去
AES加密这一块的
密钥和偏移量都是 一样的 直接解密测试一下
工具解码果然啊 是json数据 换个账号密码 再次测试
项目二 autoDecoder
burp自带的插件 他的作用就是模拟 js加密文件的逻辑 然后对数据包进行解包为明文 以便于我们进行 明文爆破非常的方便
项目三 jsrpc
原始的js逆向 就是进行扣代码,补环境 但是有时候会出现一个问题 就是 嵌套引用 环境越补越多 这个 rpc 就是远程的调用 进行远程加载浏览器的控制台 然后使用浏览器中的加载的环境
使用方法 : 直接使用对方编译好的程序
来到这个目录下 然后复制这个 dev文件内的内容
懒得看的直接复制
var rpc_client_id, Hlclient = function (wsURL) {
this.wsURL = wsURL;
this.handlers = {
_execjs: function (resolve, param) {
var res = eval(param)
if (!res) {
resolve("没有返回值")
} else {
resolve(res)
}
}
};
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.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;
return true
}
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"]) {
theHandler(function (response) {
_this.sendResult(action, message_id, response);
})
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)//不是json无需操作
}
}
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=xiaodi");
我们其实可以使用 py 脚本去远程访问 现在的情况其实就是 对方的控制台在我们的手中
写一个简单的联动脚本
运行 控制台回显 那可不可以使用这个 让我们直接拿到对方的 l() 这个函数的逻辑呢
其实是不行的因为 l 这个函数只会在 被调用的时候出现 所以我们rpc 也是不能调用的
可能说打个断点就行了 断点我们的爬虫也无法访问了 实际上也是不行的
我们只能进行本地模拟这个算法然后再 进行访问了 :
看一下浏览器 :
脚本 :
import requests
js = '''
// 创建Promise封装库加载过程
function loadCryptoJS() {
return new Promise((resolve, reject) => {
// 如果已存在则直接返回
if (typeof CryptoJS !== 'undefined') return resolve();
// 异步加载库
const script = document.createElement('script');
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js';
script.onload = () => resolve();
script.onerror = (e) => reject(e);
document.head.appendChild(script);
});
}
// 主执行函数
async function main() {
await loadCryptoJS();
// 定义密钥和初始向量
const f = CryptoJS.enc.Utf8.parse("1234567891234567");
const h = CryptoJS.enc.Utf8.parse("1234567891234567");
// 定义加密函数
function l(t) {
const encrypted = CryptoJS.AES.encrypt(t, f, {
iv: h,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return encrypted.toString();
}
// 执行加密并返回结果
const ciphertext = l("hello world");
return ciphertext; // 直接返回加密结果
}
// 执行并输出结果
main().then(result => console.log(result));
'''
url = "http://localhost:12080/execjs"
data = {"group": "xiaodi", "code": js}
res = requests.post(url, data=data)
print("加密结果:", res.text)
这一块的我们把 hello 换一下 换为测试数据 {"password":123456,"username":"123","validCode":"tj8y"}
因为这个信息有些符号是需要转义的 我们使用 `` 进行包裹就行了
真实登录 :
拿下了 这个的主要作用还是配合 burp在脚本中配置上代理 中专之后这个明文我们是可以随便进行修改的 这个就类似于上面的爆破了