SSDT(System Services Descriptor Table),系统服务描述符表。这个表就是一个把ring3的Win32 API和ring0的内核API联系起来。SSDT并不仅仅只包含一个庞大的地址索引表,它还包含着一些其它有用的信息,诸如地址索引的基地址、服务函数个数等。
  通过修改此表的函数地址可以对常用windows函数及API进行hook,从而实现对一些关心的系统动作进行过滤、监控的目的。一些HIPS、防毒软件、系统监控、注册表监控软件往往会采用此接口来实现自己的监控模块,
  目前极个别病毒确实会采用这种方法来保护自己或者破坏防毒软件,但在这种病毒进入系统前如果防毒软件能够识别并清除它将没有机会发作.

  SSDT到底是什么呢?打一个比方,SSDT相当于系统内部API的指向标,作用就是告诉系统,需要调用的API在什么地方。

请看源码解析

[cpp] view plaincopy
  1. /*************************************************************************
  2. *
  3. *ZwQuerySystemInformation函数常用结构
  4. *
  5. **************************************************************************/
  6. #ifndef _SPS_H_
  7. #define _SPS_H_ 1
  8. #include <ntddk.h>
  9. #include "table.h"
  10. #include "pe.h"
  11. #endif
  12. typedef enum _SYSTEM_INFORMATION_CLASS
  13. {
  14. SystemBasicInformation,                 // 0
  15. SystemProcessorInformation,             // 1
  16. SystemPerformanceInformation,           // 2
  17. SystemTimeOfDayInformation,             // 3
  18. SystemNotImplemented1,                  // 4
  19. SystemProcessesAndThreadsInformation,   // 5
  20. SystemCallCounts,                       // 6
  21. SystemConfigurationInformation,         // 7
  22. SystemProcessorTimes,                   // 8
  23. SystemGlobalFlag,                       // 9
  24. SystemNotImplemented2,                  // 10
  25. SystemModuleInformation,                // 11            系统模块
  26. SystemLockInformation,                  // 12
  27. SystemNotImplemented3,                  // 13
  28. SystemNotImplemented4,                  // 14
  29. SystemNotImplemented5,                  // 15
  30. SystemHandleInformation,                // 16
  31. SystemObjectInformation,                // 17
  32. SystemPagefileInformation,              // 18
  33. SystemInstructionEmulationCounts,       // 19
  34. SystemInvalidInfoClass1,                // 20
  35. SystemCacheInformation,                 // 21
  36. SystemPoolTagInformation,               // 22
  37. SystemProcessorStatistics,              // 23
  38. SystemDpcInformation,                   // 24
  39. SystemNotImplemented6,                  // 25
  40. SystemLoadImage,                        // 26
  41. SystemUnloadImage,                      // 27
  42. SystemTimeAdjustment,                   // 28
  43. SystemNotImplemented7,                  // 29
  44. SystemNotImplemented8,                  // 30
  45. SystemNotImplemented9,                  // 31
  46. SystemCrashDumpInformation,             // 32
  47. SystemExceptionInformation,             // 33
  48. SystemCrashDumpStateInformation,        // 34
  49. SystemKernelDebuggerInformation,        // 35
  50. SystemContextSwitchInformation,         // 36
  51. SystemRegistryQuotaInformation,         // 37
  52. SystemLoadAndCallImage,                 // 38
  53. SystemPrioritySeparation,               // 39
  54. SystemNotImplemented10,                 // 40
  55. SystemNotImplemented11,                 // 41
  56. SystemInvalidInfoClass2,                // 42
  57. SystemInvalidInfoClass3,                // 43
  58. SystemTimeZoneInformation,              // 44
  59. SystemLookasideInformation,             // 45
  60. SystemSetTimeSlipEvent,                 // 46
  61. SystemCreateSession,                    // 47
  62. SystemDeleteSession,                    // 48
  63. SystemInvalidInfoClass4,                // 49
  64. SystemRangeStartInformation,            // 50
  65. SystemVerifierInformation,              // 51
  66. SystemAddVerifier,                      // 52
  67. SystemSessionProcessesInformation       // 53
  68. }SYSTEM_INFORMATION_CLASS;                      //内核模块类型,我们要列举的是SystemProcessesAndThreadsInformation,进程和线程信
  69. //线程信息
  70. typedef struct _SYSTEM_THREAD_INFORMATION
  71. {
  72. LARGE_INTEGER KernelTime;
  73. LARGE_INTEGER UserTime;
  74. LARGE_INTEGER CreateTime;
  75. ULONG WaitTime;
  76. PVOID StartAddress;
  77. CLIENT_ID ClientId;
  78. KPRIORITY Priority;
  79. KPRIORITY BasePriority;
  80. ULONG ContextSwitchCount;
  81. LONG State;
  82. LONG WaitReason;
  83. } SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION;  //线程结构
  84. //进程信息
  85. typedef struct _SYSTEM_PROCESS_INFORMATION
  86. {
  87. ULONG                   NextEntryDelta;                 //NextEntryOffset下一个进程结构的偏移量,每一个进程对应一个结构
  88. //最后一个进程的NextEntryOffset=0
  89. ULONG                   NumberOfThreads;                 //线程数目
  90. LARGE_INTEGER           Reserved[3];
  91. LARGE_INTEGER           CreateTime;                      //创建时间
  92. LARGE_INTEGER           UserTime;                        //用户模式(Ring 3)的CPU时间
  93. LARGE_INTEGER           KernelTime;                      //内核模式(Ring 0)的CPU时间
  94. UNICODE_STRING          ProcessName;                     //进程名
  95. KPRIORITY               BasePriority;                    //进程优先权
  96. ULONG                   ProcessId;                       //进程标识符
  97. ULONG                   InheritedFromProcessId;          //父进程的标识符
  98. ULONG                   HandleCount;                     //句柄数目
  99. ULONG                   Reserved2[2];
  100. ULONG                   PrivatePageCount;
  101. VM_COUNTERS             VirtualMemoryCounters;           //虚拟存储器的结构
  102. IO_COUNTERS             IoCounters;                      //IO计数结构
  103. SYSTEM_THREAD_INFORMATION     Threads[0];                //进程相关线程的结构数组
  104. } SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
  105. //------------------------------------------------------------------------------
  106. //模块信息
  107. typedef struct _SYSTEM_MODULE_INFORMATION {
  108. ULONG Reserved[2];
  109. PVOID Base;
  110. ULONG Size;
  111. ULONG Flags;
  112. USHORT Index;
  113. USHORT Unknown;
  114. USHORT LoadCount;
  115. USHORT ModuleNameOffset;
  116. CHAR ImageName[256];
  117. } SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
  118. //模块列表
  119. typedef struct _SYSMODULELIST{
  120. ULONG ulCount;
  121. SYSTEM_MODULE_INFORMATION smi[1];
  122. } SYSMODULELIST, *PSYSMODULELIST;
  123. //-----------------------------------------------------------------------------------
  124. //DRIVER_SECTION结构
  125. typedef struct _LDR_DATA_TABLE_ENTRY
  126. {
  127. LIST_ENTRY InLoadOrderLinks;
  128. LIST_ENTRY InMemoryOrderLinks;
  129. LIST_ENTRY InInitializationOrderLinks;
  130. PVOID DllBase;
  131. PVOID EntryPoint;
  132. ULONG SizeOfImage;
  133. UNICODE_STRING FullDllName;
  134. UNICODE_STRING BaseDllName;
  135. ULONG Flags;
  136. USHORT LoadCount;
  137. USHORT TlsIndex;
  138. union {
  139. LIST_ENTRY HashLinks;
  140. struct
  141. {
  142. PVOID SectionPointer;
  143. ULONG CheckSum;
  144. };
  145. };
  146. union {
  147. struct
  148. {
  149. ULONG TimeDateStamp;
  150. };
  151. struct
  152. {
  153. PVOID LoadedImports;
  154. };
  155. };
  156. struct _ACTIVATION_CONTEXT * EntryPointActivationContext;
  157. PVOID PatchInformation;
  158. }LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
  159. //===================================================================================
  160. NTKERNELAPI NTSTATUS
  161. ZwQuerySystemInformation(
  162. IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
  163. OUT PVOID SystemInformation,
  164. IN ULONG SystemInformationLength,
  165. OUT PULONG ReturnLength OPTIONAL
  166. );   //最终是通过遍历EPROCESS获取的
  167. typedef NTSTATUS (*ZWQUERYSYSTEMINFORMATION)(
  168. IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
  169. OUT PVOID SystemInformation,
  170. IN ULONG SystemInformationLength,
  171. OUT PULONG ReturnLength OPTIONAL
  172. ); //定义结构
  173. NTSYSAPI BOOLEAN NTAPI KeAddSystemServiceTable(
  174. ULONG lpAddressTable,
  175. BOOLEAN bUnknown,
  176. ULONG   dwNumEntries,
  177. ULONG lpParameterTable,
  178. ULONG   dwTableID
  179. );
  180. //****************************函数声明*************************************
  181. //根据地址查找模块
  182. void FindModuleByAddress( ULONG Address, PVOID buffer);
  183. //根据RVA查找SSDT 文件偏移
  184. ULONG FindFileOffsetByRva( ULONG ModuleAddress,ULONG Rva);
  185. //路径解析出子进程名
  186. void  GetModuleName( char *ProcessPath, char *ProcessName);
  187. //根据服务号得到当前的地址
  188. ULONG FindOriAddress( ULONG index );
  189. //得到SSDT Shadow表地址
  190. ULONG GetSSDTShadowAddress2();
  191. ULONG  GetWin32Base2( PDRIVER_OBJECT driver);
  192. ULONG FindShadowOriAddress( ULONG index );
  193. /*****************************************************************************************
  194. *
  195. *函数名:FindModuleByAddress
  196. *功能描述:根据函数地址查找所属模块
  197. *
  198. ******************************************************************************************/
  199. /*****************************************************************************************
  200. *
  201. *   原理: 利用ZwQuerySystemInformation传入SystemModuleInformation(11)得到系统模块列表
  202. *           得到每个模块的起始和结束地址
  203. *           比对地址,在那个范围就属于哪个模块
  204. *           得到模块名
  205. *
  206. ******************************************************************************************/
  207. #include "refresh.h"
  208. void FindModuleByAddress( ULONG Address, PVOID buffer)
  209. {
  210. NTSTATUS status;
  211. ULONG size;
  212. ULONG i;
  213. ULONG minAddress;
  214. ULONG maxAddress;
  215. PSYSMODULELIST List;
  216. ZwQuerySystemInformation( SystemModuleInformation ,&size,0,&size);
  217. KdPrint(("[FindModuleByAddress] size:0x%x\n",size));
  218. List=(PSYSMODULELIST)ExAllocatePool(NonPagedPool,size);
  219. if(List==NULL)
  220. {
  221. KdPrint(("[FindModuleByAddress] malloc memory failed\n"));
  222. return ;
  223. }
  224. status=ZwQuerySystemInformation(SystemModuleInformation,List,size,0);
  225. if(!NT_SUCCESS(status))
  226. {
  227. KdPrint(("[FindModuleByAddress] query failed\n"));
  228. //打印错误
  229. KdPrint(("[FindModuleByAddress] status: 0x%x\n",status));
  230. ExFreePool( List );
  231. return ;
  232. }
  233. //得到了模块链表
  234. //判断模块名
  235. for( i=0; i<List->ulCount; i++)
  236. {
  237. //得到模块的范围
  238. minAddress = (ULONG)List->smi[i].Base;
  239. maxAddress = minAddress + List->smi[i].Size;
  240. //判断地址
  241. if( Address >= minAddress && Address <= maxAddress )
  242. {
  243. memcpy( buffer, List->smi[i].ImageName,sizeof(List->smi[i].ImageName));
  244. KdPrint(("[FindModuleByAddress] modulename: %s\n",buffer));
  245. //释放内存
  246. ExFreePool(List);
  247. break;
  248. }
  249. }
  250. }
  251. /***************************************************************************************
  252. *
  253. *   函数名:GetOriFunctionAddress
  254. *   功能描述:得到原始SSDT表中函数地址
  255. *
  256. ****************************************************************************************/
  257. /***************************************************************************************
  258. *
  259. *   原理: 找到内核文件,获取基址BaseAddress
  260. *           根据内核文件查找SSDT表的文件偏移SSDTFileOffset = SSDTRVA-(节RVA-节Offset)
  261. *           读取函数的文件偏移FunctionFileOffset
  262. *           VA=BaseAddress+FunctionFileOffset-00400000=800d8000 + FunctionFileOffset
  263. *
  264. *****************************************************************************************/
  265. /****************************************************************************************
  266. *
  267. *   根据RVA查找所在的文件偏移:FileOffset = Rva- (节Rva - 节Offset)
  268. *   找到区块表
  269. *****************************************************************************************/
  270. ULONG FindFileOffsetByRva( ULONG ModuleAddress,ULONG Rva)
  271. {
  272. PIMAGE_DOS_HEADER dos;
  273. PIMAGE_FILE_HEADER file;
  274. PIMAGE_SECTION_HEADER section;
  275. //区块数目
  276. ULONG number;
  277. ULONG i;
  278. ULONG minAddress;
  279. ULONG maxAddress;
  280. ULONG SeFileOffset;
  281. ULONG FileOffset;
  282. dos = (PIMAGE_DOS_HEADER)ModuleAddress;
  283. file = (PIMAGE_FILE_HEADER)( ModuleAddress + dos->e_lfanew + 4 );
  284. //得到区块数量
  285. number = file->NumberOfSections;
  286. KdPrint(("[FindFileOffsetByRva] number :0x%x\n",number));
  287. //得到第一个区块地址
  288. section = (PIMAGE_SECTION_HEADER)(ModuleAddress + dos->e_lfanew + 4 + sizeof(IMAGE_FILE_HEADER) + file->SizeOfOptionalHeader);
  289. for( i=0;i<number;i++)
  290. {
  291. minAddress = section[i].VirtualAddress;
  292. maxAddress = minAddress + section[i].SizeOfRawData;
  293. SeFileOffset = section[i].PointerToRawData;
  294. if( Rva > minAddress && Rva < maxAddress)
  295. {
  296. KdPrint(("[FindFileOffsetByRva] minAddress :0x%x\n",minAddress));
  297. KdPrint(("[FindFileOffsetByRva] SeFileOffset :0x%x\n",SeFileOffset));
  298. FileOffset = Rva - ( minAddress - SeFileOffset);
  299. KdPrint(("[FindFileOffsetByRva] FileOffset :0x%x\n",FileOffset));
  300. break ;
  301. }
  302. }
  303. return FileOffset;
  304. }
  305. //路径解析出子进程名
  306. void  GetModuleName( char *ProcessPath, char *ProcessName)
  307. {
  308. ULONG n = strlen( ProcessPath) - 1;
  309. ULONG i = n;
  310. KdPrint(("%d",n));
  311. while( ProcessPath[i] != '\\')
  312. {
  313. i = i-1;
  314. }
  315. strncpy( ProcessName, ProcessPath+i+1,n-i);
  316. }
  317. /****************************************************************************************
  318. *
  319. *   根据传入的服务号得到函数原始地址
  320. *
  321. ****************************************************************************************/
  322. ULONG FindOriAddress( ULONG index )
  323. {
  324. //根据传入的index得到函数VA地址
  325. //重定位函数地址
  326. //BaseAddress - 0x00400000 + *(PULONG)(FileOffset+(index*4))
  327. //ZwQuerySystemInformation得到内核文件基地址
  328. //得到SSDT表的地址
  329. //得到SSDT RVA 查找SSDT RVA所在的节
  330. NTSTATUS status;
  331. ULONG size;
  332. ULONG BaseAddress;
  333. ULONG SsdtRva;
  334. ULONG FileOffset = 0;
  335. PSYSMODULELIST list;
  336. char Name[32]={0};
  337. char PathName[256] = "\\SystemRoot\\system32\\";
  338. ANSI_STRING name;
  339. UNICODE_STRING modulename;
  340. OBJECT_ATTRIBUTES  object_attributes;
  341. IO_STATUS_BLOCK io_status = {0};
  342. HANDLE hFile;
  343. //读取的位置
  344. ULONG location;
  345. LARGE_INTEGER offset;
  346. ULONG address;
  347. //得到需要申请的内存大小
  348. ZwQuerySystemInformation( SystemModuleInformation,&size,0,&size );
  349. //申请内存
  350. list = (PSYSMODULELIST) ExAllocatePool( NonPagedPool,size );
  351. //验证是否申请成功
  352. if( list == NULL)
  353. {
  354. //申请失败
  355. KdPrint(("[FindOriAddress] malloc memory failed\n"));
  356. ExFreePool(list);
  357. return 0;
  358. }
  359. status = ZwQuerySystemInformation( SystemModuleInformation,list,size,0);
  360. if( !NT_SUCCESS( status ))
  361. {
  362. //获取信息失败
  363. KdPrint(("[FindOriAddress] query failed\n"));
  364. KdPrint(("[FindOriAddress] status:0x%x\n",status));
  365. ExFreePool(list);
  366. return 0;
  367. }
  368. //得到模块基址,第一个模块为内核文件
  369. BaseAddress = (ULONG )list->smi[0].Base;
  370. KdPrint(("[FindOriAddress] BaseAddress:0x%x\n",BaseAddress));
  371. //分离出内核文件名
  372. GetModuleName(list->smi[0].ImageName,Name);
  373. KdPrint(("[FindOriAddress] processname:%s\n",Name));
  374. strcat(PathName,Name);
  375. RtlInitAnsiString(&name,PathName);
  376. RtlAnsiStringToUnicodeString(&modulename,&name,TRUE);
  377. KdPrint(("[FindOriAddress] modulename: %wZ\n",&modulename));
  378. ExFreePool(list);
  379. //经验证地址正确
  380. //得到SSDT表的Rva
  381. SsdtRva = (ULONG)KeServiceDescriptorTable->ServiceTableBase - BaseAddress;
  382. //验证
  383. KdPrint(("[FindOriAddress] SsdtRva:0x%x\n",SsdtRva));
  384. //根据RVA查找文件偏移,//得到文件偏移了
  385. FileOffset= FindFileOffsetByRva( BaseAddress,SsdtRva);
  386. KdPrint(("[FindOriAddress] FileOffset:0x%x\n",FileOffset));
  387. //读取的位置
  388. location = FileOffset + index * 4;
  389. offset.QuadPart =location;
  390. KdPrint(("[FindOriAddress] location:0x%x\n",location));
  391. //利用ZwReadFile读取文件
  392. //初始化OBJECT_ATTRIBUTES结构
  393. InitializeObjectAttributes(
  394. &object_attributes,
  395. &modulename,
  396. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  397. NULL,
  398. NULL);
  399. //打开文件
  400. status = ZwCreateFile(
  401. &hFile,
  402. FILE_EXECUTE | SYNCHRONIZE,
  403. &object_attributes,
  404. &io_status,
  405. NULL,
  406. FILE_ATTRIBUTE_NORMAL,
  407. FILE_SHARE_READ,
  408. FILE_OPEN,
  409. FILE_NON_DIRECTORY_FILE |
  410. FILE_RANDOM_ACCESS |
  411. FILE_SYNCHRONOUS_IO_NONALERT,
  412. NULL,
  413. 0);
  414. if( !NT_SUCCESS( status ))
  415. {
  416. KdPrint(("[FindOriAddress] open error\n"));
  417. KdPrint(("[FindOriAddress] status = 0x%x\n", status));
  418. ZwClose( hFile );
  419. return 0;
  420. }
  421. status = ZwReadFile(
  422. hFile,
  423. NULL,
  424. NULL,
  425. NULL,
  426. NULL,
  427. &address,
  428. sizeof(ULONG),
  429. &offset,
  430. NULL);
  431. if( !NT_SUCCESS( status ))
  432. {
  433. KdPrint(("[FindOriAddress] read error\n"));
  434. KdPrint(("[FindOriAddress] status = 0x%x\n", status));
  435. ZwClose( hFile );
  436. return 0;
  437. }
  438. KdPrint(("[FindOriAddress] address:0x%x\n",address));
  439. //重定位
  440. address = BaseAddress - 0x00400000 + address;
  441. KdPrint(("[FindOriAddress] Oriaddress:0x%x\n",address));
  442. //释放动态分配的内存
  443. RtlFreeUnicodeString(&modulename);
  444. ZwClose( hFile );
  445. return address;
  446. }
  447. /******************************************************************************************
  448. *
  449. *   得到SSDT Shadow当前地址
  450. *   1、KeServiceDescriptorTable -  0x40 + 0x10
  451. *   2、搜索KeAddSystemServiceTable函数,特征码
  452. *   3、Kthread->ServiceTable指向
  453. *   4、MJ提出的搜索特定内存
  454. *
  455. *******************************************************************************************/
  456. //方式1,XP下-0x40;
  457. ULONG GetSSDTShadowAddress1()
  458. {
  459. ULONG address;
  460. ULONG ssdt;
  461. ssdt = (ULONG)KeServiceDescriptorTable;
  462. address = ssdt - 0x30;
  463. KdPrint(("[GetSSDTShadowAddress] ssdt:0x%x\n",ssdt));
  464. KdPrint(("[GetSSDTShadowAddress] address:0x%x\n",address));
  465. return address;
  466. }
  467. //方式2
  468. ULONG GetSSDTShadowAddress2()
  469. {
  470. ULONG address;
  471. PUCHAR addr;
  472. PUCHAR p;
  473. addr = (PUCHAR)KeAddSystemServiceTable;
  474. for( p=addr; p<addr+PAGE_SIZE; p++)
  475. {
  476. if(*(PUSHORT)p == 0x888D)
  477. {
  478. address = *(PULONG)((ULONG)p+2);
  479. break;
  480. }
  481. }
  482. address = address + 0x10;
  483. KdPrint(("[GetSSDTShadowAddress] address:0x%x\n",address));
  484. return address;
  485. }
  486. //方式3
  487. ULONG GetSSDTShadowAddress3()
  488. {
  489. return 0;
  490. }
  491. //方式4
  492. ULONG GetSSDTShadowAddress4()
  493. {
  494. return 0;
  495. }
  496. /*********************************************************************************
  497. *
  498. *   获得win32k.sys基址
  499. *   1、ZwQuerySystemInformation
  500. *   2、遍历DriverSection链表
  501. *
  502. **********************************************************************************/
  503. ULONG GetWin32Base1()
  504. {
  505. NTSTATUS status;
  506. ULONG i;
  507. ULONG size;
  508. ULONG address;
  509. PSYSMODULELIST List;
  510. ZwQuerySystemInformation( SystemModuleInformation ,&size,0,&size);
  511. KdPrint(("[FindModuleByAddress] size:0x%x\n",size));
  512. List=(PSYSMODULELIST)ExAllocatePool(NonPagedPool,size);
  513. if (List==NULL)
  514. {
  515. KdPrint(("[FindModuleByAddress] malloc memory failed\n"));
  516. ExFreePool( List );
  517. return 0;
  518. }
  519. status=ZwQuerySystemInformation(SystemModuleInformation,List,size,0);
  520. if (!NT_SUCCESS(status))
  521. {
  522. KdPrint(("[FindModuleByAddress] query failed\n"));
  523. //打印错误
  524. KdPrint(("[FindModuleByAddress] status: 0x%x\n",status));
  525. ExFreePool( List );
  526. return 0;
  527. }
  528. for ( i=0; i < List->ulCount; i++ )
  529. {
  530. if( strcmp(List->smi[i].ImageName,"\\SystemRoot\\System32\\win32k.sys") == 0)
  531. {
  532. KdPrint(("[GetWin32Base]name :%s\n",List->smi[i].ImageName));
  533. address = (ULONG)List->smi[i].Base;
  534. KdPrint(("[GetWin32Base1] win32k.sys address:0x%x\n",address));
  535. }
  536. }
  537. return address;
  538. }
  539. /*********************************************************************************************
  540. *
  541. *   驱动对象DRIVER_OBJECT中的DRIVER_SECTION
  542. *   LDR_DATA_TABLE_ENTRY结构包含系统加载模块链表及基址
  543. *
  544. *
  545. **********************************************************************************************/
  546. ULONG  GetWin32Base2( PDRIVER_OBJECT driver)
  547. {
  548. PLIST_ENTRY pList = NULL;
  549. PLDR_DATA_TABLE_ENTRY pLdr = NULL;
  550. ULONG BaseAddress = 0;
  551. pList = ( (PLIST_ENTRY)driver->DriverSection )->Flink;
  552. do
  553. {
  554. pLdr = CONTAINING_RECORD(
  555. pList,
  556. LDR_DATA_TABLE_ENTRY,
  557. InLoadOrderLinks
  558. );
  559. if( pLdr->EntryPoint != NULL && pLdr->FullDllName.Buffer!= NULL )
  560. {
  561. if( !_wcsicmp( pLdr->FullDllName.Buffer, L"\\SystemRoot\\System32\\win32k.sys"))
  562. {
  563. BaseAddress = (ULONG )pLdr->DllBase;
  564. KdPrint(("[GetWin32Base2] win32k.sys address:0x%x\n",BaseAddress));
  565. break ;
  566. }
  567. }
  568. pList = pList->Flink;
  569. }while( pList != ((PLIST_ENTRY)driver->DriverSection)->Flink );
  570. return BaseAddress;
  571. }
  572. /****************************************************************************************
  573. *
  574. *   根据传入的服务号得到Shadow 函数原始地址
  575. *
  576. ****************************************************************************************/
  577. ULONG FindShadowOriAddress( ULONG index )
  578. {
  579. //内核文件win32k.sys基地址
  580. //得到SSDT Shadow表的地址
  581. //得到文件偏移
  582. NTSTATUS status;
  583. ULONG size;
  584. ULONG BaseAddress;
  585. ULONG ShadowBase;
  586. ULONG ShadowAddress;
  587. ULONG SsdtRva;
  588. ULONG FileOffset = 0;
  589. UNICODE_STRING modulename;
  590. OBJECT_ATTRIBUTES  object_attributes;
  591. IO_STATUS_BLOCK io_status = {0};
  592. HANDLE hFile;
  593. //读取的位置
  594. ULONG location;
  595. LARGE_INTEGER offset;
  596. ULONG address;
  597. BaseAddress = GetWin32Base1();
  598. KdPrint(("[FindShadowOriAddress] BaseAddress:0x%x\n",BaseAddress));
  599. //经验证地址正确
  600. ShadowBase = GetSSDTShadowAddress2();
  601. ShadowAddress = *(PULONG)ShadowBase;
  602. KdPrint(("[FindShadowOriAddress] ShadowAddress:0x%x\n",ShadowAddress));
  603. //得到SSDT表的Rva
  604. SsdtRva = ShadowAddress - BaseAddress;
  605. //验证
  606. KdPrint(("[FindOriAddress] SsdtRva:0x%x\n",SsdtRva));
  607. //读取的位置
  608. location = SsdtRva + index * 4;
  609. offset.QuadPart =location;
  610. KdPrint(("[FindOriAddress] location:0x%x\n",location));
  611. //利用ZwReadFile读取文件
  612. //初始化OBJECT_ATTRIBUTES结构
  613. RtlInitUnicodeString(&modulename, L"\\SystemRoot\\system32\\win32k.sys");
  614. InitializeObjectAttributes(
  615. &object_attributes,
  616. &modulename,
  617. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  618. NULL,
  619. NULL);
  620. //打开文件
  621. status = ZwCreateFile(
  622. &hFile,
  623. FILE_EXECUTE | SYNCHRONIZE,
  624. &object_attributes,
  625. &io_status,
  626. NULL,
  627. FILE_ATTRIBUTE_NORMAL,
  628. FILE_SHARE_READ,
  629. FILE_OPEN,
  630. FILE_NON_DIRECTORY_FILE |
  631. FILE_RANDOM_ACCESS |
  632. FILE_SYNCHRONOUS_IO_NONALERT,
  633. NULL,
  634. 0);
  635. if( !NT_SUCCESS( status ))
  636. {
  637. KdPrint(("[FindOriAddress] open error\n"));
  638. KdPrint(("[FindOriAddress] status = 0x%x\n", status));
  639. ZwClose( hFile );
  640. return 0;
  641. }
  642. status = ZwReadFile(
  643. hFile,
  644. NULL,
  645. NULL,
  646. NULL,
  647. NULL,
  648. &address,
  649. sizeof(ULONG),
  650. &offset,
  651. NULL);
  652. if( !NT_SUCCESS( status ))
  653. {
  654. KdPrint(("[FindOriAddress] read error\n"));
  655. KdPrint(("[FindOriAddress] status = 0x%x\n", status));
  656. ZwClose( hFile );
  657. return 0;
  658. }
  659. KdPrint(("[FindOriAddress] address:0x%x\n",address));
  660. address = address;
  661. KdPrint(("[FindOriAddress] Oriaddress:0x%x\n",address));
  662. ZwClose( hFile );
  663. return address;
  664. }

