banner
Silas

REAO

Be a better man
github

微信 | サイコロを振る機能とじゃんけん機能の分析

本文は Android WeChat 8.0.3 に基づいています。

最近、いくつかのソフトウェアの逆向き学習を始めたので、記録しておきます。

この記事は WeChat シリーズの第一篇で、サイコロを振る機能とじゃんけん機能の分析です。

サイコロを振ることとじゃんけんはランダムな結果が出るため、推測するに、ランダム数を使って実現されているはずで、後に実際にそうであることがわかりました。

1、 フックポイントを探す#

Java の Random クラスに対応するクラス名は java.util.Random で、objection を使って watching します:

image

サイコロの絵文字を送信すると、Random の以下のメソッドが呼び出されることがわかりました:

image

java.util.Random.nextInt を watch し、再度サイコロを振って、呼び出しスタック、パラメータ、戻り値をダンプします:

image

nextInt (n) : メソッド呼び出しが 0(含む)と n(含まない)の間の擬似ランダムで均等分布の int 値を返します。

nextInt のパラメータは 6 で、戻り値は 1、サイコロの結果は 2 です。

実際、ここもフックポイントとして使えますが、詳細が不足しています。フックすべきポイントはサイコロを振ることとじゃんけんだけで、Java のツールクラスのランダム数メソッドを直接フックするのは少し粗雑です。

呼び出しスタックを遡ると、getIntRandom は tencent SDK のメソッドで、明らかにランダム数を生成するメソッドです。

さらに上に進むと、om.tencent.mm.plugin.emoji.e.f.o があり、これらの 2 つのメソッドを watch して、何か追加情報が得られるか見てみます。

android hooking watch class_method  com.tencent.mm.sdk.platformtools.Util.getIntRandom --dump-args --dump-return
android hooking watch class_method com.tencent.mm.plugin.emoji.e.f.o --dump-args --dump-return

再度サイコロを振ると、今度の結果は 5 点です。

e.f.o メソッドのパラメータは:

image

戻り値は:

image

このメソッドのパラメータと戻り値から推測すると、dice.png はサイコロの画像で、dice_5.png は 5 点のサイコロです。

image

この呼び出しプロセスでは、画像から getIntRandom が得たランダム数「0-5」が、サイコロの結果の点数「1-6」に対応していることがわかります。


次に、じゃんけんのロジックを見てみると、サイコロを振るのと一致しています。

1.field_name は「jsb.png」で、これはじゃんけんの「剪刀石头布」のピンインの頭文字です:

image

2、getIntRandom のパラメータは 2 で、[0,2] の int ランダム数を取得します:

image

3、戻り値の field_name は jsb_b.png で、じゃんけんの結果「布」と一致します。

image

image

ここまで分析した結果、利用中に e.f.o のパラメータに基づいて現在取得するランダム数がどの絵文字(じゃんけんまたはサイコロ)であるかを判断し、その後 getIntRandom の戻り値をフックして変更することで、望む結果を得ることができます。

フックできるポイントをまとめると:

com.tencent.mm.plugin.emoji.e.f.o(com.tencent.mm.storage.emotion.EmojiInfo)

com.tencent.mm.sdk.platformtools.Util.getIntRandom(int,int)

2、Frida スクリプトの作成#

設定:じゃんけんは常に剪刀を出し、サイコロは常に 6 点を出す。

Frida スクリプトを作成します:

function main() {

    Java.perform(function () {

        Java.openClassFile("/data/local/tmp/r0gson.dex").load();
        const gson = Java.use('com.r0ysue.gson.Gson')


        var jsb = 0 // じゃんけんは常に剪刀
        var dice = 5 // サイコロは常に6点

        var efo = Java.use('com.tencent.mm.plugin.emoji.e.f')


        efo.o.implementation = function (x) {

            var xstr = gson.$new().toJson(x)
            if (xstr.search('dice.png') != -1) {
                console.log('サイコロを振っています')
                hookIntRandom(dice)

            } else if (xstr.search('jsb.png') != -1) {
                console.log("じゃんけんをしています")
                hookIntRandom(jsb)
            }
            var res = this.o(x)
            return res
        }

    })
}


function hookIntRandom(a) {
    Java.perform(function () {
        var util = Java.use('com.tencent.mm.sdk.platformtools.Util')
        
        util.getIntRandom.implementation = function (int1, int2) {
            var res = this.getIntRandom(int1, int2)
            return a
        }
    })
}

setImmediate(main)

注:スクリプトでは肉丝の Gson を使用してオブジェクトを印刷していますが、非常に便利です。

image

3、参考資料#

参考資料
Frida で [object] を印刷する際の Gson パッケージの重複名問題 - https://bbs.pediy.com/thread-259186.htm

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。