騰訊管家攻防驅(qū)動(dòng)分析-TsFltMgr


layout: wiki
title: 騰訊管家攻防驅(qū)動(dòng)分析-TsFltMgr
categories: WindowsDriver
description: 騰訊管家攻防驅(qū)動(dòng)分析-TsFltMgr
keywords:
url: https://lichao890427.github.io/ https://github.com/lichao890427/


TsFltMgr.sys分析

??該驅(qū)動(dòng)為qq管家函數(shù)過(guò)濾驅(qū)動(dòng)呈昔,提供SSDT达椰、SSSDT、進(jìn)程和線程回調(diào)等過(guò)濾操作跛溉,導(dǎo)出接口給TsKsp.sys使用焊切,2者共同做函數(shù)過(guò)濾操作,TsFltMgr提供設(shè)置函數(shù)過(guò)濾的框架芳室,而實(shí)際攔截過(guò)程在TsKsp中专肪。設(shè)備名\Device\TsFltMgr ,符號(hào)名\DosDevices\TsFltMgr 。加密手段:Rabbit算法、MD5算法切威。通過(guò)InlineHook KifastCallEntry實(shí)現(xiàn)掛鉤砚殿。

一芽死、驅(qū)動(dòng)入口DriverEntry

  • 創(chuàng)建\Device\TSSysKit設(shè)備和\DosDevices\TSSysKit符號(hào)鏈接
  • 設(shè)置DeviceExtension為通信接口(Interface函數(shù)指針)
  • 分別注冊(cè)IRP_MJ_CREATE乏梁、IRP_MJ_CLOSE、IRP_MJ_DEVICE_CONTROL关贵、IRP_MJ_SHUTDOWN(關(guān)機(jī)回調(diào))派遣例程為遇骑,CreateCloseDispatch、DeviceIoControlDispatch揖曾、ShutdownDispatch
  • 注冊(cè)”Boot驅(qū)動(dòng)加載結(jié)束”回調(diào)DriverReinitializationRoutine
  • 為注冊(cè)表日志記錄分配資源RegLogSpace
  • 檢查當(dāng)前系統(tǒng)是否為注冊(cè)表version鍵指定的系統(tǒng)落萎,如果在列表中則在掛鉤KiFastCallEntry時(shí)需要做額外工作
  • 設(shè)置注冊(cè)表鍵IsBsod為1,用于檢測(cè)該驅(qū)動(dòng)是否引起藍(lán)屏(正常關(guān)機(jī)置0)
  • 獲取系統(tǒng)BuildNumber
  • 分配和設(shè)置”內(nèi)核Api代理”結(jié)構(gòu)
  • 掛鉤KiFastCallEntry
  • 掛鉤重要回調(diào)
  • 啟動(dòng)注冊(cè)表日志記錄
  • 掛鉤KeUserModeCallback
  • 記錄當(dāng)前配置

1.1 過(guò)濾模型

[圖片上傳失敗...(image-a25680-1516663378349)]

  • Ntdll.NtCreateFile通過(guò)Sysenter調(diào)用進(jìn)入nt.KiFastCallEntry
  • 在nt.KiFastCallEntry 執(zhí)行call ebx(原始為nt.NtCreateFile)前跳到TsFltMgr. InlineKiFastCallEntry
  • 執(zhí)行進(jìn)入TsFltMgr.HookFilter炭剪,在這里通過(guò)ServiceMapTable表映射到對(duì)應(yīng)Dproxy元素练链,將Dproxy->ProxyNtCreateFile設(shè)置到ebx,將其設(shè)置為ebx
  • Nt.KiFastCallEntry執(zhí)行call ebx奴拦,進(jìn)入ProxyNtCreateFile
  • 構(gòu)造FilterPacket結(jié)構(gòu)(用于承載參數(shù)媒鼓、原始api和PostFilterFunc執(zhí)行的所有過(guò)濾函數(shù)都用到),依次執(zhí)行Dproxy->PrevFilterSlot的16個(gè)過(guò)濾函數(shù)(PrevFilter是Tsksp事先設(shè)置好的)
  • 依次執(zhí)行單個(gè)Tsksp.PrevFilter错妖,進(jìn)行真正的過(guò)濾或?qū)acket. PostFilterSlot進(jìn)行設(shè)置
  • 返回TsFltMgr.ProxyNtCreateFile绿鸣,執(zhí)行nt.NtCreateFile
  • 執(zhí)行packet. PostFilterSlot的16個(gè)過(guò)濾函數(shù)(Tsksp)
  • 返回nt.KiFastCallEntry

1.2 檢查當(dāng)前系統(tǒng)是否為默認(rèn)掛鉤系統(tǒng)

BOOLEAN IsUnSupportedSystem()
{
/*注:\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\TSKS  version
    存放沒(méi)有預(yù)存 函數(shù)調(diào)用號(hào)ServiceIndex 的系統(tǒng)版本列表 格式:
BuildNumber1;BuildNumber2;...
    對(duì)于這些版本在進(jìn)行SSDT Hook時(shí),會(huì)臨時(shí)取得服務(wù)號(hào)
*/
    NTSTATUS status;
    ULONG BuildNumber = 0,MajorVersion,MinorVersion;
    const int BufSize = 1024;
    ULONG Size,Type;
    WCHAR BuildNumberStr[10] = {0};
    BOOLEAN Match = FALSE;
    UNICODE_STRING UBuildNumber;
    WCHAR* Buffer = (WCHAR*)ExAllocatePool(NonPagedPool,BufSize);
    status = GetRegDataWithSizeAndType(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\TSKSP",L"version",
        Buffer,BufSize,&Size,&Type);
    if(NT_SUCCESS(status) && Type == REG_SZ && Size)
    {
        Buffer[510] = 0;
        RtlInitUnicodeString(&UBuildNumber,BuildNumberStr);
        PsGetVersion(&MajorVersion,&MinorVersion,&BuildNumber,NULL);
        RtlIntegerToUnicodeString(BuildNumber,10,&UBuildNumber);
        if(wcsstr((wchar_t*)Buffer,UBuildNumber.Buffer))
            Match = TRUE;
    }
    ExFreePool(Buffer);
    return Match;
}

1.3 打開(kāi)TsFltMgr日志記錄

??在無(wú)保護(hù)情況下為\REGISTRY\MACHINE\SYSTEM\CurrentControlSet\Services\TsFltMgr添加TsDbgLog鍵站玄,內(nèi)容設(shè)置為目標(biāo)文件路徑(例如??\C:\TsDbgLog.txt)枚驻,如果不存在會(huì)自動(dòng)創(chuàng)建文件濒旦,重啟生效株旷。內(nèi)容示例:

[0x00000000] 2015.09.27 20:05:24.109    TS TsFltMgr DbgHelper
[0x00000001] 2015.09.27 20:06:13.750    [Sysnap DbgLog] Block--> TableIndex 0, Process spoolsv.exe[1800] 
[0x00000002] 2015.09.27 20:10:35.156    [Sysnap DbgLog] Block--> TableIndex 4, Process regedit.exe[2296] 
[0x00000003] 2015.09.27 20:13:46.500    [Sysnap DbgLog] Block--> TableIndex 4, Process regedit.exe[2296]
  • DriverReinitializationRoutine中做初始化,此時(shí)最后一個(gè)boot驅(qū)動(dòng)初始化完畢
  • 在執(zhí)行KiFastCallEntry hook時(shí)再次嘗試啟動(dòng)打印日志線程
  • ExecPrevSlotFunc中尔邓,如果存在過(guò)濾函數(shù)進(jìn)行了放行和攔截晾剖,都會(huì)打印日志

1.4 控制信息

  • 禁止hook
    ??\REGISTRY\MACHINE\SYSTEM\CurrentControlSet\Services\TsFltMgr dws=1
    ??\REGISTRY\MACHINE\SYSTEM\CurrentControlSet\services\QQSysMon\DWS dws!=0

  • 強(qiáng)制SSDT hook
    ??\REGISTRY\MACHINE\SYSTEM\CurrentControlSet\Services\TsFltMgr thm=1

  • 關(guān)機(jī)回調(diào)
    ??設(shè)置\REGISTRY\MACHINE\SYSTEM\CurrentControlSet\Services\TsFltMgr IsBsod=0,以便下次啟動(dòng)檢測(cè)是否TsFltMgr引起藍(lán)屏

1.5 全局表

BuildNumber:
Win2000
    2195    1
WinXp
    2600    2
WinServer2003
    3790    3
WinVista
    6000    4
    6001    5
    6002    6
Win7
    7600    7
    7601    8
Win8
    8102    9
    8250    10
    8400    11
    8432    12
    8441    12
    8520    13
Win8.1
    9200    14
    9600    15
Win10
    9841    16
    9860    17
    9926    18
    10041   19
    10049   20
未知  0

enum
{
    WIN2000=1,
    WINXP,
    WINXPSP3,
    WINVISTA,
    WINVISTASP1,
    WINVISTASP2,
    WIN7,
    WIN7SP1,
    WIN8_8102,
    WIN8_8250,
    WIN8_8400,
    WIN8_8432,
    WIN8_8441=WIN8_8432,
    WIN8_8520,
    WIN81_9200,
    WIN81_9600,
    WIN10_9841,
    WIN10_9860,
    WIN10_9926,
    WIN10_10041,
    WIN10_10049,
    BUILDMAX,
};
enum
{
    SSDT=0,
    SSSDT=1,
    END=2,
    CALLBACK=3,
};

#define APINUMBER 105

struct SProxy
{
    ULONG ServiceTableType;//0:SSDT 1:Shadow SSDT 2:結(jié)束符
    PWCHAR ApiName;//函數(shù)名
    ULONG  ProxyFunc;//代理函數(shù)地址
    ULONG ServiceIndex[BUILDMAX];
    ULONG IndexInTable;//在全局表中的索引
};

struct DProxy
{
    ULONG ServiceTableType;//0:SSDT 1:Shadow SSDT 2:結(jié)束符 3:回調(diào)函數(shù)
    ULONG ServiceIndex;//服務(wù)號(hào)
    PWCHAR ApiName;//函數(shù)名
    ULONG TableIndex;//自定義序號(hào)
    BOOLEAN IsInitialized;
    ULONG PrevFilterRefCount;//引用計(jì)數(shù)
    ULONG PostFilterRefCount;//引用計(jì)數(shù)
    ULONG OriginFuncAddr;//原始函數(shù)地址
    ULONG ProxyFuncAddr;//代理函數(shù)地址
    PVOID Log;//用于記錄日志
    KEVENT Lock;
    BOOLEAN DisablePrevFilter;//關(guān)閉Filter
    ULONG UsedSlotCount;// 當(dāng)前使用的Slot個(gè)數(shù)
    FILTER_SLOT PrevFilterSlot[16];//過(guò)濾函數(shù)結(jié)構(gòu)
};

struct FILTER_SLOT
{
    ULONG Tag;
    ULONG CallCount;
    ULONG DeleteCount;
    KTIMER Timer;
    ULONG Filter;
};

struct FilterPacket
{
    ULONG CurrentSlot;//當(dāng)前Filter序號(hào)
    ULONG ParamNumber;//參數(shù)個(gè)數(shù)
    ULONG Params[12];//參數(shù)
    ULONG TagSlot[16];//標(biāo)志過(guò)濾函數(shù)用梯嗽,也可用于傳遞修改參數(shù)
    NTSTATUS Status;//執(zhí)行結(jié)果
    ULONG OriginFuncAddr;//原始函數(shù)
    ULONG IndexInTable;//在DProxyTable中的索引
    ULONG Access;//訪問(wèn)權(quán)限
    ULONG PostFilterSlot[16];//過(guò)濾函數(shù)
    ULONG UsedSlotCount;//當(dāng)前使用的Slot個(gè)數(shù)
};

TsFltMgr有3張表與函數(shù)過(guò)濾相關(guān):
靜態(tài)Api代理表SProxy  SProxyTable[APINUMBER+1]        用于初始化后面2個(gè)表
動(dòng)態(tài)Api代理表DProxy* DProxyTable[APINUMBER+1]    用于Proxy*函數(shù)中進(jìn)行實(shí)際過(guò)濾操作   方便用SProxy指定的序號(hào)配置
DProxy* ServiceMapTable[2][1024]        用于InlineHook KiFastCallEntry改變ebx齿尽,映射ServiceIndex到Proxy*函數(shù)。函數(shù)前1024個(gè)用于存儲(chǔ)SSDT函數(shù)灯节,后1024用于存儲(chǔ)SSSDT函數(shù)

可以用簡(jiǎn)單的python命令自動(dòng)獲取到g_ProxyApiTable內(nèi)容
addr=0x25200
index=0
while index < 106:
if Dword(addr) == 0:
type="SSDT"
elif Dword(addr) == 1:
type="SSSDT"
else:
type="END"
ApiName=GetString(Dword(addr+4),-1,ASCSTR_UNICODE)
ProxyFunc="Proxy"+ApiName
print "{\n\t%s,L\"%s\",%s,\n\t{" %(type,ApiName,ProxyFunc)
print "\t\t%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d" %(Dword(addr+12),Dword(addr+16),Dword(addr+20),Dword(addr+24),Dword(addr+28),Dword(addr+32),Dword(addr+36),Dword(addr+40),Dword(addr+44),Dword(addr+48),Dword(addr+52),Dword(addr+56),Dword(addr+60),Dword(addr+64),Dword(addr+68),Dword(addr+72),Dword(addr+76),Dword(addr+80),Dword(addr+84),Dword(addr+88),Dword(addr+92))
print "\t},%d\n}," %(Dword(addr+96))
addr=addr+100
index=index+1

