JS逆向 - 某团Mtgsig1.2 (补环境)

概要

提示:仅供学习,不得用做商业交易,如有侵权请及时联系

逆向:某团Mtgsig1.2 (补环境)

URL: aHR0cHM6Ly9hY2NvdW50LmRpYW5waW5nLmNvbS9wY2xvZ2luP3JlZGlyPWh0dHBzOi8vbS5kaWFucGluZy5jb20vZHBob21l

目标:请求头Mtgsig

在这里插入图片描述

整体架构流程

提示:全扣补环境

1、分析加密入口:搜索 H5guard.sign
2、将整个文件扣下:
url:aHR0cHM6Ly9hcHBzZWMtbW9iaWxlLm1laXR1YW4uY29tL2g1Z3VhcmQvSDVndWFyZC5qcz92PTE3NDYwMjEzODMyNzk=

3、初始化加密环境:

在这里插入图片描述

技术名词解释

提示:检测环境数组

直接找到a6生成的位置,以为a6参与了环境计算: gG就是环境数组

在这里插入图片描述

这里直接展示一下我补的浏览器环境,基本上跟浏览器一致了

{
  //版本号
  k1: '3.1.0',
  //时间戳
  k5: 1746020851587,
  //随机生成
  sessionId: '5f0eae8fc7e443d9877edb598c683bcd',
  // getfp生成的WEBDFPID 后面一段值
  k2: '1745824008886IMQOYUOfd79fef3d01d5e9aadc18ccd4d0c95074463',
  // // getfp生成的WEBDFPID 前面一段值
  k3: 'u53zvu029uuw5730z5x026729ww0x6w48032y11148x979589u2vv091',
  k123: {
    k7: 16,
    k24: 5,
    k27: 5,
    k28: 3,
    k29: 3,
    k30: 5,
    k45: 7,
    k52: 5,
    k53: 5,
    k54: 5,
    k55: 5,
    k56: 5,
    k57: 5,
    k58: 5,
    k59: 5,
    k62: 16,
    k63: 5,
    k70: 0,
    k72: 3
  },
  // Navigator.platform
  k25: 'Win32',
  k27: '',
  k68: [ 0, 0, 0, 0, 0 ],
  // sessionStorage、localStorage、indexedDB、openDatabase、chrome、document、plugins、getOwnPropertyDescriptor、permissions、createElement、WebGLRenderingContext、getContext、AudioContext
  k50: '00ceea200',
  k61: 0,
  reload: [Function (anonymous)],
  k0: 1746020851,
  k7: '',
  k62: '',
  k63: '',
  k52: [],
  k53: [],
  k54: [],
  k55: [],
  k56: [],
  k57: [],
  k58: [],
  k59: [],
  // href 和 origin
  k6: [
    'https://脱敏/pclogin',
    'https://脱敏/'
  ],
  // navigator的属性或方法 、history的属性或方法 、window的属性或方法
  k8: 'ffffffffffffffffffffff3ffffffffffdfbfffffffffffffffffffffffffc',
  //document.readyState / performance.timing.domContentLoadedEventStart/domContentLoadedEventEnd/domLoading
  k9: 'loading|0|0|1746020851601',
  //[[screen["width"], screen["height"]], [screen["availWidth"], screen["availHeight"]], screen["colorDepth"], screen["pixelDepth"]]
  k11: [ [ 1536, 864 ], [ 1536, 824 ], 24, 24 ],
  //document["documentElement"]["clientWidth"] / window["innerWidth"]
  k12: [ 1536, 715 ],
  //window["sessionStorage"]
  k13: 1,
  //window["localStorage"]
  k14: 1,
  //window["pageYOffset"]
  k15: 0,
  //window["document"]["body"]["scrollTop"]
  k16: 0,
  //window["devicePixelRatio"]
  k17: 1.25,
  //window["length"]
  k18: 0,
  //window["performance"]["memory"]["jsHeapSizeLimit"]
  k19: 2172649472,
  //navigator["languages"]
  k20: [ 'zh-CN', 'zh' ],
  //navigator["language"]
  k21: 'zh-CN',
  //navigator["deviceMemory"]
  k22: 8,
  //navigator["hardwareConcurrency"]
  k23: 8,
  //navigator["doNotTrack"]
  k24: '',
  //window["navigator"]["plugins"] /name
  k26: [
    'PDF Viewer',
    'Chrome PDF Viewer',
    'Chromium PDF Viewer',
    'Microsoft Edge PDF Viewer',
    'WebKit built-in PDF'
  ],
  //navigator["oscpu"]
  k28: null,
  //navigator["cpuClass"]
  k29: null,
  //avigator["vendorSub"]
  k30: '',
  //navigator["maxTouchPoints"]
  k31: 0,
  //navigator["vendor"]
  k32: 'Google Inc.',
  //navigator["cookieEnabled"] ? "yes" : ""
  k33: 'yes',
  // canvas.toDAataUrl
  k34: 'data:image/png;base64,xxx',
  //对canvas指纹进行魔改md5加密
  k36: '174b4e8b63ec5d15ad9da6186992f4bc',
  // navigator["userAgent"]
  k37: 'Mozilla/5.0 xxx/537.36',
  //history["length"]
  k38: 3,
  //getParameter   --- UNMASKED_VENDOR_WEBGL
  k39: 'Google Inc. (Intel)',
  // getParameter    --- UNMASKED_RENDERER_WEBGL
  k40: 'ANGLE (Intel, Intel(R) UHD Graphics (0x00008A56) Direct3D11 vs_5_0 ps_5_0, D3D11)',
  // getParameter    ---- VENDOR
  k41: 'WebKit',
  // getParameter    ---- RENDERER
  k42: 'WebKit WebGL',
  // getParameter    ---- VERSION
  k43: 'WebGL 1.0 (OpenGL ES 2.0 Chromium)',
  k45: '',
  // matchMedia
  k46: 'srgb',
  // new Date()["getTimezoneOffset"]()
  k48: -480,
  // timeZone
  k49: 'Asia/Shanghai',
  // sessionStorage /localStorage/indexedDB
  k51: '1|1|1',
  // tostring检测、多层tostring
  k64: {
    parse: {
      function: 'function parse() { [native code] }',
      toString: [Object]
    },
    stringify: {
      function: 'function stringify() { [native code] }',
      toString: [Object]
    },
    decodeURI: {
      function: 'function decodeURI() { [native code] }',
      toString: [Object]
    },
    decodeURIComponent: {
      function: 'function decodeURIComponent() { [native code] }',
      toString: [Object]
    },
    encodeURI: {
      function: 'function encodeURI() { [native code] }',
      toString: [Object]
    },
    encodeURIComponent: {
      function: 'function encodeURIComponent() { [native code] }',
      toString: [Object]
    },
    escape: {
      function: 'function escape() { [native code] }',
      toString: [Object]
    },
    unescape: {
      function: 'function unescape() { [native code] }',
      toString: [Object]
    },
    atob: {
      function: 'function atob() { [native code] }',
      toString: [Object]
    },
    btoa: {
      function: 'function btoa() { [native code] }',
      toString: [Object]
    }
  },
  // document["getElementsByTagName"]("script") / getAttribute -src
  k65: [
    '//脱敏/js/xxx.min.js',
    'https://脱敏/yoda.xxx.js',
    '//脱敏/async_dependencies.xxx.js',
    '//脱敏/logan_2.1.5.js',
    '//脱敏/owl_1.9.3.js',
    '//脱敏/lx.js',
    'https://脱敏/xxx/xxx.js'
  ],
  // 检测bom原型和原型链上的toString 和 getOwnPropertyDescriptor
  k66: {
    Window: {
      function: 'function Window() { [native code] }',
      typeof: 'function',
      Object: [Object],
      toString: [Object]
    },
    Navigator: {
      function: 'function Navigator() { [native code] }',
      typeof: 'function',
      Object: [Object],
      toString: [Object]
    },
    window: {
      function: '[object Window]',
      typeof: 'object',
      Object: [Object],
      toString: [Object]
    },
    navigator: {
      function: '[object Navigator]',
      typeof: 'object',
      Object: [Object],
      toString: [Object]
    }
  },
  // 三个对象的configurable
  k67: { location: false, document: false, top: false },
  // RTCPeerConnection异步加载的onicecandidate事件
  k44: '1020839364',
  // encry加密得到
  k71: 'fuTAVPQM5XjsHGg6Vc==',
  k72: '',
  // getfp 进行dom操作创建标签span,字体判断得到
  k10: 'Arial,Courier,Courier New,Georgia...............',
  // span offsetWidth  offsetHeight ["monospace", "sans-serif", "serif"] 对比计算得到
  k60: 'ffff7ffff8',
  k4: 1746020851755,
  // OfflineAudioContext异步操作事件得到
  k35: '124.04347527516074',
  // navigator["getBattery"] 异步操作得到
  k47: [ 0.99, true, 'Infinity' ]
}

