Detailed Explanation of JS Reverse Browser Complementary Environment

Detailed Explanation of JS Reverse Browser Complementary Environment

"Supplementing the browser environment " is an essential skill for JS reversers to get promoted and raise their salary, and it is also an inevitable operation in the work.

In order to let everyone fully understand the reason and principle of "replenishing the browser environment ", this article will describe the following four parts:

  1. What is a complementary environment?
  2. Why make up the environment?
  3. How to make up the environment?
  4. Supplementary environment combat
  5. Supplementary environment framework finished source code

One: What is "replenishing the browser environment "?

Browser environment : refers to the runtime environment of JS code in the browser, which includes the objects automatically constructed by V8 (that is, the content of ECMAScript, such as Date, Array), and the operation DOM and BOM passed to V8 by the browser (built-in) Objects (such as document, navigator);
Node environment : a Js runtime environment based on the V8 engine, which includes V8 and its own built-in APIs, such as fs, http, path;

The similarities and differences between the Node environment and the browser environment can be briefly summarized as shown in the figure:
insert image description here

So what we call "replenishing the browser environment " actually complements the environment that the browser has but Node does not, that is, the objects that complement the BOM and DOM;

Two: Why do we need to "make up the browser environment "?

For veterans of reverse engineering, the word "replenishment environment" is not unfamiliar. When we put the "js encryption algorithm code" that we have worked so hard on every time and put it in the browser environment to execute it correctly, we need to replace it Put it into the Node environment for execution, and due to the differences between the Node environment and the browser environment , the results of some JS codes running in the browser will be different from those running in the node, which will affect our final reverse results ;eg:

function decrypt() {
    
    
    document = false;
    var flag = document?true:false;
    if (flag) {
    
    
        return "正确加密"
    } else {
    
    
        return "错误加密";
    }
}

在浏览器环境运行时 flag为true,然后得到正常结果;
在Node环境运行时 flag为false,然后得到错误结果;

Therefore, we need to "replenish the browser environment " so that the encrypted value obtained by running the deducted "js encryption algorithm code" in the Node environment is consistent with the encrypted value obtained by running in the browser environment . That is to say, for this "js encryption algorithm code" , the environment we fill out is consistent with the browser environment .

Three: How to "replenish the browser environment "?

If we want to "replenish the browser environment ", we must first know which browser environment APIs are used in the "js encryption algorithm code" , and then make up for these environments accordingly;

So how do we monitor the use of the "js encryption algorithm code" on the browser environment API?

There is no dispute: use Proxy to monitor the use of browser environment API, and supplement the browser environment

Proxy is a proxy provided by ES6, which is used to create a proxy of an object, so as to realize the interception and customization of basic operations (such as property lookup, assignment, enumeration, function call, etc.). It can proxy any type of object, including native arrays, functions, and even another proxy; it has the ability to recurse nesting dolls! !

That is to say, after we proxy an object, we become its middleman, and any operation of any JS code on it can be intercepted by us! !

# 对navigator对象进行代理,并设置拦截后的操作
var handler = {
    
    set:funcA,get:funcB,deleteProperty:funcC,has:funcD ...};
navigator = new Proxy(navigator,handler);
# 对代理后的navigator进行各种操作都会被拦截并触发对应处理函数
navigator.userAgent 会被拦截并触发 get  funcB
navigator.userAgent = "xx" 会被拦截并触发 set funcA
delete navigator; 会被拦截并触发 deleteProperty funC
"userAgent" in navigator  会被拦截并触发 has funD ...
等等... 任何操作都可以被拦截

Based on the characteristics of Proxy, two supplementary environment ideas are derived:

  1. Recursively nested Proxy to proxy all BOM, DOM objects and their properties of the browser , and then cooperate with the pure V8 environment provided by the node vm2 module , which is equivalent to proxying the entire browser environment object in node, JS code Using any browser environment api can be blocked by us. Then we make up for the intercepted environmental detection points.
  2. Build a supplementary environment framework, use JS to simulate the browser based on the prototype chain to forge and realize various BOM and DOM objects, and then organize these JS to form a pure JS beggar's version browser environment . The pure JS beggar's version of the browser environment we supplement is better Perfect, the closer to the real browser environment, the more js environment detections that can be killed. In the end, it perfectly kills all JS environment detections! ! ;Example: search for "Zhiyuanbuenvironment" at station b