struct SProxy   SProxyTable[APINUMBER+1] = 
{
    {
        SSDT,L"ZwCreateKey",ProxyZwCreateKey,
        {
            1023,35,41,43,64,64,64,70,70,347,351,351,350,350,350,354,355,355,356,359,359
        },0
    },
    {
        SSDT,L"ZwTerminateProcess",ProxyZwTerminateProcess,
        {
            1023,224,257,266,338,334,334,370,370,35,35,35,35,35,35,35,36,36,36,36,36
        },1
    },
    {
        SSDT,L"ZwSetInformationFile",ProxyZwSetInformationFile,
        {
            1023,194,224,233,305,301,301,329,329,78,79,79,78,78,78,81,82,82,82,82,82
        },2
    },
    {
        SSDT,L"ZwWriteFile",ProxyZwWriteFile,
        {
            1023,237,274,284,359,355,355,396,396,4,5,5,5,5,5,6,7,7,7,7,7
        },3
    },
    {
        SSDT,L"ZwSetValueKey",ProxyZwSetValueKey,
        {
            1023,215,247,256,328,324,324,358,358,48,48,48,48,48,48,49,50,50,50,50,50
        },4
    },
    {
        SSDT,L"ZwWriteVirtualMemory",ProxyZwWriteVirtualMemory,
        {
            1023,240,277,287,362,358,358,399,399,1,2,2,2,2,2,3,4,4,4,4,4
        },5
    },
    {
        SSDT,L"ZwCreateFile",ProxyZwCreateFile,
        {
            1023,32,37,39,60,60,60,66,66,351,356,356,355,355,355,360,361,361,362,365,365
        },6
    },
    {
        SSDT,L"ZwOpenProcess",ProxyZwOpenProcess,
        {
            1023,106,122,128,194,194,194,190,190,220,222,222,221,221,221,224,225,225,226,227,227
        },7
    },
    {
        SSDT,L"ZwDeleteKey",ProxyZwDeleteKey,
        {
            1023,53,63,66,123,123,123,103,103,310,314,314,313,313,313,317,318,318,319,321,321
        },8
    },
    {
        SSDT,L"ZwDeleteValueKey",ProxyZwDeleteValueKey,
        {
            1023,55,65,68,126,126,126,106,106,307,311,311,310,310,310,314,315,315,316,318,318
        },9
    },
    {
        SSDT,L"ZwRequestWaitReplyPort",ProxyZwRequestWaitReplyPort,
        {
            1023,176,200,208,275,276,276,299,299,108,110,110,109,109,109,112,113,113,114,114,114
        },10
    },
    {
        SSDT,L"ZwQueryValueKey",ProxyZwQueryValueKey,
        {
            1023,155,177,185,252,252,252,266,266,143,145,145,144,144,144,147,148,148,149,149,149
        },11
    },
    {
        SSDT,L"ZwEnumerateValueKey",ProxyZwEnumerateValueKey,
        {
            1023,61,73,77,136,136,136,119,119,292,296,296,295,295,295,299,300,300,301,303,303
        },12
    },
    {
        SSDT,L"ZwCreateThread",ProxyZwCreateThread,
        {
            1023,46,53,55,78,78,78,87,87,330,334,334,333,333,333,337,338,338,339,342,342
        },13
    },
    {
        SSDT,L"ZwDuplicateObject",ProxyZwDuplicateObject,
        {
            1023,58,68,71,129,129,129,111,111,300,304,304,303,303,303,307,308,308,309,311,311
        },14
    },
    {
        SSDT,L"ZwLoadDriver",ProxyZwLoadDriver,
        {
            1023,85,97,101,165,165,165,155,155,255,257,257,256,256,256,259,260,260,261,263,263
        },15
    },
    {
        SSDT,L"ZwDeviceIoControlFile",ProxyZwDeviceIoControlFile,
        {
            1023,56,66,69,127,127,127,107,107,304,308,308,307,307,307,311,312,312,313,315,315
        },16
    },
    {
        SSDT,L"ZwAlpcSendWaitReceivePort",ProxyZwAlpcSendWaitReceivePort,
        {
            1023,1023,1023,1023,38,38,38,39,39,381,386,386,385,385,385,390,391,391,393,396,396
        },17
    },
    {
        SSDT,L"ZwSetSystemInformation",ProxyZwSetSystemInformation,
        {
            1023,208,240,249,321,317,317,350,350,56,56,56,56,56,56,57,58,58,58,58,58
        },18
    },
    {
        SSDT,L"ZwDeleteFile",ProxyZwDeleteFile,
        {
            1023,52,62,65,122,122,122,102,102,311,315,315,314,314,314,318,319,319,320,322,322
        },19
    },
    {
        SSDT,L"ZwOpenSection",ProxyZwOpenSection,
        {
            1023,108,125,131,197,197,197,194,194,216,218,218,217,217,217,220,221,221,222,222,222
        },20
    },
    {
        SSDT,L"ZwCreateSection",ProxyZwCreateSection,
        {
            1023,43,50,52,75,75,75,84,84,333,337,337,336,336,336,340,341,341,342,345,345
        },21
    },
    {
        SSDT,L"ZwSuspendThread",ProxyZwSuspendThread,
        {
            1023,221,254,263,335,331,331,367,367,38,38,38,38,38,38,38,39,39,39,39,39
        },22
    },
    {
        SSDT,L"ZwTerminateThread",ProxyZwTerminateThread,
        {
            1023,225,258,267,339,335,335,371,371,34,34,34,34,34,34,34,35,35,35,35,35
        },23
    },
    {
        SSDT,L"ZwSystemDebugControl",ProxyZwSystemDebugControl,
        {
            1023,222,255,264,336,332,332,368,368,37,37,37,37,37,37,37,38,38,38,38,38
        },24
    },
    {
        SSDT,L"ZwProtectVirtualMemory",ProxyZwProtectVirtualMemory,
        {
            1023,1023,137,143,210,210,210,215,215,194,196,196,195,195,195,198,199,199,200,200,200
        },38
    },
    {
        SSDT,L"ZwCreateSymbolicLinkObject",ProxyZwCreateSymbolicLinkObject,
        {
            1023,45,52,54,77,77,77,86,86,331,335,335,334,334,334,338,339,339,340,343,343
        },39
    },
    {
        SSDT,L"ZwSetContextThread",ProxyZwSetContextThread,
        {
            1023,1023,213,221,293,289,289,316,316,91,92,92,91,91,91,94,95,95,95,95,95
        },40
    },
    {
        SSDT,L"ZwRenameKey",ProxyZwRenameKey,
        {
            1023,1023,192,200,267,267,267,290,290,117,119,119,118,118,118,121,122,122,123,123,123
        },41
    },
    {
        SSDT,L"ZwOpenThread",ProxyZwOpenThread,
        {
            1023,111,128,134,201,201,201,198,198,214,214,214,213,213,213,216,217,217,218,218,218
        },42
    },
    {
        SSDT,L"ZwGetNextThread",ProxyZwGetNextThread,
        {
            1023,1023,1023,1023,372,368,368,140,140,271,271,271,270,270,270,273,274,274,275,277,277
        },43
    },
    {
        SSDT,L"ZwCreateThreadEx",ProxyZwCreateThreadEx,
        {
            1023,1023,1023,1023,388,382,382,88,88,333,333,333,332,332,332,336,337,337,338,341,341
        },44
    },
    {
        SSDT,L"ZwRestoreKey",ProxyZwRestoreKey,
        {
            1023,1023,204,212,279,280,280,302,302,105,107,107,106,106,106,109,110,110,111,111,111
        },55
    },
    {
        SSDT,L"ZwReplaceKey",ProxyZwReplaceKey,
        {
            1023,1023,193,201,268,268,268,292,292,115,117,117,116,116,116,119,120,120,121,121,121
        },56
    },
    {
        SSDT,L"ZwGetNextProcess",ProxyZwGetNextProcess,
        {
            1023,1023,1023,1023,371,367,367,139,139,270,272,272,271,271,271,274,275,275,276,278,278
        },45
    },
    {
        SSDT,L"ZwUnmapViewOfSection",ProxyZwUnmapViewOfSection,
        {
            1023,231,267,277,352,348,348,385,385,19,19,19,19,19,19,19,20,20,20,20,20
        },46
    },
    {
        SSDT,L"ZwAssignProcessToJobObject",ProxyZwAssignProcessToJobObject,
        {
            1023,18,19,21,42,42,42,43,43,377,382,382,381,381,381,386,387,387,389,392,392
        },47
    },
    {
        SSDT,L"ZwAllocateVirtualMemory",ProxyZwAllocateVirtualMemory,
        {
            1023,16,17,18,18,18,18,19,19,403,407,407,406,406,406,411,412,412,415,418,418
        },57
    },
    {
        SSDT,L"ZwFreeVirtualMemory",ProxyZwFreeVirtualMemory,
        {
            1023,71,83,87,147,147,147,131,131,278,281,281,280,280,280,284,285,285,286,288,288
        },58
    },
    {
        SSSDT,L"NtUserFindWindowEx",ProxyNtUserFindWindowEx,
        {
            1023,368,378,377,391,391,391,396,396,455,457,458,459,460,459,460,462,466,466,466,467
        },25
    },
    {
        SSSDT,L"NtUserBuildHwndList",ProxyNtUserBuildHwndList,
        {
            1023,302,312,311,322,322,322,323,323,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },26
    },
    {
        SSSDT,L"NtUserQueryWindow",ProxyNtUserQueryWindow,
        {
            1023,466,483,481,504,504,504,515,515,478,480,481,482,483,482,483,485,489,489,489,490
        },27
    },
    {
        SSSDT,L"NtUserGetForegroundWindow",ProxyNtUserGetForegroundWindow,
        {
            1023,393,404,403,418,418,418,423,423,426,428,429,430,430,429,430,431,435,435,435,435
        },28
    },
    {
        SSSDT,L"NtUserWindowFromPoint",ProxyNtUserWindowFromPoint,
        {
            1023,568,592,588,617,617,617,629,629,640,643,646,648,650,649,652,658,664,665,666,667
        },29
    },
    {
        SSSDT,L"NtUserSetParent",ProxyNtUserSetParent,
        {
            1023,510,529,526,550,550,550,560,560,582,585,587,589,591,590,593,595,601,602,603,604
        },30
    },
    {
        SSSDT,L"NtUserSetWindowLong",ProxyNtUserSetWindowLong,
        {
            1023,525,544,540,566,566,566,578,578,560,562,564,566,567,566,569,571,575,576,576,577
        },31
    },
    {
        SSSDT,L"NtUserMoveWindow",ProxyNtUserMoveWindow,
        {
            1023,449,465,464,484,484,484,495,495,499,501,502,503,504,503,505,507,511,511,511,512
        },32
    },
    {
        SSSDT,L"NtUserSetWindowPos",ProxyNtUserSetWindowPos,
        {
            1023,527,546,542,568,568,568,580,580,558,560,562,564,565,564,567,569,573,574,574,575
        },33
    },
    {
        SSSDT,L"NtUserSetWindowPlacement",ProxyNtUserSetWindowPlacement,
        {
            1023,526,545,541,567,567,567,579,579,559,561,563,565,566,565,568,570,574,575,575,576
        },34
    },
    {
        SSSDT,L"NtUserShowWindow",ProxyNtUserShowWindow,
        {
            1023,536,555,551,579,579,579,591,591,547,549,551,553,554,553,556,558,562,563,563,564
        },35
    },
    {
        SSSDT,L"NtUserShowWindowAsync",ProxyNtUserShowWindowAsync,
        {
            1023,537,556,552,580,580,580,592,592,546,548,550,552,553,552,555,557,561,562,562,563
        },36
    },
    {
        SSSDT,L"NtUserSendInput",ProxyNtUserSendInput,
        {
            1023,481,502,500,525,525,525,536,536,606,609,611,613,615,614,617,619,625,626,627,628
        },37
    },
    {
        SSSDT,L"NtUserSetWinEventHook",ProxyNtUserSetWinEventHook,
        {
            1023,533,552,548,576,576,576,588,588,550,552,554,556,557,556,559,561,565,566,566,567
        },49
    },
    {
        SSSDT,L"NtUserClipCursor",ProxyNtUserClipCursor,
        {
            1023,0,330,329,343,343,343,348,348,333,334,335,335,335,335,337,338,342,342,342,342
        },48
    },
    {
        SSSDT,L"NtUserSetWindowsHookEx",ProxyNtUserSetWindowsHookEx,
        {
            1023,530,549,545,573,573,573,585,585,553,555,557,559,560,559,562,564,568,569,569,570
        },50
    },
    {
        SSDT,L"ZwMakeTemporaryObject",ProxyZwMakeTemporaryObject,
        {
            1023,1023,105,110,174,174,174,164,164,246,248,248,247,247,247,250,251,251,252,254,254
        },59
    },
    {
        SSDT,L"ZwCreateUserProcess",ProxyZwCreateUserProcess,
        {
            1023,1023,1023,1023,1023,383,383,93,93,322,326,326,325,325,325,329,330,330,331,334,334
        },60
    },
    {
        SSSDT,L"NtUserMessageCall",ProxyNtUserMessageCall,
        {
            1023,444,460,459,479,479,479,490,490,504,506,507,508,509,508,510,512,516,516,516,517
        },61
    },
    {
        SSSDT,L"NtUserPostMessage",ProxyNtUserPostMessage,
        {
            1023,459,475,474,497,497,497,508,508,486,488,489,490,491,490,492,494,498,498,498,499
        },62
    },
    {
        SSSDT,L"NtUserPostThreadMessage",ProxyNtUserPostThreadMessage,
        {
            1023,460,476,475,498,498,498,509,509,485,487,488,489,490,489,491,493,497,497,497,498
        },63
    },
    {
        SSSDT,L"NtUserBuildHwndList_WIN8",ProxyNtUserBuildHwndList_WIN8,
        {
            1023,1023,1023,1023,1023,1023,1023,1023,1023,358,359,360,360,360,360,362,363,367,367,367,367
        },64
    },
    {
        SSDT,L"ZwFsControlFile",ProxyZwFsControlFile,
        {
            1023,1023,84,1023,150,150,150,134,134,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },65
    },
    {
        SSSDT,L"NtUserSetImeInfoEx",ProxyNtUserSetImeInfoEx,
        {
            1023,1023,517,1023,1023,1023,1023,550,550,1023,1023,1023,1023,1023,600,603,605,611,612,613,1023
        },66
    },
    {
        SSDT,L"ZwCreateProcessEx",ProxyZwCreateProcessEx,
        {
            1023,1023,48,50,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },72
    },
    {
        SSSDT,L"NtUserGetRawInputData",ProxyNtUserGetRawInputData,
        {
            1023,1023,428,1023,1023,1023,1023,448,448,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },67
    },
    {
        SSSDT,L"NtUserGetRawInputBuffer",ProxyNtUserGetRawInputBuffer,
        {
            1023,1023,427,1023,1023,1023,1023,447,447,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },68
    },
    {
        SSSDT,L"NtUserGetAsyncKeyState",ProxyNtUserGetAsyncKeyState,
        {
            1023,1023,383,1023,1023,1023,1023,402,402,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },69
    },
    {
        SSSDT,L"NtUserGetKeyState",ProxyNtUserGetKeyState,
        {
            1023,1023,416,1023,1023,1023,1023,436,436,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },70
    },
    {
        SSSDT,L"NtUserGetKeyboardState",ProxyNtUserGetKeyboardState,
        {
            1023,1023,414,1023,1023,1023,1023,434,434,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },71
    },
    {
        SSDT,L"ZwQueueApcThread",ProxyZwQueueApcThread,
        {
            1023,1023,180,1023,1023,1023,1023,269,269,1023,1023,1023,1023,1023,139,142,143,143,144,144,144
        },74
    },
    {
        SSDT,L"ZwSetSecurityObject",ProxyZwSetSecurityObject,
        {
            1023,1023,237,1023,1023,1023,1023,347,347,1023,1023,1023,1023,1023,59,60,61,61,61,61,61
        },75
    },
    {
        SSDT,L"ZwOpenFile",ProxyZwOpenFile,
        {
            1023,1023,116,1023,1023,1023,1023,179,179,1023,1023,1023,1023,1023,232,235,236,236,237,238,238
        },76
    },
    {
        SSDT,L"ZwQueueApcThreadEx",ProxyZwQueueApcThreadEx,
        {
            1023,1023,1023,1023,1023,1023,1023,270,270,1023,1023,1023,1023,1023,138,141,142,142,143,143,143
        },77
    },
    {
        SSDT,L"ZwCreateMutant",ProxyZwCreateMutant,
        {
            1023,1023,43,45,67,67,67,74,74,1023,1023,1023,1023,1023,346,350,351,351,352,355,355
        },78
    },
    {
        SSDT,L"ZwQuerySystemInformation",ProxyZwQuerySystemInformation,
        {
            1023,1023,173,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },79
    },
    {
        SSDT,L"ZwQueryIntervalProfile",ProxyZwQueryIntervalProfile,
        {
            1023,1023,158,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },80
    },
    {
        SSDT,L"ZwSetInformationProcess",ProxyZwSetInformationProcess,
        {
            1023,1023,228,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },81
    },
    {
        SSSDT,L"NtGdiAddFontMemResourceEx",ProxyNtGdiAddFontMemResourceEx,
        {
            1023,1023,4,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },82
    },
    {
        SSDT,L"ZwReplyWaitReceivePortEx",ProxyZwReplyWaitReceivePortEx,
        {
            1023,1023,196,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },83
    },
    {
        END,L"KeUserModeCallback",ProxyKeUserModeCallback,
        {
            1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },51
    },
    {
        SSDT,L"ZwOpenKey",ProxyZwOpenKey,
        {
            1023,1023,119,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },84
    },
    {
        SSDT,L"ZwMapViewOfSection",ProxyZwMapViewOfSection,
        {
            1023,1023,108,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },85
    },
    {
        SSDT,L"ZwSetIntervalProfile",ProxyZwSetIntervalProfile,
        {
            1023,1023,231,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },86
    },
    {
        SSSDT,L"NtGdiAddFontResourceW",ProxyNtGdiAddFontResourceW,
        {
            1023,1023,2,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },87
    },
    {
        SSSDT,L"NtGdiAddRemoteFontToDC",ProxyNtGdiAddRemoteFontToDC,
        {
            1023,1023,3,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },88
    },
    {
        SSDT,L"ZwQueryInformationProcess",ProxyZwQueryInformationProcess,
        {
            1023,1023,154,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },89
    },
    {
        SSDT,L"ZwQueryInformationThread",ProxyZwQueryInformationThread,
        {
            1023,1023,155,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },90
    },
    {
        SSDT,L"ZwCreateProfile",ProxyZwCreateProfile,
        {
            1023,1023,49,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },91
    },
    {
        SSDT,L"ZwVdmControl",ProxyZwVdmControl,
        {
            1023,1023,268,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },92
    },
    {
        SSDT,L"ZwCreateProcess",ProxyZwCreateProcess,
        {
            1023,1023,47,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },93
    },
    {
        SSSDT,L"NtGdiAddEmbFontToDC",ProxyNtGdiAddEmbFontToDC,
        {
            1023,1023,214,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },94
    },
    {
        SSDT,L"NtDebugActiveProcess",ProxyNtDebugActiveProcess,
        {
            1023,1023,57,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },95
    },
    {
        SSDT,L"NtAlpcCreatePort",ProxyNtAlpcCreatePort,
        {
            1023,1023,1023,1023,1023,1023,1023,23,23,1023,1023,1023,1023,1023,401,406,407,407,410,413,413
        },96
    },
    {
        SSDT,L"NtCreatePort",ProxyNtCreatePort,
        {
            1023,1023,46,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },97
    },
    {
        SSDT,L"ZwAdjustPrivilegesToken",ProxyZwAdjustPrivilegesToken,
        {
            1023,1023,11,1023,1023,1023,1023,12,12,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },98
    },
    {
        SSDT,L"ZwConnectPort",ProxyZwConnectPort,
        {
            1023,1023,31,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },99
    },
    {
        SSDT,L"ZwSecureConnectPort",ProxyZwSecureConnectPort,
        {
            1023,1023,210,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },100
    },
    {
        SSDT,L"ZwQueryKey",ProxyZwQueryKey,
        {
            1023,1023,160,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },101
    },
    {
        SSDT,L"ZwEnumerateKey",ProxyZwEnumerateKey,
        {
            1023,1023,71,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },102
    },
    {
        SSDT,L"ZwClose",ProxyZwClose,
        {
            1023,1023,25,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },103
    },
    {
        SSSDT,L"NtUserSystemParametersInfo",ProxyNtUserSystemParametersInfo,
        {
            1023,1023,559,1023,1023,1023,1023,559,595,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023
        },104
    },
    {
        END,NULL,NULL,
        {
            -1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        },105
    }
};

