两种方法获取shadow ssdt

  1. ULONG   
  2. GetShadowSsdtCurrentAddresses(  
  3.     PSSDT_ADDRESS   AddressInfo,   
  4.     PULONG          Length  
  5.     )  
  6. {  
  7.     PSYSTEM_SERVICE_TABLE KeServiceDescriptorTableShadow = NULL;  
  8.     ULONG NumberOfService = 0;  
  9.     ULONG ServiceId = 0;  
  10.     PKAPC_STATE ApcState;  
  11.     ULONG i;  
  12.       
  13.     if (AddressInfo == NULL || Length == NULL)  
  14.     {  
  15.         KdPrint(("[GetShadowSsdtCurrentAddresses] 输入参数无效"));  
  16.         return 0;  
  17.     }  
  18.   
  19.     //KdPrint(("pid = %d", PsGetCurrentProcessId()));  
  20.     ServiceId = (ULONG)PsGetCurrentProcessId();  
  21.   
  22.     if (!g_CsrssProcess) {  
  23.         PsLookupProcessByProcessId((PVOID)ScPsGetCsrssProcessId(), &g_CsrssProcess);  
  24.     }  
  25.   
  26.     KeServiceDescriptorTableShadow = GetKeServiceDescriptorTableShadow();  
  27.   
  28.     if (KeServiceDescriptorTableShadow == NULL)    
  29.     {  
  30.         KdPrint(("[GetShadowSsdtCurrentAddresses] GetKeServiceDescriptorTableShadow failed"));  
  31.         return 0;  
  32.     }  
  33.   
  34.     NumberOfService = KeServiceDescriptorTableShadow->NumberOfService;  
  35.     if (Length[0] < NumberOfService * sizeof(SSDT_ADDRESS))  
  36.     {  
  37.         Length[0] = NumberOfService * sizeof(SSDT_ADDRESS);  
  38.         return 0;  
  39.     }  
  40.   
  41.     ApcState = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC_STATE), MEM_TAG);  
  42.     KeStackAttachProcess((PRKPROCESS)g_CsrssProcess, ApcState);  
  43.   
  44.     for (ServiceId = 0; ServiceId < NumberOfService; ServiceId ++)  
  45.     {  
  46.         AddressInfo[ServiceId].FunAddress = (ULONG)  
  47.             KeServiceDescriptorTableShadow->ServiceTableBase[ServiceId];  
  48.         AddressInfo[ServiceId].nIndex = ServiceId;  
  49.     }  
  50.   
  51.     KeUnstackDetachProcess(ApcState);  
  52.     ExFreePool(ApcState);  
  53.   
  54.     Length[0] = NumberOfService * sizeof(SSDT_ADDRESS);  
  55.     return NumberOfService;  
  56. }  
  57.   
  58. ///  
  59. //  
  60. //  功能实现:枚举当前Shadow SSDT 表函数地址  
  61. //  输入参数:void  
  62. //  输出参数:返回Shadow ssdt table  
  63. //  
  64. ///  
  65. PSYSTEM_SERVICE_TABLE   
  66. GetKeServiceDescriptorTableShadow(VOID)  
  67. {  
  68.     PSYSTEM_SERVICE_TABLE ShadowTable = NULL;  
  69.     ULONG   ServiceTableAddress = 0;  
  70.     PUCHAR  cPtr = NULL;   
  71.   
  72.     for (cPtr = (PUCHAR)KeAddSystemServiceTable;  
  73.          cPtr < (PUCHAR)KeAddSystemServiceTable + PAGE_SIZE;  
  74.          cPtr += 1 )  
  75.     {  
  76.         if (!MmIsAddressValid(cPtr))  continue;  
  77.   
  78.         ServiceTableAddress = *(PULONG)cPtr;  
  79.         if (!MmIsAddressValid((PVOID)ServiceTableAddress)) continue;  
  80.   
  81.         if (memcmp((PVOID)ServiceTableAddress, &KeServiceDescriptorTable, 16) == 0)  
  82.         {  
  83.             if ((PVOID)ServiceTableAddress == &KeServiceDescriptorTable) continue;  
  84.             ShadowTable = (PSYSTEM_SERVICE_TABLE)ServiceTableAddress;  
  85.             ShadowTable ++;  
  86.             return ShadowTable;  
  87.         }  
  88.     }  
  89.     return NULL;  
  90. }  
  91. //  
  92. // 方法2,通过硬编码实现,不通用  
  93. //   
  94. PSYSTEM_SERVICE_TABLE   
  95. GetKeServiceDescriptorTableShadow_2(VOID)  
  96. /*++ 
  97.     KeAddSystemServiceTable函数
  98.     805ba5a3 8d8840a65580    lea    ecx,nt!KeServiceDescriptorTableShadow (8055a640)[eax] 
  99.     805ba5a9 833900          cmp    dword ptr [ecx],0 
  100. --*/  
  101. {  
  102.     PSYSTEM_SERVICE_TABLE ShadowTable;  
  103.     ULONG   ServiceTableAddress;  
  104.     PUCHAR  cPtr, pOpcode;  
  105.     ULONG   Length = 0;  
  106.   
  107.     for (cPtr = (PUCHAR)KeAddSystemServiceTable;  
  108.          cPtr < (PUCHAR)KeAddSystemServiceTable + PAGE_SIZE;  
  109.          cPtr += Length )  
  110.     {  
  111.         if (!MmIsAddressValid(cPtr))  return NULL;  
  112.   
  113.         Length = SizeOfCode(cPtr, &pOpcode);  
  114.   
  115.         if (!Length || (Length == 1 && *pOpcode == 0xC3)) return NULL;  
  116.   
  117.         if (*(PUSHORT)pOpcode == 0x888D)  
  118.         {  
  119.             ServiceTableAddress = *(PULONG)(pOpcode + 2);  
  120.             ShadowTable = (PSYSTEM_SERVICE_TABLE)ServiceTableAddress;  
  121.             ShadowTable ++;  
  122.             return ShadowTable;  
  123.         }  
  124.     }  
  125.     return NULL;  
  126. }  