VC++实现恢复SSDT相关推荐

  1. 驱动开发:恢复SSDT内核钩子

    SSDT 中文名称为系统服务描述符表,该表的作用是将Ring3应用层与Ring0内核层,两者的API函数连接起来,起到承上启下的作用,SSDT并不仅仅只包含一个庞大的地址索引表,它还包含着一些其它有用 ...

  2. X86驱动:恢复SSDT内核钩子

    SSDT 中文名称为系统服务描述符表,该表的作用是将Ring3应用层与Ring0内核层,两者的API函数连接起来,起到承上启下的作用,SSDT并不仅仅只包含一个庞大的地址索引表,它还包含着一些其它有用 ...

  3. 用SSDT方法恢复冒险岛的部分函数

    看了那么多文章.视频,现在自己跟着做下恢复的驱动程序吧.今天拿冒险岛的HS驱动做为例子吧.冒险岛游戏对Xuetr进行检测了,打开XueTr不久就会游戏发现非法模块,最终游戏关闭.就拿上了一款叫Kern ...

  4. vc升级失败恢复快照后数据不一致问题

    第一次故障现象: 下午192.168.146.1 vc5.5升级6.0失败后回滚.Vcenter.DB和SSO均做的是带内存的快照.当时检查恢复完能连上vc和web client.当天晚上发现vc连接 ...

  5. 杀毒软件智能主动防御的软肋——无驱恢复系统SSDT表

    8.3 杀毒软件智能主动防御的软肋--无驱恢复系统SSDT表 大部分的杀毒软件其内置的主动防御功能,通常考虑到用户易用性的问题,都是采用的智能HIPS拦截,也就是说内置一些HIPS拦截规则,智能判断未 ...

  6. Win64 驱动内核编程-20.UnHook SSDT

    UNHOOK SSDT 要恢复 SSDT,首先要获得 SSDT 各个函数的原始地址,而 SSDT 各个函数的原始地址,自然是存储在内核文件里的.于是,有了以下思路: 1.获得内核里 KiService ...

  7. HP刀片服务器系统Flex-10 VC配置与VMware vSphere网络设计

    原文地址:http://delxu.blog.51cto.com/975660/932902 本文主要描述了HP C7000刀片服务器系统中的Flex-10 VirtualConnect模块的配置 及 ...

  8. SSDT HOOK技术轻松让最新版冰刃、XueTr失效

    刚开始学驱动,成功HOOK NtOpenProces 现在本想试试HOOK NtQuerySystemInformation,没想打它的结构N多N长,也让我很惊讶,这个API居然能获取或者设置超过50 ...

  9. 【梅哥的Ring0湿润插入教程】第二课:Ring0实现读写SSDT

    [梅哥的Ring0湿润插入教程] Email:mlkui@163.com 转载请注明出处,谢绝喷子记者等,如引起各类不适请自觉滚J8蛋! 第二课:Ring0实现读写SSDT 随着驱动保护技术的逐步成熟 ...

