﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-zzw-文章分类-安全</title><link>http://www.cppblog.com/zzw/category/7082.html</link><description>他们的秘密，也许只有天上的鸟和水里的鱼知道……</description><language>zh-cn</language><lastBuildDate>Tue, 27 May 2008 18:31:40 GMT</lastBuildDate><pubDate>Tue, 27 May 2008 18:31:40 GMT</pubDate><ttl>60</ttl><item><title>简单说说SSDT by 云舒</title><link>http://www.cppblog.com/zzw/articles/51256.html</link><dc:creator>zzw</dc:creator><author>zzw</author><pubDate>Tue, 27 May 2008 03:40:00 GMT</pubDate><guid>http://www.cppblog.com/zzw/articles/51256.html</guid><wfw:comment>http://www.cppblog.com/zzw/comments/51256.html</wfw:comment><comments>http://www.cppblog.com/zzw/articles/51256.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zzw/comments/commentRss/51256.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zzw/services/trackbacks/51256.html</trackback:ping><description><![CDATA[论技术，我还差得远，而且网上关于SSDT的文章也多不胜数。但是还是想自己写一下，因为我想试试我能不能用最简单的语言来描述SSDT——这个对一般来人来说比较神秘的属于内核的地带。引用EVA说的一句话，&#8220;以为写个驱动就是内核，还远着了&#8221;——大概是这么个意思，记得不是很清楚。 <br><br>关于SSDT，描述得最清楚的应该算《SSDT Hook的妙用－对抗ring0 inline hook》一文了，作者是堕落天才。这里引用一下他写的开头部分，略有个别字符的修改： <br><br>内核中有两个系统服务描述符表，一个是KeServiceDescriptorTable，由ntoskrnl.exe导出，一个是KeServieDescriptorTableShadow，没有导出。这两者都是一个结构体，结构下面会给出。他们的区别是，KeServiceDescriptorTable仅有 ntoskrnel一项，而KeServieDescriptorTableShadow则包含了ntoskrnel和win32k。一般的Native API的服务地址由KeServiceDescriptorTable分派，而gdi.dll和 <br>user.dll的内核API调用服务地址，由 KeServieDescriptorTableShadow分派。还有要清楚一点的是win32k.sys只有在GUI线程中才加载，一般情况下是不加载的。 <br><br>他们的结构如下： <br><strong>代码:</strong>
<table cellSpacing=1 cellPadding=5 width="100%" align=center bgColor=#d5d5d5 border=0>
    <tbody>
        <tr>
            <td style="WORD-BREAK: break-all" bgColor=#efefef><font color=#0000ff><br>typedef struct _SYSTEM_SERVICE_TABLE <br>{ <br>&nbsp;&nbsp;&nbsp;&nbsp;PVOID ServiceTableBase;&nbsp;&nbsp;&nbsp;&nbsp;//这个指向系统服务函数地址表 <br>&nbsp;&nbsp;&nbsp;&nbsp;PULONG ServiceCounterTableBase; <br>&nbsp;&nbsp;&nbsp;&nbsp;ULONG NumberOfService; &nbsp;&nbsp;&nbsp;&nbsp;//服务函数的个数,NumberOfService*4 就是整个地址表的大小 <br>&nbsp;&nbsp;&nbsp;&nbsp;ULONG ParamTableBase; <br>}SYSTEM_SERVICE_TABLE,*PSYSTEM_SERVICE_TABLE; <br><br>typedef struct _SERVICE_DESCRIPTOR_TABLE <br>{ <br>&nbsp;&nbsp;&nbsp;&nbsp;SYSTEM_SERVICE_TABLE ntoskrnel;&nbsp;&nbsp;&nbsp;&nbsp;//ntoskrnl.exe的服务函数 <br>&nbsp;&nbsp;&nbsp;&nbsp;SYSTEM_SERVICE_TABLE win32k;&nbsp;&nbsp;&nbsp;&nbsp;//win32k.sys的服务函数,(gdi.dll/user.dll的内核支持) <br>&nbsp;&nbsp;&nbsp;&nbsp;SYSTEM_SERVICE_TABLE NotUsed1; <br>&nbsp;&nbsp;&nbsp;&nbsp;SYSTEM_SERVICE_TABLE NotUsed2; <br>}SYSTEM_DESCRIPTOR_TABLE,*PSYSTEM_DESCRIPTOR_TABLE; <br></font></td>
        </tr>
    </tbody>
