Explication détaillée de l'environnement complémentaire du navigateur inversé JS

Explication détaillée de l'environnement complémentaire du navigateur inversé JS

"Compléter l'environnement du navigateur " est une compétence essentielle pour les inverseurs JS pour obtenir une promotion et augmenter leur salaire, et c'est aussi une opération inévitable dans le travail.

Afin de permettre à chacun de bien comprendre la raison et le principe de « reconstituer l'environnement du navigateur », cet article décrira les quatre parties suivantes :

  1. Qu'est-ce qu'un environnement complémentaire ?
  2. Pourquoi maquiller l'environnement ?
  3. Comment composer l'environnement?
  4. Combat environnemental supplémentaire
  5. Code source fini du framework d'environnement supplémentaire

Un : Qu'est-ce que "réapprovisionner l'environnement du navigateur " ?

Environnement du navigateur : fait référence à l'environnement d'exécution du code JS dans le navigateur, qui comprend les objets construits automatiquement par la V8 (c'est-à-dire le contenu d'ECMAScript, comme Date, Array), et l'opération DOM et BOM passée à la V8 par le navigateur (intégré) Objets (tels que document, navigateur)
 Environnement de nœud : un environnement d'exécution Js basé sur le moteur V8, qui inclut V8 et ses propres API intégrées, telles que fs, http, path ;

Les similitudes et les différences entre l'environnement Node et l'environnement du navigateur peuvent être brièvement résumées comme indiqué dans la figure :
insérez la description de l'image ici

Ainsi, ce que nous appelons "réapprovisionner l'environnement du navigateur " complète en fait l'environnement dont dispose le navigateur, mais pas Node, c'est-à-dire les objets qui complètent le BOM et le DOM ;

Deux : Pourquoi avons-nous besoin de « créer l'environnement du navigateur » ?

Pour les vétérans de l'ingénierie inverse, le mot "environnement de réapprovisionnement" n'est pas inconnu. Lorsque nous mettons le "code d'algorithme de chiffrement js" sur lequel nous avons travaillé si dur à chaque fois et que nous le mettons dans l'environnement du navigateur pour l'exécuter correctement, nous devons remplacez-le Mettez-le dans l'environnement Node pour l'exécution, et en raison des différences entre l'environnement Node et l'environnement du navigateur , les résultats de certains codes JS exécutés dans le navigateur seront différents de ceux exécutés dans le nœud, ce qui affectera notre final inverser les résultats ; par exemple :

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

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

Par conséquent, nous devons "réapprovisionner l'environnement du navigateur " afin que la valeur cryptée obtenue en exécutant le "code d'algorithme de cryptage js" déduit dans l'environnement Node soit cohérente avec la valeur cryptée obtenue en s'exécutant dans l'environnement du navigateur . C'est-à-dire que pour ce "code d'algorithme de chiffrement js" , l'environnement que nous remplissons est cohérent avec l'environnement du navigateur .

Trois : Comment « reconstituer l'environnement du navigateur » ?

Si nous voulons "réapprovisionner l'environnement du navigateur ", nous devons d'abord savoir quelles API d'environnement de navigateur sont utilisées dans le "code de l'algorithme de chiffrement js" , puis compenser ces environnements en conséquence ;

Alors, comment surveillons-nous l'utilisation du "code de l'algorithme de chiffrement js" sur l'API de l'environnement du navigateur ?

Il n'y a pas de contestation : utilisez Proxy pour surveiller l'utilisation de l'API de l'environnement du navigateur et complétez l'environnement du navigateur »

