首页
社区
课程
招聘
[旧帖] [求助]Hook SSDT ZwCreateFile 后, 偶现蓝屏, 请高人分析下原因! 0.00雪花
发表于: 2013-12-24 20:46 3261

[旧帖] [求助]Hook SSDT ZwCreateFile 后, 偶现蓝屏, 请高人分析下原因! 0.00雪花

2013-12-24 20:46
3261
源码如下:
NTSTATUS SfZwCreateFile(
        OUT PHANDLE                FileHandle,
        IN  ACCESS_MASK            DesiredAccess,
        IN POBJECT_ATTRIBUTES      ObjectAttributes,
        OUT PIO_STATUS_BLOCK       IoStatusBlock,
        IN OPTIONAL PLARGE_INTEGER AllocationSize,
        IN ULONG                   FileAttributes,
        IN ULONG                   ShareAccess,
        IN ULONG                   CreateDisposition,
        IN ULONG                   CreateOptions,
        IN OPTIONAL PVOID          EaBuffer,
        IN ULONG                   Ealength)
{
        NTSTATUS Status = 0;
        ULONG i         = 0;
        ULONG j         = 0;
        ULONG Size      = 0;
        DWORD ProcessId = (DWORD)PsGetCurrentProcessId();
        DWORD ThreadId  = (DWORD)PsGetCurrentThreadId();
       
        BOOL AnsiInit   = FALSE;  // 是否已转化成了"ANSI"格式, 如果已转化, 那么"ANSI"字串需要释放
        BOOL ProcPath   = FALSE;  // 是否需要处理获取到的路径(路径为"\??\C:\XXX\XXX.XXX"的时候, 需要去掉前面四个字符)

        WCHAR wc_process_name[MAX_FILE_PATH] = {0};
        WCHAR wc_spc         [MAX_PROCESS  ] = {0};
        WCHAR *p_wc_ext                      = NULL;

        UNICODE_STRING u_proc = {0};
        ANSI_STRING    a_proc = {0};

        InterlockedIncrement(&g_createfile_lock);

        // 取进程名
        if (!SfGetProcessName(wc_process_name))
        {
                Status = g_old_zw_create_file(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, AllocationSize, FileAttributes, ShareAccess, CreateDisposition,

CreateOptions, EaBuffer, Ealength);

                InterlockedDecrement(&g_createfile_lock);

                return Status;
        }

        // 如果是"360"发来的请求, 直接略过
        if (wcsstr(wc_process_name, L"360") != NULL)
        {
                //DbgPrint(("YUBAN.FILEWATCH.DRIVER <<<<<< !SfNtCreateSection ------ NOTE: Is 360, Pass. ------ >>>>>>"));

                Status = g_old_zw_create_file(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, AllocationSize, FileAttributes, ShareAccess, CreateDisposition,

CreateOptions, EaBuffer, Ealength);

                InterlockedDecrement(&g_createfile_lock);

                return Status;
        }
        /*
       
        if (wcsncmp(wc_process_name, L"watchprocess.exe",  wcslen(L"watchprocess.exe")) == 0)
        {
                DbgPrint(("YUBAN.FILEWATCH.DRIVER <<<<<< !SfNtCreateSection ------ NOTE: Is My Driver ------ >>>>>>"));

                Status = g_old_zw_create_file(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, AllocationSize, FileAttributes, ShareAccess, CreateDisposition,

CreateOptions, EaBuffer, Ealength);

                InterlockedDecrement(&g_createfile_lock);

                return Status;
        }
        */

        // 缓冲区不为空才处理
        if (ObjectAttributes != NULL && (ObjectAttributes->ObjectName != NULL) && (ObjectAttributes->ObjectName->Buffer != NULL))
        {
                // 输出调试信息时间对齐用到
                /*
                for (i = wcslen(ObjectAttributes->ObjectName->Buffer), j = 0; i < MAX_PROCESS; i++, j++)
                {
                        wc_spc[j] = L' ';
                }

                DbgPrint(("YUBAN.FILEWATCH.DRIVER <<<<<< !SfZwCreateFile ------ File: %ws%ws, Current Process Id : %04d, Current Thread Id : %04d, DesiredAccess : 0x%08d,

CreateOptions : 0x%08d ------ >>>>>>"), ObjectAttributes->ObjectName->Buffer, wc_spc, ProcessId, ThreadId, DesiredAccess, CreateOptions);
                */

                if (wcslen(ObjectAttributes->ObjectName->Buffer) > 0)
                {
                        // 标记已转化
                        AnsiInit = TRUE;
                        // 初始化"UNICODE"字串
                        RtlInitUnicodeString(&u_proc, ObjectAttributes->ObjectName->Buffer);
                        // 转化"UNICODE"字串
                        RtlUnicodeStringToAnsiString(&a_proc, &u_proc, TRUE);
                       
                       
                        if (a_proc.Length > 4 )
                        {
                                if (a_proc.Buffer[0] == '\\' && a_proc.Buffer[1] == '?' && a_proc.Buffer[2] == '?' && a_proc.Buffer[3] == '\\')
                                {
                                        ProcPath = TRUE;
                                }
                        }
                }
               
                // 计算后缀名白名单个数
                Size = sizeof(g_WhiteExt) / (sizeof(WCHAR) * 32);
       
                // 循环过滤掉白名单中的后缀名
                for (i = 0; i < Size; i++)
                {
                        // 取后缀名(取出后是这种格式".TXT")
                        p_wc_ext = wcsrchr(ObjectAttributes->ObjectName->Buffer, L'.');

                        // 判空
                        if (p_wc_ext != NULL && (p_wc_ext + 1) != NULL)
                        {
                                // 比较后缀名和是否为一个有效的路径
                                if (ProcPath && wcsncmp(g_WhiteExt[i], p_wc_ext + 1, MAX_FILE_EXT) == 0 && *(ObjectAttributes->ObjectName->Buffer + 5) == L':')
                                {
                                        // 不存在同一进程标识就新插入
                                        if (!LsIsExist(ProcessId, COMPARE_TYPE_PROCESS_ID, NULL, NULL))
                                        {
                                                DbgPrint(("YUBAN.FILEWATCH.DRIVER <<<<<< !SfZwCreateFile ------ LsInsert ProcessId = %d, Open file = %ws ------ >>>>>>"),

ProcessId, ObjectAttributes->ObjectName->Buffer + 4);

                                                LsInsert(ProcessId, NULL, a_proc.Buffer + 4);

                                                //LsDebugOutFile();
                                        }
                                        // 存在同一进程标识就修改
                                        else
                                        {
                                                // 进一步查询是否存在同一文件全路径, 存在就不修改, 不存在就修改
                                                if (!LsIsExist(ProcessId, COMPARE_TYPE_FILE_PATH, NULL, a_proc.Buffer + 4))
                                                {
                                                        DbgPrint(("YUBAN.FILEWATCH.DRIVER <<<<<< !SfZwCreateFile ------ LsModify ProcessId = %d, Open file = %ws ------ >>>>>>"),

ProcessId, ObjectAttributes->ObjectName->Buffer + 4);

                                                        LsModify(ProcessId, PROCESS_OPEN_STATE, NULL, a_proc.Buffer + 4);

                                                        //LsDebugOutFile();
                                                }
                                        }

                                        break;
                                }
                        }
                }
        }
       
        if (AnsiInit)
        {
                RtlFreeAnsiString(&a_proc);
        }

        Status = g_old_zw_create_file(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, AllocationSize, FileAttributes, ShareAccess, CreateDisposition, CreateOptions,

EaBuffer, Ealength);

        InterlockedDecrement(&g_createfile_lock);
       
        return Status;
}

