<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
	xmlns:media="http://search.yahoo.com/mrss/"
>

<channel>
	<title>Raullen &#187; 内核研究</title>
	<atom:link href="http://www.raullen.net/category/%e5%86%85%e6%a0%b8%e7%a0%94%e7%a9%b6/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.raullen.net</link>
	<description>上善若水</description>
	<lastBuildDate>Tue, 20 Jul 2010 17:43:15 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<!-- podcast_generator="podPress/8.8" - maintenance_release="8.8.4" -->
		<copyright>Copyright &#xA9; 2010 Raullen </copyright>
		<managingEditor>admin@raullen.net ()</managingEditor>
		<webMaster>admin@raullen.net ()</webMaster>
		<category>posts</category>
		<itunes:keywords></itunes:keywords>
		<itunes:subtitle></itunes:subtitle>
		<itunes:summary>On the way...</itunes:summary>
		<itunes:author></itunes:author>
		<itunes:category text="Society &amp; Culture"/>
		<itunes:owner>
			<itunes:name></itunes:name>
			<itunes:email>admin@raullen.net</itunes:email>
		</itunes:owner>
		<itunes:block>No</itunes:block>
		<itunes:explicit>no</itunes:explicit>
		<itunes:image href="http://www.raullen.net/wp-content/plugins/podpress/images/powered_by_podpress_large.jpg" />
		<image>
			<url>http://www.raullen.net/wp-content/plugins/podpress/images/powered_by_podpress.jpg</url>
			<title>Raullen</title>
			<link>http://www.raullen.net</link>
			<width>144</width>
			<height>144</height>
		</image>
		<item>
		<title>内核打印字符串 DbgPrint</title>
		<link>http://www.raullen.net/2008/03/16/%e5%86%85%e6%a0%b8%e6%89%93%e5%8d%b0%e5%ad%97%e7%ac%a6%e4%b8%b2-dbgprint/#utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=%25e5%2586%2585%25e6%25a0%25b8%25e6%2589%2593%25e5%258d%25b0%25e5%25ad%2597%25e7%25ac%25a6%25e4%25b8%25b2-dbgprint</link>
		<comments>http://www.raullen.net/2008/03/16/%e5%86%85%e6%a0%b8%e6%89%93%e5%8d%b0%e5%ad%97%e7%ac%a6%e4%b8%b2-dbgprint/#comments</comments>
		<pubDate>Sun, 16 Mar 2008 06:02:55 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[内核研究]]></category>

		<guid isPermaLink="false">http://www.raullen.net/240.html</guid>
		<description><![CDATA[空结尾的字符串，你可以用普通得C语法表示字符串常量    1) DbgPrint(&#8220;Hello World!&#8221;); //直接打印字符串。    2) char variable_string[] = &#8220;Hello World&#8221;;    &#160;&#160; DbgPrint(&#8220;%s&#8221;,variable_string); 
空结尾的宽字符串(WCHAR类型)     WCHAR&#160;&#160;&#160; string_w[] = L&#8220;Hello World!&#8221;;    DbgPrint(&#8220;%ws&#8221;,string_w); 
Unicode串，由UNICODE_STRING结构描述,包含16位字符。&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; typedef&#160;&#160; struct _UNICODE_STRING{    &#160;&#160;&#160;&#160;&#160;&#160; USHORT Length;    &#160;&#160;&#160;&#160;&#160;&#160; USHORT MaximumLength;    [...]]]></description>
		<wfw:commentRss>http://www.raullen.net/2008/03/16/%e5%86%85%e6%a0%b8%e6%89%93%e5%8d%b0%e5%ad%97%e7%ac%a6%e4%b8%b2-dbgprint/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>城里城外看SSDT</title>
		<link>http://www.raullen.net/2008/03/15/%e5%9f%8e%e9%87%8c%e5%9f%8e%e5%a4%96%e7%9c%8bssdt/#utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=%25e5%259f%258e%25e9%2587%258c%25e5%259f%258e%25e5%25a4%2596%25e7%259c%258bssdt</link>
		<comments>http://www.raullen.net/2008/03/15/%e5%9f%8e%e9%87%8c%e5%9f%8e%e5%a4%96%e7%9c%8bssdt/#comments</comments>
		<pubDate>Sat, 15 Mar 2008 12:19:05 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[内核研究]]></category>

		<guid isPermaLink="false">http://www.raullen.net/234.html</guid>
		<description><![CDATA[点这里下载本文的配套代码
引子
2006年，中国互联网上的斗争硝烟弥漫。这时的战场上，先前颇为流行的窗口挂钩、API挂钩、进程注入等技术已然成为昨日黄花，大有逐渐淡出之势；取而代之的，则是更狠毒、更为赤裸裸的词汇：驱动、隐藏进程、Rootkit……
前不久，我不经意翻出自己2005年9月写下的一篇文章《DLL的远程注入技术》，在下面看到了一位名叫L4bm0s的网友说这种技术已经过时了。虽然我也曾想过拟出若干辩解之词聊作应对，不过最终还是作罢了——毕竟，拿出些新的、有技术含量的东西才是王道。于是这一次，李马首度从ring3（应用层）的围城跨出，一跃而投身于ring0（内核层）这一更广阔的天地，便有了这篇《城里城外看SSDT》。——顾名思义，城里和城外的这一墙之隔，就是ring3与ring0的分界。
在这篇文章里，我会用到太多杂七杂八的东西，比如汇编，比如内核调试器，比如DDK。这诚然是一件令我瞻前顾后畏首畏尾的事情——一方面在ring0我不得不依靠这些东西，另一方面我实在担心它们会导致我这篇文章的阅读门槛过高。所以，我决定尽可能少地涉及驱动、内核与DDK，也不会对诸如如何使用内核调试器等问题作任何讲解——你只需要知道我大概在做些什么，这就足够了。
什么是SSDT？
什么是SSDT？自然，这个是我必须回答的问题。不过在此之前，请你打开命令行（cmd.exe）窗口，并输入“dir”并回车——好了，列出了当前目录下的所有文件和子目录。
那么，以程序员的视角来看，整个过程应该是这样的：

由用户输入dir命令。
cmd.exe获取用户输入的dir命令，在内部调用对应的Win32 API函数FindFirstFile、FindNextFile和FindClose，获取当前目录下的文件和子目录。
cmd.exe将文件名和子目录输出至控制台窗口，也就是返回给用户。

到此为止我们可以看到，cmd.exe扮演了一个非常至关重要的角色，也就是用户与Win32 API的交互。——你大概已经可以猜到，我下面要说到的SSDT亦必将扮演这个角色，这实在是一点新意都没有。
没错，你猜对了。SSDT的全称是System Services Descriptor Table，系统服务描述符表。这个表就是一个把ring3的Win32 API和ring0的内核API联系起来的角色，下面我将以API函数OpenProcess为例说明这个联系的过程。
你可以用任何反汇编工具来打开你的kernel32.dll，然后你会发现在OpenProcess中有类似这样的汇编代码：
call ds:NtOpenProcess
这就是说，OpenProcess调用了ntdll.dll的NtOpenProcess函数。那么继续反汇编之，你会发现ntdll.dll中的这个函数很短：
mov eax, 7Ah
mov edx, 7FFE0300h
call dword ptr [edx]
retn 10h

另外，call的一句实质是调用了KiFastSystemCall：
mov edx, esp
sysenter
上面是我的XP Professional sp2中ntdll.dll的反汇编结果，如果你用的是2000系统，那么可能是这个样子：
mov eax, 6Ah
lea edx, [esp+4]
int 2Eh
retn 10h
虽然它们存在着些许不同，但都可以这么来概括：

把一个数放入eax（XP是0&#215;7A，2000是0&#215;6A），这个数值称作系统的服务号。
把参数堆栈指针（esp+4）放入edx。
sysenter或int 2Eh。

好了，你在ring3能看到的东西就到此为止了。事实上，在ntdll.dll中的这些函数可以称作真正的NT系统服务的存根（Stub）函数。分隔ring3与ring0城里城外的这一道叹息之墙，也正是由它们打通的。接下来SSDT就要出场了，come some music。
站在城墙看城外
插一句先，貌似到现在为止我仍然没有讲出来SSDT是个什么东西，真正可以算是“犹抱琵琶半遮面”了。——书接上文，在你调用sysenter或int 2Eh之后，Windows系统将会捕获你的这个调用，然后进入ring0层，并调用内核服务函数NtOpenProcess，这个过程如下图所示。

SSDT在这个过程中所扮演的角色是至关重要的。让我们先看一看它的结构，如下图。

当程序的处理流程进入ring0之后，系统会根据服务号（eax）在SSDT这个系统服务描述符表中查找对应的表项，这个找到的表项就是系统服务函数NtOpenProcess的真正地址。之后，系统会根据这个地址调用相应的系统服务函数，并把结果返回给ntdll.dll中的NtOpenProcess。图中的“SSDT”所示即为系统服务描述符表的各个表项；右侧的“ntoskrnl.exe”则为Windows系统内核服务进程（ntoskrnl即为NT OS KerneL的缩写），它提供了相对应的各个系统服务函数。ntoskrnl.exe这个文件位于Windows的system32目录下，有兴趣的朋友可以反汇编一下。
附带说两点。根据你处理器的不同，系统内核服务进程可能也是不一样的。真正运行于系统上的内核服务进程可能还有ntkrnlmp.exe、ntkrnlpa.exe这样的情况——不过为了统一起见，下文仍统称这个进程为ntoskrnl.exe。另外，SSDT中的各个表项也未必会全部指向ntoskrnl.exe中的服务函数，因为你机器上的杀毒监控或其它驱动程序可能会改写SSDT中的某些表项——这也就是所谓的“挂钩SSDT”——以达到它们的“主动防御”式杀毒方式或其它的特定目的。
KeServiceDescriptorTable
事实上，SSDT并不仅仅只包含一个庞大的地址索引表，它还包含着一些其它有用的信息，诸如地址索引的基地址、服务函数个数等等。ntoskrnl.exe中的一个导出项KeServiceDescriptorTable即是SSDT的真身，亦即它在内核中的数据实体。SSDT的数据结构定义如下：
typedef struct _tagSSDT {
    PVOID pvSSDTBase;
    PVOID pvServiceCounterTable;
    ULONG ulNumberOfServices;
    PVOID pvParamTableBase;
} SSDT, *PSSDT;
其中，pvSSDTBase就是上面所说的“系统服务描述符表”的基地址。pvServiceCounterTable则指向另一个索引表，该表包含了每个服务表项被调用的次数；不过这个值只在Checkd Build的内核中有效，在Free Build的内核中，这个值总为NULL（注：Check/Free是DDK的Build模式，如果你只使用SDK，可以简单地把它们理解为Debug/Release）。ulNumberOfServices表示当前系统所支持的服务个数。pvParamTableBase指向SSPT（System Service Parameter Table，即系统服务参数表），该表格包含了每个服务所需的参数字节数。
下面，让我们开看看这个结构里边到底有什么。打开内核调试器（以kd为例），输入命令显示KeServiceDescriptorTable，如下。
lkd&#62; dd KeServiceDescriptorTable l4
8055ab80 804e3d20 00000000 [...]]]></description>
		<wfw:commentRss>http://www.raullen.net/2008/03/15/%e5%9f%8e%e9%87%8c%e5%9f%8e%e5%a4%96%e7%9c%8bssdt/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
