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