AST 難読化解除コードを使用した、Nike ログインの acw_sc__v2 パラメーターの詳細な逆分析 (非常に簡単なので、始めることをお勧めします)

序文

週末は何もすることがないので、Nike のログインを確認したところ、環境でも acw_sc__v2 パラメータを入力する必要がなく、楽しみやエンターテイメントのために共有できることがわかりました。
ここに画像の説明を挿入

1. 分析

F12 を開いてパケットをキャプチャし、ログインします。
ここに画像の説明を挿入
通常どおりカールをコピーし、分析のために Postman でキャプチャします。
ここに画像の説明を挿入
特定のパラメータの検索はデモンストレーションされません (必要なものと不必要なものを確認するには、パラメータを削除するだけです)。
最後に、Cookie はログインを完了するためにこの acw_sc__v2 のみを必要とすることがわかります。
ここに画像の説明を挿入
これは、acw_sc__v2 パラメータを使用しない場合に得られた結果です。
ここに画像の説明を挿入

次に、ログイン ページのコンソールに戻り、前のログインで取得した acw_sc__v2 を強制終了し、
ここに画像の説明を挿入
先祖のフック コードを使用して Cookie をフックアウトします (マウスの動きも Cookie に影響するため、小さなフィルターが作成されます)。

cookie_cache = document.cookie;
Object.defineProperty(document, "cookie", {
    
    
        get: function () {
    
    
            console.log(cookie_cache);
        // 在获取document.cookie时,执行你想要的操作
        return cookie_cache; // 返回原始的cookie值
    },
    set: function(value) {
    
    
        // 在设置document.cookie时,执行你想要的操作
        if(value.includes('acw_sc__v2')){
    
    
           debugger;
        }

    }
});

ブレークポイントが壊れたら、検索して、acw_sc__v2 パラメータ (arg3) を簡単かつ明確に見つけます。
ここに画像の説明を挿入
次に検索すると、arg3 が arg2 に関連していることがわかります。次に、arg2 のロジックを検索して、
ここに画像の説明を挿入
ここに進みます。arg2 であることがわかります。は arg1 から派生したものであるため、arg1 がどこから来たのかを調べます。
ここに画像の説明を挿入
関数の先頭まで移動すると、arg1 がパラメータとして渡されていることがわかります。その後、コール スタックを上にスクロールし続けると、コードのセクションからここに画像の説明を挿入
arg1 が抽出されていることがわかります。このコードは次のとおりです。<html><script>...非常によく知られていますが、以前はなかったのではないでしょうか? acw_sc__v2 パラメーターを使用してログイン コードを要求すると、この arg1 を一時的に修正して、arg2 によって生成された問題を解決できます。
ここに画像の説明を挿入
呼び出しスタック_0x4818 に戻り、再起動し
ここに画像の説明を挿入
、arg2 にブレークポイントを設定して
ここに画像の説明を挿入
、arg1 を暗号化して arg2 を生成するロジックをコピーします。

arg1="1029C3D5A2B9A15E217ED61D1C74843F834237A1"
var posList = [15, 35, 29, 24, 33, 16, 1, 38, 10, 9, 19, 31, 40, 27, 22, 23, 25, 13, 6, 11, 39, 18, 20, 8, 14, 21, 32, 26, 2, 30, 7, 4, 17, 5, 3, 28, 34, 37, 12, 36];
var mask = _0x1e8e("0x0");
var outPutList = [];
var arg2 = "";
var arg3 = "";
for (var i = 0; i < arg1[_0x1e8e("0x1")]; i++) {
    
    
    var this_i = arg1[i];
    for (var j = 0; j < posList[_0x1e8e("0x1")]; j++) {
    
    
        if (posList[j] == i + 1) {
    
    
            outPutList[j] = this_i
        }
    }
}
arg2 = outPutList[_0x1e8e("0x2")]("");
console.log(arg2)

次に、彼に欠けている機能を埋めます。
ここに画像の説明を挿入
足りないものを補うという考えを貫き、2つのパラメータを追加しました。しかし、実際には実行中にオーバーフローが発生したため、どのような操作によってこのコードがオーバーフローしたのかを追跡する必要があります。
ここに画像の説明を挿入
ブラウザのパラメータ値を比較すると、両者は明らかに異なっており、_0x3e9eの配列も明らかに異なっていることが分かります。これら 2 つのパラメータの間で関数を実行しています。配列 _0x3e9e は、シフト演算であるはずの演算を実行しました。
ここに画像の説明を挿入
直接実行した後
ここに画像の説明を挿入
、前のブレークポイントに到達できません。この自己実行関数にはまだ問題があることがわかります。経験から言えば、フォーマットの検出に問題があるはずです。古い方法でフォローアップします。いくつかの手順を実行すると、ここで正常に実行できないことがわかります。フォローアップしないのはなぜですか。 RegExp, これは普通ではないですか? 正則化の検出?
ここに画像の説明を挿入
対応するパラメータを出力すると、それがわかります. これは、_0x981158["test"](_0x3e4c21["removeCookie"]["toString"]())removeCookieの正則化の検出ですtrue. _0x3e9e 配列もブラウザと同じになります。

