登录后更精彩...O(∩_∩)O...
您需要 登录 才可以下载或查看,没有账号?立即注册
×
资源来自网络分享,侵权请告知删除。
如失效,请联系管理

某多多anti_content参数逆向(补环境)
本文章中所有内容仅供学习交流,相关链接做了脱敏处理,若有侵权,请联系我立即删除! 目标网址:https://dinduoduo.com/home/3c 加密参数:anti_content 请求带anti_content字段,结果正常,不带则异常
参数定位 anti_content 全局搜索
只有一处,定位到js文件中该位置,下断点
当t.next = 10 ,anti_content还未产生值 t.t1 = t.sent ,anti_content值已经产生 加密位置显而易见,Object(l.a)()是加密方法体,下断点,跳转到v函数
r.messagePackSync();产生我们需要结果,方法继续下断点
跳转到de函数,函数返回值下断点
加密函数的值是从 n[r("0x1bb", "A3e0")](ue)得到,n[r("0x1bb", "A3e0")]方法,参数传入一个参数,然后执行该参数,即执行ue()函数,即可得到anti_content加密值 拉到文件顶部,发现是一个典型的webpack
而n[r("0x1bb", "A3e0")](ue)是在fbeZ函数内部,而fbeZ又封装一个webpack,ue()函数在第四个模块(角标从0开始)
我们目标函数是在第二层webpack fbeZ内部,我们直接来扣代码,扣之前注意:找到fbeZ调用者,调用时是否传入参数。 文件全局搜索发现只有一处调用
显而易见n是外层的导出器函数,进入函数内部看看,验证正确
在n("fbez")函数内部
跟栈,可以发现调用fbez函数传入的参数:{ serverTime: e } 返回值为r
anti_content的加密值已经出来了
扣webpack 接下来我们扣webpack 代码,webpack打包的代码有明显的特征,很容易识别出来,webpack推荐
运行成功,运行fbez模块用到8oxB,YuTi模块,浏览器找到这两个模块放入pdd_webpack文件中。本地运行发现没有出结果(缺少浏览器环境),去浏览器浏览器运行,成功生成加密参数并可用
补环境 为了更好的体验调试,本次我们不用补环境框架
vm2沙箱介绍 本地js环境联条配置可参考 准备环境做好了,F5运行vm.js 
报错 
定位到浏览器W("0x3f", "LZ%H")该处位置,浏览器环境rt[z]值为document,vm2沙箱环境值为undefined,缺少document导致环境报错 
在enviroment.js文件中把window,document,navigator ,history ,localStorage常检测的环境先补上,再挂上代理 

rename,savefunction方法作用 没有使用rename,savefunction方法之前 
使用rename,savefunction方法之后,使其和浏览器结果一致 
运行vm.js,日志报错,输出日志信息 
我们将属性值为undefined对照浏览器补齐,如果浏览器的属性值为也为null可直接忽略 

补完之后出结果,可用 
 代码提供
