本论坛为只读模式,仅供查阅,不能注册新用户,不能发帖/回帖,有问题可发邮件 xikug.xp (^) gmail.com
查看: 6676|回复: 12

Delphi编写的Ring3下SSDT查看器 [复制链接]

Rank: 1

发表于 2010-4-19 13:45:45 |显示全部楼层
网上有一篇很精彩的文章《ring3下用ZwSystemDebugControl获取和恢复SSDT》,但是该代码对PE文件格式的学习很有帮助,所以用DELPHI防照这篇用C写的重新实现,相似度99%。
  1. unit SSDT;
  2. interface
  3. uses SysUtils,windows,Graphics;
  4. const
  5. STATUS_INFO_LENGTH_MISMATCH=$C0000004;
  6. SysDbgReadVirtualMemory = 8;
  7. SysDbgWriteVirtualMemory = 9;
  8. //一些常用的内型
  9. type
  10. NTSTATUS=ULONG;
  11. PVOID =Pointer;
  12. PImageBaseRelocation=^TImageBaseRelocation;
  13.   TImageBaseRelocation=Packed Record
  14.      VirtualAddress: DWORD;
  15.      SizeOfBlock: DWORD;
  16.      //TypeOffset: array[0..1] of Word;
  17. end;
  18. PModuleInformation=^TModuleInformation;
  19. TModuleInformation=packed record
  20.     Reserved:array[0..1] of ULONG ;
  21.     Base:Longint;
  22.     Size:Longint;
  23.     Flags: Longint;
  24.     Index:Smallint;
  25.     Unknown : Smallint;
  26.     Loadcount: Smallint;
  27.     ModuleNameOffset:Smallint;
  28.     ImageName:array[0..255] of  CHAR;
  29. end;
  30. PMEMORY_CHUNKS=^TMEMORY_CHUNKS;
  31. TMEMORY_CHUNKS=  packed record
  32.     Address:ULONG;
  33.     Data:PVOID;
  34.     Length:ULONG;
  35. end;
  36. TSSDT_LIST_ENTRY=packed record
  37. fname:sTRING;
  38. address1:ULONG; //原始地址
  39. address2:ULONG; //目前内存地址
  40. end;
  41. TSSDT_LIST_ARRAY=array of TSSDT_LIST_ENTRY;
  42. type
  43. PArray=^TArray;
  44. TArray=array[0..4196] of DWORD;
  45. function  ZwQuerySystemInformation(SystemInformationClass: ULONG; SystemInformation: PVOID; SystemInformationLength: ULONG; lpReturnLength: PULONG): NTSTATUS; stdcall; external 'ntdll.dll' name 'ZwQuerySystemInformation';
  46. function  ZwSystemDebugControl(ControlCode:integer;InputBuffer:PVOID;InputBufferLength:ulong;OutputBuffer:PVOID;OutputBufferLength:ulong;ReturnLength:PULONG): NTSTATUS; stdcall; external 'ntdll.dll' name 'ZwSystemDebugControl';
  47. function LocateNtdllEntry():BOOL;
  48. function GetHeaders(ibase:PCHAR;var pfh:PImageFileHeader;var poh:PImageOptionalHeader;var psh:PImageSectionHeader):DWORD;
  49. procedure FindExport();
  50. function FindKiServiceTable(hModule:HMODULE ;dwKSDT:DWORD):DWORD;
  51. function DebugPrivilege(PName:PCHAR;bEnable:BOOL):BOOL;
  52. procedure GetSSDT();
  53. var
  54. ssdt_list:TSSDT_LIST_ARRAY;
  55. dwKSDT:DWORD;                // rva of KeServiceDescriptorTable
  56. dwKiServiceTable:DWORD;    // rva of KiServiceTable
  57. dwKernelBase,dwServices:DWORD;
  58. implementation
  59.   uses unit1;
  60. function LocateNtdllEntry():BOOL;
  61. var
  62. ntdll:THandle;
  63. PFunc:TFarProc;
  64. begin
  65. ntdll:=GetModuleHandle('ntdll.dll');
  66. if ntdll=0 then
  67. result:=False;
  68. pFunc:=GetProcAddress(ntdll,'ZwQuerySystemInformation');
  69. if pFunc=nil then
  70. result:=False;
  71. end;
  72. function GetHeaders(ibase:PCHAR;var pfh:PImageFileHeader;var poh:PImageOptionalHeader;var psh:PImageSectionHeader):DWORD;
  73. var
  74. mzhead: PImageDosHeader;
  75. nthead: PImageNtHeaders;
  76. begin
  77. mzhead:=PImageDosHeader(ibase);
  78. if (mzhead^.e_magic<>IMAGE_DOS_SIGNATURE)  then
  79. begin
  80. result:=0;
  81. exit;
  82. end;
  83. nthead:=PImageNtHeaders(ibase+DWORD(mzhead^._lfanew));
  84. if  nthead^.Signature<> IMAGE_NT_SIGNATURE  then
  85. begin
  86. result:=0;
  87. exit;
  88. end;
  89. pfh:=PImageFileHeader(ibase + DWORD(mzhead^._lfanew) + Sizeof(DWORD));
  90. poh:=PImageOptionalHeader(ibase + DWORD(mzhead^._lfanew) + Sizeof(DWORD)+ sizeof(IMAGE_FILE_HEADER) );
  91. if poh^.Magic<> $10b then
  92. begin
  93. result:=0;
  94. exit;
  95. end;
  96. psh:=PImageSectionHeader( ibase + DWORD(mzhead^._lfanew) + Sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + Sizeof(IMAGE_OPTIONAL_HEADER) ) ;
  97. result:=1;
  98. end;
  99. //搜索函数名称
  100. procedure FindExport();
  101. var
  102. pfh:PImageFileHeader;
  103. poh:PImageOptionalHeader;
  104. psh:PImageSectionHeader;
  105. ped:PImageExportDirectory;
  106. arrayOfFunctionNames:PArray;
  107. arrayOfFunctionAddresses:PArray;
  108. arrayOfFunctionOrdinals: PWordArray;
  109. functionOrdinal,functionAddress:DWORD;
  110. hNtdll:THandle;
  111. i:integer;
  112. funcName: PChar;
  113. number:Word;
  114. begin
  115. hNtdll:=GetModuleHandle('ntdll.dll');
  116. GetHeaders(PCHAR(hNtdll),pfh,poh,psh);
  117. if(poh^.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress<>0) then
  118. begin
  119.   ped:= PImageExportDirectory( poh^.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + pchar(hNtdll) );
  120.   arrayOfFunctionNames:= PArray( hNtdll+ DWORD(ped^.AddressOfNames));
  121.   arrayOfFunctionAddresses:= PArray(hNtdll+ DWORD(ped^.AddressOfFunctions));
  122.   arrayOfFunctionOrdinals:=   PWordArray(hNtdll+ WORD(ped^.AddressOfNameOrdinals));
  123. end;
  124. SetLength(ssdt_list,ped^.NumberOfNames);
  125. for i:= 0 to ped^.NumberOfNames -1 do
  126. begin
  127.   funcName:=PCHAR(hNtdll+ arrayOfFunctionNames[i]);
  128.   functionOrdinal :=  arrayOfFunctionOrdinals[i] + ped^.Base - 1;
  129.   functionAddress:= DWORD( hNtdll + arrayOfFunctionAddresses[functionOrdinal]);
  130.   if (Copy(funcName,1,2)='Nt') then
  131.   begin
  132.     number:=(PWORD(functionAddress+1))^;
  133.     if (number>ped^.NumberOfNames) then continue;
  134.      ssdt_list[number].fname:=StrPas(funcName);
  135.     //messagebox(0,pchar(inttostr(number)+'  '+StrPas(funcName)),'sad',0);
  136.   end;
  137. end;
  138. end;
  139. // 根据 KeServiceDescriptorTable 的RVA查找 KiServiceTable
  140. function FindKiServiceTable(hModule:HMODULE ;dwKSDT:DWORD):DWORD;
  141. var
  142. pfh:PImageFileHeader;
  143. poh:PImageOptionalHeader;
  144. psh:PImageSectionHeader;
  145. pbr:PImageBaseRelocation;
  146. pfe:PWORD;
  147. i,dwPointerRva,dwPointsToRva,dwKiServiceTable:DWORD;
  148. bFirstChunk:BOOL;
  149. begin
  150.   GetHeaders(PCHAR(hModule),pfh,poh,psh);
  151. if (poh^.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress<>0) then
  152. begin
  153.     pbr:=PImageBaseRelocation(POINTER(DWORD(hModule)+DWORD(poh^.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)));
  154.     bFirstChunk:=TRUE;
  155.     while(bFirstChunk or (pbr^.VirtualAddress<>0)) do
  156.     begin
  157.       bFirstChunk:=FALSE;
  158.       pfe:=PWORD(DWORD(pbr)+sizeof(TImageBaseRelocation)) ;
  159.       for i:=0 to ((pbr^.SizeOfBlock-sizeof(TImageBaseRelocation)) shr 1)-1 do
  160.       begin
  161.         if(( (pfe^ and $F000) shr 12 ) = 3 ) then
  162.         begin
  163.          dwPointerRva:=pbr^.VirtualAddress + (pfe^ and $0FFF);
  164.          dwPointsToRva:=(PDWORD(DWORD(hModule)+dwPointerRva))^ - DWORD(poh^.ImageBase);
  165.          if (dwPointsToRva=dwKSDT)  then
  166.          begin
  167.           //这里要具体分析一下
  168.           if((PWORD(DWORD(hModule)+dwPointerRva-2))^=$05c7)  then
  169.           begin
  170.           dwKiServiceTable:=(PDWORD(DWORD(hModule) + dwPointerRva +4))^ - poh^.ImageBase;
  171.           Result:= dwKiServiceTable;
  172.           EXIT;
  173.           end;
  174.          end;
  175.         end;
  176.        pfe:=PWORD(DWORD(pfe)+sizeof(WORD));
  177.       end;
  178.       (PDWORD(@pbr))^ := (PDWORD(@pbr))^ + pbr^.SizeOfBlock;
  179.     end;
  180. end;
  181.   result:=0;
  182. end;
  183. procedure GetSSDT();
  184. var
  185. hKernel: HMODULE    ;
  186. pKernelName: PCHAR ;
  187. pService:PDWORD ;
  188. pfh:PImageFileHeader;
  189. poh:PImageOptionalHeader;
  190. psh:PImageSectionHeader;
  191. n:ULONG;
  192. P:PULONG;
  193. module,s:PModuleInformation;
  194. nowaddress:PDWORD;
  195. QueryBuff: TMEMORY_CHUNKS;
  196. ReturnLength:DWORD;
  197. i,j:integer;
  198. begin
  199.   ZwQuerySystemInformation(11,0,0,@n); //查询长度
  200.   GetMem(p,sizeof(ULONG)*n); //分配空间
  201.   ZwQuerySystemInformation(11,p,n*sizeof(ULONG),nil);   //通过长度查询内容
  202.   module:= PModuleInformation(PULONG(Ulong(p)+sizeof(ULONG)));
  203.   dwKernelBase:=DWORD(module^.Base);
  204.   pKernelName:=pchar(module^.ImageName+module^.ModuleNameOffset);
  205.   hKernel:=LoadLibraryEx(pKernelName,0,DONT_RESOLVE_DLL_REFERENCES);
  206.    // map ntoskrnl - hopefully it has relocs
  207.   if  hKernel=0 then
  208.   begin
  209.   exit;
  210.   end;
  211.   dwKSDT:=DWORD(GetProcAddress(hKernel,'KeServiceDescriptorTable'));
  212.   if  dwKSDT=0 then
  213.   begin
  214.   exit;
  215.   end;
  216.   //得到KeServiceDescriptorTable的相对偏移
  217.   dwKSDT:=dwKSDT-DWORD(hKernel);
  218.   dwKiServiceTable:=FindKiServiceTable(hKernel,dwKSDT);
  219.   GetHeaders(PCHAR(hKernel),pfh,poh,psh);
  220.   dwServices:=0;
  221.   pService:=PDWORD((DWORD(hKernel)+dwKiServiceTable));
  222.   while ( (pService^- poh^.ImageBase)<poh^.SizeOfImage ) do
  223.   begin
  224.   ssdt_list[dwServices].address1:=pService^ - poh^.ImageBase + dwKernelBase;//dwKernelBase查询的模块地址
  225.   pService:=PDWORD(DWORD(pService)+sizeof(DWORD));
  226.   inc(dwServices);
  227.   end;
  228.   FreeLibrary(hKernel);
  229.    GetMem(nowaddress,sizeof(DWORD)* dwServices);
  230.    QueryBuff.Address:=  dwKernelBase+dwKiServiceTable;
  231.    QueryBuff.Data:= nowaddress;
  232.    QueryBuff.Length:=sizeof(DWORD)* dwServices;
  233.   ZwSystemDebugControl(SysDbgReadVirtualMemory,
  234.                        @QueryBuff,
  235.                        sizeof(QueryBuff),
  236.                        nil,
  237.                        0,
  238.                        @ReturnLength);
  239.    // messagebox(0,pchar(inttohex(Ulong(QueryBuff),4)),'lk',0);
  240. //把结果输出来
  241. form1.ListView1.Clear;
  242. i:=0;
  243. while(i<dwServices) do
  244. begin
  245.   form1.ListView1.Items.Add;
  246.   form1.ListView1.Items.Item[i].Caption:='0x'+inttohex(i,2);
  247.   form1.ListView1.Items.Item[i].SubItems.add( ssdt_list[i].fname);
  248.   form1.ListView1.Items.Item[i].SubItems.add('0x'+inttohex(ssdt_list[i].address1,4));
  249.   ssdt_list[i].address2:= nowaddress^;
  250.   form1.ListView1.Items.Item[i].SubItems.add('0x'+inttohex(ssdt_list[i].address2,4));
  251.   nowaddress:=PDWORD(DWORD(nowaddress)+sizeof(DWORD));
  252.   s:=module;
  253.    //搜索模块
  254.    for j:=0 to p^-1 do
  255.    begin
  256.     if(ssdt_list[i].address2>DWORD(s^.Base)) and (ssdt_list[i].address2<DWORD(s^.Base+ s^.Size) )  then
  257.      begin
  258.        form1.Listview1.Items.Item[i].SubItems.add(s^.ImageName);
  259.        break;
  260.     end;
  261.     s:=PModuleInformation(DWORD(module)+sizeof(TModuleInformation)*J);
  262.   end;
  263.   inc(i);
  264. end;
  265.     FreeMem(p);
  266. end;
  267. //使用 ZwSystemDebugControl前必须提权
  268. function DebugPrivilege(PName:PCHAR;bEnable:BOOL):BOOL;
  269. var
  270. Ok:BOOL;
  271. hToken:THANDLE;
  272. tp,tkpo:  TTokenPrivileges;
  273. lBufferNeeded:DWORD;
  274. begin
  275. if (OpenProcessToken(GetCurrentProcess,TOKEN_QUERY or TOKEN_ADJUST_PRIVILEGES,hToken)) then
  276. begin
  277.   tp.PrivilegeCount:=1;
  278.   if  bEnable then
  279.   tp.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;
  280.   LookupPrivilegeValue(nil,PName,tp.Privileges[0].Luid);
  281.   AdjustTokenPrivileges(hToken, False, tp, Sizeof(TOKEN_PRIVILEGES), TKPO, lBufferNeeded);
  282.   if  GetLastError()=ERROR_SUCCESS then
  283.   begin
  284.       ok:=false;
  285.       Exit;
  286.   end ;
  287.   CloseHandle(hToken);
  288.   result:=ok;
  289. end;
  290. end;