1.6 Proxy*函數(shù)模型

NPAGED_LOOKASIDE_LIST FilterLookAside;
BOOLEAN g_EvaluateTime;
//Proxy*函數(shù)模型  3參數(shù)函數(shù)為例
NTSTATUS __stdcall ProxyNtFunc(int param1,int param2,int param3)
{
    NTSTATUS status = STATUS_ACCESS_DENIED;
    ULONG Result;//自定義結(jié)果
    ULONGLONG Time = 0;
    DProxy* proxydata = DProxyTable[ENtFunc];
    FilterPacket* packet = ExAllocateFromNPagedLookasideList(&FilterLookAside);
    if(g_EvaluateTime)
        Time = KeQueryInterruptTime();
    if(!packet)
    {
        if(!proxydata->OriginFuncAddr)
            return status;
        return proxydata->OriginFuncAddr(param1,param2,param3);
    }
    packet->Params[0] = param1;
    packet->Params[1] = param2;
    packet->Params[2] = param3;
    packet->ParamNumber = 3;
    packet->OriginFuncAddr = proxydata->OriginFuncAddr;
    packet->IndexInTable = ENtFunc;
    InterlockedIncrement(&proxydata->PrevFilterRefCount);
    Result = ExecPrevFilter(packet,proxydata);//Prev過(guò)濾
    InterlockedDecrement(&proxydata->PrevFilterRefCount);
    if(Result == SYSMON_UNHANDLED)
    {
        if(packet->OriginFuncAddr)
        {
            status = packet->OriginFuncAddr(param1,param2,param3);
            packet->Status = status;
            InterlockedIncrement(&proxydata->PostFilterRefCount);
            Result = ExecPostFilter(packet);//Post過(guò)濾
            InterlockedDecrement(&proxydata->PostFilterRefCount);
        }
    }
    if(Result == SYSMON_HANDLED)
    {
        status = packet->Status;
    }
    if(g_EvaluateTime)
        EvaluateTime(proxydata,Time);
    ExDeleteNPagedLookasideList(packet);
    return status;
}

ULONG ExecPrevFilter(FilterPacket* packet,DProxy* proxydata)
{
    ULONG Result;
    if(!proxydata || !packet || packet->DisablePrevFilter)
        return SYSMON_UNHANDLED;
    for(int i=0;i<16;i++)
    {
        if(!proxydata->PrevFilterSlot[i].DeleteCount && proxydata->PrevFilterSlot[i].Filter && proxydata->SlotNum != 0)
        {
            InterlockedIncrement(&proxydata->PrevFilterSlot[i].CallCount);
            packet->CurrentSlot = i;
            Result = proxydata->PrevFilterSlot[i].Filter(packet);
            InterlockedDecrement(&proxydata->PrevFilterSlot[i].CallCount);
            if(packet->Access & 0x10)//如果權(quán)限被設(shè)置為放行
            {
                TsLogSprintfOutput(SysMonLogPt,"[Sysnap DbgLog] Modify--> TableIndex %d, Process %s[%d] ",
                    proxydata->TableIndex,PsGetProcessImageFileName(IoGetCurrentProcess()),PsGetCurrentProcessId());
            }
            switch(Result)
            {
            case SYSMON_FORBID:
                TsLogSprintfOutput(SysMonLogPt,"[Sysnap DbgLog] Block--> TableIndex %d, Process %s[%d] ",
                    proxydata->TableIndex,PsGetProcessImageFileName(IoGetCurrentProcess()),PsGetCurrentProcessId());
                return SYSMON_FORBID;
            case SYSMON_HANDLED:
                return SYSMON_HANDLED;
            case SYSMON_PASS:
            case SYSMON_PASS1:
                return SYSMON_UNHANDLED;
            default:
                break;
            }
        }
    }
}

ULONG ExecPostFilter(FilterPacket* packet)
{
    ULONG Result;
    if(!packet)
        return SYSMON_UNHANDLED;
    FILTER_SLOT* CurrentSlot = DProxyTable[packet->IndexInTable]->PrevFilterSlot;
    for(int i=0;i<16;i++)
    {
        if(!CurrentSlot [i].DeleteCount)
        {
            InterlockedIncrement(&CurrentSlot [i].CallCount);
            packet->CurrentSlot = i;
            Result = packet->PostFilterSlot(packet);
            InterlockedDecrement(&CurrentSlot [i].CallCount);
        }
        switch(Result)
        {
        case SYSMON_HANDLED:
            return SYSMON_HANDLED;
        case SYSMON_PASS:
        case SYSMON_PASS1:
        case SYSMON_FORBID:
            return SYSMON_UNHANDLED;
        default:
            break;
        }
    }
}

二循头、驅(qū)動(dòng)接口Interface

2.1 DeviceExtension接口

DeviceObject->DeviceExtension結(jié)構(gòu):
+00h    TAG=’TSFL’
+14h    FARPROC Interface
FARPROC Interface(intindex)

NTSTATUS Interface(int index,FARPROC* outfunc)
{//注意下面的函數(shù)都是自己實(shí)現(xiàn)的穿透函數(shù)
    If(!outfunc)
        Return STATUS_UNSUCCESSFUL;
    switch(index)
    {
    case 0:
*outfunc = SetEvaluateTime;
        Break;
    case 1:
*outfunc = DisablePrevFilter;
        Break;
    case 2:
*outfunc = SetPostFilter;
        Break;
    case 3:
*outfunc = ExecOriginFromPacket;
        Break;
    case 4:
*outfunc = AddPrevFilter;
        Break;
    case 5:
*outfunc = RemovePrevFilter;
        Break;
    case 6:
*outfunc = GetCurrentHookInfo;
        Break;
    case 7:
*outfunc = GetDProxyTable;
        Break;
default:
        *outfunc = NULL;
        Break;
}
Return STATUS_SUCESS;
}

2.2 SetEvaluateTime

Void __stdcall SetEvaluateTime(bool EvaluateTime)
{//設(shè)置計(jì)算過(guò)濾函數(shù)執(zhí)行耗時(shí)
    g_EvaluateTime = EvaluateTime;
}

2.3 SetDisablePrevFilter

Void __stdcall SetDisablePrevFilter(ULONG Index,BOOLEAN Disable)
{//設(shè)置是否執(zhí)行PrevFilter(同時(shí)也是PostFilter)
    If(Index < APINUMBER)
{
    If(DProxyTable[Index])
        DProxyTable[Index]-> DisablePrevFilter = Disable;
}
}

2.4 SetPostFilter

Void __stdcall SetPostFilter(FilterPacket* Packet,FARPROC Filter,ULONG Tag)
{//設(shè)置PostFilter函數(shù)
    If(Packet)
{
    Packet->TagSlot[Packet->CurrentSlot] = Tag;//用于修改參數(shù)或區(qū)分Filter
    Packet->PostFilterSlot[Packet->CurrentSlot] = Filter;
    Packet->SlotCount++;
}
}

2.5 ExecOriginFromPacket

NTSTATUS __stdcall ExecOriginFromPacket(FilterPacket* Packet) 
{//執(zhí)行Nt*原始函數(shù)
    If(!Packet || !Packet->OriginFuncAddr)
        Return STATUS_UNSUCCESSFUL;
    _asm
    {
        Mov eax, Packet->ParamNumber
        Test eax,eax
        Jbe tag1
        Lea ecx,[eax-1]
        Test ecx,ecx
        Jl tag1
        Lea edx,Packet->Params[ecx]//參數(shù)逐個(gè)壓棧
Tag1:
        Mov eax,[edx]
        Push eax
        Sub ecx,1
        Sub edx,4
        Test ecx,ecx
        Jge tag2
Tag2:
        Call Packet->OriginFuncAddr
    }
}

2.6 AddPrevFilter

NTSTATUS __stdcall ExecOriginFromPacket(FilterPacket* Packet) 
{//執(zhí)行Nt*原始函數(shù)
    If(!Packet || !Packet->OriginFuncAddr)
        Return STATUS_UNSUCCESSFUL;
    _asm
    {
        Mov eax, Packet->ParamNumber
        Test eax,eax
        Jbe tag1
        Lea ecx,[eax-1]
        Test ecx,ecx
        Jl tag1
        Lea edx,Packet->Params[ecx]//參數(shù)逐個(gè)壓棧
Tag1:
        Mov eax,[edx]
        Push eax
        Sub ecx,1
        Sub edx,4
        Test ecx,ecx
        Jge tag2
Tag2:
        Call Packet->OriginFuncAddr
    }
}

2.7 RemovePrevFilter

void WaitStop(FILTER_SLOT* CurrentSlot)
{
    KeInitializeTimer(&CurrentSlot->Timer);
    Li.QuadPart = 1000000;
    while(CurrentSlot->CallCount)
    {
        KeSetTimer(&CurrentSlot->Timer,&Li,NULL);
        KeWaitForSingleObject(&CurrentSlot->Timer,Executive,KernelMode,FALSE,NULL);
    }
    KeCancelTimer(&CurrentSlot->Timer);
}

NTSTATUS __fastcall RemovePrevFilter(ULONG Index,FARPROC Filter)
{//從Index對(duì)應(yīng)的函數(shù)過(guò)濾中查找刪除Filter
    if(!Filter || Index >= APINUMBER)
        return STATUS_UNSUCCESSFUL;
    if(!DProxyTable[Index] || !DProxyTable[Index]->IsInitialized)
        return STATUS_UNSUCCESSFUL;
    for(int i=0;i<16;i++)
    {
        if(DProxyTable[Index]->PrevFilterSlot[i].Filter == Filter)
        {
            LARGE_INTEGER Li;
            FILTER_SLOT* CurrentSlot = &DProxyTable[Index]->PrevFilterSlot[i];
            CurrentSlot->DeleteCount = FALSE;
            InterlockedIncrement(&CurrentSlot->DeleteCount);
            WaitStop(CurrentSlot);
            InterlockedExchange(&CurrentSlot->Filter,NULL);
            InterlockedDecrement(&DProxyTable[Index]->UsedSlotCount);
            WaitStop(CurrentSlot);
            InterlockedDecrement(&CurrentSlot->DeleteCount);
            return STATUS_UNSUCCESSFUL;
        }
    }
    return STATUS_UNSUCCESSFUL;
}

2.8 GetCurrentHookInfo

NTSTATUS __stdcall GetCurrentHookInfo(PULONG pLastErrorCode,PULONG pserHookType,PULONG pOsVer,PULONG pHookErrorIndex)
{
    if(OsVer && !LastErrorCode && HookErrorIndex == -1)
    {
        if(pLastErrorCode)
            *pLastErrorCode = 0;//獲取系統(tǒng)buildnumber
        if(pserHookType)
            *pserHookType = serHookType;
        if(pOsVer)
            *pOsVer = OsVer;
        if(pHookErrorIndex)
            *pHookErrorIndex = HookErrorIndex;
    }
    return STATUS_UNSUCCESSFUL;
}

LastErrorCode
0x01    ZwQuerySystemInformation獲取失敗
0x02    KeServiceDescriptorTable獲取失敗
0x04    KeAddSystemServiceTable獲取失敗
0x08    ShadowSSDT獲取失敗
0x10    MmUserProbeAddress獲取失敗
0x20    Int2E校驗(yàn)失敗

InitState
0x01    ZwQuerySystemInformation獲取成功
0x02    KeServiceDescriptorTable獲取成功
0x04    ShadowSSDT獲取成功
0x08    獲取Inline Hook點(diǎn)成功