[JavaScript] 纯文本查看 复制代码 // vm.js代码
var vm= require("vm2")
var fs = require('fs')
const {VM,VMScript} = vm
var vm = new VM()
var code = fs.readFileSync('./enviroment.js')
code += fs.readFileSync('./pdd.js')
const script = new VMScript(code, `sy_debugging.js`);
vm.run(script)
debugger;;
// function get_encrypt(){
// var res = vm.run(code)
// return res
// }
// debugger;
// console.log(get_encrypt());
[JavaScript] 纯文本查看 复制代码 //enviroment.js 补环境代码
debugger;;
catvm = {}
catvm.memory = {log:[]};
// 保护伪造函数toString
;(() => {
const $toString = Function.toString
const myFunction_toString_symbol = Symbol('('.concat('', ')_', (Math.random()) + '').toString(36))
const myToString = function (){
return typeof this === 'function' && this[myFunction_toString_symbol] || $toString.call(this)
}
function set_native(func, key, value){
Object.defineProperty(func, key, {
enumerable: false,
configurable: true,
writable: true,
value: value
})
}
delete Function.prototype.toString
set_native(Function.prototype, "toString", myToString)
set_native(Function.prototype.toString, myFunction_toString_symbol, "function toString() { [native code] }")
this.catvm.savefunction = (func, funcname) => {
//todo 系统函数没名字 native code
set_native(func, myFunction_toString_symbol, `function ${func.name || funcname || ''}() { [native code] }`)
}
}).call(this)
//代理
catvm.proxy = function (obj) {
// Proxy 可以多层代理,即 a = new proxy(a); a = new proxy(a);第二次代理
// 后代理的检测不到先代理的
return new Proxy(obj, {
set(target, property, value) {
catvm.memory.log.push({"类型":"set-->","调用者":target,"调用属性":property,"设置值":value});
console.table([{"类型":"set-->","调用者":target,"调用属性":property,"设置值":value}]);
return Reflect.set(...arguments); //这是一种反射语句,这种不会产生死循环问题
},
get(target, property, receiver) {
if(target.name!=='toString' && property !=='Math' && property !== 'isNaN' && property !=='undefined'){
catvm.memory.log.push({"类型":"get<--","调用者":target,"调用属性":property,"获取值":target[property]});
console.table([{"类型":"get<--","调用者":target,"调用属性":property,"获取值":target[property]}]);
}
return target[property]; // target中访问属性不会再被proxy拦截,所以不会死循环
}
});
};
//定义原型名称
catvm.rename = function rename(obj,proValue)
{
//定义原型名称
Object.defineProperties(obj,{
[Symbol.toStringTag]:{
value:proValue,
configurable:true
}
});
}
delete global;
delete Buffer;
window = globalThis;
window.outerHeight = 1080;
window.chrome = catvm.proxy({})
setTimeout = function setTimeout(){console.log(arguments)}
var Window = function Window(){};
Object.setPrototypeOf(window,Window.prototype);
catvm.rename(Window.prototype,'Window');
catvm.savefunction(Window)
var HTMLDocument = function HTMLDocument(){};
document = {
cookie:'_nano_fp=XpmaXqdaXqdbXqXJXo_ShM7Br8OTCzqBDo6OVbYc',
referrer:'https://xxx.com/home/3c',
getElementById:function getElementById(){
console.log(arguments);
},
addEventListener:function addEventListener(){
console.log(arguments);
}
};
Object.setPrototypeOf(document,HTMLDocument.prototype);
catvm.rename(HTMLDocument.prototype,'HTMLDocument');
catvm.savefunction(HTMLDocument)
var Location = function Location(){};
location = {
href:'https://xxx.com/home/3c',
port:'',
};
Object.setPrototypeOf(location,Location.prototype);
catvm.rename(Location.prototype,'Location');
catvm.savefunction(Location)
var Navigator = function Navigator(){};
navigator = {
plugins:[],//插件直接补为空列表就ok,有的浏览器可能就是没有插件
languages:['zh-CN', 'zh'],
userAgent:'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36',
};
Object.setPrototypeOf(navigator,Navigator.prototype);
catvm.rename(Navigator.prototype,'Navigator')
catvm.savefunction(Navigator)
var History = function History(){};
history = {
back:function back(){
console.log(arguments);
}
};
Object.setPrototypeOf(history,History.prototype);
catvm.rename(History.prototype,'History')
catvm.savefunction(History)
var Storage = function Storage(){};
localStorage = {
getItem:function getItem(){
console.log(arguments)
}
};
Object.setPrototypeOf(localStorage,Storage.prototype);
catvm.rename(Storage.prototype,'Storage')
catvm.savefunction(Storage)
var Screen = function Screen(){};
screen = {
availHeight:1080,
};
Object.setPrototypeOf(screen,Screen.prototype);
catvm.rename(Screen.prototype,'Screen')
catvm.savefunction(Screen)
window = catvm.proxy(window)
document = catvm.proxy(document)
location = catvm.proxy(location)
navigator = catvm.proxy(navigator)
history = catvm.proxy(history)
localStorage = catvm.proxy(localStorage)
screen = catvm.proxy(screen)
结语拼多多补环境比较简单,这样补的环境并不完善,仅仅是针对pdd网站,可以搭建一个补环境框架逐步向框架里面添加浏览器环境,补的环境越多越完善,通杀的网站越多
from: https://blog.csdn.net/m0_38098782/article/details/138271203
|