Windbg dump Info:
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

PAGE_FAULT_IN_NONPAGED_AREA (50)
Invalid system memory was referenced.  This cannot be protected by try-except,
it must be protected by a Probe.  Typically the address is just plain bad or it
is pointing at freed memory.
Arguments:
Arg1: c92d8000, memory referenced.
Arg2: 00000000, value 0 = read operation, 1 = write operation.
Arg3: 8443f310, If non-zero, the instruction address which referenced the bad memory
        address.
Arg4: 00000000, (reserved)

Debugging Details:
------------------

Unable to load image \SystemRoot\System32\Drivers\Hookport.sys, Win32 error 0n2
*** WARNING: Unable to verify timestamp for Hookport.sys
*** ERROR: Module load completed but symbols could not be loaded for Hookport.sys
*** WARNING: Unable to verify timestamp for qutmdrv.sys
*** ERROR: Module load completed but symbols could not be loaded for qutmdrv.sys

READ_ADDRESS: GetPointerFromAddress: unable to read from 845a084c
Unable to read MiSystemVaType memory at 8457fe20
c92d8000

FAULTING_IP:
nt!wcslen+8
8443f310 668b08          mov     cx,word ptr [eax]

MM_INTERNAL_CODE:  0

CUSTOMER_CRASH_COUNT:  1

DEFAULT_BUCKET_ID:  VISTA_DRIVER_FAULT

BUGCHECK_STR:  0x50

PROCESS_NAME:  System

CURRENT_IRQL:  0

TRAP_FRAME:  807b86a4 -- (.trap 0xffffffff807b86a4)
ErrCode = 00000000
eax=c92d8000 ebx=8979b866 ecx=c92d0059 edx=807b8c34 esi=807b8c28 edi=c0000503
eip=8443f310 esp=807b8718 ebp=807b8718 iopl=0         nv up ei pl nz na pe nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010206
nt!wcslen+0x8:
8443f310 668b08          mov     cx,word ptr [eax]        ds:0023:c92d8000=????
Resetting default scope

LAST_CONTROL_TRANSFER:  from 84477aa8 to 844c4879