serHookType 對(duì)KiFastCallEntry做inline hook的類型
0.  Nonhook         HOOKTYPE_NONE
1.  Inlinehook          HOOKTYPE_INLINE
2.  SSDTHook            HOOKTYPE_SSDT
3.  金山共存Inlinehook  HOOKTYPE_KSINLINE

OsVer
BuildNumber:
Win2000
2195        1
WinXp
2600        2
WinServer2003
3790        3
WinVista
6000        4
6001        5
6002        6
Win7
7600        7
7601        8
Win8
8102        9
8250        10
8400        11
8432        12
8441        12
8520        13
Win8.1
9200        14
9600        15
Win10
9841        16
9860        17
9926        18
10041   19
10049   20
?? 0

HookErrorIndex
    -1

IsBsod
    記錄藍(lán)屏

三、基礎(chǔ)庫(kù)

3.1 獲取注冊(cè)表鍵值

NTSTATUS GetRegDataWithType(PWCHAR RegPath,PWCHAR KeyName,PVOID OutData,ULONG BufSize,PULONG OutType)
{
    NTSTATUS status;
    HANDLE KeyHandle = NULL;
    ULONG ResultLength = 0;
    OBJECT_ATTRIBUTES Oa;
    UNICODE_STRING URegPath,UKeyName;
    PVOID ValueInfo;
    const int BufSize = sizeof(PKEY_VALUE_PARTIAL_INFORMATION) + sizeof(WCHAR[260]);
    if(!RegPath || !KeyName)
        return STATUS_INVALID_PARAMETER;
    InitializeObjectAttributes(&Oa,&URegPath,OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,NULL,NULL);
    status = ZwOpenKey(&KeyHandle,KEY_EXECUTE,&Oa);
    ValueInfo = ExAllocatePool(NonPagedPool,BufSize);
    if(NT_SUCCESS(status) && ValueInfo)
    {
        RtlZeroMemory(ValueInfo,BufSize);
        RtlInitUnicodeString(&UKeyName,KeyName);
        status = ZwQueryValueKey(KeyHandle,&UKeyName,KeyValuePartialInformation,ValueInfo,BufSize,&ResultLength);
        if(NT_SUCCESS(status))
        {
            PKEY_VALUE_PARTIAL_INFORMATION Info = (PKEY_VALUE_PARTIAL_INFORMATION)ValueInfo;
            if(OutType)
                *OutType = Info->Type;
            if(OutData)
                RtlCopyMemory(OutData,Info->Data,BufSize<Info->DataLength?BufSize:Info->DataLength);
        }
    }
    if(KeyHandle)
        ZwClose(KeyHandle);
    if(ValueInfo)
        ExFreePool(ValueInfo);
    return status;
}

NTSTATUS GetRegDataWithSize(PWCHAR RegPath,PWCHAR KeyName,PVOID OutData,ULONG BufSize,PULONG OutSize)
{
    NTSTATUS status;
    HANDLE KeyHandle = NULL;
    ULONG ResultLength = 0;
    OBJECT_ATTRIBUTES Oa;
    UNICODE_STRING URegPath,UKeyName;
    PVOID ValueInfo;
    const int BufSize = sizeof(PKEY_VALUE_PARTIAL_INFORMATION) + sizeof(WCHAR[260]);
    if(!RegPath || !KeyName)
        return STATUS_INVALID_PARAMETER;
    InitializeObjectAttributes(&Oa,&URegPath,OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,NULL,NULL);
    status = ZwOpenKey(&KeyHandle,KEY_EXECUTE,&Oa);
    ValueInfo = ExAllocatePool(NonPagedPool,BufSize);
    if(NT_SUCCESS(status) && ValueInfo)
    {
        RtlZeroMemory(ValueInfo,BufSize);
        RtlInitUnicodeString(&UKeyName,KeyName);
        status = ZwQueryValueKey(KeyHandle,&UKeyName,KeyValuePartialInformation,ValueInfo,BufSize,&ResultLength);
        if(NT_SUCCESS(status))
        {
            PKEY_VALUE_PARTIAL_INFORMATION Info = (PKEY_VALUE_PARTIAL_INFORMATION)ValueInfo;
            if(OutSize)
                *OutSize = Info->DataLength;
            if(OutData)
                RtlCopyMemory(OutData,Info->Data,BufSize<Info->DataLength?BufSize:Info->DataLength);
        }
    }
    if(KeyHandle)
        ZwClose(KeyHandle);
    if(ValueInfo)
        ExFreePool(ValueInfo);
    return status;
}

NTSTATUS GetRegDataWithSizeAndType(PWCHAR RegPath,PWCHAR KeyName,PVOID OutData,ULONG BufSize,PULONG OutSize,PULONG OutType)
{
    NTSTATUS status;
    HANDLE KeyHandle = NULL;
    ULONG ResultLength = 0;
    OBJECT_ATTRIBUTES Oa;
    UNICODE_STRING URegPath,UKeyName;
    PVOID ValueInfo;
    const int BufSize = sizeof(PKEY_VALUE_PARTIAL_INFORMATION) + sizeof(WCHAR[260]);
    if(!RegPath || !KeyName)
        return STATUS_INVALID_PARAMETER;
    InitializeObjectAttributes(&Oa,&URegPath,OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,NULL,NULL);
    status = ZwOpenKey(&KeyHandle,KEY_EXECUTE,&Oa);
    ValueInfo = ExAllocatePool(NonPagedPool,BufSize);
    if(NT_SUCCESS(status) && ValueInfo)
    {
        RtlZeroMemory(ValueInfo,BufSize);
        RtlInitUnicodeString(&UKeyName,KeyName);
        status = ZwQueryValueKey(KeyHandle,&UKeyName,KeyValuePartialInformation,ValueInfo,BufSize,&ResultLength);
        if(NT_SUCCESS(status))
        {
            PKEY_VALUE_PARTIAL_INFORMATION Info = (PKEY_VALUE_PARTIAL_INFORMATION)ValueInfo;
            if(OutSize)
                *OutSize = Info->DataLength;
            if(OutType)
                *OutType = Info->Type;
            if(OutData)
                RtlCopyMemory(OutData,Info->Data,BufSize<Info->DataLength?BufSize:Info->DataLength);
        }
    }
    if(KeyHandle)
        ZwClose(KeyHandle);
    if(ValueInfo)
        ExFreePool(ValueInfo);
    return status;
}

3.2 通過(guò)進(jìn)程名獲取進(jìn)程ID

HANDLE GetProcessIdByName(PWCHAR ProcessName)
{//根據(jù)進(jìn)程名獲取進(jìn)程ID
    HANDLE ProcessId = 0;
    NTSTATUS status = STATUS_SUCCESS;
    SIZE_T size = 512;
    UNICODE_STRING UProcessName;
    LPVOID Buffer;
    RtlInitUnicodeString(&UProcessName,ProcessName);
    while(true)
    {
        Buffer = ExAllocatePool(PagedPool,size);
        if(!Buffer)
            return 0;
        status = ZwQuerySystemInformation(SystemProcessesAndThreadsInformation,Buffer,size,NULL);
        if(status != STATUS_INFO_LENGTH_MISMATCH)
            break;
        ExFreePool(Buffer);
        size *= 2;
    }
    if(!NT_SUCCESS(Buffer))
        ExFreePool(Buffer);
    PSYSTEM_PROCESS_INFORMATION ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)Buffer;
    while(ProcessInfo->NextEntryOffset)
    {
        ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((UCHAR*)ProcessInfo + ProcessInfo->NextEntryOffset);
        if(RtlEqualUnicodeString(&UProcessName,&ProcessInfo->ImageName,TRUE)
            ProcessId = ProcessInfo->UniqueProcessId;
    }
    ExFreePool(Buffer);
    return ProcessId;
}

3.3 Rabbit加密算法

??Q管很多驅(qū)動(dòng)中存在的用于傳輸時(shí)加密的可逆算法使用了Rabbit分組加密算法炎疆,可以分段加解密卡骂,加密過(guò)程和解密過(guò)程一致。根據(jù)驅(qū)動(dòng)中加解密過(guò)程可以得到如下代碼邏輯:

#define ld(x) ((x>>32)&0xFFFFFFFF)
#define hw(x) ((x>>16)&0xFFFF)
#define lw(x) (x&0xFFFF)
#define rotl(x,y) ((x<<y)|(x>>(32-y)))

struct Rabbit
{
    unsigned int X[8];
    unsigned int C[8];
    unsigned int b;
};

bool Rabbit_nextState(Rabbit* rabbit);
bool Rabbit_Init(Rabbit* rabbit);
unsigned int Rabbit_toInt(unsigned char* key,int index);
bool Rabbit_SetKey(unsigned char* key,Rabbit* rabbit);

bool Rabbit_Init(Rabbit* rabbit)
{
    if(!rabbit)
        return false;
    for(int i=0;i<8;i++)
    {
        rabbit->C[i] = 0;
        rabbit->X[i] = 0;
        rabbit->b = 0;
    }
    return true;
}

unsigned int Rabbit_toInt(unsigned char* key,int index)
{
    if(!key)
        return 0;
    return key[index+3]|(key[index+2]<<8)|(key[index+1]<<16)|(key[index+0]<<24);
}

bool Rabbit_SetKey(unsigned char* key,Rabbit* rabbit)
{
    if(!key || !rabbit)
        return false;
    unsigned int K0 = Rabbit_toInt(key,0);
    unsigned int K1 = Rabbit_toInt(key,4);
    unsigned int K2 = Rabbit_toInt(key,8);
    unsigned int K3 = Rabbit_toInt(key,12);
    rabbit->X[0] = K3;
    rabbit->X[1] = (K0<<16)|(K1>>16);
    rabbit->X[2] = K2;
    rabbit->X[3] = (K3<<16)|(K0>>16);
    rabbit->X[4] = K1;
    rabbit->X[5] = (K2<<16)|(K3>>16);
    rabbit->X[6] = K0;
    rabbit->X[7] = (K1<<16)|(K2>>16);
    rabbit->C[0] = (K1<<16)|(K1>>16);
    rabbit->C[1] = ((K3&0xFFFF0000)|(K2&0xFFFF));
    rabbit->C[2] = (K0<<16)|(K0>>16);
    rabbit->C[3] = ((K2&0xFFFF0000)|(K1&0xFFFF));
    rabbit->C[4] = (K3<<16)|(K3>>16);
    rabbit->C[5] = ((K1&0xFFFF0000)|(K0&0xFFFF));
    rabbit->C[6] = (K2<<16)|(K2>>16);
    rabbit->C[7] = ((K0&0xFFFF0000)|(K3&0xFFFF));
    rabbit->b = 0;
    for(int i=0;i<4;i++)
    {
        Rabbit_nextState(rabbit);
    }
    for(int i=0;i<8;i++)
    {
        rabbit->C[i] ^= rabbit->X[(i+4)&7];
    }
    return true;
}


unsigned int Rabbit_u1(unsigned int n)
{
    unsigned int r0 = ((lw(n) * lw(n)) >> 17) + lw(n) * hw(n);
    unsigned int r1 = (r0 >> 15) + hw(n) * hw(n);
    unsigned int r2 = n * n;
    return r1 ^ r2;
//  _asm
//  {
//      mov esi,n
//      movzx edx,si
//      mov ecx,esi
//      shr ecx,0x10
//      push edi
//      mov eax, edx
//      imul eax, edx
//      mov edi, ecx
//      imul edi, edx
//      mov edx, ecx
//      imul edx, ecx
//      mov ecx, esi
//      imul ecx, esi
//      shr eax, 11h
//      add eax, edi
//      shr eax, 0Fh
//      add eax, edx
//      pop edi
//      xor eax, ecx
//  }
}

bool Rabbit_nextState(Rabbit* rabbit)
{
    unsigned int G[8]={0};
    unsigned int c_old[8];
    if(!rabbit)
        return false;
    memcpy(c_old,rabbit->C,sizeof(c_old));
    rabbit->C[0] += rabbit->b + 1295307597;
    rabbit->C[1] += (rabbit->C[0] < c_old[0]) - 749914925;
    rabbit->C[2] += (rabbit->C[1] < c_old[1]) + 886263092;
    rabbit->C[3] += (rabbit->C[2] < c_old[2]) + 1295307597;
    rabbit->C[4] += (rabbit->C[3] < c_old[3]) - 749914925;
    rabbit->C[5] += (rabbit->C[4] < c_old[4]) + 886263092;
    rabbit->C[6] += (rabbit->C[5] < c_old[5]) + 1295307597;
    rabbit->C[7] += (rabbit->C[6] < c_old[6]) - 749914925;
    rabbit->b = rabbit->C[7] < c_old[7];
    for(int i=0;i<8;i++)
    {
        G[i] = Rabbit_u1(rabbit->X[i]+rabbit->C[i]);
    }
    rabbit->X[0] = G[0] + rotl(G[7],16) + rotl(G[6],16);
    rabbit->X[1] = G[1] + rotl(G[0],8) + G[7];
    rabbit->X[2] = G[2] + rotl(G[1],16) + rotl(G[0],16);
    rabbit->X[3] = G[3] + rotl(G[2],8) + G[1];
    rabbit->X[4] = G[4] + rotl(G[3],16) + rotl(G[2],16);
    rabbit->X[5] = G[5] + rotl(G[4],8) + G[3];
    rabbit->X[6] = G[6] + rotl(G[5],16) + rotl(G[4],16);
    rabbit->X[7] = G[7] + rotl(G[6],8) + G[5];
    return true;
}

bool Rabbit_toByte(unsigned int s,unsigned char* d)
{
    if(!d)
        return false;
    d[0] = (s>>24)&0xff;
    d[1] = (s>>16)&0xff;
    d[2] = (s>>8)&0xff;
    d[3] = (s)&0xff;
    return true;
}

bool Rabbit_EncryptBuf(Rabbit* rabbit,unsigned char* src,int srclen,unsigned char* dst,int dstlen)
{
    unsigned int K[4] = {0};
    unsigned char v[4] = {0};
    if(!rabbit || !src || !dst || srclen>dstlen || srclen<=0)
        return false;
    for(int i=0;i<srclen;i+=16)
    {
        Rabbit_nextState(rabbit);
        K[0] = rabbit->X[0]^(rabbit->X[5]>>16)^(rabbit->X[3]<<16)^Rabbit_toInt(src,i);
        K[1] = rabbit->X[2]^(rabbit->X[5]<<16)^(rabbit->X[7]>>16)^Rabbit_toInt(src,i+4);
        K[2] = rabbit->X[4]^(rabbit->X[7]<<16)^(rabbit->X[1]>>16)^Rabbit_toInt(src,i+8);
        K[3] = rabbit->X[6]^(rabbit->X[3]>>16)^(rabbit->X[1]<<16)^Rabbit_toInt(src,i+12);
        for(int j=0;j<4;j++)
        {
            Rabbit_toByte(K[j],v);
            *(unsigned int*)(dst+i+4*j) = *(unsigned int*)v;
        }
    }
    return true;
}

