GetDriveType系練習問題

認証用ISO 認証している場合が見たい時に
http://dl.dropbox.com/u/13673436/SAMPLE.iso
説明用
http://dl.dropbox.com/u/13673436/GetDriveType.AllDrive.exe
練習問題1
http://dl.dropbox.com/u/13673436/GetDriveTypeFuncA.exe
http://dl.dropbox.com/u/13673436/GetDriveTypeFuncA.cpp
練習問題2
http://dl.dropbox.com/u/13673436/GetDriveTypeFucnB.exe
http://dl.dropbox.com/u/13673436/GetDriveTypeFucnB.cpp

練習問題の解答
説明用
ドライブ名チェック部分

00EF10BD     85C0           TEST EAX,EAX
00EF10BF  |. 74 3D          |JE SHORT GetDrive.00EF10FE

解析

00EF10BD     85C0           TEST EAX,EAX

TEST->XORにする。XORにすると判定条件がひっくり返るのでSAMPLEというディスクがあった場合には認証失敗になる。もし、それが困るならTESTの下のJNZをNOPで潰した方がいいだろう。

ドライブの種類チェック部分

00EF1069  |. 83F8 05        |CMP EAX,5
00EF106C  |. 75 53          |JNZ SHORT GetDrive.00EF10C1

JNZ SHORT GetDrive.00EF10C1->NOP

0000046C: 75 90
0000046D: 53 90
000004BD: 85 33

HDDしか存在しないドライブもあるのでドライブタイプが違っている場合でもジャンプしないようにした。

GetDriveTypeFuncA.exe

013510F5     84C0           TEST AL,AL
013510F7    ^74 90          JE SHORT GetDrive.01351089
013510F9   . C74424 0C 2021>MOV DWORD PTR SS:[ESP+C],GetDrive.013521>
01351101   . C74424 08 2021>MOV DWORD PTR SS:[ESP+8],GetDrive.013521>;成功
01351109   .-FF25 B8203501  JMP DWORD PTR DS:[<&USER32.MessageBoxW>] ;  USER32.MessageBoxW
0135110F   > C74424 0C 2C21>MOV DWORD PTR SS:[ESP+C],GetDrive.013521>;  ASCII ""8D,"",8A,"<",8A,"1YWe"
01351117   . C74424 08 3821>MOV DWORD PTR SS:[ESP+8],GetDrive.013521>;失敗
0135111F   .-FF25 B8203501  JMP DWORD PTR DS:[<&USER32.MessageBoxW>] ;  USER32.MessageBoxW

解析

013510F7    ^74 90          JE SHORT GetDrive.01351089

JE->NOP
000004F7: 74 90
000004F8: 16 90

GetDriveTypeFucnB.exe

012F11B0  /$ 83EC 44        SUB ESP,44
012F11B3     E8 90909090    CALL 91BFA248
012F11B8     84C0           TEST AL,AL ;
012F11BA  |. 75 1D          JNZ SHORT GetDrive.012F11D9

CALL 91BFA248でドライブのチェック関数を呼んでる。失敗した場合は関数内でMesageBoxを呼び出す。
JNZ で飛ぶとウインドウを消して、終了する。CALL命令をNOPで潰して終了

前回作った全ドライブ調べてドライブの文字列がSAMPLEというのがあったら成功というプログラムの解析が思った以上に難しかったので、文字列のみ比較するプログラムを作成し、そしてそのプログラムの解析を行った。
バイナリ
http://dl.dropbox.com/u/13673436/CompreString.exe

ソース

#include <stdio.h>
#include <windows.h>
#include <tchar.h>
#include <locale.h>
int WINAPI WinMain(
		HINSTANCE hInstance ,
		HINSTANCE hPrevInstance ,
		LPSTR lpCmdLine ,
		int nCmdShow ) {
    setlocale( LC_ALL, "Japanese");  //ロケール(地域言語)を日本語でセット
	   WCHAR volumeName[10] = L"ユニコード文字列";
	if(wcscmp(volumeName,_T("SAMPLE"))==0)
	{
		MessageBox(NULL , TEXT("認証成功") ,
		TEXT("認証成功") ,
		MB_OK | MB_ICONINFORMATION);
	} else {
		MessageBox(NULL , TEXT("認証失敗") ,
		TEXT("認証失敗") ,
		MB_OK | MB_ICONINFORMATION);
	}
	return 0;
}

解析

00BA108D  |. 85C0           TEST EAX,EAX			   ;EAXは1
00BA108F    ^75 90          JNZ SHORT CompreSt.00BA1021
00BA1091  |. 68 3421BA00    PUSH CompreSt.00BA2134
00BA1096  |. 68 3421BA00    PUSH CompreSt.00BA2134
00BA109B  |. EB 0A          JMP SHORT CompreSt.00BA10A7
00BA109D  |> 68 4021BA00    PUSH CompreSt.00BA2140                   ;  ASCII ""8D,"",8A,"<",8A,"1YWe"
00BA10A2  |. 68 4021BA00    PUSH CompreSt.00BA2140                   ;  ASCII ""8D,"",8A,"<",8A,"1YWe"
00BA10A7  |> 6A 00          PUSH 0                                   ; |hOwner = NULL
00BA10A9  |. FF15 B020BA00  CALL DWORD PTR DS:[<&USER32.MessageBoxW>>; \MessageBoxW

TEST EAX,EAXはAND演算を行ったつもりになる命令。”したつもりなので”ゼロフラグが変化するだけ。
JNZ SHORT CompreSt.00BA1021 JNZ(Jump Not Zero)はゼロ以外であればジャンプする命令。今回はEAXが1なのでジャンプする。ANDは両方1のときのみ1ORは両方1のときに1に。XORは「0と1」か「1と0」のときのみ1

ここでジャンプしないようするためにはJNZをNOPにして命令を潰すかTESTをXORにする。
XORに変えた場合
0000048D: 85 33