ここに画像の説明を挿入
では、類推して考えてみましょう。前にここでオーバーフローするでしょうか? これも正則化検出のせいです。検索を直接開いて、他の 2 つの RegExp を除外した後 (追加された自己実行関数内にあるため
ここに画像の説明を挿入
、次の結果には影響しません。)、上の図では RegExp がまだ存在していることがわかりますが、上とまったく同じではないため、ここでブレークポイントを設定して何が起こっているかを確認してみましょう
ここに画像の説明を挿入
。オーバーフローします。arg2
ここに画像の説明を挿入
が正常に出力されたことがわかります。
ここに画像の説明を挿入
ブラウザと比較すると、同じ効果があります。
ここに画像の説明を挿入
次に、arg3 から開始できます。分析するものは何もありません。arg2 の直後に配置します。結果があります。

for (var i = 0; i < arg2[_0x1e8e("0x1")] && i < mask[_0x1e8e("0x1")]; i += 2) {
    
    
    var GxjQsM = _0x1e8e("0x3")[_0x1e8e("0x4")]("|")
      , QoWazb = 0;
    while (!![]) {
    
    
        switch (GxjQsM[QoWazb++]) {
    
    
        case "0":
            if (xorChar[_0x1e8e("0x1")] == 1) {
    
    
                xorChar = "0" + xorChar
            }
            continue;
        case "1":
            var strChar = parseInt(arg2[_0x1e8e("0x5")](i, i + 2), 16);
            continue;
        case "2":
            arg3 += xorChar;
            continue;
        case "3":
            var xorChar = (strChar ^ maskChar)[_0x1e8e("0x6")](16);
            continue;
        case "4":
            var maskChar = parseInt(mask[_0x1e8e("0x5")](i, i + 2), 16);
            continue
        }
        break
    }
}
console.log(arg3)

ここに画像の説明を挿入
ここに画像の説明を挿入

3. まとめ

実際、それは難しいことではなく、主に正則化のテストであり、環境を補う必要さえありません。主にアイデアを与えるためです。

四、番外

もちろん上記の方法だけではなく、Cookieなしでアクセスして取得したjsコードを覚えていますか?
ここに画像の説明を挿入

1.AST の難読化解除

手書きしたくない場合は、Apemanology に付属のワンキー難読化解除機能を直接使用できます。ただし、その効果は希望するほど任意ではありませんが、速度は高速です。
ただし、ここでは私の手書きの AST 難読化解除コード ( bianhhua.jsCookie なしでアクセスして取得した JS コード) を示します。具体的に各行がどのような機能を持っているかは、gpt を使用して自分で理解してください~

const {
    
    parse} = require("@babel/parser");
const generator = require("@babel/generator").default;
const traverse = require("@babel/traverse").default;
const types = require("@babel/types");
const fs = require("fs");
var AST_code = fs.readFileSync('bianhhua.js', {
    
    encoding: 'utf-8'});

let AST_parse = parse(AST_code);
traverse(AST_parse, {
    
    
        //  字符串美化,便于观察
        "StringLiteral|NumericLiteral"(path){
    
    
            path.node.extra && delete path.node.extra;
    
        },
})
const js_code = generator(AST_parse, {
    
    compact:true}).code;
let AST_parse_1 = parse(js_code);

// 获取解密函数,并写入内存
let memory_decode_js = '';
for(let i=0;i<=3;i++){
    
    
    memory_decode_js += generator(AST_parse_1.program.body[i], {
    
    compact:true}).code
}
AST_parse_1.program.body[3] = ""
eval(memory_decode_js);
traverse(AST_parse_1, {
    
    
    //  替换加密字符参数
    "CallExpression"(path){
    
    
        if(path.node.callee.name === '_0x55f3'){
    
    
            path.replaceInline(types.valueToNode(eval(path.toString())));
        }
    },
})

const js_code_1 = generator(AST_parse_1, {
    
    compact:true}).code;
console.log(js_code_1)

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/qq_41866988/article/details/131263718
おすすめ