JS逆向之浏览器补环境(一)
简介
今天分享是是浏览器环境检测以及node js补环境
我们点击检测设备信息看发出的请求,可以看到是sign和data
这个data看起来像base64,我们试一下,发现不是
分析加密位置
可以看到经过混淆了
我们选中看一下
那我们接下来就知道了,要逆向的两个参数变量
_0x392f2d
_0xd9e63f
我们直接把整个文件拷贝到webstrom里,看一下这两个变量在哪里定义的,可以看到在这
由于我们只需要这两个变量,所以下面的代码可以删除了,变成这样
追踪检测
然后引入proxy检测对象变化的代码
proxy.js
let _window = {
};
let _stringify = JSON.stringify;
JSON.stringify = function (Object) {
// ?? 的意思是,如果 ?? 左边的值是 null 或者 undefined,那么就返回右边的值。
if ((Object?.value ?? Object) === global) {
return "global";
}
return _stringify(Object);
};
function getMethodHandler(WatchName) {
let methodhandler = {
apply(target, thisArg, argArray) {
let result = Reflect.apply(target, thisArg, argArray);
console.log(`[${WatchName}] apply function name is [${target.name}], argArray is [${argArray}], result is [${result}].`);
return result;
},
construct(target, argArray, newTarget) {
let result = Reflect.construct(target, argArray, newTarget);
console.log(`[${WatchName}] construct function name is [${target.name}], argArray is [${argArray}], result is [${JSON.stringify(result)}].`);
return result;
}
};
return methodhandler;
}
function getObjHandler(WatchName) {
let handler = {
get(target, propKey, receiver) {
let result = Reflect.get(target, propKey, receiver);
if (result instanceof Object) {
if (typeof result === "function") {
console.log(`[${WatchName}] getting propKey is [${propKey}] , it is function`);
//return new Proxy(result,getMethodHandler(WatchName))
} else {
console.log(`[${WatchName}] getting propKey is [${propKey}], result is [${JSON.stringify(result)}]`);
}
return new Proxy(result, getObjHandler(`${WatchName}.${propKey}`));
}
console.log(`[${WatchName}] getting propKey is [${propKey}], result is [${result}]`);
return result;
},
set(target, propKey, value, receiver) {
if (value instanceof Object) {
console.log(`[${WatchName}] setting propKey is [${propKey}], value is [${JSON.stringify(value)}]`);
} else {
console.log(`[${WatchName}] setting propKey is [${propKey}], value is [${value}]`);
}
return Reflect.set(target, propKey, value, receiver);
},
has(target, propKey) {
let result = Reflect.has(target, propKey);
console.log(`[${WatchName}] has propKey [${propKey}], result is [${result}]`);
return result;
},
deleteProperty(target, propKey) {
let result = Reflect.deleteProperty(target, propKey);
console.log(`[${WatchName}] delete propKey [${propKey}], result is [${result}]`);
return result;
},
getOwnPropertyDescriptor(target, propKey) {
let result = Reflect.getOwnPropertyDescriptor(target, propKey);
console.log(`[${WatchName}] getOwnPropertyDescriptor propKey [${propKey}] result is [${JSON.stringify(result)}]`);
return result;
},
defineProperty(target, propKey, attributes) {
let result = Reflect.defineProperty(target, propKey, attributes);
console.log(`[${WatchName}] defineProperty propKey [${propKey}] attributes is [${JSON.stringify(attributes)}], result is [${result}]`);
return result;
},
getPrototypeOf(target) {
let result = Reflect.getPrototypeOf(target);
console.log(`[${WatchName}] getPrototypeOf result is [${JSON.stringify(result)}]`);
return result;
},
setPrototypeOf(target, proto) {
console.log(`[${WatchName}] setPrototypeOf proto is [${JSON.stringify(proto)}]`);
return Reflect.setPrototypeOf(target, proto);
},
preventExtensions(target) {
console.log(`[${WatchName}] preventExtensions`);
return Reflect.preventExtensions(target);
},
isExtensible(target) {
let result = Reflect.isExtensible(target);
console.log(`[${WatchName}] isExtensible, result is [${result}]`);
return result;
},
ownKeys(target) {
let result = Reflect.ownKeys(target);
console.log(`[${WatchName}] invoke ownKeys, result is [${JSON.stringify(result)}]`);
return result;
},
apply(target, thisArg, argArray) {
let result = Reflect.apply(target, thisArg, argArray);
console.log(`[${WatchName}] apply function name is [${target.name}], argArray is [${argArray}], result is [${result}].`);
return result;
},
construct(target, argArray, newTarget) {
let result = Reflect.construct(target, argArray, newTarget);
console.log(`[${WatchName}] construct function name is [${target.name}], argArray is [${argArray}], result is [${JSON.stringify(result)}].`);
return result;
}
};
return handler;
}
_window = Object.assign(global, _window);
const window = new Proxy(Object.create(_window), getObjHandler("window"));
module.exports = {
window
};
在拷贝到webstrom里的代码进行导入
const {window} = require("../tools/proxy");
然后我们运行之前拷贝到webstrom里的代码
发现在window上需要定义一个XMLHttpRequest,那是定义在window上呢,还是定义在它的原型链上呢,我们可以浏览器里看一下
第一个是检查对象自身的属性,第二是检查所有属性。因此我们需要定义在它的原型上
修改追踪的代码
然后我们打印看一下,发现也没有问题
我们再运行以下之前的代码,发现需要navigator
那我们也补上
let _window = {
XMLHttpRequest: function (){},
};
let _navigator = {
};
_window = Object.assign(global, _window);
const window = new Proxy(Object.create(_window), getObjHandler("window"));
const navigator = new Proxy(Object.create(_navigator), getObjHandler("navigator"));
module.exports = {
window,
navigator,
};
然后又要这个,同理
发现没有问题了,也拿到了sign和data
python调用
然后我们通过python试一下
然后到在线工具里转一下
https://tool.lu/curl/
发现直接被检测到了,就是我们的环境检测没有通过
补环境
我们可以看到有一堆undefined,这些都是我们需要补的环境
然后我们要看一下这个值在浏览器里是怎么样的,并且是定义在对象上还是原型上,比如navigator来说,发现是定义在原型上的。
然后就照着补就行了
注意这个,getOwnPropertyDescriptor是拿的自身属性上的
最后补的结果
let _window = {
XMLHttpRequest: function (){},
sessionStorage: function (){},
localStorage: function (){},
};
let _navigator = {
userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36 Edg/99.0.1150.39",
appCodeName: "Mozilla",
plugins: {
length: 0
},
};
let _screen = {
colorDepth: 24,
height: 900,
width: 1440,
};
_window = Object.assign(global, _window);
const window = new Proxy(Object.create(_window), getObjHandler("window"));
const navigator = new Proxy(Object.create(_navigator), getObjHandler("navigator"));
const screen = new Proxy(Object.create(_screen), getObjHandler("screen"));
module.exports = {
window,
navigator,
screen,
};
再跑一次,拿着data和sign去请求,通过!
另一种操作(不推荐)
使用JSDOM自带的浏览器环境
安装
npm install jsdom
使用
const jsdom = require("jsdom");
const {JSDOM} = jsdom;
const {window} = new JSDOM(``);
const navigator = window.navigator;
const screen = window.screen;
// 这个是缺啥补啥 基本都齐了
window.XMLHttpRequest = function XMLHttpRequest() {
};
module.exports = {
window,
navigator,
screen
};
导入
但是会出现各式各样的问题,不推荐
先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