実践的な戦闘 | APP 上の複数の制限を忘れずに回避してください

特定のアプリには強化、フリーダ検出、ルート検出があり、テスト中に証明書バインディング、双方向証明書認証、データ暗号化が使用されていることが判明しました。

フリーダ検出バイパス

最初は、難読化された frida がまだ検出されることがわかりました。まず、frida フック dlopen を使用して、ロードされた so を表示します。dlopen は主に、いくつかのシステム ライブラリをロードするために使用されます。libc.so ライブラリが開かれていることがわかります, に基づいてlibc.so の検出は一般に 2 つのタイプに分類されます: 1 つはマップやステータスなどのファイルの読み取りおよび書き込みクラス、もう 1 つはスレッド クラスです。dlopen_ext を通じて、libexec と libexecmain が最も可能性が高いこともわかります。フリーダを検出します。

写真

上記のことから、libexec または libexecmain が pthread_create を呼び出し、関連する検出スレッドを作成したことがわかります。そのため、Thread.backtrace([context, backtracer]): を使用して現在のスレッドのコール スタックを取得し、出力することで so ファイル名を取得します。スタック。

写真

この時点で、libexec が pthread_create を呼び出して関連する検出メソッドを作成したことが確認できます。探しているメソッドは、プログラムがクラッシュする前に作成されたメソッド pthread_create です。次に、取得した関連する動的アドレスから libexec ベース アドレスを減算することで関連するメソッドのオフセットを特定でき、最終的に、pthread_create が検出スレッドを作成するときに対応するメソッドを置き換えることができます。

function getunfrida() {
   
       var pthaddr = Module.findExportByName("libc.so","pthread_create");    var timeaddr=Module.findExportByName("libc.so","time");    Interceptor.attach(pthaddr,{
   
           onEnter: function(args){
   
               var baseaddr=Module.findBaseAddress("libexec.so");            if(args[2]-baseaddress==270080 ||args[2]-baseaddress==193128 ||args[2]-baseaddress==193072){
   
                   args[2]=timeaddr;            }        },onLeave: function(retval){
   
       }});}

ルート検出バイパス

ルート化された電話機を開くと、デバイスがルート化されていることを示すプロンプトが表示され、自動的にプログラムを終了し、コードを解凍し、jadx で関連するコードを検索し、checkroot メソッドを使用してルート化されているかどうかを検出します。

写真

このメソッドをフックすると、プログラムは環境リスクを表示して終了しますが、checkmagisk メソッドも存在することがわかりました。

写真

これら 2 つのメソッドをインターセプトするフック スクリプトを作成します。

Java.perform(function(){
   
       let LoginActivity = Java.use("com.xxxx.LoginActivity");    LoginActivity["checkroot"].overload('java.lang.Object').implementation = function () {
   
         console.log('checkroot is pass');    };    LoginActivity["checkmagisk"].implementation = function () {
   
           console.log('checkmagisk is pass');    };    });

写真

双方向の証明書認証バイパス

両方のメソッドがフックされましたが、データ パケットをキャプチャできないことがわかりました。APK の network_security_config.xml リソース ファイルを確認してください。アプリはユーザー証明書を信頼しています。

写真

時間の制約のため、最初は root 検出に関連する方法には目を向けませんでした。権限昇格の脆弱性を直接利用して、root によって実行される frida スクリプトを取得しました。アプリがシステム証明書のみを信頼する場合でも、テスト マシンは、この脆弱性を利用して root シェル コマンド ラインを取得すると、メモリ ファイル システムを一時的にマウントし、そこにシステム証明書をインポートすることもできます。

写真

チャールズモニター16666。

写真

携帯電話は、16666 ソックス 5 を後部経由でチャールズに転送し、外部プロキシをげっぷするように設定します。

写真

burp のデータを確認すると、データ パケットが 400 を返していることがわかり、双方向の証明書認証を使用している可能性があると判断されるため、直接パスワードを吐き出してみることができます。

function hook_KeyStore_load() {
   
       Java.perform(function () {
   
           var StringClass = Java.use("java.lang.String");        var KeyStore = Java.use("java.security.KeyStore");        KeyStore.load.overload('java.security.KeyStore$LoadStoreParameter').implementation = function (arg0) {
   
               console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));            console.log("KeyStore.load1:", arg0);            this.load(arg0);        };        KeyStore.load.overload('java.io.InputStream', '[C').implementation = function (arg0, arg1) {
   
               console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));            console.log("KeyStore.load2:", arg0, arg1 ? StringClass.$new(arg1) : null);            this.load(arg0, arg1);        };
        var AssetManager = Java.use("android.content.res.AssetManager");        AssetManager["open"].overload('java.lang.String', 'int').implementation = function (fileName, accessMode) {
   
               console.log('open is called' + ', ' + 'fileName: ' + fileName );            let ret = this.open(fileName, accessMode);            return ret;            };
    });}