Although the first idea is simple to implement, it is mainly the use of Proxy interceptors, but it has limited environmental monitoring capabilities, and it is difficult to monitor more complex prototype chains, and the upper limit is not high even for secondary development; It is also quite troublesome to hand repair in many environments;
although the second idea is more complicated to implement, the upper limit is extremely high, and it is perfectly compatible with the first idea, and has the potential to grow and kill.

Therefore, the supplementary environment framework in the industry is almost always based on the second idea. First, build a skeleton of the supplementary environment framework, and complete the common browser environment BOM and DOM objects, such as: window, location, Document, navigator, etc., etc., when you are free or When encountering BOM and DOM objects in other browser environments during work, fill them in. The more complete the supplement, the more we can pass through the detection of JS environment .

advantage:

  • The more perfect the supplement is, the more JS environment detection can be passed through . In the end, it perfectly kills all JS environment detections! ! ;
  • One-click operation to output all environmental detection points in the target JS;
  • The generated final code can be directly used in the production environment (can be directly used by nodejs and v8);
  • Bid farewell to metaphysics to supplement the environment, and no longer go to the debugger line by line, which greatly improves work efficiency.
  • Browserless environment debugging can be performed in the Chrome browser.
  • A must for newcomers to overtake on corners

Four: Actual Combat of "Supplementing the Environmental Framework "

Traditional complement environment format:

// 环境头:
window = global;
navigator= {userAgent:"Mozilla/5.0 (Windows NT 1";}
// 扣出来的JS
........
......

The traditional supplementary environment is too simple, not universal enough, and the code organization is chaotic. We'd better organize it as a project:

The overall structure of the Supplementary Environment Framework Project:
Framework

So what steps and considerations are needed to implement such a browser supplementary environment framework?

  • First determine the framework to run the main process, that is, the entry file.
  • The implementation of each BOM and DOM object uses a separate js file, which is easy to locate and maintain.
  • Read these BOM and DOM files according to the priority order of the prototype chain, and stitch them into the entire browser environment.
  • Think about how to implement a BOM and DOM object to make it consistent with the browser; (this is an important factor affecting the upper limit of the framework, and it also includes a lot of repetitive human work)
  • Event processing (helpful for behavior verification codes)
  • Think about how to ensure that all browser environments used in JS can be detected by us; (this is an important factor affecting the upper limit of the framework)
  • How to design and optimize the extensibility and maintainability of the environmental framework project; (very necessary)
    ...
    and some other detailed considerations, our target framework is an easy-to-extensible and maintainable framework that can detect all browser environment APIs in JS Using and implementing common browser environment methods, etc., let us make up the environment later to achieve the kill effect.

If the thinking about the principle and implementation direction is not comprehensive and in-depth, then the upper limit of the implementation framework will be limited, and the probability of metaphysics will be high. I have also experienced a long time of polishing, overthrowing many times, learning from multiple courses, and finally realizing it. This ideal framework.

The following are some specific implementations:
The following is the main process entry skeleton:

var  fs = require('fs');
var catvm2 = require('./CatVm2/catvm2.node.js');

const {
    
    VM,VMScript} = require('vm2'); //看作纯净V8

var catvm2_code = catvm2.GetCode();  //获取所有代码(工具代码、补的所有BOM、DOM对象)
var web_js_code = fs.readFileSync(`${
    
    __dirname}/target/get_b_fz.js`) ; // 获取目标网站js代码
var log_code = "\r\ncatvm.print.getAll();debugger;\r\r";
var all_code = catvm2_code+web_js_code+log_code;
fs.writeFileSync(`${
    
    __dirname}/debugger_bak.js`,all_code);
const script = new VMScript(all_code,`${
    
    __dirname}/debugger.js`); //真实路径,浏览器打开的就是该缓存文件

const vm = new VM(); // new 一个纯净v8环境
debugger
vm.run(script); // 在V8环境中运行调试
debugger

After the skeleton is set up, we need to fill in the corresponding BOM and DOM objects, such as Navigator:
1. First observe the object in the browser environment: Navigator,
whether you can create a new Navigator, if not, throw an exception in its constructor definition, Don't throw it away if you can;

var dsf_tmp_context = catvm.memory.variable.Navigator = {
    
    };
var Navigator = function Navigator() {
    
     // 构造函数
	throw new TypeError("Illegal constructor");
}; catvm.safefunction(Navigator);//13