下面是一個(gè)實(shí)例:
unsigned char encrypt[448] =
    {//加密過(guò)的進(jìn)程id
        0x30,0xa2,0xf6,0xa4,0xdb,0x6c,0xe9,0xa2,0x4d,0xdd,0x66,0x18,0xd1,0x8e,0xa9,0x8a,
        0x1c,0xa2,0xf6,0xa4,0xf3,0x6c,0xe9,0xa2,0x65,0xdd,0x66,0x18,0xc9,0x8e,0xa9,0x8a,
        0x08,0xa2,0xf6,0xa4,0x0b,0x6c,0xe9,0xa2,0xb5,0xdd,0x66,0x18,0x09,0x8e,0xa9,0x8a,
        0xc8,0xa2,0xf6,0xa4,0x43,0x6c,0xe9,0xa2,0xd5,0xdd,0x66,0x18,0x81,0x89,0xa9,0x8a,
        0x4c,0xa5,0xf6,0xa4,0xbf,0x6b,0xe9,0xa2,0x51,0xda,0x66,0x18,0xf5,0x89,0xa9,0x8a,
        0xc8,0xa5,0xf6,0xa4,0x43,0x6b,0xe9,0xa2,0xc5,0xda,0x66,0x18,0x6d,0x89,0xa9,0x8a,
        0x7c,0xa4,0xf6,0xa4,0x17,0x6a,0xe9,0xa2,0x89,0xdb,0x66,0x18,0x1d,0x88,0xa9,0x8a,
        0xc4,0xa4,0xf6,0xa4,0x5f,0x6a,0xe9,0xa2,0xf1,0xdb,0x66,0x18,0x55,0x88,0xa9,0x8a,
        0x14,0xa7,0xf6,0xa4,0xe7,0x69,0xe9,0xa2,0x79,0xd8,0x66,0x18,0xdd,0x8b,0xa9,0x8a,
        0x04,0xa7,0xf6,0xa4,0xf7,0x69,0xe9,0xa2,0x69,0xd8,0x66,0x18,0xcd,0x8b,0xa9,0x8a,
        0xf8,0xa7,0xf6,0xa4,0x13,0x69,0xe9,0xa2,0x85,0xd8,0x66,0x18,0x29,0x8b,0xa9,0x8a,
        0xe8,0xa7,0xf6,0xa4,0x2b,0x69,0xe9,0xa2,0xbd,0xd8,0x66,0x18,0x01,0x8b,0xa9,0x8a,
        0x64,0xa6,0xf6,0xa4,0x97,0x68,0xe9,0xa2,0x39,0xd9,0x66,0x18,0x85,0x8a,0xa9,0x8a,
        0xfc,0xa6,0xf6,0xa4,0x2b,0x68,0xe9,0xa2,0xbd,0xd9,0x66,0x18,0x09,0x8a,0xa9,0x8a,
        0xc8,0xa6,0xf6,0xa4,0x43,0x68,0xe9,0xa2,0xd5,0xd9,0x66,0x18,0x5d,0x8a,0xa9,0x8a,
        0x80,0xa6,0xf6,0xa4,0x17,0x6e,0xe9,0xa2,0xd1,0xdf,0x66,0x18,0x19,0x8c,0xa9,0x8a,
        0x90,0xa0,0xf6,0xa4,0x5f,0x6e,0xe9,0xa2,0x61,0xdf,0x66,0x18,0x81,0x8e,0xa9,0x8a,
        0xe0,0xa5,0xf6,0xa4,0x33,0x6b,0xe9,0xa2,0xa5,0xda,0x66,0x18,0xe1,0x88,0xa9,0x8a,
        0x80,0xa5,0xf6,0xa4,0xe7,0x6a,0xe9,0xa2,0x6d,0xdb,0x66,0x18,0x15,0x88,0xa9,0x8a,
        0xdc,0xa4,0xf6,0xa4,0x3f,0x6a,0xe9,0xa2,0x95,0xd8,0x66,0x18,0x7d,0x8b,0xa9,0x8a,
        0xa0,0xa7,0xf6,0xa4,0x77,0x69,0xe9,0xa2,0xed,0xd8,0x66,0x18,0xe9,0x8b,0xa9,0x8a,
        0x40,0xa7,0xf6,0xa4,0x8b,0x69,0xe9,0xa2,0xc9,0xdb,0x66,0x18,0x65,0x88,0xa9,0x8a,
        0xa4,0xa4,0xf6,0xa4,0x03,0x68,0xe9,0xa2,0x69,0xd9,0x66,0x18,0xd5,0x8a,0xa9,0x8a,
        0x78,0xa9,0xf6,0xa4,0x93,0x67,0xe9,0xa2,0x05,0xd6,0x66,0x18,0x91,0x85,0xa9,0x8a,
        0x50,0xa9,0xf6,0xa4,0xab,0x67,0xe9,0xa2,0xdd,0xd6,0x66,0x18,0x05,0x84,0xa9,0x8a,
        0x0c,0xab,0xf6,0xa4,0x6b,0x62,0xe9,0xa2,0xfd,0xd0,0x66,0x18,0xe9,0x83,0xa9,0x8a,
        0xa8,0xaf,0xf6,0xa4,0xb7,0x63,0xe9,0xa2,0xad,0xce,0x66,0x18,0xa1,0x9c,0xa9,0x8a,
        0x44,0xb2,0xf6,0xa4,0x7f,0x7c,0xe9,0xa2,0x15,0xca,0x66,0x18,0xb1,0x8d,0xa9,0x8a,
    };
    unsigned char decrypt[448]={0};//解密到目標(biāo)內(nèi)存
    Rabbit rabbit;
    Rabbit_Init(&rabbit);//初始化
    Rabbit_SetKey((unsigned char*)"0123456789ABCDEF",&rabbit);//加載密鑰
    Rabbit_EncryptBuf(&rabbit,encrypt,448,decrypt,448);//加密/解密
    /*解密后的進(jìn)程id
    00000344 00000358 0000035c 00000360
    00000368 00000370 00000374 00000378
    0000037c 00000388 000003a4 000003b8
    000003bc 000003c0 000003c4 00000430
    00000438 0000043c 00000440 00000444
    000004bc 000004c0 000004d4 000004dc
    00000508 00000594 00000598 000005ac
    000005b0 000005dc 000005e0 000005e4
    00000660 00000664 00000668 0000066c
    00000670 00000674 00000678 0000067c
    0000068c 00000690 00000694 00000698
    0000069c 000006a8 000006ac 000006b0
    00000710 00000714 00000728 00000734
    00000788 000007a8 000007ac 000007b8
    000007bc 000007c0 000007c4 000007ec
    000007f4 00000194 000001c0 000001a8
    000001e4 000001dc 00000170 00000330
    00000494 000004b0 000004b4 00000550
    000004f4 00000564 0000057c 000005a4
    000005a8 000005bc 00000684 000006cc
    000006d4 000006f4 000006fc 00000658
    00000634 00000608 000005d8 000005d4
    000005d0 00000780 00000778 00000764
    0000080c 00000810 00000814 00000820
    00000824 00000828 000008cc 000009b4
    00000a78 00000de8 00000eec 00000e58
    00000edc 00000c34 000010bc 00001110
    00001330 000013fc 00001404 00000000
*/

四形入、InlineHook KiFastCallEntry

  • 重置藍(lán)屏死機(jī)計(jì)數(shù) 用于檢測(cè)hook造成的藍(lán)屏
  • 獲取SSDT/SSSDT/ hook點(diǎn)
  • 分配跳轉(zhuǎn)表ServiceMapTable
  • 改寫(xiě)KiFastCallEntry使跳轉(zhuǎn)表生效
  • Hook重要回調(diào)
  • 開(kāi)啟日志記錄
  • Hook KeUserModeCallback

4.1 獲取SSDT/SSSDT/Hook點(diǎn)

ULONG InitState = 0;
ULONG LastErrorCode = 0;


UCHAR int2Ecode1[10] = {0x8B, 0xFC, 0x3B, 0x35, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x83};
UCHAR int2Ecode2[22] = {0x8B, 0xFC, 0xF6, 0x45, 0x72, 0x02, 0x75, 0x06, 0xF6, 0x45, 0x6C,
                        0x01, 0x74, 0x0C, 0x3B, 0x35, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x83};

ULONG GetHookPoint1()
{//檢測(cè)系統(tǒng)原始KiFastCallEntry
    *(ULONG*)(int2Ecode2 + 4) = MmUserProbeAddress;//構(gòu)造cmp esi,dword ptr ds:[MmUserProbeAddress]
    if(!MmUserProbeAddress)
        return 0;
    ULONG ptr = GetKiSystemServiceAddr();//KiFastCallEntry總在KiSystemService之后
    if(ptr < NtosBase || ptr > NtosBase+NtosSize)
        return 0;
    for(int offset = 0;offset < 1024;offset++,ptr++)
    {
        /*
            mov edi,esp
            cmp esi,dword ptr ds:[MmUserProbeAddress]
            jae ??
        */
        if(RtlCompareMemory(ptr,int2Ecode1,sizeof(int2Ecode1)) == sizeof(int2Ecode1))
            return ptr;
    }
    return 0;
}

ULONG GetHookPoint2()
{//檢測(cè)是否被金山inline hook過(guò)得KiFastCallEntry
    *(ULONG*)(int2Ecode2 + 16) = MmUserProbeAddress;//構(gòu)造cmp esi,dword ptr ds:[MmUserProbeAddress]
    if(!MmUserProbeAddress)
        return 0;
    ULONG ptr = GetKiSystemServiceAddr();
    if(ptr < NtosBase || ptr > NtosBase+NtosSize)
        return 0;
    for(int offset = 0;offset < 1024;offset++,ptr++)
    {
        /*
            mov edi,esp
            test byte ptr[ebp+72h],2
            jne $1
            test byte ptr[ebp+6Ch],1
            je ??
            $1:
            cmp esi,dword ptr ds:[MmUserProbeAddress]
            jae ??
        */
        if(RtlCompareMemory(ptr,int2Ecode2,sizeof(int2Ecode2)) == sizeof(int2Ecode2))
            return ptr;
    }
    return 0;
}

ULONG InitState = 0,LastErrorCode = 0,serHookType = 0;
ULONG NtosBase,NtosSize,SSDTBase,SSDTLimit,ShadowSSDTBase,ShadowSSDTLimit,Win32kBase,Win32kSize;
ULONG dwcsrssId;
ULONG BuildIndex;
PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;
ULONG MmUserProbeAddress;

struct HOOKINFO
{
    ULONG InlinePoint;
    ULONG JmpBackPoint;
    UCHAR OriginCode[8];
};

HOOKINFO HookInfo1={0},HookInfo2={0};
/*
KiFastCallEntry+0xde:
    mov     ebx,dword ptr [edi+eax*4]
    jmp     81f9e3e0
    nop                                             =>  InlinePoint
    nop
    nop
    jmp     TsFltMgr+0x2300 (f8517300)
    jae     nt!KiSystemCallExit2+0x9f (8053e7ec)    =>  JmpBackPoint
    rep movs dword ptr es:[edi],dword ptr [esi]
    call    ebx

    OriginCode[8];
    8bfc            mov     edi,esp
    3b35549a5580    cmp     esi,dword ptr [nt!MmUserProbeAddress]
*/
NTSTATUS PrepareHook()
{
    RTL_PROCESS_MODULE_INFORMATION Win32kInfo,NtosInfo;
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    ULONG ReturnLength = 0;
    ULONG OutData;
    LPVOID Buffer = NULL;
    RtlZeroMemory(&Win32kInfo,sizeof(Win32kInfo));
    RtlZeroMemory(&NtosInfo,sizeof(NtosInfo));
    InitState = 0;
    LastErrorCode = 0;
    status = GetRegDataWithType(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\TsFltMgr", 
        L"thm", &OutData, 4, 0)
    if(NT_SUCCESS(status) && OutData == 1)
        serHookType = HOOKTYPE_SSDT;
    ZwQuerySystemInformation(SystemModuleInformation,&ReturnLength,0,&ReturnLength);
    if(ReturnLength)
        Buffer = ExAllocatePool(PagedPool,ReturnLength);
    if(Buffer)
        status = ZwQuerySystemInformation(SystemModuleInformation,Buffer,ReturnLength,NULL);
    if(!NT_SUCCESS(status))
    {
        ExFreePool(Buffer);
        Buffer = NULL;
    }
    if(Buffer)
    {
        RtlCopyMemory(&NtosInfo,((PRTL_PROCESS_MODULES)Buffer)->Modules,sizeof(NtosInfo));
        ExFreePool(Buffer);
        NtosBase = NtosInfo.ImageBase;
        NtosSize = NtosInfo.ImageSize;
        ULONG FuncAddr = MiLocateExportName(NtosBase,"KeServiceDescriptorTable");
        if(FuncAddr && MmIsAddressValid(FuncAddr))
        {
            PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable = (PKSERVICE_TABLE_DESCRIPTOR)FuncAddr;
            SSDTBase = KeServiceDescriptorTable[0].Base;
            SSDTLimit = KeServiceDescriptorTable[0].Limit;
            InitState |= 2;
            dwcsrssId = GetProcessIdByName(L"csrss.exe");
            if(GetProcessInfoByFileName("WIN32K.SYS",&Win32kInfo))
            {
                Win32kBase = Win32kInfo.ImageBase;
                Win32kSize = Win32kInfo.ImageSize;
                if(NT_SUCCESS(GetShadowSSDTInfo()))
                    InitState |= 4;
            }
            
            UNICODE_STRING UMmUserProbeAddress;
            RtlInitUnicodeString(&UMmUserProbeAddress,L"MmUserProbeAddress");
            ULONG MmUserProbeAddress = MmGetSystemRoutineAddress(&UMmUserProbeAddress);
            if(MmUserProbeAddress && MmIsAddressValid(MmUserProbeAddress))
            {
                HookInfo1.InlinePoint = GetHookPoint1();
                if(HookInfo1.InlinePoint)
                    HookInfo1.JmpBackPoint = HookInfo1.InlinePoint + 8;
                else
                {
                    HookInfo2.InlinePoint = GetHookPoint2();
                    if(HookInfo2.InlinePoint)
                        HookInfo2.JmpBackPoint = HookInfo2.InlinePoint + 6;
                }
                if(HookInfo1.InlinePoint == 0 && HookInfo2.InlinePoint == 0)
                {
                    LastErrorCode |= 0x20;
                    return status;
                }
                InitState |= 8;
                MmUserProbeAddress = *(ULONG*)MmUserProbeAddress;
                status = STATUS_SUCCESS;
            }
            else
            {
                LastErrorCode |= 0x10;
            }
        }
        else
        {
            LastErrorCode |= 2;
        }
    }
    else
    {
        LastErrorCode |= 1;
    }
    return status;
}

4.2 從KiSystemService獲取KiFastCallEntry

struct IDTR
{
    USHORT IDTLimit;
    PKIDTENTRY IDTBase;
};
ULONG GetKiSystemServiceAddr()
{
    IDTR idt = {0};
    RTL_PROCESS_MODULE_INFORMATION NtosInfo,Win32kInfo;
    RtlZeroMemory(&NtosInfo,sizeof(NtosInfo));
    __sidt(&idt);
    if(idt.IDTBase)
    {
        KIDTENTRY int2e = idt.IDTBase[0x2E];
        if(MmIsAddressValid(int2e))
            return MAKEULONG(int2e.ExtendedOffset,int2e.Offset);
    }
    return 0;
}

4.3 獲取SSSDT信息