証明書のパスワードを正常に取得しました。

写真

もちろん、コード (簡略化) を通じて関連するコードを見つけることもできます。コードを通じて、パスワードが getValue メソッドから取得されたものであることがわかります。

写真

スクリプトフックを作成した後、証明書のパスワードを取得できます。

写真

証明書のパスワードを取得したら、リソース ファイル内で対応する 2 つの証明書ファイルを見つけて、それらを burp にインポートします。

写真

ここにチャールズもインポートします。

写真

ドメイン名 1 のデータ パケットのキャプチャに成功しました。

写真

しかし、ログインをクリックしてもドメイン名 2 のデータパケットをキャプチャできません。このとき、データパケットにはポート 8099 のソケットプロトコルを示すデータパケットがあることがわかります。

写真

Charles のプロキシ設定に非標準の https ポートを追加します。

写真

もう一度「ログイン」をクリックして、ログイン データ パケットを正常にキャプチャします。

写真

暗号化アルゴリズムのバイパス

テストを容易にするために Charles 経由でげっぷに自動的に転送され、データが暗号化されていることがわかります。

写真

暗号化アルゴリズムの場所を見つけます。

写真

フック スクリプトを作成し、sm4 暗号化フック コードを frida バイパス スクリプトに追加します。

Java.perform(function(){
   
       let hooksm4 = Java.use("com.xx.xxxx");    hooksm4["sm4De"].implementation = function (cipherStr, sm4Key) {
   
           console.log('sm4De is called' + ', ' + 'cipherStr: ' + cipherStr + ', ' + 'sm4Key: ' + sm4Key);        let ret = this.sm4Decrypt(cipherStr, sm4Key);        console.log('sm4De ret value is ' + ret);        return ret;};    });

フックを通じて、事前に暗号化されたコンテンツと国家機密 sm4 アルゴリズムのキーを取得できます。

写真

もちろん、フックを通じて見つかったキーは動的キーです。固定キーを書き込んだ後、テストを開始できます。その後のテストでは、ドメイン名 3 とドメイン名 4 の両方に証明書バインドがあることがわかりました。

写真

したがって、証明書バインディング バイパス コードを frida バイパス スクリプトに追加する必要があります。

function checkTrustedRecursive() {
   
       Java.perform(function () {
   
           var array_list = Java.use("java.util.ArrayList");        var TrustManagerImpl_Activity_1 = Java.use('com.android.org.conscrypt.TrustManagerImpl');        TrustManagerImpl_Activity_1.checkTrustedRecursive.implementation = function(certs, ocspData, tlsSctData, host, clientAuth, untrustedChain, trustAnchorChain, used) {
   
               console.log('[+] Bypassing TrustManagerImpl (Android > 7) checkTrustedRecursive check: '+ host);            return array_list.$new();        };});}

写真

この時点で、すべてのデータ パケットをキャプチャできます。

写真

補充する

中間テスト中に、frida スポーン モードが開始され、スクリプトがバイパスされ、証明書のパスワードをフックすることはできましたが、プログラムが起動ページでスタックし、正常にアプリに入ることができませんでした。 , アタッチに失敗しました: pid 7854 のプロセスにアクセスできませんが、再び表示されました。システム制限へ; `sudo sysctl kernel.yama.ptrace_scope=0` を試すか、ルート エラーとして Frida を実行してください。

写真

まだデュアルプロセス保護が残っているようです。何度かテストした後、最初にスポーンモードを実行して最終的に起動しました。プログラムがスタックしました。待機を続けるか終了するかを尋ねられました。クリックして終了します。

写真

プログラムがクラッシュして終了した後は、アプリを再度開いたり、frida Attach モードを実行したりしないでください (この時点では、プログラムが見つからないというメッセージが表示されずにアプリをロードできます)。

写真

アプリを開くと、アプリに正常に入り、スクリプトが正常に実行されます(非常に不思議です)。

写真

Supongo que te gusta

Origin blog.csdn.net/ab6326795/article/details/131822492
Recomendado
Clasificación