最新文章

  1. solr安装-tomcat+solrCloud构建稳健solr集群
  2. 黑马程序员pink老师前端入门教程,零基础必看的JavaScript基础语法视频教程(一)
  3. WF 创建 SQL 持久性数据库
  4. 微信小程序错误监控方法谈
  5. PAT_B_1004_Java(20分)
  6. java面试手写单链表_(转)面试大总结之一:Java搞定面试中的链表题目
  7. ElementUI弹框组件 messageBox 如何换行 ?
  8. nodejs注册为windows服务实现开机自启动
  9. 瑞星力荐金山毒霸 原来是广告程序 作崇
  10. 【数据挖掘案例】财政收入影响因素分析及预测模型
  11. 查找整数c语言程序,查找整数(示例代码)
  12. 小学期云效能训练营-Day01
  13. session Asii码转换
  14. CMOS基础知识(一)
  15. 计算机系统运行太慢,如何解决电脑运行速度慢
  16. 「Git」常用工作流介绍
  17. 6 统计正数和负数的个数然后计算这些数的平均值
  18. 快速识别图像的人工智能图像识别小程序分享
  19. android app2sd+无法安装应用的解决办法。
  20. 牛客网Chino with Queue【状压DP】

热门文章

  1. ant design pro (十六)advanced 权限管理
  2. 解决sublime 乱码显示GBK编码文件
  3. 再说TCP神奇的40ms
  4. python学习笔记之函数(方法)
  5. 7项最佳实践助您利用媒体转换不断发展数据中心网络
  6. 浅析机器视觉在安防行业的应用
  7. WPF 自定义列表筛选 自定义TreeView模板 自定义ListBox模板
  8. 【编码】对qsort函数的稳定排序优化-京东实习笔试编程题(一)-2016.04.08
  9. 【巧妙算法系列】【Uva 11464】 - Even Parity 偶数矩阵
  10. 增加堆内存的大小 - 提防眼镜蛇效应