目次

難読化とあなた

アプリケーションのセキュリティ もはや既知の事実です。誰もがその必要性を認識しており、攻撃者は基本的な保護を破る方法も知っています。保護されていないアプリケーションを配布することはもはや選択肢ではありません。強力な保護はすべて、静的解析による防御と動的攻撃検知の2つの要素で構成されています。静的解析は、攻撃者にアプリケーション固有の実装の詳細に関する独自の洞察を提供する強力なツールです。アプリケーションの最も脆弱な部分を露呈させ、攻撃を加速させたり、貴重なビジネスIPを盗んだりするのに役立ちます。ソースコードだけでなく、データも 難読化 静的解析保護の重要な部分です。コードとデータを変換して悪意のある攻撃者の攻撃を遅らせる方法をいくつかご紹介します。攻撃者がより苦労すればするほど、 safe私たちの世界はこうなるのです。

保護を民営化する

アプリケーションは何らかの難読化を行わずに配布すべきではありませんが、すべての難読化が同じように作られているわけではありません。強力な難読化には、プライベート IP とランダム化という 2 つの重要な要素があります。現在利用可能なオープンソースの難読化ツールは、アプリケーション開発者と同様に攻撃者にとっても有用です。これらのオープンソースの難読化ツールが提供する保護レベルは、エンタープライズ品質のアプリケーションを確実に保護するには十分ではありません。効果的な難読化を行うには、ソースコードを人間が判読できず、自動化された攻撃ツールでも元に戻せないものに変換する必要があります。公開されている難読化手法は、それらを破るための独自のロゼッタストーンとして機能します。カスタムビルドされ、公開されていない難読化手法を使用することで、Timmy Turner が生成 AI フェアリーを使用してアプリの難読化を元に戻すのを阻止できます。これらのプライベート アルゴリズムを固有のランダム性と組み合わせることで、人間や LLM が糸のもつれを解くことができないようにします。

PRNGの反撃

攻撃者は、同じアプリケーションの異なるリリースを比較することで、かなりの情報を収集できます。アプリのバージョン間で難読化を変更することは絶対に必要です。ほとんどの疑似乱数化エンジンは、シード値を使用して予測可能性を強制しながらも、固有のランダム性を維持しており、難読化も例外ではありません。シード値を増減するだけで、入力アプリケーションに適用される難読化に劇的な変化が生じます。これにより、必要に応じて再現性が得られますが、新しいバージョンがリリースされた後にアプリケーションをリバースエンジニアリングする際には、攻撃者は最初からやり直す必要があります。これは、攻撃者が私道の半分を雪かきし、ホットココアで休憩した後、戻ってくると新雪が積もっているようなものです。強力なセキュリティは、無駄な時間を使うことに重点を置いています。 リバースエンジニアリングの 時間と絶えず変化する風景は、彼らの時間を無駄にする最良の方法の 1 つです。

難読化 難読化 難読化

概念的には、難読化は最適化の逆です。コンパイラが複数の最適化パスを持つことが多いのと同様に、難読化パスも複数あります。つまり、追加された難読化にさらに難読化を適用するということです。その結果、コードが読みにくくなります。

図 1: 複数の難読化パスにより、プログラム制御フローを解決する Ghidra などのツールの有効性が大幅に低下します。

単純な「add」や「mov」命令でさえ、あっという間に50、あるいは数百もの命令に発展する可能性があります。「adrp add」命令を適切に難読化することで、自動化ツール(ghidraやIDAなど)によるプログラム制御フローの解決能力を著しく低下させることができます。一見些細な難読化でも、攻撃者が「acceptUserCredentials」関数呼び出しの開始、終了、あるいは途中を特定することをほぼ不可能にしてしまう可能性があります。数百もの複合的で多様な難読化によって、潜在的な攻撃者はコードがどのように正常に実行されるのかさえ解明しようと試みることになります。

ボップして、ツイストして、構成する