ULONG GetShadowSsdtCurrentAddresses( PSSDT_ADDRESS AddressInfo, PULONG Length ) { PSYSTEM_SERVICE_TABLE KeServiceDescriptorTableShadow = NULL; ULONG NumberOfService = 0; ULONG ServiceId = 0; PKAPC_STATE ApcState; ULONG i; if (AddressInfo == NULL || Length == NULL) { KdPrint(("[GetShadowSsdtCurrentAddresses] 输入参数无效")); return 0; } //KdPrint(("pid = %d", PsGetCurrentProcessId())); ServiceId = (ULONG)PsGetCurrentProcessId(); if (!g_CsrssProcess) { PsLookupProcessByProcessId((PVOID)ScPsGetCsrssProcessId(), &g_CsrssProcess); } KeServiceDescriptorTableShadow = GetKeServiceDescriptorTableShadow(); if (KeServiceDescriptorTableShadow == NULL) { KdPrint(("[GetShadowSsdtCurrentAddresses] GetKeServiceDescriptorTableShadow failed")); return 0; } NumberOfService = KeServiceDescriptorTableShadow->NumberOfService; if (Length[0] < NumberOfService * sizeof(SSDT_ADDRESS)) { Length[0] = NumberOfService * sizeof(SSDT_ADDRESS); return 0; } ApcState = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC_STATE), MEM_TAG); KeStackAttachProcess((PRKPROCESS)g_CsrssProcess, ApcState); for (ServiceId = 0; ServiceId < NumberOfService; ServiceId ++) { AddressInfo[ServiceId].FunAddress = (ULONG) KeServiceDescriptorTableShadow->ServiceTableBase[ServiceId]; AddressInfo[ServiceId].nIndex = ServiceId; } KeUnstackDetachProcess(ApcState); ExFreePool(ApcState); Length[0] = NumberOfService * sizeof(SSDT_ADDRESS); return NumberOfService; } /// // // 功能实现:枚举当前Shadow SSDT 表函数地址 // 输入参数:void // 输出参数:返回Shadow ssdt table // /// PSYSTEM_SERVICE_TABLE GetKeServiceDescriptorTableShadow(VOID) { PSYSTEM_SERVICE_TABLE ShadowTable = NULL; ULONG ServiceTableAddress = 0; PUCHAR cPtr = NULL; for (cPtr = (PUCHAR)KeAddSystemServiceTable; cPtr < (PUCHAR)KeAddSystemServiceTable + PAGE_SIZE; cPtr += 1 ) { if (!MmIsAddressValid(cPtr)) continue; ServiceTableAddress = *(PULONG)cPtr; if (!MmIsAddressValid((PVOID)ServiceTableAddress)) continue; if (memcmp((PVOID)ServiceTableAddress, &KeServiceDescriptorTable, 16) == 0) { if ((PVOID)ServiceTableAddress == &KeServiceDescriptorTable) continue; ShadowTable = (PSYSTEM_SERVICE_TABLE)ServiceTableAddress; ShadowTable ++; return ShadowTable; } } return NULL; } // // 方法2,通过硬编码实现,不通用 // PSYSTEM_SERVICE_TABLE GetKeServiceDescriptorTableShadow_2(VOID) /*++ 805ba5a3 8d8840a65580 lea ecx,nt!KeServiceDescriptorTableShadow (8055a640)[eax] 805ba5a9 833900 cmp dword ptr [ecx],0 --*/ { PSYSTEM_SERVICE_TABLE ShadowTable; ULONG ServiceTableAddress; PUCHAR cPtr, pOpcode; ULONG Length = 0; for (cPtr = (PUCHAR)KeAddSystemServiceTable; cPtr < (PUCHAR)KeAddSystemServiceTable + PAGE_SIZE; cPtr += Length ) { if (!MmIsAddressValid(cPtr)) return NULL; Length = SizeOfCode(cPtr, &pOpcode); if (!Length || (Length == 1 && *pOpcode == 0xC3)) return NULL; if (*(PUSHORT)pOpcode == 0x888D) { ServiceTableAddress = *(PULONG)(pOpcode + 2); ShadowTable = (PSYSTEM_SERVICE_TABLE)ServiceTableAddress; ShadowTable ++; return ShadowTable; } } return NULL; }

转载于:https://www.cnblogs.com/kuangke/p/5761555.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本实例由VS2008开发,在提供了一套驱动开发框架的同时,又演示了如何获取Shadow SSDT表函数原始地址的办法。 主要函数:ULONG GetShadowSSDT_Function_OriAddr(ULONG index); 原理说明: 根据特征码搜索导出函数KeAddSystemServiceTable来获取Shadow SSDT基址,以及通过ZwQuerySystemInformation()函数获取win32k.sys基址,然后解析PE定位到Shadow SSDT在win32k.sys的偏移地址,并通过进一步计算来得到Shadow SSDT表函数的原始地址。 这里只测试了三个函数:(460)NtUserMessageCall、(475)NtUserPostMessage和(502)NtUserSendInput,具体使用时可以举一反三,网上完整的源代码实例并不太多,希望可以帮到真正有需要的朋友。 系统环境: 在WinXP SP3系统 + 瑞星杀毒软件 打印输出: [ LemonInfo : Loading Shadow SSDT Original Address Driver... ] [ LemonInfo : 创建“设备”值为:0 ] [ LemonInfo : 创建“设备”成功... ] [ LemonInfo : 创建“符号链接”状态值为:0 ] [ LemonInfo : 创建“符号链接”成功... ] [ LemonInfo : 驱动加载成功... ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP 开始... ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP Enter IRP_MJ_DEVICE_CONTROL... ] [ LemonInfo : 获取ShadowSSDT表 (460)NtUserMessageCall 函数的“当前地址”为:0xB83ECFC4,“起源地址”为:0xBF80EE6B ] [ LemonInfo : 获取ShadowSSDT表 (475)NtUserPostMessage 函数的“当前地址”为:0xB83ECFA3,“起源地址”为:0xBF8089B4 ] [ LemonInfo : 获取ShadowSSDT表 (502)NtUserSendInput 函数的“当前地址”为:0xBF8C31E7,“起源地址”为:0xBF8C31E7 ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP_MJ_DEVICE_CONTROL 成功执行... ] [ LemonInfo : 派遣函数(DispatchRoutine) IRP 结束... ] [ LemonInfo : UnLoading Shadow SSDT Original Address Driver... ] [ LemonInfo : 删除“符号链接”成功... ] [ LemonInfo : 删除“设备”成功... ] [ LemonInfo : 驱动卸载成功... ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值