Proxy est un proxy fourni par ES6, qui est utilisé pour créer un proxy d'un objet, afin de réaliser l'interception et la personnalisation des opérations de base (telles que la recherche de propriété, l'affectation, l'énumération, l'appel de fonction, etc.). Il peut proxy n'importe quel type d'objet, y compris les tableaux natifs, les fonctions et même un autre proxy ; il a la capacité de récurser les poupées imbriquées ! !

C'est-à-dire qu'après avoir mandaté un objet, nous devenons son intermédiaire, et toute opération de n'importe quel code JS sur celui-ci peut être interceptée par nous ! !

# 对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 ...
等等... 任何操作都可以被拦截

Sur la base des caractéristiques de Proxy, deux idées d'environnement supplémentaires sont dérivées :

  1. Proxy imbriqué de manière récursive pour proxy tous les objets BOM, DOM et leurs propriétés du navigateur , puis coopérer avec l'environnement V8 pur fourni par le module node vm2 , ce qui équivaut à proxy l'intégralité de l'objet d'environnement du navigateur dans le nœud, le code JS Utilisation de n'importe quel navigateur environnement api peut être bloqué par nous. Ensuite, nous rattrapons les points de détection environnementaux interceptés.
  2. Construisez un cadre d'environnement supplémentaire, utilisez JS pour simuler le navigateur en vous basant sur la chaîne de prototypes pour forger et réaliser divers objets BOM et DOM, puis organisez ces JS pour former un environnement de navigateur version pure JS mendiant . l'environnement que nous complétons est meilleur Parfait, plus il est proche de l'environnement réel du navigateur, plus il peut tuer de détections d'environnement js. Au final, il tue parfaitement toutes les détections d'environnement JS ! ! ;Exemple : rechercher "Zhiyuanbuenvironment" à la station b

Bien que la première idée soit simple à mettre en œuvre, il s'agit principalement de l'utilisation d'intercepteurs Proxy, mais elle a des capacités de surveillance environnementale limitées, et il est difficile de surveiller des chaînes de prototypes plus complexes, et la limite supérieure n'est pas élevée même pour le développement secondaire ; Il est également assez difficile à réparer à la main dans de nombreux environnements ;
bien que la deuxième idée soit plus compliquée à mettre en œuvre, la limite supérieure est extrêmement élevée, et elle est parfaitement compatible avec la première idée, et a le potentiel de croître et de tuer.

Par conséquent, le cadre d'environnement supplémentaire dans l'industrie est presque toujours basé sur la deuxième idée. Tout d'abord, construisez un squelette du cadre d'environnement supplémentaire et complétez les objets BOM et DOM de l'environnement de navigateur commun, tels que : fenêtre, emplacement, document, navigateur , etc., etc., lorsque vous êtes libre ou Lorsque vous rencontrez des objets BOM et DOM dans d'autres environnements de navigateur pendant le travail, remplissez-les. Plus le complément est complet, plus on peut passer par la détection d'environnement JS .

avantage:

  • Plus le supplément est parfait, plus la détection d'environnement JS peut être transmise . Au final, il tue parfaitement toutes les détections d'environnement JS ! ! ;
  • Opération en un clic pour générer tous les points de détection environnementaux dans le JS cible ;
  • Le code final généré peut être directement utilisé dans l'environnement de production (peut être directement utilisé par nodejs et v8) ;
  • Dites adieu à la métaphysique pour compléter l'environnement, et ne passez plus au débogueur ligne par ligne, ce qui améliore grandement l'efficacité du travail.
  • Le débogage de l'environnement sans navigateur peut être effectué dans le navigateur Chrome.
  • Un must pour les nouveaux venus pour dépasser dans les virages

Quatrième : Combat réel de "compléter le cadre environnemental "

Format d'environnement de complément traditionnel :

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

L'environnement complémentaire traditionnel est trop simple, pas assez universel, et l'organisation du code est chaotique, mieux vaut l'organiser en projet :

La structure globale du projet de cadre environnemental supplémentaire :
Cadre

Alors, quelles étapes et considérations sont nécessaires pour implémenter un tel cadre d'environnement supplémentaire de navigateur ?

  • Déterminez d'abord le cadre pour exécuter le processus principal, c'est-à-dire le fichier d'entrée.
  • L'implémentation de chaque objet BOM et DOM utilise un fichier js distinct, facile à localiser et à gérer.
  • Lisez ces fichiers BOM et DOM selon l'ordre de priorité de la chaîne de prototypes et assemblez-les dans l'ensemble de l'environnement du navigateur.
  • Réfléchissez à la façon d'implémenter un objet BOM et DOM pour le rendre cohérent avec le navigateur ; (c'est un facteur important affectant la limite supérieure du cadre, et cela inclut également beaucoup de travail humain répétitif)
  • Traitement des événements (utile pour les codes de vérification de comportement)
  • Réfléchissez à la manière de vous assurer que tous les environnements de navigateur utilisés dans JS peuvent être détectés par nous ; (il s'agit d'un facteur important affectant la limite supérieure du cadre)
  • Comment concevoir et optimiser l'extensibilité et la maintenabilité du projet de cadre environnemental ; (très nécessaire)
    ...
    et quelques autres considérations détaillées, notre cadre cible est un cadre facile à étendre et à maintenir qui peut détecter toutes les API d'environnement de navigateur dans JS En utilisant et en implémentant des méthodes d'environnement de navigateur courantes, etc., créons l'environnement plus tard pour obtenir l'effet kill.

