撰写本系列文章目的在於提升资讯安全之实务能力,
并透过实作体悟到资讯安全领域的重要性,
本系列所有文章之内容皆有一定技术水平,
不得从事非法行为、恶意攻击等非法活动,
「一切不合法规之行为皆受法律所约束」,
为了避免造成公司、厂商或玩家之间困扰,
所有实作不会拿已上市产品、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( ̄▽ ̄)ブ
惯例先上成果图XD https://asciinema.org/a/439607 终於开机开到she...
距离完赛已经过了一阵子,前天想自己刻刻看计算机,拆解任务、实际执行後才发现知识量不足,导致无法顺利完...
摘要 Keras Application 预训练模型种类 模型选用考量 选用结果 内容 Keras ...
Q: 如何反驳「工程师离开电脑之後就是个废物」的这个说法? A: 不不不,很多工程师在电脑前面也是...
前情提要 郑列展现了自己的工具力(快速找杂物),但似乎还有别的? 郑列:我看你是完全不懂啊,我还有别...