</table>
<br><br>当系统需要使用一个本机API的时候，就会去查找SYSTEM_DESCRIPTOR_TABLE这个表，也就是由ntoskrnl.exe导出的KeServiceDescriptorTable： <br><br><strong>代码:</strong>
<table cellSpacing=1 cellPadding=5 width="100%" align=center bgColor=#d5d5d5 border=0>
    <tbody>
        <tr>
            <td style="WORD-BREAK: break-all" bgColor=#efefef><font color=#0000ff><br>nt!RtlpBreakWithStatusInstruction: <br>80527fc8 cc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp; 3 <br>kd&gt; dd KeServiceDescriptorTable <br>80553380&nbsp;&nbsp;805021fc 00000000 0000011c 80502670 <br>80553390&nbsp;&nbsp;00000000 00000000 00000000 00000000 <br>805533a0&nbsp;&nbsp;00000000 00000000 00000000 00000000 <br>805533b0&nbsp;&nbsp;00000000 00000000 00000000 00000000 <br>805533c0&nbsp;&nbsp;00002710 bf80c227 00000000 00000000 <br>805533d0&nbsp;&nbsp;f9e6da80 f963a9e0 816850f0 806e0f40 <br>805533e0&nbsp;&nbsp;00000000 00000000 00000000 00000000 <br>805533f0&nbsp;&nbsp;97c5ac40 01c7abf5 00000000 00000000 <br></font></td>
        </tr>
    </tbody>
</table>
<br>可以看到，KeServiceDescriptorTable的地址是80553380。现在看看这个地址保存的是什么，因为这个地址的值就是SYSTEM_SERVICE_TABLE的起始地址。好了，我们看到这个地址保存的是805021fc，那么也就是说，系统服务的地址表起始地址为805021fc了。看看这个表是些什么鬼东西： <br><strong>代码:</strong>
<table cellSpacing=1 cellPadding=5 width="100%" align=center bgColor=#d5d5d5 border=0>
    <tbody>
        <tr>
            <td style="WORD-BREAK: break-all" bgColor=#efefef><font color=#0000ff><br>kd&gt; dd 805021fc <br>805021fc&nbsp;&nbsp;80599746 805e6914 805ea15a 805e6946 <br>8050220c&nbsp;&nbsp;805ea194 805e697c 805ea1d8 805ea21c <br>8050221c&nbsp;&nbsp;8060b880 8060c5d2 805e1cac 805e1904 <br>8050222c&nbsp;&nbsp;805ca928 805ca8d8 8060bea6 805ab334 <br>8050223c&nbsp;&nbsp;8060b4be 8059dbbc 805a5786 805cc406 <br>8050224c&nbsp;&nbsp;804ffed0 8060c5c4 8056be64 805353f2 <br>8050225c&nbsp;&nbsp;80604b90 805b19c0 805ea694 80619a56 <br>8050226c&nbsp;&nbsp;805eeb86 80599e34 80619caa 805996e6 <br></font></td>
        </tr>
    </tbody>
</table>
<br>这个过程是这样的，最开始是SYSTEM_DESCRIPTOR_TABLE（80553380）保存了SYSTEM_SERVICE_TABLE的地址（805021fc），SYSTEM_SERVICE_TABLE的地址（805021fc）又保存了很多地址，这个地址就是系统服务的地址了，类似NtOpenProcess这样的ring0的函数地址。这样，系统就可以方便的找到每一个ring0函数去调用。 <br><br>我们先看看第一个地址80599746是个什么函数，反汇编一下： <br><strong>代码:</strong>
<table cellSpacing=1 cellPadding=5 width="100%" align=center bgColor=#d5d5d5 border=0>
    <tbody>
        <tr>
            <td style="WORD-BREAK: break-all" bgColor=#efefef><font color=#0000ff><br>kd&gt; u 80599746 <br>nt!NtAcceptConnectPort: <br>80599746 689c000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;&nbsp;9Ch <br>8059974b 6820a14d80&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;&nbsp;offset nt!_real+0x128 (804da120) <br>80599750 e8abebf9ff&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;call&nbsp;&nbsp;&nbsp;&nbsp;nt!_SEH_prolog (80538300) <br>80599755 64a124010000&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp; eax,dword ptr fs:[00000124h] <br>8059975b 8a8040010000&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp; al,byte ptr [eax+140h] <br>80599761 884590&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp; byte ptr [ebp-70h],al <br>80599764 84c0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;test&nbsp;&nbsp;&nbsp;&nbsp;al,al <br>80599766 0f84b9010000&nbsp;&nbsp;&nbsp;&nbsp;je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nt!NtAcceptConnectPort+0x1df (80599925) <br></font></td>
        </tr>
    </tbody>