函数保护,过多层tostring

!(function () {
    "use strict";
    const $toString = Function.toString;
    const myFunction_toString_symbol = Symbol('('.concat('', ')_', (Math.random() + '').toString(36)));
    const mytoString = function () {
        return typeof this == 'function' && this[myFunction_toString_symbol] || $toString.call(this);
    };

    function set_native(func, key, value) {
        Object.defineProperty(func, key, {
            "enumerable": false,
            "configurable": true,
            "writable": true,
            "value": value
        })
    };
    delete Function.prototype['toString'];
    set_native(Function.prototype, "toString", mytoString);
    set_native(Function.prototype.toString, myFunction_toString_symbol, "function toString() { [native code] }");
    this.func_set_native = function (func) {
        set_native(func, myFunction_toString_symbol, `function ${myFunction_toString_symbol, func.name || ''}() { [native code] }`)
    }
}).call(globalThis);

补充点:RTCPeerConnection、getBattery、OfflineAudioContext三个异步

offauidio = proxy({
    createOscillator: function createOscillator() {
        return proxy({
            frequency: {
                setValueAtTime: function setValueAtTime() { },
            },
            connect: function connect() { },
            start: function start() { },
            disconnect:function disconnect() { }
        }, 'OscillatorNode')
    },
    createDynamicsCompressor: function createDynamicsCompressor() {
        return proxy({
            connect: function connect() { },
            threshold: {
                setValueAtTime: function setValueAtTime() { },
            },
            knee: {
                setValueAtTime: function setValueAtTime() { },
            },
            ratio: 0,
            reduction: {
                setValueAtTime: function setValueAtTime() { },
            },
            attack: {
                setValueAtTime: function setValueAtTime() { },
            },
            release: {
                setValueAtTime: function setValueAtTime() { },
            },
            disconnect:function disconnect() { }
        }, 'DynamicsCompressorNode')
    },
    currentTime: 0,
    destination: {},
    startRendering: function startRendering() { },
}, 'OfflineAudioContext');
Object.defineProperty(offauidio, 'oncomplete', {
    set: function (func) {
        func({
            renderedBuffer: {
                getChannelData: function () {
                	return new Float32Array([...]);
                },
            }
        })
        return func
    }
})
OfflineAudioContext = function OfflineAudioContext() {
    return offauidio
}
// 创建电池管理器对象原型 
const BatteryManager = {
    level: 1,
    charging: true,
    chargingTime: 0,
    dischargingTime: Infinity,
    onchargingchange: null,
    onlevelchange: null,
    toString: function() {
      return `BatteryManager {
        charging: ${this.charging}, 
        level: ${this.level}, 
        chargingTime: ${this.chargingTime}, 
        dischargingTime: ${this.dischargingTime} 
      }`
    }
  }
