はじめに
下記記事のまとめで話しているADSにあるファイルが実行できるかどうかの検証をしてみた
Windowsでtmpファイルを実行する話。
やってみた
まず、ADSにバイナリ値をコピーしたいのでとりあえずプログラムを書いてみる。
普通のコマンドプロンプトとかのリダイレクトだと文字列として扱われる可能性があったりするので今回は使わない。
とはいえ、普通のコピーを行うだけのプログラムなので特段特殊なことはしていない。
ただし、Windows APIを直に使ったほうが良さそうなので、CreateFileとReadFile/WriteFileAPIを直に使っている。
(C言語処理系のライブラリ依存な実装でファイルシステム固有の操作はバグに繋がりそうなので極力したくない)
普通のコピープログラム(copy.exe)のソース
#include<stdio.h>
#include<windows.h>
int main(int argc,char* argv[]){
int status = 0;
if(argc<=2){
printf("specify the source and destination file name for argument.\n");
printf("%s <source(file)> <destination(file)>",argv[0]);
return -1;
}
HANDLE hReadFile = CreateFile( argv[1], GENERIC_READ , FILE_SHARE_READ , NULL ,
OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL , NULL);
if (hReadFile == INVALID_HANDLE_VALUE) {
printf("file access failure.(read)");
status = -1;
goto readOpenFailure; // Close処理を共通化したいのであえてgoto使う。
}
HANDLE hWriteFile = CreateFile( argv[2], GENERIC_WRITE , 0 , NULL ,
CREATE_ALWAYS , FILE_ATTRIBUTE_NORMAL , NULL);
if (hWriteFile == INVALID_HANDLE_VALUE) {
printf("file access failure.(write)");
status = -1;
goto writeOpenFailure; // Close処理を共通化したいのであえてgoto使う。
}
#define BUF_SIZE 4096
// コピー処理
char buf[BUF_SIZE]={};
DWORD read_size=BUF_SIZE;
DWORD write_size=0;
while(read_size==BUF_SIZE){
ReadFile(hReadFile,buf,BUF_SIZE,&read_size,NULL);
WriteFile(hWriteFile,buf,read_size,&write_size,NULL);
}
// ハンドルのクローズ
generic_error:
CloseHandle(hWriteFile);
writeOpenFailure:
CloseHandle(hReadFile);
readOpenFailure:
return status;
}
コピー先のファイル(このファイルのADSに実行ファイルを配置する)
自分で撮った星の写真。これ奥多摩なんですよ。奥多摩マジですごくないですか?
で、このファイルのADSを出してみる。何もしていないので空の状態ですね。
PS D:\Users\segfo\Documents\vmShare\testCodes\test_windows\infect> get-item .\DSC_0008-1.jpg -stream *
PSPath : Microsoft.PowerShell.Core\FileSystem::D:\Users\segfo\Documents\vmShare\testCodes\test_windows\infect\DSC_0008-1.jpg::$DATA
PSParentPath : Microsoft.PowerShell.Core\FileSystem::D:\Users\segfo\Documents\vmShare\testCodes\test_windows\infect
PSChildName : DSC_0008-1.jpg::$DATA
PSDrive : D
PSProvider : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
FileName : D:\Users\segfo\Documents\vmShare\testCodes\test_windows\infect\DSC_0008-1.jpg
Stream : :$DATA
Length : 556810
画像のADSにexeをコピーしてみる(準備編)
普通にやっても面白みがないので、特殊ファイルっぽさを出してみる。
Zone.IdentifierというADSのファイルがよく使われるのでドットを消してコピーしてみる(そのままコピーするとWindowsのファイルとして扱われてしまうので)
この検証環境のディレクトリ的にはこんな感じ。
copy.exe: 上記のコピープログラム
create_process.exe: CreateProcessでプログラムを実行するだけのアプリ(実装はWindowsでtmpファイルを実行する話。で記載)
test.exe: ADSに突っ込むアプリ(実装はWindowsでtmpファイルを実行する話。で記載。test.tmpという名前のファイルと同一のバイナリです。)
画像のADSにexeをコピーしてみる(実行編)
コピーの実行
> ./copy .\test.exe .\DSC_0008-1.jpg:ZoneIdentifier
実行後のADSの中身
PS D:\Users\segfo\Documents\vmShare\testCodes\test_windows\infect> get-item .\DSC_0008-1.jpg -stream *
PSPath : Microsoft.PowerShell.Core\FileSystem::D:\Users\segfo\Documents\vmShare\testCodes\test_windows\infect\DSC_0008-1.jpg::$DATA
PSParentPath : Microsoft.PowerShell.Core\FileSystem::D:\Users\segfo\Documents\vmShare\testCodes\test_windows\infect
PSChildName : DSC_0008-1.jpg::$DATA
PSDrive : D
PSProvider : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
FileName : D:\Users\segfo\Documents\vmShare\testCodes\test_windows\infect\DSC_0008-1.jpg
Stream : :$DATA
Length : 556810
PSPath : Microsoft.PowerShell.Core\FileSystem::D:\Users\segfo\Documents\vmShare\testCodes\test_windows\infect\DSC_0008-1.jpg:ZoneIdentifier
PSParentPath : Microsoft.PowerShell.Core\FileSystem::D:\Users\segfo\Documents\vmShare\testCodes\test_windows\infect
PSChildName : DSC_0008-1.jpg:ZoneIdentifier
PSDrive : D
PSProvider : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
FileName : D:\Users\segfo\Documents\vmShare\testCodes\test_windows\infect\DSC_0008-1.jpg
Stream : ZoneIdentifier <----これ
Length : 3412126
うまくコピーできているようです。ディレクトリに変化は有りません。
ただし、見えないところでの変化は上記の通りしています。
Alternate Data StreamにZoneIdentifierが追加されました。
ではこれを実行してみましょう。
タスクマネージャ(プロセスタブ)
タスクマネージャ(詳細タブ)
というわけで、出来ました。あたかも、jpgファイルが実行されているかのようですね。面白いですね。
Forensics的観点だと、こういうADSに潜むマルウェアも見なければなりませんね、という検証記事でした。
では今日はこんなところで。