講座11 ディスクチェック解除 後編

ディスクチェック編ラストです

長らくお待たせしましたが、ようやくディスクチェックに関する講座も最後です。
ではいってみましょう♪

前回は…

手動でディスクチェックの通過フラグを強制的にONにすることにより、
キーディスクが入っていないにも関わらず、本来はキーディスクが無ければ
続行されないはずの正常処理へと繋ぐことに成功しました。
ただ、毎回プロセスエディタを起動して手動で書き替えるのは非常に面倒です。
しかしキーディスクが入っている場合はフラグがONになるということは、
キーディスクの有無によりフラグのON/OFFを行うという処理があるはずです。
この有無を判定するのが、おなじみ判定ジャンプです。
ですが、その処理がどこにあるか、実は前回すでに確認しています。
それは…
:0040109A 750A          jne 004010A6
:0040109C C785FCFEFFFF01000000  mov dword[ebp+FFFFFEFC], 00000001
前回、フラグをON/OFFしている部分を探すという項目名で解説しましたね。
アドレス dword[ebp+FFFFFEFC] に格納されている値がフラグであり、
mov命令を使って、このアドレスの値を 01 にすることで通過フラグをONにする…。
これは、この後編を見るまでもなく気づいた人も多いかと思います。

アドレス 0040109A にある判定分岐 jne によりフラグを書き替えるかどうかを判定してるんですから、
この判定分岐を潰してしまえば、強制的にフラグがONになるはずですね。
それではやってみましょう。
:0040109A 750A          jne 004010A6

:0040109A 90           nop
:0040109B 90           nop
毎度おなじみ、nop命令です。
これで「ディスクが入っていない場合はフラグをONにする処理を飛び越える」という
処理が、事実上、無効化されるはずです。

なお別の方法としてはフラグの有無を確認する処理を書き替えるというパターンもあります。
今回のリストでは…
:004010AB 83BDFCFEFFFF01 cmp dword[ebp+FFFFFEFC], 00000001 // もしフラグが01
:004010B2 7502      jne 004010B6            // でなければ分岐
:004010B4 EB2D      jmp 004010E3            // 無条件分岐
の処理を書き替えることになります。
01がフラグON(正常)ですので、2行目の条件分岐命令jneでは不正なら分岐という処理になります。
分岐先のアドレス 004010B6 からは警告メッセージを表示する処理が続いているので間違いありません。
そして3行目の無条件分岐の飛んだ先のアドレス 004010E3 には正常終了処理があります。
ここまで説明すればわかると思いますが、この場合、書き替えるとすれば…
:004010B2 7502      jne 004010B6

:004010B2 90       nop
:004010B3 90       nop
と、なりますね。
これでディスク(フラグ)の有無に関わらず、最終チェックを必ず通過するようになり、
結果、キーディスク無しで起動するようになります。

おしまい?

はい、おしまいです(笑
さんざん引っ張った割に、意外とあっけない最後ですが、まぁこんなもんです。
ただ、これだけで終了〜…というにはあまりにも短すぎるので、以下、別のパターンに
出会ってしまった場合の対処法をお教え致します。

Case1 GetVolumeInformationが見つからない

そりゃボリュームラベルでチェックしてないから〜としか言いようがありませんが、
まあ、とりあえず以下のようなものが挙げられます。

FindFirstFileA … チェック用ファイルを検索し、その有無を判定。
CreateFileA … チェック用ファイルを読み込み、成功(失敗)したかどうかを判定。
OpenFile … CreateFileAと同じチェックだが、専ら使われているのは古いソフト。
GetFileAttributesA … ディスク上のファイルの属性を取得し、そのコードを判定(エラーは-1)。

他にも多々チェックの種類はありますが、以上の命令を覚えておけばとりあえずは大丈夫と思います。

Case2 ディスクチェック処理はあるけど判定分岐が無い

これは、ディスクチェック処理のみがサブルーチンになっていると考えられます。
この場合、どんなに処理を追いかけても最後は大体 ret という命令で終わっていると思います。
retを使うと、この処理のコール元(メインルーチン)に戻ることができるのですが、
そのコール元の直後に最終チェックが存在する可能性が高いです。

コール元の見つけ方ですが、デバッガでコールスタックを追跡しても良いのですが、
とりあえずは簡単な方法としてサブルーチンの先頭行を見つけるという方法があります。
別に難しく考える必要はなく、ディスクチェック処理をひたすら逆スクロールさせるだけです。
しばらく見ていると…
=========
:00401062 55        push ebp
とまぁ、[=]が9個続く行が見つかると思います(※Disassemの場合)
…ここが先頭行です(早

続いて先頭行のアドレスを確認します。
上記の例ではアドレス 00401062 が先頭アドレスとなりますので控えておきましょう。
そして、逆アセンブルリストからこのアドレスである 00401062 を検索してみます。
すると…
:00401014 E849000000    call 00401062
というようにcall **という命令にヒットすると思います。
これがコール元であり、この処理の周辺を探せば最終チェック用の分岐が見つかるはずです。

さいごに

長〜〜〜〜い説明になりましたが、全3編のディスクチェック解説でした。
なお、さらに別パターンを知りたい方は「キーディスクチェック解析」のコンテンツも見てくださいな。

もちろん、最終目標は市販ソフトのディスクチェックを解除することにあります。
現在の法律では、解除するためのパッチやプログラムを配布することは違法ですが、
個人的に製作することについては合法です。
というわけで、アナタも挑戦してみましょう!