getBattery = function getBattery() {
     return Promise.resolve({
         __proto__: BatteryManager,
         // 动态参数配置(示例值)
         level: 0.99,
         charging: true,
         dischargingTime: 'Infinity' // 2小时放电时间 
       })
 }
 RTCPeerConnection = function RTCPeerConnection() {
    return proxy({
        createDataChannel: function createDataChannel() { },
        createOffer: function createOffer() {
            this.onicecandidate({
                candidate:{
                    "candidate": "candidate:1020839364 1 udp 1677729535 xxxx 56455 typ srflx raddr 0.0.0.0 rport 0 generation 0 ufrag 7Ocn network-cost 999",
                    "sdpMid": "0",
                    "sdpMLineIndex": 0,
                    "usernameFragment": "7Ocn"
                }
            });
            return new Promise(function (resolve, reject) {
                resolve(proxy({
                    type: 'offer',
                    sdp: 'offerSdp',
                    then: function then() {
                        
                    },
                }, 'RTCSessionDescription'));
            });
        },
        setLocalDescription: function setLocalDescription() {
            
        },
    }, 'RTCPeerConnection');
};
webkitRTCPeerConnection = RTCPeerConnection;

Object.getOwnPropertyDescriptor检测点:

Object.getOwnPropertyDescriptor_ = Object.getOwnPropertyDescriptor;
Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(obj, prop) {
    var desc = Object.getOwnPropertyDescriptor_(obj, prop);
    if (obj + '' === '[object Window]' && prop === 'location') {
        return {
            configurable: false,
            enumerable: true,
            get: {location(){}}.location,
            set:{location(){}}.location
        };
    }
    if (obj + '' === '[object Window]' && prop === "document") {
        return {
            configurable: false,
            enumerable: true,
            get: {document(){}}.document,
            set:undefined
        };
    }
    if (obj + '' === '[object Window]' && prop === "top") {
        return {
            configurable: false,
            enumerable: true,
            get: {top(){}}.top,
            set:undefined
        };
    }
    return desc;
}

这里说一下XML怎么补,不会补就第三方库

XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest
XMLHttpRequest.prototype = new XMLHttpRequest();

技术细节

提示:补了一辈子,环境与浏览器都一致了,就是过不了,最后发现js中有空行,离谱
在这里插入图片描述

结果

在这里插入图片描述

小结

提示:学习交流群+v主页(+知识星球交流学习)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值