NTSTATUS GetShadowSSDTInfo()
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    PVOID pt = MiLocateExportName(NtosBase, "KeAddSystemServiceTable");
    PMDL mdl = NULL;
    if(pt && !MmIsAddressValid(pt))
    {//頁(yè)換出
        mdl = MmCreateMdl(NULL,pt,0x1000);
        if(mdl)
        {
            MmProbeAndLockPages(mdl,KernelMode,IoReadAccess);
        }
    }
    if(!pt || !MmIsAddressValid(pt))
    {
        LastErrorCode |= 4;
        goto END;
    }

    switch(BuildIndex)
    {
    case WIN2000:
    case WINXP:
    case WINXPSP3:
    case WINVISTA:
    case WINVISTASP1:
    case WINVISTASP2:
    case WIN7:
    case WIN7SP1:
        for(int i=0;i<256;i++)
        {
            if(MmIsAddressValid(pt) && *(USHORT*)pt == 0x888D)
            {//8d88603f5580    lea     ecx,nt!KeServiceDescriptorTableShadow 
                PKSERVICE_TABLE_DESCRIPTOR Table = *(ULONG*)(pt+2);
                ShadowSSDTBase = Table[1].Base;
                ShadowSSDTLimit = Table[1].Limit;
                status = STATUS_SUCCESS;
            }
        }
        break;
    case WIN8_8102:
    case WIN8_8250:
    case WIN81_9200:
    case WIN81_9600:
        for(int i=0;i<256;i++)
        {
            if(MmIsAddressValid(pt) && *(USHORT*)pt == 0xB983)
            {//83b9603f558083  cmp     dword ptr nt!KeServiceDescriptorTableShadow
                PKSERVICE_TABLE_DESCRIPTOR Table = *(ULONG*)(pt+2);
                if(KeServiceDescriptorTable == Table)
                {
                    ShadowSSDTBase = Table[1].Base;
                    ShadowSSDTLimit = Table[1].Limit;
                    status = STATUS_SUCCESS;
                }
            }
        }
        break;
    case WIN10_9841:
    case WIN10_9860:
    case WIN10_9926:
    case WIN10_10041:
    case WIN10_10049:
        for(int i=0;i<256;i++)
        {
            if(MmIsAddressValid(pt) && *(USHORT*)pt == 0x3D83)
            {//833d90d28d8100  cmp     dword ptr [nt!KeServiceDescriptorTableShadow+0x10],0
                PKSERVICE_TABLE_DESCRIPTOR Table = *(ULONG*)(pt+2) - 16;
                if(KeServiceDescriptorTable == Table)
                {
                    ShadowSSDTBase = Table[1].Base;
                    ShadowSSDTLimit = Table[1].Limit;
                    status = STATUS_SUCCESS;
                }
            }
        }
        break;
    }
    if(!ShadowSSDTBase)
        LastErrorCode |= 8;
END:
    if(mdl)
    {
        MmUnlockPages(mdl);
        IoFreeMdl(mdl);
    }
}

4.4 初始化InlineHook KiFastCallEntry跳轉(zhuǎn)表

BOOLEAN InitProxyTable()
{
    ULONG BuildIndex = GetBuildNumberAsIndex();
    for(int i = 0;i < APINUMBER;i++)
    {
        for(int j = 0;j < BUILDMAX;j++)
        {
            if(SProxyTable[i].ServiceIndex[j] == 0)
                SProxyTable[i].ServiceIndex[j] = 1023;//置為無(wú)效
        }
    }
    if(GetServiceIndex("ZwCreateKey") == -1)
    {//不能獲取到服務(wù)號(hào)
        if(NtosBase)
        {
            for(int i = 0;i < APINUMBER;i++)
            {
                if(SProxyTable[i].ServiceTableType == END)
                    break;
                else if(SProxyTable[i].ServiceTableType == SSDT)
                {
                    if(SProxyTable[i].ApiName)
                    {
                        UNICODE_STRING UApiName;
                        ANSI_STRING AApiName;
                        RtlInitUnicodeString(&UApiName,SProxyTable[i].ApiName);
                        if(NT_SUCCESS(RtlUnicodeStringToAnsiString(&AApiName,&UApiName,TRUE)))
                        {
                            GetServiceIndexFromNtos(AApiName.Buffer);
                            RtlFreeAnsiString(AApiName);
                        }
                    }               
                }
            }
        }
    }
    else
    {//能獲取到服務(wù)號(hào)   由于SProxyTable已存服務(wù)號(hào)全跨,所以下面代碼本身無(wú)效
        for(int i = 0;i < APINUMBER;i++)
        {
            if(SProxyTable[i].ServiceTableType == END)
                break;
            if(SProxyTable[i].ServiceTableType == SSDT)
            {
                if(SProxyTable[i].ApiName)
                {
                    UNICODE_STRING UApiName;
                    ANSI_STRING AApiName;
                    RtlInitUnicodeString(&UApiName,SProxyTable[i].ApiName);
                    if(NT_SUCCESS(RtlUnicodeStringToAnsiString(&AApiName,&UApiName,TRUE)))
                    {
                        ULONG Index = GetServiceIndexFromNtdll(AApiName.Buffer);
                        if(Index != -1)
                            SProxyTable[i].ServiceIndex[BuildIndex] = Index;
                        RtlFreeAnsiString(AApiName);
                    }
                }
            }
        }
    }
    return TRUE;
}

int AllocHookTable()
{//已知系統(tǒng)情況下初始化代理表,直接使用ServiceIndex
    ULONG BuildIndex = GetBuildNumberAsIndex();
    DProxy* Proxydata = NULL;
    ULONG Count = 0;//未成功布置的代理函數(shù)個(gè)數(shù)
    if(BuildIndex >= 0 && BuildIndex < BUILDMAX)
    {
        InitProxyTable();
        for(int i=0;i<APINUMBER;i++)
        {
            if(SProxyTable[i].ServiceTableType == END)
                break;
            if(SProxyTable[i].ServiceIndex[BuildIndex] != 1023)
            {
                if(SProxyTable[i].ApiName && SProxyTable[i].ProxyFunc && SProxyTable[i].IndexInTable < APINUMBER)
                {
                    Proxydata = (DProxy*)ExAllocatePool(NonPagedPool,sizeof(DProxy));
                    if(Proxydata)
                    {
                        Proxydata->IsInitialized = FALSE;
                        Proxydata->ApiName = SProxyTable[i].ApiName;
                        Proxydata->TableIndex = SProxyTable[i].IndexInTable;
                        Proxydata->ProxyFuncAddr = SProxyTable[i].ProxyFunc;
                        Proxydata->ServiceIndex = -1;
                        KeInitializeEvent(Proxydata->Lock,SynchronizationEvent,FALSE);
                        DProxyTable[SProxyTable[i].IndexInTable] = Proxydata;
                        ULONG ServiceType = SProxyTable[i].ServiceTableType;
                        ULONG ServiceIndex = SProxyTable[i].ServiceIndex[BuildIndex];
                        if(ServiceType >= 2 ||  ServiceIndex== -1 || ServiceIndex >= 1024)
                        {
                            Count++;
                        }
                        else
                        {
                            ServiceMapTable[ServiceType][ServiceIndex] = Proxydata;
                            Proxydata->ServiceTableType = ServiceType;
                            Proxydata->ServiceIndex = ServiceIndex;
                        }
                    }
                }
            }
        }
        return Count;
    }
    return APINUMBER;//返回未成功代理的個(gè)數(shù)
}

int AllocHookTableU()
{//未知系統(tǒng)情況下初始化代理表亿遂,臨時(shí)從Ntos模塊獲取ServiceIndex
    
    if(!NtosBase)
        return 0;//返回成功布置代理的個(gè)數(shù)
    for(int i=0;i<APINUMBER;i++)
    {
        if(SProxyTable[i].ServiceTableType == END)
            break;
        else if(SProxyTable[i].ServiceTableType == SSDT)
        {
            if(SProxyTable[i].ApiName)
            {
                PUNICODE_STRING UApiName;
                ANSI_STRING AApiName;
                ULONG Index = -1;
                RtlInitUnicodeString(&UApiName,SProxyTable[i].ApiName);
                if(NT_SUCCESS(RtlUnicodeStringToAnsiString(&AApiName,&UApiName,TRUE)))
                {
                    Index = GetServiceIndexFromNtos(AApiName.Buffer);
                    RtlFreeAnsiString(&AApiName);
                }
                if(Index != -1)
                {
                    if(SProxyTable[i].ApiName && SProxyTable[i].ProxyFunc && SProxyTable[i].IndexInTable < APINUMBER)
                    {
                        Proxydata = (DProxy*)ExAllocatePool(NonPagedPool,sizeof(DProxy));
                        if(Proxydata)
                        {
                            Proxydata->IsInitialized = FALSE;
                            Proxydata->ApiName = SProxyTable[i].ApiName;
                            Proxydata->TableIndex = SProxyTable[i].IndexInTable;
                            Proxydata->ProxyFuncAddr = SProxyTable[i].ProxyFunc;
                            Proxydata->ServiceIndex = -1;
                            KeInitializeEvent(Proxydata->Lock,SynchronizationEvent,FALSE);
                            DProxyTable[SProxyTable[i].IndexInTable] = Proxydata;
                            ULONG ServiceType = SProxyTable[i].ServiceTableType;
                            ULONG ServiceIndex = SProxyTable[i].ServiceIndex[BuildIndex];
                            if(ServiceType >= 2 ||  ServiceIndex== -1 || ServiceIndex >= 1024)
                            {
                                Count++;
                                ServiceMapTable[ServiceType][ServiceIndex] = Proxydata;
                                Proxydata->ServiceTableType = ServiceType;
                                Proxydata->ServiceIndex = ServiceIndex;
                            }
                        }
                    }
                }
            }
        }
    }
    return Count;
}

4.5 獲取系統(tǒng)服務(wù)號(hào)的2種方式

ULONG GetServiceIndexFromNtdll(PCHAR ApiName)
{
    ULONG result = -1;
    RTL_PROCESS_MODULE_INFORMATION ProcessInfo;
    ULONG Index;
    RtlZeroMemory(&ProcessInfo,sizeof(ProcessInfo));
    if(GetProcessInfoByFileName("ntdll.dll",&ProcessInfo) && ProcessInfo.ImageBase && ApiName)
    {
        Index = MiLocateExportName(ProcessInfo.ImageBase,ApiName);
        if(Index)
        {
            result = *(ULONG*)(Index+1);
        }
    }
    return result;
}

ULONG GetServiceIndexFromNtos(PCHAR ApiName)
{
    ULONG result = -1;
    ULONG Index = MiLocateExportName(ProcessInfo.ImageBase,ApiName);
    if(Index)
    {
        result = *(ULONG*)(Index+1);
    }
    if(Index & 0xFFFFC000)
    {
        result = -1;
    }
    return result;
}

4.6 InlineHook過(guò)程

NTSTATUS DoInlineHook()
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    ULONG MajorVersion = 0,MinorVersion = 0,BuildNumber = 0;
    PsGetVersion(&MajorVersion,&MinorVersion,&BuildNumber,NULL);
    if(serHookType == HOOKTYPE_SSDT || !(InitState & 8))//外部hook或沒(méi)找到hook掛載點(diǎn)
        return status;
    if(HookInfo1.InlinePoint)
    {//如果為默認(rèn)方式hook
        if(GetBuildNumberAsIndex() >= WINVISTA)
            status = ModifyAndHook(HookInfo1.InlinePoint,InlineKiFastCallEntry1);
        else
            status = ModifyAndHook(HookInfo1.InlinePoint,InlineKiFastCallEntry2);
        if(NT_SUCCESS(status))
            serHookType = HOOKTYPE_INLINE;
    }
    else if(HookInfo2.InlinePoint)
    {//如果為金山共存方式hook
        if(GetBuildNumberAsIndex() >= WINVISTA)
            status = ModifyAndHookK(HookInfo2.InlinePoint,InlineKiFastCallEntry3);
        else
            status = ModifyAndHookK(HookInfo2.InlinePoint,InlineKiFastCallEntry4);
        if(NT_SUCCESS(status))
            serHookType = HOOKTYPE_KSINLINE;
    }
    if(NT_SUCCESS(status))
    {
        for(int i=0;i<APINUMBER;i++)
        {
            if(DProxyTable[i] != 0 && (DProxyTable[i]->ServiceTableType == SSDT || DProxyTable[i]->ServiceTableType == SSSDT))
                DProxyTable[i]->IsInitialized = TRUE;
        }
    }
}

NTSTATUS DoInlineHookU()
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    ULONG MajorVersion = 0,MinorVersion = 0,BuildNumber = 0;
    PsGetVersion(&MajorVersion,&MinorVersion,&BuildNumber,NULL);
    if(serHookType == HOOKTYPE_SSDT || !(InitState & 8))//采用外部hook或沒(méi)找到hook掛載點(diǎn)
        return status;
    if(HookInfo1.InlinePoint)
    {//如果為默認(rèn)方式hook
        if(GetBuildNumberAsIndex() >= WINVISTA)
            status = ModifyAndHook(HookInfo1.InlinePoint,InlineKiFastCallEntry1);
        else
            status = ModifyAndHook(HookInfo1.InlinePoint,InlineKiFastCallEntry2);
        if(NT_SUCCESS(status))
            serHookType = HOOKTYPE_INLINE;
    }
    else if(HookInfo2.InlinePoint)
    {//如果為金山共存方式hook
        if(GetBuildNumberAsIndex() >= WINVISTA)
            status = ModifyAndHookK(HookInfo2.InlinePoint,InlineKiFastCallEntry3);
        else
            status = ModifyAndHookK(HookInfo2.InlinePoint,InlineKiFastCallEntry4);
        if(NT_SUCCESS(status))
            serHookType = HOOKTYPE_KSINLINE;
    }
    if(NT_SUCCESS(status))
    {
        for(int i=0;i<APINUMBER;i++)
        {
            if(DProxyTable[i] != 0 && (DProxyTable[i]->ServiceTableType == SSDT || DProxyTable[i]->ServiceTableType == SSSDT))
                DProxyTable[i]->IsInitialized = TRUE;
        }
    }
}

NTSTATUS ModifyAndHook(ULONG InlinePoint,FARPROC JmpToFunc)
{//HOOKTYPE_INLINE 更改KiFastCallEntry
    NTSTATUS status;
    PVOID MappedAddress = NULL;
    if(!InlinePoint || !InlineHookFunc)
        return STATUS_UNSUCCESSFUL;
    PMDL mdl = GetWritablePage(InlinePoint,16,&MappedAddress);
    /*
        改寫(xiě)                      為
        mov edi,esp                     nop
        cmp esp,dword ptr ds:[?]        nop
                                        nop
                                        jmp ?
    */
    if(!mdl)
        return STATUS_UNSUCCESSFUL;
    ULONG data[3] = {InlinePoint,JmpToFunc,MappedAddress};
    status = MakeJmp(data,DoHook);
    MmUnlockPages(mdl);
    IoFreeMdl(mdl);
    return status;
}

NTSTATUS ModifyAndHookK(ULONG InlinePoint,FARPROC JmpToFunc)
{//HOOKTYPE_KSINLINE 更改KiFastCallEntry
    NTSTATUS status;
    PVOID MappedAddress = NULL;
    if(!InlinePoint || !InlineHookFunc)
        return STATUS_UNSUCCESSFUL;
    PMDL mdl = GetWritablePage(InlinePoint,16,&MappedAddress);
    if(!mdl)
        return STATUS_UNSUCCESSFUL;
    ULONG data[3] = {InlinePoint,JmpToFunc,MappedAddress};
    status = MakeJmp(data,DoHookK);
    MmUnlockPages(mdl);
    IoFreeMdl(mdl);
    return status;
}