Si la réflexion sur le principe et la direction de mise en œuvre n'est pas complète et approfondie, alors la limite supérieure du cadre de mise en œuvre sera limitée et la probabilité de métaphysique sera élevée. J'ai également vécu une longue période de polissage, renversant de nombreux fois, apprendre de plusieurs cours, et enfin le réaliser.Ce cadre idéal.

Voici quelques implémentations spécifiques :
Voici le squelette d'entrée de processus principal :

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

Une fois le squelette configuré, nous devons remplir les objets BOM et DOM correspondants, tels queNavigator :
1. Observez d'abord l'objet dans l'environnement du navigateur : Navigator,
si vous pouvez créer un nouveau Navigateur, sinon, lancez une exception dans son définition du constructeur, ne le jetez pas si vous le pouvez ;

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

2. Vérifiez Navigator.prototypeles propriétés, les méthodes et la chaîne de prototypes de son prototype et
constatez que Navigatorles propriétés et les méthodes du prototype ne peuvent pas être appelées via le prototype et
Navigator.appVersionqu'une exception sera levée.
On constate que sa chaîne prototype n'a qu'une seule couche, à savoirNavigator.prototype.__proto__ === Object.prototype

3. Observez l'objet d'instance dans l'environnement du navigateur : navigator
vérifiez la différence entre ses propriétés, ses méthodes et son prototype, et constatez qu'il est presque identique, héritant essentiellement du prototype.
Il peut donc être simplement ajouté comme suit :


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);


Remarque : L'exemple ci-dessus n'est qu'un moyen de compléter l'environnement, qui est basé sur la granularité des objets et des attributs ; j'utilise personnellement une autre façon de penser , basée sur le fait 对象.属性.特性粒度即Object.getOwnPropertyDescriptor 的value,writable..等que bien que plus de codes soient nécessaires, l'effet de simulation est plus parfait , et la limite supérieure théorique est extrêmement élevée.

Il y a trop d'objets et de propriétés de navigateur, et il nous est impossible de remplir manuellement les propriétés de l'objet. Par conséquent, afin de créer un environnement de navigateur parfait, nous devons écrire 浏览器环境自吐脚本. Autrement dit, lorsque le script est exécuté dans le navigateur, il fusionne toutes les propriétés et méthodes d'un certain objet d'environnement de navigateur dans le code d'environnement supplémentaire requis par notre framework, et nous pouvons directement le coller et le modifier légèrement.

Nous pouvons utiliser : Reflect.ownKeys(real_obj)pour obtenir toutes les propriétés et méthodes de l'objet,
puis faire divers jugements et processus sur celui-ci attr, et enfin les assembler dans ce dont nous avons besoin.

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
        }
    }
    ..........太长,略过(下面框架源码中有)

Une fois que chaque objet de navigateur est terminé, il peut être exécuté pour comparer avec le vrai navigateur, progressivement optimisé, et enfin obtenir un effet parfait.

Cinq : Le code source du produit fini de "Supplementary Environment Framework "

补环境框架C'est devenu un gros tueur pour les inverseurs JS, et c'est aussi le point d'inspection de nombreux enquêteurs. Nous avons compris son principe et ses étapes de mise en œuvre, et ensuite nous pouvons essayer de mettre en place un framework d'environnement supplémentaire complet à partir de zéro, mais cela prendra beaucoup de temps à développer, et il y a beaucoup de tâches répétitives qui sont ennuyeuses (copier et coller le contraste, etc. .).

Prenez la voie rapide :

Je suis sur cette route depuis longtemps et j'ai créé de nombreux environnements. Si vous souhaitez gagner beaucoup de temps et améliorer considérablement l'efficacité, si vous êtes direct, vous pouvez me contacter sur WeChat: dengshengfeng666 Source payante 弯道超车référence du code ;
prix forfaitaire unifié 99, envoyez-le directement Le code source du projet framework (vous pouvez vous lancer directement avec le readme), et si vous avez des questions, vous pouvez directement me les poser.
Ou envoyez-moi un message privé directement sur CSDN.

Une partie de l'affichage des résultats (prenez l'exemple de la valeur du signe du titre) :

Les points de détection surveillés, les jolis garçons qui l'ont fait peuvent voir s'il y en a
Impression des points de test

Par rapport au vrai navigateur
Comparer avec un vrai navigateur
Dépassement dans les virages, partez de moi

Je suppose que tu aimes

Origine blog.csdn.net/qq_36291294/article/details/127699273
conseillé
Classement