丑团-H5参数逆向心得

本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!

本文章未经许可禁止转载,禁止任何修改后二次传播,擅自使用本文讲解的技术而导致的任何意外,作者均不负责,若有侵权,请联系作者立即删除!

本篇文章都是在网络其他文章的基础上进行分析的,因此有些地方可能可能会发出怀疑你是怎么找到的,当然我会尽量写详细点。

AST还原

还原代码网络上还是很多,找找也能用,但还是有部分代码需要自己写下的。

const a = ["9bfdeef5f8eff2f4f5", "13727e77",....] // 大数组
function b(c, d) {
    var e = a[c -= 0];
    ...// 就是老是进来的那个方法
}
const vis1 = {
    "CallExpression"(path) {
        let {callee, arguments} = path.node;
        if (types.isIdentifier(callee, {'name': 'b'})) {
            try {
                let value = eval(path.toString())
                path.replaceWith(types.valueToNode(value));
            } catch (e) {
                console.log(e);
            }
        }
    }
}
traverse(ast, vis1)

有几个地方会还原失败了,但是都打印出来了,手动还原下就行。

调用

万事都有个开头,所以我们也要先知道他是调用哪个方法生成的。实际上只要你网络上搜索的多就能找到,无需自己去跟了。

window.H5guard.init({参数到自己的浏览器里去搜索})
window.H5guard.sign({参数后面说})

补环境

像这种大厂的肯定会检测原型链的,所以补的时候尽量都补到原型链上

文件导入

下载整个H5guard.js文件,然后用require('./H5guard.js');导入下,免得代码太长补的时候恶心到自己。

a6

文章看多了就知道加密中的a6就是加密后的环境参数。a6的组成部分在头部有个明显的h1.标识,如果你有对js代码进行ast还原,那么直接搜索h1.就能找到生成位置了。

没还原也没事,根据网上的文章分析,搜索!1,找到类似gU(kz, !1, kt)的代码也行……

所以把最终环境补成a6加密前的样子就行了,当然有部分环境是不在a6内的,你也要补!

k3

只要你执行了js文件,那他就会发送请求获取k3的值,但是实际上让他不发送请求使用k2的值也是可以的。因此推荐是补下sendBeacon和XMLHttpRequest,但是实际内容不要去实现即可。

XMLHttpRequest = function XMLHttpRequest() {
    console.log('XMLHttpRequest-->')
}
Navigator.prototype.sendBeacon = function (url, data) {
    console.log('window.navigator.sendBeacon-->', url, data)
}

k66

嵌套的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);
// 下面是这段代码的使用方法
func_set_native(btoa)
func_set_native(atob)
func_set_native(Window)
func_set_native(Navigator)

k35

补的是音频类相关的?同样使用网络上的代码,同样会报错

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
}
AudioContext = function () {
    console.log('AudioContext-->')
}

解决:new Float32Array([…]),替换…就行,替换成啥就到自己的浏览器中打断点找到调用这个方法的地方然后copy下就行了。或者把补环境的代码给DeepSeek,让他帮忙生成?

其他

k47,k70等等这些都是异步的,我给的建议是不要加setTimeout = function () {}这段代码,不然就怎么也执行不到了,还有就是直接写成API的形式这样就不用管异步的问题了。

const http = require('http');
http.createServer(async (req, res) => {
    try {
        const result = await window.H5guard.xxx(); // 调用核心方法
        res.end(JSON.stringify({sign: result}));
    } catch (err) {
        res.statusCode = 500;
        res.end('Execution failed');
    }
}).listen(3000);

console.log('Server running at http://localhost:3000/');

至于其他的,按理来说只要AST还原了就没啥难度了,基本都看的清楚做了些什么。

调用

相信大家都能快速的找到加密调用位置,直接搜H5guard.sign(settings)都能找到,但是这里出的结果是错误的,自己去和实际请求携带的参数比对下就知道了。

所以这里需要断点到sign方法内,然后稍微看一眼就知道了,实际上就是真实的入参不在是settings的格式而已。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