<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_Zachary.XiaoZhen - 梦想的家园</title><subtitle type="text"/><id>http://feed.cnblogs.com/blog/u/60996/rss</id><updated>2012-03-31T02:27:11Z</updated><author><name>Zachary.XiaoZhen</name><uri>http://www.cnblogs.com/BoyXiao/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BoyXiao/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/60996/rss"/><entry><id>http://www.cnblogs.com/BoyXiao/archive/2012/03/31/2426495.html</id><title type="text">C/C++ SQLite 之基础篇</title><summary type="text">文章目录： 1. 下载 SQLite3 源码： 2. 下载 SQLite3.dll 文件： 3. 生成 SQLite3.lib 文件 ： 4. 生成或者下载 SQLite3 Shell 文件 ： 5. 创建数据库以及数据表： 6. 总结： 1. 下载 SQLite3 源码： ...</summary><published>2012-03-31T02:24:00Z</published><updated>2012-03-31T02:24:00Z</updated><author><name>Zachary.XiaoZhen</name><uri>http://www.cnblogs.com/BoyXiao/</uri></author><link rel="alternate" href="http://www.cnblogs.com/BoyXiao/archive/2012/03/31/2426495.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BoyXiao/archive/2012/03/31/2426495.html"/><content type="html">&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;文章目录：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;1. 下载 SQLite3 源码：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;2. 下载 SQLite3.dll 文件：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;3. 生成 SQLite3.lib 文件 ：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;4. 生成或者下载 SQLite3 Shell 文件 ：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;5. 创建数据库以及数据表：&lt;/strong&gt;&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;6. 总结：&lt;/strong&gt;&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;1. 下载 SQLite3 源码：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;虽然说摆弄 c/c++ 有很长时间了，但是说到用 c/c++ 来摆弄数据库倒还真是没有弄过，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;一直有关数据库的项目似乎都用 .Net 给去 OK 了，就好比 SQLite，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;现在的项目就是用的 SQLite.Net，有什么东西都是用 c# 直接操作 SQLite.Net 了，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而相对底层的东西则使用 c/c++ 完成且封装成 DLL 供 c# 调用就 OK 了。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;不过有的时候自己在写一些小东西的时候，可能也会有些数据需要本地存储的，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;以前为了图个简单，就直接存文件咯，不过要是相对隐私点的东西的话，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;我想还是有个数据库比较好，这不是就有 SQLite3 了嘛，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;注意一下哈，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;SQLite3 是供 c/c++ 代码来使用的，如果是 .Net 的话那就得用 SQLite.Net 了，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;废话少说，进入正题了，首先我们需要下载好 SQLite3 的相关文件，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;官网地址：&lt;a href="http://www.sqlite.org/download.html"&gt;http://www.sqlite.org/download.html&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;我们先下载的是 SQLite3 的源码，下载好后，你可以解压缩出来，然后你就会看到 4 个 C/C++ 文件了。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而我们每次在 C/C++ 中使用 SQLite3 时总是需要其中的头文件 sqlite3.h&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023211761.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023243972.png" width="706" height="504" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023254920.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023275801.png" width="845" height="270" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;2. 下载 SQLite3.dll：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后需要下载的是 SQLite3 的 DLL 文件以及导出库，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;下载完后你可以解压出来，你会发现只有 SQLite3.dll 和 SQLite3.def 两个文件，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023283194.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023308785.png" width="773" height="305" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023319243.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023335174.png" width="781" height="286" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;3. 生成 SQLite3.lib 文件：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;做过 c/c++ DLL 的都知道，.def 文件可以用来定义一个 DLL 中 API 的导出，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;所以我们可以打开 SQLite3.def 看看，里面定义的 API 名称就是 SQLite3.dll 所导出的 API，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而在 C/C++ 中如果你要链接到其他的 DLL 上，你必须要有那个 DLL 的导出库，也就是 .lib 文件，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而我们这里没有导出文件(Lib)怎么办呢?没有那就根据 DLL 和.def 文件来生成一个 .lib 文件不就 OK 了 ~&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;首先将 SQLite3.dll 和 SQLite3.def 文件拷贝到 VS 安装目录下的 Bin 文件夹，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;比如我安装的是 VS2010，且默认安装在 C:\Program Files\ 目录下面，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;那么你就需要将上面的两个文件拷贝到以下目录：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="1" face="Courier New"&gt;&lt;strong&gt;C:\Program Files\Microsoft Visual Studio 10.0\VC\bin&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后打开 Visual Studio 命令提示符，且定位到上面的这个目录，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后输入命令:&lt;font color="#0000ff" size="1"&gt;&lt;strong&gt;lib /def:sqlite3.def /machine:ix86&lt;/strong&gt;&lt;/font&gt;，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后你就会在 Bin 目录下发现已经生成了 SQLite3.lib 文件。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/20120331102334930.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023358847.png" width="681" height="447" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023371190.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023392877.png" width="701" height="338" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;4. 生成或下载 SQLite3 Shell 文件：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;关于这 SQLite3 的 Shell 文件呢，就是用来创建 SQLite3 数据库啊，创建表啊之类的东西，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;说白了就是个 SQLite Admin 的控制台界面，当然咯，控制台这个东西并不怎么好用，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;所以你可以考虑换个其他的带 GUI 的工具来管理你的 SQLite3 数据库。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;有个工具不错，叫 DataBase.Net，什么乱七八糟的数据库它都可以连接上去，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;不过要 .Net Framework 的支持。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;对于这个 SQLite3 的 Shell 文件你可以直接在 SQLite 的官方网站上下载到，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023406333.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023445381.png" width="722" height="420" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023468247.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023484112.png" width="733" height="268" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而后，除了下载 SQLite3 的 Shell 工具外，我们还可以自己编译 SQLite 源代码来生成这个工具，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;前面我们已经下载好了 SQLite3 的源代码，并且源代码里面还有一个叫做 shell.c 的文件，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;其实这个文件就可以用来处理 SQLite3 Shell 命令的，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;所以我们可以直接在 VS2010 下新建一个 Console 项目，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后将源代码里面的 4 个 C\C++ 文件拷贝到项目中，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;然后直接编译，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;你也可以得到 SQLite3 的 Shell 工具 SQLite3.exe。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023491505.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023503325.png" width="356" height="439" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;5. 创建数据库以及数据表：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;这里使用麻烦点的方式，即使用 SQLite3 的 Shell 工具，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;下面的例子呢就是很简单的方式，即使用 SQLite3 的 Shell 工具来创建个 DataBase，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后再创建个 Table，再插入几条记录，查询一下就 OK 了。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;具体命令就看下面的截图就好了：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;首先在命令行下定位到你的 SQLite3.exe 也就是 Shell 程序所在的目录：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;比如我的 SQLite3.exe 所在目录为：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;E:\Code\SQLite\sqlite-shell-win32-x86-3071000&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023518209.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023536375.png" width="727" height="476" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;然后输入命令 sqlite3 testDB.db 从而创建 SQLite 数据库，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023548784.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023554192.png" width="734" height="482" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;然后输入命令 create table testDB_ID(ID int, Number int) 来创建数据表 testDB_ID&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;然后输入命令 ; 从而执行上面的创建表的命令。&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311023572042.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311024007841.png" width="750" height="492" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;执行完这些命令后，在你的 Shell 程序也就是 SQLite3.exe 所在的位置中发现你创建的 testDB.db 数据库了。&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311024025168.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311024043333.png" width="693" height="234" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;其实上面的这种创建数据库的方式太麻烦了，还不如直接用 Database.Net 来做，方便很多，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;比如我用 DataBase.Net 打开我们上面创建的这个 testDB.db 数据库，用这个工具来管理数据库很方便。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311024055710.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201203/201203311024071051.png" width="718" height="412" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;6. 小结：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;好，这篇博文到这里就完了，话说回来上面的文章还真没有讲到什么有用的东西，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;仅仅是一些关于 SQLite 的环境啊之类的流水账记录。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;仅仅是对于那些没有操作过 SQLite3 的小白可能还有点作用，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;当然咯，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;我也还是个小白，所以才做这个文章做个记录。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;下面的篇章就要来写写在 C\C++ 下面对 SQLite 的一些具体的操作了。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;font face="Verdana"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;strong&gt;版权所有，&lt;strong&gt;欢&lt;/strong&gt;迎转载，但转载请注明： 转载自&amp;#160; &lt;/strong&gt;&lt;strong&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/"&gt;&lt;strong&gt;Zachary.XiaoZhen - 梦想的天空&lt;/strong&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/BoyXiao/aggbug/2426495.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/archive/2012/03/31/2426495.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/BoyXiao/archive/2012/02/20/2359273.html</id><title type="text">进程与端口映射</title><summary type="text">文章目录： 1. Demo 效果展示： 2. 进程和端口乱扯淡： 3. 查询进程和端口的 API 的介绍： 4. 根据进程 ID 获得该进程所打开的 TCP 和 UDP 端口： 5. 根据端口号来获得打开该端口号的进程： 6. 小结： 1. Demo 效果展示： ...</summary><published>2012-02-20T05:12:00Z</published><updated>2012-02-20T05:12:00Z</updated><author><name>Zachary.XiaoZhen</name><uri>http://www.cnblogs.com/BoyXiao/</uri></author><link rel="alternate" href="http://www.cnblogs.com/BoyXiao/archive/2012/02/20/2359273.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BoyXiao/archive/2012/02/20/2359273.html"/><content type="html">&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;文章目录：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;1. Demo 效果展示：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;2. 进程和端口乱扯淡：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;3. 查询进程和端口的 API 的介绍：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;4. 根据进程 ID 获得该进程所打开的 TCP 和 UDP 端口：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;5. 根据端口号来获得打开该端口号的进程：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;6. 小结：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;1. Demo 效果展示：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;下面的这个 Demo 我只是用最简单的方式做了个 CUI 界面来演示一下而已，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;支持 Windows XP，Windows Server 2003，Vista，Windows 7 ~&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;并且使用 C++ 来完成的，所以对于博客园里面这么多的 .Net 开发者来说不太友好，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;但是有兴趣的可以将 Demo 改写成 DLL，然后 .Net 程序也就可以进行平台调用了，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;里面所有的封装都很工整，所有改写 DLL 以及平台调用的声明也会很简单，有过平台调用经验的都可以改写的。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;本文的后面我将会把这个 Demo 提供链接下载；&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#9b00d3" size="4" face="Courier New"&gt;&lt;strong&gt;本篇博文 Demo 效果演示：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;&lt;strong&gt;(关于端口的查询操作，你可以使用 netstat 命令行进行查询，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;&lt;strong&gt;也可以使用 TCPView 这个工具来查询，当然还可以使用 360 的流量防火墙里面的网络连接来进行查询)&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;查询指定进程所打开的所有的 TCP 端口：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201202/201202201311338264.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201202/201202201311366610.png" width="753" height="494" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;查询指定进程所打开的所有的 UDP 端口：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201202/201202201311382315.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201202/201202201311414040.png" width="750" height="493" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;查询指定 TCP 端口所属的进程 ID：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201202/201202201311425318.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201202/201202201311457044.png" width="755" height="495" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;查询指定 UDP 端口所属的进程 ID：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201202/201202201311472192.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201202/201202201311499109.png" width="763" height="500" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;2. 进程和端口乱扯淡：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;很久没写博文了，以前跟自己说的，每个月要写那么一两篇还看得下去的博文，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;可是去年春节家里出了些事情给耽搁了 1 个多月，而后人又懒了 1 个多月，所以算下来有 2 个多月没有写博文了。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而后今年过来帮一小哥做了个小东西，主要是用来实现伪造端口、伪造远程地址以及进程内存的保护啊之类的动作。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而后呢就是上面提到的这个小东西中中涉及到了端口的知识，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;一开始嘛，我也是放狗一搜索，然后发现关于端口这一块的东西，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;在 2000、XP、Server 2003 下的资料很多，但惟独到了 Vista 和 7 上面就没什么资料了，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;似乎一下子端口就完了似的，就好比端口的隐藏吧，在 XP 上无数端口隐藏工具，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;应用层的，内核层的都有，但是在 Vista 和 7 上呢就都死绝了(主要是指内核层)，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;没办法，只能够自己去研究了，研究的成果呢，主要分为内核层和应用层的成果，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;当然咯，今天我的这篇博文并不会去介绍内核里面关于端口的什么东西，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而是介绍如何在应用层里面完成端口和进程之间的映射。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="Verdana"&gt;&lt;strong&gt;所谓的进程与端口映射在我来理解，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="Verdana"&gt;&lt;strong&gt;简单点就是假如我知道一个进程，那我就要知道这个进程所打开的所有的端口，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2"&gt;&lt;strong&gt;又假如我知道一个端口，那我就应该知道是哪一个进程打开了这个端口。&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2"&gt;所以要完成端口和进程的映射其实归根结底是一个根据进程查询端口和根据端口查询进程的问题。&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后我稍微解释一下为何到了 Vista 和 7 以后，狗上面的关于端口的资源就锐减了，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;其实原因是这样的，在 Vista 之前，我这里摘抄一点在别人博客上的东西出来：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font style="background-color: #cccccc" color="#000000" size="1" face="Consolas"&gt;Windows Vista 的网络模块较从前发生了很大变化,从而导致很多旧的端口隐藏工具无法使用.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font style="background-color: #cccccc" color="#000000" size="1" face="Consolas"&gt;事实上在 Vista 下 netstat.exe 调用 Iphlpapi.dll 导出的 InternalGetTcpTable2 函数实现对所有打开端口的列举.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font style="background-color: #cccccc" color="#000000" size="1" face="Consolas"&gt;InternalGetTcpTable2 随后调用由 nsi.dll 导出的 NsiAllocateAndGetTable 函数,&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font style="background-color: #cccccc" color="#000000" size="1" face="Consolas"&gt;nsi.dll 则调用 NsiEnumerateObjectsAllParametersEx 向 nsiproxy.sys 发送 Irp 最终转入内核.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font style="background-color: #cccccc" color="#000000" size="1" face="Consolas"&gt;而nsiproxy.sys 又只是对 netio.sy s的简单封装,它最终调用了 netio.sys 导出的内核服务例程.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;上面的这些文字多说无益，大体的意思就是从 Vista 开始，Windows 的网络模块发生了大的变化，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;不过话说回来，上面的这种变化在应用层体会的不多，不过如果做到内核的话，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;你就能够体会到网络层确实变化很大 ~&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;安全焦点上的一篇关于在 Vista 之前的系统上的进程和端口的很古老的文章&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;《再谈进程与端口的映射》：&lt;/strong&gt;&lt;/font&gt;&lt;a href="http://www.xfocus.net/articles/200202/344.html"&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;http://www.xfocus.net/articles/200202/344.html&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;3. 查询进程和端口的 API 介绍：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;好，上面说的有点离题了，这篇博文的目的在应用层而不在内核层，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;所以我们无须去体会 Windows 网络层的这种变化。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;一般来说，要完成进程和端口的映射，我们使用的是由 IPHlpapi.dll 中导出的 API 来完成的，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;在 Vista 之前的操作系统中，要查询进程和端口的信息，容易很多，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;你可以通过调用 IPHlpapi.dll 中导出的下面两个 API 来完成查询 TCP 和 UDP 端口的信息，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;下面的两个 API 分别用来查询 TCP 和 UDP 端口信息，&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;(下面的两个 API 仅适用于 XP 和 Server 2003，在 Vista 以及 7 中，这两个 API 被移除)&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt; &lt;font size="2" face="Courier New"&gt;   &lt;div id="codeSnippetWrapper"&gt;     &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;       &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; DWORD WINAPI AllocateAndGetTcpExTableFromStack(&lt;!--CRLF--&gt;      &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt;   __out         PVOID* ppTcpTable,&lt;!--CRLF--&gt;      &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;   __in          BOOL bOrder,&lt;!--CRLF--&gt;      &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;   __in          HANDLE hHeap,&lt;!--CRLF--&gt;      &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;   __in          DWORD dwFlags,&lt;!--CRLF--&gt;      &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;   __in          DWORD dwFamily&lt;!--CRLF--&gt;      &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; );&lt;!--CRLF--&gt;      &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;      &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt; DWORD WINAPI AllocateAndGetUdpExTableFromStack(&lt;!--CRLF--&gt;      &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;   __out         PVOID* ppUDPTable,&lt;!--CRLF--&gt;      &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;   __in          BOOL bOrder,&lt;!--CRLF--&gt;      &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;   __in          HANDLE hHeap,&lt;!--CRLF--&gt;      &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;   __in          DWORD dwFlags,&lt;!--CRLF--&gt;      &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;   __in          DWORD dwFamily&lt;!--CRLF--&gt;      &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt; );&lt;!--CRLF--&gt;      &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;&lt;/div&gt;  &lt;/div&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;参数说明：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;第一个参数：很显然，为输出参数，带回我们查询到的 TCP 或者 UDP 信息；&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;第二个参数：也很显然，判断输出结果是否排序；&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;第三个参数：指定在哪个 Heap 上分配内存；&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;第四个参数：指定用来控制 Heap 的标识；&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;第四个参数：指定 IP_V4 还是 IP_V6，具体看下面的截图：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201202/20120220131151637.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201202/20120220131153378.png" width="600" height="535" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;不过要完成进程和端口的映射在 Vista 和 7 下确实也没那么容易，至于原因呢，&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/font&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;就是 IPHlpapi.dll 中关于查询进程和端口信息的 API 没有公开，即为 UnDocument API，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;不过我们还是可以通过 UnDocument API 来完成这个查询的工作，具体涉及到下面的两个 API，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;当然，下面的这两个 API 由于是 UnDocumnet API，自然你查什么 MSDN 啊之类都找不到这个 API 的声明的，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;下面的两个 API 分别用来查询 TCP 和 UDP 端口信息，&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000"&gt;//=====================================================================================//&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; &lt;span style="color: #008000"&gt;//Name: DWORD InternalGetTcpTable2()                                                   //&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; &lt;span style="color: #008000"&gt;//                                                                                     //&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; &lt;span style="color: #008000"&gt;//Descripion: 该函数在 Windows Vista 以及 Windows 7 下面效                                    //&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; &lt;span style="color: #008000"&gt;//                                                                                     //&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; &lt;span style="color: #008000"&gt;//=====================================================================================//&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;typedef&lt;/span&gt; DWORD (WINAPI *PFNInternalGetTcpTable2)(&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     PMIB_TCPEXTABLE_VISTA *pTcpTable_Vista,&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     HANDLE heap,&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     DWORD flags&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;     );&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt; &lt;span style="color: #008000"&gt;//=====================================================================================//&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt; &lt;span style="color: #008000"&gt;//Name: DWORD InternalGetUdpTableWithOwnerPid()                                        //&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt; &lt;span style="color: #008000"&gt;//                                                                                     //&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt; &lt;span style="color: #008000"&gt;//Descripion: 该函数在 Windows Vista 以及 Windows 7 下面效                                    //&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt; &lt;span style="color: #008000"&gt;//                                                                                     //&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt; &lt;span style="color: #008000"&gt;//=====================================================================================//&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;typedef&lt;/span&gt; DWORD (WINAPI *PFNInternalGetUdpTableWithOwnerPid)(&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;     PMIB_UDPEXTABLE *pUdpTable,&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;     HANDLE heap,&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;     DWORD flags&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;     );&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;参数说明：&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;第一个参数：pTcpTable_Vista 或者 pUdpTable 则不需要多说，其为输出参数，带回查询到的值；&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;第二个参数：heap 也不需要多说，其指示要从哪个 Heap 上面分配内存；&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;第三个参数：flags 则未知，一般都设置为 1，不过貌似设置为 2 啊之类的好像又多影响不大；&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;4. 根据进程 ID 获得该进程所打开的所有的 TCP 和 UDP 端口：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;废话不多少的，直接上代码来得更加容易，注意下面函数中的 HeapFree 函数的调用，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;因为从函数里面分配了内存，并且函数返回指针带出了这片内存，所以必须在外部释放，否则会造成内存泄露。&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000"&gt;//=======================================================================================//&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; &lt;span style="color: #008000"&gt;//Name: DWORD GetAllPortByProcessId()                                                    //&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; &lt;span style="color: #008000"&gt;//                                                                                       //&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; &lt;span style="color: #008000"&gt;//Descripion: 根据进程 ID 来求出该进程所打开的所有的端口号，并且在 dwAllPort 数组中返回所有端口号 //&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; &lt;span style="color: #008000"&gt;//              其中 dwMaxLen 为数组的长度，函数的返回值为进程所打开的端口的数目                  //&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; &lt;span style="color: #008000"&gt;//              (支持 XP，Server 2003，Vista，Win7)                                       //&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; &lt;span style="color: #008000"&gt;//                                                                                       //&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt; &lt;span style="color: #008000"&gt;//=======================================================================================//&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt; DWORD GetAllPortByProcessId(TcpOrUdp type, DWORD dwProcessId, DWORD * dwAllPort, DWORD dwMaxLen)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;     DWORD dwPortCount = 0;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;     HMODULE hModule = LoadLibraryW(L&lt;span style="color: #006080"&gt;&amp;quot;iphlpapi.dll&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (hModule == NULL)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; dwPortCount;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(type == TcpType)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;         &lt;span style="color: #008000"&gt;// 表明查询的是 UDP 信息&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;         PFNAllocateAndGetTcpExTableFromStack pAllocateAndGetTcpExTableFromStack;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;         pAllocateAndGetTcpExTableFromStack = &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;             (PFNAllocateAndGetTcpExTableFromStack)GetProcAddress(hModule, &lt;span style="color: #006080"&gt;&amp;quot;AllocateAndGetTcpExTableFromStack&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pAllocateAndGetTcpExTableFromStack != NULL)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt;             &lt;span style="color: #008000"&gt;// 表明为 XP 或者 Server 2003 操作系统&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum27"&gt;  27:&lt;/span&gt;             PMIB_TCPEXTABLE pTcpExTable = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum28"&gt;  28:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pAllocateAndGetTcpExTableFromStack(&amp;amp;pTcpExTable, &lt;span style="color: #0000ff"&gt;TRUE&lt;/span&gt;, GetProcessHeap(), 0, AF_INET) != 0)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum29"&gt;  29:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum30"&gt;  30:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pTcpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum31"&gt;  31:&lt;/span&gt;                 {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum32"&gt;  32:&lt;/span&gt;                     HeapFree(GetProcessHeap(), 0, pTcpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum33"&gt;  33:&lt;/span&gt;                 }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum34"&gt;  34:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum35"&gt;  35:&lt;/span&gt;                 FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum36"&gt;  36:&lt;/span&gt;                 hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum37"&gt;  37:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum38"&gt;  38:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; dwPortCount;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum39"&gt;  39:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum40"&gt;  40:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum41"&gt;  41:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (UINT i = 0; i &amp;lt; pTcpExTable-&amp;gt;dwNumEntries; i++)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum42"&gt;  42:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum43"&gt;  43:&lt;/span&gt;                 &lt;span style="color: #008000"&gt;// 过滤掉数据，只获取我们要查询的进程的 Port 信息&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum44"&gt;  44:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(dwProcessId == pTcpExTable-&amp;gt;table[i].dwProcessId)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum45"&gt;  45:&lt;/span&gt;                 {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum46"&gt;  46:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(dwPortCount &amp;lt; dwMaxLen)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum47"&gt;  47:&lt;/span&gt;                     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum48"&gt;  48:&lt;/span&gt;                         dwAllPort[dwPortCount] = ntohs(0x0000FFFF &amp;amp; pTcpExTable-&amp;gt;table[i].dwLocalPort);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum49"&gt;  49:&lt;/span&gt;                         dwPortCount++;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum50"&gt;  50:&lt;/span&gt;                     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum51"&gt;  51:&lt;/span&gt;                 }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum52"&gt;  52:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum53"&gt;  53:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum54"&gt;  54:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pTcpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum55"&gt;  55:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum56"&gt;  56:&lt;/span&gt;                 HeapFree(GetProcessHeap(), 0, pTcpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum57"&gt;  57:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum58"&gt;  58:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum59"&gt;  59:&lt;/span&gt;             FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum60"&gt;  60:&lt;/span&gt;             hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum61"&gt;  61:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum62"&gt;  62:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; dwPortCount;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum63"&gt;  63:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum64"&gt;  64:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum65"&gt;  65:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum66"&gt;  66:&lt;/span&gt;             &lt;span style="color: #008000"&gt;// 表明为 Vista 或者 7 操作系统&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum67"&gt;  67:&lt;/span&gt;             PMIB_TCPEXTABLE_VISTA pTcpExTable = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum68"&gt;  68:&lt;/span&gt;             PFNInternalGetTcpTable2 pInternalGetTcpTable2 = &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum69"&gt;  69:&lt;/span&gt;                 (PFNInternalGetTcpTable2)GetProcAddress(hModule, &lt;span style="color: #006080"&gt;&amp;quot;InternalGetTcpTable2&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum70"&gt;  70:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pInternalGetTcpTable2 == NULL)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum71"&gt;  71:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum72"&gt;  72:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pTcpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum73"&gt;  73:&lt;/span&gt;                 {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum74"&gt;  74:&lt;/span&gt;                     HeapFree(GetProcessHeap(), 0, pTcpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum75"&gt;  75:&lt;/span&gt;                 }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum76"&gt;  76:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum77"&gt;  77:&lt;/span&gt;                 FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum78"&gt;  78:&lt;/span&gt;                 hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum79"&gt;  79:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum80"&gt;  80:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; dwPortCount;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum81"&gt;  81:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum82"&gt;  82:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum83"&gt;  83:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pInternalGetTcpTable2(&amp;amp;pTcpExTable, GetProcessHeap(), 1))&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum84"&gt;  84:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum85"&gt;  85:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pTcpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum86"&gt;  86:&lt;/span&gt;                 {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum87"&gt;  87:&lt;/span&gt;                     HeapFree(GetProcessHeap(), 0, pTcpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum88"&gt;  88:&lt;/span&gt;                 }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum89"&gt;  89:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum90"&gt;  90:&lt;/span&gt;                 FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum91"&gt;  91:&lt;/span&gt;                 hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum92"&gt;  92:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum93"&gt;  93:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; dwPortCount;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum94"&gt;  94:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum95"&gt;  95:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum96"&gt;  96:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (UINT i = 0;i &amp;lt; pTcpExTable-&amp;gt;dwNumEntries; i++)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum97"&gt;  97:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum98"&gt;  98:&lt;/span&gt;                 &lt;span style="color: #008000"&gt;// 过滤掉数据，只获取我们要查询的进程的 TCP Port 信息&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum99"&gt;  99:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(dwProcessId == pTcpExTable-&amp;gt;table[i].dwProcessId)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum100"&gt; 100:&lt;/span&gt;                 {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum101"&gt; 101:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(dwPortCount &amp;lt; dwMaxLen)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum102"&gt; 102:&lt;/span&gt;                     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum103"&gt; 103:&lt;/span&gt;                         dwAllPort[dwPortCount] = ntohs(0x0000FFFF &amp;amp; pTcpExTable-&amp;gt;table[i].dwLocalPort);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum104"&gt; 104:&lt;/span&gt;                         dwPortCount++;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum105"&gt; 105:&lt;/span&gt;                     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum106"&gt; 106:&lt;/span&gt;                 }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum107"&gt; 107:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum108"&gt; 108:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum109"&gt; 109:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pTcpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum110"&gt; 110:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum111"&gt; 111:&lt;/span&gt;                 HeapFree(GetProcessHeap(), 0, pTcpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum112"&gt; 112:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum113"&gt; 113:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum114"&gt; 114:&lt;/span&gt;             FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum115"&gt; 115:&lt;/span&gt;             hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum116"&gt; 116:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum117"&gt; 117:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; dwPortCount;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum118"&gt; 118:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum119"&gt; 119:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum120"&gt; 120:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(type == UdpType)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum121"&gt; 121:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum122"&gt; 122:&lt;/span&gt;         &lt;span style="color: #008000"&gt;// 表明查询的是 UDP 信息&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum123"&gt; 123:&lt;/span&gt;         PMIB_UDPEXTABLE pUdpExTable = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum124"&gt; 124:&lt;/span&gt;         PFNAllocateAndGetUdpExTableFromStack pAllocateAndGetUdpExTableFromStack;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum125"&gt; 125:&lt;/span&gt;         pAllocateAndGetUdpExTableFromStack = &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum126"&gt; 126:&lt;/span&gt;             (PFNAllocateAndGetUdpExTableFromStack)GetProcAddress(hModule,&lt;span style="color: #006080"&gt;&amp;quot;AllocateAndGetUdpExTableFromStack&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum127"&gt; 127:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pAllocateAndGetUdpExTableFromStack != NULL)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum128"&gt; 128:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum129"&gt; 129:&lt;/span&gt;             &lt;span style="color: #008000"&gt;// 表明为 XP 或者 Server 2003 操作系统&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum130"&gt; 130:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pAllocateAndGetUdpExTableFromStack(&amp;amp;pUdpExTable, &lt;span style="color: #0000ff"&gt;TRUE&lt;/span&gt;, GetProcessHeap(), 0, AF_INET) != 0)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum131"&gt; 131:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum132"&gt; 132:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pUdpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum133"&gt; 133:&lt;/span&gt;                 {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum134"&gt; 134:&lt;/span&gt;                     HeapFree(GetProcessHeap(), 0, pUdpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum135"&gt; 135:&lt;/span&gt;                 }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum136"&gt; 136:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum137"&gt; 137:&lt;/span&gt;                 FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum138"&gt; 138:&lt;/span&gt;                 hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum139"&gt; 139:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum140"&gt; 140:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; dwPortCount;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum141"&gt; 141:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum142"&gt; 142:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum143"&gt; 143:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (UINT i = 0; i &amp;lt; pUdpExTable-&amp;gt;dwNumEntries; i++)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum144"&gt; 144:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum145"&gt; 145:&lt;/span&gt;                 &lt;span style="color: #008000"&gt;// 过滤掉数据，只获取我们要查询的进程的 UDP Port信息&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum146"&gt; 146:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(dwProcessId == pUdpExTable-&amp;gt;table[i].dwProcessId)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum147"&gt; 147:&lt;/span&gt;                 {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum148"&gt; 148:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(dwPortCount &amp;lt; dwMaxLen)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum149"&gt; 149:&lt;/span&gt;                     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum150"&gt; 150:&lt;/span&gt;                         dwAllPort[dwPortCount] = ntohs(0x0000FFFF &amp;amp; pUdpExTable-&amp;gt;table[i].dwLocalPort);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum151"&gt; 151:&lt;/span&gt;                         dwPortCount++;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum152"&gt; 152:&lt;/span&gt;                     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum153"&gt; 153:&lt;/span&gt;                 }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum154"&gt; 154:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum155"&gt; 155:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum156"&gt; 156:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pUdpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum157"&gt; 157:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum158"&gt; 158:&lt;/span&gt;                 HeapFree(GetProcessHeap(), 0, pUdpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum159"&gt; 159:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum160"&gt; 160:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum161"&gt; 161:&lt;/span&gt;             FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum162"&gt; 162:&lt;/span&gt;             hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum163"&gt; 163:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum164"&gt; 164:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; dwPortCount;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum165"&gt; 165:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum166"&gt; 166:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum167"&gt; 167:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum168"&gt; 168:&lt;/span&gt;             &lt;span style="color: #008000"&gt;// 表明为 Vista 或者 7 操作系统&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum169"&gt; 169:&lt;/span&gt;             PFNInternalGetUdpTableWithOwnerPid pInternalGetUdpTableWithOwnerPid;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum170"&gt; 170:&lt;/span&gt;             pInternalGetUdpTableWithOwnerPid = &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum171"&gt; 171:&lt;/span&gt;                 (PFNInternalGetUdpTableWithOwnerPid)GetProcAddress(hModule, &lt;span style="color: #006080"&gt;&amp;quot;InternalGetUdpTableWithOwnerPid&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum172"&gt; 172:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pInternalGetUdpTableWithOwnerPid != NULL)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum173"&gt; 173:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum174"&gt; 174:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pInternalGetUdpTableWithOwnerPid(&amp;amp;pUdpExTable, GetProcessHeap(), 1))&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum175"&gt; 175:&lt;/span&gt;                 {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum176"&gt; 176:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pUdpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum177"&gt; 177:&lt;/span&gt;                     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum178"&gt; 178:&lt;/span&gt;                         HeapFree(GetProcessHeap(), 0, pUdpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum179"&gt; 179:&lt;/span&gt;                     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum180"&gt; 180:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum181"&gt; 181:&lt;/span&gt;                     FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum182"&gt; 182:&lt;/span&gt;                     hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum183"&gt; 183:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum184"&gt; 184:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; dwPortCount;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum185"&gt; 185:&lt;/span&gt;                 }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum186"&gt; 186:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum187"&gt; 187:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (UINT i = 0; i &amp;lt; pUdpExTable-&amp;gt;dwNumEntries; i++)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum188"&gt; 188:&lt;/span&gt;                 {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum189"&gt; 189:&lt;/span&gt;                     &lt;span style="color: #008000"&gt;// 过滤掉数据，只获取我们要查询的进程的 UDP Port信息&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum190"&gt; 190:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(dwProcessId == pUdpExTable-&amp;gt;table[i].dwProcessId)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum191"&gt; 191:&lt;/span&gt;                     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum192"&gt; 192:&lt;/span&gt;                         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(dwPortCount &amp;lt; dwMaxLen)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum193"&gt; 193:&lt;/span&gt;                         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum194"&gt; 194:&lt;/span&gt;                             dwAllPort[dwPortCount] = ntohs(0x0000FFFF &amp;amp; pUdpExTable-&amp;gt;table[i].dwLocalPort);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum195"&gt; 195:&lt;/span&gt;                             dwPortCount++;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum196"&gt; 196:&lt;/span&gt;                         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum197"&gt; 197:&lt;/span&gt;                     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum198"&gt; 198:&lt;/span&gt;                 }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum199"&gt; 199:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum200"&gt; 200:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum201"&gt; 201:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pUdpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum202"&gt; 202:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum203"&gt; 203:&lt;/span&gt;                 HeapFree(GetProcessHeap(), 0, pUdpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum204"&gt; 204:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum205"&gt; 205:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum206"&gt; 206:&lt;/span&gt;             FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum207"&gt; 207:&lt;/span&gt;             hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum208"&gt; 208:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum209"&gt; 209:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; dwPortCount;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum210"&gt; 210:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum211"&gt; 211:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum212"&gt; 212:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum213"&gt; 213:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum214"&gt; 214:&lt;/span&gt;         FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum215"&gt; 215:&lt;/span&gt;         hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum216"&gt; 216:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum217"&gt; 217:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; dwPortCount;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum218"&gt; 218:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum219"&gt; 219:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;5. 根据端口号来获得打开该端口的进程：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;同样是直接上代码，同样需要注意下面函数中的 HeapFree 函数的调用，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;因为从函数里面分配了内存，并且函数返回指针带出了这片内存，所以必须在外部释放，否则会造成内存泄露。&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000"&gt;//=====================================================================================//&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; &lt;span style="color: #008000"&gt;//Name: DWORD GetProcessIdByPort()                                                     //&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; &lt;span style="color: #008000"&gt;//                                                                                     //&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; &lt;span style="color: #008000"&gt;//Descripion: 根据端口号求出打开该端口号的进程 ID(支持 XP，Server 2003，Vista，Win7)        //&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; &lt;span style="color: #008000"&gt;//                                                                                     //&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; &lt;span style="color: #008000"&gt;//=====================================================================================//&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; DWORD GetProcessIdByPort(TcpOrUdp type, DWORD dwPort)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     HMODULE hModule = LoadLibraryW(L&lt;span style="color: #006080"&gt;&amp;quot;iphlpapi.dll&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (hModule == NULL)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(type == TcpType)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;         &lt;span style="color: #008000"&gt;// 表明查询的是 TCP 信息&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;         PFNAllocateAndGetTcpExTableFromStack pAllocateAndGetTcpExTableFromStack;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;         pAllocateAndGetTcpExTableFromStack = &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;             (PFNAllocateAndGetTcpExTableFromStack)GetProcAddress(hModule, &lt;span style="color: #006080"&gt;&amp;quot;AllocateAndGetTcpExTableFromStack&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pAllocateAndGetTcpExTableFromStack != NULL)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;             &lt;span style="color: #008000"&gt;// 表明为 XP 或者 Server 2003 操作系统&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;             PMIB_TCPEXTABLE pTcpExTable = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pAllocateAndGetTcpExTableFromStack(&amp;amp;pTcpExTable, &lt;span style="color: #0000ff"&gt;TRUE&lt;/span&gt;, GetProcessHeap(), 0, AF_INET) != 0)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum27"&gt;  27:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pTcpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum28"&gt;  28:&lt;/span&gt;                 {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum29"&gt;  29:&lt;/span&gt;                     HeapFree(GetProcessHeap(), 0, pTcpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum30"&gt;  30:&lt;/span&gt;                 }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum31"&gt;  31:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum32"&gt;  32:&lt;/span&gt;                 FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum33"&gt;  33:&lt;/span&gt;                 hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum34"&gt;  34:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum35"&gt;  35:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum36"&gt;  36:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum37"&gt;  37:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum38"&gt;  38:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (UINT i = 0; i &amp;lt; pTcpExTable-&amp;gt;dwNumEntries; i++)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum39"&gt;  39:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum40"&gt;  40:&lt;/span&gt;                 &lt;span style="color: #008000"&gt;// 过滤掉数据，只查询我们需要的进程数据&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum41"&gt;  41:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(dwPort == ntohs(0x0000FFFF &amp;amp; pTcpExTable-&amp;gt;table[i].dwLocalPort))&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum42"&gt;  42:&lt;/span&gt;                 {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum43"&gt;  43:&lt;/span&gt;                     DWORD dwProcessId = pTcpExTable-&amp;gt;table[i].dwProcessId;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum44"&gt;  44:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pTcpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum45"&gt;  45:&lt;/span&gt;                     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum46"&gt;  46:&lt;/span&gt;                         HeapFree(GetProcessHeap(), 0, pTcpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum47"&gt;  47:&lt;/span&gt;                     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum48"&gt;  48:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum49"&gt;  49:&lt;/span&gt;                     FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum50"&gt;  50:&lt;/span&gt;                     hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum51"&gt;  51:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum52"&gt;  52:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; dwProcessId;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum53"&gt;  53:&lt;/span&gt;                 }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum54"&gt;  54:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum55"&gt;  55:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum56"&gt;  56:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pTcpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum57"&gt;  57:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum58"&gt;  58:&lt;/span&gt;                 HeapFree(GetProcessHeap(), 0, pTcpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum59"&gt;  59:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum60"&gt;  60:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum61"&gt;  61:&lt;/span&gt;             FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum62"&gt;  62:&lt;/span&gt;             hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum63"&gt;  63:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum64"&gt;  64:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum65"&gt;  65:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum66"&gt;  66:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum67"&gt;  67:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum68"&gt;  68:&lt;/span&gt;             &lt;span style="color: #008000"&gt;// 表明为 Vista 或者 7 操作系统&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum69"&gt;  69:&lt;/span&gt;             PMIB_TCPEXTABLE_VISTA pTcpExTable = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum70"&gt;  70:&lt;/span&gt;             PFNInternalGetTcpTable2 pInternalGetTcpTable2 = &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum71"&gt;  71:&lt;/span&gt;                 (PFNInternalGetTcpTable2)GetProcAddress(hModule, &lt;span style="color: #006080"&gt;&amp;quot;InternalGetTcpTable2&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum72"&gt;  72:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pInternalGetTcpTable2 == NULL)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum73"&gt;  73:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum74"&gt;  74:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pTcpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum75"&gt;  75:&lt;/span&gt;                 {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum76"&gt;  76:&lt;/span&gt;                     HeapFree(GetProcessHeap(), 0, pTcpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum77"&gt;  77:&lt;/span&gt;                 }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum78"&gt;  78:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum79"&gt;  79:&lt;/span&gt;                 FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum80"&gt;  80:&lt;/span&gt;                 hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum81"&gt;  81:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum82"&gt;  82:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum83"&gt;  83:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum84"&gt;  84:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum85"&gt;  85:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pInternalGetTcpTable2(&amp;amp;pTcpExTable, GetProcessHeap(), 1))&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum86"&gt;  86:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum87"&gt;  87:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pTcpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum88"&gt;  88:&lt;/span&gt;                 {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum89"&gt;  89:&lt;/span&gt;                     HeapFree(GetProcessHeap(), 0, pTcpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum90"&gt;  90:&lt;/span&gt;                 }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum91"&gt;  91:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum92"&gt;  92:&lt;/span&gt;                 FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum93"&gt;  93:&lt;/span&gt;                 hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum94"&gt;  94:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum95"&gt;  95:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum96"&gt;  96:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum97"&gt;  97:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum98"&gt;  98:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (UINT i = 0;i &amp;lt; pTcpExTable-&amp;gt;dwNumEntries; i++)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum99"&gt;  99:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum100"&gt; 100:&lt;/span&gt;                 &lt;span style="color: #008000"&gt;// 过滤掉数据，只查询我们需要的进程数据&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum101"&gt; 101:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(dwPort == ntohs(0x0000FFFF &amp;amp; pTcpExTable-&amp;gt;table[i].dwLocalPort))&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum102"&gt; 102:&lt;/span&gt;                 {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum103"&gt; 103:&lt;/span&gt;                     DWORD dwProcessId = pTcpExTable-&amp;gt;table[i].dwProcessId;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum104"&gt; 104:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pTcpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum105"&gt; 105:&lt;/span&gt;                     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum106"&gt; 106:&lt;/span&gt;                         HeapFree(GetProcessHeap(), 0, pTcpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum107"&gt; 107:&lt;/span&gt;                     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum108"&gt; 108:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum109"&gt; 109:&lt;/span&gt;                     FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum110"&gt; 110:&lt;/span&gt;                     hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum111"&gt; 111:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum112"&gt; 112:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; dwProcessId;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum113"&gt; 113:&lt;/span&gt;                 }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum114"&gt; 114:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum115"&gt; 115:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum116"&gt; 116:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pTcpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum117"&gt; 117:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum118"&gt; 118:&lt;/span&gt;                 HeapFree(GetProcessHeap(), 0, pTcpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum119"&gt; 119:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum120"&gt; 120:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum121"&gt; 121:&lt;/span&gt;             FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum122"&gt; 122:&lt;/span&gt;             hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum123"&gt; 123:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum124"&gt; 124:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum125"&gt; 125:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum126"&gt; 126:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum127"&gt; 127:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt;(type == UdpType)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum128"&gt; 128:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum129"&gt; 129:&lt;/span&gt;         &lt;span style="color: #008000"&gt;// 表明查询的是 UDP 信息&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum130"&gt; 130:&lt;/span&gt;         PMIB_UDPEXTABLE pUdpExTable = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum131"&gt; 131:&lt;/span&gt;         PFNAllocateAndGetUdpExTableFromStack pAllocateAndGetUdpExTableFromStack;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum132"&gt; 132:&lt;/span&gt;         pAllocateAndGetUdpExTableFromStack = &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum133"&gt; 133:&lt;/span&gt;             (PFNAllocateAndGetUdpExTableFromStack)GetProcAddress(hModule,&lt;span style="color: #006080"&gt;&amp;quot;AllocateAndGetUdpExTableFromStack&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum134"&gt; 134:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pAllocateAndGetUdpExTableFromStack != NULL)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum135"&gt; 135:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum136"&gt; 136:&lt;/span&gt;             &lt;span style="color: #008000"&gt;// 表明为 XP 或者 Server 2003 操作系统&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum137"&gt; 137:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pAllocateAndGetUdpExTableFromStack(&amp;amp;pUdpExTable, &lt;span style="color: #0000ff"&gt;TRUE&lt;/span&gt;, GetProcessHeap(), 0, AF_INET) != 0)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum138"&gt; 138:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum139"&gt; 139:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pUdpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum140"&gt; 140:&lt;/span&gt;                 {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum141"&gt; 141:&lt;/span&gt;                     HeapFree(GetProcessHeap(), 0, pUdpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum142"&gt; 142:&lt;/span&gt;                 }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum143"&gt; 143:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum144"&gt; 144:&lt;/span&gt;                 FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum145"&gt; 145:&lt;/span&gt;                 hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum146"&gt; 146:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum147"&gt; 147:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum148"&gt; 148:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum149"&gt; 149:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum150"&gt; 150:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (UINT i = 0; i &amp;lt; pUdpExTable-&amp;gt;dwNumEntries; i++)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum151"&gt; 151:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum152"&gt; 152:&lt;/span&gt;                 &lt;span style="color: #008000"&gt;// 过滤掉数据，只查询我们需要的进程数据&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum153"&gt; 153:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (dwPort == ntohs(0x0000FFFF &amp;amp; pUdpExTable-&amp;gt;table[i].dwLocalPort))&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum154"&gt; 154:&lt;/span&gt;                 {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum155"&gt; 155:&lt;/span&gt;                     DWORD dwProcessId = pUdpExTable-&amp;gt;table[i].dwProcessId;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum156"&gt; 156:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pUdpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum157"&gt; 157:&lt;/span&gt;                     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum158"&gt; 158:&lt;/span&gt;                         HeapFree(GetProcessHeap(), 0, pUdpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum159"&gt; 159:&lt;/span&gt;                     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum160"&gt; 160:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum161"&gt; 161:&lt;/span&gt;                     FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum162"&gt; 162:&lt;/span&gt;                     hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum163"&gt; 163:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum164"&gt; 164:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; dwProcessId;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum165"&gt; 165:&lt;/span&gt;                 }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum166"&gt; 166:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum167"&gt; 167:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum168"&gt; 168:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pUdpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum169"&gt; 169:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum170"&gt; 170:&lt;/span&gt;                 HeapFree(GetProcessHeap(), 0, pUdpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum171"&gt; 171:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum172"&gt; 172:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum173"&gt; 173:&lt;/span&gt;             FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum174"&gt; 174:&lt;/span&gt;             hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum175"&gt; 175:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum176"&gt; 176:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum177"&gt; 177:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum178"&gt; 178:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum179"&gt; 179:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum180"&gt; 180:&lt;/span&gt;             &lt;span style="color: #008000"&gt;// 表明为 Vista 或者 7 操作系统&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum181"&gt; 181:&lt;/span&gt;             PFNInternalGetUdpTableWithOwnerPid pInternalGetUdpTableWithOwnerPid;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum182"&gt; 182:&lt;/span&gt;             pInternalGetUdpTableWithOwnerPid = &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum183"&gt; 183:&lt;/span&gt;                 (PFNInternalGetUdpTableWithOwnerPid)GetProcAddress(hModule, &lt;span style="color: #006080"&gt;&amp;quot;InternalGetUdpTableWithOwnerPid&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum184"&gt; 184:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pInternalGetUdpTableWithOwnerPid != NULL)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum185"&gt; 185:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum186"&gt; 186:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pInternalGetUdpTableWithOwnerPid(&amp;amp;pUdpExTable, GetProcessHeap(), 1))&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum187"&gt; 187:&lt;/span&gt;                 {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum188"&gt; 188:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pUdpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum189"&gt; 189:&lt;/span&gt;                     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum190"&gt; 190:&lt;/span&gt;                         HeapFree(GetProcessHeap(), 0, pUdpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum191"&gt; 191:&lt;/span&gt;                     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum192"&gt; 192:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum193"&gt; 193:&lt;/span&gt;                     FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum194"&gt; 194:&lt;/span&gt;                     hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum195"&gt; 195:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum196"&gt; 196:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum197"&gt; 197:&lt;/span&gt;                 }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum198"&gt; 198:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum199"&gt; 199:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (UINT i = 0; i &amp;lt; pUdpExTable-&amp;gt;dwNumEntries; i++)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum200"&gt; 200:&lt;/span&gt;                 {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum201"&gt; 201:&lt;/span&gt;                     &lt;span style="color: #008000"&gt;// 过滤掉数据，只查询我们需要的进程数据&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum202"&gt; 202:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (dwPort == ntohs(0x0000FFFF &amp;amp; pUdpExTable-&amp;gt;table[i].dwLocalPort))&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum203"&gt; 203:&lt;/span&gt;                     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum204"&gt; 204:&lt;/span&gt;                         DWORD dwProcessId = pUdpExTable-&amp;gt;table[i].dwProcessId;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum205"&gt; 205:&lt;/span&gt;                         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pUdpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum206"&gt; 206:&lt;/span&gt;                         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum207"&gt; 207:&lt;/span&gt;                             HeapFree(GetProcessHeap(), 0, pUdpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum208"&gt; 208:&lt;/span&gt;                         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum209"&gt; 209:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum210"&gt; 210:&lt;/span&gt;                         FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum211"&gt; 211:&lt;/span&gt;                         hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum212"&gt; 212:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum213"&gt; 213:&lt;/span&gt;                         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; dwProcessId;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum214"&gt; 214:&lt;/span&gt;                     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum215"&gt; 215:&lt;/span&gt;                 }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum216"&gt; 216:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum217"&gt; 217:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum218"&gt; 218:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pUdpExTable)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum219"&gt; 219:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum220"&gt; 220:&lt;/span&gt;                 HeapFree(GetProcessHeap(), 0, pUdpExTable);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum221"&gt; 221:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum222"&gt; 222:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum223"&gt; 223:&lt;/span&gt;             FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum224"&gt; 224:&lt;/span&gt;             hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum225"&gt; 225:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum226"&gt; 226:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum227"&gt; 227:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum228"&gt; 228:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum229"&gt; 229:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum230"&gt; 230:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum231"&gt; 231:&lt;/span&gt;         FreeLibrary(hModule);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum232"&gt; 232:&lt;/span&gt;         hModule = NULL;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum233"&gt; 233:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum234"&gt; 234:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; -1;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum235"&gt; 235:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum236"&gt; 236:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;6. 小结：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;好了，文章就写到这里了，对于那些对端口有兴趣的童鞋，我想这篇文章还是很有帮助的，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;因为在网络上关于这一块的资料真的不多的，不过到最后了还是要提一下，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;就是上面的文章介绍的是在应用层，也就是 Ring3 下的端口的查询以及使用，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;我做过在 Ring0 下的端口隐藏，是通过 Hook NtDeviceIoControlFile 来实现的，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;在 Vista 之前的操作系统中都容易搞定，但是在 Vista 后的操作系统中，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;由于网络模块和之前完全不同了，而且公开的资料又太少，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;所以在 Vista 后的操作系统中的端口隐藏以及端口伪造实现效果很不好，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;不知有同仁是否研究过这一块的东西，有的话，我们可以讨论讨论的 ~&lt;/font&gt; &lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font style="background-color: #cccccc" color="#ff0000" size="3" face="Courier New"&gt;Demo 下载地址：&lt;font style="background-color: #ffffff"&gt; &lt;/font&gt;&lt;a title="http://files.cnblogs.com/BoyXiao/TestPort.zip" href="http://files.cnblogs.com/BoyXiao/TestPort.zip"&gt;&lt;font style="background-color: #ffffff" size="2"&gt;http://files.cnblogs.com/BoyXiao/TestPort.zip&lt;/font&gt;&lt;/a&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;strong&gt;版权所有，&lt;strong&gt;欢&lt;/strong&gt;迎转载，但转载请注明： 转载自&amp;#160; &lt;/strong&gt;&lt;strong&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/"&gt;&lt;strong&gt;Zachary.XiaoZhen - 梦想的天空&lt;/strong&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/BoyXiao/aggbug/2359273.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/archive/2012/02/20/2359273.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/BoyXiao/archive/2011/11/01/2232324.html</id><title type="text">约定 - 王菲</title><summary type="text">还记得当天旅馆的门牌 还留住笑著离开的神态 当天整个城市 那样轻快 沿路一起走半哩长街 还记得街灯照出一脸黄 还燃亮那份微温的便档 剪影的你轮廓太好看 凝住眼泪才敢细看 忘掉天地 彷佛也想不起自己 仍未忘相约看漫天黄叶远飞 就算会与你分...</summary><published>2011-11-01T15:44:00Z</published><updated>2011-11-01T15:44:00Z</updated><author><name>Zachary.XiaoZhen</name><uri>http://www.cnblogs.com/BoyXiao/</uri></author><link rel="alternate" href="http://www.cnblogs.com/BoyXiao/archive/2011/11/01/2232324.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BoyXiao/archive/2011/11/01/2232324.html"/><content type="html">&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;还记得当天旅馆的门牌       &lt;br /&gt;还留住笑著离开的神态        &lt;br /&gt;当天整个城市&amp;#160; 那样轻快        &lt;br /&gt;沿路一起走半哩长街        &lt;br /&gt;还记得街灯照出一脸黄        &lt;br /&gt;还燃亮那份微温的便档        &lt;br /&gt;剪影的你轮廓太好看        &lt;br /&gt;凝住眼泪才敢细看&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;忘掉天地 彷佛也想不起自己        &lt;br /&gt;仍未忘相约看漫天黄叶远飞        &lt;br /&gt;就算会与你分离&amp;#160; 凄绝的戏        &lt;br /&gt;要决心忘记我便记不起        &lt;br /&gt;明日天地&amp;#160; 只恐怕认不出自己        &lt;br /&gt;仍未忘跟你约定假如没有死        &lt;br /&gt;就算你壮阔胸膛 不敌天气        &lt;br /&gt;两鬓斑白都可认得你&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;还记得当天吉他的和弦        &lt;br /&gt;还明白每段旋律的伏线        &lt;br /&gt;当天街角流过你声线        &lt;br /&gt;沿路旅程如歌褪变&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;忘掉天地&amp;#160; 彷佛也想不起自己       &lt;br /&gt;仍未忘相约看漫天黄叶远飞        &lt;br /&gt;就算会与你分离&amp;#160; 凄绝的戏        &lt;br /&gt;要决心忘记我便记不起        &lt;br /&gt;明日天地&amp;#160; 只恐怕认不出自己        &lt;br /&gt;仍未忘跟你约定假如没有死        &lt;br /&gt;就算你壮阔胸膛&amp;#160; 不敌天气        &lt;br /&gt;两鬓斑白都可认得你&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;就算你壮阔胸膛 不敌天气        &lt;br /&gt;两鬓斑白都可认得你&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/BoyXiao/aggbug/2232324.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/archive/2011/11/01/2232324.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/BoyXiao/archive/2011/10/26/2225168.html</id><title type="text">【转】理解 RESTful 架构</title><summary type="text">越来越多的人开始意识到，网站即软件，而且是一种新型的软件。 这种"互联网软件"采用客户端/服务器模式，建立在分布式体系上， 通过互联网通信，具有高延时（high latency）、高并发等特点。 网站开发，完全可以采用软件开发的模式。但是传统上，软件和网络是两个不同的领域，很少有交集； 软件开发主要针对单机环境，网络则主要研究系统之间的通信。互联网的兴起，使得这两个领域开始融合, 现在我...</summary><published>2011-10-26T06:14:00Z</published><updated>2011-10-26T06:14:00Z</updated><author><name>Zachary.XiaoZhen</name><uri>http://www.cnblogs.com/BoyXiao/</uri></author><link rel="alternate" href="http://www.cnblogs.com/BoyXiao/archive/2011/10/26/2225168.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BoyXiao/archive/2011/10/26/2225168.html"/><content type="html">&lt;p&gt;&lt;font size="2" face="Courier New"&gt;越来越多的人开始意识到，&lt;strong&gt;网站即软件&lt;/strong&gt;，而且是一种新型的软件。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;这种&amp;quot;互联网软件&amp;quot;采用客户端/服务器模式，建立在分布式体系上，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;通过互联网通信，具有高延时（high latency）、高并发等特点。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;网站开发，完全可以采用软件开发的模式。但是传统上，软件和网络是两个不同的领域，很少有交集；&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;软件开发主要针对单机环境，网络则主要研究系统之间的通信。互联网的兴起，使得这两个领域开始融合,&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&lt;strong&gt;现在我们必须考虑，如何开发在互联网环境中使用的软件。&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;img src="http://image.beekka.com/blog/201109/bg2011091202.jpg" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;RESTful架构，就是目前最流行的一种互联网软件架构。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;它结构清晰、符合标准、易于理解、扩展方便，所以正得到越来越多网站的采用。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;但是，到底什么是RESTful架构，并不是一个容易说清楚的问题。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;下面，我就谈谈我理解的RESTful架构。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;一、起源&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;REST这个词，是&lt;/font&gt;&lt;a href="http://en.wikipedia.org/wiki/Roy_Fielding"&gt;&lt;font size="2" face="Courier New"&gt;Roy Thomas Fielding&lt;/font&gt;&lt;/a&gt;&lt;font size="2" face="Courier New"&gt;在他2000年的&lt;/font&gt;&lt;a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm"&gt;&lt;font size="2" face="Courier New"&gt;博士论文&lt;/font&gt;&lt;/a&gt;&lt;font size="2" face="Courier New"&gt;中提出的。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;img src="http://image.beekka.com/blog/201109/bg2011091201.jpg" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;Fielding是一个非常重要的人，他是HTTP协议（1.0版和1.1版）的主要设计者、&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;Apache服务器软件的作者之一、Apache基金会的第一任主席。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;所以，他的这篇论文一经发表，就引起了关注，并且立即对互联网开发产生了深远的影响。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;他这样介绍论文的写作目的：&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;quot;本文研究计算机科学两大前沿----软件和网络----的交叉点。&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Courier New"&gt;长期以来，软件研究主要关注软件设计的分类、设计方法的演化，很少客观地评估不同的设计选择对系统行为的影响。&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而相反地，网络研究主要关注系统之间通信行为的细节、如何改进特定通信机制的表现，常常忽视了一个事实，&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Courier New"&gt;那就是改变应用程序的互动风格比改变互动协议，对整体表现有更大的影响。&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;我这篇文章的写作目的，就是想在符合架构原理的前提下，理解和评估以网络为基础的应用软件的架构设计，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;得到一个功能强、性能好、适宜通信的架构。&lt;/strong&gt;&amp;quot;&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Courier New"&gt;(This dissertation explores a junction on the frontiers of two research disciplines &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Courier New"&gt;in computer science: software and networking. Software research has long been concerned &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Courier New"&gt;with the categorization of software designs and the development of design methodologies, &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Courier New"&gt;but has rarely been able to objectively evaluate the impact of various design choices &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Courier New"&gt;on system behavior. Networking research, in contrast, is focused on the details of &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Courier New"&gt;generic communication behavior between systems and improving the performance of &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Courier New"&gt;particular communication techniques, often ignoring the fact that changing the &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Courier New"&gt;interaction style of an application can have more impact on performance than the &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Courier New"&gt;communication protocols used for that interaction. My work is motivated by the desire &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Courier New"&gt;to understand and evaluate the architectural design of network-based application software &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Courier New"&gt;through principled use of architectural constraints, thereby obtaining the functional, &lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Courier New"&gt;performance, and social properties desired of an architecture. )&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="3" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;二、名称&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;Fielding 将他对互联网软件的架构原则，定名为 REST，即 Representational State Transfer 的缩写。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;我对这个词组的翻译是&amp;quot;表现层状态转化&amp;quot;。&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;如果一个架构符合 REST 原则，就称它为 RESTful 架构。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&lt;strong&gt;要理解 RESTful 架构，最好的方法就是去理解 Representational State Transfer 这个词组到底是什么意思，&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;它的每一个词代表了什么涵义。&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;如果你把这个名称搞懂了，也就不难体会REST是一种什么样的设计。&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;三、资源（Resources）&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;REST 的名称&amp;quot;表现层状态转化&amp;quot;中，省略了主语。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;quot;表现层&amp;quot;其实指的是&amp;quot;资源&amp;quot;（Resources）的&amp;quot;表现层&amp;quot;。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&lt;strong&gt;所谓&amp;quot;资源&amp;quot;，就是网络上的一个实体，或者说是网络上的一个具体信息。&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;它可以是一段文本、一张图片、一首歌曲、一种服务，总之就是一个具体的实在。&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;你可以用一个 URI（统一资源定位符）指向它，每种资源对应一个特定的 URI。&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;要获取这个资源，访问它的URI就可以，因此 URI 就成了每一个资源的地址或独一无二的识别符。&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;所谓&amp;quot;上网&amp;quot;，就是与互联网上一系列的&amp;quot;资源&amp;quot;互动，调用它的 URI。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;四、表现层（Representation）&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&amp;quot;资源&amp;quot;是一种信息实体，它可以有多种外在表现形式。&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&lt;strong&gt;我们把&amp;quot;资源&amp;quot;具体呈现出来的形式，叫做它的&amp;quot;表现层&amp;quot;（Representation）。&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;比如，文本可以用txt格式表现，也可以用HTML格式、XML格式、JSON格式表现，甚至可以采用二进制格式；&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;图片可以用JPG格式表现，也可以用PNG格式表现。&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;URI 只代表资源的实体，不代表它的形式。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;严格地说，有些网址最后的&amp;quot;.html&amp;quot;后缀名是不必要的，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;因为这个后缀名表示格式，属于&amp;quot;表现层&amp;quot;范畴，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;而 URI 应该只代表&amp;quot;资源&amp;quot;的位置。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;它的具体表现形式，应该在 HTTP 请求的头信息中用 Accept 和 Content-Type 字段指定，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;这两个字段才是对&amp;quot;表现层&amp;quot;的描述。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;五、状态转化（State Transfer）&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;访问一个网站，就代表了客户端和服务器的一个互动过程。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;在这个过程中，势必涉及到数据和状态的变化。&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;互联网通信协议HTTP协议，是一个无状态协议。&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;这意味着，所有的状态都保存在服务器端。&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&lt;strong&gt;因此，如果客户端想要操作服务器，必须通过某种手段，让服务器端发生&amp;quot;状态转化&amp;quot;（State Transfer）。&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;而这种转化是建立在表现层之上的，所以就是&amp;quot;表现层状态转化&amp;quot;。&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;客户端用到的手段，只能是HTTP协议。&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;具体来说，就是 HTTP 协议里面，四个表示操作方式的动词：GET、POST、PUT、DELETE。&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&lt;strong&gt;GET 用来获取资源；&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&lt;strong&gt;POST 用来新建资源（也可以用于更新资源）；&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&lt;strong&gt;PUT 用来更新资源；&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&lt;strong&gt;DELETE 用来删除资源；&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;六、综述&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;综合上面的解释，我们总结一下什么是RESTful架构：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt; （1）每一个URI代表一种资源；&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt; （2）客户端和服务器之间，传递这种资源的某种表现层；&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt; （3）客户端通过四个HTTP动词，对服务器端资源进行操作，实现&amp;quot;表现层状态转化&amp;quot;。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;七、误区&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;RESTful 架构有一些典型的设计误区。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&lt;strong&gt;最常见的一种设计错误，就是 URI 包含动词。&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;因为&amp;quot;资源&amp;quot;表示一种实体，所以应该是名词，URI 不应该有动词，动词应该放在 HTTP 协议中。&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;举例来说，某个 URI 是 /posts/show/1，其中 show 是动词，这个 URI 就设计错了，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;正确的写法应该是 /posts/1，然后用 GET 方法表示 show。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;如果某些动作是 HTTP 动词表示不了的，你就应该把动作做成一种资源。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;比如网上汇款，从账户 1 向账户 2 汇款 500 元，错误的 URI 是：&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font size="2" face="Courier New"&gt; POST /accounts/1/transfer/500/to/2&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;正确的写法是把动词 transfer 改成名词 transaction，资源不能是动词，但是可以是一种服务：&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font size="2" face="Courier New"&gt; POST /transaction HTTP/1.1       &lt;br /&gt; Host: 127.0.0.1        &lt;br /&gt; from=1&amp;amp;to=2&amp;amp;amount=500.00&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&lt;strong&gt;另一个设计误区，就是在URI中加入版本号&lt;/strong&gt;：&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font size="2" face="Courier New"&gt; http://www.example.com/app/1.0/foo&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Courier New"&gt; http://www.example.com/app/1.1/foo&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Courier New"&gt; http://www.example.com/app/2.0/foo&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;因为不同的版本，可以理解成同一种资源的不同表现形式，所以应该采用同一个 URI。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;版本号可以在 HTTP 请求头信息的 Accept 字段中进行区分（参见 &lt;/font&gt;&lt;a href="http://www.informit.com/articles/article.aspx?p=1566460"&gt;&lt;font size="2" face="Courier New"&gt;Versioning REST Services&lt;/font&gt;&lt;/a&gt;&lt;font size="2" face="Courier New"&gt;）：&lt;/font&gt;&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&lt;font size="2" face="Courier New"&gt; Accept: vnd.example-com.foo+json; version=1.0&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Courier New"&gt; Accept: vnd.example-com.foo+json; version=1.1&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size="2" face="Courier New"&gt; Accept: vnd.example-com.foo+json; version=2.0&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;（完）&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;文档信息&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;font size="2" face="Courier New"&gt;版权声明：自由转载-非商用-非衍生-保持署名 | &lt;/font&gt;&lt;a href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh"&gt;&lt;font size="2" face="Courier New"&gt;Creative Commons BY-NC-ND 3.0&lt;/font&gt;&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;font size="2" face="Courier New"&gt;原文网址：&lt;/font&gt;&lt;a href="http://www.ruanyifeng.com/blog/2011/09/restful.html"&gt;&lt;font size="2" face="Courier New"&gt;http://www.ruanyifeng.com/blog/2011/09/restful.html&lt;/font&gt;&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;font size="2" face="Courier New"&gt;最后修改时间：2011年10月25日 14:53 &lt;/font&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="3" face="Courier New"&gt;&lt;strong&gt;本博文转载自：阮一峰的网络日志 - 《理解 RESTful 架构》&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/BoyXiao/aggbug/2225168.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/archive/2011/10/26/2225168.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/BoyXiao/archive/2011/10/20/2219091.html</id><title type="text">棋子 - 王菲</title><summary type="text">想走出你控制的领域 却走近你安排的战局我没有坚强的防备 也没有后路可以退 想逃离你布下的陷阱 却陷入了另一个困境我没有决定输赢的勇气 也没有逃脱的幸运 我像是一颗棋 进退任由你决定我不是你眼中唯一将领 却是不起眼的小兵 我像是一颗棋子 来去全不由自己举手无回你从不曾犹豫 我却受控在你手里 想走出你控制的领域 却走近你安排的战局我没有坚强的防备 也没有后路可以退 想逃离...</summary><published>2011-10-20T08:16:00Z</published><updated>2011-10-20T08:16:00Z</updated><author><name>Zachary.XiaoZhen</name><uri>http://www.cnblogs.com/BoyXiao/</uri></author><link rel="alternate" href="http://www.cnblogs.com/BoyXiao/archive/2011/10/20/2219091.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BoyXiao/archive/2011/10/20/2219091.html"/><content type="html">&lt;font size="2"&gt;&lt;strong&gt;想走出你控制的领域  &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;却走近你安排的战局&lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;我没有坚强的防备  &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;也没有后路可以退&lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;想逃离你布下的陷阱  &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;却陷入了另一个困境&lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;我没有决定输赢的勇气  &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;也没有逃脱的幸运&lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;我像是一颗棋  &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;进退任由你决定&lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;我不是你眼中唯一将领  &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;却是不起眼的小兵&lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;我像是一颗棋子  &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;来去全不由自己&lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;举手无回你从不曾犹豫  &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;我却受控在你手里&lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;想走出你控制的领域  &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;却走近你安排的战局&lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;我没有坚强的防备  &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;也没有后路可以退&lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;想逃离你布下的陷阱  &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;却陷入了另一个困境&lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;我没有决定输赢的勇气  &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;也没有逃脱的幸运&lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;我像是一颗棋  &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;进退任由你决定&lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;我不是你眼中唯一将领  &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;却是不起眼的小兵&lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;我像是一颗棋子  &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;来去全不由自己&lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;举手无回你从不曾犹豫  &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;我却受控在你手里&lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;我像是一颗棋子  &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;来去全不由自己&lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;举手无回你从不曾犹豫  &lt;/strong&gt;&lt;/font&gt;      &lt;font size="2"&gt;&lt;strong&gt;我却受控在你手里&lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;我却受控在你手里&lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;我却受控在你手里&lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;            &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;             &lt;/strong&gt;&lt;/font&gt;&lt;font size="2"&gt;&lt;strong&gt;              &lt;/strong&gt;&lt;/font&gt;&lt;img src="http://www.cnblogs.com/BoyXiao/aggbug/2219091.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/archive/2011/10/20/2219091.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/BoyXiao/archive/2011/10/12/2209427.html</id><title type="text">七友 - 梁汉文</title><summary type="text">为了她 又再勉强去谈天论爱 又再振作去慰解他人 如难复合便尽早放开 凡事看开 又再讲 没有情人时还可自爱 忘掉或是为自己感慨 笑住说沉沦那些苦海 会有害 因为我坚强到利用自己的痛心 转换成爱心 抵 我对她操心 已记不起我也有权利爱人 谁人曾照顾过我的感受 待我温柔 吻过我伤口 能得到的安慰是失恋者得救后很感激忠诚的狗 谁人曾介意我也不好受 ...</summary><published>2011-10-12T14:03:00Z</published><updated>2011-10-12T14:03:00Z</updated><author><name>Zachary.XiaoZhen</name><uri>http://www.cnblogs.com/BoyXiao/</uri></author><link rel="alternate" href="http://www.cnblogs.com/BoyXiao/archive/2011/10/12/2209427.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BoyXiao/archive/2011/10/12/2209427.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;为了她&amp;#160; 又再勉强去谈天论爱 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;又再振作去慰解他人 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;如难复合便尽早放开&amp;#160; 凡事看开 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;又再讲&amp;#160; 没有情人时还可自爱 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;忘掉或是为自己感慨 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;笑住说沉沦那些苦海&amp;#160; 会有害&lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;因为我坚强到利用自己的痛心&amp;#160; 转换成爱心 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;抵&amp;#160; 我对她操心&amp;#160; 已记不起我也有权利爱人 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;谁人曾照顾过我的感受&amp;#160; 待我温柔 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;吻过我伤口 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;能得到的安慰是失恋者得救后很感激忠诚的狗 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;谁人曾介意我也不好受 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;为我出头&amp;#160; 碰过我的手 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;重生者走得的都走 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;谁人又为天使忧愁 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;甜言蜜语没有&amp;#160; 但却有我这个好友 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;直到她&amp;#160; 又再告诉我重新被爱 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;又再看透了我的将来 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;完成任务后大可喝采&amp;#160; 无谓搭台 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;别怪她&amp;#160; 就怪我永远难得被爱 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;然后自虐地赞她可爱 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;往日最徬徨那刻&amp;#160; 好彩有我在 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;因为我坚强到利用自己的痛心&amp;#160; 转换成爱心 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;抵&amp;#160; 我对她操心&amp;#160; 已记不起我也有权利爱人 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;谁人曾照顾过我的感受&amp;#160; 待我温柔 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;吻过我伤口 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;能得到的安慰是失恋者得救后很感激忠诚的狗 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;谁人曾介意我也不好受 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;为我出头&amp;#160; 碰过我的手 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;重生者走得的都走 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;谁人又为天使忧愁 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;甜言蜜语没有&amp;#160; 但却有我这个好友&lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;白雪公主不多 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;认命扮矮人的有太多个&amp;#160; 早有六个 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;多我这个不多&amp;#160; 我太好心还是太傻 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;未问过她&amp;#160; 有没有理我的感受 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;待我温柔&amp;#160; 吻过我伤口 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;能得到的安慰是失恋者得救后很感激忠诚的狗 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;谁人曾介意我也不好受 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;为我出头&amp;#160; 碰过我的手 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;重生者走得的都走 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;谁人又为天使忧愁 &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2"&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;甜言蜜语没有&amp;#160; 但却有我这个好友&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;      &lt;p&gt;&lt;strong&gt;&lt;span style="font-family: &amp;#39;Courier New&amp;#39;; font-size: x-small" face="Courier New" size="2"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/BoyXiao/aggbug/2209427.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/archive/2011/10/12/2209427.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/BoyXiao/archive/2011/09/21/2183059.html</id><title type="text">Native Application 开发详解</title><summary type="text">文章目录： 1. 引子： 2. Native Application Demo 展示： 3. Native Application 简介： 4. Native Application 有何妙用： 5. MJ0011 关于 Native Application 的文章整理： 6. 互联网上其他关于 Native Application 的文章整理：...</summary><published>2011-09-21T00:56:00Z</published><updated>2011-09-21T00:56:00Z</updated><author><name>Zachary.XiaoZhen</name><uri>http://www.cnblogs.com/BoyXiao/</uri></author><link rel="alternate" href="http://www.cnblogs.com/BoyXiao/archive/2011/09/21/2183059.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BoyXiao/archive/2011/09/21/2183059.html"/><content type="html">&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;文章目录：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;1. 引子：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;2. Native Application Demo 展示：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;3. Native Application 简介：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;4. Native Application 有何妙用：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;5. MJ0011 关于 Native Application 的文章整理：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;6. 互联网上其他关于 Native Application 的文章整理：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;7. 小结：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;1. 引子：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;其实在好久以前就看了 MJ0011 翻译的那个《Native 应用程序详细》系列的文章，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;(PS: MJ0011 为 360 的首席技术执行官，技术是没的说，不过貌似有点狂妄之说 ~ &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;)&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而且看完后对这一系列文章也很感兴趣的，所以又去 Google 上找了几个小资料学习了一下，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而这篇文章呢，则是将我前阵子的所谓的学习给总结出来也顺道给大伙分享一下。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;虽然这里是说的总结 Native Application，但&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;最早出现 Native Application 应该&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;是 06 年的事了，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;(当然，Native Application 这个技术是一直存在的，只是在 06 年后有了下面这篇文章后就稍微火了点)&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;其是 Sysinternals 上的一篇由 Mark Russinovich 发表的文章&lt;strong&gt;《Inside Native Applications》&lt;/strong&gt;，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;文章地址如下：&lt;/font&gt;&lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb897447"&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;http://technet.microsoft.com/en-us/sysinternals/bb897447&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而我却在 2011 年才得以来总结这个技术，所以我确是属于研究这些东西的落后者啊 ~ &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;下面我给出一副截图来看一下 Windows 操作系统下的程序的类型：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/20110921085424196.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109210854363543.png" width="710" height="383" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;在 Windows 最初设计的时候考虑到了兼容各种系统的应用程序，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;所以有了环境子系统之说，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;其中一开始的时候考虑到了子系统，POSIX 子系统和 OS/2 子系统，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;但是随着历史的发展，现在也就剩下个 Windows 子系统了，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;我们日常使用的 Windows 操作系统的上层其实也就是指的这个 Windows 子系统了，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;至于这里为何要扯到 Windows 子系统的话，就看下文介绍了。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;很多朋友都知道有 Windows 应用程序和 Windows 内核驱动程序之说，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;却很少有知道在 Windows 中还有 Native Application 一说了，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;但是这类程序确实是存在的 ~&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;只不过这类程序应用比较窄，也没有被很好的推广开来，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;当然还有一点就是 Microsoft 自然不希望你随随便便的使用 Native API。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;2. Native Application Demo 展示：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;首先你需要将下载(博文的最后面附上 Demo 的下载地址)的 EXE 文件拷贝一份到 system32 目录下，&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;(博文的 Demo 只是拿了网上的代码然后自行使用 DDK 编译了而已，Demo 并非笔者原创)&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后再在注册表以下路径中修改 BootExecute，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#9b00d3" size="2" face="Courier New"&gt;HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;在其中添加&lt;strong&gt; NativeApp_01 Hello World !&lt;/strong&gt; 这个字符串，&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109210854439785.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109210854554560.png" width="773" height="430" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109210855011807.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109210855127271.png" width="704" height="471" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;重启电脑，然后就可以看到下面的效果图了(仅在 XP SP3 上进行了测试)&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109210855132678.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="2011-09-18_111934" border="0" alt="2011-09-18_111934" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109210855154399.gif" width="879" height="656" /&gt;&lt;/a&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;3. Native Application 简介：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;何为 Native API ? &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;Native API 就是你 system32 目录下的那个 ntdll.dll 中所公开的 API(大部分为 Undocument)~&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;如果读者看过我前面的《进程隐藏与进程保护(SSDT Hook 实现)》系列文章的话，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;相信肯定会知道在 Windows 中 kernel32.dll 中的 API 的调用都会经过转换，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;也就是跳转到 ntdll.dll 中，并且在 ntdll.dll 中也有与之相对于的 API 调用，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;(比如 Kernel32.dll 中的 CreateProcess 在 ntdll.dll 中有 NtCreateProcess 与之对应)&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;那么什么称之为 Native 应用程序呢 ?&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;下面给出一副截图：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109210855195955.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/20110921085527146.png" width="810" height="589" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;从上面的截图可以看出，在一开始的 Windows NT 内核中是支持三个环境子系统的，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;即 POSIX,WINDOWS,OS/2，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;这些子系统属于同一层，它们共用了 Windows NT 所提供的 API，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;即每一个子系统中的 API 的调用都会转换到下一层的相同调用上，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;在 Windows 环境子系统(有 Windows,Posix,OS/2)中的程序，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;都会调用其相对于的子系统下的 API，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;比如 Windows 子系统中的程序有可能会调用 Win32 API CreateProcess，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而 Posix 子系统中的程序也有可能会调用 Posix API CreateProcess(当然有可能在 POSIX 下创建进程不是这个名称)，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;但是终归来说，这两个 CreateProcess 的调用都会转换到 Ntdll.dll 中的 NtCreateProcess 中，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;也就是上面的三个子系统最后的调用都会回归到 ntdll.dll 上，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;而我们的 Native Application 则是绕过 Windows 子系统，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;直接自己调用 Native API，比如创建进程的话，我就不再通过子系统中的神马 CreateProcess 来完成了，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;而是直接在程序中调用 ntdll.dll 中的 Native API NtCreateProcess 来完成，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;而这类程序即称之为 Native Application !&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="3" face="Courier New"&gt;&lt;strong&gt;Native Application 的运行环境：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;上面也说了，Native Application 是只能够访问 ntdll.dll 中的内容的，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而如果是在子系统下运行一个程序的话，必然会加载其他的 DLL，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;比如在 Windows 子系统下一个 kernel32.dll 是必不可少的吧，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;如果 Native Application 能够运行在 Windows 子系统下的话，必然也会加载到 Kernel32.dll，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;这样不就和上面相违背了嘛 ~ &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#9b00d3" size="2" face="Courier New"&gt;&lt;strong&gt;总之：Native Application 是不能够运行在任何子系统下的 !&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;比如在 Windows 子系统下运行 Native Application 会弹出如下错误对话框：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109210855308420.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109210855359287.png" width="672" height="193" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="3" face="Courier New"&gt;&lt;strong&gt;Native Application 的启动时机：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;对于 Windows 操作系统的引导过程，这里需要带一笔的，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;Windows 操作系统启动时，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;当 Windows 内核的引导完成以后，就会启动会话管理器 smss.exe 进程了，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;smss.exe 进程虽然是一个用户模式的进程，但是这个进程相对于其他用户模式进程是具有一定特殊性的，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;首先 smss.exe 进程是直接建立在 Windows NT 内核上的，其不依赖于任何一个环境子系统，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;至于不依赖于任何一个环境子系统这一说的话，还是可以很好的解释的，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;因为当环境子系统进程(Windows 子系统进程为 csrss.exe)就是由 smss.exe 进程启动的，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后 smss.exe 是 Windows 操作系统启动的第一个用户态进程，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而 Native Application 也属于用户态程序，自然 Native Application 的启动是在 smss.exe 之后，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而后&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;前面也说过，Native Application 运行时，子系统进程还尚未启动，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;所以 Native Application 的启动则是在 csrss.exe 之前的，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而话又说回来，csrss.exe 就是由会话管理器(smss.exe)启动的，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#9b00d3" size="2" face="Courier New"&gt;&lt;strong&gt;所以 Native Application 的启动时机也就只有一种可能了，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#9b00d3" size="2" face="Courier New"&gt;&lt;strong&gt;即 smss.exe 先启动 Native Application，然后 Native Application 开始执行，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#9b00d3" size="2" face="Courier New"&gt;&lt;strong&gt;等到 Native Application 都给执行完了后 smss.exe 再启动 csrss.exe 进程。&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#9b00d3" size="2" face="Courier New"&gt;（事实上，Win32 应用程序环境子系统 csrss.exe 本质上也是一个 Native Application ~）&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#000000" size="2" face="Courier New"&gt;下面给出一副截图以说明 SMSS.EXE 的在启动过程中所完成的工作：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#000000" size="2" face="Courier New"&gt;运行启动时执行的程序即是执行 Native Application&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109210855408759.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109210855521026.png" width="779" height="492" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;4. Native Application 有何妙用：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;前面也提到过，Native Application 的应用范围比较窄，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;这主要受以下几点约束：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;首先，Native Application 是直接调用 Native API 来完成任务的，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而在 Windows 中，Native API 绝大部分都是 Undocument 的，这样开发起来自然难度会大很多了。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后，由于 Native Application 是调用的 Undocument API，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;说不准那一天 Microsoft 就在下一代 Windows 中修改了这个 API，这样的话，你程序的可移植性也就完全没了。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;最后的话，Native Application 的执行环境并非是在 Windows 子系统中，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;事实上，当 Native Application 开始执行的时候，Windows 子系统进程(csrss.exe)进程都还没有启动的 ~ &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;所以 Native Application 的执行是受限制的，其不能够执行子系统中的任何东西，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;说白一点的话就是 Native Application 只能够调用 ntdll.dll 中的 API，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;其他 DLL 中的 API 一律不得调用，这样也就注定 Native Application 的应用范围不会很广泛了。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;应用范围比较窄并不等于说没有应用价值，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;也还是有蛮多的软件，包括一些商业软件也都是用了 Native Application，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;下面来看一些 Native Application 的应用(我也只是从网上道听途说，不过有些也确实是自己也用过的)：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;最典型的应用自然是属于 Windows 操作系统自带的磁盘自检程序了;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;然后比较典型的商业应用是瑞星的开机杀毒，即实现让病毒在你还没有完全开机之前死掉;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;然后就是可以通过 Native Application 来实现接管 Windows 的开机启动界面和密码输入界;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;还可以通过 Native Application 来实现开机前的磁盘修复(Windows 自带了这款工具也是这样实现的);&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;5. MJ0011 关于 Native Application 的文章整理：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;这一小节里面主要是整理一下关于 MJ0011 的 Native Application 的博文，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;也就是说我这里纯粹是将他的东西给贴出来瞧瞧，关于 MJ0011 博文的原地址为：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;《NATIVE应用程序详细之一》：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://hi.baidu.com/mj0011/blog/item/7ee496d67a4d4d2f07088bc7.html"&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;http://hi.baidu.com/mj0011/blog/item/7ee496d67a4d4d2f07088bc7.html&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;《NATIVE应用程序详细之2 NATIVE应用程序的优势和劣势》&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://hi.baidu.com/mj0011/blog/item/f8108f2f5890fb381e30896d.html"&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;http://hi.baidu.com/mj0011/blog/item/f8108f2f5890fb381e30896d.html&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;《native应用程序详细之三 构建native应用程序》：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://hi.baidu.com/mj0011/blog/item/725b4882042b03a20df4d269.html"&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;http://hi.baidu.com/mj0011/blog/item/725b4882042b03a20df4d269.html&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;《深入Native应用程序》(该文翻译自《Inside Native Application》)：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;a href="http://hi.baidu.com/mj0011/blog/item/85c0b50f80b1baedab6457de.html"&gt;&lt;strong&gt;http://hi.baidu.com/mj0011/blog/item/85c0b50f80b1baedab6457de.html&lt;/strong&gt;&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;《native app GUI界面的实现》：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://hi.baidu.com/mj0011/blog/item/6e5a22fa214c8116a9d3115b.html"&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;http://hi.baidu.com/mj0011/blog/item/6e5a22fa214c8116a9d3115b.html&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="3"&gt;&lt;font color="#0000ff"&gt;&lt;b&gt;Native &lt;/b&gt;&lt;b&gt;应用程序简介：&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;NT 系统被设计成为支持子系统（封装），它可以执行在不同平台上的代码。&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;包括但不限于：POSIX、OS/2和Win32，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;为了管理这些子系统，NT内核输出了大量名为 Native API的API函数，子系统服务将这些函数包装为他们自己的函数。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;例如:CreateFile和fopen都被映射到NtCreateFile.&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;那么子系统管理程序运行在哪个子系统中？&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;为了避免先有鸡还是先有蛋的问题，NT系统同样支持原生的Native应用程序。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;这些Native应用程序是独立于子系统的。&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;现在，所有的子系统应用程序都需要注册它们自己的子系统服务，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;显然，Kernel32是一个Win32应用程序，csrss注册WIN32子系统，然后通知子系统管理器SMSS，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;因此，一个Native应用程序是无法调用其中数千种API的，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;同时它也无法使用一些基本的DLL中的函数例如kernel32、user32、gdi32等，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;其它任何调用了这三者的DLL中的函数的DLL也无法被使用。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;事实上，加载者在其入口点没有被加载前，并不允许加载决大多数的Win32 DLL。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;因此，native应用程序被限制只许使用一个DLL：ntdll.dll，这个DLL供应所有Native和运行函数。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;但是想想，既然所有Win32函数最后都是去调用Ntdll.dll中的函数来实现的（除了GUI部分），&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;这些函数就已经足够了，不是吗?&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="3" face="Courier New"&gt;&lt;strong&gt;Native应用程序优势：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;&lt;font color="#9b00d3"&gt;(一) 内存使用和大小：&lt;/font&gt;&lt;/strong&gt;因为Native应用程序并不需要加载90多个DLL到内存中去，因此其使用的内存是很小的。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;&lt;font color="#9b00d3"&gt;(二) 速度：&lt;/font&gt;&lt;/strong&gt;Native API比Win32对应的函数要更快（通常会快很多），&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;尽管实际上很多时间都被消耗在Win32 API的封装上，这些包括修改、兼容性选项，和其他的代码部分，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;这些都会在执行真正的Native调用前执行。如果你知道如何去做而且希望它运行得更快，Native是一个很好的方法。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;因为不需要加载那90多个DLL，kernel32不需要到csrss和smss做lpc注册，因此启动也是非常快速和直接的。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;&lt;font color="#9b00d3"&gt;(三) 熟悉程度和特性：&lt;/font&gt;&lt;/strong&gt;Native应用程序并没有古怪的入口点或者奇怪的Hack，就象读命令行一样简单使用，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而事实上将在后面介绍，Native应用程序和Console程序一样启动与_main函数，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;通过一组简单的char*[]队列来接受命令行参数和环境变量，就象一个典型的Win32 Console程序一样，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;一些特性例如缓冲区溢出保护(/GS)、Safe SEH(/SAFESEH）、hotpathing(/HOTPATCH)，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;以及其他的特性都被支持。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;&lt;font color="#9b00d3"&gt;(四) 丰富：&lt;/font&gt;&lt;/strong&gt;Native API非常丰富，它们提供的特性和功能性要远远超越Win32函数所能达到的程度。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;这并不是说Win32无法做到Native API那样的更困难和更复杂的工作，而是Win32太过简单而已，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;比如Win32函数中，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;无法远程注入一个Section到一个进程中，因为MapViewOfFileEx不提供进程句柄接口，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而Native API则可以实现这个功能。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;&lt;font color="#9b00d3"&gt;(五) 安全：&lt;/font&gt;&lt;/strong&gt;但是Native应用程序有这样一个特点:人们对于Native API不是十分熟悉，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;他们需要花费更多的时间才能理解你的代码，而更重要的是，无法使用一个用户模式的debugger来调试Native应用程序，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;只有SoftIce和使用内核模式远程连接的WinDbg才可以对其进行调试，这足以让那些废物脚本小子去死了，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;再说一遍，这并不意味着Native 应用程序是“不可调试的，安全的”，只是它更模糊更难被破解。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;&lt;font color="#9b00d3"&gt;(六) 同内核模式的连接:&lt;/font&gt;&lt;/strong&gt;因为Native应用程序只使用Native API，这些函数在内核模式仍然可用，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;这样，一个Native程序只需少量修改就可修改为内核驱动，而Win32程序则需要几乎重写所有代码。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;&lt;font color="#9b00d3"&gt;(七) 运行在独立于子系统的环境中：&lt;/font&gt;&lt;/strong&gt;因为Native应用程序并不依赖与任何子系统，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;它运行于一个正常应用永远无法再次得到的环境中，比如autochk.exe，它运行与任何子系统加载之前，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;并负责显示'press any key to scan your hard disk&amp;quot;信息，并扫描你的硬盘是否有错误。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;在这个模式运行允许你显示信息到启动屏幕上，以及很多增强特性。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;&lt;font color="#9b00d3"&gt;(八) 标准性：&lt;/font&gt;&lt;/strong&gt;不象Win32函数有一个正常版本，一个&amp;quot;Ex&amp;quot;版本，以及经常有一个&amp;quot;扩展其他功能&amp;quot;的版本，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;以及经常返回0,1,-1或一些随机的数值来表示成功，并且要使用SetLastError来设置返回错误，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;在Native应用程序中，这些垃圾都是不存在的，所有的Native API都有统一的标准，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;所有都返回NTSTAUS(除非明确表示会返回一个特定的值），NTSTAUS是一个标准的错误码定义，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而且使用它们时你也不需要考虑该死的Ex版本。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="3"&gt;&lt;font color="#0000ff"&gt;&lt;b&gt;Native &lt;/b&gt;&lt;b&gt;应用程序劣势：&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;&lt;font color="#9b00d3"&gt;(一) 和Win32开发的差异较大：&lt;/font&gt;&lt;/strong&gt;如果你以前从来没有进行过Native API或内核驱动的相关开发，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;你可能需要学习所有的API相关知识，当然，他们的名字是相似的，但是他们的标志经常是完全不同的，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而且他们的返回值，很可能使你感到迷惑。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;&lt;font color="#9b00d3"&gt;(二) 缺少文档：&lt;/font&gt;&lt;/strong&gt;虽然所有的Rtl*函数都是有文档的，数百个其他的Native API仍是无文档的。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;&lt;font color="#9b00d3"&gt;(三) 缺少商业价值：&lt;/font&gt;&lt;/strong&gt;虽然Native程序如此美好，但是建议你不要在商业产品中使用 Native API 或着使用Native应用程序，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;Native API是可能改变的，虽然它们通常没有改变，但是他们很可能变得不再有用，不要拿你的客户的钱冒险。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;&lt;font color="#9b00d3"&gt;(四) 没有GUI、及输入/输出接口:&lt;/font&gt;&lt;/strong&gt;没有&amp;quot;Native控制台程序&amp;quot;，你无法简单地从用户那里接受到输入或显示些什么到屏幕上，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;因为那些接口都无法再使用（控制台API都是Win32 API)。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="3"&gt;&lt;font color="#0000ff"&gt;&lt;b&gt;Native &lt;/b&gt;&lt;b&gt;应用程序构建：&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;你需要这两者或两者之一来创建你的 native 应用程序:&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;(1)Visual C++ 2005 Express(or higher)&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;(2)Windows Driver Kit&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;我们将从基础开始，首先你需要创建你的应用程序的头文件，precomp.h，ntddk.h&lt;/font&gt;&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;span class="lnum"&gt;   1:  &lt;/span&gt;#include &lt;span class="str"&gt;&amp;quot;ntddk.h&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;Now that that's done, create your main initialization file, &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;which we will call init.c. In this file, add precomp.h like this:&lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;#include &lt;span class="str"&gt;&amp;quot;precomp.h&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;And define your entrypoint:&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;NTSTATUS __cdeclmain(  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;INT argc,  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;PCHAR argv[],  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;PCHAR envp[],  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;ULONG DebugFlag OPTIONAL)  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  11:  &lt;/span&gt;{  &lt;span class="lnum"&gt;  12:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  13:  &lt;/span&gt;&lt;span class="rem"&gt;// Entry code here&lt;/span&gt;  &lt;span class="lnum"&gt;  14:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  15:  &lt;/span&gt;}&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;Hopefully you are familiar with this entrypoint, it's the typical one used &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;by C programs, &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;except with an addon: the &amp;quot;DebugFlag&amp;quot;. Right now, we don't &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;need to care about this. &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;We'll keep this entry simple, and turn this into a &amp;quot;Hello World&amp;quot;:&lt;/font&gt;&lt;/p&gt;&lt;font size="2" face="Courier New"&gt;  &lt;p class="csharpcode"&gt;&lt;/p&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;NTSTATUS __cdecl main(  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;INT argc,  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;PCHAR argv[],  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;PCHAR envp[],  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;ULONG DebugFlag OPTIONAL)  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  11:  &lt;/span&gt;{  &lt;span class="lnum"&gt;  12:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  13:  &lt;/span&gt;UNICODE_STRING HelloMsg = RTL_CONSTANT_STRING(L&lt;span class="str"&gt;&amp;quot;Hello World!\n&amp;quot;&lt;/span&gt;);  &lt;span class="lnum"&gt;  14:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  15:  &lt;/span&gt;&lt;span class="rem"&gt;//Say hello&lt;/span&gt;  &lt;span class="lnum"&gt;  16:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  17:  &lt;/span&gt;NtDisplayString(&amp;amp;HelloMsg);  &lt;span class="lnum"&gt;  18:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  19:  &lt;/span&gt;}  &lt;span class="lnum"&gt;  20:  &lt;/span&gt;&amp;#160;  &lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;Now, if you're wondering what NTSTATUS is, &lt;/p&gt;  &lt;p&gt;what NtDisplayString is or what &lt;/p&gt;  &lt;font size="2" face="Courier New"&gt;RTL_CONSTANT_STRING and UNICODE_STRINGs are, &lt;/font&gt;&lt;/font&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;then you'll need to read all &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;the DDK documentation you can swallow, &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;as well as Nebett's Undocumented &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;Native API book. &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;Although it's outdated, &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;the information about the APIs is &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;still pretty valid. &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;I also plan to possibly give a fully-fledged lesson on this if lots of &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;people are interested.&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;So now that we have our simple program, &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;we need to build it. &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;I prefer using the WDK myself, &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;because it's much &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;simpler and doesn't require changing 100 of MSVC's default settings.&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;Assuming you've properly installed the WDK and entered the Windows build &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;environment &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;for &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;your OS (from the Start Menu), &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;you'll need to create two &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;files in the directory where init.c and precomp.h are: &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;sources and makefile.&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#9b00d3" size="2" face="Courier New"&gt;&lt;strong&gt;Sources should look something like this:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;--&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;TARGETNAME=native  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;TARGETTYPE=PROGRAM  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;UMTYPE=nt  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;INCLUDES=\  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;$(DDK_INC_PATH); \  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  11:  &lt;/span&gt;$(NDK_INC_PATH);  &lt;span class="lnum"&gt;  12:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  13:  &lt;/span&gt;SOURCES=init.c  &lt;span class="lnum"&gt;  14:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  15:  &lt;/span&gt;PRECOMPILED_INCLUDE=precomp.h  &lt;span class="lnum"&gt;  16:  &lt;/span&gt;&amp;#160;&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;-- &lt;p&gt;&lt;font size="2" face="Courier New"&gt;that you'll have to set NDK_INC_PATH as an environment variable yourself, &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;to where the NDK is installed (DDK_INC_PATH is already setup by the WDK).&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#9b00d3" size="2" face="Courier New"&gt;Finally, you'll need a makefile:&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;--&lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;INCLUDE $(NTMAKEENV)\makefile.def&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;--&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;That's all you really need for our purposes.&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;So now you should &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;have init.c, precomp.h, sources and makefile.&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;The only thing left is to &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;write &amp;quot;build&amp;quot;, &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;and the WDK should do the magic and create your first native application. &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;Unforunately, you can't really test it for now, &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;unless you do &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;the following:&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;Open registry editor and browse to &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#9b00d3" size="2" face="Courier New"&gt;HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;Edit the &amp;quot;BootExecute&amp;quot; key and write &amp;quot;native&amp;quot; instead of what's currently &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;in it, &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;then copy native.exe to your system32 directory and restart the &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;computer. &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;You should see the message appear on the screen for a little while.&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;Make sure that you do NOT boot with /NOGUIBOOT, or else you will never see &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;it.&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#008040" size="2" face="Courier New"&gt;&lt;strong&gt;//////////////////////////////////////////////////////////////////////////////&amp;#160;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#008040" size="2" face="Courier New"&gt;&lt;strong&gt;//////////////////////////////////////////////////////////////////////////////&amp;#160;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#008040" size="2" face="Courier New"&gt;&lt;strong&gt;/////////////////&lt;font color="#000000"&gt;MJ0011 翻译《Inside Native Application》&lt;/font&gt;//////////////////////&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#008040" size="2" face="Courier New"&gt;&lt;strong&gt;//////////////////////////////////////////////////////////////////////////////&amp;#160;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;&lt;font color="#008040"&gt;//////////////////////////////////////////////////////////////////////////////&lt;/font&gt;&lt;/strong&gt;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="3" face="Courier New"&gt;导言&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;如果你对Windows Nt结构有一定的了解，你可能会知道，Win32 应用程序所使用的API，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;并非是&amp;quot;真正&amp;quot;的NT API，POSIX、OS/2和Win32这些Windows NT 操作系统环境，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;使用他们自己的 API 同他们的客户应用程序进行交流，但却使用Windows NT的&amp;quot;Native&amp;quot; API同Windows NT交流，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;这些Native API大都是未公开UnDocumented 的。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;大约只有25个API（包含250种功能）在Windows NT设备驱动开发工具包(DDK)里有所描述。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;尽管绝大多数人都不知道，但&amp;quot;Native&amp;quot;应用程序的确存在与Windows NT上，他们在操作环境上没有任何客户程序，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;这些程序交流着Native NT API并且不能使用任何操作环境API比如 Win32，为什么这样一种程序是必须的呢?&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;因为在Win32子系统启动之前(大约在登陆对话框出现时)只可以运行Native应用程序，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;最常见的Native应用程序的例子是&amp;quot;autochk&amp;quot;程序，他在初始化蓝色登陆屏幕前运行chkdsk(程序在屏幕上打印一串&amp;quot;.&amp;quot;)。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;当然，Win32应用程序环境服务程序:CSRSS.exe(客户-服务运行时间子系统)，也是一个Native应用程序。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;在这篇文章里，我将会讲述如何构造一个Native应用程序以及它们是如何工作的，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;同时我也会提供一个Native应用程序的示例源代码。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;这个示例很容易安装，它会在启动时的蓝色屏幕打印一段你指定的字符串。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&lt;font color="#0000ff"&gt;&lt;font size="3"&gt;&lt;strong&gt;Autochk&lt;/strong&gt;&lt;strong&gt;是如何被执行的&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;Autochk在当内存分页被打开，Windows启动和系统开始驱动被载入之间的时间内运行，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;在这个时间点会启动会话管理器(smss.exe)进入Windows NT用户模式，并且没有任何程序被启动。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;注册表中:&lt;/font&gt;&lt;font color="#9b00d3" size="2" face="Courier New"&gt;&lt;strong&gt;HKLM\System\CurrentControlSet\Control\Session Manager\BootExecute&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;一个MULTI_SZ类型的键值，这里存放着将被会话管理器所执行的程序名称和参数，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;通常是Autochk后加*号作为其参数&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#9b00d3" size="2" face="Courier New"&gt;Autocheck Autochk *     &lt;br /&gt;;名称 程序名 参数&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;会话管理器在&amp;lt;winnt&amp;gt;\system32目录下查找该值列出的可执行程序，当Autochk运行时，没有任何文件被打开，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;所以Autochk可以用raw模式打开任何一个驱动器卷(包括根驱动器)，并操作其磁盘数据结构，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;之后的任何时间点都无法进行类似这样的操作。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&lt;font color="#0000ff"&gt;&lt;font size="3"&gt;&lt;strong&gt;编译&lt;/strong&gt;&lt;strong&gt;Native&lt;/strong&gt;&lt;strong&gt;应用程序&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#000000" size="2" face="Courier New"&gt;1. 微软没有提供相应的文档，但是NT DDK构建器知道如何去生成一个Native应用程序，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#000000"&gt;&lt;font size="2" face="Courier New"&gt;而且它可以被用来编译autochk程序，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;和编写设备驱动程序一样，你必须指定SOURCE文件中的信息来定义应用程序，&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#000000"&gt;&lt;font size="2" face="Courier New"&gt;然而和编写驱动不同的时，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;你在SOURCE文件中要求生成一个Native应用程序需要这样定义:&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#000000" size="2" face="Courier New"&gt;TARGETTYPE=PROGRAM&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;font color="#000000"&gt;2. 构建器使用一个标准的makefile来进行向导:\ddk\inc\makefile.def 在编译Native应用程序时，&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#000000" size="2" face="Courier New"&gt;会查找名为nt.lib的运行库。不幸的是，微软并没在DDK上装载这个文件(在Windows Server 2003 DDK里包括了这个文件，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#000000" size="2" face="Courier New"&gt;但是我怀疑你用这个版本来连接你的Native应用程序是无法运行在Windows XP或Windows 2000上的）不管怎样，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#000000" size="2" face="Courier New"&gt;你可以忽略这个错误，方法是加入一行不考虑nt.lib，而指定Visual C++ 的运行库msvcrt.lib到makefile.lib中。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#000000" size="2" face="Courier New"&gt;3. 如果你在DDK的&amp;quot;Checked Build&amp;quot;环境下进行编译，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#000000" size="2" face="Courier New"&gt;将会在%BASEDIR%\lib\%CPU%\ Checked(例如c:\ddk\lib\i386\checked\ native.exe)&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#000000" size="2" face="Courier New"&gt;产生一个包含了全部调试信息的Native应用程序。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;font color="#000000"&gt;4. 如果在&amp;quot;Free Build&amp;quot;环境中编译，你会在%BASEDIR%\lib\%CPU%\Free得到一个释出版本的程序，&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#000000" size="2" face="Courier New"&gt;这些和构造设备驱动程序放置的位置是一样的。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;font color="#000000"&gt;5. Native应用程序有着&amp;quot;.exe&amp;quot;的扩展名，但是你不能像 Win32的.exe文件那样去运行它，&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#000000" size="2" face="Courier New"&gt;如果你在Win32环境下运行下，将会得到如下提示:&amp;quot;&amp;lt;应用程序名&amp;gt; 应用程序无法在Win32模式中运行。&amp;quot;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="3"&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;深入学习&lt;/strong&gt;&lt;strong&gt;Native&lt;/strong&gt;&lt;strong&gt;应用程序&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;1. Native应用程序的入口点是NtProcessStartup，类似WinMain或Main，不同于其他的 Win32入口点的是，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;Native应用程序提供一个数据结构来存放它的唯一的参数来定位命令行参数。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;2. 大多数的Native应用程序的运行环境是由Windows Nt的Native API输出库 - NTDLL.DLL提供的。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;3. Native应用程序必须使用RtlCreateHeap(一个ntdll函数)来创建他们自己的堆来分配存储，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;使用RtlAllocateHeap来分配内存以及用RtlFreeHeap来释放内存。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;4. Native应用程序需要使用NtDisplayString 函数才可以打印想要的内容到屏幕上(将被输出到初始化时的蓝色屏幕上)。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;5. Native应用程序不像Win32程序那样简单地从他们的启动函数返回，你需要调用NtProcessTerminate函数来结束它的进程。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;6. NTDLL运行包含了数百个函数允许Native应用程序执行文件I/O，与设备驱动进行相连，并执行进程间通讯。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;不幸的是，他们大部分都是未公开的。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&lt;font color="#0000ff"&gt;&lt;font size="3"&gt;&lt;b&gt;Native&lt;/b&gt;&lt;b&gt;应用程序实例&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;1. 我创建一个Native应用程序用来演示Native应用程序是如何构建的以及他们是如何工作的。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;运行install.bat来安装Native程序。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;2. 批处理程序复制Native.exe到你的&amp;lt;winnt&amp;gt;\system32目录，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;并在注册表中增加一个BootExecute的入口点: native Hello World!&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;3. 当你重新启动时，会话管理器运行完autochk后就会执行Native，Native分配一些堆，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;定位它的命令行参数并打印参数(&amp;quot;Hello world!&amp;quot;)到蓝色屏幕上，它所使用的函数上面已说过了。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;如果你想要打印其他的简单内容，可以编辑BootExecute值使用regedit或regedit32，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;修改&amp;quot;Hello world&amp;quot;为你想要的信息。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;4. 运行uinstall.bat可以卸载这个Native执行程序。它从&amp;lt;winnt&amp;gt;\system32 目录删除 Native.exe，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;并修改BootExecute值为通常的值。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;5. 如果你想要构建native程序你必须要用Windows设备驱动工具包(DDK)，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;复制makefile.def到 \ddk\inc然后你可以运行构建。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;font color="#0000ff" size="3" face="Courier New"&gt;Native.H&lt;/font&gt;&lt;/b&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="rem"&gt;//Environment information, which includes command line and image file name&lt;/span&gt;  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;typedef &lt;span class="kwrd"&gt;struct&lt;/span&gt;   &lt;span class="lnum"&gt;   3:  &lt;/span&gt;{  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;    ULONG            Unknown[21];       &lt;span class="lnum"&gt;   5:  &lt;/span&gt;    UNICODE_STRING   CommandLine;  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;    UNICODE_STRING   ImageFile;  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;} ENVIRONMENT_INFORMATION, *PENVIRONMENT_INFORMATION;  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;   &lt;span class="lnum"&gt;   9:  &lt;/span&gt;&lt;span class="rem"&gt;// This structure is passed as NtProcessStartup's parameter&lt;/span&gt;  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;typedef &lt;span class="kwrd"&gt;struct&lt;/span&gt;   &lt;span class="lnum"&gt;  11:  &lt;/span&gt;{  &lt;span class="lnum"&gt;  12:  &lt;/span&gt;    ULONG                     Unknown[3];  &lt;span class="lnum"&gt;  13:  &lt;/span&gt;    PENVIRONMENT_INFORMATION  Environment;  &lt;span class="lnum"&gt;  14:  &lt;/span&gt;} STARTUP_ARGUMENT, *PSTARTUP_ARGUMENT;  &lt;span class="lnum"&gt;  15:  &lt;/span&gt;   &lt;span class="lnum"&gt;  16:  &lt;/span&gt;&lt;span class="rem"&gt;// Data structure for heap definition. &lt;/span&gt;  &lt;span class="lnum"&gt;  17:  &lt;/span&gt;&lt;span class="rem"&gt;// This includes various sizing parameters and callback routines, &lt;/span&gt;  &lt;span class="lnum"&gt;  18:  &lt;/span&gt;&lt;span class="rem"&gt;// which, if left NULL, result in default behavior&lt;/span&gt;  &lt;span class="lnum"&gt;  19:  &lt;/span&gt;typedef &lt;span class="kwrd"&gt;struct&lt;/span&gt;   &lt;span class="lnum"&gt;  20:  &lt;/span&gt;{  &lt;span class="lnum"&gt;  21:  &lt;/span&gt;    ULONG     Length;  &lt;span class="lnum"&gt;  22:  &lt;/span&gt;    ULONG     Unknown[11];  &lt;span class="lnum"&gt;  23:  &lt;/span&gt;} RTL_HEAP_DEFINITION, *PRTL_HEAP_DEFINITION;  &lt;span class="lnum"&gt;  24:  &lt;/span&gt;   &lt;span class="lnum"&gt;  25:  &lt;/span&gt;&lt;span class="rem"&gt;// Native NT api function to write something to the boot-time&lt;/span&gt;  &lt;span class="lnum"&gt;  26:  &lt;/span&gt;&lt;span class="rem"&gt;// blue screen&lt;/span&gt;  &lt;span class="lnum"&gt;  27:  &lt;/span&gt;NTSTATUS NTAPI NtDisplayString(  &lt;span class="lnum"&gt;  28:  &lt;/span&gt;    PUNICODE_STRING String  &lt;span class="lnum"&gt;  29:  &lt;/span&gt;    );  &lt;span class="lnum"&gt;  30:  &lt;/span&gt;   &lt;span class="lnum"&gt;  31:  &lt;/span&gt;&lt;span class="rem"&gt;// Native applications must kill themselves when done - &lt;/span&gt;  &lt;span class="lnum"&gt;  32:  &lt;/span&gt;&lt;span class="rem"&gt;// the job of this native API&lt;/span&gt;  &lt;span class="lnum"&gt;  33:  &lt;/span&gt;NTSTATUS NTAPI NtTerminateProcess(  &lt;span class="lnum"&gt;  34:  &lt;/span&gt;    HANDLE ProcessHandle,   &lt;span class="lnum"&gt;  35:  &lt;/span&gt;    LONG ExitStatus   &lt;span class="lnum"&gt;  36:  &lt;/span&gt;    );  &lt;span class="lnum"&gt;  37:  &lt;/span&gt;   &lt;span class="lnum"&gt;  38:  &lt;/span&gt;&lt;span class="rem"&gt;// Definition to represent current process&lt;/span&gt;  &lt;span class="lnum"&gt;  39:  &lt;/span&gt;&lt;span class="preproc"&gt;#define&lt;/span&gt; NtCurrentProcess() ( (HANDLE) -1 )  &lt;span class="lnum"&gt;  40:  &lt;/span&gt;   &lt;span class="lnum"&gt;  41:  &lt;/span&gt;&lt;span class="rem"&gt;// Heap creation routine&lt;/span&gt;  &lt;span class="lnum"&gt;  42:  &lt;/span&gt;HANDLE NTAPI RtlCreateHeap(  &lt;span class="lnum"&gt;  43:  &lt;/span&gt;    ULONG Flags,   &lt;span class="lnum"&gt;  44:  &lt;/span&gt;    PVOID BaseAddress,   &lt;span class="lnum"&gt;  45:  &lt;/span&gt;    ULONG SizeToReserve,   &lt;span class="lnum"&gt;  46:  &lt;/span&gt;    ULONG SizeToCommit,   &lt;span class="lnum"&gt;  47:  &lt;/span&gt;    PVOID Unknown,  &lt;span class="lnum"&gt;  48:  &lt;/span&gt;    PRTL_HEAP_DEFINITION Definition  &lt;span class="lnum"&gt;  49:  &lt;/span&gt;    );  &lt;span class="lnum"&gt;  50:  &lt;/span&gt;   &lt;span class="lnum"&gt;  51:  &lt;/span&gt;&lt;span class="rem"&gt;// Heap allocation function (ala &amp;quot;malloc&amp;quot;)&lt;/span&gt;  &lt;span class="lnum"&gt;  52:  &lt;/span&gt;PVOID NTAPI RtlAllocateHeap(  &lt;span class="lnum"&gt;  53:  &lt;/span&gt;    HANDLE Heap,   &lt;span class="lnum"&gt;  54:  &lt;/span&gt;    ULONG Flags,   &lt;span class="lnum"&gt;  55:  &lt;/span&gt;    ULONG Size   &lt;span class="lnum"&gt;  56:  &lt;/span&gt;    );  &lt;span class="lnum"&gt;  57:  &lt;/span&gt;   &lt;span class="lnum"&gt;  58:  &lt;/span&gt;&lt;span class="rem"&gt;// Heap free function (ala &amp;quot;free&amp;quot;)&lt;/span&gt;  &lt;span class="lnum"&gt;  59:  &lt;/span&gt;BOOLEAN NTAPI RtlFreeHeap(  &lt;span class="lnum"&gt;  60:  &lt;/span&gt;    HANDLE Heap,   &lt;span class="lnum"&gt;  61:  &lt;/span&gt;    ULONG Flags,   &lt;span class="lnum"&gt;  62:  &lt;/span&gt;    PVOID Address   &lt;span class="lnum"&gt;  63:  &lt;/span&gt;    );&lt;/div&gt;&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="3" face="Courier New"&gt;Native.C&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="rem"&gt;//======================================================================&lt;/span&gt;  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="rem"&gt;//&lt;/span&gt;  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;&lt;span class="rem"&gt;// This is a demonstration of a Native NT program. These programs&lt;/span&gt;  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="rem"&gt;// run outside of the Win32 environment and must rely on the raw&lt;/span&gt;  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;span class="rem"&gt;// services provided by NTDLL.DLL. AUTOCHK (the program that executes&lt;/span&gt;  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;&lt;span class="rem"&gt;// a chkdsk activity during the system boot) is an example of a&lt;/span&gt;  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;&lt;span class="rem"&gt;// native NT application.&lt;/span&gt;  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;&lt;span class="rem"&gt;//&lt;/span&gt;  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;&lt;span class="rem"&gt;// This example is a native 'hello world' program. When installed with&lt;/span&gt;  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;&lt;span class="rem"&gt;// the regedit file associated with it, you will see it print &lt;/span&gt;  &lt;span class="lnum"&gt;  11:  &lt;/span&gt;&lt;span class="rem"&gt;// &amp;quot;hello world&amp;quot; on the initialization blue screen during the system&lt;/span&gt;  &lt;span class="lnum"&gt;  12:  &lt;/span&gt;&lt;span class="rem"&gt;// boot. This program cannot be run from inside the Win32 environment.&lt;/span&gt;  &lt;span class="lnum"&gt;  13:  &lt;/span&gt;&lt;span class="rem"&gt;//&lt;/span&gt;  &lt;span class="lnum"&gt;  14:  &lt;/span&gt;&lt;span class="rem"&gt;//======================================================================&lt;/span&gt;  &lt;span class="lnum"&gt;  15:  &lt;/span&gt;#include &lt;span class="str"&gt;&amp;quot;ntddk.h&amp;quot;&lt;/span&gt;  &lt;span class="lnum"&gt;  16:  &lt;/span&gt;#include &lt;span class="str"&gt;&amp;quot;stdio.h&amp;quot;&lt;/span&gt;  &lt;span class="lnum"&gt;  17:  &lt;/span&gt;#include &lt;span class="str"&gt;&amp;quot;native.h&amp;quot;&lt;/span&gt;  &lt;span class="lnum"&gt;  18:  &lt;/span&gt;   &lt;span class="lnum"&gt;  19:  &lt;/span&gt;&lt;span class="rem"&gt;// Our heap&lt;/span&gt;  &lt;span class="lnum"&gt;  20:  &lt;/span&gt;HANDLE Heap;  &lt;span class="lnum"&gt;  21:  &lt;/span&gt;&lt;span class="rem"&gt;//----------------------------------------------------------------------&lt;/span&gt;  &lt;span class="lnum"&gt;  22:  &lt;/span&gt;&lt;span class="rem"&gt;// NtProcessStartup&lt;/span&gt;  &lt;span class="lnum"&gt;  23:  &lt;/span&gt;&lt;span class="rem"&gt;// Instead of a 'main', NT applications are entered via this entry point.  &lt;/span&gt;  &lt;span class="lnum"&gt;  24:  &lt;/span&gt;&lt;span class="rem"&gt;//----------------------------------------------------------------------&lt;/span&gt;  &lt;span class="lnum"&gt;  25:  &lt;/span&gt;&lt;span class="kwrd"&gt;void&lt;/span&gt; NtProcessStartup( PSTARTUP_ARGUMENT Argument )  &lt;span class="lnum"&gt;  26:  &lt;/span&gt;{  &lt;span class="lnum"&gt;  27:  &lt;/span&gt;    PUNICODE_STRING commandLine;  &lt;span class="lnum"&gt;  28:  &lt;/span&gt;    PWCHAR stringBuffer;  &lt;span class="lnum"&gt;  29:  &lt;/span&gt;    PWCHAR argPtr;  &lt;span class="lnum"&gt;  30:  &lt;/span&gt;    UNICODE_STRING helloWorld;  &lt;span class="lnum"&gt;  31:  &lt;/span&gt;    RTL_HEAP_DEFINITION  heapParams;  &lt;span class="lnum"&gt;  32:  &lt;/span&gt;      &lt;span class="lnum"&gt;  33:  &lt;/span&gt;    &lt;span class="rem"&gt;// Initialize some heap&lt;/span&gt;  &lt;span class="lnum"&gt;  34:  &lt;/span&gt;    memset( &amp;amp;heapParams, 0, &lt;span class="kwrd"&gt;sizeof&lt;/span&gt;( RTL_HEAP_DEFINITION ));  &lt;span class="lnum"&gt;  35:  &lt;/span&gt;    heapParams.Length = &lt;span class="kwrd"&gt;sizeof&lt;/span&gt;( RTL_HEAP_DEFINITION );  &lt;span class="lnum"&gt;  36:  &lt;/span&gt;    Heap = RtlCreateHeap( 2, 0, 0x100000, 0x1000, 0, &amp;amp;heapParams );  &lt;span class="lnum"&gt;  37:  &lt;/span&gt;      &lt;span class="lnum"&gt;  38:  &lt;/span&gt;    &lt;span class="rem"&gt;// Point at command line&lt;/span&gt;  &lt;span class="lnum"&gt;  39:  &lt;/span&gt;    commandLine = &amp;amp;Argument-&amp;gt;Environment-&amp;gt;CommandLine;  &lt;span class="lnum"&gt;  40:  &lt;/span&gt;    &lt;span class="rem"&gt;// Locate the argument&lt;/span&gt;  &lt;span class="lnum"&gt;  41:  &lt;/span&gt;    argPtr = commandLine-&amp;gt;Buffer;  &lt;span class="lnum"&gt;  42:  &lt;/span&gt;    &lt;span class="kwrd"&gt;while&lt;/span&gt;( *argPtr != L&lt;span class="str"&gt;' '&lt;/span&gt; )  &lt;span class="lnum"&gt;  43:  &lt;/span&gt;    {  &lt;span class="lnum"&gt;  44:  &lt;/span&gt;        argPtr++;  &lt;span class="lnum"&gt;  45:  &lt;/span&gt;    }  &lt;span class="lnum"&gt;  46:  &lt;/span&gt;    argPtr++;  &lt;span class="lnum"&gt;  47:  &lt;/span&gt;      &lt;span class="lnum"&gt;  48:  &lt;/span&gt;    &lt;span class="rem"&gt;// Print out the argument&lt;/span&gt;  &lt;span class="lnum"&gt;  49:  &lt;/span&gt;    stringBuffer = RtlAllocateHeap( Heap, 0, 256 );  &lt;span class="lnum"&gt;  50:  &lt;/span&gt;    swprintf( stringBuffer, L&lt;span class="str"&gt;&amp;quot;\n%s&amp;quot;&lt;/span&gt;, argPtr );  &lt;span class="lnum"&gt;  51:  &lt;/span&gt;   &lt;span class="lnum"&gt;  52:  &lt;/span&gt;    helloWorld.Buffer = stringBuffer;  &lt;span class="lnum"&gt;  53:  &lt;/span&gt;    helloWorld.Length = wcslen( stringBuffer ) * &lt;span class="kwrd"&gt;sizeof&lt;/span&gt;(WCHAR);  &lt;span class="lnum"&gt;  54:  &lt;/span&gt;    helloWorld.MaximumLength = helloWorld.Length + &lt;span class="kwrd"&gt;sizeof&lt;/span&gt;(WCHAR);  &lt;span class="lnum"&gt;  55:  &lt;/span&gt;   &lt;span class="lnum"&gt;  56:  &lt;/span&gt;    NtDisplayString( &amp;amp;helloWorld );  &lt;span class="lnum"&gt;  57:  &lt;/span&gt;      &lt;span class="lnum"&gt;  58:  &lt;/span&gt;    &lt;span class="rem"&gt;// Free heap&lt;/span&gt;  &lt;span class="lnum"&gt;  59:  &lt;/span&gt;    RtlFreeHeap( Heap, 0, stringBuffer );  &lt;span class="lnum"&gt;  60:  &lt;/span&gt;   &lt;span class="lnum"&gt;  61:  &lt;/span&gt;    &lt;span class="rem"&gt;// Terminate&lt;/span&gt;  &lt;span class="lnum"&gt;  62:  &lt;/span&gt;    NtTerminateProcess( NtCurrentProcess(), 0 );  &lt;span class="lnum"&gt;  63:  &lt;/span&gt;}&lt;/div&gt;&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="3" face="Courier New"&gt;Install.bat：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;@echo off  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;copy native.exe %systemroot%\system32\.  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;regedit /s add.reg  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;echo Native Example Installed&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="3" face="Courier New"&gt;&lt;strong&gt;UnInstall.bat：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;@echo off  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;del %systemroot%\system32\native.exe  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;regedit /s remove.reg  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;echo Native Example Uninstalled&lt;/div&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;6. 互联网上其他关于 Native Application 的文章整理：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;下面给出的则是我在互联网上其他地方找到的关于 Native Application 的比较好的资料，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;这里也只是将这些资料进行一个整理。 &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;《native app 开发小结（一）》：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://hi.baidu.com/316526334/blog/item/32823e8a83d87b1fc9fc7a0f.html"&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;http://hi.baidu.com/316526334/blog/item/32823e8a83d87b1fc9fc7a0f.html&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;《native app 开发小结（二）》：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://hi.baidu.com/316526334/blog/item/43a21061ad619cd28cb10d08.html"&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;http://hi.baidu.com/316526334/blog/item/43a21061ad619cd28cb10d08.html&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;《Native Application 应用之开机杀毒》：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cublog.cn/u/8754/showart_447592.html"&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;http://www.cublog.cn/u/8754/showart_447592.html&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="3" face="Courier New"&gt;&lt;strong&gt;程序类型&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;关于程序级别的分类，大概可以分为三层：&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;应用层程序，即普通的APP程序；&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;Native App程序，如常见的chkdsk工具，PQ分区工具等，都属于这类，它是在win子系统未启动起来就执行的程序，执行环境比较纯净，只能调用ntdll.dll导出的函数；&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;Driver 内核驱动程序，因功能不同也分为若干类，如设备驱动程序，内核扩展程序，文件系统驱动，过滤驱动等，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;同属于内核态程序；&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;其中，native app在项目开发中用的较少，所用的函数接口MS也均未公开，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;开发难度和驱动相当，所以很少有人问津。但是，事实上，在某些应用场景下，用native app来实现是非常完美的，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;比如：接管winodws的开机启动界面和密码输入界面，需要native app；&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;在开机前，执行磁盘修复，需要native app；开机前，执行杀毒，或者磁盘整理，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;因为此时环境比较纯净，需要native app。诸如此类~ &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;最近，开发一个Native App项目，其规模和复杂度也不一般。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;期间遇到很多问题，在逐一解决的时候也收获了很多东西。现在略作整理，以备将来查用，二来与大家分享之~&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="3" face="Courier New"&gt;&lt;strong&gt;Native app 基本工作原理&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;这里，只想简单的描述下。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;Windows的设计是基于分层模型的，在设计之初，内核NT支持三个子系统，OS/2,posix,win32,&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;这些子系统同属于一个层面上，它们公用windows nt提供的系统API和例程。其中，在某一个子系统上的API调用，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;都会经过NT”native”API同windowsNT进行通信。这些native API就是ntdll.dll导出的函数，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;因为它导出的大部分函数都只是起一个从子系统到NT内核的转发传递作用，所以也成为stub函数，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;这些函数的原型大多是未公开的，在早期的DDK里会有相关的描述，但是现在没了，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;取而代之的是内核实现的zw*,nt*开头的驱动函数。这里表明了MS的一个态度，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;不希望第三方在native app上干涉windows的太多工作，比如，接管了开机启动系统，接管了登录密码界面:D. &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;后来，因为种种历史原因，对OS/2和posix子系统的支持逐渐被淡忘。但是这种分层模型仍然存在，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;native app就是工作在子系统未启动之前，此时的系统环境很纯净，权限也相对较高；&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;另外，对操作系统来说，支持native app也是一种必须，因为在子系统启动之前，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;很多功能的程序只能以native app来呈现，比如登录界面，CSRSS~&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;具体的启动时机：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;Native app由启动会话管理器(smss.exe)来启动，如果想通知smss来执行一个native app程序，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;只需要修改一个注册表项，smss在每次启动的时候会去检查该项，确保该项下面的每个native app程序依次执行。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;注册表项为：HKLM\System\CurrentControlSet\Control\Session Manager\BootExecute ，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;其类型为MULTI_SZ, 又是MS玩的一种字符串类型—多字符串类型，也就是说，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;这个MULTI_SZ字符串包含多个以\0结尾的子字符串，而整个字符串以\0\0结尾。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;在该注册表项后面添加要注册的native 程序名和参数就可以了。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;关于native app的更多详细介绍，可以参考Mark Russinovich的一篇关于native的文章。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="3" face="Courier New"&gt;&lt;strong&gt;Native app程序结构&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;Native app程序结构很简单，就好像我们写hello world，需要写一个main函数入口一样，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;native app的入口函数是NtProcessStartup，形如：&lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;void&lt;/span&gt; NtProcessStartup( PSTARTUP_ARGUMENT Argument )&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;其中，参数PSTARTUP_ARGUMENT是一个结构体，用来存放传入参数。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;程序退出时，主动调用函数NtProcessTerminate退出，它不会像普通应用程序一样一个返回return就退出了。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;基本的结构就是这样了：&lt;/font&gt;&lt;/p&gt;&lt;font size="2" face="Courier New"&gt;  &lt;p class="csharpcode"&gt;&lt;/p&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;void&lt;/span&gt; NtProcessStartup( PSTARTUP_ARGUMENT Argument )  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;{  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;span class="rem"&gt;// do something else&lt;/span&gt;  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;NtProcessTerminate( NtCurrentProcess(), 0 );  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;}  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;&amp;#160;  &lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;当然现在还没有包含头文件之类的。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;/font&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;font color="#0000ff" size="3" face="Courier New"&gt;&lt;strong&gt;开发语言及第三方的库&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt; &lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;Native app支持的开发语言有C/ASM/C++,并且完美的支持C++的类特性,不过要像编写驱动一样，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;需要重载new,delete等内存分配函数。&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;在内存使用上，可以使用两套接口：堆函数接口，以及虚拟内存函数接口，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;但是根据我的经验，使用堆函数接口，更高效并且内存bug出现的频率会大大降低。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;举个例子：我在调试native app的时候，一切正常，且全部通过，但是双机调试的时候，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;功能代码都运行完了，在子系统起来的时候，提示memory_corruption错误，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;这个问题整整找了好几天都没有找到，到最后，无意间屏蔽掉了系统的DbgPrint函数，memory错误才解决。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;其原因是，native gui图形模块的debug消息打印的太快太频繁，导致调试缓冲被溢出，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;当屏蔽了系统DbgPrint的时候，也就是在windbg 下bp DbgPrint,然后a eip,ret后，就正常了。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;虽然这个现象和程序无关，但是，用了虚拟内存的话，这个问题会更加容易重现。关于这个问题的重现很容易，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;就是在native 环境下双机调试，target机器一直打印消息，当打印到10W条以上时，调试缓冲就“爆”了。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;这真不知道是ms的bug，还是自己~~&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="3" face="Courier New"&gt;&lt;strong&gt;关于 new, delete 的重载。&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;使用堆函数过程如下：首先创建一个全局堆，然后在这个全局堆上分配和释放局部堆。&lt;/font&gt;&lt;/p&gt;&lt;font size="2" face="Courier New"&gt;  &lt;p class="csharpcode"&gt;&lt;/p&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;HANDLE hGlobalHeap = NULL; &lt;span class="rem"&gt;// for globle call&lt;/span&gt;  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;&lt;span class="kwrd"&gt;void&lt;/span&gt;* __cdecl &lt;span class="kwrd"&gt;operator&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt;(size_t size)  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;{  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt;(hGlobalHeap == NULL)  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;             &lt;span class="kwrd"&gt;return&lt;/span&gt; NULL;  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; RtlAllocateHeap(hGlobalHeap,0&lt;span class="rem"&gt;/*HEAP_ZERO_MEMORY*/&lt;/span&gt;,size);  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;}  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  11:  &lt;/span&gt;&lt;span class="kwrd"&gt;void&lt;/span&gt; __cdecl &lt;span class="kwrd"&gt;operator&lt;/span&gt; delete(&lt;span class="kwrd"&gt;void&lt;/span&gt;* addr)  &lt;span class="lnum"&gt;  12:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  13:  &lt;/span&gt;{  &lt;span class="lnum"&gt;  14:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt;(hGlobalHeap &amp;amp;&amp;amp; addr) (&lt;span class="kwrd"&gt;void&lt;/span&gt;)RtlFreeHeap(hGlobalHeap,0,addr);  &lt;span class="lnum"&gt;  15:  &lt;/span&gt;}  &lt;span class="lnum"&gt;  16:  &lt;/span&gt;&amp;#160;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;/p&gt;  &lt;p&gt;关于 NDK：前面说到，native app用的是ntdll.dll的导出函数，而这些函数MS并没有公开接口声明，&lt;/p&gt;  &lt;p&gt;那么我们使用的时候，首先必须要自己定义函数声明。&lt;/p&gt;  &lt;p&gt;NDK就是这样的一个类库，它几乎定义了ntdll.dll导出的全部函数的声明以及一些常用的数据结构的定义，&lt;/p&gt;  &lt;p&gt;我们只需要包含相应的头文件，导入ntdll.lib库，就可以像使用普通的API函数一样开发native app了。&lt;/p&gt;&lt;/font&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;关于DLL：native app可以调用同一级别的DLL，使大型的项目开发更加容易，更加容易划分模块。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;注意，DLL的编译环境要和native app一致。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;关于native app的编译：可以选择用vs环境，也可以用DDK/WDK，但是推荐使用WDK。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;用VS环境的话，需要简单的设置下，随意创建一个类型的工程，然后修改Linker-&amp;gt;system-&amp;gt;Native，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;就可以了。如果用WDK编译，需要写一个SOURCE模板，如：&lt;/font&gt;&lt;/p&gt;&lt;font size="2" face="Courier New"&gt;  &lt;p class="csharpcode"&gt;&lt;/p&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;TARGETNAME=defrag  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;TARGETPATH=obj  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;TARGETTYPE=PROGRAM  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;INCLUDES=$(PUBLIC_ROOT)\inc\ddk  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;SOURCES=defrag.cpp  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;&amp;#160;  &lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;注意：上面说的DLL的编译环境和native app的编译环境要一致，&lt;/p&gt;  &lt;p&gt;指的是不要用WDK编译的native去尝试链接VS编译的DLL,反之亦然。 &lt;/p&gt;  &lt;div class="csharpcode"&gt;    &lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="rem"&gt;//NTSTATUS NTAPI NtDisplayString( PUNICODE_STRING String);&lt;/span&gt;    &lt;font color="#0000ff" size="3" face="Courier New"&gt;&lt;strong&gt;              &lt;/strong&gt;&lt;/font&gt;  &lt;/div&gt;&lt;/font&gt;&lt;p&gt;&lt;font color="#0000ff" size="3" face="Courier New"&gt;&lt;strong&gt;Native GUI&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;在native app执行环境下画界面是不可行的，但是不是说做不到。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;前面说了，可以写一个native app来接管windows的启动界面和密码输入界面，那么这个界面是如何画的呢？&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;也有从驱动里实现的。但是，事实上，MS提供了一个native级别的动态库，名为:Bootvid.dll，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;用来实现GUI启动屏幕的引导视频驱动，这个dll导出了一些函数，可以实现画图，贴图功能，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;当然，这些函数接口仍然是未公开的。呵呵~&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;另外，在native app程序，可以利用一个函数向屏幕打印输出字符串，名为：&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;但是，事实上，这个函数已经不推荐使用了，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;在用WDK编译native app的时候，会提示一个警告信息，deprecated~~&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="3" face="Courier New"&gt;&lt;strong&gt;Native app的灵活性&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;native app由于受到调用函数接口未公开，以及开发难度和调试难度不小的原因，很少有项目问津，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;但是，事实上，它仍然是一种工作于ring3的用户态程序，只是在子系统启动之前运行，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;所以，native app程序一般不会引起系统蓝屏的问题。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;也正是如此，native 程序工作在一个相对纯净的环境下，可以访问任何文件，甚至搬移MFT，系统元文件等。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;Ntdll.dll为native app导出的函数虽少，但是可以完成很多的功能。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;这些导出函数，基本上和内核的系统例程都是一一对应的。结合其他的模块，driver,应用程app,&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;在加之native独特的运行环境和执行能力，往往会达到一个良好的效果。在这里，仅仅是一个普及~&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="3" face="Courier New"&gt;&lt;strong&gt;具体应用及实例&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;在开发native app之前，我想，最好有开发驱动的基础。因为native app程序的编写规范基本上和驱动一样，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;除了入口函数，调试方法也一样，必须要双机调试。当然，只是说编写规则一样，驱动特有的函数例程以及工作原理，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;二者是毫不相干的。举个例子，操作注册表，文件IO，线程创建，内存使用，二者基本上是一致的，具体的在使用中自己体会吧。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="3" face="Courier New"&gt;&lt;strong&gt;作为入门例子&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;作为入门我想还是用Mark Russinovich的例子吧，就好像Hello World的作用一样，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;让你真切的感受下native app程序。该程序在系统启动时，蓝屏界面上输出一行字符串信息。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;程序在附件，没什么过多的需要解释的。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="3" face="Courier New"&gt;&lt;strong&gt;实际开发&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;实际开发中，有不少的应用例子。比如，影子系统的启动界面，PQ分区工具，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;win系统自带的chkdsk工具，都属于这类程序。&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;下面说下自己的一些经历吧：&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;项目中有个需要，对特定文件进行磁盘整理。我们知道，文件系统导出了一组函数接口，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;用于对磁盘上的文件进行搬移操作，使文件内碎片和外碎片减少，提高IO吞吐率和磁盘访问率。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;唯一的限制是，pagefile.sys和日志文件不能整理，其他的文件，如MFT,系统元文件都可以整理。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;对于文件整理，更重要的是算法和稳定法，当然，这是另外一个话题了。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;根据prefreth原理，一个应用程序的工作集页面在运行时基本上是趋于稳定的，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;那么这些稳定的页面如果位于不同的文件（可能是链接库之类），且这些文件在磁盘上比较分散，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;那么就会影响程序的启动时间了，虽然prefretch做了改善，会自动的激发系统的磁盘整理来对“相关”的文件紧密排放，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;但仍然是不够的。所以，关于这种性能的改善看起来微乎其微，但是做好了，价值是不可估量的。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;这仅仅是一个方面，当然，项目中的主要目的并不是这个，虽然也是为了提高性能。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;在native app下操作文件，考虑的情况是比较单一的，不会担心文件或目录被锁，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;从而出现不能访问的情况，也不会考虑过多的并发问题。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;所以，功能会更加集中，运行效率会更高，操作的空间和权限也更大。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;仅限于此，就到这吧 ~&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;7. 小结：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;上面的文字呢就大体的把 Native Application 给介绍的差不多了，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;主要是总结了一下自己关于 Native Application 的理解，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后再将 MJ0011 和互联网上的几位博主的文章给整理了一下(原博文排版不怎么好)，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;这里对 MJ0011 以及所整理的文章的博主表示感谢 ~ &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;博文中的 Demo 我是采用的 DDK 2600.1106 编译的，至于 WDK 7 的话，我没有去试哦 ~ &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;有兴趣的可以直接下载了 Demo 进行测试的，代码什么的都在里面，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;source 和 makefile 我也都整理好了放在 Demo 中 ~ &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;最后还是和以往一样，给出些我近来的一些疑问:&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;我曾经从一台电脑 A 上下载了卡巴斯基的试用版，然后我将这个试用版的安装文件拷贝到了电脑 B 上，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;这时我发现卡巴斯基的这个安装文件在电脑 B 上是无法运行的 ~ 直接报错，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;当然，这个安装文件在电脑 A 上是可以运行安装的，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;我想应该是卡巴斯基的这个安装文件在拷贝的过程中还是下载的过程中记录下了我的电脑 A，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;然后在安装的时候，其自动判断是否是在电脑 A 上安装运行，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;如果是的话，则可以成功安装，如果不是，则直接报错 ~ &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;我想知道上面是怎么来实现的呢 ? 我只是下载和拷贝了一下哦 ~ &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;还有就是貌似要考个微软的 MCTS 证书，&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;应该是 Windows 方向的 71-511 或者 Web 方向的 71-515 这两门考试，&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;不晓得大伙有什么好建议或者好的资料没有哦 ~ 可否提供一些呢 ~ 谢谢咯 ~ &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;然后再问一下哦，有没有湖南娄底的啊 ? 国庆组队回去否 ?(我在深圳 ~)&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="3" face="Courier New"&gt;&lt;strong&gt;&lt;u&gt;下载 Demo&lt;/u&gt;&lt;/strong&gt;&lt;/font&gt;&lt;a href="http://files.cnblogs.com/BoyXiao/NativeApp.zip"&gt;&lt;font color="#ff0000" size="3" face="Courier New"&gt;&lt;strong&gt; Source Code&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;font color="#ff0000" size="3" face="Courier New"&gt;&lt;strong&gt;&lt;u&gt; &lt;/u&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;font face="Verdana"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;strong&gt;版权所有，&lt;strong&gt;欢&lt;/strong&gt;迎转载，但转载请注明： 转载自&amp;#160; &lt;/strong&gt;&lt;strong&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/"&gt;&lt;strong&gt;Zachary.XiaoZhen - 梦想的天空&lt;/strong&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/BoyXiao/aggbug/2183059.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/archive/2011/09/21/2183059.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/BoyXiao/archive/2011/09/05/2168115.html</id><title type="text">进程隐藏与进程保护（SSDT Hook 实现）（三）</title><summary type="text">文章目录： 1. 引子： 2. 获取当前系统下所有进程： 3. 服务管理（安装，启动，停止，卸载）： 4. 应用程序和内核程序通信： 5. 小结： 1. 引子： 关于这个 SSDT Hook 实现进程隐藏和进程保护呢，这是最后一篇博文了， 在文章的结...</summary><published>2011-09-05T15:03:00Z</published><updated>2011-09-05T15:03:00Z</updated><author><name>Zachary.XiaoZhen</name><uri>http://www.cnblogs.com/BoyXiao/</uri></author><link rel="alternate" href="http://www.cnblogs.com/BoyXiao/archive/2011/09/05/2168115.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BoyXiao/archive/2011/09/05/2168115.html"/><content type="html">&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;文章目录：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;1. 引子：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;2. 获取当前系统下所有进程：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;3. 服务管理（安装，启动，停止，卸载）：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;4. 应用程序和内核程序通信：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;5. 小结：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;1. 引子：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;关于这个 SSDT Hook 实现进程隐藏和进程保护呢，这是最后一篇博文了，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;在文章的结尾处呢你可以下载到整个项目的实例程序以及代码，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;程序可以在 XP、Server、Win7 上运行的，当然我是说的 32 位操作系统。&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;《进程隐藏与进程保护(SSDT Hook 实现)(一)》呢把 SSDT Hook 的原理说得差不多了，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;博文地址：&lt;/strong&gt;&lt;/font&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/archive/2011/09/03/2164574.html"&gt;&lt;font size="2" face="Courier New"&gt;http://www.cnblogs.com/BoyXiao/archive/2011/09/03/2164574.html&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;《进程隐藏与进程保护(SSDT Hook 实现)(二)》则把 SSDT Hook 的实现说得差不多了，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;博文地址：&lt;/strong&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/archive/2011/09/04/2166596.html"&gt;http://www.cnblogs.com/BoyXiao/archive/2011/09/04/2166596.html&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;这一篇博文介绍的则是在 Ring3 下编写 MFC 应用程序，并且让应用程序与内核程序通信，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;即由应用程序将需要隐藏的进程或者是需要保护的进程的 PID 传递给内核程序，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后在内核程序中就会将传递进来的这个 PID 进行隐藏或者保护 ~ &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;在这里再给出这个应用程序的一张截图：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109052303087302.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109052303211720.png" width="854" height="670" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;2. 获取当前系统下所有进程：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;前面提到过，要想获取到系统下的所有进程，有三种方法，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;第一种即是使用 ToolHelp 来获取，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;第二种则是使用 PSAPI 来获取，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;第三种则是使用 ntdll.dll 中的未文档化的 NtQuerySystemInformation 之类的 API 来获取(比较麻烦)。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而在这里我使用最简单的方式，即通过 PSAPI 中的 EnumProcesses 这个 API 来获取，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;EnumProcesses API 可以获取到当前系统下所有进程的 PID，并且将 PID 存放在作为输出参数的数组当中，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;其原型如下（可以看 MSDN）：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;span class="lnum"&gt;   1:  &lt;/span&gt;BOOL WINAPI EnumProcesses(  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;  __out         DWORD* pProcessIds,  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;  __in          DWORD cb,  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;  __out         DWORD* pBytesReturned  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;);  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;&amp;#160;&lt;/div&gt;&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;代码中使用(将获取到所有的 PID，然后将 PID 保存到 vector 容器中)：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="rem"&gt;//遍历当前所有的进程，并且将进程 ID 填充到容器 vectorPID 中&lt;/span&gt;  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;void&lt;/span&gt; CSSDTProcessDlg::FillPIDVector()  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;{  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;    DWORD dwPIDArray[MAX_PROCESS_COUNT];  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;    DWORD dwNeededBytes;  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;    DWORD dwProcCount;  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;    dwNeededBytes = 0;  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;    dwProcCount = 0;  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;    memset(dwPIDArray, 0, &lt;span class="kwrd"&gt;sizeof&lt;/span&gt;(DWORD) * MAX_PROCESS_COUNT);  &lt;span class="lnum"&gt;  11:  &lt;/span&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt;(NULL != EnumProcesses(dwPIDArray, &lt;span class="kwrd"&gt;sizeof&lt;/span&gt;(dwPIDArray), &amp;amp;dwNeededBytes))  &lt;span class="lnum"&gt;  12:  &lt;/span&gt;    {  &lt;span class="lnum"&gt;  13:  &lt;/span&gt;        dwProcCount = dwNeededBytes / &lt;span class="kwrd"&gt;sizeof&lt;/span&gt;(DWORD);  &lt;span class="lnum"&gt;  14:  &lt;/span&gt;    }  &lt;span class="lnum"&gt;  15:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  16:  &lt;/span&gt;    BubbleSort(dwPIDArray, dwProcCount);  &lt;span class="lnum"&gt;  17:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  18:  &lt;/span&gt;    ClearVector();  &lt;span class="lnum"&gt;  19:  &lt;/span&gt;    &lt;span class="kwrd"&gt;for&lt;/span&gt;(&lt;span class="kwrd"&gt;int&lt;/span&gt; i=0; i&amp;lt;dwProcCount; i++)  &lt;span class="lnum"&gt;  20:  &lt;/span&gt;    {  &lt;span class="lnum"&gt;  21:  &lt;/span&gt;        PROCESS_BIND procBind;  &lt;span class="lnum"&gt;  22:  &lt;/span&gt;        procBind.dwPID = dwPIDArray[i];  &lt;span class="lnum"&gt;  23:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt;(dwPIDArray[i] == 0)  &lt;span class="lnum"&gt;  24:  &lt;/span&gt;        {  &lt;span class="lnum"&gt;  25:  &lt;/span&gt;            procBind.state = ProcessStateUnknown;  &lt;span class="lnum"&gt;  26:  &lt;/span&gt;        }  &lt;span class="lnum"&gt;  27:  &lt;/span&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt;  &lt;span class="lnum"&gt;  28:  &lt;/span&gt;        {  &lt;span class="lnum"&gt;  29:  &lt;/span&gt;            procBind.state = ProcessStateGeneral;  &lt;span class="lnum"&gt;  30:  &lt;/span&gt;        }  &lt;span class="lnum"&gt;  31:  &lt;/span&gt;        &lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;m_vctAllProcess.push_back(procBind);  &lt;span class="lnum"&gt;  32:  &lt;/span&gt;    }  &lt;span class="lnum"&gt;  33:  &lt;/span&gt;}&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;3. 服务管理（安装，启动，停止，卸载）：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;在 Windows 内核程序中，现在大体可以分为三类了，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;第一类是 NT 式驱动程序；&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;第二类为 WDM 驱动程序；&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;第三类为 WDF 驱动程序；&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;其中，对于 NT 式驱动程序，其安装方式是很简单的，因为你可以将 NT 式驱动程序看做一个服务，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;既然是服务的话，自然在 Windows 中可以通过 SCM API 来完成其安装，启动，停止和卸载等功能 ~&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;而至于 WDM 和 WDF 的话，如果其中涉及到了设备的话，还必须使用 INF 文件来实现安装 ~ &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;而我们前面的那个 SSDT 内核程序就是基于 NT 式的驱动程序，所以可以通过 SCM API 来实现上面的这些功能，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;至于如何使用 SCM API 来完成服务的安装、启动、停止和卸载功能的话，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;可以参见笔者的另外一篇博文&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;《Windows 服务(附服务开发辅助工具)》，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;博文地址为：&lt;/strong&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/archive/2011/08/07/2130208.html"&gt;http://www.cnblogs.com/BoyXiao/archive/2011/08/07/2130208.html&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;下面就只是将服务的安装 API、启动 API、停止 API 和卸载 API 贴出来了 ~&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;至于这些代码的细细道来的话，可以参加上面给出的那篇博文的 ~ &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="rem"&gt;//Name: bool InstallSvc()                                                              //&lt;/span&gt;  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;&lt;span class="rem"&gt;//                                                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="rem"&gt;//Descripion: 安装服务                                                                 //&lt;/span&gt;  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;span class="rem"&gt;//            lpszSvcName 为服务名称，                                                 //&lt;/span&gt;  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;&lt;span class="rem"&gt;//            lpszDisplay 为显示在服务控制管理器中的名称，                             //&lt;/span&gt;  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;&lt;span class="rem"&gt;//            lpszSvcBinaryPath 为服务映像文件所在路径，                               //&lt;/span&gt;  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;&lt;span class="rem"&gt;//            dwSvcType 为服务类型                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;&lt;span class="rem"&gt;//            dwStartType 为服务启动类型                                               //&lt;/span&gt;  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;  11:  &lt;/span&gt;&lt;span class="kwrd"&gt;bool&lt;/span&gt; CSSDTProcessDlg::InstallSvc(LPTSTR lpszSvcName, LPTSTR lpszDisplayName,  &lt;span class="lnum"&gt;  12:  &lt;/span&gt;        LPTSTR lpszSvcBinaryPath, DWORD dwSvcType, DWORD dwStartType)  &lt;span class="lnum"&gt;  13:  &lt;/span&gt;{  &lt;span class="lnum"&gt;  14:  &lt;/span&gt;    SC_HANDLE hSCM = NULL;  &lt;span class="lnum"&gt;  15:  &lt;/span&gt;    SC_HANDLE hSvc = NULL;  &lt;span class="lnum"&gt;  16:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  17:  &lt;/span&gt;    AdjustProcessTokenPrivilege();  &lt;span class="lnum"&gt;  18:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  19:  &lt;/span&gt;    hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);  &lt;span class="lnum"&gt;  20:  &lt;/span&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt;(NULL == hSCM)  &lt;span class="lnum"&gt;  21:  &lt;/span&gt;    {  &lt;span class="lnum"&gt;  22:  &lt;/span&gt;        OutputErrorMessage(TEXT(&lt;span class="str"&gt;&amp;quot;InstallSvc - OpenSCManager Failed , Error Code Is %d , Error Message Is %s !&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt;  23:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  24:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; FALSE;  &lt;span class="lnum"&gt;  25:  &lt;/span&gt;    }  &lt;span class="lnum"&gt;  26:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  27:  &lt;/span&gt;    &lt;span class="kwrd"&gt;for&lt;/span&gt;(&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; 3 &amp;amp;&amp;amp; (NULL == hSvc); i++)  &lt;span class="lnum"&gt;  28:  &lt;/span&gt;    {  &lt;span class="lnum"&gt;  29:  &lt;/span&gt;        &lt;span class="rem"&gt;//SERVICE_WIN32_OWN_PROCESS  | SERVICE_INTERACTIVE_PROCESS&lt;/span&gt;  &lt;span class="lnum"&gt;  30:  &lt;/span&gt;        hSvc = CreateService(hSCM, lpszSvcName, lpszDisplayName, SERVICE_ALL_ACCESS,   &lt;span class="lnum"&gt;  31:  &lt;/span&gt;            dwSvcType, dwStartType, SERVICE_ERROR_NORMAL,   &lt;span class="lnum"&gt;  32:  &lt;/span&gt;            lpszSvcBinaryPath, NULL, NULL, NULL, NULL, NULL);  &lt;span class="lnum"&gt;  33:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt;(NULL != hSvc)  &lt;span class="lnum"&gt;  34:  &lt;/span&gt;        {  &lt;span class="lnum"&gt;  35:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt;(NULL != hSvc)  &lt;span class="lnum"&gt;  36:  &lt;/span&gt;            {  &lt;span class="lnum"&gt;  37:  &lt;/span&gt;                CloseServiceHandle(hSvc);  &lt;span class="lnum"&gt;  38:  &lt;/span&gt;            }  &lt;span class="lnum"&gt;  39:  &lt;/span&gt;            CloseServiceHandle(hSCM);  &lt;span class="lnum"&gt;  40:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; TRUE;  &lt;span class="lnum"&gt;  41:  &lt;/span&gt;        }  &lt;span class="lnum"&gt;  42:  &lt;/span&gt;    }  &lt;span class="lnum"&gt;  43:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  44:  &lt;/span&gt;    OutputErrorMessage(TEXT(&lt;span class="str"&gt;&amp;quot;InstallSvc - CreateService Failed , Error Code Is %d , Error Message Is %s !&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt;  45:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  46:  &lt;/span&gt;    CloseServiceHandle(hSCM);  &lt;span class="lnum"&gt;  47:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  48:  &lt;/span&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; FALSE;  &lt;span class="lnum"&gt;  49:  &lt;/span&gt;}  &lt;span class="lnum"&gt;  50:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  51:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  52:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;  53:  &lt;/span&gt;&lt;span class="rem"&gt;//Name: bool UnInstallSvc()                                                            //&lt;/span&gt;  &lt;span class="lnum"&gt;  54:  &lt;/span&gt;&lt;span class="rem"&gt;//                                                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;  55:  &lt;/span&gt;&lt;span class="rem"&gt;//Descripion: 实现卸载服务                                                             //&lt;/span&gt;  &lt;span class="lnum"&gt;  56:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;  57:  &lt;/span&gt;&lt;span class="kwrd"&gt;bool&lt;/span&gt; CSSDTProcessDlg::UnInstallSvc(LPTSTR lpszSvcName)  &lt;span class="lnum"&gt;  58:  &lt;/span&gt;{  &lt;span class="lnum"&gt;  59:  &lt;/span&gt;    SC_HANDLE hSCM = NULL;  &lt;span class="lnum"&gt;  60:  &lt;/span&gt;    SC_HANDLE hSvc = NULL;  &lt;span class="lnum"&gt;  61:  &lt;/span&gt;    &lt;span class="kwrd"&gt;bool&lt;/span&gt; rtResult = FALSE;  &lt;span class="lnum"&gt;  62:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  63:  &lt;/span&gt;    AdjustProcessTokenPrivilege();  &lt;span class="lnum"&gt;  64:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  65:  &lt;/span&gt;    hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);  &lt;span class="lnum"&gt;  66:  &lt;/span&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt;(NULL == hSCM)  &lt;span class="lnum"&gt;  67:  &lt;/span&gt;    {  &lt;span class="lnum"&gt;  68:  &lt;/span&gt;        OutputErrorMessage(TEXT(&lt;span class="str"&gt;&amp;quot;UnInstallSvc - OpenSCManager Failed , Error Code Is %d , Error Message Is %s !&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt;  69:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  70:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; FALSE;  &lt;span class="lnum"&gt;  71:  &lt;/span&gt;    }  &lt;span class="lnum"&gt;  72:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  73:  &lt;/span&gt;    hSvc = OpenService(hSCM, lpszSvcName, SERVICE_ALL_ACCESS);  &lt;span class="lnum"&gt;  74:  &lt;/span&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt;(NULL == hSvc)  &lt;span class="lnum"&gt;  75:  &lt;/span&gt;    {  &lt;span class="lnum"&gt;  76:  &lt;/span&gt;        OutputErrorMessage(TEXT(&lt;span class="str"&gt;&amp;quot;UnInstallSvc - OpenService Failed , Error Code Is %d , Error Message Is %s !&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt;  77:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  78:  &lt;/span&gt;        CloseServiceHandle(hSCM);  &lt;span class="lnum"&gt;  79:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  80:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; FALSE;  &lt;span class="lnum"&gt;  81:  &lt;/span&gt;    }  &lt;span class="lnum"&gt;  82:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  83:  &lt;/span&gt;    rtResult = DeleteService(hSvc);  &lt;span class="lnum"&gt;  84:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  85:  &lt;/span&gt;    CloseServiceHandle(hSvc);  &lt;span class="lnum"&gt;  86:  &lt;/span&gt;    CloseServiceHandle(hSCM);  &lt;span class="lnum"&gt;  87:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  88:  &lt;/span&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; rtResult;  &lt;span class="lnum"&gt;  89:  &lt;/span&gt;}  &lt;span class="lnum"&gt;  90:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  91:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  92:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;  93:  &lt;/span&gt;&lt;span class="rem"&gt;//Name: bool StartSvc()                                                                //&lt;/span&gt;  &lt;span class="lnum"&gt;  94:  &lt;/span&gt;&lt;span class="rem"&gt;//                                                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;  95:  &lt;/span&gt;&lt;span class="rem"&gt;//Descripion: 实现启动服务                                                             //&lt;/span&gt;  &lt;span class="lnum"&gt;  96:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;  97:  &lt;/span&gt;&lt;span class="kwrd"&gt;bool&lt;/span&gt; CSSDTProcessDlg::StartSvc(LPTSTR lpszSvcName)  &lt;span class="lnum"&gt;  98:  &lt;/span&gt;{  &lt;span class="lnum"&gt;  99:  &lt;/span&gt;    SC_HANDLE hSCM = NULL;  &lt;span class="lnum"&gt; 100:  &lt;/span&gt;    SC_HANDLE hSvc = NULL;  &lt;span class="lnum"&gt; 101:  &lt;/span&gt;    &lt;span class="kwrd"&gt;bool&lt;/span&gt; rtResult = FALSE;  &lt;span class="lnum"&gt; 102:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 103:  &lt;/span&gt;    AdjustProcessTokenPrivilege();  &lt;span class="lnum"&gt; 104:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 105:  &lt;/span&gt;    hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);  &lt;span class="lnum"&gt; 106:  &lt;/span&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt;(NULL == hSCM)  &lt;span class="lnum"&gt; 107:  &lt;/span&gt;    {  &lt;span class="lnum"&gt; 108:  &lt;/span&gt;        OutputErrorMessage(TEXT(&lt;span class="str"&gt;&amp;quot;StartSvc - OpenSCManager Failed , Error Code Is %d , Error Message Is %s !&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt; 109:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 110:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; FALSE;  &lt;span class="lnum"&gt; 111:  &lt;/span&gt;    }  &lt;span class="lnum"&gt; 112:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 113:  &lt;/span&gt;    hSvc = OpenService(hSCM, lpszSvcName, SERVICE_ALL_ACCESS);  &lt;span class="lnum"&gt; 114:  &lt;/span&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt;(NULL == hSvc)  &lt;span class="lnum"&gt; 115:  &lt;/span&gt;    {  &lt;span class="lnum"&gt; 116:  &lt;/span&gt;        OutputErrorMessage(TEXT(&lt;span class="str"&gt;&amp;quot;StartSvc - OpenService Failed , Error Code Is %d , Error Message Is %s !&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt; 117:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 118:  &lt;/span&gt;        CloseServiceHandle(hSCM);  &lt;span class="lnum"&gt; 119:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 120:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; FALSE;  &lt;span class="lnum"&gt; 121:  &lt;/span&gt;    }  &lt;span class="lnum"&gt; 122:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 123:  &lt;/span&gt;    rtResult = StartService(hSvc, NULL, NULL);  &lt;span class="lnum"&gt; 124:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 125:  &lt;/span&gt;    CloseServiceHandle(hSvc);  &lt;span class="lnum"&gt; 126:  &lt;/span&gt;    CloseServiceHandle(hSCM);  &lt;span class="lnum"&gt; 127:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 128:  &lt;/span&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt;(FALSE == rtResult)  &lt;span class="lnum"&gt; 129:  &lt;/span&gt;    {  &lt;span class="lnum"&gt; 130:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt;(ERROR_SERVICE_ALREADY_RUNNING == GetLastError())  &lt;span class="lnum"&gt; 131:  &lt;/span&gt;        {  &lt;span class="lnum"&gt; 132:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; TRUE;  &lt;span class="lnum"&gt; 133:  &lt;/span&gt;        }  &lt;span class="lnum"&gt; 134:  &lt;/span&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt;  &lt;span class="lnum"&gt; 135:  &lt;/span&gt;        {  &lt;span class="lnum"&gt; 136:  &lt;/span&gt;            OutputErrorMessage(TEXT(&lt;span class="str"&gt;&amp;quot;StartSvc - StartService Failed , Error Code Is %d , Error Message Is %s !&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt; 137:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 138:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; FALSE;  &lt;span class="lnum"&gt; 139:  &lt;/span&gt;        }  &lt;span class="lnum"&gt; 140:  &lt;/span&gt;    }  &lt;span class="lnum"&gt; 141:  &lt;/span&gt;    &lt;span class="kwrd"&gt;else&lt;/span&gt;  &lt;span class="lnum"&gt; 142:  &lt;/span&gt;    {  &lt;span class="lnum"&gt; 143:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; TRUE;  &lt;span class="lnum"&gt; 144:  &lt;/span&gt;    }  &lt;span class="lnum"&gt; 145:  &lt;/span&gt;}  &lt;span class="lnum"&gt; 146:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 147:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 148:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt; 149:  &lt;/span&gt;&lt;span class="rem"&gt;//Name: bool StopSvc()                                                                 //&lt;/span&gt;  &lt;span class="lnum"&gt; 150:  &lt;/span&gt;&lt;span class="rem"&gt;//                                                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt; 151:  &lt;/span&gt;&lt;span class="rem"&gt;//Descripion: 实现停止服务                                                             //&lt;/span&gt;  &lt;span class="lnum"&gt; 152:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt; 153:  &lt;/span&gt;&lt;span class="kwrd"&gt;bool&lt;/span&gt; CSSDTProcessDlg::StopSvc(LPTSTR lpszSvcName)  &lt;span class="lnum"&gt; 154:  &lt;/span&gt;{  &lt;span class="lnum"&gt; 155:  &lt;/span&gt;    SC_HANDLE hSCM = NULL;  &lt;span class="lnum"&gt; 156:  &lt;/span&gt;    SC_HANDLE hSvc = NULL;  &lt;span class="lnum"&gt; 157:  &lt;/span&gt;    &lt;span class="kwrd"&gt;bool&lt;/span&gt; rtResult = FALSE;  &lt;span class="lnum"&gt; 158:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 159:  &lt;/span&gt;    SERVICE_STATUS svcStatus;  &lt;span class="lnum"&gt; 160:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 161:  &lt;/span&gt;    AdjustProcessTokenPrivilege();  &lt;span class="lnum"&gt; 162:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 163:  &lt;/span&gt;    hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);  &lt;span class="lnum"&gt; 164:  &lt;/span&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt;(NULL == hSCM)  &lt;span class="lnum"&gt; 165:  &lt;/span&gt;    {  &lt;span class="lnum"&gt; 166:  &lt;/span&gt;        OutputErrorMessage(TEXT(&lt;span class="str"&gt;&amp;quot;StopSvc - OpenSCManager Failed , Error Code Is %d , Error Message Is %s !&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt; 167:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 168:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; FALSE;  &lt;span class="lnum"&gt; 169:  &lt;/span&gt;    }  &lt;span class="lnum"&gt; 170:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 171:  &lt;/span&gt;    hSvc = OpenService(hSCM, lpszSvcName, SERVICE_ALL_ACCESS);  &lt;span class="lnum"&gt; 172:  &lt;/span&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt;(NULL == hSvc)  &lt;span class="lnum"&gt; 173:  &lt;/span&gt;    {  &lt;span class="lnum"&gt; 174:  &lt;/span&gt;        OutputErrorMessage(TEXT(&lt;span class="str"&gt;&amp;quot;StopSvc - OpenService Failed , Error Code Is %d , Error Message Is %s !&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt; 175:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 176:  &lt;/span&gt;        CloseServiceHandle(hSCM);  &lt;span class="lnum"&gt; 177:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 178:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; FALSE;  &lt;span class="lnum"&gt; 179:  &lt;/span&gt;    }  &lt;span class="lnum"&gt; 180:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 181:  &lt;/span&gt;    rtResult = ControlService(hSvc, SERVICE_CONTROL_STOP, &amp;amp;svcStatus);  &lt;span class="lnum"&gt; 182:  &lt;/span&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt;(rtResult == FALSE)  &lt;span class="lnum"&gt; 183:  &lt;/span&gt;    {  &lt;span class="lnum"&gt; 184:  &lt;/span&gt;        OutputErrorMessage(TEXT(&lt;span class="str"&gt;&amp;quot;StopSvc - ControlService Failed , Error Code Is %d , Error Message Is %s !&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt; 185:  &lt;/span&gt;    }  &lt;span class="lnum"&gt; 186:  &lt;/span&gt;    CloseServiceHandle(hSvc);  &lt;span class="lnum"&gt; 187:  &lt;/span&gt;    CloseServiceHandle(hSCM);  &lt;span class="lnum"&gt; 188:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 189:  &lt;/span&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; rtResult;  &lt;span class="lnum"&gt; 190:  &lt;/span&gt;}&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;那么服务的安装和启动放在那里比较合适，而服务的关闭和卸载又放在那里比较合适呢 ?&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;由于这个应用程序采用 MFC 开发，自然可以在 OnInitDialog()中安装和启动服务比较合适，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;而后可以在对话框类的析构函数中关闭和卸载掉服务 ~ &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;安装和启动服务：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;    wstring wStrSysPath = GetSysFilePath();  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;    BOOL bResult = InstallSvc(((LPTSTR)(LPCTSTR)SSDT01_SERVICE_NAME),   &lt;span class="lnum"&gt;   3:  &lt;/span&gt;                              ((LPTSTR)(LPCTSTR)SSDT01_SERVICE_NAME),   &lt;span class="lnum"&gt;   4:  &lt;/span&gt;                              ((LPTSTR)(LPCTSTR)wStrSysPath.c_str()),   &lt;span class="lnum"&gt;   5:  &lt;/span&gt;                              SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START);  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt;(FALSE == bResult)  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;    {  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;        MessageBox(_TEXT(&lt;span class="str"&gt;&amp;quot; Install SSDT Service Failed , Application Auto Exit !  &amp;quot;&lt;/span&gt;),  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;                   _TEXT(&lt;span class="str"&gt;&amp;quot;Application Error&amp;quot;&lt;/span&gt;), MB_OK | MB_ICONSTOP);  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;        CDialogEx::OnCancel();          &lt;span class="lnum"&gt;  11:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; FALSE;  &lt;span class="lnum"&gt;  12:  &lt;/span&gt;    }  &lt;span class="lnum"&gt;  13:  &lt;/span&gt;    &lt;span class="kwrd"&gt;else&lt;/span&gt;  &lt;span class="lnum"&gt;  14:  &lt;/span&gt;    {  &lt;span class="lnum"&gt;  15:  &lt;/span&gt;        bResult = StartSvc(SSDT01_SERVICE_NAME);  &lt;span class="lnum"&gt;  16:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt;(FALSE == bResult)  &lt;span class="lnum"&gt;  17:  &lt;/span&gt;        {  &lt;span class="lnum"&gt;  18:  &lt;/span&gt;            MessageBox(_TEXT(&lt;span class="str"&gt;&amp;quot; Start SSDT Service Failed , Application Auto Exit !  &amp;quot;&lt;/span&gt;),   &lt;span class="lnum"&gt;  19:  &lt;/span&gt;                       _TEXT(&lt;span class="str"&gt;&amp;quot;Application Error&amp;quot;&lt;/span&gt;), MB_OK | MB_ICONSTOP);  &lt;span class="lnum"&gt;  20:  &lt;/span&gt;            CDialogEx::OnCancel();  &lt;span class="lnum"&gt;  21:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; FALSE;  &lt;span class="lnum"&gt;  22:  &lt;/span&gt;        }  &lt;span class="lnum"&gt;  23:  &lt;/span&gt;    }&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;停止并且将服务卸载掉： &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;    ~CSSDTProcessDlg()  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;    {  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;        &lt;span class="rem"&gt;//在析构函数中关闭 SSDT 设备句柄&lt;/span&gt;  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt;(&lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;m_hDevice)  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;        {  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;            CloseHandle(&lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;m_hDevice);  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;        }  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;        &lt;span class="rem"&gt;//当发生析构函数时，停止服务并且卸载服务&lt;/span&gt;  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;        StopSvc(SSDT01_SERVICE_NAME);  &lt;span class="lnum"&gt;  11:  &lt;/span&gt;        UnInstallSvc(SSDT01_SERVICE_NAME);  &lt;span class="lnum"&gt;  12:  &lt;/span&gt;    }&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;4. 应用程序和内核程序通信：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;由前面的第二篇博文，可以知道，应用程序和内核程序的通信我是通过 DeviceIoControl 来完成的，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;开发过内核程序的都清楚，应用程序和内核程序的通信最普遍的也就通过三个 API 来实现，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;一个 ReadFile，一个 WriteFile，一个 DeviceIoContrl，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;当然其中属 DeviceIoControl 功能最为强大，完全可以用其替换掉 ReadFile 和 WriteFile，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;DeviceIoControl 原型(详细信息可以参考 MSDN)：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;BOOL WINAPI DeviceIoControl(  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;  __in          HANDLE hDevice,  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;  __in          DWORD dwIoControlCode,  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;  __in          LPVOID lpInBuffer,  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;  __in          DWORD nInBufferSize,  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;  __out         LPVOID lpOutBuffer,  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;  __in          DWORD nOutBufferSize,  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;  __out         LPDWORD lpBytesReturned,  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;  __in          LPOVERLAPPED lpOverlapped  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;);  &lt;span class="lnum"&gt;  11:  &lt;/span&gt;&amp;#160;&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;至于如何实现应用程序和内核程序的通信的话，在我的 Demo 中是这样做处理的，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;首先在 OnInitDialog 事件中通过 CreateFile 打开我们所安装的服务中创建的设备，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;(在 NT 式驱动程序中我创建了一个设备，这个设备用来实现应用程序和内核程序的通信)，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后在对话框类中保存有一个全局变量，这个全局变量即代表所打开的这个设备的句柄，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109052303225723.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109052303249858.png" width="635" height="206" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;既然这个全局变量是保存的我们的设备的句柄，自然我们需要来获取到设备的句柄，并且将句柄赋值给该全局变量，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;而这个呢，又是在 OnInitDialog 中完成的 ~ &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;    &lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;m_hDevice = CreateFile(SSDT01_DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0,   &lt;span class="lnum"&gt;   2:  &lt;/span&gt;                                 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt;(INVALID_HANDLE_VALUE == &lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;m_hDevice)  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;    {  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;        MessageBox(_TEXT(&lt;span class="str"&gt;&amp;quot; Open SSDT Device Failed , Application Auto Exit !  &amp;quot;&lt;/span&gt;),   &lt;span class="lnum"&gt;   6:  &lt;/span&gt;                   _TEXT(&lt;span class="str"&gt;&amp;quot;Application Error&amp;quot;&lt;/span&gt;), MB_OK | MB_ICONSTOP);  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;        CDialogEx::OnCancel();  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; FALSE;  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;    }&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;有了这个设备句柄，我们就可以通过其来实现和内核程序的通信了，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;因为通过在应用程序中调用 DeviceIoControl 可以产生 IRP_MJ_DEVICE_CONTROL 的 IRP，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;然后该 IRP 可以被驱动程序中的 DeviceIoControl 分发函数所处理 ~ &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000" size="2" face="Courier New"&gt;我们的应用程序只需要将我们所要隐藏或者是需要保护的进程的 PID 通过 DeviceIoControl 传递给内核程序即可 !!!&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;所以我们在应用程序中只需要调用 DeviceIoContrl 即可 ~ &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;下面给出的代码比较凌乱(重点请看 DeviceIoControl 的调用)&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="rem"&gt;//隐藏进程或者取消对进程的隐藏&lt;/span&gt;  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;void&lt;/span&gt; CSSDTProcessDlg::OnBnClickedBtnHideorunhide()  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;{  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;    &lt;span class="kwrd"&gt;int&lt;/span&gt; nIndex;  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;    DWORD dwPID;  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;    CString cStrText;  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;    CString cStrState;  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;      &lt;span class="lnum"&gt;   9:  &lt;/span&gt;    DWORD dwOutput;  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;    BOOL bRet;  &lt;span class="lnum"&gt;  11:  &lt;/span&gt;    CHAR inBuffer[10];  &lt;span class="lnum"&gt;  12:  &lt;/span&gt;    CHAR outBuffer[10];  &lt;span class="lnum"&gt;  13:  &lt;/span&gt;    memset(inBuffer, 0, 10);  &lt;span class="lnum"&gt;  14:  &lt;/span&gt;    memset(outBuffer, 0, 10);  &lt;span class="lnum"&gt;  15:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  16:  &lt;/span&gt;    dwPID = &lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;GetDlgItemInt(IDC_STATIC_SELECTED_PID);  &lt;span class="lnum"&gt;  17:  &lt;/span&gt;    &lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;GetDlgItemText(ID_BTN_HIDEORUNHIDE, cStrText);  &lt;span class="lnum"&gt;  18:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  19:  &lt;/span&gt;    ultoa(dwPID, inBuffer, 10);  &lt;span class="lnum"&gt;  20:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  21:  &lt;/span&gt;    nIndex = QueryItemIndexByPID(dwPID);  &lt;span class="lnum"&gt;  22:  &lt;/span&gt;    cStrState = &lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;m_ListCtrlProcess.GetItemText(nIndex, 4);  &lt;span class="lnum"&gt;  23:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  24:  &lt;/span&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt;(cStrText.CompareNoCase(_TEXT(&lt;span class="str"&gt;&amp;quot;Hide&amp;quot;&lt;/span&gt;)) == 0)  &lt;span class="lnum"&gt;  25:  &lt;/span&gt;    {  &lt;span class="lnum"&gt;  26:  &lt;/span&gt;        &lt;span class="rem"&gt;//隐藏 dwPID&lt;/span&gt;  &lt;span class="lnum"&gt;  27:  &lt;/span&gt;        bRet = DeviceIoControl(&lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;m_hDevice, IO_INSERT_HIDE_PROCESS, inBuffer, 10,   &lt;span class="lnum"&gt;  28:  &lt;/span&gt;             &amp;amp;outBuffer, 10, &amp;amp;dwOutput, NULL);  &lt;span class="lnum"&gt;  29:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt;(bRet)  &lt;span class="lnum"&gt;  30:  &lt;/span&gt;        {  &lt;span class="lnum"&gt;  31:  &lt;/span&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;SetDlgItemText(ID_BTN_HIDEORUNHIDE, _TEXT(&lt;span class="str"&gt;&amp;quot;UnHide&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt;  32:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt;(cStrState.CompareNoCase(_TEXT(&lt;span class="str"&gt;&amp;quot;Protect&amp;quot;&lt;/span&gt;)) == 0)  &lt;span class="lnum"&gt;  33:  &lt;/span&gt;            {  &lt;span class="lnum"&gt;  34:  &lt;/span&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;m_ListCtrlProcess.SetItemText(nIndex, 4, _TEXT(&lt;span class="str"&gt;&amp;quot;HideAndProtect&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt;  35:  &lt;/span&gt;            }  &lt;span class="lnum"&gt;  36:  &lt;/span&gt;            &lt;span class="kwrd"&gt;else&lt;/span&gt;  &lt;span class="lnum"&gt;  37:  &lt;/span&gt;            {  &lt;span class="lnum"&gt;  38:  &lt;/span&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;m_ListCtrlProcess.SetItemText(nIndex, 4, _TEXT(&lt;span class="str"&gt;&amp;quot;Hide&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt;  39:  &lt;/span&gt;            }  &lt;span class="lnum"&gt;  40:  &lt;/span&gt;            MessageBox(_TEXT(&lt;span class="str"&gt;&amp;quot; Hide Process Sucess !  &amp;quot;&lt;/span&gt;), _TEXT(&lt;span class="str"&gt;&amp;quot;Information&amp;quot;&lt;/span&gt;), MB_OK |   &lt;span class="lnum"&gt;  41:  &lt;/span&gt;                     MB_ICONINFORMATION);  &lt;span class="lnum"&gt;  42:  &lt;/span&gt;        }  &lt;span class="lnum"&gt;  43:  &lt;/span&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt;  &lt;span class="lnum"&gt;  44:  &lt;/span&gt;        {  &lt;span class="lnum"&gt;  45:  &lt;/span&gt;            MessageBox(_TEXT(&lt;span class="str"&gt;&amp;quot; Hide Process Failed !  &amp;quot;&lt;/span&gt;), _TEXT(&lt;span class="str"&gt;&amp;quot;Warning&amp;quot;&lt;/span&gt;), MB_OK | MB_ICONERROR);  &lt;span class="lnum"&gt;  46:  &lt;/span&gt;        }  &lt;span class="lnum"&gt;  47:  &lt;/span&gt;    }  &lt;span class="lnum"&gt;  48:  &lt;/span&gt;    &lt;span class="kwrd"&gt;else&lt;/span&gt;  &lt;span class="lnum"&gt;  49:  &lt;/span&gt;    {  &lt;span class="lnum"&gt;  50:  &lt;/span&gt;        &lt;span class="rem"&gt;//解除 dwPID 隐藏&lt;/span&gt;  &lt;span class="lnum"&gt;  51:  &lt;/span&gt;        bRet = DeviceIoControl(&lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;m_hDevice, IO_REMOVE_HIDE_PROCESS, inBuffer, 10,   &lt;span class="lnum"&gt;  52:  &lt;/span&gt;             &amp;amp;outBuffer, 10, &amp;amp;dwOutput, NULL);  &lt;span class="lnum"&gt;  53:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt;(bRet)  &lt;span class="lnum"&gt;  54:  &lt;/span&gt;        {  &lt;span class="lnum"&gt;  55:  &lt;/span&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;SetDlgItemText(ID_BTN_HIDEORUNHIDE, _TEXT(&lt;span class="str"&gt;&amp;quot;Hide&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt;  56:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt;(cStrState.CompareNoCase(_TEXT(&lt;span class="str"&gt;&amp;quot;Protect&amp;quot;&lt;/span&gt;)) == 0 ||   &lt;span class="lnum"&gt;  57:  &lt;/span&gt;               cStrState.CompareNoCase(_TEXT(&lt;span class="str"&gt;&amp;quot;HideAndProtect&amp;quot;&lt;/span&gt;))== 0)  &lt;span class="lnum"&gt;  58:  &lt;/span&gt;            {  &lt;span class="lnum"&gt;  59:  &lt;/span&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;m_ListCtrlProcess.SetItemText(nIndex, 4, _TEXT(&lt;span class="str"&gt;&amp;quot;Protect&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt;  60:  &lt;/span&gt;            }  &lt;span class="lnum"&gt;  61:  &lt;/span&gt;            &lt;span class="kwrd"&gt;else&lt;/span&gt;  &lt;span class="lnum"&gt;  62:  &lt;/span&gt;            {  &lt;span class="lnum"&gt;  63:  &lt;/span&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;m_ListCtrlProcess.SetItemText(nIndex, 4, _TEXT(&lt;span class="str"&gt;&amp;quot;General&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt;  64:  &lt;/span&gt;            }  &lt;span class="lnum"&gt;  65:  &lt;/span&gt;            MessageBox(_TEXT(&lt;span class="str"&gt;&amp;quot; UnHide Process Sucess !  &amp;quot;&lt;/span&gt;), _TEXT(&lt;span class="str"&gt;&amp;quot;Information&amp;quot;&lt;/span&gt;), MB_OK |   &lt;span class="lnum"&gt;  66:  &lt;/span&gt;                  MB_ICONINFORMATION);  &lt;span class="lnum"&gt;  67:  &lt;/span&gt;        }  &lt;span class="lnum"&gt;  68:  &lt;/span&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt;  &lt;span class="lnum"&gt;  69:  &lt;/span&gt;        {  &lt;span class="lnum"&gt;  70:  &lt;/span&gt;            MessageBox(_TEXT(&lt;span class="str"&gt;&amp;quot; UnHide Process Failed !  &amp;quot;&lt;/span&gt;), _TEXT(&lt;span class="str"&gt;&amp;quot;Warning&amp;quot;&lt;/span&gt;), MB_OK | MB_ICONERROR);  &lt;span class="lnum"&gt;  71:  &lt;/span&gt;        }  &lt;span class="lnum"&gt;  72:  &lt;/span&gt;    }  &lt;span class="lnum"&gt;  73:  &lt;/span&gt;}  &lt;span class="lnum"&gt;  74:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  75:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  76:  &lt;/span&gt;&lt;span class="rem"&gt;//保护进程或者取消对进程的保护操作&lt;/span&gt;  &lt;span class="lnum"&gt;  77:  &lt;/span&gt;&lt;span class="kwrd"&gt;void&lt;/span&gt; CSSDTProcessDlg::OnBnClickedBtnProtectorunprotect()  &lt;span class="lnum"&gt;  78:  &lt;/span&gt;{  &lt;span class="lnum"&gt;  79:  &lt;/span&gt;    &lt;span class="kwrd"&gt;int&lt;/span&gt; nIndex;  &lt;span class="lnum"&gt;  80:  &lt;/span&gt;    DWORD dwPID;  &lt;span class="lnum"&gt;  81:  &lt;/span&gt;    CString cStrText;  &lt;span class="lnum"&gt;  82:  &lt;/span&gt;    CString cStrState;  &lt;span class="lnum"&gt;  83:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  84:  &lt;/span&gt;    DWORD dwOutput;  &lt;span class="lnum"&gt;  85:  &lt;/span&gt;    BOOL bRet;  &lt;span class="lnum"&gt;  86:  &lt;/span&gt;    CHAR inBuffer[10];  &lt;span class="lnum"&gt;  87:  &lt;/span&gt;    CHAR outBuffer[10];  &lt;span class="lnum"&gt;  88:  &lt;/span&gt;    memset(inBuffer, 0, 10);  &lt;span class="lnum"&gt;  89:  &lt;/span&gt;    memset(outBuffer, 0, 10);  &lt;span class="lnum"&gt;  90:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  91:  &lt;/span&gt;    dwPID = &lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;GetDlgItemInt(IDC_STATIC_SELECTED_PID);  &lt;span class="lnum"&gt;  92:  &lt;/span&gt;    &lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;GetDlgItemText(ID_BTN_PROTECTORUNPROTECT, cStrText);  &lt;span class="lnum"&gt;  93:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  94:  &lt;/span&gt;    ultoa(dwPID, inBuffer, 10);  &lt;span class="lnum"&gt;  95:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  96:  &lt;/span&gt;    nIndex = QueryItemIndexByPID(dwPID);  &lt;span class="lnum"&gt;  97:  &lt;/span&gt;    cStrState = &lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;m_ListCtrlProcess.GetItemText(nIndex, 4);  &lt;span class="lnum"&gt;  98:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  99:  &lt;/span&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt;(cStrText.CompareNoCase(_TEXT(&lt;span class="str"&gt;&amp;quot;Protect&amp;quot;&lt;/span&gt;)) == 0)  &lt;span class="lnum"&gt; 100:  &lt;/span&gt;    {  &lt;span class="lnum"&gt; 101:  &lt;/span&gt;        &lt;span class="rem"&gt;//保护 dwPID 保护&lt;/span&gt;  &lt;span class="lnum"&gt; 102:  &lt;/span&gt;        bRet = DeviceIoControl(&lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;m_hDevice, IO_INSERT_PROTECT_PROCESS, inBuffer, 10,   &lt;span class="lnum"&gt; 103:  &lt;/span&gt;             &amp;amp;outBuffer, 10, &amp;amp;dwOutput, NULL);  &lt;span class="lnum"&gt; 104:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt;(bRet)  &lt;span class="lnum"&gt; 105:  &lt;/span&gt;        {  &lt;span class="lnum"&gt; 106:  &lt;/span&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;SetDlgItemText(ID_BTN_PROTECTORUNPROTECT, _TEXT(&lt;span class="str"&gt;&amp;quot;UnProtect&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt; 107:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt;(cStrState.CompareNoCase(_TEXT(&lt;span class="str"&gt;&amp;quot;Hide&amp;quot;&lt;/span&gt;))== 0)  &lt;span class="lnum"&gt; 108:  &lt;/span&gt;            {  &lt;span class="lnum"&gt; 109:  &lt;/span&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;m_ListCtrlProcess.SetItemText(nIndex, 4, _TEXT(&lt;span class="str"&gt;&amp;quot;HideAndProtect&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt; 110:  &lt;/span&gt;            }  &lt;span class="lnum"&gt; 111:  &lt;/span&gt;            &lt;span class="kwrd"&gt;else&lt;/span&gt;  &lt;span class="lnum"&gt; 112:  &lt;/span&gt;            {  &lt;span class="lnum"&gt; 113:  &lt;/span&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;m_ListCtrlProcess.SetItemText(nIndex, 4, _TEXT(&lt;span class="str"&gt;&amp;quot;Protect&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt; 114:  &lt;/span&gt;            }  &lt;span class="lnum"&gt; 115:  &lt;/span&gt;            MessageBox(_TEXT(&lt;span class="str"&gt;&amp;quot; Protect Process Sucess !  &amp;quot;&lt;/span&gt;), _TEXT(&lt;span class="str"&gt;&amp;quot;Information&amp;quot;&lt;/span&gt;), MB_OK |   &lt;span class="lnum"&gt; 116:  &lt;/span&gt;                  MB_ICONINFORMATION);  &lt;span class="lnum"&gt; 117:  &lt;/span&gt;        }  &lt;span class="lnum"&gt; 118:  &lt;/span&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt;  &lt;span class="lnum"&gt; 119:  &lt;/span&gt;        {  &lt;span class="lnum"&gt; 120:  &lt;/span&gt;            MessageBox(_TEXT(&lt;span class="str"&gt;&amp;quot; Protect Process Failed !  &amp;quot;&lt;/span&gt;), _TEXT(&lt;span class="str"&gt;&amp;quot;Warning&amp;quot;&lt;/span&gt;), MB_OK | MB_ICONERROR);  &lt;span class="lnum"&gt; 121:  &lt;/span&gt;        }  &lt;span class="lnum"&gt; 122:  &lt;/span&gt;    }  &lt;span class="lnum"&gt; 123:  &lt;/span&gt;    &lt;span class="kwrd"&gt;else&lt;/span&gt;  &lt;span class="lnum"&gt; 124:  &lt;/span&gt;    {  &lt;span class="lnum"&gt; 125:  &lt;/span&gt;        &lt;span class="rem"&gt;//解除 dwPID 保护&lt;/span&gt;  &lt;span class="lnum"&gt; 126:  &lt;/span&gt;        bRet = DeviceIoControl(&lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;m_hDevice, IO_REMOVE_PROTECT_PROCESS, inBuffer, 10,   &lt;span class="lnum"&gt; 127:  &lt;/span&gt;             &amp;amp;outBuffer, 10, &amp;amp;dwOutput, NULL);  &lt;span class="lnum"&gt; 128:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt;(bRet)  &lt;span class="lnum"&gt; 129:  &lt;/span&gt;        {  &lt;span class="lnum"&gt; 130:  &lt;/span&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;SetDlgItemText(ID_BTN_PROTECTORUNPROTECT, _TEXT(&lt;span class="str"&gt;&amp;quot;Protect&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt; 131:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt;(cStrState.CompareNoCase(_TEXT(&lt;span class="str"&gt;&amp;quot;Hide&amp;quot;&lt;/span&gt;)) == 0 ||   &lt;span class="lnum"&gt; 132:  &lt;/span&gt;                 cStrState.CompareNoCase(_TEXT(&lt;span class="str"&gt;&amp;quot;HideAndProtect&amp;quot;&lt;/span&gt;)) == 0)  &lt;span class="lnum"&gt; 133:  &lt;/span&gt;            {  &lt;span class="lnum"&gt; 134:  &lt;/span&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;m_ListCtrlProcess.SetItemText(nIndex, 4, _TEXT(&lt;span class="str"&gt;&amp;quot;Hide&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt; 135:  &lt;/span&gt;            }  &lt;span class="lnum"&gt; 136:  &lt;/span&gt;            &lt;span class="kwrd"&gt;else&lt;/span&gt;  &lt;span class="lnum"&gt; 137:  &lt;/span&gt;            {  &lt;span class="lnum"&gt; 138:  &lt;/span&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;-&amp;gt;m_ListCtrlProcess.SetItemText(nIndex, 4, _TEXT(&lt;span class="str"&gt;&amp;quot;General&amp;quot;&lt;/span&gt;));  &lt;span class="lnum"&gt; 139:  &lt;/span&gt;            }  &lt;span class="lnum"&gt; 140:  &lt;/span&gt;            MessageBox(_TEXT(&lt;span class="str"&gt;&amp;quot; UnProtect Process Sucess !  &amp;quot;&lt;/span&gt;), _TEXT(&lt;span class="str"&gt;&amp;quot;Information&amp;quot;&lt;/span&gt;), MB_OK |   &lt;span class="lnum"&gt; 141:  &lt;/span&gt;                  MB_ICONINFORMATION);  &lt;span class="lnum"&gt; 142:  &lt;/span&gt;        }  &lt;span class="lnum"&gt; 143:  &lt;/span&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt;  &lt;span class="lnum"&gt; 144:  &lt;/span&gt;        {  &lt;span class="lnum"&gt; 145:  &lt;/span&gt;            MessageBox(_TEXT(&lt;span class="str"&gt;&amp;quot; UnProtect Process Failed !  &amp;quot;&lt;/span&gt;), _TEXT(&lt;span class="str"&gt;&amp;quot;Warning&amp;quot;&lt;/span&gt;), MB_OK | MB_ICONERROR);  &lt;span class="lnum"&gt; 146:  &lt;/span&gt;        }  &lt;span class="lnum"&gt; 147:  &lt;/span&gt;    }  &lt;span class="lnum"&gt; 148:  &lt;/span&gt;}              &amp;#160;&lt;/div&gt;&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;5. 小结：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;介绍这个应用程序呢，还真是不好写，因为感觉整个 Demo 里面却是没有什么好介绍的，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;无非就是获取到所有的进程，然后通过一个 ListCtrl 来显示这些数据，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后用户选择一个进程，单击一下隐藏呢，我就在这个按钮的消息处理函数中和内核程序通过 DeviceIoControl 通信一下，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;将这个进程的 PID 传递给内核程序，其他的就都不需要理会了 ~ &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;所以转来转去的，也没什么好些的，干脆就写到这里得了，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;等下将整个 Demo 打个包，直接提供下载，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;&lt;font face="Verdana"&gt;我这里说得口干舌燥也没什么用，&lt;/font&gt;感兴趣的自己下载了源码去慢慢玩得了 ~ &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;最后再总结一个 SSDT Hook 的优点，那就是 SSDT Hook 无论你是 Windows XP 还是 Server 或者 Vista 或者 Win7，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;你都是可以很好的运行程序的，所以你下载的 Demo 你可以放心的在上面的这些操作系统上运行，当然 64 位的除外，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;64 位的操作系统虽然我没有做过测试，但是我估摸着会蓝屏的 ~ 有兴趣的可以去蓝一次 ~ &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="3" face="Courier New"&gt;&lt;strong&gt;&lt;u&gt;下载 Demo&lt;/u&gt;&lt;/strong&gt;&lt;/font&gt;&lt;a href="http://files.cnblogs.com/BoyXiao/HookDemo.zip"&gt;&lt;font color="#ff0000" size="3" face="Courier New"&gt;&lt;strong&gt; Source Code&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;font color="#ff0000" size="3" face="Courier New"&gt;&lt;strong&gt;&lt;u&gt; &lt;/u&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;font face="Verdana"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;strong&gt;版权所有，&lt;strong&gt;欢&lt;/strong&gt;迎转载，但转载请注明： 转载自&amp;#160; &lt;/strong&gt;&lt;strong&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/"&gt;&lt;strong&gt;Zachary.XiaoZhen - 梦想的天空&lt;/strong&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/BoyXiao/aggbug/2168115.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/archive/2011/09/05/2168115.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/BoyXiao/archive/2011/09/04/2166596.html</id><title type="text">进程隐藏与进程保护（SSDT Hook 实现）（二）</title><summary type="text">文章目录：          1. 引子 – Demo 实现效果： 2. 进程隐藏与进程保护概念： 3. SSDT Hook 框架搭建： 4. Ring0 实现进程隐藏： 5. Ring0 实现进程保护： 6. 隐藏进程列表和保护进程列表的维护： 7. 小结：          1. 引子 – Demo 实现效果：         ...</summary><published>2011-09-04T10:10:00Z</published><updated>2011-09-04T10:10:00Z</updated><author><name>Zachary.XiaoZhen</name><uri>http://www.cnblogs.com/BoyXiao/</uri></author><link rel="alternate" href="http://www.cnblogs.com/BoyXiao/archive/2011/09/04/2166596.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BoyXiao/archive/2011/09/04/2166596.html"/><content type="html">&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;文章目录：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;1. 引子 – Demo 实现效果：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;2. 进程隐藏与进程保护概念：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;3. SSDT Hook 框架搭建：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;4. Ring0 实现进程隐藏：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;5. Ring0 实现进程保护：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;6. 隐藏进程列表和保护进程列表的维护：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;7. 小结：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;1. 引子 – Demo 实现效果：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;上一篇《进程隐藏与进程保护(SSDT Hook 实现)(一)》呢把 SSDT 说得差不多了，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;博文地址：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/archive/2011/09/03/2164574.html"&gt;&lt;font size="2" face="Courier New"&gt;http://www.cnblogs.com/BoyXiao/archive/2011/09/03/2164574.html&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;不过呢，那也只是些理论的东西，看不到什么实物，估计说来说去把人说晕了后，也没什么感觉，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而这一篇博文的话，给出点新意的，让人头脑清醒点的 ~ 所以先给个 Demo 出来吧 ~ &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;(不好意思，本着不喝倒怎出得了好文章这个理由，所以今天又喝多了点，文章有疏忽之处还请见谅 ~ &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;顺便在这里跟朋友们分享一下哈，晚上于这个时间点，比如 2 点的时候啊，喝点小酒，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;听点曲子，你会精神振奋，头脑更加清醒，思路也会很清晰，尤其是写起程序来那是唰唰的来の ~ )&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;进程隐藏效果：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;应用程序主界面：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109041808024709.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109041808142376.png" width="732" height="492" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;隐藏进程 taskmgr.exe：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109041808242626.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109041808438021.png" width="976" height="656" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;取消进程隐藏 taskmgr.exe：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109041808549143.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109041809133109.png" width="936" height="633" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;进程保护效果：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;进程保护(保护自身进程 SSDTProcess.exe)：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109041809207424.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109041809348735.png" width="903" height="529" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;取消进程保护(这里还是以 SSDTProcess.exe 为例)：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;下面的截图表示 SSDTProcess.exe 已经被取消了保护，&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;此时再到任务管理器中结束 SSDTProcess.exe 时，&lt;/font&gt;&lt;/strong&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;你可以发现是可以正常结束这个进程的 ~ &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109041809403441.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109041809535733.png" width="694" height="527" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;2. 进程隐藏与进程保护概念：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;在 Ring3 下获取到当前 Windows 操作系统下的所有的进程无外乎以下的几种方法：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;第一种：&lt;/strong&gt;使用 ToolHelp 遍历获取到所有进程，关于这种方式的话，笔者以前写过一篇博文的，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;《列举 Windows 所有进程(ToolHelp)》博文地址如下：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/archive/2011/02/27/1966383.html"&gt;&lt;font size="2" face="Courier New"&gt;http://www.cnblogs.com/BoyXiao/archive/2011/02/27/1966383.html&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;第二种：&lt;/strong&gt;使用 PSAPI 下的 EnumProcesses 获取到所有进程的 PID，然后提升进程权限为 SE_DEBUG 权限，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;再调用 OpenProcess 即可打开进程，从而获取到进程的基本信息(可以查看 MSDN 的 PSAPI 专题)。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;第三种：&lt;/strong&gt;使用未公开的本地 API 即位于 Ntdll.dll 中的未文档化的 API – NtQuerySystemInformation，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而 Windows 任务管理器就是通过这种方式来获取到所有的进程信息的 ~ &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而事实上的是，ToolHelp 和 PSAPI 只不过是对 Ntdll.dll 中 NtQuerySystemInformation API 的一个封装，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;所以在 Ring3 下获取系统中所有进程信息最终都会回到 Ndll.dll 中 NtQuerySystemInformation API 的调用上。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;如果要实现在 Ring3 中对进程进行隐藏的话，只需要 Hook 掉 NtQuerySystemInformation API 即可。&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而至于进程保护的话，我们需要考虑到两种情况，第一种则是该进程自行终止，第二种情况则是该进程被其他进程给杀掉，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;第一种情况基本上对于窗口应用程序来说，一般都是用户点击了右上角的 x 按钮，然后产生 WM_CLOSE 消息，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;最后由窗口过程退出进程，这种情况下，我们应该是需要允许退出的，也就是进程是可以正常退出的。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而第二种情况的话，就是进程被别的进程杀掉，比如在任务管理器中就可以杀掉绝大部分的应用程序进程，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而这里的进程保护就是要实现进程不能够被任务管理器或者其他的进程管理工具杀掉。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;在 Ring3 中，由一个进程结束其他进程，调用的 API 为 Kernel32.dll 中的 TerminateProcess，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;如果追溯这个 TerminateProcess，可以发现，其调用了 Ntdll.dll 中的 NtTerminateProcess API，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后再追溯下去就可以到 ntoskrnl.exe 中的 ZwTerminateProcess 和系统服务 NtTerminateProcess 了。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而这和我的上一篇博文中介绍 NtQuerySystemInformation 就是一致的了，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;所以如果我们要实现进程保护，需要 Hook 的系统服务就是 NtTerminateProcess ~ &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;3. SSDT Hook 框架搭建：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;从上面的介绍中，我们可以知道，要想实现进程隐藏和进程保护，我们需要在 SSDT 中 Hook 两个系统服务，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;即 Ring0 下的 NtQuerySystemInformation 和 Ring0 下的 NtTerminateProcess，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;既然要实现两个 Hook 的话，我干嘛不将 SSDT Hook 写成一个框架呢，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;这样的话，以后我无论是需要 Hook 哪个 SSDT 中的系统服务，我直接调用这个 SSDT 框架不就 OK 了，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;免得再去重复造轮子不，所以这里就来简单介绍一下这个 SSDT 框架 ~ &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;当然这里谈得 SSDT Hook 框架可不是大伙眼里的什么 .Net 框架啊，MVC 框架啊之类的，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;没那么复杂，算到底也就是一个 .cpp 和一个 .h 的文件而已，然后再在其中对外公开几个 API 即 OK 了 ~ &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109041809559519.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/20110904180959505.png" width="377" height="438" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;这里既是使用了 SSDT 的话，而在前一篇博文中也谈到了在 ntoskrnl.exe 中导出了 KeServiceDescriptorTable，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;但是内核中导出归导出，它导出有个屁用啊，别个类型啊什么的都没给你，看你怎么在你代码中使用它 ~ &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;所以我们首先要做的就是如何使用这个 ntoskrnl.exe 中导出的 KeServiceDescriptorTable 了，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;不过好在还有 WRK(当然在反汇编，逆向工程里面那些牛的作用也是相当的给力)的帮助，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;我们可以定义下面的代码来完成在自己的代码中使用 KeServiceDescriptorTable 这个任务：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="rem"&gt;//Name: KSYSTEM_SERVICE_TABLE 和 KSERVICE_TABLE_DESCRIPTOR                             //&lt;/span&gt;  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="rem"&gt;//Descripion: 用来定义 SSDT 结构                                                       //&lt;/span&gt;  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;typedef &lt;span class="kwrd"&gt;struct&lt;/span&gt; _KSYSTEM_SERVICE_TABLE  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;{  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;    PULONG  ServiceTableBase;        &lt;span class="rem"&gt;// SSDT (System Service Dispatch Table)的基地址&lt;/span&gt;  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;    PULONG  ServiceCounterTableBase; &lt;span class="rem"&gt;// 包含 SSDT 中每个服务被调用的次数&lt;/span&gt;  &lt;span class="lnum"&gt;  11:  &lt;/span&gt;    ULONG   NumberOfService;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="rem"&gt;// 服务函数的个数, NumberOfService * 4 就是整个地址表的大小&lt;/span&gt;  &lt;span class="lnum"&gt;  12:  &lt;/span&gt;    ULONG   ParamTableBase;          &lt;span class="rem"&gt;// SSPT(System Service Parameter Table)的基地址&lt;/span&gt;  &lt;span class="lnum"&gt;  13:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  14:  &lt;/span&gt;} KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;  &lt;span class="lnum"&gt;  15:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  16:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  17:  &lt;/span&gt;typedef &lt;span class="kwrd"&gt;struct&lt;/span&gt; _KSERVICE_TABLE_DESCRIPTOR  &lt;span class="lnum"&gt;  18:  &lt;/span&gt;{  &lt;span class="lnum"&gt;  19:  &lt;/span&gt;    KSYSTEM_SERVICE_TABLE   ntoskrnl; &lt;span class="rem"&gt;// ntoskrnl.exe 的服务函数&lt;/span&gt;  &lt;span class="lnum"&gt;  20:  &lt;/span&gt;    KSYSTEM_SERVICE_TABLE   win32k;   &lt;span class="rem"&gt;// win32k.sys 的服务函数(GDI32.dll/User32.dll 的内核支持)&lt;/span&gt;  &lt;span class="lnum"&gt;  21:  &lt;/span&gt;    KSYSTEM_SERVICE_TABLE   notUsed1;  &lt;span class="lnum"&gt;  22:  &lt;/span&gt;    KSYSTEM_SERVICE_TABLE   notUsed2;  &lt;span class="lnum"&gt;  23:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  24:  &lt;/span&gt;} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;  &lt;span class="lnum"&gt;  25:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  26:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  27:  &lt;/span&gt;&lt;span class="rem"&gt;//导出由 ntoskrnl.exe 所导出的 SSDT&lt;/span&gt;  &lt;span class="lnum"&gt;  28:  &lt;/span&gt;&lt;span class="kwrd"&gt;extern&lt;/span&gt; PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;既然是个 SSDT Hook 框架的话，自然需要能够安装 Hook，当然也需要能够解除 Hook，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;而我们拿什么来解除 Hook 呢，经过前面的介绍，我们可以知道的是，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;SSDT Hook 其实就是拿我们自己的 Hook 函数的地址去替换掉原来 SSDT 中保存的系统服务的地址，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;如果 Hook 了某个 API，那就意味着在 SSDT 中指定索引处所保存的系统服务的地址被修改为了 Hook 函数的地址，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;而如果要解除这个 API 的 Hook，自然就需要将原来系统中原有的系统服务的地址写回 SSDT 指定索引处，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;但是我们拿什么来保存 SSDT Hook 之前的系统服务的地址呢 ?&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;由于在 32 位机器上，一个入口地址可以用 32 位来表示，也就可以使用一个 ULONG 类型来保存，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;而由于我们这个是 SSDT 框架，也就是能够随意的 Hook SSDT 中的任意系统服务，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;自然为了能成功实现 Hook 的解除，就需要将 SSDT 中在 Hook 之前的每一个系统服务的地址保存下来，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;根据上面的总结，这可以通过一个 ULONG 数组来保存就可以了 ~ &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后再在 Hook 任意的系统服务之前，将 SSDT 中的所有系统服务的地址保存或者说是备份到 ULONG 数组中即可 ~ &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;而后在解除 Hook 时，我们就可以从这个 ULONG 数组中取出原有系统服务的地址，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后将地址写入到 SSDT 中即可实现 Hook 解除 ~&lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="rem"&gt;//定义 SSDT(系统服务描述表) 中服务个数的最大数目&lt;/span&gt;  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="rem"&gt;//这里定义为 1024 个，实际上在 XP SP3 是 0x0128 个&lt;/span&gt;  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;&lt;span class="preproc"&gt;#define&lt;/span&gt; MAX_SYSTEM_SERVICE_NUMBER 1024  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;span class="rem"&gt;//用来保存 SSDT 中所有的旧的服务函数的地址&lt;/span&gt;  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;ULONG oldSysServiceAddr[MAX_SYSTEM_SERVICE_NUMBER];&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;同时由于要实现安装 Hook，解除 Hook，所以自然也要公开两个 API，一个用来安装 Hook，一个用来解除 Hook，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;根据上面的这些呢，我们大致可以确定至少需要三个 API：&lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="rem"&gt;//备份 SSDT 中所有系统服务的地址&lt;/span&gt;  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;VOID BackupSysServicesTable();  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="rem"&gt;//安装 Hook&lt;/span&gt;  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;NTSTATUS InstallSysServiceHook(ULONG oldService, ULONG newService);  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;&lt;span class="rem"&gt;//解除 Hook&lt;/span&gt;  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;NTSTATUS UnInstallSysServiceHook(ULONG oldService);&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;然后还需要注意的是，SSDT 中保存的地址不是说你想写就可以写的，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;SSDT 在内存中是具有只读属性保护的，如果你想修改 SSDT 中的内容，你必须先要解除只读属性，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;也就是要赋予 SSDT 所在的这块内存具有可写属性才行，不然回馈你的将是一个无情的蓝屏(内存写入错误) ~&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;你给了这块内存可写属性后，你他妈的写完后总的把可写属性去掉，把别个恢复到只读属性吧 ~ &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;不然也太不厚道了，用完就不管了 ~ 所以还需要一个恢复只读属性的 API，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;综述，在 SSDT Hook 框架中又有了两个 API：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="rem"&gt;//禁止写入保护，也就是恢复到只读&lt;/span&gt;  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;VOID DisableWriteProtect(ULONG oldAttr);  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="rem"&gt;//允许写入保护，也就是设置为可写&lt;/span&gt;  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;VOID EnableWriteProtect(PULONG pOldAttr);&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后呢下面就将上面的这些个 API 的实现代码给贴出来，个人觉得自己的代码风格还算比较好的，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;应该还是看得下去吧(当然这只是我现在的观点，说不准再过段时间回头来看这些代码就会感慨这代码是给人看的嘛) ~ &lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;#include &lt;span class="str"&gt;&amp;quot;SSDTHook.h&amp;quot;&lt;/span&gt;  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;span class="rem"&gt;//Name: VOID DisableWriteProtect()                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;&lt;span class="rem"&gt;//                                                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;&lt;span class="rem"&gt;//Descripion: 用来去掉内存的可写属性，从而实现内存只读                                 //&lt;/span&gt;  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;&lt;span class="rem"&gt;//                                                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;VOID DisableWriteProtect(ULONG oldAttr)  &lt;span class="lnum"&gt;  11:  &lt;/span&gt;{  &lt;span class="lnum"&gt;  12:  &lt;/span&gt;    _asm  &lt;span class="lnum"&gt;  13:  &lt;/span&gt;    {  &lt;span class="lnum"&gt;  14:  &lt;/span&gt;        mov eax, oldAttr  &lt;span class="lnum"&gt;  15:  &lt;/span&gt;        mov cr0, eax  &lt;span class="lnum"&gt;  16:  &lt;/span&gt;        sti;  &lt;span class="lnum"&gt;  17:  &lt;/span&gt;    }  &lt;span class="lnum"&gt;  18:  &lt;/span&gt;}  &lt;span class="lnum"&gt;  19:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  20:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  21:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;  22:  &lt;/span&gt;&lt;span class="rem"&gt;//Name: VOID EnableWriteProtect()                                                      //&lt;/span&gt;  &lt;span class="lnum"&gt;  23:  &lt;/span&gt;&lt;span class="rem"&gt;//                                                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;  24:  &lt;/span&gt;&lt;span class="rem"&gt;//Descripion: 用来去掉内存的只读保护，从而实现可以写内存                               //&lt;/span&gt;  &lt;span class="lnum"&gt;  25:  &lt;/span&gt;&lt;span class="rem"&gt;//                                                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;  26:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;  27:  &lt;/span&gt;VOID EnableWriteProtect(PULONG pOldAttr)  &lt;span class="lnum"&gt;  28:  &lt;/span&gt;{  &lt;span class="lnum"&gt;  29:  &lt;/span&gt;    ULONG uAttr;   &lt;span class="lnum"&gt;  30:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  31:  &lt;/span&gt;    _asm   &lt;span class="lnum"&gt;  32:  &lt;/span&gt;    {   &lt;span class="lnum"&gt;  33:  &lt;/span&gt;        cli;  &lt;span class="lnum"&gt;  34:  &lt;/span&gt;        mov  eax, cr0;   &lt;span class="lnum"&gt;  35:  &lt;/span&gt;        mov  uAttr, eax;   &lt;span class="lnum"&gt;  36:  &lt;/span&gt;        and  eax, 0FFFEFFFFh; &lt;span class="rem"&gt;// CR0 16 BIT = 0 &lt;/span&gt;  &lt;span class="lnum"&gt;  37:  &lt;/span&gt;        mov  cr0, eax;   &lt;span class="lnum"&gt;  38:  &lt;/span&gt;    };   &lt;span class="lnum"&gt;  39:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  40:  &lt;/span&gt;    &lt;span class="rem"&gt;//保存原有的 CRO 属性 &lt;/span&gt;  &lt;span class="lnum"&gt;  41:  &lt;/span&gt;    *pOldAttr = uAttr;   &lt;span class="lnum"&gt;  42:  &lt;/span&gt;}  &lt;span class="lnum"&gt;  43:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  44:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  45:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;  46:  &lt;/span&gt;&lt;span class="rem"&gt;//Name: VOID BackupSysServicesTable()                                                  //&lt;/span&gt;  &lt;span class="lnum"&gt;  47:  &lt;/span&gt;&lt;span class="rem"&gt;//                                                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;  48:  &lt;/span&gt;&lt;span class="rem"&gt;//Descripion: 备份 SSDT 中原有服务的地址，因为在解除 Hook 时需要还原 SSDT 中原有地址   //&lt;/span&gt;  &lt;span class="lnum"&gt;  49:  &lt;/span&gt;&lt;span class="rem"&gt;//                                                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;  50:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;  51:  &lt;/span&gt;VOID BackupSysServicesTable()  &lt;span class="lnum"&gt;  52:  &lt;/span&gt;{  &lt;span class="lnum"&gt;  53:  &lt;/span&gt;    ULONG i;  &lt;span class="lnum"&gt;  54:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  55:  &lt;/span&gt;    &lt;span class="kwrd"&gt;for&lt;/span&gt;(i = 0; (i &amp;lt; KeServiceDescriptorTable-&amp;gt;ntoskrnl.NumberOfService) &amp;amp;&amp;amp; (i &amp;lt; MAX_SYSTEM_SERVICE_NUMBER); i++)  &lt;span class="lnum"&gt;  56:  &lt;/span&gt;    {  &lt;span class="lnum"&gt;  57:  &lt;/span&gt;        oldSysServiceAddr[i] = KeServiceDescriptorTable-&amp;gt;ntoskrnl.ServiceTableBase[i];  &lt;span class="lnum"&gt;  58:  &lt;/span&gt;        &lt;span class="rem"&gt;//oldSysServiceAddr[i] = *(PULONG)((ULONG)KeServiceDescriptorTable-&amp;gt;ntoskrnl.ServiceTableBase + 4 * i);&lt;/span&gt;  &lt;span class="lnum"&gt;  59:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  60:  &lt;/span&gt;        KdPrint((&lt;span class="str"&gt;&amp;quot;\Function Information { Number: 0x%04X , Address: %08X}&amp;quot;&lt;/span&gt;, i, oldSysServiceAddr[i]));  &lt;span class="lnum"&gt;  61:  &lt;/span&gt;    }  &lt;span class="lnum"&gt;  62:  &lt;/span&gt;}  &lt;span class="lnum"&gt;  63:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  64:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  65:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;  66:  &lt;/span&gt;&lt;span class="rem"&gt;//Name: NTSTATUS InstallSysServiceHook()                                               //&lt;/span&gt;  &lt;span class="lnum"&gt;  67:  &lt;/span&gt;&lt;span class="rem"&gt;//                                                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;  68:  &lt;/span&gt;&lt;span class="rem"&gt;//Descripion: 实现 Hook 的安装，主要是在 SSDT 中用 newService 来替换掉 oldService      //&lt;/span&gt;  &lt;span class="lnum"&gt;  69:  &lt;/span&gt;&lt;span class="rem"&gt;//                                                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;  70:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;  71:  &lt;/span&gt;NTSTATUS InstallSysServiceHook(ULONG oldService, ULONG newService)  &lt;span class="lnum"&gt;  72:  &lt;/span&gt;{  &lt;span class="lnum"&gt;  73:  &lt;/span&gt;    ULONG uOldAttr = 0;  &lt;span class="lnum"&gt;  74:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  75:  &lt;/span&gt;    EnableWriteProtect(&amp;amp;uOldAttr);  &lt;span class="lnum"&gt;  76:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  77:  &lt;/span&gt;    SYSCALL_FUNCTION(oldService) = newService;  &lt;span class="lnum"&gt;  78:  &lt;/span&gt;    &lt;span class="rem"&gt;//KeServiceDescriptorTable-&amp;gt;ntoskrnl.ServiceTableBase[SYSCALL_INDEX(oldService)] = newService;&lt;/span&gt;  &lt;span class="lnum"&gt;  79:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  80:  &lt;/span&gt;    DisableWriteProtect(uOldAttr);  &lt;span class="lnum"&gt;  81:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  82:  &lt;/span&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; STATUS_SUCCESS;  &lt;span class="lnum"&gt;  83:  &lt;/span&gt;}  &lt;span class="lnum"&gt;  84:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  85:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  86:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;  87:  &lt;/span&gt;&lt;span class="rem"&gt;//Name: NTSTATUS UnInstallSysServiceHook()                                             //&lt;/span&gt;  &lt;span class="lnum"&gt;  88:  &lt;/span&gt;&lt;span class="rem"&gt;//                                                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;  89:  &lt;/span&gt;&lt;span class="rem"&gt;//Descripion: 实现 Hook 的解除，主要是在 SSDT 中用备份下的服务地址来替换掉 oldService  //&lt;/span&gt;  &lt;span class="lnum"&gt;  90:  &lt;/span&gt;&lt;span class="rem"&gt;//                                                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;  91:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;  92:  &lt;/span&gt;NTSTATUS UnInstallSysServiceHook(ULONG oldService)  &lt;span class="lnum"&gt;  93:  &lt;/span&gt;{  &lt;span class="lnum"&gt;  94:  &lt;/span&gt;    ULONG uOldAttr = 0;  &lt;span class="lnum"&gt;  95:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  96:  &lt;/span&gt;    EnableWriteProtect(&amp;amp;uOldAttr);  &lt;span class="lnum"&gt;  97:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  98:  &lt;/span&gt;    SYSCALL_FUNCTION(oldService) = oldSysServiceAddr[SYSCALL_INDEX(oldService)];  &lt;span class="lnum"&gt; 100:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 101:  &lt;/span&gt;    DisableWriteProtect(uOldAttr);  &lt;span class="lnum"&gt; 102:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt; 103:  &lt;/span&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; STATUS_SUCCESS;  &lt;span class="lnum"&gt; 104:  &lt;/span&gt;}&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;可以注意到上面有两个很重要的宏，即 SYSCALL_FUNCTION 和 SYSCALL_INDEX 宏，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;关于这两个宏的具体作用，可以看注释的 ~ &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="rem"&gt;//根据 Zw_ServiceFunction 获取 Zw_ServiceFunction 在 SSDT 中所对应的服务的索引号&lt;/span&gt;  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="preproc"&gt;#define&lt;/span&gt; SYSCALL_INDEX(ServiceFunction) (*(PULONG)((PUCHAR)ServiceFunction + 1))  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;span class="rem"&gt;//根据 Zw_ServiceFunction 来获得服务在 SSDT 中的索引号，&lt;/span&gt;  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;&lt;span class="rem"&gt;//然后再通过该索引号来获取 Nt_ServiceFunction的地址&lt;/span&gt;  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;&lt;span class="preproc"&gt;#define&lt;/span&gt; SYSCALL_FUNCTION(ServiceFunction)   &lt;span class="lnum"&gt;   8:  &lt;/span&gt;        KeServiceDescriptorTable-&amp;gt;ntoskrnl.ServiceTableBase[SYSCALL_INDEX(ServiceFunction)]&lt;/div&gt;&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;4. Ring0 实现进程隐藏：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;有了 SSDT Hook 框架后，其实要实现进程的隐藏是很简单的了，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;根据前面的介绍，要想实现进程隐藏，你可以通过 Hook NtQuerySystemInformation 来实现，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;所以剩下的任务就只需要在我们自己的 Hook 处理函数中来将进程隐藏掉就 OK 了 ~&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;由于 NtQuerySystemInformation 这个系统服务在 ntddk.h 中并没有被声明，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;虽然这个系统服务在 ntoskrnl.exe 中被导出了，但是没有它的声明，我们仍然是无法使用的，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;所以我们就需要手动的声明一下这个函数 ~ &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;还有需要注意的是，我们在前面知道，在 ntoskrnl.exe 中实质上是存在 ZwQuerySystemInformation &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;以及 NtQuerySystemInformation 这两个 API 的，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;而在 SSDT Hook 中我们是根据 ZwQuerySystemInformation &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;来推算出在 SSDT 中保存有 NtQuerySystemInformation 的地址所在的索引号的 ~ &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;关于这个，你可以查看 SYSCALL_INDEX 这个宏来再次确认一下 ~ &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后有了这个索引号，我们才可以进行对 NtQuerySystemInformation 系统服务的 Hook，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;所以在声明时，我们需要声明两个 API，当然如果这些 API 在 ntddk.h 中声明了就不需要了，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;但是由于 ZwQuerySystemInformation 和 NtQuerySystemInformation 在 ntddk.h 中都没有声明，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;所以需要在我们自己的代码中手动声明 ~ &lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation (  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;    __in SYSTEM_INFORMATION_CLASS SystemInformationClass,  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;    __out_bcount_opt(SystemInformationLength) PVOID SystemInformation,  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;    __in ULONG SystemInformationLength,  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;    __out_opt PULONG ReturnLength  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;    );  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;typedef NTSTATUS (* NTQUERYSYSTEMINFORMATION)(  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;    __in SYSTEM_INFORMATION_CLASS SystemInformationClass,  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;    __out_bcount_opt(SystemInformationLength) PVOID SystemInformation,  &lt;span class="lnum"&gt;  11:  &lt;/span&gt;    __in ULONG SystemInformationLength,  &lt;span class="lnum"&gt;  12:  &lt;/span&gt;    __out_opt PULONG ReturnLength  &lt;span class="lnum"&gt;  13:  &lt;/span&gt;    );&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;(暂停一下，肚子饿了 ~ 吃饭去 ~ )&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;(好，饭给吃了，酒也喝了，精神亢奋中，现在咱继续哈 ~ 嘿嘿 ~)&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;完成了这些声明后，我们就可以来实现自己的 NtQuerySystemInformation Hook 函数了，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;在这个 Hook 函数中，我们需要对我们感兴趣的进程进行隐藏 ~ &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;然后这里需要注意的是，我是如何来实现对进程隐藏的，&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;首先我是判断这个进程的 ID 是否是需要隐藏的进程 ID，&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;这是通过 ValidateProcessNeedHide 函数来判断的 ~ 这个函数会在后面给出 ~ &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;注意结合代码中的注释来看(虽然注释比较少 ~ 嘿嘿 ~ )&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;NTSTATUS HookNtQuerySystemInformation (  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;    __in SYSTEM_INFORMATION_CLASS SystemInformationClass,  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;    __out_bcount_opt(SystemInformationLength) PVOID SystemInformation,  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;    __in ULONG SystemInformationLength,  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;    __out_opt PULONG ReturnLength  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;    );&lt;/div&gt;&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="rem"&gt;//Name: NTSTATUS HookNtQuerySystemInformation()                                        //&lt;/span&gt;  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;&lt;span class="rem"&gt;//                                                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="rem"&gt;//Descripion: 自定义的 NtQuerySystemInformation，用来实现 Hook Kernel API              //&lt;/span&gt;  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;span class="rem"&gt;//                                                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;NTSTATUS HookNtQuerySystemInformation (  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;    __in SYSTEM_INFORMATION_CLASS SystemInformationClass,  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;    __out_bcount_opt(SystemInformationLength) PVOID SystemInformation,  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;    __in ULONG SystemInformationLength,  &lt;span class="lnum"&gt;  11:  &lt;/span&gt;    __out_opt PULONG ReturnLength  &lt;span class="lnum"&gt;  12:  &lt;/span&gt;    )  &lt;span class="lnum"&gt;  13:  &lt;/span&gt;{  &lt;span class="lnum"&gt;  14:  &lt;/span&gt;    NTSTATUS rtStatus;  &lt;span class="lnum"&gt;  15:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  16:  &lt;/span&gt;    pOldNtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)  &lt;span class="lnum"&gt;  17:  &lt;/span&gt;        oldSysServiceAddr[SYSCALL_INDEX(ZwQuerySystemInformation)];  &lt;span class="lnum"&gt;  18:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  19:  &lt;/span&gt;    rtStatus = pOldNtQuerySystemInformation(SystemInformationClass, SystemInformation,   &lt;span class="lnum"&gt;  20:  &lt;/span&gt;        SystemInformationLength, ReturnLength);  &lt;span class="lnum"&gt;  21:  &lt;/span&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt;(NT_SUCCESS(rtStatus))  &lt;span class="lnum"&gt;  22:  &lt;/span&gt;    {  &lt;span class="lnum"&gt;  23:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt;(SystemProcessInformation == SystemInformationClass)  &lt;span class="lnum"&gt;  24:  &lt;/span&gt;        {  &lt;span class="lnum"&gt;  25:  &lt;/span&gt;            PSYSTEM_PROCESS_INFORMATION pPrevProcessInfo = NULL;  &lt;span class="lnum"&gt;  26:  &lt;/span&gt;            PSYSTEM_PROCESS_INFORMATION pCurrProcessInfo =   &lt;span class="lnum"&gt;  27:  &lt;/span&gt;                (PSYSTEM_PROCESS_INFORMATION)SystemInformation;   &lt;span class="lnum"&gt;  28:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  29:  &lt;/span&gt;            &lt;span class="kwrd"&gt;while&lt;/span&gt;(pCurrProcessInfo != NULL)  &lt;span class="lnum"&gt;  30:  &lt;/span&gt;            {  &lt;span class="lnum"&gt;  31:  &lt;/span&gt;                &lt;span class="rem"&gt;//获取当前遍历的 SYSTEM_PROCESS_INFORMATION 节点的进程名称和进程 ID&lt;/span&gt;  &lt;span class="lnum"&gt;  32:  &lt;/span&gt;                ULONG uPID = (ULONG)pCurrProcessInfo-&amp;gt;UniqueProcessId;  &lt;span class="lnum"&gt;  33:  &lt;/span&gt;                UNICODE_STRING strTmpProcessName = pCurrProcessInfo-&amp;gt;ImageName;  &lt;span class="lnum"&gt;  34:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  35:  &lt;/span&gt;                &lt;span class="rem"&gt;//判断当前遍历的这个进程是否为需要隐藏的进程&lt;/span&gt;  &lt;span class="lnum"&gt;  36:  &lt;/span&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt;(ValidateProcessNeedHide(uPID) != -1)  &lt;span class="lnum"&gt;  37:  &lt;/span&gt;                {  &lt;span class="lnum"&gt;  38:  &lt;/span&gt;                    &lt;span class="kwrd"&gt;if&lt;/span&gt;(pPrevProcessInfo)  &lt;span class="lnum"&gt;  39:  &lt;/span&gt;                    {  &lt;span class="lnum"&gt;  40:  &lt;/span&gt;                        &lt;span class="kwrd"&gt;if&lt;/span&gt;(pCurrProcessInfo-&amp;gt;NextEntryOffset)  &lt;span class="lnum"&gt;  41:  &lt;/span&gt;                        {  &lt;span class="lnum"&gt;  42:  &lt;/span&gt;                            &lt;span class="rem"&gt;//将当前这个进程(即要隐藏的进程)从 SystemInformation 中摘除(更改链表偏移指针实现)&lt;/span&gt;  &lt;span class="lnum"&gt;  43:  &lt;/span&gt;                            pPrevProcessInfo-&amp;gt;NextEntryOffset += pCurrProcessInfo-&amp;gt;NextEntryOffset;  &lt;span class="lnum"&gt;  44:  &lt;/span&gt;                        }  &lt;span class="lnum"&gt;  45:  &lt;/span&gt;                        &lt;span class="kwrd"&gt;else&lt;/span&gt;  &lt;span class="lnum"&gt;  46:  &lt;/span&gt;                        {  &lt;span class="lnum"&gt;  47:  &lt;/span&gt;                            &lt;span class="rem"&gt;//说明当前要隐藏的这个进程是进程链表中的最后一个&lt;/span&gt;  &lt;span class="lnum"&gt;  48:  &lt;/span&gt;                            pPrevProcessInfo-&amp;gt;NextEntryOffset = 0;  &lt;span class="lnum"&gt;  49:  &lt;/span&gt;                        }  &lt;span class="lnum"&gt;  50:  &lt;/span&gt;                    }  &lt;span class="lnum"&gt;  51:  &lt;/span&gt;                    &lt;span class="kwrd"&gt;else&lt;/span&gt;  &lt;span class="lnum"&gt;  52:  &lt;/span&gt;                    {  &lt;span class="lnum"&gt;  53:  &lt;/span&gt;                        &lt;span class="rem"&gt;//第一个遍历到得进程就是需要隐藏的进程&lt;/span&gt;  &lt;span class="lnum"&gt;  54:  &lt;/span&gt;                        &lt;span class="kwrd"&gt;if&lt;/span&gt;(pCurrProcessInfo-&amp;gt;NextEntryOffset)  &lt;span class="lnum"&gt;  55:  &lt;/span&gt;                        {  &lt;span class="lnum"&gt;  56:  &lt;/span&gt;                            (PCHAR)SystemInformation += pCurrProcessInfo-&amp;gt;NextEntryOffset;  &lt;span class="lnum"&gt;  57:  &lt;/span&gt;                        }  &lt;span class="lnum"&gt;  58:  &lt;/span&gt;                        &lt;span class="kwrd"&gt;else&lt;/span&gt;  &lt;span class="lnum"&gt;  59:  &lt;/span&gt;                        {  &lt;span class="lnum"&gt;  60:  &lt;/span&gt;                            SystemInformation = NULL;  &lt;span class="lnum"&gt;  61:  &lt;/span&gt;                        }  &lt;span class="lnum"&gt;  62:  &lt;/span&gt;                    }  &lt;span class="lnum"&gt;  63:  &lt;/span&gt;                }  &lt;span class="lnum"&gt;  64:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  65:  &lt;/span&gt;                &lt;span class="rem"&gt;//遍历下一个 SYSTEM_PROCESS_INFORMATION 节点&lt;/span&gt;  &lt;span class="lnum"&gt;  66:  &lt;/span&gt;                pPrevProcessInfo = pCurrProcessInfo;  &lt;span class="lnum"&gt;  67:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  68:  &lt;/span&gt;                &lt;span class="rem"&gt;//遍历结束&lt;/span&gt;  &lt;span class="lnum"&gt;  69:  &lt;/span&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt;(pCurrProcessInfo-&amp;gt;NextEntryOffset)  &lt;span class="lnum"&gt;  70:  &lt;/span&gt;                {  &lt;span class="lnum"&gt;  71:  &lt;/span&gt;                    pCurrProcessInfo = (PSYSTEM_PROCESS_INFORMATION)  &lt;span class="lnum"&gt;  72:  &lt;/span&gt;                        (((PCHAR)pCurrProcessInfo) + pCurrProcessInfo-&amp;gt;NextEntryOffset);  &lt;span class="lnum"&gt;  73:  &lt;/span&gt;                }  &lt;span class="lnum"&gt;  74:  &lt;/span&gt;                &lt;span class="kwrd"&gt;else&lt;/span&gt;  &lt;span class="lnum"&gt;  75:  &lt;/span&gt;                {  &lt;span class="lnum"&gt;  76:  &lt;/span&gt;                    pCurrProcessInfo = NULL;  &lt;span class="lnum"&gt;  77:  &lt;/span&gt;                }  &lt;span class="lnum"&gt;  78:  &lt;/span&gt;            }  &lt;span class="lnum"&gt;  79:  &lt;/span&gt;        }  &lt;span class="lnum"&gt;  80:  &lt;/span&gt;    }  &lt;span class="lnum"&gt;  81:  &lt;/span&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; rtStatus;  &lt;span class="lnum"&gt;  82:  &lt;/span&gt;}&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;既然有了自己的 Hook NtQuerySystemInformation 了，自然我们就可以通过利用 SSDT 框架来实现 Hook 了，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;这部分的代码其实是最简单的，因为我只需要在 DriverEntry 中 Hook 掉 NtQuerySystemInformation 即可，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;这里需要注意的是，在执行 Hook 之前需要备份一次 SSDT，即在 DriverEntry 中最先需要备份 SSDT ~&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;当然为了保证系统的安全以及其他诸多方面，我们在 DriverUnload 中会将 Hook 解除掉 ~ &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;从下面的代码中，我们看到在安装 Hook 和解除 Hook 时参数传递进去的是 ZwQuerySystemInformation，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;这样很有可能会让很多朋友认为我们在 Ring0 下的 Hook 的是 ZwQuerySystemInformation，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;如果你这样认为的话，那就大错特错了，确实在 Google 上搜索出的一大堆关于 SSDT Hook 中，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;很多文章都说是 Hook 的 ZwQuerySystemInformation，而事实上这是大错特错的，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;我们这里传入 ZwQuerySystemInformation ，是因为我们需要调用 SYS_INDEX(ZwQuerySystemInformation) &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;来获得 NtQuerySystemInformation 在 SSDT 中的地址所在的索引号，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;然后我们根据这个索引号来 Hook NtQuerySystemInformation，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;认识到这一点是非常重要的，因为我一开始也认为是 Hook 的 ZwQuerySystemInformation，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;从而导致蓝屏了 n 次，在这里非常鄙视那些把文章从别处拷贝过来也不加验证就乱发表的 ~ 害死人 ~ 当然也要怪自己懒 ~&lt;/font&gt;&lt;/strong&gt; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109041810011575.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109041810059430.png" width="1047" height="130" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109041810072169.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109041810136908.png" width="1066" height="411" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;5. Ring0 实现进程保护：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;有了上面实现进程隐藏的基础，要再来实现进程保护，其实也就是过过场子了 ~ &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;进程保护呢，上面也说了，是要 Hook NtTermianteProcess 这个系统服务 ~ &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;由于 ZwTerminateProcess 呢，在 ntddk.h 中已经声明了，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;所以在我们自己的代码中就不需要声明 ZwTermianteProcess 了，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;而只需要声明 NtTerminateProcess 以及 Hook 函数就 OK 了 ~ &lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;typedef NTSTATUS (* NTTERMINATEPROCESS)(  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;    __in_opt HANDLE ProcessHandle,  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;    __in NTSTATUS ExitStatus  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;    );  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;NTSTATUS HookNtTerminateProcess(  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;    __in_opt HANDLE ProcessHandle,  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;    __in NTSTATUS ExitStatus  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;    );  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  11:  &lt;/span&gt;NTTERMINATEPROCESS pOldNtTerminateProcess;&lt;/div&gt;&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;至于安装 Hook 以及卸载 Hook ，都可以根据进程隐藏中的代码来完成，因为有了 SSDT Hook 框架，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;这一切也就变得很简单了，只要在 DriverEntry 中 InstallHook ，然后再在 DriverUnload 中 UnInstallHook 即 OK ~&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;下面我们重点来看一看我们自己的 Hook NtTerminateProcess 中是如何实现进程保护的 ~ &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;进程保护呢其实也是比较简单的，因为从上面一层的调用会传递一个进程句柄下来，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;而后我们可以根据这个进程句柄来获得进程的 EPROCESS 对象(进程位于执行体层得对象)，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;通过这个 EPROCESS 对象，我们就可以获得这个请求被结束的进程的 PID，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;我们再判断这个 PID 是否是我们已经保护了的 PID，如果是的话，直接返回一个请求被拒绝即可，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;而如果这个 PID 未被保护，自然我们就交给原来的 NtTerminateProcess 处理即可 ~&lt;/font&gt;&lt;/strong&gt; &lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="rem"&gt;//Name: NTSTATUS HookNtTerminateProcess()                                              //&lt;/span&gt;  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;&lt;span class="rem"&gt;//                                                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="rem"&gt;//Descripion: 自定义的 NtTerminateProcess，用来实现 Hook Kernel API                    //&lt;/span&gt;  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;span class="rem"&gt;//                                                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;NTSTATUS HookNtTerminateProcess(  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;    __in_opt HANDLE ProcessHandle,  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;    __in NTSTATUS ExitStatus  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;    )  &lt;span class="lnum"&gt;  11:  &lt;/span&gt;{  &lt;span class="lnum"&gt;  12:  &lt;/span&gt;    ULONG uPID;  &lt;span class="lnum"&gt;  13:  &lt;/span&gt;    NTSTATUS rtStatus;  &lt;span class="lnum"&gt;  14:  &lt;/span&gt;    PCHAR pStrProcName;  &lt;span class="lnum"&gt;  15:  &lt;/span&gt;    PEPROCESS pEProcess;  &lt;span class="lnum"&gt;  16:  &lt;/span&gt;    ANSI_STRING strProcName;  &lt;span class="lnum"&gt;  17:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  18:  &lt;/span&gt;    &lt;span class="rem"&gt;//通过进程句柄来获得该进程所对应的 FileObject 对象，由于这里是进程对象，自然获得的是 EPROCESS 对象&lt;/span&gt;  &lt;span class="lnum"&gt;  19:  &lt;/span&gt;    rtStatus = ObReferenceObjectByHandle(ProcessHandle,   &lt;span class="lnum"&gt;  20:  &lt;/span&gt;        FILE_READ_DATA, NULL, KernelMode, &amp;amp;pEProcess, NULL);  &lt;span class="lnum"&gt;  21:  &lt;/span&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt;(!NT_SUCCESS(rtStatus))  &lt;span class="lnum"&gt;  22:  &lt;/span&gt;    {  &lt;span class="lnum"&gt;  23:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; rtStatus;  &lt;span class="lnum"&gt;  24:  &lt;/span&gt;    }  &lt;span class="lnum"&gt;  25:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  26:  &lt;/span&gt;    &lt;span class="rem"&gt;//保存 SSDT 中原来的 NtTerminateProcess 地址&lt;/span&gt;  &lt;span class="lnum"&gt;  27:  &lt;/span&gt;    pOldNtTerminateProcess =   &lt;span class="lnum"&gt;  28:  &lt;/span&gt;        (NTTERMINATEPROCESS)oldSysServiceAddr[SYSCALL_INDEX(ZwTerminateProcess)];  &lt;span class="lnum"&gt;  29:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  30:  &lt;/span&gt;    &lt;span class="rem"&gt;//通过该函数可以获取到进程名称和进程 ID，该函数在内核中实质是导出的(在 WRK 中可以看到)&lt;/span&gt;  &lt;span class="lnum"&gt;  31:  &lt;/span&gt;    &lt;span class="rem"&gt;//但是 ntddk.h 中并没有到处，所以需要自己声明才能使用&lt;/span&gt;  &lt;span class="lnum"&gt;  32:  &lt;/span&gt;    uPID = (ULONG)PsGetProcessId(pEProcess);  &lt;span class="lnum"&gt;  33:  &lt;/span&gt;    pStrProcName = (PCHAR)PsGetProcessImageFileName(pEProcess);  &lt;span class="lnum"&gt;  34:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  35:  &lt;/span&gt;    &lt;span class="rem"&gt;//通过进程名来初始化一个 ASCII 字符串&lt;/span&gt;  &lt;span class="lnum"&gt;  36:  &lt;/span&gt;    RtlInitAnsiString(&amp;amp;strProcName, pStrProcName);  &lt;span class="lnum"&gt;  37:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  38:  &lt;/span&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt;(ValidateProcessNeedProtect(uPID) != -1)  &lt;span class="lnum"&gt;  39:  &lt;/span&gt;    {  &lt;span class="lnum"&gt;  40:  &lt;/span&gt;        &lt;span class="rem"&gt;//确保调用者进程能够结束(这里主要是指 taskmgr.exe)&lt;/span&gt;  &lt;span class="lnum"&gt;  41:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt;(uPID != (ULONG)PsGetProcessId(PsGetCurrentProcess()))  &lt;span class="lnum"&gt;  42:  &lt;/span&gt;        {  &lt;span class="lnum"&gt;  43:  &lt;/span&gt;            &lt;span class="rem"&gt;//如果该进程是所保护的的进程的话，则返回权限不够的异常即可&lt;/span&gt;  &lt;span class="lnum"&gt;  44:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; STATUS_ACCESS_DENIED;  &lt;span class="lnum"&gt;  45:  &lt;/span&gt;        }  &lt;span class="lnum"&gt;  46:  &lt;/span&gt;    }  &lt;span class="lnum"&gt;  47:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  48:  &lt;/span&gt;    &lt;span class="rem"&gt;//对于非保护的进程可以直接调用原来 SSDT 中的 NtTerminateProcess 来结束进程&lt;/span&gt;  &lt;span class="lnum"&gt;  49:  &lt;/span&gt;    rtStatus = pOldNtTerminateProcess(ProcessHandle, ExitStatus);  &lt;span class="lnum"&gt;  50:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  51:  &lt;/span&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; rtStatus;  &lt;span class="lnum"&gt;  52:  &lt;/span&gt;}&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;6. 隐藏进程列表和保护进程列表的维护：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;由于需要隐藏的进程以及需要被保护的进程都是由应用程序传递进来的，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;也就是说这个内核程序是需要和应用程序通信的，自然就需要创建一个 Device，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后我就采用了简单的 DeviceIoControl 来实现了内核程序和应用程序的通信，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;对于需要隐藏的进程或者是需要保护的进程，其由应用程序通过 DeviceIoControl 来将这个进程的 PID 传递给内核程序，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后在内核程序中呢，维护了两个数组，一个数组用来存放需要隐藏的进程的 PID，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;另外一个数组自然就是用来存放需要保护的进程的 PID，&lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;ULONG g_PIDHideArray[MAX_PROCESS_ARRARY_LENGTH];  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;ULONG g_PIDProtectArray[MAX_PROCESS_ARRARY_LENGTH];  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;ULONG g_currHideArrayLen = 0;  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;ULONG g_currProtectArrayLen = 0;&lt;/div&gt;&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;为了维护上面的这两个数组呢，又衍生出了几个 API，即实现对数组中的 PID 进行增删查 ~ &lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="rem"&gt;//验证 uPID 所代表的进程是否存在于隐藏进程列表中，即判断 uPID 这个进程是否需要隐藏&lt;/span&gt;  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;ULONG ValidateProcessNeedHide(ULONG uPID);  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="rem"&gt;//验证 uPID 所代表的进程是否存在于保护进程列表中，即判断 uPID 这个进程是否需要保护&lt;/span&gt;  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;ULONG ValidateProcessNeedProtect(ULONG uPID);  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;&lt;span class="rem"&gt;//往隐藏进程列表中插入 uPID&lt;/span&gt;  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;ULONG InsertHideProcess(ULONG uPID);  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;&lt;span class="rem"&gt;//从隐藏进程列表中移除 uPID&lt;/span&gt;  &lt;span class="lnum"&gt;  11:  &lt;/span&gt;ULONG RemoveHideProcess(ULONG uPID);  &lt;span class="lnum"&gt;  12:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  13:  &lt;/span&gt;&lt;span class="rem"&gt;//往保护进程列表中插入 uPID&lt;/span&gt;  &lt;span class="lnum"&gt;  14:  &lt;/span&gt;ULONG InsertProtectProcess(ULONG uPID);  &lt;span class="lnum"&gt;  15:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  16:  &lt;/span&gt;&lt;span class="rem"&gt;//从隐藏进程列表中移除 uPID&lt;/span&gt;  &lt;span class="lnum"&gt;  17:  &lt;/span&gt;ULONG RemoveProtectProcess(ULONG uPID);&lt;/div&gt;&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;对于前面谈及的 HookNtQuerySystemInformation 和 HookNtTerminateProcess 的话，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;需要判断一个进程是否是需要被保护或者需要被隐藏的进程就是通过上面的数组来完成的，&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;即判断一个进程是否需要被隐藏时，只需要判断这个进程在隐藏列表中是否存在即可，&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;而对于实现进程保护的话，道理也是一样的 ~ &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;上面说过，应用程序和内核程序的通信是通过 DeviceIoControl 来完成的，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;下面我们就来看看 DeviceIoControl 的代码：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;  &lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="rem"&gt;//Name: NTSTATUS SSDT01DeviceIoControlDispatcher()                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;&lt;span class="rem"&gt;//                                                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="rem"&gt;//Descripion: 分发函数                                                                 //&lt;/span&gt;  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;span class="rem"&gt;//                                                                                     //&lt;/span&gt;  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;&lt;span class="rem"&gt;//=====================================================================================//&lt;/span&gt;  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;NTSTATUS SSDT01DeviceIoControlDispatcher(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;{  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;    NTSTATUS rtStatus;  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  11:  &lt;/span&gt;    ULONG uPID;  &lt;span class="lnum"&gt;  12:  &lt;/span&gt;    ULONG uInLen;  &lt;span class="lnum"&gt;  13:  &lt;/span&gt;    ULONG uOutLen;  &lt;span class="lnum"&gt;  14:  &lt;/span&gt;    ULONG uCtrlCode;  &lt;span class="lnum"&gt;  15:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  16:  &lt;/span&gt;    PCHAR pInBuffer;  &lt;span class="lnum"&gt;  17:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  18:  &lt;/span&gt;    PIO_STACK_LOCATION pStack;      &lt;span class="lnum"&gt;  19:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  20:  &lt;/span&gt;    uPID = 0;  &lt;span class="lnum"&gt;  21:  &lt;/span&gt;    rtStatus = STATUS_SUCCESS;  &lt;span class="lnum"&gt;  22:  &lt;/span&gt;    pStack = IoGetCurrentIrpStackLocation(pIrp);  &lt;span class="lnum"&gt;  23:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  24:  &lt;/span&gt;    uInLen = pStack-&amp;gt;Parameters.DeviceIoControl.InputBufferLength;  &lt;span class="lnum"&gt;  25:  &lt;/span&gt;    uOutLen = pStack-&amp;gt;Parameters.DeviceIoControl.OutputBufferLength;  &lt;span class="lnum"&gt;  26:  &lt;/span&gt;    uCtrlCode = pStack-&amp;gt;Parameters.DeviceIoControl.IoControlCode;  &lt;span class="lnum"&gt;  27:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  28:  &lt;/span&gt;    &lt;span class="rem"&gt;//使用缓冲区方式与应用程序进行通信&lt;/span&gt;  &lt;span class="lnum"&gt;  29:  &lt;/span&gt;    pInBuffer = (PCHAR)pIrp-&amp;gt;AssociatedIrp.SystemBuffer;  &lt;span class="lnum"&gt;  30:  &lt;/span&gt;      &lt;span class="lnum"&gt;  31:  &lt;/span&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt;(uInLen &amp;gt;= 4)  &lt;span class="lnum"&gt;  32:  &lt;/span&gt;    {  &lt;span class="lnum"&gt;  33:  &lt;/span&gt;        &lt;span class="rem"&gt;//stdlib.h(atol = Array To LONG)&lt;/span&gt;  &lt;span class="lnum"&gt;  34:  &lt;/span&gt;        uPID = atol(pInBuffer);  &lt;span class="lnum"&gt;  35:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  36:  &lt;/span&gt;        &lt;span class="kwrd"&gt;switch&lt;/span&gt;(uCtrlCode)  &lt;span class="lnum"&gt;  37:  &lt;/span&gt;        {  &lt;span class="lnum"&gt;  38:  &lt;/span&gt;        &lt;span class="kwrd"&gt;case&lt;/span&gt; IO_INSERT_PROTECT_PROCESS:  &lt;span class="lnum"&gt;  39:  &lt;/span&gt;            {  &lt;span class="lnum"&gt;  40:  &lt;/span&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt;(InsertProtectProcess(uPID) == FALSE)  &lt;span class="lnum"&gt;  41:  &lt;/span&gt;                {  &lt;span class="lnum"&gt;  42:  &lt;/span&gt;                    rtStatus = STATUS_PROCESS_IS_TERMINATING;  &lt;span class="lnum"&gt;  43:  &lt;/span&gt;                }  &lt;span class="lnum"&gt;  44:  &lt;/span&gt;                &lt;span class="kwrd"&gt;break&lt;/span&gt;;  &lt;span class="lnum"&gt;  45:  &lt;/span&gt;            }  &lt;span class="lnum"&gt;  46:  &lt;/span&gt;        &lt;span class="kwrd"&gt;case&lt;/span&gt; IO_REMOVE_PROTECT_PROCESS:  &lt;span class="lnum"&gt;  47:  &lt;/span&gt;            {  &lt;span class="lnum"&gt;  48:  &lt;/span&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt;(RemoveProtectProcess(uPID) == FALSE)  &lt;span class="lnum"&gt;  49:  &lt;/span&gt;                {  &lt;span class="lnum"&gt;  50:  &lt;/span&gt;                    rtStatus = STATUS_PROCESS_IS_TERMINATING;  &lt;span class="lnum"&gt;  51:  &lt;/span&gt;                }  &lt;span class="lnum"&gt;  52:  &lt;/span&gt;                &lt;span class="kwrd"&gt;break&lt;/span&gt;;  &lt;span class="lnum"&gt;  53:  &lt;/span&gt;            }  &lt;span class="lnum"&gt;  54:  &lt;/span&gt;        &lt;span class="kwrd"&gt;case&lt;/span&gt; IO_INSERT_HIDE_PROCESS:  &lt;span class="lnum"&gt;  55:  &lt;/span&gt;            {  &lt;span class="lnum"&gt;  56:  &lt;/span&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt;(InsertHideProcess(uPID) == FALSE)  &lt;span class="lnum"&gt;  57:  &lt;/span&gt;                {  &lt;span class="lnum"&gt;  58:  &lt;/span&gt;                    rtStatus = STATUS_PROCESS_IS_TERMINATING;  &lt;span class="lnum"&gt;  59:  &lt;/span&gt;                }  &lt;span class="lnum"&gt;  60:  &lt;/span&gt;                &lt;span class="kwrd"&gt;break&lt;/span&gt;;  &lt;span class="lnum"&gt;  61:  &lt;/span&gt;            }  &lt;span class="lnum"&gt;  62:  &lt;/span&gt;        &lt;span class="kwrd"&gt;case&lt;/span&gt; IO_REMOVE_HIDE_PROCESS:  &lt;span class="lnum"&gt;  63:  &lt;/span&gt;            {  &lt;span class="lnum"&gt;  64:  &lt;/span&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt;(RemoveHideProcess(uPID) == FALSE)  &lt;span class="lnum"&gt;  65:  &lt;/span&gt;                {  &lt;span class="lnum"&gt;  66:  &lt;/span&gt;                    rtStatus = STATUS_PROCESS_IS_TERMINATING;  &lt;span class="lnum"&gt;  67:  &lt;/span&gt;                }  &lt;span class="lnum"&gt;  68:  &lt;/span&gt;                &lt;span class="kwrd"&gt;break&lt;/span&gt;;  &lt;span class="lnum"&gt;  69:  &lt;/span&gt;            }  &lt;span class="lnum"&gt;  70:  &lt;/span&gt;        &lt;span class="kwrd"&gt;default&lt;/span&gt;:  &lt;span class="lnum"&gt;  71:  &lt;/span&gt;            {  &lt;span class="lnum"&gt;  72:  &lt;/span&gt;                rtStatus = STATUS_INVALID_VARIANT;  &lt;span class="lnum"&gt;  73:  &lt;/span&gt;                &lt;span class="kwrd"&gt;break&lt;/span&gt;;  &lt;span class="lnum"&gt;  74:  &lt;/span&gt;            }  &lt;span class="lnum"&gt;  75:  &lt;/span&gt;        }  &lt;span class="lnum"&gt;  76:  &lt;/span&gt;    }  &lt;span class="lnum"&gt;  77:  &lt;/span&gt;    &lt;span class="kwrd"&gt;else&lt;/span&gt;  &lt;span class="lnum"&gt;  78:  &lt;/span&gt;    {  &lt;span class="lnum"&gt;  79:  &lt;/span&gt;        rtStatus = STATUS_INVALID_PARAMETER;  &lt;span class="lnum"&gt;  80:  &lt;/span&gt;    }  &lt;span class="lnum"&gt;  81:  &lt;/span&gt;      &lt;span class="lnum"&gt;  82:  &lt;/span&gt;    &lt;span class="rem"&gt;//输出信息总是为空，即该驱动程序不返回输出信息&lt;/span&gt;  &lt;span class="lnum"&gt;  83:  &lt;/span&gt;    pIrp-&amp;gt;IoStatus.Status = rtStatus;  &lt;span class="lnum"&gt;  84:  &lt;/span&gt;    pIrp-&amp;gt;IoStatus.Information = 0;  &lt;span class="lnum"&gt;  85:  &lt;/span&gt;    IoCompleteRequest(pIrp, IO_NO_INCREMENT);  &lt;span class="lnum"&gt;  86:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  87:  &lt;/span&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; rtStatus;  &lt;span class="lnum"&gt;  88:  &lt;/span&gt;}&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;7. 小结：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;这篇博文呢，是承接前一篇博文《进程隐藏与进程保护(SSDT Hook 实现)(一)》来的，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;前面的博文主要介绍了 SSDT 是个什么东西，以及我们做内核 Hook 的一些基础，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;而这篇博文则完整的介绍了 SSDT Hook 的具体实现，其中涉及到了很多底层的知识的，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;对于绝大部分的代码呢，大伙是可以参考代码来进行理解的，而后我会将内核部分的代码先公开出来 ~ &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;本来呢是打算将这个 SSDT Hook 做两篇博文就给结束得了，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;不过第二篇博文写了这么长了，但是在应用程序中的实现都还没有开始介绍，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;而今晚真的又太晚了，再写下去天就亮了，还说要尽量不熬夜的 ~ 唉 ~ 算了，权当周末给自己找个借口吧 ~ &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;下一篇博文将介绍的是如何在应用程序中获取到所有的进程啊，以及应用程序如何和内核程序设备进行通信之类的知识，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;知识重点是放在 Ring3 了，其中不会涉及到很多 Ring0 的内容了 ~ &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;开发工具以及环境搭建：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;Visual Studio 2010 + VirtualDDK + WDK + VMware + Windows Service 2003 SP1，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;至于具体环境的搭建，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;可以参考我的博文&lt;strong&gt;《驱动程序环境搭建(VS2010 + WDK + VirtualDDK + VMware)》&lt;/strong&gt;，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;博文地址如下：&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/archive/2011/07/31/2122755.html"&gt;&lt;font size="2" face="Courier New"&gt;http://www.cnblogs.com/BoyXiao/archive/2011/07/31/2122755.html&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="3" face="Courier New"&gt;&lt;strong&gt;&lt;u&gt;下载 &lt;/u&gt;&lt;/strong&gt;&lt;/font&gt;&lt;a href="http://files.cnblogs.com/BoyXiao/SSDT01.zip"&gt;&lt;font color="#ff0000" size="3" face="Courier New"&gt;&lt;strong&gt;SSDT Hook Source Code&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;font color="#ff0000" size="3" face="Courier New"&gt;&lt;strong&gt;&lt;u&gt; &lt;/u&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;font face="Verdana"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;和前一篇文章一样，我将我近来遇到的一些疑问放到博文的最后面，看是否有看官遇到过，如果有遇到过的，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;还请不吝赐教 ~ 在下感激不尽 ~ &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;疑问 1： &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;在 .Net WinForm 中，我有一个定时器，然后又有一个按钮，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;那么对应的就有一个定时器 Tick 处理事件，&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;按钮也会有一个 Click 事件，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;考虑在多核处理器上，&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;有没有这样一种可能，按钮的 Click 事件和 Tick 处理事件并发执行 ?&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;如果有的话，大伙一般都是如何做处理的 ?&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;疑问 2：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;大家都有用过 SVN 的，当我们安装好客户端工具 TortoiseSVN 后，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;每次启动 PC ，均会有一个 TSVNCache.exe 的进程随 PC 自动启动，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;请教一下大家这个进程是如何启动的 ?&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;strong&gt;版权所有，&lt;strong&gt;欢&lt;/strong&gt;迎转载，但转载请注明： 转载自&amp;#160; &lt;/strong&gt;&lt;strong&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/"&gt;&lt;strong&gt;Zachary.XiaoZhen - 梦想的天空&lt;/strong&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;#160;&lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/BoyXiao/aggbug/2166596.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/archive/2011/09/04/2166596.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/BoyXiao/archive/2011/09/03/2164574.html</id><title type="text">进程隐藏与进程保护（SSDT Hook 实现）（一）</title><summary type="text">文章目录：          1. 引子 – Hook 技术： 2. SSDT 简介： 3. 应用层调用 Win32 API 的完整执行流程： 4. 详解 SSDT： 5. SSDT Hook 原理： 6. 小结：       1. 引子 – Hook 技术：    前面一篇博文呢介绍了代码的注入技术(远程线程实现)，博文地址如下： http:...</summary><published>2011-09-03T00:17:00Z</published><updated>2011-09-03T00:17:00Z</updated><author><name>Zachary.XiaoZhen</name><uri>http://www.cnblogs.com/BoyXiao/</uri></author><link rel="alternate" href="http://www.cnblogs.com/BoyXiao/archive/2011/09/03/2164574.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BoyXiao/archive/2011/09/03/2164574.html"/><content type="html">&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;文章目录：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;1. 引子 – Hook 技术：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;2. SSDT 简介：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;3. 应用层调用 Win32 API 的完整执行流程：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;4. 详解 SSDT：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;5. SSDT&amp;#160; Hook 原理：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff" size="2" face="微软雅黑"&gt;&lt;strong&gt;6. 小结：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;1. 引子 – Hook 技术：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;前面一篇博文呢介绍了代码的注入技术(远程线程实现)，博文地址如下：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/archive/2011/08/11/2134367.html"&gt;&lt;font size="2" face="Courier New"&gt;http://www.cnblogs.com/BoyXiao/archive/2011/08/11/2134367.html&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;虽然代码注入是很老的技术了，但是这种技术也还是比较常见，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;当然也比较好用的，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;比如在 Spy++ 中就使用了远程线程注入技术，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;同时，如果有兴趣的阅读过 Spy++ 的源码的朋友，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;当然也可以在其源码中阅读到关于远程线程注入技术了。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;（这篇博文虽然我会截断分为两篇博文撰写，但是博文仍然会比较长，内容其实是比较多的，覆盖面也比较广，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;需要有一定耐心和基础方可阅读完，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;有兴趣者请自备茶水以及零食，然后慢慢阅读全文，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;PS：这话引用自园子里某位园友）&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;（&lt;font size="2" face="Courier New"&gt;然后的话就是漫漫长夜，心情不佳，于是写了篇博文，刚好又喝了点，所以估计会有些许疏漏之处，还请见谅 ~&lt;/font&gt;）&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;在这一篇博文中呢，介绍的是一种 Hook 技术，对于 Hook 技术，可以分为两块，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;第一块是在 Ring3 层的 Hook，俗称应用层 Hook 技术，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而另外一块自然是在 Ring0 层得 Hook，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;俗称为内核层 Hook 技术，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而在 Ring3 层的 Hook 基本上可以分为两种大的类型，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;第一类即是 Windows 消息的 Hook，第二类则是 Windows API 的 Hook。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;关于 Hook 的几种类型呢，下面给出几个简洁的图示：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030815403696.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030815428321.png" width="606" height="275" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/20110903081543895.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030815446567.png" width="620" height="245" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030815459698.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/20110903081547768.png" width="806" height="423" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;关于 Windows 消息的 Hook，相信很多朋友都有接触过的，因为一个 SetWindowsHookEx 即可以完成消息 Hook，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;在这里简要介绍一下消息 Hook，消息 Hook 是通过 SetWindowsHookEx 可以实现将自己的钩子插入到钩子链的最前端，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而对于发送给被 Hook 的窗口(也有可能是所有的窗口，即全局 Hook)的消息都会被我们的钩子处理函数所捕获到，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;也就是我们可以优先于窗体先捕获到这些消息，Windows 消息 Hook 可以实现为进程内消息 Hook 和全局消息 Hook，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;对于进程内消息 Hook，则可以简单的将 Hook 处理函数直接写在这个进程内，即是自己 Hook 自己，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而对于用途更为广泛的全局消息 Hook，则需要将 Hook 处理函数写在一个 DLL 中，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;这样才可以让你的处理函数被所有的进程所加载(进程自动加载包含 Hook 消息处理函数的 DLL)。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;对于 Windows 消息 Hook 呢，可以有个简单的邪恶应用，就是记录键盘按键消息，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;从而达到监视用户输入的键值信息的目的，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;这样，对于一些简单的用户通过键盘输入的密码就可以被 Hook 获取到，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;因为没当用户按下一个键时，Windows 都会产生一个按键消息(当然有按下，弹起等消息的区分)，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;然后我们可以 Hook 到这个按键消息，这样就可以在 Hook 的消息处理函数中获取到用户按下的是什么键了。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;当然关于消息 Hook 的话，其不是这篇博文的重点，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;这篇博文主要介绍的是 SSDT Hook 技术，即内核 Hook 技术的一种，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;这种技术呢，也是比较老的技术了，貌似是当年 Rootkit 起火的时候出来的，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;但是 SSDT Hook 现在也还比较流行，比如在很多的杀毒软件或者安全软件里面也都会使用到 SSDT Hook 技术。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;关于内核 Hook 也有几种类型，下面也给出一副图示：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030815479995.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030815507718.png" width="705" height="574" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;上面的几种内核级 Hook 技术，在看雪啊，debugman，xfocus 上都有很多的介绍，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而我只不过是落后这些技术很多年的小辈后生，在这里也只是将自己的学习以及一些总结的经验给列出来而已，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;如果有兴趣想深入了解这些内容的话，完全可以在看雪上找到资料 ~ &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;2. SSDT 简介：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;以下介绍来自百度(PS:被百度文库弄去了很多博文，这里也抄它一下)：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;u&gt;SSDT 的全称是 System Services Descriptor Table，系统服务描述符表。&lt;/u&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;u&gt;这个表就是一个把 Ring3 的 Win32 API 和 Ring0 的内核 API 联系起来。&lt;/u&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;u&gt;SSDT 并不仅仅只包含一个庞大的地址索引表，它还包含着一些其它有用的信息，诸如地址索引的基地址、服务函数个数等。&lt;/u&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;u&gt;通过修改此表的函数地址可以对常用 Windows 函数及 API 进行 Hook，从而实现对一些关心的系统动作进行过滤、监控的目的。&lt;/u&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;u&gt;一些 HIPS、防毒软件、系统监控、注册表监控软件往往会采用此接口来实现自己的监控模块。&lt;/u&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;在 NT 4.0 以上的 Windows 操作系统中，默认就存在两个系统服务描述表，这两个调度表对应了两类不同的系统服务，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;这两个调度表为：KeServiceDescriptorTable 和 KeServiceDescriptorTableShadow，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;其中 KeServiceDescriptorTable 主要是处理来自 Ring3 层得 Kernel32.dll 中的系统调用，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而 KeServiceDescriptorTableShadow 则主要处理来自 User32.dll 和 GDI32.dll 中的系统调用，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;并且 KeServiceDescriptorTable 在 ntoskrnl.exe(Windows 操作系统内核文件，包括内核和执行体层)是导出的，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而 KeServiceDescriptorTableShadow 则是没有被 Windows 操作系统所导出，&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;而关于 SSDT 的全部内容则都是通过 KeServiceDescriptorTable 来完成的 ~ &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;从下面的截图可以看出 KeServiceDescriptorTable 在 ntoskrnl.exe 中被导出：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030815513215.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030815564823.png" width="841" height="475" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;然后我们再来看看在 Windows 操作系统的源码 WRK 中，KeServiceDescriptorTable 是怎么被定义的 ~&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;首先来看 KeServiceDescriptorTable 是如何被 Windows 操作系统源码给导出的：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;从下面的截图可以看出，这个系统服务描述表是在 WRK 源码中的某一个模块划分文件(.def)中所导出的。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;关于 WRK 是什么东西 ? 则可以参阅我的另一篇博文&lt;strong&gt;《Windows 内核(WRK)简介》&lt;/strong&gt;，博文地址如下：&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/archive/2011/01/08/1930904.html"&gt;&lt;font size="2" face="Courier New"&gt;http://www.cnblogs.com/BoyXiao/archive/2011/01/08/1930904.html&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030815577431.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816007761.png" width="762" height="301" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;而在 Windows 源码 WRK 中对于系统服务描述符表的代码定义如下&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;(KeServiceDecriptorTable 即由该结构定义)：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816011240.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816055781.png" width="815" height="372" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="2" face="Courier New"&gt;上面的这个结构定义在成员变量的名称上还看不出什么名堂，下面给出我们将在自己代码中所使用的结构体：&lt;/font&gt;&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;span class="lnum"&gt;   1:  &lt;/span&gt;typedef &lt;span class="kwrd"&gt;struct&lt;/span&gt; _KSYSTEM_SERVICE_TABLE  &lt;span class="lnum"&gt;   2:  &lt;/span&gt;{  &lt;span class="lnum"&gt;   3:  &lt;/span&gt;    PULONG  ServiceTableBase;          &lt;span class="rem"&gt;// SSDT (System Service Dispatch Table)的基地址&lt;/span&gt;  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;    PULONG  ServiceCounterTableBase;   &lt;span class="rem"&gt;// 用于 checked builds, 包含 SSDT 中每个服务被调用的次数&lt;/span&gt;  &lt;span class="lnum"&gt;   5:  &lt;/span&gt;    ULONG   NumberOfService;           &lt;span class="rem"&gt;// 服务函数的个数, NumberOfService * 4 就是整个地址表的大小&lt;/span&gt;  &lt;span class="lnum"&gt;   6:  &lt;/span&gt;    ULONG   ParamTableBase;            &lt;span class="rem"&gt;// SSPT(System Service Parameter Table)的基地址&lt;/span&gt;  &lt;span class="lnum"&gt;   7:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;   8:  &lt;/span&gt;} KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;  &lt;span class="lnum"&gt;   9:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  10:  &lt;/span&gt;typedef &lt;span class="kwrd"&gt;struct&lt;/span&gt; _KSERVICE_TABLE_DESCRIPTOR  &lt;span class="lnum"&gt;  11:  &lt;/span&gt;{  &lt;span class="lnum"&gt;  12:  &lt;/span&gt;    KSYSTEM_SERVICE_TABLE   ntoskrnl;  &lt;span class="rem"&gt;// ntoskrnl.exe 的服务函数&lt;/span&gt;  &lt;span class="lnum"&gt;  13:  &lt;/span&gt;    KSYSTEM_SERVICE_TABLE   win32k;    &lt;span class="rem"&gt;// win32k.sys 的服务函数(GDI32.dll/User32.dll 的内核支持)&lt;/span&gt;  &lt;span class="lnum"&gt;  14:  &lt;/span&gt;    KSYSTEM_SERVICE_TABLE   notUsed1;  &lt;span class="lnum"&gt;  15:  &lt;/span&gt;    KSYSTEM_SERVICE_TABLE   notUsed2;  &lt;span class="lnum"&gt;  16:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  17:  &lt;/span&gt;} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;  &lt;span class="lnum"&gt;  18:  &lt;/span&gt;&amp;#160;  &lt;span class="lnum"&gt;  19:  &lt;/span&gt;&lt;span class="rem"&gt;//导出由 ntoskrnl.exe 所导出的 SSDT&lt;/span&gt;  &lt;span class="lnum"&gt;  20:  &lt;/span&gt;&lt;span class="kwrd"&gt;extern&lt;/span&gt; PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;有了上面的介绍后，我们可以简单的将 KeServiceDescriptor 看做是一个数组了(其实质也就是个数组)，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;在应用层 ntdll.dll 中的 API 在这个系统服务描述表(SSDT)中都存在一个与之相对应的服务，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;当我们的应用程序调用 ntdll.dll 中的 API 时，最终会调用内核中与之相对应的系统服务，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;由于有了 SSDT，所以我们只需要告诉内核需要调用的服务所在 SSDT 中的索引就 OK 了，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;然后内核根据这个索引值就可以在 SSDT 中找到相对应的服务了，然后再由内核调用服务完成应用程序 API 的调用请求即可。&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;基本结构可以参考下图：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816069751.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816078454.png" width="709" height="168" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;3. 应用层调用 Win32 API 的完整执行流程：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;有了上面的 SSDT 基础后，我们再来看一下在应用层调用 Win32 API(这里主要指的是 ntdll.dll 中的 API)的完整流程，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;这里我们主要是分析 ntdll.dll 中的 NtQuerySystemInformation 这个 API 的调用流程，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;(PS:Windows 任务管理器即是通过这个 API 来获取到系统的进程等等信息的)。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;先给出一副图示(先记住这里有四个类似的 API，但是必须得注意区分开来，弄混淆了就麻烦大了)：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816089110.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816113867.png" width="835" height="416" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;再给出这些个 API 的基本的调用流程(让大伙有个印象，至少不会迷失)：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816128983.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816151232.png" width="703" height="415" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font size="2" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;首先，使用 PE 工具来打开 ntdll.dll 文件，可以看到 NtQuerySystemInformation，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816152411.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816189120.png" width="845" height="295" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;除了 NtQuerySystemInformation 外，同时还可以看到 ZwQuerySystemInformation，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816194235.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816233203.png" width="837" height="326" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;而实质上，在 Windows 操作系统中，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;Ntdll.dll 中的ZwQuerySystemInformation 和 NtQuerySystemInformation 是同一函数，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;可以通过下面的截图看出，这两个函数的入口地址指向同一区域，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;他们的函数入口地址都是一样的 ~ &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;很奇怪吧 ~ 其实我也觉得奇怪 ~ 何必多此一举呢 ~ &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816248286.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816256814.png" width="876" height="182" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;众所周知 Ntdll.dll 中的 API 都只不过是一个简单的包装函数而已，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;当 Kernel32.dll 中的 API 通过 Ntdll.dll 时，会完成参数的检查，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;再调用一个中断(int 2Eh 或者 SysEnter 指令)，&lt;/strong&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;从而实现从&lt;/font&gt;&lt;font size="2" face="Courier New"&gt; Ring3 进入 Ring0 层，&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;并且将所要调用的服务号(也就是在 SSDT 数组中的索引值)存放到寄存器 EAX 中，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;并且将参数地址放到指定的寄存器(EDX)中，再将参数复制到内核地址空间中，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;再根据存放在 EAX 中的索引值来在 SSDT 数组中调用指定的服务 ~ &lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#000000" size="4" face="Courier New"&gt;&lt;strong&gt;经过上面的步骤后，便由 Ring3 层进入了 Ring0 层，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;我们再通过 PE 工具来查看 ntoskrnl.exe 中的 ZwQuerySystemInformation 和 NtQuerySystemInformation&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816271407.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816303373.png" width="788" height="321" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816317409.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816344151.png" width="758" height="315" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;先来看 ntoskrnl.exe 中的 ZwQuerySystemInformation：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816358361.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816378036.png" width="747" height="301" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;在上面的这幅截图中，可以看到在 Ring0 下的 ZwQuerySystemInformation 将 0ADh 放入了寄存器 eax 中，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;然后调用了系统服务分发函数 KiSystemService，而这个 KiSystemService 函数则是根据 eax 寄存器中的索引值，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;然后再 SSDT 数组中找到索引值为 eax 寄存器中存放的值得那个 SSDT 项，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;最后就是根据这个 SSDT 项中所存放的系统服务的地址来调用这个系统服务了 ~ &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;比如在这里就是调用 KeServiceDescriptorTable[0ADh] 处所保存的地址所对应的系统服务了 ~ &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;也就是调用 Ring0 下的 NtQuerySystemInformation 了 ~ &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;至此，在应用层中调用 NtQuerySystemInformation 的全部流程也就结束了 ~ &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;最后，贴出一点在 Ring0 下的 NtQuerySystemInformation 的反汇编代码：&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816378102.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816394397.png" width="808" height="262" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;4. 详解 SSDT：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;在这一节里面，我们将来看看 SSDT 到底是个什么东西 ~ &lt;/font&gt;&lt;font size="2" face="Courier New"&gt;这里使用 WinDbg 来调试 XP SP2 系统 ~&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;首先来看看 KeServiceDescriptorTable 是何物 ?&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;从下面的截图中可以看到 KeServiceDesciptorTable 的首地址为 804e58a0，&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;然后查看分析这个地址，可以查看到第一个系统服务的入口地址为 80591bfb ！&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816405368.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="2011-08-18_012703" border="0" alt="2011-08-18_012703" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816424137.gif" width="489" height="483" /&gt;&lt;/a&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;我们再来看看 80591bfb 这个地址对应的究竟是何系统服务 ?&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;从下面的截图中，可以看到 SSDT 中第一个系统服务就是 NtAcceptConnectPort !!!&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="2" face="Courier New"&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816435665.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="2011-08-18_013027" border="0" alt="2011-08-18_013027" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816451403.gif" width="734" height="518" /&gt;&lt;/a&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;由于我们知道了 SSDT 的首地址，又知道了 Ring0 下 NtQuerySystemInformation 服务的索引号，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;所以可以根据 &lt;font color="#0000ff"&gt;“SSDT 中系统服务地址所在的 Address = SSDT 首地址 + 4 * 索引号”,&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;推算出 NtQuerySystemInformation 服务的地址，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;因此有 Address = 804e58a0 + 4 * 0adh = 804E5B54；&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;然后我们再来看 804E5B54 这个地址的信息，信息如下截图：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;从截图中，我们可以看到 NtQuerySystemInformation 的起始地址为 80586ff1，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816468961.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="2011-08-18_020103" border="0" alt="2011-08-18_020103" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816477980.gif" width="579" height="251" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;&amp;#160; &lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;下面就来验证一下地址 80586ff1 到底是不是 NtQuerySystemInformation 的首地址 ~ &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;从下面的截图中可以肯定 80586ff1 确实就是 NtQuerySystemInformation 的首地址，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;这和我们上面对 SSDT 中指定索引号的服务的地址的计算公式计算出来的结果是统一的 !!!&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816471634.gif"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="2011-08-18_020231" border="0" alt="2011-08-18_020231" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816489781.gif" width="771" height="247" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;从上面的介绍，可以看出，其实 SSDT 就是一个用来保存 Windows 系统服务地址的数组而已 !!!&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;5. SSDT&amp;#160; Hook 原理：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;有了上面的这部分基础后，就可以来看 SSDT HOOK 的原理了，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;其实 SSDT Hook 的原理是很简单的，从上面的分析中，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;我们可以知道在 SSDT 这个数组中呢，保存了系统服务的地址，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;比如对于 Ring0 下的 NtQuerySystemInformation 这个系统服务的地址，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;就保存在 KeServiceDescriptorTable[0ADh] 中，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;既然是 Hook 的话，我们就可以将这个 KeServiceDescriptorTable[0ADh] 下保存的服务地址替换掉，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;将我们自己的 Hook 处理函数的地址来替换掉原来的地址，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;这样当每次调用 KeServiceDescriptorTable[0ADh]时就会调用我们自己的这个 Hook 处理函数了。&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;strong&gt;下面用几幅截图来表示：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816494340.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816522653.png" width="828" height="378" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;下面的截图则是 SSDT Hook 之后了，可以看到将 SSDT 中的服务地址修改为 MyHookNtQuerySystemInformation 了，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;这样的话，每次系统调用 NtQuerySystemInformation 这个系统服务时，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;实质上调用的就是 MyHookNtQuerySystemInformation 了，而我们为了保证系统的稳定性(至少不让其崩溃)，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;一般会在 MyHookNtQuerySystemInformation 中调用系统中原来的服务，也就是 NtQuerySystemInformation。&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816538640.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/BoyXiao/201109/201109030816565623.png" width="865" height="532" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000" size="5" face="微软雅黑"&gt;&lt;strong&gt;6. 小结：&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;本篇博文呢尚还只是介绍了 SSDT 到底是个什么东西，而还没有给出具体的 SSDT Hook 的实现，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;对于 SSDT Hook 的实现以及 Demo 我都放到(二)中完成，也就是本篇博文未完 , 待续 ……&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;关于 SSDT 的话，在看雪上有很多的文章，由于我也是前阵子对这东西突然感兴趣了，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;所以我也算是初次了解，自然也看过了很多的文章，SSDT 在 Google 一搜索可以出来一大堆，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;但是要说介绍 SSDT 最详细的话，我想还是我的这篇文章介绍的比较详细，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;因为网上很多介绍 SSDT 的都只是将 SSDT 原理做了简单的介绍，然后在网上 down 一个 Demo，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;把代码贴出来就完事了，&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;甚至是代码都还无法完整编译通过的，&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;所以如果读者想对 SSDT 有所了解的话，可以好好看一看这篇文章的 ~ &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;顺便这里还带出一个问题，是我这阵子脑子里突然冒出来的一个疑问，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;但是由于时间或者说是个人状态问题，一直没有去研究 ~ 不晓得园子里有木有对这个有研究的 ~ &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;众所周知，在 Windows 操作系统中，System 进程的进程 PID 为 4，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;我想问的就是：System 进程的 PID 为何是 4 ? &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;欢迎大家对这个问题讨论啊 ~ &lt;/font&gt;&lt;/strong&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;在这里先给点思路，&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff" size="2" face="Courier New"&gt;&lt;strong&gt;那就是可以通过 Windows 操作系统的启动过程，然后结合 WRK 源码进行研究 ~ &lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&lt;font face="微软雅黑"&gt;&lt;strong&gt;版权所有，&lt;strong&gt;欢&lt;/strong&gt;迎转载，但转载请注明： 转载自&amp;#160; &lt;/strong&gt;&lt;strong&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/"&gt;&lt;strong&gt;Zachary.XiaoZhen - 梦想的天空&lt;/strong&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font face="微软雅黑"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font face="微软雅黑"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/BoyXiao/aggbug/2164574.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/BoyXiao/archive/2011/09/03/2164574.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
