講座09 ディスクチェック解除 前編

〜はじめに〜

ついに、本格的なプログラム改造をお教えします。
その第1段として「ディスクチェックの解除」の解説をします。
「あれ? CDチェック解除の解説は…?」と思うかもしれませんが、
それについては後ほどで…

そもそもディスクチェックとは?

本来は違法コピーを防止する役割であったり、CD−DAでBGM再生する場合などに用いられてました。
現状ではCD−Rドライブも普及しましたし、コピー防止というのは結構減っています。
(SAFE DISCなどのように、時代にひたすら逆行するようなものもありますが…)

で、ディスクチェックは基本的に「***のCDを挿入してください」などの
メッセージを表示して終了・再試行するようなものが大半です。

ディスクチェック解除のターゲットは〜

私の作ったサンプルです(苦笑
メーカーさんの、CDチェック付きのゲームを改造したほうが実用的なのですが、
そうすると、不正競争防止法をギリギリ回避〜…な内容ですので…(汗
>>とりあえずサンプルをダウンロード

サンプルの中身

これは、「キーディスクチェック解析」で公開されている No.01 と同じものです。
ファイル構成は〜
はじめに.TXT … 推奨環境などを記述してます。
使用手順.TXT … 内容解説、キーディスクの作成方法などの全般的なマニュアル。
CHK_VOL .CPP … VisualC++用ソースファイル(Borland C++ Compilerも可能)。
CHK_VOL .EXE … サンプルの実行ファイル本体。
ASM解析 .TXT … サンプルを逆アセンブルし、リスト出力したものにコメントをつけたもの。
というふうになっています。

ちなみに、このサンプルのキーディスクとは「フロッピーディスク」です。
最近は付いてないPCもあるそうですが、まぁ、何とかしてください(ぉ
さすがに、CDチェックサンプルを作って、キーディスクのCDイメージをアップして、
「焼いてから使ってね♪」というのは…(苦笑
(別に難しくは無いんですけど、コスト面に問題が…)

あと、解析の際に「ASM解析.TXT」を見ながら作業を行うのも良いですが、スキルを付けるならば、
自力で CHK_VOL.EXE を逆アセンブルし、リスト出力したものを見てから作業をすると良いです。
ちなみに、リスト出力をDOSプロンプトで行う場合は、
DSASSM02 CHK_01.EXE > LIST.ASM
ですね(これで LIST.ASM というファイル名で出力されます)。

リストからディスクチェック処理を探す

出力した逆アセンブルリストをテキストエディタで開いたら、とりあえず何も考えずに
GetDriveTypeA という文字列を検索してみましょう。
すると、
Addr:000055A0 hint(0104) Name: GetDriveTypeA
…全然関係ありません(ぉ
とまぁ、1発くらいは無関係なところに該当したりもしますが、気にせずに次を検索します。
:00401059 FF1504504000      call dword[00405004]
               ;;call KERNEL32.GetDriveTypeA
一番左にアドレス、すぐ右にバイナリデータ、一番右に命令。
以降を検索しても該当する場所は無し…というわけでヒットしました。
いきなりですが、ここがディスクチェック処理の1ステップ目とも言える部分です。

たま〜に例外もありますが、基本的にディスクチェックを行う処理には GetDriveTypeA が
使われているので、この文字列をサーチしたら一発ヒット〜というわけです。

そもそも GetDriveTypeA とは?

名前のとおり「ドライブの種類を取得する命令」です。
VisualC++などで組む場合は drivetype=GetDriveType("A:\\"); って感じに使います。
この例だと、Aドライブの装置の種類判別用の数値が drivetype 変数に返されます。
なお、数値は以下のようになっています。
0 … 判別不能
1 … 指定した装置(ルートディレクトリ)は存在しない
2 … 取り外し可能なメディア(フロッピーとか)
3 … 取り外し不可なメディア(ハードディスクとか)
4 … リモート(ネットワーク)ドライブ
5 … CD-ROMドライブ
6 … RAMディスク
この数値を判定することにより「目的のドライブがキーディスクドライブの媒体かどうか?」を判別。
つまり、ディスクチェックの1ステップ目は「ドライブの種類を得る」ということにあります。

ということは…

種類判別用の数値を見て気づいた人も居ると思いますが、2がフロッピーで、5がCD-ROMドライブ…
そう、フロッピーチェックだろうがCDチェックだろうが、実はやってることはほとんど同じです。
サンプルで GetDriveTypeA を検索してフロッピードライブ判定処理を見つけるように、
市販ソフトでも GetDriveTypeA を検索してCDドライブ判定処理を見つけることができます。

ってわけで、とりあえずサンプルの GetDriveTypeA のすぐ下2行を見てみましょう。
:0040105F 83F802         cmp eax, 00000002
:00401062 7542          jne 004010A6
何と言うか、まんまですね(笑
この2つの命令については第7回を参照していただくとして、これは順に、
cmp eax, 00000002(eaxレジスタが 00000002)
jne 004010A6   (でなければ(Jump not equal)アドレス 004010A6 に分岐)
という動作をしています。
eaxレジスタが 00000002 でなければアドレス 004010A6 に分岐…これは言うまでもなく、
ドライブをチェックしたときに返ってきた値が2(フロッピー)でなければ分岐という処理ですね。

書き替える

これは言うならば、
「CDドライブが付いてないマシンでCDチェックを行うと、ドライブが見つからなくて起動不可」
という現象の原因とも言える部分だったりします。
では、今回はここを書き替えるパターンを紹介します。

1.チェック対象ドライブの種類を変更する

例えば、サンプルだと「判別用の数値 2(フロッピー) が見つからなければ起動不可」という動作ですが、
これを判定用の数値 3(ハードディスクなど) に変更します。
これで、ハードディスクを搭載していれば……普通はウインドウズマシンでハードディスク無し
というのは聞かないので(笑)、100%処理を続行させることが可能になります。
ちなみに書き替えるには
:0040105F 83F802         cmp eax, 00000002

:0040105F 83F803         cmp eax, 00000003
ん〜、たった1バイト変更するだけ。簡単ですねぇ。
ちなみに書き換えには、バイナリエディタを使ってくださいな。

2.判定分岐を無効にする

「ドライブが見つからなかったら分岐」とか、この判定分岐を無効にしてしまえば、
もちろん、通過するようになります。
逆を言えば「ドライブが見つかれば分岐」ならば無条件分岐にすればOKです。
というわけで、無効にするにはいつもどおり
:00401062 7542          jne 004010A6

:00401062 90           nop
:00401063 90           nop
nopで埋めるだけですね。
もちろん、無条件分岐ならば
:00401062 7542          jne 004010A6

:00401062 EB42          jmp 004010A6
です。
(ただし、サンプルでこの部分を無条件分岐にすると、永遠にドライブ発見不可に…(苦笑)
 というか、CDチェックの場合は前者以外見たこと無いです)

さいごに

と、ドライブ種類を取得する処理の動作を書き替える方法を紹介したところで次回に続く〜です。
次回は「ディスクチェック解除 後編(予定)」です。
おたのしみに〜
…と言ってたのですが、次回は中編になりました(苦笑
ごめんなさいぃ〜〜〜

>>NEXT STEP