NTSTATUS DoHook(ULONG* data)
{//HOOKTYPE_INLINE
    ULONGLONG shellcode;
    if(!data)
        return STATUS_UNSUCCESSFUL;
    *(ULONGLONG*)(HookInfo1.OriginCode) = *(ULONGLONG*)data[0];//保存原始8字節(jié)
    *(ULONG*)((UCHAR*)&shellcode+4) = data[1] - data[0] - 8;//填寫(xiě)偏移 jmp offset
    *(ULONG*)((UCHAR*)&shellcode) = 0xE9909090;//寫(xiě)入新8字節(jié)
    /*
        構(gòu)造
        nop
        nop
        nop
        jmp ????
    */
    InterlockedCompareExchange64((LONGLONG*)data[2],shellcode,*(LONGLONG*)data[2]);
    return STATUS_SUCCESS;
}

NTSTATUS DoHookK(ULONG* data)
{//HOOKTYPE_KSINLINE
    ULONGLONG shellcode;
    if(!data)
        return STATUS_UNSUCCESSFUL;
    *(ULONGLONG*)(HookInfo1.OriginCode) = *(ULONGLONG*)data[0];//保存原始8字節(jié)
    *(USHORT*)((UCHAR*)&shellcode+6) = 0x0675;
    *(ULONG*)((UCHAR*)&shellcode+2) = data[1] - data[0] - 8;//填寫(xiě)偏移 jmp offset
    *(ULONG*)((UCHAR*)&shellcode) = 0xE990;//寫(xiě)入新8字節(jié)
    InterlockedCompareExchange64((LONGLONG*)data[2],shellcode,*(LONGLONG*)data[2]);
    return STATUS_SUCCESS;
}

PMDL GetWritablePage(PVOID VirtualAddress,ULONG Length,PVOID* pMappedAddress)
{
    PMDL mdl = IoAllocateMdl(VirtualAddress,Length,FALSE,TRUE,NULL);
    if(mdl)
    {
        MmProbeAndLockPages(mdl,KernelMode,IoWriteAccess);
        PVOID NewAddr = MmGetSystemAddressForMdlSafe (Mdl, NormalPagePriority);
        if(!NewAddr)
        {
            MmUnlockPages(mdl);
            IoFreeMdl(mdl);
            mdl = NULL;
        }
        if(NewAddr)
            *pMappedAddress = NewAddr;
    }
    return mdl;
}

4.7 構(gòu)造InlineHook跳轉(zhuǎn)后的執(zhí)行語(yǔ)句

ULONG Filter(ULONG ServiceIndex,ULONG OriginFunc,ULONG Base)
{
    if(ServiceIndex >= 1024)
        return OriginFunc;
    ULONG TableType;
    if(Base == SSDTBase && ServiceIndex <= SSDTLimit)
    {
        TableType = SSDT;
    }
    else if(KeServiceDescriptorTable && KeServiceDescriptorTable->Base == Base && ServiceIndex <= SSDTLimit)
    {
        TableType = SSDT;
    }
    else if(Base == ShadowSSDTBase && ServiceIndex <= ShadowSSDTLimit)
    {
        TableType = SSSDT;
    }
    else
    {
        return OriginFunc;
    }
    if(ServiceMapTable[TableType][ServiceIndex])
    {
        ULONG NewAddr = ServiceMapTable[TableType][ServiceIndex]->ProxyFuncAddr;
        if(NewAddr)
        {
            ServiceMapTable[TableType][ServiceIndex]->OriginFuncAddr = OriginFunc;
            return NewAddr;
        }
    }
    return OriginFunc;
}

void __declspec(naked) InlineKiFastCallEntry1()
{
    /*  HOOKTYPE_INLINE   >=VISTA
        輸入
        eax=ServiceIndex
        edx=OriginFunc
        edi=SSDTBase
        輸出
        edx=FuncAddr  最終函數(shù)調(diào)用地址
    */
    _asm
    {
        pushf;
        pusha;
        push edi;
        push edx;
        push eax;
        call Filter;
        mov [esp+0x14],eax;//改棧中的edx
        popa;
        popf;
        mov edi,esp;
        cmp esi,MmUserProbeAddress;
        push dword ptr HookInfo1.JmpBackPoint;
        retn;//跳回JmpBackPoint
    }
}

void __declspec(naked) InlineKiFastCallEntry2()
{
    /*  HOOKTYPE_INLINE   <VISTA
        輸入
        eax=ServiceIndex
        edx=OriginFunc
        edi=SSDTBase
        輸出
        ebx=FuncAddr  最終函數(shù)調(diào)用地址
    */
    _asm
    {
        pushf;
        pusha;
        push edi;
        push edx;
        push eax;
        call Filter;
        mov [esp+0x10],eax;//改棧中的ebx
        popa;
        popf;
        mov edi,esp;
        cmp esi,MmUserProbeAddress;
        push dword ptr HookInfo1.JmpBackPoint;
        retn;
    }
}

void __declspec(naked) InlineKiFastCallEntry3()
{
    /*  HOOKTYPE_KSINLINE   <VISTA
        輸入
        eax=ServiceIndex
        edx=OriginFunc
        edi=SSDTBase
        輸出
        edx=FuncAddr  最終函數(shù)調(diào)用地址    (KiFastCallEntry后面mov ebx,edx)
    */
    _asm
    {
        pushf;
        pusha;
        push edi;
        push edx;
        push eax;
        call Filter;
        mov [esp+0x14],eax;//改棧中的edx
        popa;
        popf;
        mov edi,esp;
        test byte ptr [ebp+0x72],2;
        push dword ptr HookInfo2.JmpBackPoint;
        retn;//跳回JmpBackPoint
    }
}

void __declspec(naked) InlineKiFastCallEntry4()
{
    /*  HOOKTYPE_KSINLINE   <VISTA
        輸入
        eax=ServiceIndex
        edx=OriginFunc
        edi=SSDTBase
        輸出
        ebx=FuncAddr  最終函數(shù)調(diào)用地址
    */
    _asm
    {
        pushf;
        pusha;
        push edi;
        push edx;
        push eax;
        call Filter;
        mov [esp+0x14],eax;//改棧中的edx
        popa;
        popf;
        mov edi,esp;
        test byte ptr [ebp+0x72],2;
        push dword ptr HookInfo2.JmpBackPoint;
        retn;//跳回JmpBackPoint
    }
}

4.8 強(qiáng)制單核互斥執(zhí)行指定Procedure

struct SpinData
{
    KSPIN_LOCK SpinLock;
    ULONG SpinRefCount;
}g_Spin = {0};
KDPC Dpc[32];

void DpcRoutine(PKDPC Dpc,PVOID DeferredContext,PVOID SystemArgument1,PVOID SystemArgument2)
{
    KIRQL OldIrql;
    SpinData* spin = (SpinData*)DeferredContext;zh
    _disable();
    OldIrql = KeRaiseIrqlToDpcLevel();
    InterlockedIncrement(spin->SpinRefCount);
    KeAcquireSpinLockAtDpcLevel(spin->SpinLock);
    KeReleaseSpinLockFromDpcLevel(spin->SpinLock);
    KeLowerIrql(OldIrql);
    _enable();
}

NTSTATUS MakeJmp(ULONG* data,FARPROC addr)
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    ULONG ulCurrentCpu = 0;
    KIRQL OldIrql,NewIrql;
    KAFFINITY CpuAffinity;
    if(!addr)
        return status;
    CpuAffinity = KeQueryActiveProcessors();
    for(int i = 0;i < 32;i++)
    {
        if((CpuAffinity >> i) & 1)
            ulCurrentCpu++;
    }
    if(ulCurrentCpu == 1)//單核
    {
        _disable();
        OldIrql = KeRaiseIrqlToDpcLevel();
        status = addr(data);
        KeLowerIrql(OldIrql);
        _enable();
    }
    else//多核  將除當(dāng)前cpu以外的cpu用自旋鎖鎖住
    {
        SpinData* pSpinData = &g_Spin;
        ULONG ulNumberOfActiveCpu = 0;
        KeInitializeSpinLock(&g_Spin.SpinLock);
        for(int i = 0;i < 32;i++)
        {
            KeInitializeDpc(&Dpc[i],DpcRoutine,&pSpinData);
        }
        pSpinData->SpinRefCount = 0;
        _disable();
        NewIrql = KeAcquireSpinLock(&g_Spin.SpinLock);
        ulCurrentCpu = KeGetCurrentProcessorNumber();
        for(int i = 0;i < 32;i++)
        {
            if((CpuAffinity >> i) & 1)
                ulNumberOfActiveCpu++;
            if(i != ulCurrentCpu)
            {
                KeSetTargetProcessorDpc(Dpc[i],i);
                KeSetImportanceDpc(Dpc[i],HighImportance);
                KeInsertQueueDpc(Dpc[i],NULL,NULL);
            }
            KeInitializeDpc(&Dpc[i],DpcRoutine,&pSpinData);
        }
        //此時(shí)只有一個(gè)核在工作
        for(int i = 0;i < 16;i++)//嘗試16次
        {
            for(int count = 1000000;count > 0;count--);//延時(shí)
            if(g_Spin.SpinRefCount == ulNumberOfActiveCpu - 1)//等待DpcRoutine全部執(zhí)行到死鎖
            {
                status = addr(data);
                break;
            }
        }
        KeReleaseSpinLock(&g_Spin.SpinLock,NewIrql);//恢復(fù)多核運(yùn)行
        _enable();
    }
    return status;
}

4.9 進(jìn)行SSDT hook

??在注冊(cè)表Services\TsFltMgr thm=1的情況下浓若,或者Inline hook KiFastCallEntry失敗的情況下渺杉,會(huì)進(jìn)行SSDT表 hook

NTSTATUS BeginSSDTHook()
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    int result = -1;
    PVOID MappedAddress = NULL;
    PMDL mdl = NULL;
    if(serHookType == HOOKTYPE_INLINE || serHookType == HOOKTYPE_KSINLINE)//已成功inline hook
        return STATUS_UNSUCCESSFUL;
    serHookType = HOOKTYPE_SSDT;
    for(int i = 0;i <= APINUMBER;i++)
    {
        if(DProxyTable[i] && DProxyTable[i]->ServiceIndex != -1 && !DProxyTable[i]->IsInitialized)
        {
            if(DProxyTable[i]->ServiceTableType == SSDT)
            {
                int index = DProxyTable[i]->ServiceIndex;
                if(index != 1023 && DProxyTable[i]->ProxyFunc && SSDTBase)
                {
                    PVOID MappedAddress = NULL;
                    PMDL mdl = GetWritablePage(SSDTBase,4*SSDTLimit,&MappedAddress);
                    if(mdl)
                    {
                        DProxyTable[i]->OriginFuncAddr = ((ULONG*)SSDTBase)[index];
                        ((ULONG*)MappedAddress)[index] = DProxyTable[i]->ProxyFunc;
                        MmUnlockPages(mdl);
                        IoFreeMdl(mdl);
                        result = index;
                    }
                }
            }
            else if(DProxyTable[i]->ServiceTableType == SSSDT)
            {
                int index = DProxyTable[i]->ServiceIndex;
                if(index != 1023 && DProxyTable[i]->ProxyFunc && ShadowSSDTBase)
                {
                    HANDLE CurProcessId = PsGetCurrentProcessId();
                    HANDLE SmssProcessId = GetProcessIdByName(L"smss.exe");
                    if(!dwcsrssId)//如果沒(méi)有獲取到csrss.exe的id
                    {
                        if(CurProcessId == SmssProcessId)//使用smss.exe的SSSDT
                        {
                            mdl = GetWritablePage(ShadowSSDTBase,4*ShadowSSDTLimit,&MappedAddress);
                            if(mdl)
                            {
                                DProxyTable[i]->OriginFuncAddr = ((ULONG*)ShadowSSDTBase)[index];
                                ((ULONG*)MappedAddress)[index] = DProxyTable[i]->ProxyFunc;
                                MmUnlockPages(mdl);
                                IoFreeMdl(mdl);
                                result = index;
                            }
                        }
                    }
                    else
                    {//附加到csrss.exe
                        PVOID attachobj = AttachDriverToProcess(dwcsrssId);
                        if(attachobj)
                        {
                            mdl = GetWritablePage(ShadowSSDTBase,4*ShadowSSDTLimit,&MappedAddress);
                            if(mdl)
                            {
                                DProxyTable[i]->OriginFuncAddr = ((ULONG*)ShadowSSDTBase)[index];
                                ((ULONG*)MappedAddress)[index] = DProxyTable[i]->ProxyFunc;
                                MmUnlockPages(mdl);
                                IoFreeMdl(mdl);
                                result = index;
                            }
                            DetachDriverFromProcess(attachobj);
                        }
                    }
                }   
            }
            if(result != -1)
                DProxyTable[i]->IsInitialized = TRUE;
        }
    }
    return STATUS_SUCCESS;
}

struct AttachData
{
    KAPC_STATE ApcState;
    PVOID Process;
};

PVOID AttachDriverToProcess(HANDLE ProcessId)
{
    PVOID Process = NULL;
    AttachData* Buffer = NULL;
    if(ProcessId == PsGetCurrentProcessId())
        return 0xEEEEDDDD;//自身標(biāo)識(shí)
    if(ProcessId && NT_SUCCESS(PsLookupProcessByProcessId(ProcessId,&Process)))
    {
        Buffer = (AttachData*)ExAllocatePool(PagedPool,sizeof(AttachData));
        if(!Buffer)
        {
            ObDereferenceObject(Process);
            return NULL;
        }
        Buffer->Process = Process;
        KeStackAttachProcess(Process,&Buffer->ApcState)
    }
}

NTSTATUS DetachDriverFromProcess(PVOID Buffer)
{
    if(Buffer && (ULONG)Buffer != 0xEEEEDDDD)
    {
        AttachData* data = (AttachData*)Buffer;
        KeUnstackDetachProcess(&data->ApcState);
        ObDereferenceObject(data->Process);
        ExFreePool(Buffer);
    }
}

4.10 對(duì)重要回調(diào)(進(jìn)程回調(diào)、線程回調(diào)挪钓、映像加載回調(diào))的掛鉤

/*
    Sproxy Index:
    普通api使用index 0-0x33 0x37-0x48 0x4A-0x69
    52    CreateNotifyRoutine
    53    ThreadNofify
    54    ImageNotify
    73    CreateNotifyRoutine2
*/
enum
{
    INDEX_KECALLBACK = 51,
    INDEX_PROCESS = 52,
    INDEX_THREAD = 53,
    INDEX_IMAGE = 54,
    INDEX_PROCESSEX = 73,
};

