同じ macOS IM クライアントでも、アップグレードのたびに、リバースのコストは少しずつ高くなる。これは「ホットアップデート」から「小バージョン」への段差の記録であり、何度も検証された経験でもある。バージョンをまたいで再利用できるのは、決してハードコードされた座標ではない。
2つのアップグレード、難度は一桁違う
- ホットアップデート:コードの位置だけを移し、関数本体は変わらない → 前のバージョンのアンカーを変位に合わせて全体平行移動すれば再利用できる。
- 小バージョン:関数本体を書き換える → 全体平行移動はすべて無効になり、再度特定しなければならない。
同じ「アップグレード」でも、この2つではリバースの作業量が一桁違う。
key を取る段差が最も急
初期バージョンでは、復号に使う key が識別できる形でプロセスのメモリに残されていた。そのため、多くの「読み取りだけ」のツールは、メモリをスキャンするだけで key を取得できた。新しいバージョンはこの道を塞いだ——すべての「純粋なメモリスキャン」による key 取得方法が、一斉にゼロへ戻された。
結論はとても明快だ。key 取得は「静的なメモリスキャン」から「実行時の動的観察」へと追い込まれ、敷居が急激に上がった。この一刀で切り落とされたのは、コミュニティで最大の部類に属するツールだった。
関数本体が書き換えられても、どうやって見分けるのか?
「呼び出し点のトポロジー」による。ある関数がどの子関数を呼び出しているか、そしてそれぞれの呼び出し点が関数内のどの相対位置にあるかは、関数本体そのものよりも、バージョンをまたいでずっと保守的に残る。
関数本体が派手にすっかり変わっていても、呼び出し点の位置列が一つずつ対応できるなら、新バージョンでも同じ関数だと見分けられる。これは「関数サイズで判定する / オフセットで全体平行移動する」よりずっと安定している。後者は関数本体の書き換えに遭うと役に立たなくなるが、前者は呼び出し構造が残っているかぎり有効だ。
メタな教訓
ハードコードされたアドレス、メモリ上のリテラルに対するスキャンは、どれも流砂だ——次のバージョンで洗い流されてしまう。生き残れるのは、構造の不変条件(呼び出しトポロジー、命令パターン)と**動的観察**だけだ。
ターゲットが強化されているなら、リバースも「座標を探す」ことから「不変条件を探す」ことへ進化しなければならない。
コメント
コメントは即時公開されますが、ポリシー違反時は非表示になる場合があります。