アプリケーションにおいて、すべてのメソッドや関数呼び出しが機密性を必要とするわけではありません。また、一部のメソッドや関数呼び出しはパフォーマンスに大きく影響する場合があります。アプリケーション全体に均一に難読化を適用することは、何もしないよりははるかに優れていますが、実行時パフォーマンスに大きな影響を与える可能性があります。セキュリティエンジニアが機密性の高い呼び出しを高度に難読化し、パフォーマンスを低下させる呼び出しを軽度に難読化できるようにすることは、世界クラスの保護ツールを提供するための重要な要素です。アプリケーションに挿入される動的な保護(ガード)は、基盤となるソースコードに必要な難読化と同等の難読化が必要です。これらのアクティブなガードに同じ高度なセキュリティ難読化手法を適用することで、ガードの保護と実行を維持し、攻撃者がガードを特定して削除しようとする動きを遅らせることができます。セキュリティを重視する組織にとって、設定の柔軟性は不可欠であり、保護ツールは企業の方針に合わせて迅速に変更する必要があります。前述のように、難読化には異なる方法で構築されるものもあります。ここでは、本格的な難読化エンジンが提供するいくつかの概念と、承認されていないトラフィックをブロックする方法について説明します。

計算された制御フロー

攻撃者は、アプリケーション全体の関数呼び出しフローを調べるだけで、アプリケーションに関するかなりの情報を得ることができます。これに対抗するため、当社の難読化では計算制御フローと呼ばれる技術を採用しています。計算制御フローは、逆コンパイラが関数呼び出しとラベル参照をアプリケーションのメインエントリポイントに結び付けるのを阻止します。これは、世界クラスの保護において不可欠な要素です。逆コンパイラがバイナリを解析する際、ある関数が別の関数をどのように呼び出しているかを確認するのは、多くの場合簡単です。例えば、「b.eq 0x10055bc42」や「bl 0x100abcdef」のような命令を考えてみましょう。逆コンパイラは、これらの仮想メモリ位置に何が存在するかを正確に把握しています。前の2つの命令の場合、それは関数内のラベルか、関数呼び出しそのものです。優れた逆コンパイラであれば、関数呼び出しが絡み合った美しい蜘蛛の巣を描画し、アプリケーション全体の実行パスを明確に示します。これを、例えばアセンブリ内のどこで「ログイン成功」メッセージが使用されているかを確認するといった他の基本的なトリックと組み合わせると、攻撃者が悪用可能なコードを特定するのは容易になります。計算制御フローとは、明らかな制御フロー呼び出しの前に挿入される一連の数学演算です。これらの数学演算により、逆コンパイラはジャンプ先の正確な相対仮想アドレスを認識できなくなり、制御フローグラフを生成する能力を破壊します。

図 2: 計算された制御フロー (右) により、デコンパイラがジャンプ先の正確な相対仮想アドレスを認識できなくなり、機能する制御フロー グラフ (左) を生成する能力が破壊されます。

制御フローの平坦化

計算制御フローは、すでにデコンパイラにとって脅威となっています。これをさらに悪化させるのは、実に残念なことです。論理的な制御フローを崩すもう1つの戦略は、制御フローの平坦化(CFF)です。CFFには様々な形式がありますが、最近追加されたもの(Nexus)は、この重要な難読化手法に新たな息吹を吹き込んでいます。私たちは皆、`main` でチェスゲームを書いたことがありますが、実稼働レベルのアプリケーション全体を単一の自己参照型switch文で記述するのはどうでしょうか?Nexusは、実行時のパフォーマンスを優先しながら、まさにそれを実現します。CFF、その重要性、そしてその仕組みに関する情報は豊富にあります。この難読化手法が攻撃者の作業をどれほど困難にするかは、言葉では言い表せません。そのため、ステージング環境からCFFを除外したアプリは、必ずステージング環境から除外すべきです。

Cホップアップ

