windows:根據特征碼查找內核任意函數


在windows平台做逆向、外掛等,經常需要調用很多未導出的內核函數,怎么方便、快速查找了?可以先用IDA等工具查看硬編碼,再根據硬編碼定位到需要調用的函數。整個思路大致如下:

1、先查找目標模塊

   遍歷模塊的方式有多種。既然通過驅動在內核編程,這里選擇遍歷driverObject的DriverSection字段來遍歷內核所有模塊,核心代碼如下:

 1 /*
 2   可以用來動態查找內核模塊的基址,后續用於:
 3   1、PTE\PDE等base計算
 4   2、其他函數、變量精確位置的計算(IDA靜態分析只能查到偏移)
 5 */
 6 PVOID FindMould(PDRIVER_OBJECT pDriverObject, PWCHAR moudName, PULONG pSize)
 7 {
 8     // 從PDRIVER_OBJECT獲取DriverSection,便可獲得驅動模塊鏈表
 9     PLDR_DATA_TABLE_ENTRY pDriverData = (PLDR_DATA_TABLE_ENTRY)pDriverObject->DriverSection;
10     // 開始遍歷雙向鏈表
11     PLDR_DATA_TABLE_ENTRY pFirstDriverData = pDriverData;
12     do
13     {
14         if ((0 < pDriverData->BaseDllName.Length) ||
15             (0 < pDriverData->FullDllName.Length))
16         {
17             // 顯示
18             DbgPrint("BaseDllName=%ws,\tDllBase=0x%p,\tSizeOfImage=0x%X,\tFullDllName=%ws\n",
19                 pDriverData->BaseDllName.Buffer, pDriverData->DllBase,
20                 pDriverData->SizeOfImage, pDriverData->FullDllName.Buffer);
21             //BaseDllName.Buffer是PWCH,也就是寬字符串,所以自己定義的moudName也要是PWCHAR類型
22             if (!_stricmp(moudName, (PCHAR)pDriverData->BaseDllName.Buffer))
23             {
24                 DbgPrint("find target : BaseDllName=%ws,\tDllBase=0x%p,\tSizeOfImage=0x%X,\tFullDllName=%ws\n",
25                     pDriverData->BaseDllName.Buffer, pDriverData->DllBase,
26                     pDriverData->SizeOfImage, pDriverData->FullDllName.Buffer);
27                 *pSize = pDriverData->SizeOfImage;
28                 return pDriverData->DllBase;
29             }
30 
31         }
32         // 下一個
33         pDriverData = (PLDR_DATA_TABLE_ENTRY)pDriverData->InLoadOrderLinks.Flink;
34 
35     } while (pFirstDriverData != pDriverData);
36 
37     return NULL;
38 }

  傳入driverObject、模塊名稱,得到模塊基址(返回值)和模塊長度(參數);

2、得到模塊基址后,再進一步根據特征碼查找目標函數:

 1 PVOID FindFun(PVOID pSearchBeginAddr, ULONG ulSearchLength, PUCHAR pSpecialCode, ULONG ulSpecialCodeLength)
 2 {
 3     PVOID pDestAddr = NULL;
 4     PUCHAR pBeginAddr = (PUCHAR)pSearchBeginAddr;
 5     PUCHAR pEndAddr = pBeginAddr + ulSearchLength;
 6     PUCHAR i = NULL;
 7     ULONG j = 0;
 8 
 9     for (i = pBeginAddr; i <= pEndAddr; i++)
10     {
11         // 遍歷特征碼
12         for (j = 0; j < ulSpecialCodeLength; j++)
13         {
14             // 判斷地址是否有效  ntoskrnl.exe有時地址無效,藍屏報錯:PAGE FAULED IN NONPAGED AREA
15             if (FALSE == MmIsAddressValid((PVOID)(i + j)))
16             {
17                 break;
18             }
19             // 匹配特征碼
20             if (*(PUCHAR)(i + j) != pSpecialCode[j])
21             {
22                 break;
23             }
24         }
25         // 匹配成功
26         if (j >= ulSpecialCodeLength)
27         {
28             pDestAddr = (PVOID)i;
29             break;
30         }
31     }
32 
33     return pDestAddr;
34 }

  這里特征碼搜索可以繼續改進,比如用正則做模糊匹配~~~

3、用法舉例:強行殺死線程時,需要調用 PspTerminateThreadByPointer 函數,但此函數並未導出,可以通過IDA查看匯編代碼,也可以在windbg通過U PspTerminateThreadByPointer,如下:

kd> u nt!PspTerminateThreadByPointer 

nt!PspTerminateThreadByPointer:

fffff803`d01c6210 48895c2408      mov     qword ptr [rsp+8],rbx

fffff803`d01c6215 48896c2410      mov     qword ptr [rsp+10h],rbp

fffff803`d01c621a 4889742418      mov     qword ptr [rsp+18h],rsi

fffff803`d01c621f 57              push    rdi

fffff803`d01c6220 4883ec30        sub     rsp,30h

fffff803`d01c6224 8b81d0060000    mov     eax,dword ptr [rcx+6D0h]

fffff803`d01c622a 418ae8          mov     bpl,r8b

fffff803`d01c622d 488bb920020000  mov     rdi,qword ptr [rcx+220h]

由於大多數函數剛開始都是初始化堆棧代碼,這里特征碼重合度較高,為了避免找到其他函數,建議從稍微靠后幾行代碼處提取特征碼,比如這里從第7行開始提取 418ae8488bb920020000 10個字節,找到后再減去26字節就回到了PspTerminateThreadByPointer入口;

 1 NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
 2 {
 3     DbgPrint("Enter DriverEntry\n");
 4 
 5     NTSTATUS status = STATUS_SUCCESS;
 6     pDriverObject->DriverUnload = DriverUnload;
 7     for (ULONG i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
 8     {
 9         pDriverObject->MajorFunction[i] = DriverDefaultHandle;
10     }
11 
12     ULONG mouldSize = 0;
13     PWCHAR mouldName = L"ntkrnlmp.exe";
14     PVOID mouldBase = FindMould(pDriverObject, mouldName, &mouldSize);
15 
16
17     DbgPrint("mould name = %ws ;   mould base = 0x%p;   mould size = 0x%X\n", mouldName, mouldBase, mouldSize);
18 
19     UCHAR pSpecialCode[256] = { 0 };
20     /*418ae8488bb920020000*/
21     pSpecialCode[0] = 0x41;
22     pSpecialCode[1] = 0x8a;
23     pSpecialCode[2] = 0xe8;
24     pSpecialCode[3] = 0x48;
25     pSpecialCode[4] = 0x8b;
26     pSpecialCode[5] = 0xb9;
27     pSpecialCode[6] = 0x20;
28     pSpecialCode[7] = 0x02;
29     pSpecialCode[8] = 0x00;
30     pSpecialCode[9] = 0x00;
31 
32     PVOID FunAddress = FindFun(mouldBase, mouldSize, pSpecialCode, 4);
33     DbgPrint("Finally function address = 0x%p;\n", FunAddress-26);
34 
35     return status;
36 }

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM