ZwReadFile失败,异常代码0xC0000005,求指点

哈尔滨-猫猫 2014-01-02 09:53:55
首先,我HOOK了SSDT的ZwReadFile函数,替换为我的_ZwReadFile,实现对系统所有进程读文件操作的过滤目的。当检测当前进程为w3wp.exe或者为ReadFileTest.exe(由于我获取进程名只获取到16个字节,所以少获取了一个'e',判断时,使用了ReadFileTest.ex)进程时,将判断这两个进程读的文件头10个字节,是否为我指定的内容,如果是,则执行相关解密操作。

其次,在进程进入我的_ZwReadFile时,是可以正常读取文件内容的,然后我想判断一下此次读的文件的头10个字节是否为我指定的内容,由于刚刚已经读到了文件结尾,下一次读时需要将文件位置设置为0,以便再次从文件头中读取文件头10个字节的内容。

于是,有如下代码:
bool IsEncrypt(HANDLE FileHandle)
{
IO_STATUS_BLOCK ioStatus;
ULONG dwReaded = 0;
FILE_POSITION_INFORMATION current_fpi;
FILE_POSITION_INFORMATION fpi;
NTSTATUS status;

InterlockedIncrement(&g_uCount);
//获取当前文件位置信息,以便读取文件头后,恢复当前文件指针位置
status = ZwQueryInformationFile(FileHandle, &ioStatus, ¤t_fpi, sizeof(FILE_POSITION_INFORMATION), FilePositionInformation);
DbgPrint("%ld", current_fpi.CurrentByteOffset);
if (NT_SUCCESS(status))
{
DbgPrint("ZwQueryInformationFile successful");
}
else
{
DbgPrint("ZwQueryInformationFile failed");
}

//移动文件指针位置到文件头部
fpi.CurrentByteOffset.QuadPart = 0i64;
DbgPrint("%ld", fpi.CurrentByteOffset);
//设置文件指针位置信息
status = ZwSetInformationFile(FileHandle, &ioStatus, &fpi, sizeof(FILE_POSITION_INFORMATION), FilePositionInformation);
if (NT_SUCCESS(status))
{
DbgPrint("ZwSetInformationFile successful");
}
else
{
DbgPrint("ZwSetInformationFile failed");
}

char *szFileHeader = (char*)ExAllocatePool(NonPagedPool, 10);
ULONG length = 10;

NTSTATUS status1 = g_pfnZwReadFile(
FileHandle,
NULL,
NULL,
NULL,
&ioStatus,
szFileHeader,
length,
NULL,
NULL);
if (NT_SUCCESS(status1))
{
DbgPrint("Read File Header successful");
}
else
{
//此处将会被执行,读取文件失败。。。
DbgPrint("Read File Header failed : %d, %d, %d", status1, ioStatus.Status, ioStatus.Information);
}

//恢复文件指针位置
ZwSetInformationFile(FileHandle, &ioStatus, ¤t_fpi, sizeof(FILE_POSITION_INFORMATION), FilePositionInformation);
InterlockedDecrement(&g_uCount);

DbgPrint("FileHeader : %s", szFileHeader);
if (!strcmp(szFileHeader, "QQ:7278449"))
{
return TRUE;
}
ExFreePool(szFileHeader);
return FALSE;
}



NTSTATUS NTAPI _ZwReadFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL,
IN PULONG Key OPTIONAL
)
{
NTSTATUS status;
char szProcessName[256] = {0};
GetProcessName((ULONG)PsGetCurrentProcessId(), szProcessName);

InterlockedIncrement(&g_uCount);
status = g_pfnZwReadFile(
FileHandle,
Event,
ApcRoutine,
ApcContext,
IoStatusBlock,
Buffer,
Length,
ByteOffset,
Key);
InterlockedDecrement(&g_uCount);

if (!strcmp(szProcessName, "w3wp.exe") || !strcmp(szProcessName, "ReadFileTest.ex"))
{
DbgPrint("Current Process Name : %s", szProcessName);
DbgPrint("%s", Buffer);
if (IsEncrypt(FileHandle))
{
DbgPrint("the file is encrypt!!!");
Decrypt((char*)Buffer, Length);
}
}

return status;
}

注:g_pfnZwReadFile为HOOK后,原ZwReadFile函数的指针。
经过一周时间windbg调试+DebugView,也没能找出读文件失败原因,还请大神指点,表示感谢!
可用分全部奉上....
...全文
615 17 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
liutingting2020 2014-07-18
  • 打赏
  • 举报
回复
可以给我发一个源码吗?就发上面那个QQ就好啦。谢谢哦。
liutingting2020 2014-07-18
  • 打赏
  • 举报
回复
亲,你是不是对文件进行防护啊。我现在也在做这方面。还想多和你交流。我的QQ:865213875
zgcbj 2014-01-08
  • 打赏
  • 举报
回复
楼主,该结帖啦
哈尔滨-猫猫 2014-01-03
  • 打赏
  • 举报
回复
1.如何判断用户的ReadFile是我想要过滤的文件? 2.如果用户层只调用了CreateFile 而之后没有进行读操作呢? 3.假如打开文件时,我判断文件是否是加密的,那我保存什么呢? 文件路径:我不是所有进程读这个文件,都要给解密 文件句柄:那如果上层应用读一个文件的时候,用了两次以上CreateFile呢? 还有很多未知问题,因为我的目的是过滤一下某些进程读文件操作,而去hook 离其较远的CreateFile,中间n多问题的。
哈尔滨-猫猫 2014-01-03
  • 打赏
  • 举报
回复
g_pfnZwReadFile是原ZwReadFile的函数指针 Hook ZwReadFile的时候,要保存原函数的入口地址啊,以便于驱动卸载时恢复ssdt~ 如果Hook CreateFile会有很多问题,如:
hahayezhe112 2014-01-03
  • 打赏
  • 举报
回复
g_pfnZwReadFile 里面是什么?文件指针吗,指向读函数? 你已经Hook了ZwReadFile,怎么去调用读函数呢? 我觉得你的思路是否可以改下,改成hook打开文件的函数,在打开文件之前根据路径打开一次,读取前10个字节去判断。
哈尔滨-猫猫 2014-01-02
  • 打赏
  • 举报
回复
LARGE_INTEGER li; li.QuadPart = 0i64; 然后把&li传进去 实现从头读文件 但是效果还是不行,读文件依然失败,同样的错误。 解释一下哈,用qq用习惯了,总是习惯用 ctrl+enter换行,,,蛋碎了,又不小心按错
哈尔滨-猫猫 2014-01-02
  • 打赏
  • 举报
回复
不读不行啊,我HOOK了ZwReadFile,我最起码应该保证上层所有读操作能正常进行下去,否则上层很容易蹦掉或者卡死的。 话说DDK帮助里 我也研究了一下这个ByteOffset,也尝试了,貌似给这个值NULL,使用的应该是当前文件指针位置,也就有了我保存当前位置,又恢复当前位置的操作。 另外,根据文档,也可以这里直接传递一个PLARGE_INTEGER 大整数指针过去,可以指定文件指针位置,类似如下代码:
zgcbj 2014-01-02
  • 打赏
  • 举报
回复
你这一句话两层楼,是为了顶帖子么?好少年啊。 不过,能不能判断 IN PLARGE_INTEGER ByteOffset OPTIONAL 倒数第二个参数,判断位置,如果位置是开头,就读,不是开头就不读。 如果你要求,别管多少次ReadFile,都要判断最开始几个字节,那估计就得像你这样做了。
哈尔滨-猫猫 2014-01-02
  • 打赏
  • 举报
回复
这样分多次读取一个文件的情况,从第二次ReadFile开始 缓冲区里就不会包含有该文件的头信息了 所以我在IsEncrypt里 特意去读的文件头
哈尔滨-猫猫 2014-01-02
  • 打赏
  • 举报
回复
但,如果上层应用,读一个文件是调用两次以上ReadFile呢?
哈尔滨-猫猫 2014-01-02
  • 打赏
  • 举报
回复
嗯,一开始我也是像你这么想。但是有一种情况,这样不行。 比如上层应用读一个文件,只调用了一次ReadFile就把整个文件读取了,你说的方法,没有问题。
zgcbj 2014-01-02
  • 打赏
  • 举报
回复
你在 _ZwReadFile的开头是不是已经读到了,为什么又去 IsEncrypt(FileHandle)这里面再读一遍?直接拿buff里面的比不行吗?我不懂了。
哈尔滨-猫猫 2014-01-02
  • 打赏
  • 举报
回复
其他人说内核少用栈空间,于是才改的。但问题依旧,应该不是这里的问题(已调试验证过)
哈尔滨-猫猫 2014-01-02
  • 打赏
  • 举报
回复
char buffer[11] = {0};
哈尔滨-猫猫 2014-01-02
  • 打赏
  • 举报
回复
这里调试了,成功。本来没用堆内存,用的栈上的缓冲区,如下
zgcbj 2014-01-02
  • 打赏
  • 举报
回复
char *szFileHeader = (char*)ExAllocatePool(NonPagedPool, 10); 这个怎么没看到检查成功失败呢?
notepad--v3.4 windows Notepad--v3.4.0-plugin-Installer.exe 是win10下面的插件版安装包,会关联右键菜单等。 Notepad--v3.4.0-win10-portable.zip 是绿色免安装版本,解压即用,不会关联右键菜单注册表。 Ndd-quick-v3.3.0-win10-single-portable.zip 是单文件绿色免安装版,只包含皮肤和vc依赖库,不含插件、不含文件对比,主推轻量级、快速反应。适合只需要纯粹、轻快级,文本编辑器的用户。不定期发布。 MacOS 版本 Notepad--v3.4.0-mac_x64_12.3.dmg 是macos 12.x 及以后的版本。 Notepad--v3.4.0-mac_arm64_12.3.dmg 是macos 12.x 及以后 arm64 m1/m2芯片 的版本。第一次安装时,需要在设置偏好里面,放开苹果的安装限制,才能正常识别,请自行放开设置一下。 如果还是有问题,参考帖子:#I8JTJN:macOS Sonoma 14.1.1安装提示已损坏:macOS Sonoma 14.1.1安装提示已损坏 uos com.hmja.notepad_3.4.0.0_amd64.deb 是x64 cpu架构的uos系统对应的ndd版本。 其余系统版本后续会发布。 3.4 修改如下: 1 支持文件标签拖入拖出到新窗口的效果。 2 windows下修改快捷键放开。 3 按行号切分大文件。 4 大文件打开时,在文件夹查找所在目录,macos下可能会崩溃问题。 5 目录右键增加删除文件、文件夹功能。 6 补充深色主题下rust语法高亮; lisp 语法失效问题。 7 linux下信号打开文件,不拿锁,打开文件在消息队列中去做。

21,615

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
  • 驱动开发/核心开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