現(xiàn)在根據(jù)實(shí)例來配合,現(xiàn)在要得到NtOpenProcess的內(nèi)存地址
用 winDebug 得到 SSDT這個表的首地址是 0x80505480

進(jìn)入這個地址看看里面的內(nèi)容是什么

0: kd> dd poi[KeServiceDescriptorTable]
地址 0 1 2 3
80505480 805a565c 805f243e 805f5c74 805f2470
4 5 6 7
80505490 805f5cae 805f24a6 805f5cf2 805f5d36
8 9 10 11
805054a0 80616d1e 80617a60 805ed83c 805ed494
805054b0 805d5bae 805d5b5e 80617344 805b6fe2
805054c0 80616960 805a9ae6 805b15f6 805d7672
805054d0 8050289c 80617a52 80577b0a 80539c34
805054e0 8060ff2e 805bd55c 805f61ae 80624cf0
805054f0 805fa6c2 805a5d4a 80624f44 805a55fc
看到 0x80505480 這個地址存的第0個地址是 0x805A565C
用 Kerne Detective 這個工具看看這個是什么API

第0個是NtAcceptConnectPort 這個API
可以看到 WinDebug 得到的數(shù)據(jù) 和 KD 一樣
用工具可以很容易找到SSDT的基地址 和 索引號以及NtAPI的內(nèi)存地址
用編程實(shí)現(xiàn) (精華):
要檢查 SSDT 指定的NtAPI有沒有被HOOK 就要先 獲取到現(xiàn)在的NtAPI地址、獲取原來的NtAPI的內(nèi)存地址,然后將兩個地址相比較即可。
獲取現(xiàn)在NtAPI的內(nèi)存地址的具體流程
首先應(yīng)該得到SSDT的首地址 即 基址
然后將ServiceTableBase 的內(nèi)存首地址+索引號*4 得到存儲著相應(yīng)索引號內(nèi)核NtAPI現(xiàn)在的內(nèi)存地址的地址(ServiceTableBase的偏移地址)
讀取該地址得到現(xiàn)在的NtAPI內(nèi)存地址
獲取原來的NtAPI的內(nèi)存地址的具體流程
通過 MmGetSystemRoutineAddress 可以得到原來的NtAPI 地址
主要是 獲取現(xiàn)在的NtAPI比較費(fèi)心思去理解,只要理解了這個流程,也就理解了SSDT表的結(jié)構(gòu)了。
看看下面的代碼以及注釋就能理解SSDT表的結(jié)構(gòu)了
左邊是用KD工具得到 NOtOpenProcess 內(nèi)存地址 右邊是用WinDebug得到

下圖是通過編程得到 NtOpenProcess 內(nèi)存地址:

代碼:
ypedef struct _ServiceDescriptorTable {
PVOID ServiceTableBase; //System Service Dispatch Table 的基地址
PVOID ServiceCounterTable;
//包含著SSDT 中每個服務(wù)被調(diào)用次數(shù)的計數(shù)器。這個計數(shù)器一般由sysenter 更新。
unsigned int NumberOfServices;//由ServiceTableBase 描述的服務(wù)的數(shù)目。
PVOID ParamTableBase; //包含每個系統(tǒng)服務(wù)參數(shù)字節(jié)數(shù)表的基地址-系統(tǒng)服務(wù)參數(shù)表
}*PServiceDescriptorTable;
extern PServiceDescriptorTable KeServiceDescriptorTable;
ULONG GetNt_CurAddr() //獲取當(dāng)前SSDT_NtOpenProcess的現(xiàn)在地址
{
LONG *SSDT_Adr,SSDT_NtOpenProcess_Cur_Addr,t_addr;
KdPrint(("驅(qū)動成功被加載中.............................\n\n"));
KdPrint(("********************** 計算現(xiàn)在的地址**********************\n\n"));
//讀取SSDT表中索引值為x7A的函數(shù)
//poi(poi(KeServiceDescriptorTable)+0x7a*4)
t_addr=(LONG)KeServiceDescriptorTable->ServiceTableBase; // 得到ServiceTableBase 的地址
KdPrint(("[得到ServiceTableBase 的基址] \n當(dāng)前ServiceTableBase地址為0x%X \n\n",t_addr));
// 將該地址里面的內(nèi)容+ 索引號* 4 就能得到相應(yīng)索引號內(nèi)核NtAPI現(xiàn)在的內(nèi)存地址0x7A為NtOpenProcess在SSDT的索引
SSDT_Adr=(PLONG)(t_addr+0x7A*4);
KdPrint(("[將ServiceTableBase 的內(nèi)存首地址+索引號*4 \n得到存儲著相應(yīng)索引號內(nèi)核NtAPI現(xiàn)在的內(nèi)存地址的地址(ServiceTableBase的偏移地址)]\n"));
KdPrint(("SSDT首地址0x%X + 0x7A * 4= 0x%X 這個地址0x%X 存儲著索引號為0x7A 的NtOpenProcess內(nèi)存地址\n\n", t_addr, SSDT_Adr, SSDT_Adr));
SSDT_NtOpenProcess_Cur_Addr=*SSDT_Adr;
KdPrint(("[讀取0x%X 得到NtOpenProcess 函數(shù)現(xiàn)在的內(nèi)存地址] 現(xiàn)在的NtOpenProcess 內(nèi)存地址為0x%X \n\n",SSDT_Adr, SSDT_NtOpenProcess_Cur_Addr));
KdPrint(("********************** 計算完畢***************************\n\n"));
// 匯編
/*
__asm
{ int 3
push ebx
push eax
mov ebx,KeServiceDescriptorTable
mov ebx,[ebx] //表的基地址 取 KeServiceDescriptorTable 的地址 t_addr=(LONG)KeServiceDescriptorTable->ServiceTableBase;
mov eax,0x7a
shl eax,2//0x7A*4 //imul eax,eax,4//shl eax,2
add ebx,eax//[KeServiceDescriptorTable]+0x7A*4
mov ebx,[ebx] // SSDT_NtOpenProcess_Cur_Addr=*SSDT_Adr; // 取出該地址中存儲的NtOpenProcess 函數(shù)的地址
mov SSDT_NtOpenProcess_Cur_Addr,ebx
pop eax
pop ebx
}
*/
return SSDT_NtOpenProcess_Cur_Addr; // 將獲得的地址返回
}
ULONG GetNt_OldAddr()
{
UNICODE_STRING Old_NtOpenProcess;
ULONG Old_Addr;
KdPrint(("********************** 計算原來的地址**********************\n\n"));
RtlInitUnicodeString(&Old_NtOpenProcess,L"NtOpenProcess");
Old_Addr=(ULONG)MmGetSystemRoutineAddress(&Old_NtOpenProcess);//取得NtOpenProcess的地址
KdPrint(("用MmGetSystemRoutineAddress 取得原來NtOpenProcess 的地址為0x%X\n\n",Old_Addr));
KdPrint(("********************** 計算完畢****************************\n\n"));
return Old_Addr;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING B) //TYPEDEF LONG NTSTATUS
{
ULONG cur,old;
cur=GetNt_CurAddr();// 得到現(xiàn)在的NtAPI 地址
old=GetNt_OldAddr();// 得到原來的NtAPI 地址
if (cur!=old)
KdPrint(("NtOpenProcess被HOOK了"));
else
KdPrint(("NtOpenProcess 沒有被HOOK"));
}