STACK_TEXT:  
807b868c 84477aa8 00000000 c92d8000 00000000 nt!MmAccessFault+0x104
807b868c 8443f310 00000000 c92d8000 00000000 nt!KiTrap0E+0xdc
807b8718 9c19f471 c92d7fb0 00000000 00000000 nt!wcslen+0x8
807b8a58 8979b934 807b8c60 00000000 807b8c34 Yb_Process!SfZwCreateFile+0x1e1 [e:\ybworkspace\example\watchprocess\driverprocess\driverprocess.c @ 612]
WARNING: Stack unwind information not available. Following frames may be wrong.
807b8b50 844748c6 807b8c60 00000000 807b8c34 Hookport+0x1934
807b8b50 84472339 807b8c60 00000000 807b8c34 nt!KiSystemServicePostCall
807b8bf4 9158a3f2 807b8c60 00000000 807b8c34 nt!ZwCreateFile+0x11
807b8c64 9158c535 915b0d68 807b8ca0 00000000 qutmdrv+0x73f2
807b8ca8 9158d374 00000000 915b1f40 00000000 qutmdrv+0x9535
807b8d34 9158d64c 915b1f60 874c86a8 00000000 qutmdrv+0xa374
807b8d50 8464013d 00000000 9f30c3c0 00000000 qutmdrv+0xa64c
807b8d90 844e7559 9158d5da 00000000 00000000 nt!PspSystemThreadStartup+0x9e
00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x19

STACK_COMMAND:  kb

FOLLOWUP_IP:
Yb_Process!SfZwCreateFile+1e1 [e:\ybworkspace\example\watchprocess\driverprocess\driverprocess.c @ 612]
9c19f471 83c404          add     esp,4

SYMBOL_STACK_INDEX:  3

SYMBOL_NAME:  Yb_Process!SfZwCreateFile+1e1

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: Yb_Process

IMAGE_NAME:  Yb_Process.sys

DEBUG_FLR_IMAGE_TIMESTAMP:  52b937a1

FAILURE_BUCKET_ID:  0x50_Yb_Process!SfZwCreateFile+1e1

BUCKET_ID:  0x50_Yb_Process!SfZwCreateFile+1e1

Followup: MachineOwner
---------

修修改改了好些天了.. 还是偶现, 一天有个一两次蓝屏. 哎...

另外还有个问题想问下:

假设SSDT中系统的"ZwCreateFile"地址为"0xF0000001", 此时驱动'A' Hook 了, SSDT中"ZwCreateFile"地址变为"0xE0000001", 之后我又 Hook 了, SSDT中"ZwCreateFile"地址变为"0xD0000001", 那么程序调用顺序就变成了 "0xD0000001"->"0xE0000001"->"0xF0000001", 此时如果驱动'A'卸载了并且恢复了SSDT, 那么之前我写入的"0xD0000001"就被覆盖了, 就不会调到我的"ZwCreateFile"里面来了吗???

这里是我的dump文件:

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

上传的附件:
收藏
免费 0
支持
分享
最新回复 (11)
雪    币: 40
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
没人吗, 自己顶一下.
2013-12-25 08:53
0
雪    币: 40
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
看的人多.. 没一个帮忙的...
2013-12-25 18:27
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
帮你顶一下,我提的问题也没有解决方案
2013-12-25 18:31
0
雪    币: 40
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
谢谢帮忙, 貌似现在都潜水... 只见人影不见人...
2013-12-25 19:23
0
雪    币: 75
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
蓝屏应该要上传Dump,用WinDbg查看具体的原因就知道了
2013-12-25 20:04
0
雪    币: 40
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
终于有个活口了... dump文件才上传了... 我刚接触驱动不久, 还不会深入的去分析, 如果会也不会在这里求助人了... 我看windebug的信息只知道是在SfZwCreateFile处蓝的.. 其它的原因... 技术有限...
2013-12-25 21:01
0
雪    币: 75
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
你把Dump文件传上来,我帮你看看
就算我解决不了,这里高手那么多,你也可以请他们帮忙分析啊
2013-12-25 21:34
0
雪    币: 31
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
if (wcslen(ObjectAttributes->ObjectName->Buffer) > 0)
像这个不蓝才怪,谁告诉你Buffer一定以0结尾,判断长度用ObjectAttributes->ObjectName->Length/sizeof(WCHAR)。
看清楚UINICODE_STRING的定义就知道了,不保证以0结尾的。
2013-12-25 21:58
0
雪    币: 31
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
另外再说一句,读取ObjectAttributes这样的参数要区分是内核态调用还是用户态调用,用户态调用要用ProbeForRead,然后加上异常处理,否则总会有概率悲剧。
2013-12-25 22:13
0
雪    币: 40
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
谢谢回答, 不过判断改为 if (ObjectAttributes->ObjectName->Length > 0) { ... } 后还是蓝, 至于你刚提到的, 用户态和内核态, 我还真是不懂, 可否指点一下, 怎么去判断? 判断完后如何处理呢? 比方说如果是用户态, 我怎么处理? 内核态又怎么处理呢?谢谢了..
2013-12-26 10:17
0
雪    币: 31
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
改了之后蓝在哪里在对症下药,我也没仔细看你的代码。
判断用户态的话用
if(ExGetPreviousMode()==UserMode)
{
__try
{
ProbeForRead(...)
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
具体的看ProbeForRead的用法
2013-12-26 19:37
0
游客
登录 | 注册 方可回帖
返回
//