NTSTATUS HookImportantNotify()
{
    if(!DProxyTable[INDEX_PROCESS])
    {
        DProxy* Proxydata = (DProxy*)ExAllocatePool(NonPagedPool,sizeof(DProxy));
        if(Proxydata)
        {
            Proxydata->IsInitialized = FALSE;
            Proxydata->ApiName = "ProcessNotify";
            Proxydata->TableIndex = INDEX_PROCESS;
            Proxydata->ProxyFuncAddr = CreateNotifyRoutine1;
            Proxydata->ServiceIndex = -1;
            KeInitializeEvent(&Proxydata->Lock,SynchronizationEvent,FALSE);
            DProxyTable[INDEX_PROCESS] = Proxydata;
        }
    }
    if(DProxyTable[INDEX_PROCESS] && !DProxyTable[INDEX_PROCESS]->IsInitialized)
    {
        DProxyTable[INDEX_PROCESS]->ServiceTableType = CALLBACK;
        if(NT_SUCCESS(PsSetCreateProcessNotifyRoutine(CreateProcessNotify,FALSE)))
            DProxyTable[INDEX_PROCESS]->IsInitialized = TRUE;
    }
    if(!DProxyTable[INDEX_PROCESSEX])
    {
        DProxy* Proxydata = (DProxy*)ExAllocatePool(NonPagedPool,sizeof(DProxy));
        if(Proxydata)
        {
            Proxydata->IsInitialized = FALSE;
            Proxydata->ApiName = "ProcessNotifyEx";
            Proxydata->TableIndex = INDEX_PROCESSEX;
            Proxydata->ProxyFuncAddr = CreateNotifyRoutine1Ex;
            Proxydata->ServiceIndex = -1;
            KeInitializeEvent(&Proxydata->Lock,SynchronizationEvent,FALSE);
            DProxyTable[INDEX_PROCESSEX] = Proxydata;
        }
    }
    if(DProxyTable[INDEX_PROCESSEX] && !DProxyTable[INDEX_PROCESSEX]->IsInitialized)
    {
        DProxyTable[INDEX_PROCESSEX]->ServiceTableType = CALLBACK;
        if(NT_SUCCESS(PsSetCreateProcessNotifyRoutineEx(CreateProcessNotifyEx,FALSE)))
            DProxyTable[INDEX_PROCESSEX]->IsInitialized = TRUE;
    }
    if(!DProxyTable[INDEX_THREAD])
    {
        DProxy* Proxydata = (DProxy*)ExAllocatePool(NonPagedPool,sizeof(DProxy));
        if(Proxydata)
        {
            Proxydata->IsInitialized = FALSE;
            Proxydata->ApiName = "ThreadNotify";
            Proxydata->TableIndex = INDEX_THREAD;
            Proxydata->ProxyFuncAddr = CreateThreadNotify;
            Proxydata->ServiceIndex = -1;
            KeInitializeEvent(&Proxydata->Lock,SynchronizationEvent,FALSE);
            DProxyTable[INDEX_THREAD] = Proxydata;
        }
    }
    if(DProxyTable[INDEX_THREAD] && !DProxyTable[INDEX_THREAD]->IsInitialized)
    {
        DProxyTable[INDEX_THREAD]->ServiceTableType = CALLBACK;
        if(NT_SUCCESS(PsSetCreateThreadNotifyRoutine(CreateThreadNotify,FALSE)))
            DProxyTable[INDEX_THREAD]->IsInitialized = TRUE;
    }
    if(!DProxyTable[INDEX_IMAGE])
    {
        DProxy* Proxydata = (DProxy*)ExAllocatePool(NonPagedPool,sizeof(DProxy));
        if(Proxydata)
        {
            Proxydata->IsInitialized = FALSE;
            Proxydata->ApiName = "ImageNotify";
            Proxydata->TableIndex = INDEX_IMAGE;
            Proxydata->ProxyFuncAddr = LoadImageNotify;
            Proxydata->ServiceIndex = -1;
            KeInitializeEvent(&Proxydata->Lock,SynchronizationEvent,FALSE);
            DProxyTable[INDEX_IMAGE] = Proxydata;
        }
    }
    if(DProxyTable[INDEX_IMAGE] && !DProxyTable[INDEX_IMAGE]->IsInitialized)
    {
        DProxyTable[INDEX_IMAGE]->ServiceTableType = CALLBACK;
        if(NT_SUCCESS(PsSetLoadImageNotifyRoutine(LoadImageNotify,FALSE)))
            DProxyTable[INDEX_IMAGE]->IsInitialized = TRUE;
    }
}

4.11 Hook KeUserModeCallback

NTSTATUS HookKeUserModeCallback()
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    if(!Win32kBase)
        return status;
    OBJECT_ATTRIBUTES Oa;
    IO_STATUS_BLOCK IoStatusBlock;
    HANDLE SectionHandle = NULL;
    ULONG ViewSize = 0;
    HANDLE FileHandle = NULL;
    PVOID BaseAddress = 0x5000000;
    UNICODE_STRING UKeUserModeCallback;
    if(!DProxyTable[INDEX_KECALLBACK])
    {
        DProxy* Proxydata = (DProxy*)ExAllocatePool(NonPagedPool,sizeof(DProxy));
        if(Proxydata)
        {
            Proxydata->IsInitialized = FALSE;
            Proxydata->ApiName = "ImageNotify";
            Proxydata->TableIndex = INDEX_KECALLBACK;
            Proxydata->ProxyFuncAddr = ProxyKeUserModeCallback;
            Proxydata->ServiceIndex = -1;
            KeInitializeEvent(&Proxydata->Lock,SynchronizationEvent,FALSE);
            DProxyTable[INDEX_KECALLBACK] = Proxydata;
        }
    }
    RtlInitUnicodeString(&UKeUserModeCallback,L"\\SystemRoot\\System32\\Win32k.sys");
    InitializeObjectAttributes(&Oa,L"KeUserModeCallback",OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,NULL,NULL);
    status = ZwOpenFile(&FileHandle,GENERIC_READ,&Oa,&IoStatusBlock,FILE_SHARE_READ,FILE_SYNCHRONOUS_IO_NONALERT);
    if(NT_SUCCESS(status))
    {
        Oa.ObjectName = NULL;
        status = ZwCreateSection(&SectionHandle,SECTION_MAP_EXECUTE,&Oa,NULL,PAGE_WRITECOPY,SEC_IMAGE);
        if(NT_SUCCESS(status))
        {
            status = ZwMapViewOfSection(&SectionHandle,NtCurrentProcess(),&BaseAddress,0,0,NULL,&ViewSize,ViewUnmap,0,PAGE_EXECUTE);
            if(!NT_SUCCESS(status))
            {
                BaseAddress = NULL;
                ZwMapViewOfSection(&SectionHandle,NtCurrentProcess(),&BaseAddress,0,0,NULL,&ViewSize,ViewUnmap,0,PAGE_EXECUTE);
            }
        }
    }
    if(BaseAddress)
    {
        if(!DProxyTable[INDEX_KECALLBACK]->IsInitialized)
        {
            ULONG IatOffset = GetProcOffsetFromIat(BaseAddress);
            DProxyTable[INDEX_KECALLBACK]->OriginFuncAddr = ExchangeMem(IatOffset,Win32kBase,ProxyKeUserModeCallback);
            if(DProxyTable[INDEX_KECALLBACK]->OriginFuncAddr)
            {
                DProxyTable[INDEX_KECALLBACK]->IsInitialized;
                status = STATUS_SUCCESS;
            }
        }
        ZwUnmapViewOfSection(NtCurrentProcess(),BaseAddress);
    }
    return status;
}

4.12 交換內(nèi)存

ULONG ExchangeMem(ULONG Offset,ULONG BaseAddress,ULONG NewValue)
{//替換基址BaseAddress 偏移Offset 處的ULONG數(shù)據(jù)是越,返回原始數(shù)據(jù)
    HANDLE CurProcessId = PsGetCurrentProcessId();
    HANDLE SmssProcessId = GetProcessIdByName(L"smss.exe");
    ULONG OriginValue = 0;
    PMDL mdl = NULL;
    if(!dwcsrssId)//如果沒(méi)有獲取到csrss.exe的id
    {
        if(CurProcessId == SmssProcessId)//使用smss.exe的SSSDT
        {
            mdl = GetWritablePage(BaseAddress+Offset,16,&MappedAddress);
            if(mdl)
            {
                OriginValue = InterlockedExchange(MappedAddress,NewValue);
                MmUnlockPages(mdl);
                IoFreeMdl(mdl);
            }
        }
    }
    else
    {//附加到csrss.exe
        PVOID attachobj = AttachDriverToProcess(dwcsrssId);
        if(attachobj)
        {
            mdl = GetWritablePage(BaseAddress+Offset,4,&MappedAddress);
            if(mdl)
            {
                OriginValue = InterlockedExchange(MappedAddress,NewValue);
                MmUnlockPages(mdl);
                IoFreeMdl(mdl);
            }
            DetachDriverFromProcess(attachobj);
        }
    }
    return OriginValue;
}

4.13 獲取函數(shù)Iat偏移

ULONG GetProcOffsetFromIat(PVOID ImageBase,PCHAR ModuleName,PCHAR ApiName)
{//ImageBase當(dāng)前進(jìn)程映像基址  ModuleName導(dǎo)入模塊映像基址  ApiName導(dǎo)入函數(shù)名
    ANSI_STRING AApiName;
    UNICODE_STRING UApiname;
    PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
    ULONG ObjProcAddr;
    ULONG Offset = 0;
    PCHAR ImportedName;
    PIMAGE_THUNK_DATA FunctionNameList;
    RtlInitAnsiString(&AApiName,ApiName);
    if(!NT_SUCCESS(RtlAnsiStringToUnicodeString(&UApiname,&AApiName,TRUE)))
        return 0;
    ObjProcAddr = MmGetSystemRoutineAddress(&UApiname);
    RtlFreeUnicodeString(&UApiname);
    ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(ImageBase,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT);
    if(!ImportModuleDirectory)
        return 0;
    for (;(ImportModuleDirectory->Name != 0) && (ImportModuleDirectory->FirstThunk != 0);ImportModuleDirectory++)
    {
        ImportedName = (PCHAR)ImageBase + ImportModuleDirectory->Name;
        if(!stricmp(ModuleName,ImportedName))
        {
            FunctionNameList = (PIMAGE_THUNK_DATA)((UCHAR*)ImageBase+ImportModuleDirectory->FirstThunk);
            while(*FunctionNameList != 0)
            {
                if((*FunctionNameList) & 0x80000000)
                {
                    if(FunctionNameList->u1.Function == ObjProcAddr)
                        return (UCHAR*)FunctionNameList - (UCHAR*)ImageBase;
                }
                else
                {
                    IMAGE_IMPORT_BY_NAME *pe_name = (IMAGE_IMPORT_BY_NAME*)((PCHAR)ImageBase + *FunctionNameList);
                    if(pe_name->Name[0] == 'K' && !stricmp(pe_name->Name,"KeUserModeCallback"))
                        return (UCHAR*)FunctionNameList - (UCHAR*)ImageBase;
                }
                FunctionNameList++;
            }
        }
    }
    return 0;
}

4.14 另一種方式獲取ShadowSSDT信息

??當(dāng)常規(guī)方式獲取SSSDT失敗時(shí),會(huì)臨時(shí)設(shè)置ZwSetSystemInformation的過(guò)濾函數(shù)捕獲系統(tǒng)設(shè)置服務(wù)表(SYSTEM_INFORMATION_CLASS =SystemExtendServiceTableInformation)碌上,

void TryAnotherWayToGetShadowSSDT()
{
    AddPrevFilter(EZwSetSystemInformation,ZwSetSystemInformationFilter1,0,0,NULL);
}

ULONG OldKeAddSystemServiceTable;

ULONG __stdcall ZwSetSystemInformationFilter1(FilterPacket* Packet)
{//改EAT以獲取SSSDT
    if(!ShadowSSDTBase && Packet->Params[0] == SystemExtendServiceTableInformation && !OldKeAddSystemServiceTable)
    {
        OldKeAddSystemServiceTable = ExchangeEat(NtosBase,NewKeAddSystemServiceTable);
        if(OldKeAddSystemServiceTable)
        {
            Packet->TagSlot[Packet->CurrentSlot] = 0xABCDEEEE;//用于標(biāo)記
            Packet->PostFilterSlot[Packet->CurrentSlot] = ZwSetSystemInformationFilter2;
            Packet->UsedSlotCount++;
        }
    }
    return SYSMON_PASSTONEXT;
}

ULONG __stdcall ZwSetSystemInformationFilter2(FilterPacket* Packet)
{//獲取之后恢復(fù)EAT
    if(Packet->TagSlot[Packet->CurrentSlot] == 0xABCDEEEE)//檢查標(biāo)記
    {
        if(serHookType != 1 && serHookType != 3)//是否SSDT型Hook
        {
            BeginSSDTHook();
        }
    }
    return SYSMON_PASSTONEXT;
}

BOOLEAN __stdcall KeAddSystemServiceTable(PULONG_PTR Base,PULONG Count,ULONG Limit,PUCHAR Number,ULONG Index)
{//獲取SSSDT
    RTL_PROCESS_MODULE_INFORMATION ProcessInfo;
    RtlZeroMemory(&ProcessInfo,sizeof(ProcessInfo));
    if(!ShadowSSDTBase && GetProcessInfoByFileName("win32k.sys",&ProcessInfo) &&
        Base >= ProcessInfo.ImageBase && Base <= ProcessInfo.ImageBase+ProcessInfo.ImageSize)
    {
        Win32kBase = ProcessInfo.ImageBase;
        Win32kSize = ProcessInfo.ImageSize;
        ShadowSSDTBase = Base;
        ShadowSSDTLimit = Limit;
        ExchangeEat(NtosBase,OldKeAddSystemServiceTable);
    }
    return  OldKeAddSystemServiceTable(Base,Count,Limit,Number,Index);
}

ULONG ExchangeEat(ULONG ImageBase,ULONG NewFunc)
{
    PVOID Address = MiLocateExportName(ImageBase,"KeAddSystemServiceTable");
    if(Address)
    {
        return ExchangeMem(0,Address,NewFunc);
    }
    return 0;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末英妓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子绍赛,更是在濱河造成了極大的恐慌蔓纠,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吗蚌,死亡現(xiàn)場(chǎng)離奇詭異腿倚,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)蚯妇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門敷燎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人箩言,你說(shuō)我怎么就攤上這事硬贯。” “怎么了陨收?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵饭豹,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我务漩,道長(zhǎng)拄衰,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任饵骨,我火速辦了婚禮翘悉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘居触。我一直安慰自己妖混,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布轮洋。 她就那樣靜靜地躺著制市,像睡著了一般。 火紅的嫁衣襯著肌膚如雪砖瞧。 梳的紋絲不亂的頭發(fā)上息堂,一...
    開(kāi)封第一講書(shū)人閱讀 51,598評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼荣堰。 笑死床未,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的振坚。 我是一名探鬼主播薇搁,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼渡八!你這毒婦竟也來(lái)了啃洋?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤屎鳍,失蹤者是張志新(化名)和其女友劉穎宏娄,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體逮壁,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡孵坚,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了窥淆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片卖宠。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖忧饭,靈堂內(nèi)的尸體忽然破棺而出扛伍,到底是詐尸還是另有隱情,我是刑警寧澤词裤,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布刺洒,位于F島的核電站,受9級(jí)特大地震影響亚斋,放射性物質(zhì)發(fā)生泄漏作媚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一帅刊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧漂问,春花似錦赖瞒、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至磷仰,卻和暖如春袍嬉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工伺通, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留箍土,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓罐监,卻偏偏與公主長(zhǎng)得像吴藻,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子弓柱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容