复制代码

SSDTView(Ring3).rar

212 KB, 下载次数: 678

Rank: 2

发表于 2010-4-19 14:04:12 |显示全部楼层
可以写一个VC的吗?

Rank: 1

发表于 2010-4-19 14:05:59 |显示全部楼层
就是通过ring3下用ZwSystemDebugControl获取和恢复SSDT这个c代码改过来的,你到网上去收一下,很多

Rank: 9Rank: 9Rank: 9

发表于 2010-4-19 15:01:09 |显示全部楼层
代码用[Code][/Code]包起来比较好看
悟空,退下,为师一个人就够了

Rank: 1

发表于 2010-4-19 17:07:32 |显示全部楼层
谢谢xIkUg 哥

Rank: 1

发表于 2010-4-20 00:48:51 |显示全部楼层
这个早就有了

Rank: 3Rank: 3

发表于 2010-4-20 11:06:27 |显示全部楼层
这个要支持的

Rank: 1

发表于 2010-4-21 13:56:41 |显示全部楼层
shadowssdt
delphi和vb代码,别人的

Shadow+SSDT--vb原版.rar

400 KB, 下载次数: 502

枚举shadowssdt--delphi 翻译版.rar

15 KB, 下载次数: 888

Rank: 1

发表于 2010-5-7 16:31:38 |显示全部楼层
学习

Rank: 1

发表于 2010-8-28 20:54:37 |显示全部楼层
下下来看看,谢谢分享

Rank: 1

发表于 2010-9-1 17:14:48 |显示全部楼层
谢谢 真是不错

Rank: 2

发表于 2010-10-18 13:21:04 |显示全部楼层
学习

Rank: 1

发表于 2013-5-4 16:30:21 |显示全部楼层
学习
您需要登录后才可以回帖 登录 | 立即加入

Archiver|手机版|第8个男人 - 论坛为只读模式,仅供查阅

GMT+8, 2019-7-21 12:55 , Processed in 0.041324 second(s), 11 queries .

Design by pvo.cn

© 2011 Pvo Inc.

回顶部