2. Check Navigator.prototypethe properties, methods, and prototype chain of its prototype, and
find that Navigatorthe properties and methods of the prototype cannot be called through the prototype, and
Navigator.appVersionan exception will be thrown.
It is found that its prototype chain has only one layer, namelyNavigator.prototype.__proto__ === Object.prototype

3. Observe the instance object in the browser environment: navigator
check the difference between its properties, methods and prototype, and find that it is almost the same, basically inheriting the prototype.
So it can be simply added as follows:


Object.defineProperties(Navigator.prototype, {
    
    
    [Symbol.toStringTag]: {
    
    
		value: "Navigator",
	    configurable: true
	}
});
var navigator = {
    
    };
navigator.__proto__ = Navigator.prototype;


Navigator.prototype.plugins = [];
Navigator.prototype.languages = ["zh-CN", "zh"];
Navigator.prototype.userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36';
Navigator.prototype.platform = 'Win32';
Navigator.prototype.maxTouchPoints = 0;
Navigator.prototype.onLine = true;
for (var _prototype in Navigator.prototype) {
    
    
    navigator[_prototype] = Navigator.prototype[_prototype];
    if (typeof (Navigator.prototype[_prototype]) != "function") {
    
    
        Navigator.prototype.__defineGetter__(_prototype, function () {
    
    
            debugger;
            var e = new Error();
            e.name = "TypeError";
            e.message = "Illegal constructor";
            e.stack = "VM988:1 Uncaught TypeError: Illegal invocation \r\n " +
                "at <anonymous>:1:21";
            throw e;
            // throw new TypeError("Illegal constructor");
        });
    }
}

// 加上代理
navigator = catvm.proxy(navigator);


Note: The above example is just a way of supplementing the environment, which is based on the granularity of objects and attributes ; I personally use another way of thinking , based on the fact 对象.属性.特性粒度即Object.getOwnPropertyDescriptor 的value,writable..等that although more codes are needed, the simulation effect is more perfect, and the theoretical upper limit is extremely high.

There are too many browser objects and properties, and it is impossible for us to manually fill in the object properties. Therefore, in order to make up a perfect browser environment, we need to write 浏览器环境自吐脚本. That is, when the script is executed in the browser, it will splice all the properties and methods of a certain browser environment object into the supplementary environment code required by our framework, and we can directly paste it in and modify it slightly.

We can use: Reflect.ownKeys(real_obj)to obtain all the properties and methods of the object,
and then make various judgments and processes on it attr, and finally stitch them into what we need.

var all_attrs = Reflect.ownKeys(real_obj);
var continue_attrs = ["prototype", "constructor"];
for (let index = 0; index < all_attrs.length; index++) {
    
    
    let attr_name = all_attrs[index];
    // 暂时不处理在 continue_attrs 中的属性
    if (continue_attrs.indexOf(attr_name) != -1) {
    
    
        console.log(`遇到 ${
    
    attr_name},跳过`);
        continue
    }
        if (attr_name == Symbol.toStringTag) {
    
    
            result_code = `Object.defineProperties(${
    
    repair_obj}, {
    
    
    [Symbol.toStringTag]: {
    
    
		value: "${real_obj[Symbol.toStringTag]}",
	    configurable: true
	}
});//23\n`;
            symbol_code_ls.push(result_code);
            continue
        }
    }
    ..........太长,略过(下面框架源码中有)

After each browser object is completed, it can be run to compare with the real browser, gradually optimized, and finally achieve a perfect effect.

Five: The source code of the finished product of "Supplementary Environment Framework "

补环境框架It has become a big killer for JS reversers, and it is also the inspection point of many interviewers. We have understood its principle and implementation steps, and then we can try to implement a complete supplementary environment framework from scratch, but it will take a long time to develop, and there are many repetitive tasks that are boring (copy and paste contrast, etc.).

Take the fast lane:

I have been on this road for a long time, and I have made up a lot of environments. If you want to save a lot of time and greatly improve efficiency, if you are direct, you can contact me on WeChat: dengshengfeng666 Paid source code 弯道超车reference ; unified
fixed price 99, send it directly The source code of the framework project (you can get started directly with the readme), and if you have any questions, you can directly ask me.
Or private message me directly on CSDN.

Part of the results display (take the headline sign value as an example):

The monitored detection points, the pretty boys who have done it can see if there are any
Test point printing

Compared with the real browser
Compare with real browser
Overtaking on curves, start from me

Guess you like

Origin blog.csdn.net/qq_36291294/article/details/127699273