一.简介
1. 瑞数
瑞数动态安全 Botgate(机器人防火墙)以“动态安全”技术为核心,通过动态封装、动态验证、动态混淆、动态令牌等技术对服务器网页底层代码持续动态变换,增加服务器行为的“不可预测性”,实现了从用户端到服务器端的全方位“主动防护”,为各类 Web、HTML5 提供强大的安全保护。
2. 瑞数执行流程分析
我们在做逆向的时候,首先得分析出哪些加密参数
是需要逆向的,然后再是去逆向这些参数。当然瑞数也是一样。
所以我们第一步就是明确逆向的目标
:
- 现象:上了rs的网站会请求两次page_url,第二次请求page_url时才能得到正确的页面内容;
- 分析:分析其请求体,发现第二次请求page_url时带上了cookie_s和cookie_t, 而cookies_s是来自第一次请求page_url时其响应头set的;
3.执行流程
这里我们需要关注eval调用
的位置(也就是VM的入口
),cookie生成的位置。
注:浏览器
v8
调用eval
执行代码时会开启一个虚拟机(VM
+数字)去执行JavaScript代码。
二.瑞数4
1. 逆向目标
- 网址:http://www.fangdi.com.cn/index.html
- 逆向参数:
FSSBBIl1UgzbN7N80T
2. 瑞数4特点
- debugger: 两次
- key名字:
FSSBBIl1UgzbN7N80T
是js代码生成,FSSBBIl1UgzbN7N80S
是服务器返回
3. 逆向分析
- 过无限debugger
var _constructor = constructor;
Function.prototype.constructor = function(s) {
if (s == "debugger") {
console.log(s);
return null;
}
return _constructor(s);
}
//去除无限debugger
Function.prototype.__constructor_back = Function.prototype.constructor ;
Function.prototype.constructor = function() {
if(arguments && typeof arguments[0]==='string'){
//alert("new function: "+ arguments[0]);
if( "debugger" === arguments[0]){
// arguments[0]="consoLe.Log(\"anti debugger\");";
//arguments[0]=";";
return
}
}
return Function.prototype.__constructor_back.apply(this,arguments);
};
var _Function = Function;
Function = function(s) {
if (s == "debugger") {
console.log(s);
return null;
}
return _Function(s);
}
- hook对应cookie生成的位置
(function () {
// 严谨模式 检查所有错误
'use strict';
// document 为要hook的对象 这里是hook的cookie
var cookieTemp = "";
Object.defineProperty(document, 'cookie', {
// hook set方法也就是赋值的方法
set: function (val) {
// 这样就可以快速给下面这个代码行下断点
// 从而快速定位设置cookie的代码
if (val.indexOf('FSSBBIl1UgzbN7N80T') != -1) {
debugger;
}
console.log('Hook捕获到cookie设置->', val);
cookieTemp = val;
return val;
}, // hook get 方法也就是取值的方法
get: function () {
return cookieTemp;
}
});
})();
- 可以看到cookie的生成位置,
- 是有
$FG
函数调用生成的,执行的代码是在vm
文件当中 vm
文件在瑞数当中都是通过eval
生成的,可以网上找到他执行eval
的位置
- 往下面的栈进行查找可以找到入口文件
- 这个文件就是瑞数第一次请求返回412状态码的页面
- 那我们就需要把这个页面的代码拿下来我们自己执行,获取的方法是一个自执行方法
- 需要把这个文件的外链js代码也拿过来,一般是一个ts数据的js文件
- 要进外链js文件的话,需要通过抓包工具的脚本功能
- 那下来之后我们就可以补环境了
4.逆向结果
- JavaScript代码
// 检测当前执行的文件是哪一个
delete __dirname
delete __filename
content = "content_data"
function get_enviroment(proxy_array) {
for (var i = 0; i < proxy_array.length; i++) {
handler = '{\n' +
' get: function(target, property, receiver) {\n' +
' console.log("方法:", "get ", "对象:", ' +
'"' + proxy_array[i] + '" ,' +
'" 属性:", property, ' +
'" 属性类型:", ' + 'typeof property, ' +
// '" 属性值:", ' + 'target[property], ' +
'" 属性值类型:", typeof target[property]);\n' +
' return target[property];\n' +
' },\n' +
' set: function(target, property, value, receiver) {\n' +
' console.log("方法:", "set ", "对象:", ' +
'"' + proxy_array[i] + '" ,' +
'" 属性:", property, ' +
'" 属性类型:", ' + 'typeof property, ' +
// '" 属性值:", ' + 'target[property], ' +
'" 属性值类型:", typeof target[property]);\n' +
' return Reflect.set(...arguments);\n' +
' }\n' +
'}'
eval('try{\n' + proxy_array[i] + ';\n'
+ proxy_array[i] + '=new Proxy(' + proxy_array[i] + ', ' + handler + ')}catch (e) {\n' + proxy_array[i] + '={};\n'
+ proxy_array[i] + '=new Proxy(' + pr