</table>
<br>原来是NtAcceptConnectPort函数，第二个805e6914呢？我们也看一下， <br><strong>代码:</strong>
<table cellSpacing=1 cellPadding=5 width="100%" align=center bgColor=#d5d5d5 border=0>
    <tbody>
        <tr>
            <td style="WORD-BREAK: break-all" bgColor=#efefef><font color=#0000ff><br>kd&gt; u 805e6914 <br>nt!NtAccessCheck: <br>805e6914 8bff&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp; edi,edi <br>805e6916 55&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;&nbsp;ebp <br>805e6917 8bec&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp; ebp,esp <br>805e6919 33c0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xor&nbsp;&nbsp;&nbsp;&nbsp; eax,eax <br>805e691b 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;&nbsp;eax <br>805e691c ff7524&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;&nbsp;dword ptr [ebp+24h] <br>805e691f ff7520&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;&nbsp;dword ptr [ebp+20h] <br>805e6922 ff751c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;push&nbsp;&nbsp;&nbsp;&nbsp;dword ptr [ebp+1Ch] <br></font></td>
        </tr>
    </tbody>
</table>
<br>原来是NtAccessCheck函数。 <br><br>这样我们可以清楚的看到，在这个起始地址为0x805021fc的表中，保存了各个ring0函数的地址。下面我来做个简单的比喻。 <br><br>从前有一个很大的帮派，名字叫做Windows，功能很多并且很强大。因为这些各方面的能力由各个专人负责，他们一个人做一件事情。随着人员增多，帮主发现联系起来越来越困了。有一天帮主要找竟然NtOpenProcess来调查一下他的一个手下是不是别的帮派派来的间谍，但是他发现NtOpenProcess跑不见了。 <br><br>于是军师就想出了一个好办法来解决这个问题：先建立一个封闭的密室，这个密室只有八袋长老以上的人才能进去。密室中间有一张纸条，上面写着一个地址——温家堡，还有这个地址放着多少人的联系信息等内容。这个密室就是Ntdll.dll，这个纸条就是SYSTEM_DESCRIPTOR_TABLE，上写的地址就是SYSTEM_SERVICE_TABLE，也就是温家堡了。这个温家堡是一个有很多大房间的地方，每个房子有个房间号 <br>，房间里面又放着一张纸条，上面写着各个手下的住所。比如说编号为7A的房间，里面放的是NtOpenProcess的家庭住址。 <br><br>这样一来，帮主要找人就容易了。先去密室找到纸条，看看上面写的是温家堡还是白云城，那个地方有多少个人的联系信息等。如果是温家堡就跑到那里去，看看要找谁，找NtOpenProcess就去7A房间。在这个房间里一看，啊，里面写着NtOpenProcess现在就住在密室的旁边&#8230;&#8230;搞定。 <br><br>这里就有一个新的问题，帮主假设这个里面写的东西都是正确的，没有被人改过。于是就有了别派的间谍发现了，偷偷溜进密室，然后根据纸条的内容，又跑到温家堡。进到7A房间，神不知鬼不觉的把里面记录的NtOpenProcess的地址改成了自己的家。于是，帮主再找人，发现找到对头家里去了。这个就是传说中的SSDT Hook了。 <br><br>攻击者进入ring0之后，找到KeServiceDescriptorTable地址的值，即SYSTEM_SERVICE_TABLE的地址（进入密室，找到纸条写的地址——温家堡）。然后改写SYSTEM_SERVICE_TABLE中一个特定函数的地址为自己定义的函数入口处，截获了系统调用（来到温家堡，改掉7A房间里面写的住所，改成自己家）。一次HOOK就完成了。 <br><br>下面我给一段简单的代码，演示怎么样让一个特定的PID不会被杀死。这段代码基本和《SSDT Hook的妙用－对抗ring0 inline hook》一文一样，我只是注释了一下而已，另外在MyNtOpenProcess处加了个判断是不是某个特定PID的功能。 <br><strong>代码:</strong>
<table cellSpacing=1 cellPadding=5 width="100%" align=center bgColor=#d5d5d5 border=0>
    <tbody>
        <tr>
            <td style="WORD-BREAK: break-all" bgColor=#efefef><font color=#0000ff><br><br>/* <br>演示HOOK系统服务调用表中的NtOpenProcess函数，保护需要保护的进程被，防止被杀掉 <br>*/ <br><br>#include&lt;ntddk.h&gt; <br><br>/* <br>KeServiceDescriptorTable仅有ntoskrnel一项，没有包含win32k，而且后面的两个字段都没有使用，所 <br><br>以为了简便直接把SystemServiceDescriptorTable定义成SYSTEM_SERVICE_TABLE，免得访问多个结构体的 <br><br>字段，麻烦。这里明白就行了。 <br>*/ <br>typedef struct _SystemServiceDescriptorTable <br>{ <br>&nbsp;&nbsp;&nbsp;&nbsp;PVOID&nbsp;&nbsp;&nbsp;&nbsp;ServiceTableBase; <br>&nbsp;&nbsp;&nbsp;&nbsp;PULONG&nbsp;&nbsp;&nbsp;&nbsp;ServiceCounterTableBase; <br>&nbsp;&nbsp;&nbsp;&nbsp;ULONG&nbsp;&nbsp;&nbsp;&nbsp;NumberOfService; <br>&nbsp;&nbsp;&nbsp;&nbsp;ULONG&nbsp;&nbsp;&nbsp;&nbsp;ParamTableBase; <br>}SystemServiceDescriptorTable,*PSystemServiceDescriptorTable; <br><br>// KeServiceDescriptorTable为ntoskrnl.exe导出 <br>extern&nbsp;&nbsp;&nbsp;&nbsp;PSystemServiceDescriptorTable&nbsp;&nbsp;&nbsp;&nbsp;KeServiceDescriptorTable; <br><br>// 定义一下NtOpenProcess的原型，下面如果用汇编调用就不用定义了，但是我想尽量不用汇编 <br>typedef&nbsp;&nbsp;&nbsp;&nbsp;NTSTATUS&nbsp;&nbsp;&nbsp;&nbsp;(__stdcall *NTOPENPROCESS)( OUT PHANDLE ProcessHandle, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br><br>IN ACCESS_MASK AccessMask, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br><br>IN POBJECT_ATTRIBUTES ObjectAttributes, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br><br>IN PCLIENT_ID ClientId <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br><br>); <br><br>NTOPENPROCESS&nbsp;&nbsp;&nbsp;&nbsp;RealNtOpenProcess; <br><br>// 定义函数原型 <br>VOID Hook(); <br>VOID Unhook(); <br>VOID OnUnload(IN PDRIVER_OBJECT DriverObject); <br><br>// 真实的函数地址，我们会在自定义的函数中调用 <br>ULONG&nbsp;&nbsp;&nbsp;&nbsp;RealServiceAddress; <br><br>// 需要被驱动保护的进程ID <br>HANDLE&nbsp;&nbsp;&nbsp;&nbsp;MyPID; <br><br>// 自定义的NtOpenProcess函数 <br>NTSTATUS __stdcall MyNtOpenProcess( OUT&nbsp;&nbsp;&nbsp;&nbsp;PHANDLE ProcessHandle, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN&nbsp;&nbsp;&nbsp;&nbsp;ACCESS_MASK DesiredAccess, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN&nbsp;&nbsp;&nbsp;&nbsp;POBJECT_ATTRIBUTES ObjectAttributes, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN&nbsp;&nbsp;&nbsp;&nbsp;PCLIENT_ID ClientId ) <br>{ <br>&nbsp;&nbsp;&nbsp;&nbsp;NTSTATUS&nbsp;&nbsp;&nbsp;&nbsp;rc; <br>&nbsp;&nbsp;&nbsp;&nbsp;ULONG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PID; <br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;//DbgPrint( "NtOpenProcess() called.\n" ); <br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;rc = (NTSTATUS)(NTOPENPROCESS)RealNtOpenProcess( ProcessHandle, DesiredAccess, <br><br>ObjectAttributes, ClientId ); <br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;if( (ClientId != NULL) ) <br>&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PID = (ULONG)ClientId-&gt;UniqueProcess; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//DbgPrint( "%d was opened,Handle is %d.\n", PID, (ULONG)ProcessHandle ); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 如果进程PID是1520，直接返回权限不足，并将句柄设置为空 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if( PID == 1520 ) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint( "Some want to open pid 1520！\n" ); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ProcessHandle = NULL; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rc = STATUS_ACCESS_DENIED; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br>&nbsp;&nbsp;&nbsp;&nbsp;} <br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;return rc; <br>} <br><br>// 驱动入口 <br>NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath ) <br>{ <br>&nbsp;&nbsp;&nbsp;&nbsp;DriverObject-&gt;DriverUnload = OnUnload; <br><br>&nbsp;&nbsp;&nbsp;&nbsp;Hook(); <br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;return STATUS_SUCCESS; <br>} <br><br>// 驱动卸载 <br>VOID OnUnload(IN PDRIVER_OBJECT DriverObject) <br>{ <br>&nbsp;&nbsp;&nbsp;&nbsp;Unhook( ); <br>} <br><br>//&nbsp;&nbsp;此处修改SSDT中的NtOpenProcess服务地址 <br>VOID Hook() <br>{ <br>&nbsp;&nbsp;&nbsp;&nbsp;ULONG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Address; <br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;// 0x7A为Winxp+SP2下NtOpenProcess服务ID号 <br>&nbsp;&nbsp;&nbsp;&nbsp;// Adress是个地址A，这个地址的数据还是一个地址B，这个地址B就是NtOpenProcess的地址了 <br>&nbsp;&nbsp;&nbsp;&nbsp;// (ULONG)KeServiceDescriptorTable-&gt;ServiceTableBase就是温家堡的第一个房间 <br>&nbsp;&nbsp;&nbsp;&nbsp;// Address是第7A个房间。 <br>&nbsp;&nbsp;&nbsp;&nbsp;Address = (ULONG)KeServiceDescriptorTable-&gt;ServiceTableBase + 0x7A * 4; <br><br>&nbsp;&nbsp;&nbsp;&nbsp;// 取得地址A的值，也就是NtOpenProcess服务的地址了，保存原来NtOpenProcess的地址以后恢 <br><br>复用 <br>&nbsp;&nbsp;&nbsp;&nbsp;RealServiceAddress = *(ULONG*)Address; <br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;RealNtOpenProcess = (NTOPENPROCESS)RealServiceAddress; <br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint( "Address of Real NtOpenProcess: 0x%08X\n", RealServiceAddress ); <br><br>&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint(" Address of MyNtOpenProcess: 0x%08X\n", MyNtOpenProcess ); <br><br>&nbsp;&nbsp;&nbsp;&nbsp;// 去掉内存保护 <br>&nbsp;&nbsp;&nbsp;&nbsp;__asm <br>&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cli <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;eax, cr0 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;&nbsp;&nbsp;&nbsp;eax, not 10000h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;cr0, eax <br>&nbsp;&nbsp;&nbsp;&nbsp;} <br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;// 修改SSDT中NtOpenProcess服务的地址 <br>&nbsp;&nbsp; *((ULONG*)Address) = (ULONG)MyNtOpenProcess; <br><br>&nbsp;&nbsp;&nbsp;&nbsp;// 恢复内存保护 <br>&nbsp;&nbsp;&nbsp;&nbsp;__asm <br>&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;eax, cr0 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;or&nbsp;&nbsp;&nbsp;&nbsp;eax, 10000h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;cr0, eax <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sti <br>&nbsp;&nbsp;&nbsp;&nbsp;} <br>} <br><br>////////////////////////////////////////////////////// <br>VOID Unhook() <br>{ <br>&nbsp;&nbsp; ULONG&nbsp;&nbsp; Address; <br>&nbsp;&nbsp; Address = (ULONG)KeServiceDescriptorTable-&gt;ServiceTableBase + 0x7A * 4; <br><br>&nbsp;&nbsp;&nbsp;&nbsp;__asm <br>&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cli <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;eax, cr0 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;&nbsp;&nbsp;&nbsp;eax, not 10000h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;cr0, eax <br>&nbsp;&nbsp;&nbsp;&nbsp;} <br><br>&nbsp;&nbsp;&nbsp;&nbsp;// 还原SSDT <br>&nbsp;&nbsp;&nbsp;&nbsp;*((ULONG*)Address) = (ULONG)RealServiceAddress; <br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;__asm <br>&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;eax, cr0 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;or&nbsp;&nbsp;&nbsp;&nbsp;eax, 10000h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;cr0, eax <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sti <br>&nbsp;&nbsp;&nbsp;&nbsp;} <br><br>&nbsp;&nbsp;&nbsp;&nbsp;DbgPrint("Unhook"); <br>} <br></font></td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cppblog.com/zzw/aggbug/51256.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zzw/" target="_blank">zzw</a> 2008-05-27 11:40 <a href="http://www.cppblog.com/zzw/articles/51256.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>