撰寫本系列文章目的在於提升資訊安全之實務能力,
並透過實作體悟到資訊安全領域的重要性,
本系列所有文章之內容皆有一定技術水平,
不得從事非法行為、惡意攻擊等非法活動,
「一切不合法規之行為皆受法律所約束」,
為了避免造成公司、廠商或玩家之間困擾,
所有實作不會拿已上市產品、Online Game 等等來作範例學習,
且部分具有深度、價值之內容,將會提升一定閱讀門檻(不對該技術做分析、解說),
請勿透過本系列文章所學,從事任何非法活動,請不要以身試法!!!
學會這個,就可以把邪惡的東西藏在硬碟裡了XD
首先要先說一下,
小弟我目前還屬於菜鳥階段,正不斷努力學習中,
若有發現錯誤或不妥之處還請不吝賜教。
歡迎大家多多留言,互相交流交流。
那麼進入今天主題~~
使用這個 Project 隱藏後的檔案或目錄,實際上還是存在的,
但這個 Project 不會讓你/妳用「正常」的方式瀏覽、打開(有絕對路徑也一樣),
Mini Filter 是向 Filter Manager 註冊一些 callback operations,
通過這些 callback operations 來過濾一些「基於 IRP 的 I/O 操作」,
而每個選定的 IRP 都可以各自註冊一個:
更多詳細內容可看官方文件,這邊就不多做說明:
再來就是你/妳可能會問:
這就要講到 Mini Filter 的小規則,
執行的順序會由 Altitude 來決定,
當 Altitude 越高,就會越先執行你/妳所註冊的 preoperation,
根據 Altitude 的大小依序由大到小執行 preoperation,
當這個 IRP 操作已經執行或應該說已經執行完成,
則會依照 Altitude 的大小依序由小到大執行 postoperation。
完整解釋就是官方文件上的這張圖:
圖片來源:Filter Manager Concepts
Altitude 怎麼看?
可以用 YDark 這個ARK工具找到:
Altitude 怎麼改、又是如何決定?
這個 Project 是過濾以下「IRP」的操作來達到隱藏效果,
IRP_MJ_DIRECTORY_CONTROL
IRP_MJ_CREATE
好,那簡單說明一下這個 Project 的流程:
最後你/妳可能會問:
#define _NO_CRT_STDIO_INLINE
NTSTATUS AddHiddenFile(PUNICODE_STRING FilePath, PULONGLONG ObjId)
{
--- --- --- ---
--- --- --- ---
--- --- --- ---
--- --- --- ---
//將要隱藏的檔案資訊放進 g_excludeFileContext
status = AddExcludeListFile(g_excludeFileContext, &normalized, ObjId, 0);
if (NT_SUCCESS(status))
LogTrace("Added hidden file:%wZ", &normalized);
else
LogTrace("Adding hidden file failed with code:%08x, path:%wZ", status, &normalized);
--- --- --- ---
--- --- --- ---
}
NTSTATUS AddHiddenDir(PUNICODE_STRING DirPath, PULONGLONG ObjId)
{
--- --- --- ---
--- --- --- ---
--- --- --- ---
--- --- --- ---
//將要隱藏的目錄資訊放進 g_excludeDirectoryContext
status = AddExcludeListDirectory(g_excludeDirectoryContext, &normalized, ObjId, 0);
if (NT_SUCCESS(status))
LogTrace("Added hidden dir:%wZ", &normalized);
else
LogTrace("Adding hidden dir failed with code:%08x, path:%wZ", status, &normalized);
--- --- --- ---
--- --- --- ---
}
//每當有 IRP_MJ_DIRECTORY_CONTROL 訊號都走進這個 Func
//這個 Project 把事件寫在 PostOperation 中,PerOperation 沒寫。
FltDirCtrlPostOperation(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID CompletionContext, FLT_POST_OPERATION_FLAGS Flags)
{
PFLT_PARAMETERS params = &Data->Iopb->Parameters;
--- --- --- ---
--- --- --- ---
__try
{
status = STATUS_SUCCESS;
// _FILE_INFORMATION_CLASS
switch (params->DirectoryControl.QueryDirectory.FileInformationClass)
{
case FileBothDirectoryInformation:
//XP && XP 以下的系統走這裡。
status = CleanFileBothDirectoryInformation(xxx);
break;
--- --- --- ---
--- --- --- ---
case FileIdBothDirectoryInformation:
//Vista && Vista 以上的系統走這裡。
status = CleanFileIdBothDirectoryInformation((PFILE_ID_BOTH_DIR_INFORMATION)params->DirectoryControl.QueryDirectory.DirectoryBuffer, fltName);
break;
}
Data->IoStatus.Status = status;
}
--- --- --- ---
--- --- --- ---
}
CleanFileIdBothDirectoryInformation(PFILE_ID_BOTH_DIR_INFORMATION info, PFLT_FILE_NAME_INFORMATION fltName)
{
//這個FUNC傳進來的第一個參數 info 是一個緩衝區
//這個緩衝區裡保存著 User 嘗試存取的目錄的各種資訊
//要做的事情很簡單:
//1.列舉這個緩衝區
//2.過濾掉要隱藏的目錄或文件就能達到隱藏的效果
//以下 code 很難懂,請在頭腦清晰時在閱讀
PFILE_ID_BOTH_DIR_INFORMATION nextInfo, prevInfo = NULL;
UNICODE_STRING fileName;
UINT32 offset, moveLength;
BOOLEAN matched, search;
NTSTATUS status = STATUS_SUCCESS;
offset = 0;
search = TRUE;
do
{
fileName.Buffer = info->FileName;
fileName.Length = (USHORT)info->FileNameLength;
fileName.MaximumLength = (USHORT)info->FileNameLength;
//檢查當前請求的目錄或檔案是否存在於要隱藏的列表中。
//因為要隱藏的目錄或檔案分別放在不同的表
//所以這邊寫了 if else
if (info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
matched = CheckExcludeListDirFile(xxx);
else
matched = CheckExcludeListDirFile(xxxxxxx);
//發現了當前請求的目錄或檔案是要被隱藏的。
if (matched)
{
BOOLEAN retn = FALSE;
//如果在之前的 do 循環中沒發現要隱藏的目錄或檔案才會走這裡。
if (prevInfo != NULL)
{
//如果不是最後一個位置。
if (info->NextEntryOffset != 0)
{
//紀錄目前位置,並計算下一個位置的 offset。
//這裡可以直接看做是往前了一個位置(略過了目前這個位置)。
prevInfo->NextEntryOffset += info->NextEntryOffset;
offset = info->NextEntryOffset;
}
else
{
//已經走到最後沒東西了。
prevInfo->NextEntryOffset = 0;
status = STATUS_SUCCESS;
retn = TRUE;
}
//不管現在 info 是什麼,通通清空,
//因為會走到這有兩個原因:
//1.已經走到最後沒東西了,清空不影響,稍後要 return 了。
//2.目前這個位置是要略過的,清空不影響(直接略過了目前位置,前往下一個位置了)。
RtlFillMemory(info, sizeof(FILE_ID_BOTH_DIR_INFORMATION), 0);
}
else //第一次發現要隱藏檔案或目錄時走這個else。
{
//判斷是不是最後一個位置。
if (info->NextEntryOffset != 0)
{
//略過現在這個位置(當前的位置就是要被隱藏的),所以往前移動一個。
nextInfo = (PFILE_ID_BOTH_DIR_INFORMATION)((PUCHAR)info + info->NextEntryOffset);
moveLength = 0;
//把這之後的所有位置記錄起來。
while (nextInfo->NextEntryOffset != 0)
{
moveLength += nextInfo->NextEntryOffset;
nextInfo = (PFILE_ID_BOTH_DIR_INFORMATION)((PUCHAR)nextInfo + nextInfo->NextEntryOffset);
}
moveLength += FIELD_OFFSET(FILE_ID_BOTH_DIR_INFORMATION, FileName) + nextInfo->FileNameLength;
//覆蓋原本 info,這樣就略過了要隱藏的檔案或目錄。
RtlMoveMemory(info, (PUCHAR)info + info->NextEntryOffset, moveLength);//continue
//這裡不確定後面是否還有要被隱藏的目錄或檔案
//所以讓它繼續往下走(continue)。
}
else
{
//已經走到最後沒東西了。
status = STATUS_NO_MORE_ENTRIES;
retn = TRUE;
}
}
LogTrace("Removed from query: %wZ\\%wZ", &fltName->Name, &fileName);
if (retn)
return status;
info = (PFILE_ID_BOTH_DIR_INFORMATION)((PCHAR)info + offset);
continue;
}
//往下一個位置移動
offset = info->NextEntryOffset;
prevInfo = info;
info = (PFILE_ID_BOTH_DIR_INFORMATION)((PCHAR)info + offset);
if (offset == 0)
search = FALSE;
} while (search);
return status;
}
FLT_PREOP_CALLBACK_STATUS FltCreatePreOperation(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_ PVOID *CompletionContext)
{
--- --- --- ---
--- --- --- ---
--- --- --- ---
--- --- --- ---
--- --- --- ---
--- --- --- ---
if (!(options & FILE_DIRECTORY_FILE))
{
// If it is create file event
if (CheckExcludeListDirectory(g_excludeFileContext, &fltName->Name))
neededPrevent = TRUE;
}
// If it is create directory/file event
if (!neededPrevent && CheckExcludeListDirectory(g_excludeDirectoryContext, &fltName->Name))
neededPrevent = TRUE;
FltReleaseFileNameInformation(fltName);
if (neededPrevent)
{
//如果有 create directory/file event
//而且操作對象在隱藏的列表中
//就回送STATUS_NO_SUCH_FILE
//(底下有放效果圖)
LogTrace("Operation has been cancelled for: %wZ", &Data->Iopb->TargetFileObject->FileName);
Data->IoStatus.Status = STATUS_NO_SUCH_FILE;
return FLT_PREOP_COMPLETE;
}
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
STATUS_NO_SUCH_FILE 對照圖
不知道那個 Project 什麼時候會不見?放張圖片在這好了。(20210915)
Data->IoStatus.Status = STATUS_NO_SUCH_FILE;
大家看到這邊有沒有想到什麼問題?
如果沒有我來提幾個SB問題 XD
xxx.exe /hide dir C:\
xxx.exe /hide dir D:\
大家可以想一想這些問題和發生的原因,都留個言討論一下吧 XD
有空再來給大家回復、解答囉~~~
我們下期見 o( ̄▽ ̄)ブ