某某航空 同盾 blackbox 补环境
文章目录
- 概要
- 整体架构流程
- 技术细节
- 小结
概要
提示:仅供学习,不得用做商业交易,如有侵权请及时联系
逆向:某某航空 同盾 blackbox 补环境
URL:aHR0cHM6Ly9wYXNzcG9ydC5qdW5leWFvYWlyLmNvbS8=
目标:blackbox参数
整体架构流程
提示:分析流程
1、登录接口:blackbox值
验证码为鸡眼3
2、通过堆栈找到该值生成的地方:
进一步搜索该值生成的地方:
3、断住该位置,重新初始化加载(刷新页面):
该接口加载返回:url:aHR0cHM6Ly9mcC50b25nZHVuLm5ldC93ZWIzXzgvcHJvZmlsZS5qc29u
js:fm.js文件生成
4、补环境:
- 挂代理,补环境
dtavm = {}
dtavm.log = console.log
function proxy(obj, objname, type) {
function getMethodHandler(WatchName, target_obj) {
let methodhandler = {
apply(target, thisArg, argArray) {
if (this.target_obj) {
thisArg = this.target_obj
}
let result = Reflect.apply(target, thisArg, argArray)
if (target.name !== "toString") {
if (target.name === "addEventListener") {
dtavm.log(`调用者 => [${WatchName}] 函数名 => [${target.name}], 传参 => [${argArray[0]}], 结果 => [${result}].`)
} else if (WatchName === "window.console") {
} else {
dtavm.log(`调用者 => [${WatchName}] 函数名 => [${target.name}], 传参 => [${argArray}], 结果 => [${result}].`)
}
} else {
dtavm.log(`调用者 => [${WatchName}] 函数名 => [${target.name}], 传参 => [${argArray}], 结果 => [${result}].`)
}
return result
},
construct(target, argArray, newTarget) {
var result = Reflect.construct(target, argArray, newTarget)
dtavm.log(`调用者 => [${WatchName}] 构造函数名 => [${target.name}], 传参 => [${argArray}], 结果 => [${(result)}].`)
return result;
}
}
methodhandler.target_obj = target_obj
return methodhandler
}
function getObjhandler(WatchName) {
let handler = {
get(target, propKey, receiver) {
let result = target[propKey]
if (result instanceof Object) {
if (typeof result === "function") {
dtavm.log(`调用者 => [${WatchName}] 获取属性名 => [${propKey}] , 是个函数`)
return new Proxy(result, getMethodHandler(WatchName, target))
} else {
dtavm.log(`调用者 => [${WatchName}] 获取属性名 => [${propKey}], 结果 => [${(result)}]`);
if (`${propKey}` === 'top') {
return window
}
if (`${propKey}` === 'self') {
return self
}
}
return new Proxy(result, getObjhandler(`${WatchName}.${propKey}`))
}
if (typeof (propKey) !== "symbol") {
dtavm.log(`调用者 => [${WatchName}] 获取属性名 => [${propKey?.description ?? propKey}], 结果 => [${result}]`);
}
return result;
},
set(target, propKey, value, receiver) {
if (value instanceof Object) {
dtavm.log(`调用者 => [${WatchName}] 设置属性名 => [${propKey}], 值为 => [${(value)}]`);
} else {
dtavm.log(`调用者 => [${WatchName}] 设置属性名 => [${propKey}], 值为 => [${value}]`);
}
return Reflect.set(target, propKey, value, receiver);
},
has(target, propKey) {
var result = Reflect.has(target, propKey);
dtavm.log(`针对in操作符的代理has=> [${WatchName}] 有无属性名 => [${propKey}], 结果 => [${result}]`)
return result;
},
deleteProperty(target, propKey) {
var result = Reflect.deleteProperty(target, propKey);
dtavm.log(`拦截属性delete => [${WatchName}] 删除属性名 => [${propKey}], 结果 => [${result}]`)
return result;
},
defineProperty(target, propKey, attributes) {
var result = Reflect.defineProperty(target, propKey, attributes);
dtavm.log(`拦截对象define操作 => [${WatchName}] 待检索属性名 => [${propKey.toString()}] 属性描述 => [${(attributes)}], 结果 => [${result}]`)
// debugger
return result
},
getPrototypeOf(target) {
var result = Reflect.getPrototypeOf(target)
dtavm.log(`被代理的目标对象 => [${WatchName}] 代理结果 => [${(result)}]`)
return result;
},
setPrototypeOf(target, proto) {
dtavm.log(`被拦截的目标对象 => [${WatchName}] 对象新原型==> [${(proto)}]`)
return Reflect.setPrototypeOf(target, proto);
},
preventcExtensions(target) {
dtavm.log(`方法用于设置preventcExtensions => [${WatchName}] 防止扩展`)
return Reflect.preventcExtensions(target);
},
isExtensible(target) {
var result = Reflect.isExtensible(target)
dtavm.log(`拦截对对象的isExtensible() => [${WatchName}] isExtensible, 返回值==> [${result}]`)
return result;
},
}
return handler;
}
if (type === "method") {
return new Proxy(obj, getMethodHandler(objname, obj));
}
return new Proxy(obj, getObjhandler(objname));
}
- 提前加载的window属性:_fmOpt
window._fmOpt = {
partner: 'jxhk',
appName: 'jxhk_web',
token: 'jxhk' + "-" + new Date().getTime() + "-" + Math.random().toString(16).substr(2),
fmb: true,
success: function (data) {
_blackbox = data
},
fpHost: "https://fp.xxx.net"
};
3.接口生成的地方:document.createElement会创建一个script标签,然后赋值src链接,最后得到刚刚我们看到的接口并响应得到
_1743586336088_9724({
"code": "000",
"result": {
"tokenId": "xxx",
"xxid": "xx/xxx+8nEJGtj+fM4QZmvqCvcMiy/EdGYN4=",
"xdid": "xx",
"bxid": "MfgjSjjxV//xx==",
"c": {
"factor": 0,
"op": 0,
"cm": 0,
"vt": 604800
}
},
"desc": ""
})
4._1743586336088_9724这个在fm文件中已经被重写成了一个方法,最后允许该方法生成blackbox
//script创建的标签
Object.defineProperty(script, 'src', {
set: function (value) {
if (value != undefined) {
fetch(value).then(function (response) {
return response.text();
}).then(function (text) {
console.log('profile.json响应结果:',text)
eval(text);
})
}
}
})
5.eval执行之后在window._fmOpt.success得到我们需要的_blackbox
技术细节
提示:结果
最后,看结果吧!
这里说一下,作者最近开了星球,主要以补环境为主,欢迎各位的加入,咱们一起学习交流~
小结
提示:学习交流+v看主页(可加知识星球)