アクセスカウンタ - Windowsプラットフォームで、カーネルレベルのファイルへのアクセス
1。背景
shinobi.jp - アクセス解析, ブログ, カウンター とかを提供しているNINJA TOOLSの別館的サイト
。kernel32のからのCreateFile / ReadFileは/のWriteFile関数は、ローカルシステムサービスに、ファイルシステムとFilterDriverするには、レベルの多くの経験。それぞれのレベルでは、セキュリティソフトウェア、ウイルスやバックドアが監視したり、フィルタの機会のためにそこにいる。セキュリティ製品の開発として、我々は他のものよりも、我々は我々は適切なファイルシステムをきれいに見ることができるように低レベルの"Windowsプラットフォーム、カーネルレベルのファイルへのアクセス"アプローチを必要とする先に進む必要がある。
2。使用
。。。これらの側面を監視するためには、監視プログラムの更新に合わせて設計することができる最新のモニタリング技術をバイパスすることができます。
3。カーネルレベルのファイルアクセスへのダイレクトアクセスは、FSDの
。我々はFSDに当社独自のドライバでは、オペレーティングシステムを模倣することができます場合は、APIフックなど、上記対策を回避するためのネイティブAPIとWin32 APIの、また、これらのレベルで設定をバイパスすることができますIRPを、に直接送信されます。
3.1が作成し、ファイルを開きます。
作成し、IoCreateFileを完了するには、関数を呼び出すか、FSDのにIRP_MJ_CREATEを送ることができるファイルを開きます。。。IoCreateFile関数を使用してサンプルコード:
HANDLE openfile(WCHAR* name,ACCESS_MASK access,ULONG share)
{
//return 0 for error.
HANDLE hfile;
IO_STATUS_BLOCK iosb;
int stat;
OBJECT_ATTRIBUTES oba;
UNICODE_STRING nameus;
///
if(KeGetCurrentIrql()>PASSIVE_LEVEL){return 0;}
RtlInitUnicodeString(&nameus,name);
InitializeObjectAttributes(&oba,&nameus,OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE,0,0);
stat=IoCreateFile(&hfile,access,&oba,&iosb,0,FILE_ATTRIBUTE_NORMAL,share,FILE_OPEN,0,0,0,0,0,0);
if(!NT_SUCCESS(stat)){return 0;}
return hfile;
}
HANDLE createnewfile(WCHAR* name,ACCESS_MASK access,ULONG share)
{
//return 0 for error.
HANDLE hfile;
IO_STATUS_BLOCK iosb;
int stat;
OBJECT_ATTRIBUTES oba;
UNICODE_STRING nameus;
///
if(KeGetCurrentIrql()>PASSIVE_LEVEL){return 0;}
RtlInitUnicodeString(&nameus,name);
InitializeObjectAttributes(&oba,&nameus,OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE,0,0);
stat=IoCreateFile(&hfile,access,&oba,&iosb,0,//AllocationSize this set to 0 that when file opened it was zeroed.
FILE_ATTRIBUTE_NORMAL,share,FILE_OVERWRITE_IF,0,0,0,0,0,0);
if(!NT_SUCCESS(stat)){return 0;}
return hfile;
}
法等によりFSDへIRP_MJ_CREATEを送信、命令IFSDDK文書IRP_MJ_CREATEを参照することができます。上記の方法では、このメソッドは、ハンドル、ハンドルのスレッドを依存する必要がないことよりも上記の方法ではFILE_OBJECTに、よりよい作成する必要が異なる場合は、FileObjectのは、スレッドとは無関係です。
3.2の読み込み、ファイルをお書きください。
我々は、IRP_MJ_WRITEファイルを書き換えるFSDへ送信されたドキュメントを読んでFSDのIRP_MJ_READに送信。
。私たちはFileObjectのにIRPを送信することができます。
stat=ObReferenceObjectByHandle(handle,GENERIC_READ,*IoFileObjectType,KernelMode,(PVOID*)&fileob,0);
その後、我々はIoAllocateIrpでIRPを割り当てる。のFileObject ->デバイスオブジェクト-> Flags値によると、我々は、ターゲットファイルシステムを使用するかを決定かIOの方法の種類。
if(fileob->DeviceObject->Flags & DO_BUFFERED_IO)
{
irp->AssociatedIrp.SystemBuffer=buffer;//buffered io
}
else if(fileob->DeviceObject->Flags & DO_DIRECT_IO)
{
mdl=IoAllocateMdl(buffer,count,0,0,0);
MmBuildMdlForNonPagedPool(mdl);
irp->MdlAddress=mdl;//direct io
}
else
{
irp->UserBuffer=buffer;//neither i/o, use kernel buffer
}
。我々は、ドメインのIRP内のパラメータを埋めるには、IRPを送信することができます。
irpsp->FileObject=fileob;
irpsp->MajorFunction=IRP_MJ_READ;
irpsp->MinorFunction=IRP_MN_NORMAL;//0
irpsp->Parameters.Read.ByteOffset=offsetused;
irpsp->Parameters.Read.Key=0;
irpsp->Parameters.Read.Length=count;
IRPが時間内に完了されていない場合、非同期に返されますが、考えて、私たちが読むか、または完了している書き込み操作をメインスレッドの私たちに知らせるために有効化されているCompletionRoutineでイベントを設定CompletionRoutineをインストールする。
IoSetCompletionRoutine(irp,IoCompletion,&event,1,1,1);
NTSTATUS
IoCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
KeSetEvent((PRKEVENT)Context, IO_DISK_INCREMENT, 0);
return STATUS_MORE_PROCESSING_REQUIRED;
}
。。。
stat=IoCallDriver(fileob->DeviceObject,irp);
if(stat==STATUS_PENDING){
KeWaitForSingleObject(&event, Executive,KernelMode,0,0);
stat=irp->IoStatus.Status;
}
if(!NT_SUCCESS(stat))
{
IoFreeIrp(irp);
if(mdl){IoFreeMdl(mdl);}//if DO_DIRECT_IO
return -1;
}
stat=irp->IoStatus.Information;//bytes read
IoFreeIrp(irp);
if(mdl){IoFreeMdl(mdl);}//if DO_DIRECT_IO
return stat;
3.3ファイルの削除
削除は、実際には、IRPのFSDののIRP_MJ_SET_INFORMATIONを介して送信されますIrpSp -> Parameters.SetFile.FileInformationClassは、実行するには、バッファFILE_DISPOSITION_INFORMATION構造を充填し、FileDispositionInformationに設定。
fdi.DeleteFile=TRUE;
irpsp->MajorFunction=IRP_MJ_SET_INFORMATION;
irpsp->Parameters.SetFile.Length = sizeof(FILE_DISPOSITION_INFORMATION);
irpsp->Parameters.SetFile.FileInformationClass = FileDispositionInformation;
irpsp->Parameters.SetFile.DeleteHandle = (HANDLE)handle;
3.4ファイルの名前を変更
削除と同様に、名前の変更は、FSDののIRP_MJ_SET_INFORMATIONのIRPに送られ、IrpSp -> Parameters.SetFile.FileInformationClassはFileRenameInformationに設定すると、FILE_RENAME_INFORMATIONのバッファ構造を埋める。
fri.ReplaceIfExists=TRUE;
fri.RootDirectory=0;//Set fri.FileName to full path name.
fri.FileNameLength=wcslen(filename)*2;
wcscpy(fri.FileName,filename);//If the RootDirectory member is NULL, and the file is being moved to a different directory, this member specifies the full pathname to be assigned to the file.
irpsp->MajorFunction=IRP_MJ_SET_INFORMATION;
irpsp->Parameters.SetFile.Length = sizeof(FILE_FILE_RENAME_INFORMATION);
irpsp->Parameters.SetFile.FileInformationClass = FileRenameInformation;
要約すると、我々はIRPがネイティブAPIとWin32 APIレベルをバイパスして、ファイルシステムにアクセスするために送信することによって直接が駆動することができます。
4。バイパスファイルシステムフィルタドライバとフック
内容の第三部では、我々は今FSDの操作ドキュメントに直接要求を送信することができます。または、多くのアンチウイルスソフトウェアや監視ツールFSDのフィルタドライバがあるので、FSDのフックがファイル操作を監視するための手段しかし、それは、十分ではなかった。。
通常のファイルシステム上でシステムフィルタドライバをファイル添付し、監視し、我々のファイルへのアクセスのフィルタリング。。我々は、ファンクションドライバオブジェクト(FDO)の底部に対応するのFileObjectを取得するためにIoGetRelatedDeviceObjectにこの関数を使用することができます。でもでも、かかわらず、フィルタドライバをバイパスするものがFSDは、通常の存在は、フィルタドライバのとおりですので、または、NTFS / Fastfat、通常のFSDをバイパス。ディスク上のファイルは、オブジェクトのFDOの下部に対応するFtdisk.sysされ、それがあまりにも低レベルであるため、IRPの配信のための私達の要求を処理することはできませんが。
実際には、Vpb FSDの構造体に格納され、通常の情報は、我々はそれを得るためにIoGetBaseFileSystemDeviceObjectを文書化されていないカーネル関数を使用することができます。これは、IRPを送信するために我々の目標です。
4.2はFSDのフックDispatchRoutineを置き換えるに対処する
これは、FSDのフックの一般的な方法です。。。ここで考えている:私たちは、元のFSDの駆動読むことができます。 INITセクション、または。テキストセグメントは、必ず独自のセットDriverObjectすべてDispatchRoutineでのDriverEntry関数のDriverEntry関数を見つけるために。この関数では、我々はDispatchRoutineをするアドレスを見つけることができます。ただ、この値を検索できる検索メソッドのシグネチャを使用して。
インラインフックDispatchRoutineと4.3契約自体がフックをFSDの機能
この悪質なフックとの比較ではなく、非常にセキュリティ製品の一般的な、トロイの木馬やルートキット、ルートキットの一般的なアプリケーションは、私はそれを自分で書いたような。それは、DispatchRoutineのDriverObject関数ポインタ内で変更されませんJMPの関数の先頭には、関数をジャンプしてアセンブリ命令を記述する。基本的な考え方は、メモリにクリーンなバックアップのファイルは、負荷を読んでFSDのディスク上にそれに対処するためには、我々は、バックアップの最初の数バイトを見ているこのクリーンと一致しているDispatchRoutineを呼び出す。そうでない場合は、JMP命令は、RET、アセンブリ命令のINT3のクラスがある場合は特に、それはインラインフックがあることを、非常に可能性があります。。)がある場合はインラインフックは、我々は、オーバライド機能上の関数のクリーンコピーから始めましょう感染第一。。
5。ありがとう
。