ステンレス製のナイフセットには、それに合うステンレス製のハサミが欠かせません。Chopup は、これとほぼ同じように制御フローの難読化を補完します。バイナリ ファイル形式は、通常、ディスク容量を節約するために高密度にパックされています。つまり、関連する関数呼び出しのほとんどは互いに非常に近い位置にあります。その結果、逆アセンブルされたバイナリは関連する関数をグループ化する傾向があり、ほとんどの場合、関数はバイナリ内で 1 つの連続したブロックとして存在します。これでは読みやすくなりすぎて、非常にイライラします。Chopup はこれを変えます。バイナリには、関数呼び出しがメモリ内で連続していることを要求する技術的な制限はなく、優れたハサミ (および柔軟な接着剤) があれば、バイナリを期待どおりに動作させながら、攻撃者が論理的な制御フローを探すためにバイナリの隅々までジャンプすることを余儀なくできます。

図 3: Chopup は、攻撃者に論理制御フローを探すためにバイナリの隅々までジャンプすることを強制します。

mgDaeaと修復

コードフロー自体を難読化することは重要な保護層ですが、基礎となるアプリケーション データを難読化することも同様に必要です。損傷と修復は、静的分析保護における混沌とした悪と秩序ある善であり、ほぼ常に連動しています。データの一部、または場合によってはコードの一部を損傷し、読み取りまたは実行の直前に修復すると、静的分析が事実上不可能になります。損傷により、指定されたデータはガベージ メモリのように見えるものに変更されます。同じデータが修復呼び出しにさらされると、多くの場合は使用される直前に元の形式に戻されます。そのデータは、スコープ外になった後に再び損傷される可能性があり、関数が次に呼び出されるまで使用されません。その API キーは、最初はバイナリ内で「1#&at0d$*nd@@z」かもしれませんが、使用前に修正されるので安心してください。

シンボル名の変更

ソースコードやデータの難読化を施しても、コンパイルされたバイナリにはソースコードのシンボル名が残ってしまいます。例えば、「acceptContinuousPayment」のような関数名のシンボルアーティファクトは、その関数の実装への直接リンクを簡単に提供してしまう可能性があります。一度見つけられてしまうと、アセンブリを改変して有料機能に無償でアクセスするのは容易です。包括的なシンボル名変更によって、残りのアーティファクトは隠蔽され、攻撃者が利用できるものは何もありません。保護されたバイナリから機密性の高い機能へのヒントや手がかりをすべて削除することで、攻撃者は静的解析を完全に諦めざるを得なくなります。

図 4: 包括的なシンボル名の変更により、残りのアーティファクトが隠され、攻撃者が操作できるものが何も残りません。

終了

これらは強力な難読化の実践と手法の一例に過ぎず、決して網羅的なリストではありません。アプリケーションを保護されていない状態で放置すると、誰でも固有のIPアドレスを完全に把握でき、攻撃者にはビジネスロジックを垣間見ることができるようになります。生成AIとソースコードコパイロットが急速に普及したことで、コードの作成、そして場合によってはリバースエンジニアリングがはるかに容易になりました。このように変化の激しい環境において、強力なセキュリティソリューションの実装に組織全体で取り組むことが、唯一現実的な道です。開発者の努力が無駄にならないよう、セキュリティ対策を怠らないようにしてください。

 

IDCの見解を読む 難読化と改ざん防止 あなたの一部として DevSecOps 練習。

デモプレースホルダージャングル

著者

コール・ヘルツォーク

企業を拡大する準備はできていますか?

詳しく見る

世界の最新情報 Digital.ai

2026 年 3 月 2 日

防衛研究所からモバイルアプリまで:アプリケーション保護の成長

2001 年はアプリケーション セキュリティにとって転換点となりましたが、…

もっと詳しく知る
2026 年 2 月 23 日

シュレックスクール Application Security

あるいは、私が心配するのをやめて、愛することを学んだ方法

もっと詳しく知る
2026 年 2 月 12 日

AIがあらゆるものを加速させるとき、セキュリティはよりスマートになる必要がある

ソフトウェア配信は新たな段階に入りました。2022年からはAI主導の…

もっと詳しく知る