js逆向环境自吐(第六版)

前言

写了一个简单的环境自吐直接看缺了什么,借助了chatgpt的一些提示,如果有不正确的地方请指正。(仅供学习使用)代码在最下面。

  • 第五版增加了详细注释
  • 第六版支持了浏览器和Node使用,在浏览器上用需要将window变成windows,浏览器window暂时不支持使用代理(貌似用插件可以实现,正在寻找解决办法中…)

实践

1.某宝
在这里插入图片描述

2.某夕夕

在这里插入图片描述
3.某团
在这里插入图片描述

Reference

chatgpt机器人

代码

window = new function monitorWindow() {
    
    
  // 设置打印字符串长度
  const MAX_VALUE_LENGTH = 70;
  /**
   截取 value 值,用于在日志中输出时限制字符串长度,避免日志过长。
   @param {Object} value - 需要被截取的值。
   @returns {Object} 返回截取后的字符串值。
   */
  function truncateValue(value) {
    
    
    const MAX_VALUE_LENGTH = 60;

    if (typeof value === "string" && value.length > MAX_VALUE_LENGTH) {
    
    
      return value.substring(0, MAX_VALUE_LENGTH) + "...";
    }

    if (typeof value !== "object") {
    
    
      return value;
    }

    const keys = Object.keys(value);
    const result = {
    
    };

    if (keys.length > 2) {
    
    
      result[keys[0]] = value[keys[0]].toString().substring(0,MAX_VALUE_LENGTH) + "...";
    }

    return "{" + Object.entries(result).map(([k, v]) => `${
      
      k}: ${
      
      v}`).join(", ") + "}";
  }

  /**
   序列化 value 值,用于在日志中输出时处理对象或方法。
   @param {Object} value - 需要被序列化的值。
   @returns {Object} 返回序列化后的字符串值。
   */
  function serializeValue(value) {
    
    
    if (typeof value === "object") {
    
    
      try {
    
    
        return JSON.stringify(value);
      } catch {
    
    
        return value;
      }
    }
    return value;
  }

  /**
   * 创建代理处理程序,用于对被代理对象的属性访问、属性设置、方法调用等进行监听并打印操作日志。
   * @param {Object} name - 对象名。
   * @returns {Object} 返回代理处理程序。
   */
  function createHandler(name) {
    
    

    function shouldSkipKey(key, name) {
    
    

      if (key === 'window' || key === 'self' || key === 'globalThis' || key === name || key === "_globalObject") {
    
    
        return true;
      }

      if (typeof key === 'string' && (key.startsWith('__') || key.endsWith('__'))) {
    
    
        return true;
      }

      return String(key) === "Symbol(impl)" || String(key) === "Element" || String(key) === "prototype" || truncateValue(serializeValue(name)).includes("Symbol(impl)");


    }
    return {
    
    
      get(target, key, receiver) {
    
    
        // 打印调用栈
        // console.log(new Error().stack);
        // target=Object.defineProperty(target)
        // 获取属性值

        const value = target[key];

        // 不打印toString和valueOf特定的信息
        if (key === Symbol.unscopables || key === 'toString' || key === 'valueOf') {
    
    
          return Reflect.get(target, key, receiver);
        }

        // 内部属性
        if (shouldSkipKey(key, name)) {
    
    
          console.log(`访问: "${
      
      (String(key) + "\"内部属性").padEnd(28, " ")}|"${
      
      (truncateValue(serializeValue(name)) + "\"对象").padEnd(50, " ")}|值=`,truncateValue(serializeValue(value)));
          return value;
        }

        // 处理代理函数的构造函数
        if (typeof value === 'function' && value.hasOwnProperty('prototype')) {
    
    
          try{
    
    
            new value
            // console.log(`调用了构造函数: ${String(key).padEnd(22, " ")} |"参数": ${JSON.stringify(value)}`);
            return new Proxy(value,createHandler(`${
      
      String(name)}.${
      
      String(key)}`))
          }catch (e) {
    
    
          }
        }

        // 处理代理对象的属性访问和设置()
        if (typeof value === 'function' && !value.hasOwnProperty('prototype')) {
    
    
          return function (...args) {
    
    
            console.log(`调用了函数: ${
      
      (String(key)).padEnd(27, " ")}|"${
      
      (truncateValue(serializeValue(name)) + "\"对象").padEnd(50, " ")}|参数= ${
      
      truncateValue(serializeValue(args))}`);
            return Reflect.apply(value, target, args);
          }
        }

        // 处理代理对象的属性访问和设置(递归调用)
        if (value != null && (typeof value === 'object')) {
    
    
          console.log(`访问: "${
      
      (String(key) + "\"属性").padEnd(30, " ")}|"${
      
      (truncateValue(serializeValue(name)) + "\"对象").padEnd(50, " ")}|值=`, truncateValue(serializeValue(value)));
          return new Proxy(value,createHandler(`${
      
      String(name)}.${
      
      String(key)}`));
        }

        if (typeof value === 'function'){
    
    
          // 在Node上和windows有些差异,node有函数也有prototype,所以需要继续回调
          return new Proxy(value,createHandler(`${
      
      String(name)}.${
      
      String(key)}`));
        }else{
    
    
          // 不进行代理的属性或方法
          console.log(`获取: "${
      
      (String(key) + "\"属性").padEnd(30, " ")}|"${
      
      (truncateValue(serializeValue(name)) + "\"对象").padEnd(50, " ")}|值=`, truncateValue(serializeValue(value)));
        }
        return value;
      },
      set(target, key, value, receiver) {
    
    
        // 打印调用栈
        // console.log(new Error().stack);
        console.log(`设置对象: "${
      
      (String(key) + "\"").padEnd(28, " ")}|"${
      
      (truncateValue(serializeValue(name)) + "\"对象").padEnd(50, " ")}|值=`, truncateValue(serializeValue(value)));
        return Reflect.set(target, key, value, receiver);
      },
      apply(target, thisArg, args) {
    
    
        // 打印调用栈
        // console.log(new Error().stack);
        console.log(`调用了函数: ${
      
      (String(name)).padEnd(27, " ")}|"${
      
      (truncateValue(serializeValue(name)) + "\"对象").padEnd(50, " ")}|参数= ${
      
      truncateValue(serializeValue(args))}`);
        return Reflect.apply(target, thisArg, args);
      },
      construct(target, args, newTarget) {
    
    
        // 打印调用栈
        // console.log(new Error().stack);
        console.log(`调用了构造函数: ${
      
      String(target.name).padEnd(23, " ")}|"${
      
      (truncateValue(serializeValue(name)) + "\"对象").padEnd(50, " ")}|参数= ${
      
      JSON.stringify(args)}`);
        return Reflect.construct(target, args, newTarget);
      },
    };
  }
  return new Proxy(window,createHandler('window'));
}

猜你喜欢

转载自blog.csdn.net/qq_41866988/article/details/129053596