﻿<?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>IT博客-NetRoc's Blog-文章分类-内核技术</title><link>http://www.cnitblog.com/cc682/category/7183.html</link><description>N-Tech</description><language>zh-cn</language><lastBuildDate>Wed, 28 Sep 2011 07:29:57 GMT</lastBuildDate><pubDate>Wed, 28 Sep 2011 07:29:57 GMT</pubDate><ttl>60</ttl><item><title>运行期修改可执行文件的路径和Command Line</title><link>http://www.cnitblog.com/cc682/articles/43271.html</link><dc:creator>NetRoc</dc:creator><author>NetRoc</author><pubDate>Sun, 04 May 2008 07:17:00 GMT</pubDate><guid>http://www.cnitblog.com/cc682/articles/43271.html</guid><wfw:comment>http://www.cnitblog.com/cc682/comments/43271.html</wfw:comment><comments>http://www.cnitblog.com/cc682/articles/43271.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/cc682/comments/commentRss/43271.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/cc682/services/trackbacks/43271.html</trackback:ping><description><![CDATA[&nbsp;
<p align=center><span>cc682/NetRoc</span></p>
<p><span>目前的很多主动防御工具和反</span><span>XX</span><span>系统，在对特定进程进行保护的时候，出于兼容性的考虑，都会保留一些白名单。特别是一些系统进程，例如</span><span>csrss.exe</span><span>、</span><span>svchost.exe</span><span>等等。而针对这些系统进程，判断是否在白名单中的方式，为了简便起见经常采用取系统路径、可执行文件名的方式。</span></p>
<p><span>内核中比较明显的能够取到可执行文件路径的方法有下面几个：</span></p>
<p><span><span>1、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>通过</span><span>PEB. ProcessParameters -&gt; ImagePathName</span><span>取得可执行文件路径，通过</span><span>PEB. ProcessParameters -&gt; CommandLine</span><span>取得执行的命令行，以及</span><span>PEB. ProcessParameters</span><span>里面其他几个成员取得其他一些相关的路径信息。</span></p>
<p><span><span>2、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>通过</span><span>nt!_EPROCESS</span><span>的</span><span>ImageFileName</span><span>取得。</span></p>
<p><span><span>3、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>通过</span><span>nt!_EPROCESS:: SeAuditProcessCreationInfo:: ImageFileName</span><span>取得。</span></p>
<p><span><span>4、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>通过和</span><span>_EPROCESS</span><span>相关的文件对象信息取得。</span></p>
<p><span>常见的方式一般只有</span><span>1</span><span>、</span><span>2</span><span>两种。而上述的前三种方式都可以在运行时被修改掉，用来进行欺骗。特别是</span><span>PEB</span><span>里面的信息由于在</span><span>ring3</span><span>直接就可以访问，实现上来说非常简单。</span></p>
<p><span>下面这段代码通过</span><span>NtQueryInformationProcess</span><span>拿到</span><span>PEB</span><span>，然后修改路径信息：</span></p>
<p><span>HMODULE hMod = GetModuleHandle( _T( "ntdll.dll"));</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pfnNtQueryInformationProcess p = (pfnNtQueryInformationProcess)::GetProcAddress( hMod, "NtQueryInformationProcess");</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>PROCESS_BASIC_INFORMATION stInfo = {0};</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>DWORD dwRetnLen = 0;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>DWORD dw = p( GetCurrentProcess(), ProcessBasicInformation, &amp;stInfo, sizeof(stInfo), &amp;dwRetnLen);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>PPEB pPeb = stInfo.PebBaseAddress;</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>WCHAR wszFullPath[MAX_PATH] = {0};</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>WCHAR wszTmp2[MAX_PATH] = {0};</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>wcscpy( wszFullPath, wszPath);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>MultiByteToWideChar( CP_THREAD_ACP, 0, szName, -1, wszTmp2, MAX_PATH);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>wcscat( wszFullPath, wszTmp2);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>wcscpy( pPeb-&gt;ProcessParameters-&gt;ImagePathName.Buffer, wszFullPath);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pPeb-&gt;ProcessParameters-&gt;ImagePathName.Length = wcslen( wszFullPath) * sizeof(WCHAR);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>int nParamStart = 0;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>WCHAR *wszTmp = new WCHAR[pPeb-&gt;ProcessParameters-&gt;CommandLine.MaximumLength];</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ZeroMemory( wszTmp, sizeof(WCHAR) * pPeb-&gt;ProcessParameters-&gt;CommandLine.MaximumLength);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>wcscpy( wszTmp, pPeb-&gt;ProcessParameters-&gt;CommandLine.Buffer);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if ( pPeb-&gt;ProcessParameters-&gt;CommandLine.Buffer[0] == '"')</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>for ( int i = 1; i &lt; pPeb-&gt;ProcessParameters-&gt;CommandLine.Length / 2; i++)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&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; </span>if ( pPeb-&gt;ProcessParameters-&gt;CommandLine.Buffer[i] == '"')</span></p>
<p><span><span>&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; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>nParamStart = i;</span></p>
<p><span><span>&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; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if ( nParamStart != 0)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if ( pPeb-&gt;ProcessParameters-&gt;CommandLine.Buffer[0] == '"')</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&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; </span>pPeb-&gt;ProcessParameters-&gt;CommandLine.Buffer[0] = NULL;</span></p>
<p><span><span>&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; </span>wcscat( pPeb-&gt;ProcessParameters-&gt;CommandLine.Buffer, L"\"");</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>else</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&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; </span>pPeb-&gt;ProcessParameters-&gt;CommandLine.Buffer[0] = NULL;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>wcscat( pPeb-&gt;ProcessParameters-&gt;CommandLine.Buffer, wszFullPath);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>wcscat( pPeb-&gt;ProcessParameters-&gt;CommandLine.Buffer, wszTmp + nParamStart);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>delete[] wszTmp;</span></p>
<p><span>这个方式可以欺骗通过</span><span>toolhelp</span><span>函数枚举出来的模块路径，以及直接读取</span><span>PEB</span><span>获取进程主模块路径的方式。</span></p>
<p><span>另外，通过修改</span><span>EPROCESS</span><span>中的主模块名信息，可以欺骗一些在驱动层的程序。基本的代码如下：</span></p>
<p><span>首先需要获取</span><span>EPROCESS</span><span>里面</span><span>ImageFileName</span><span>的偏移。这个函数必须在</span><span>DriverEntry</span><span>里面调用。</span></p>
<p><span>ULONG GetNameOffsetInEProcss()</span></p>
<p><span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>PEPROCESS pProcess = NULL;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ULONG i = 0;</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pProcess = PsGetCurrentProcess();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>for ( i = 0; i &lt; 0x1000; i++)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if ( strncmp( "System", (PUCHAR)pProcess + i, strlen("System")) == 0)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&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; </span>return i;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return 0;</span></p>
<p><span>}</span></p>
<p><span>然后可以在</span><span>IoCtrl</span><span>里面修改当前进程的名字：</span></p>
<p><span>case IOCTL_CHANGE_EXENAME:</span></p>
<p><span><span>&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; </span>szName = (char*)Irp-&gt;AssociatedIrp.SystemBuffer;</span></p>
<p><span><span>&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; </span>if ( !szName)</span></p>
<p><span><span>&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; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ntStatus = STATUS_UNSUCCESSFUL;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>break;</span></p>
<p><span><span>&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; </span>}</span></p>
<p><span><span>&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; </span>pEProcess = PsGetCurrentProcess();</span></p>
<p><span><span>&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; </span>strncpy( (PCHAR)pEProcess + g_NameOffsetInEProcess, szName, 16);</span></p>
<p><span><span>&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; </span>ntStatus = STATUS_SUCCESS;</span></p>
<p><span><span>&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; </span>break;</span></p>
<p><span>由于只是示例，所以只实现了良种方式。修改</span><span>SeAuditProcessCreationInfo</span><span>里面的信息，考虑到兼容性问题，可能稍微复杂一点。不过也可以比较容易的实现。</span></p>
<p><span>这种方式的伪装可以穿过多少主动防御工具没有试过，大家可以去看看，哈哈。</span></p>
<p><span>至于对付的方式，可以通过上面说的第四种取进程路径的方法。不过就比较复杂了，呵呵。</span></p>
<p><span>流程就是，通过</span><span>EPROCESS</span><span>的</span><span>SectionObject</span><span>获得文件的</span><span>FilePointer</span><span>，通过</span><span>ObQueryNameString</span><span>取得这个对象的名字。然后就可以取得主映像模块的路径了。详细的代码可以参考</span><span>wrk</span><span>中</span><span>NtQueryInformationProcess</span><span>的相关实现。</span></p>
<p><span>下面是实现代码</span><span>: <br><a title=ImgPathChanger.rar href="http://www.cnitblog.com/Files/cc682/ImgPathChanger.rar">ImgPathChanger.rar</a></span></p>
<img src ="http://www.cnitblog.com/cc682/aggbug/43271.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/cc682/" target="_blank">NetRoc</a> 2008-05-04 15:17 <a href="http://www.cnitblog.com/cc682/articles/43271.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>瑞星2008主动防御体系分析</title><link>http://www.cnitblog.com/cc682/articles/43269.html</link><dc:creator>NetRoc</dc:creator><author>NetRoc</author><pubDate>Sun, 04 May 2008 07:13:00 GMT</pubDate><guid>http://www.cnitblog.com/cc682/articles/43269.html</guid><wfw:comment>http://www.cnitblog.com/cc682/comments/43269.html</wfw:comment><comments>http://www.cnitblog.com/cc682/articles/43269.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/cc682/comments/commentRss/43269.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/cc682/services/trackbacks/43269.html</trackback:ping><description><![CDATA[<p>&nbsp; </p>
<p><span>cc682/NetRoc</span></p>
<p><span><a href="http://netroc682.spaces.live.com/"><span>http://netroc682.spaces.live.com/</span></a></span></p>
<p><span><span>一、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>基本原理和基本技术</span></p>
<p><span><span>1、<span> </span></span></span><span>Rising 2008</span><span>本身对产品的描述：</span></p>
<p><span>瑞星杀毒软件</span><span>2008</span><span>中采用的主动防御技术包含三个层次，资源访问规则控制；资源访问扫描；程序活动行为分析引擎，其中尤其以行为分析引擎技术最为关键。</span></p>
<p>&nbsp;</p>
<p><span>第一层：资源访问控制层（即</span><span>HIPS</span><span>）</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span></span><span>它通过对系统资源（注册表、文件、特定系统</span><span>API</span><span>的调用、进程启动）等进行规则化控制，阻止病毒、木马等恶意程序对这些资源的使用，从而达到抵御未知病毒、木马攻击的目的。</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span></span><span>第二层：资源访问扫描层（即传统的文件监控、邮件监控等）</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span></span><span>通过监控对一些资源，如文件、引导区、邮件、脚本的访问</span><span>,</span><span>并使用拦截的上下文内容（文件内存、引导区内容等）进行威胁扫描识别的方式，来处理已经经过分析的恶意代码。</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span></span><span>第三层：进程活动行为判定层（危险行为判定、</span><span>DNA</span><span>识别）</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span></span><span>进程活动行为判定层自动收集从前两层传上来的进程动作及特征信息，并对其进行加工判断。瑞星专家经过对数十万病毒的危险行为进行分析，提炼，设计出全新的主动防御智能恶意行为判定引擎。无需用户参与，该层可以自动识别出具有有害动作的未知病毒、木马、后门等恶意程序。</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span></span><span>目前，市面上的一些主动防御软件只做了三层结构中的部分功能，瑞星认为，只有全面实现三个层级的主动防御，才是真正意义上的&#8220;主动防御功能&#8221;，如果用户使用不完全的主动防御，将给自己带来严重的安全风险。</span></p>
<p>&nbsp;</p>
<p><span>帐号保险柜，严密保护您的帐号密码</span></p>
<p><span>木马强杀技术，彻底查杀</span><span>70</span><span>万木马</span></p>
<p><img height=328 alt="" src="http://www.cnitblog.com/images/cnitblog_com/cc682/rsing1.jpg" width=552 border=0></p>
<p><span><span>2、<span> </span></span></span><span>分析得到的</span><span>rising 2008</span><span>主动防御的体系结构</span></p>
<p><span>Rising2008</span><span>的主动防御体系基本涵盖了它自己描述的几大方面。</span></p>
<p><span><span>l&nbsp;</span></span><span>文件访问控制方面，对关键的系统目录、</span><span>Rising</span><span>程序安装目录进行保护，在其他程序进行访问系统目录的时候，弹出用户提示；拒绝对</span><span>Rising</span><span>安装目录的修改、删除等操作。</span></p>
<p><img height=454 alt="" src="http://www.cnitblog.com/images/cnitblog_com/cc682/rsing2.jpg" width=403 border=0></p>
<p><span><span>l&nbsp;</span></span><span>进程启动控制方面，通过对注册表相关项的监控实现。很弱智的是，对</span><span>Start Menu\Programs\Startup</span><span>的访问没有进行监控。</span></p>
<p><img height=458 alt="" src="http://www.cnitblog.com/images/cnitblog_com/cc682/rsing3.jpg" width=405 border=0></p>
<p><span><span>l&nbsp;</span></span><span>系统动作规则方面，对跨进程访问的一些</span><span>API</span><span>调用进行了</span><span>Hook</span><span>和控制。包括</span><span>ntos</span><span>和少量</span><span>win32k</span><span>的操作。在应用程序调用这些</span><span>API</span><span>函数时，</span><span>rising</span><span>只是给以任务栏的气泡提示，并没有发现可供用户选择策略的方法。这可能也是为了方便大多数普通用户采取的模式。</span></p>
<p>&#160;</p>
<p><img height=120 alt="" src="http://www.cnitblog.com/images/cnitblog_com/cc682/rsing4.jpg" width=260 border=0><br><img height=117 alt="" src="http://www.cnitblog.com/images/cnitblog_com/cc682/rsing5.jpg" width=194 border=0></p>
<p><span><span>l&nbsp;</span></span><span>邮件和网页监控由于不在本次分析重点范围内，所以也跳过这部分。不过在驱动内部没有发现和这两个功能相关代码，基本可排除在</span><span>ring0</span><span>实现的可能性。</span></p>
<p><span><span>l&nbsp;</span></span><span>Rising</span><span>用于主动防御的文件和基本结构如图：</span></p>
<p><img height=350 alt="" src="http://www.cnitblog.com/images/cnitblog_com/cc682/rsing6.jpg" width=473 border=0></p>
<p><span>HookNtos</span><span>、</span><span>HookReg</span><span>、</span><span>HookSys</span><span>分别有一个驱动和一个</span><span>ring3</span><span>层接口</span><span>dll</span><span>构成。</span><span>HookNtos</span><span>主要处理对</span><span> SSDT</span><span>中进程保护相关的函数、</span><span>Win32K</span><span>的</span><span>hook</span><span>和相关逻辑</span></p>
<p><span>HookReg</span><span>主要处理</span><span>SSDT</span><span>中注册表相关函数的</span><span>Hook</span><span>和逻辑。</span></p>
<p><span>HookSys</span><span>中包含对文件系统驱动的</span><span>Hook</span><span>，以及文件扫描、处理等的代码。</span></p>
<p><span>上述三个模块，都依赖于一个支持模块</span><span>HookHelp.sys</span><span>。</span><span>HookHelp</span><span>提供对内核</span><span>Hook</span><span>的支持。包括管理</span><span>Hook</span><span>所使用的跳板代码的内存等功能。另外，提供对</span><span>nt!_EPROCESS</span><span>等内核结构的访问支持，供其它模块获取进程信息使用。</span></p>
<p><span><span>3、<span> </span></span></span><span>基本技术</span></p>
<p><span>Rising</span><span>主动防御的核心技术只有</span><span>2</span><span>个</span></p>
<p><span><span>l&nbsp;</span></span><span>SSDT</span><span>以及</span><span>SSDT Shadow</span><span>的</span><span>Hook</span></p>
<p><span><span>l&nbsp;</span></span><span>DriverObject</span><span>的</span><span>IRP</span><span>处理例程</span><span>Hook</span></p>
<p><span><span>二、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>详细实现</span></p>
<p><span><span>1、<span> </span></span></span><span>HookHelp.sys</span><span>部分</span></p>
<p><span>下图是</span><span>HookHelp.sys</span><span>的导出函数</span></p>
<p><img height=346 alt="" src="http://www.cnitblog.com/images/cnitblog_com/cc682/rsing7.jpg" width=374 border=0></p>
<p><span>Hook</span><span>方面</span><span>Hook</span><span>的</span><span>SSDT</span><span>会跳转到</span><span>HookHelp</span><span>中的跳板代码：</span></p>
<p><span>f775a571 687caa46f7<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>push<span>&nbsp;&nbsp;&nbsp; </span>offset HookNtos+0x1a7c (f746aa7c)</span></p>
<p><span>f775a576 c3<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ret</span></p>
<p><span>通过跳板，实际转到</span><span>Hook</span><span>函数中。</span></p>
<p><span>ProcessInfo</span><span>方面，都是从</span><span>nt!_EPROCESS</span><span>中获取。</span></p>
<p><span><span>2、<span> </span></span></span><span>HookReg</span><span>部分</span></p>
<p><span>通过</span><span>Hook SSDT</span><span>中以下函数实现：</span></p>
<p><span>NtCreateKey</span></p>
<p><span>NtDeleteKey</span></p>
<p><span>NtDeleteValueKey</span></p>
<p><span>NtRenameKey</span></p>
<p><span>NtRestoreKey</span></p>
<p><span>NtSetSecurityObject</span></p>
<p><span>NtSetValueKey</span></p>
<p><span>对注册表操作进行监控，向一些关键的注册表主键下面写入或者修改数据，会提示用户并询问操作。主要有以下几处：</span></p>
<p><img height=269 alt="" src="http://www.cnitblog.com/images/cnitblog_com/cc682/rising10.jpg" width=541 border=0></p>
<p><span><span>3、<span> </span></span></span><span>HookNtos</span><span>部分</span></p>
<p><span>Hook</span><span>掉的函数包括</span><span>SSDT</span><span>和</span><span>SSDT Shadow</span><span>中的一共有以下几个：</span></p>
<p><img height=389 alt="" src="http://www.cnitblog.com/images/cnitblog_com/cc682/rsing8.jpg" width=325 border=0></p>
<p><span>这些函数都是对应于瑞星进程保护的各个选项：</span></p>
<p><img height=314 alt="" src="http://www.cnitblog.com/images/cnitblog_com/cc682/rsing9.jpg" width=419 border=0></p>
<p><span>另外，对</span><span>Rising</span><span>的几个进程，默认都是会进行保护的。</span></p>
<p><span>监控了驱动加载和卸载的几个函数，以实现对内核模块加载卸载的控制。</span></p>
<p><span><span>4、<span> </span></span></span><span>HookSys</span><span>部分</span></p>
<p><span>主要是处理文件操作的</span><span>Hook</span><span>。</span></p>
<p><span>通过</span><span>ObReferenceObjectByName</span><span>获取以下几个设备对象：</span></p>
<p><span>\FileSystem\Ntfs</span></p>
<p><span>\FileSystem\Fastfat</span></p>
<p><span>\FileSystem\fastfat</span></p>
<p><span>\FileSystem\MRxSmb</span></p>
<p><span>\FileSystem\mrxsmb</span></p>
<p><span>\FileSystem\Cdfs</span></p>
<p><span>\FileSystem\Rdr</span></p>
<p><span>并钩挂</span><span>DriverObject</span><span>里面的</span></p>
<p><span>IRP_MJ_CLEANUP</span></p>
<p><span>IRP_MJ_CLOSE</span></p>
<p><span>IRP_MJ_SET_INFORMATION</span></p>
<p><span>IRP_MJ_WRITE</span></p>
<p><span>IRP_MJ_SET_SECURITY</span></p>
<p><span>DRIVER_OBJECT::FastIoDispatch::FastIoWrite</span></p>
<p><span>实现对文件监控。</span></p>
<p><span><span>三、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>整体评价</span></p>
<p><span>Rising</span><span>的主动防御系统是</span><span>08</span><span>年</span><span>Rising</span><span>主推的产品特性。总体来看，还是实现得中规中矩。没有什么新东西，但是还是具备基本的一些主动防御产品的特性。例如对系统文件夹访问的控制、对启动项的监控、对驱动加载的监控等等。</span></p>
<p><span>不过，和现在市面上绝大多数主动防御系统一样。由于突破关键保护的方法多种多样，并且很多是由系统本身所提供的，主动防御难以面面俱到，将每种方法都进行监控，</span><span>Rising</span><span>不可避免的存在一点突破，满盘皆输的毛病。对于普通用户的价值有限。</span></p>
<img src ="http://www.cnitblog.com/cc682/aggbug/43269.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/cc682/" target="_blank">NetRoc</a> 2008-05-04 15:13 <a href="http://www.cnitblog.com/cc682/articles/43269.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>进程中dll模块的隐藏</title><link>http://www.cnitblog.com/cc682/articles/43263.html</link><dc:creator>NetRoc</dc:creator><author>NetRoc</author><pubDate>Sun, 04 May 2008 06:59:00 GMT</pubDate><guid>http://www.cnitblog.com/cc682/articles/43263.html</guid><wfw:comment>http://www.cnitblog.com/cc682/comments/43263.html</wfw:comment><comments>http://www.cnitblog.com/cc682/articles/43263.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/cc682/comments/commentRss/43263.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/cc682/services/trackbacks/43263.html</trackback:ping><description><![CDATA[&nbsp;
<p align=center><span>cc682/NetRoc</span></p>
<p align=center><span>&nbsp;<a href="http://netroc682.spaces.live.com/">http://netroc682.spaces.live.com/</a></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>为了避免自己的某个</span><span>dll</span><span>模块被别人检测出来，有时候希望在自己加载一个</span><span>dll</span><span>之后，或者将</span><span>dll</span><span>注入到他人进程之后避免被检查出来。这就需要想办法抹掉这个</span><span>dll</span><span>的模块信息，使得</span><span>Toolhelp</span><span>、</span><span>psapi</span><span>等枚举模块的</span><span>API</span><span>无法枚举它。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>我们可以先简单看看</span><span>Windows</span><span>枚举进程内模块的办法吧：</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>首先是</span><span>BOOL EnumProcessModules( HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>EnumProcessModules</span><span>实际调用</span><span>EnumProcessModulesInternal</span><span>进行枚举。下面是</span><span>vista</span><span>下</span><span>psapi</span><span>的代码片断：</span></p>
<p><span>.text:514024B8<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>push<span>&nbsp;&nbsp;&nbsp; </span>ebx</span></p>
<p><span>.text:514024B9<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>push<span>&nbsp;&nbsp;&nbsp; </span>18h</span></p>
<p><span>.text:514024BB<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>lea<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>eax, [ebp+stProcessBasicInfo]</span></p>
<p><span>.text:514024BE<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>push<span>&nbsp;&nbsp;&nbsp; </span>eax</span></p>
<p><span>.text:514024BF<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>push<span>&nbsp;&nbsp;&nbsp; </span>ebx<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>;ebx=0</span></p>
<p><span>.text:514024C0<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>push<span>&nbsp;&nbsp;&nbsp; </span>[ebp+hProcess]</span></p>
<p><span>.text:514024C3<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>call<span>&nbsp;&nbsp;&nbsp; </span>ds:__imp__NtQueryInformationProcess@20 ; NtQueryInformationProcess(x,x,x,x,x)</span></p>
<p><span>.text:514024C9<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>cmp<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>eax, ebx</span></p>
<p><span>.text:514024CB<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>jge<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>short loc_514024E0</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>调用</span><span>NtQueryInformationProcess</span><span>获得</span><span>ProcessBasicInformation</span><span>，在</span><span>PROCESS_BASIC_INFORMATION</span><span>结构中取得</span><span>PEB</span><span>地址。然后读取指定进程</span><span>PEB</span><span>中的数据</span></p>
<p><span>text:514024E0 loc_514024E0:<span>&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; </span>; CODE XREF: EnumProcessModulesInternal(x,x,x,x,x)+24j</span></p>
<p><span>.text:514024E0<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>mov<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>eax, [ebp+stProcessBasicInfo.PebBaseAddress]</span></p>
<p><span>.text:514024E3<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>cmp<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>eax, ebx</span></p>
<p><span>.text:514024E5<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>jnz<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>short loc_514024EE</span></p>
<p><span>.text:514024E7<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>push<span>&nbsp;&nbsp;&nbsp; </span>8000000Dh</span></p>
<p><span>.text:514024EC<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>jmp<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>short loc_514024CE</span></p>
<p><span>.text:514024EE ; ---------------------------------------------------------------------------</span></p>
<p><span>.text:514024EE</span></p>
<p><span>.text:514024EE loc_514024EE:<span>&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; </span>; CODE XREF: EnumProcessModulesInternal(x,x,x,x,x)+3Ej</span></p>
<p><span>.text:514024EE<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>push<span>&nbsp;&nbsp;&nbsp; </span>ebx<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>; lpNumberOfBytesRead</span></p>
<p><span>.text:514024EF<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>push<span>&nbsp;&nbsp;&nbsp; </span>4<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>; nSize</span></p>
<p><span>.text:514024F1<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>lea<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>ecx, [ebp+Ldr]</span></p>
<p><span>.text:514024F4<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>push<span>&nbsp;&nbsp;&nbsp; </span>ecx<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>; lpBuffer</span></p>
<p><span>.text:514024F5<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>add<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>eax, 0Ch</span></p>
<p><span>.text:514024F8<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>push<span>&nbsp;&nbsp;&nbsp; </span>eax<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>; lpBaseAddress</span></p>
<p><span>.text:514024F9<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>push<span>&nbsp;&nbsp;&nbsp; </span>[ebp+hProcess]&nbsp;; hProcess</span></p>
<p><span>.text:514024FC<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>mov<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>edi, ds:__imp__ReadProcessMemory@20 ; ReadProcessMemory(x,x,x,x,x)</span></p>
<p><span>.text:51402502<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>call<span>&nbsp;&nbsp;&nbsp; </span>edi ; ReadProcessMemory(x,x,x,x,x) ; ReadProcessMemory(x,x,x,x,x)</span></p>
<p><span>这里读取的是</span><span>PEB</span><span>地址</span><span>+0C</span><span>处的四个字节。</span></p>
<p><span>通过</span><span>WinDbg</span><span>我们可以看看</span><span>nt!_PEB</span><span>的结构</span></p>
<p><span>0: kd&gt; dt nt!_PEB</span></p>
<p><span><span>&nbsp;&nbsp; </span>+0x000 InheritedAddressSpace : UChar</span></p>
<p><span><span>&nbsp;&nbsp; </span>+0x001 ReadImageFileExecOptions : UChar</span></p>
<p><span><span>&nbsp;&nbsp; </span>+0x002 BeingDebugged<span>&nbsp;&nbsp;&nbsp; </span>: UChar</span></p>
<p><span><span>&nbsp;&nbsp; </span>+0x003 SpareBool<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>: UChar</span></p>
<p><span><span>&nbsp;&nbsp; </span>+0x004 Mutant<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>: Ptr32 Void</span></p>
<p><span><span>&nbsp;&nbsp; </span>+0x008 ImageBaseAddress : Ptr32 Void</span></p>
<p><span><span>&nbsp;&nbsp; </span>+0x00c Ldr<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>: Ptr32 _PEB_LDR_DATA</span></p>
<p><span>&nbsp;&nbsp;+0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS</span></p>
<p><span>&#8230;&#8230;</span></p>
<p><span>+0C</span><span>处是一个</span><span>_PEB_LDR_DATA</span><span>结构指针，里面包含了和</span><span>LDR</span><span>相关的一些数据，进程的模块链表就保存在</span><span>Ldr</span><span>中。下面是</span><span>_PEB_LDR_DATA</span><span>的结构：</span></p>
<p><span>0: kd&gt; dt nt!_PEB_LDR_DATA</span></p>
<p><span><span>&nbsp;&nbsp; </span>+0x000 Length<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>: Uint4B</span></p>
<p><span><span>&nbsp;&nbsp; </span>+0x004 Initialized<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>: UChar</span></p>
<p><span><span>&nbsp;&nbsp; </span>+0x008 SsHandle<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>: Ptr32 Void</span></p>
<p><span><span>&nbsp;&nbsp; </span>+0x00c InLoadOrderModuleList : _LIST_ENTRY</span></p>
<p><span><span>&nbsp;&nbsp; </span>+0x014 InMemoryOrderModuleList : _LIST_ENTRY</span></p>
<p><span><span>&nbsp;&nbsp; </span>+0x01c InInitializationOrderModuleList : _LIST_ENTRY</span></p>
<p><span><span>&nbsp;&nbsp; </span>+0x024 EntryInProgress&nbsp;: Ptr32 Void</span></p>
<p><span>其中，</span><span>InLoadOrderModuleList</span><span>、</span><span>InMemoryOrderModuleList</span><span>、</span><span>InInitializationOrderModuleList</span><span>就是进程当前已加载模块的链表，只是按照不同的方式排序。</span><span>EnumProcessModules</span><span>是通过</span><span>InMemoryOrderModuleList</span><span>链表枚举的，而根据</span><span>Win2k</span><span>代码，</span><span>ToolHelp32</span><span>函数是通过</span><span>InLoadOrderModuleList</span><span>枚举。这三个</span><span>_LIST_ENTRY</span><span>都是在一个</span><span>RTL_PROCESS_MODULE_INFORMATION</span><span>结构中的成员。这个结构在</span><span>2k</span><span>代码中有引用，不过没有确切的定义，下面是</span><span>ReactOS</span><span>中的定义，不过看起来我的</span><span>vista PSAPI</span><span>中使用的结构已经有所变化了，这里只作参考。</span></p>
<p><span>//</span></p>
<p><span>// Loader Data Table Entry</span></p>
<p><span>//</span></p>
<p><span>typedef struct _LDR_DATA_TABLE_ENTRY</span></p>
<p><span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>LIST_ENTRY InLoadOrderLinks;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>LIST_ENTRY InMemoryOrderModuleList;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>LIST_ENTRY InInitializationOrderModuleList;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>PVOID DllBase;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>PVOID EntryPoint;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>ULONG SizeOfImage;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>UNICODE_STRING FullDllName;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>UNICODE_STRING BaseDllName;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>ULONG Flags;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT LoadCount;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT TlsIndex;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>union</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>LIST_ENTRY HashLinks;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>PVOID SectionPointer;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>};</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>ULONG CheckSum;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>union</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ULONG TimeDateStamp;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>PVOID LoadedImports;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>};</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>PVOID EntryPointActivationContext;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>PVOID PatchInformation;</span></p>
<p><span>} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;</span></p>
<p><span>到这里，隐藏模块的方法就已经明了了：通过</span><span>PEB</span><span>取得</span><span>Ldr</span><span>数据，拿到三个模块链表，并将要隐藏的模块断链即可。下面是主要代码实现：</span></p>
<p><span>BOOL</span><span> <span>HideMyself</span>()</span></p>
<p><span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>HMODULE</span> <span>hMod</span> = <span>GetModuleHandle</span>( <span>_T</span>( <span>"ntdll.dll"</span>));</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>HMODULE</span> <span>hModMyself</span> = <span>GetModuleHandle</span>( <span>_T</span>(<span>"dll.dll"</span>));</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>pfnNtQueryInformationProcess</span> <span>p</span> = (<span>pfnNtQueryInformationProcess</span>)::<span>GetProcAddress</span>( <span>hMod</span>, <span>"NtQueryInformationProcess"</span>);</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>PROCESS_BASIC_INFORMATION</span> <span>stInfo</span> = {0};</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>DWORD</span> <span>dwRetnLen</span> = 0;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>DWORD</span> <span>dw</span> = <span>p</span>( <span>GetCurrentProcess</span>(), 0, &amp;<span>stInfo</span>, <span>sizeof</span>(<span>stInfo</span>), &amp;<span>dwRetnLen</span>);</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>PPEB</span> <span>pPeb</span> = <span>stInfo</span>.<span>PebBaseAddress</span>;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>PLIST_ENTRY</span> <span>ListHead</span>, <span>Current</span>;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>PLDR_DATA_TABLE_ENTRY</span> <span>pstEntry</span> = <span>NULL</span>;</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>ListHead</span> = &amp;( <span>stInfo</span>.<span>PebBaseAddress</span>-&gt;<span>Ldr</span>-&gt;<span>InLoadOrderModuleList</span>);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>Current</span> = <span>ListHead</span>-&gt;<span>Flink</span>;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>while</span> ( <span>Current</span> != <span>ListHead</span>)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>pstEntry</span> = <span>CONTAINING_RECORD</span>( <span>Current</span>, <span>LDR_DATA_TABLE_ENTRY</span>, <span>InLoadOrderLinks</span>);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>//DebugOutW( L"Module:%s, base:0x%X\r\n", pstEntry-&gt;FullDllName.Buffer, pstEntry-&gt;EntryPoint);</span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>if</span> ( <span>pstEntry</span>-&gt;<span>DllBase</span> == <span>hModMyself</span>)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>pstEntry</span>-&gt;<span>InLoadOrderLinks</span>.<span>Flink</span>-&gt;<span>Blink</span> = <span>pstEntry</span>-&gt;<span>InLoadOrderLinks</span>.<span>Blink</span>;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>pstEntry</span>-&gt;<span>InLoadOrderLinks</span>.<span>Blink</span>-&gt;<span>Flink</span> = <span>pstEntry</span>-&gt;<span>InLoadOrderLinks</span>.<span>Flink</span>;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>DebugOut</span>( <span>_T</span>( <span>"Hide injected dll."</span>));</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>break</span>;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>Current</span> = <span>pstEntry</span>-&gt;<span>InLoadOrderLinks</span>.<span>Flink</span>;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>ListHead</span> = &amp;( <span>stInfo</span>.<span>PebBaseAddress</span>-&gt;<span>Ldr</span>-&gt;<span>InMemoryOrderModuleList</span>);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>Current</span> = <span>ListHead</span>-&gt;<span>Flink</span>;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>while</span> ( <span>Current</span> != <span>ListHead</span>)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>pstEntry</span> = <span>CONTAINING_RECORD</span>( <span>Current</span>, <span>LDR_DATA_TABLE_ENTRY</span>, <span>InMemoryOrderModuleList</span>);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>DebugOutW</span>( <span>L</span><span>"Module:%s, base:0x%X\r\n"</span>, <span>pstEntry</span>-&gt;<span>FullDllName</span>.<span>Buffer</span>, <span>pstEntry</span>-&gt;<span>EntryPoint</span>);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>if</span> ( <span>pstEntry</span>-&gt;<span>DllBase</span> == <span>hModMyself</span>)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>pstEntry</span>-&gt;<span>InMemoryOrderModuleList</span>.<span>Flink</span>-&gt;<span>Blink</span> = <span>pstEntry</span>-&gt;<span>InMemoryOrderModuleList</span>.<span>Blink</span>;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>pstEntry</span>-&gt;<span>InMemoryOrderModuleList</span>.<span>Blink</span>-&gt;<span>Flink</span> = <span>pstEntry</span>-&gt;<span>InMemoryOrderModuleList</span>.<span>Flink</span>;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>DebugOut</span>( <span>_T</span>( <span>"Hide injected dll."</span>));</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>break</span>;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>Current</span> = <span>pstEntry</span>-&gt;<span>InMemoryOrderModuleList</span>.<span>Flink</span>;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>DebugOutW</span>( <span>L</span><span>"\r\n"</span>);</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>ListHead</span> = &amp;( <span>stInfo</span>.<span>PebBaseAddress</span>-&gt;<span>Ldr</span>-&gt;<span>InInitializationOrderModuleList</span>);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>Current</span> = <span>ListHead</span>-&gt;<span>Flink</span>;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>while</span> ( <span>Current</span> != <span>ListHead</span>)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>pstEntry</span> = <span>CONTAINING_RECORD</span>( <span>Current</span>, <span>LDR_DATA_TABLE_ENTRY</span>, <span>InInitializationOrderModuleList</span>);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>DebugOutW</span>( <span>L</span><span>"Module:%s, base:0x%X\r\n"</span>, <span>pstEntry</span>-&gt;<span>FullDllName</span>.<span>Buffer</span>, <span>pstEntry</span>-&gt;<span>EntryPoint</span>);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>if</span> ( <span>pstEntry</span>-&gt;<span>DllBase</span> == <span>hModMyself</span>)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>pstEntry</span>-&gt;<span>InInitializationOrderModuleList</span>.<span>Flink</span>-&gt;<span>Blink</span> = <span>pstEntry</span>-&gt;<span>InInitializationOrderModuleList</span>.<span>Blink</span>;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>pstEntry</span>-&gt;<span>InInitializationOrderModuleList</span>.<span>Blink</span>-&gt;<span>Flink</span> = <span>pstEntry</span>-&gt;<span>InInitializationOrderModuleList</span>.<span>Flink</span>;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>DebugOut</span>( <span>_T</span>( <span>"Hide injected dll."</span>));</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>break</span>;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>Current</span> = <span>pstEntry</span>-&gt;<span>InInitializationOrderModuleList</span>.<span>Flink</span>;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>//DebugOut( _T("Out HideMyself\r\n"));</span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>return</span> <span>TRUE</span>;</span></p>
<p><span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>这样处理之后，通过常规的枚举进程方式已经枚举不到隐藏模块，</span><span>ProcessExplorer</span><span>也无法枚举。但是，通过枚举进程内存空间等非常规方法，仍然是可以找到的。关于</span><span>PSAPI</span><span>和</span><span>Toolhelp</span><span>函数枚举模块的原理，可以逆向</span><span>Windows</span><span>代码，或者查找网上的代码看看就明白了。</span></p>
<img src ="http://www.cnitblog.com/cc682/aggbug/43263.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/cc682/" target="_blank">NetRoc</a> 2008-05-04 14:59 <a href="http://www.cnitblog.com/cc682/articles/43263.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>两种不使用过滤驱动从驱动获取数据的方法</title><link>http://www.cnitblog.com/cc682/articles/43264.html</link><dc:creator>NetRoc</dc:creator><author>NetRoc</author><pubDate>Sun, 04 May 2008 06:59:00 GMT</pubDate><guid>http://www.cnitblog.com/cc682/articles/43264.html</guid><wfw:comment>http://www.cnitblog.com/cc682/comments/43264.html</wfw:comment><comments>http://www.cnitblog.com/cc682/articles/43264.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/cc682/comments/commentRss/43264.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/cc682/services/trackbacks/43264.html</trackback:ping><description><![CDATA[&nbsp;
<p>&nbsp;</p>
<p align=right><span>NetRoc</span></p>
<p><span>一直想写点技术文章的，但是每次想起这事的时候没时间，有时间的时候又提不起兴致</span><span><span>J</span></span><span>。</span></p>
<p><span>我们有时候需要从系统中某些驱动处理数据的方式，例如作一些过滤、对数据进行一些修改或者监视通过某个设备栈的数据等等。通常情况下是采用</span><span>Filter Driver</span><span>的方式实现。但是这样有种种局限性：容易暴露自己的存在、有些情况下可能不能再</span><span>Detach</span><span>掉，升级驱动的时候必须重启机器等等。</span></p>
<p><span>这里介绍两种通过</span><span>HOOK</span><span>方式截取数据的方法。</span></p>
<p><span><span>1、<span> </span></span></span><span>Hook Dispatch</span><span>例程。</span></p>
<p><span>首先通过</span><span>ObReferenceObjectByName</span><span>等函数拿到被</span><span>Hook</span><span>设备的</span><span>DriverObject</span><span>。有了这个之后，我们就可以用指向自己例程的指针改写</span><span>MajorFunction</span><span>数组里面的指针。</span></p>
<p>&nbsp;</p>
<p><span>NTSTATUS ntStatus = STATUS_SUCCESS;</span></p>
<p><span>UNICODE_STRING wszDriverName;</span></p>
<p><span>PDRIVER_OBJECT&nbsp;pDriverObject = NULL;</span></p>
<p><span>PDRIVER_DISPATCH pOrgDispatch = NULL;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p><span>RtlInitUnicodeString( &amp;wszDriverName, DRIVER_NAME);</span></p>
<p>&nbsp;</p>
<p><span>ntStatus = ObReferenceObjectByName( &amp;wszDriverName, </span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>0, </span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>NULL, </span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>0, </span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>*IoDriverObjectType, </span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//NULL,</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>KernelMode, </span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>NULL, </span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>(PVOID*)&amp;pDriverObject);</span></p>
<p><span>if( !NT_SUCCESS(ntStatus))</span></p>
<p><span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>DbgPrint( "ObReferenceObjectByName Fail.\r\n");</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return FALSE;</span></p>
<p><span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pOrgDispatch&nbsp;= (PDRIVER_DISPATCH) InterlockedExchange( ( PLONG)&amp;pDriverObject-&gt;MajorFunction[IRP_MJ_READ], (LONG)&amp;DispatchMyRead);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>&#8230;&#8230;</span></p>
<p><span>卸载的时候同样这样修改回去即可。</span></p>
<p><span>这种方法比较方便，由于只需要改写一个函数指针，避免了</span><span>inline hook</span><span>的很多不稳定因素。另外，在调用原来的</span><span>Dispatch</span><span>例程的时候也只需要直接</span><span>call</span><span>它就行了。</span></p>
<p><span>但是，如果有些</span><span>IRP</span><span>不能立即完成的，例如键盘鼠标驱动的</span><span>IRP</span><span>，用这种方法就拿不到完成时候的数据了。因此我们还需要第二种方式</span><span><span>J</span></span></p>
<p>&nbsp;</p>
<p><span><span>2、<span> </span></span></span><span>Hook Completion Routine</span><span>。</span></p>
<p><span>在</span><span>Hook</span><span>掉的</span><span>Dispatch</span><span>里面，我们已经拿到了发到下层驱动的</span><span>IRP</span><span>。想在完成时再获得控制权，很简单，只需要再</span><span>Hook</span><span>掉</span><span>Completion Routine</span><span>。</span></p>
<p><span>NTSTATUS DispatchMyRead ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP Irp)</span></p>
<p><span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp);</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//</span><span>需要保存一下旧的完成例程信息</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>g_RecentIrpInfo.ComplettionRoutine = irpSp-&gt;CompletionRoutine;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>g_RecentIrpInfo.Context = irpSp-&gt;Context;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>g_RecentIrpInfo.Control = irpSp-&gt;Control;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>g_RecentIrpInfo.irpSp = irpSp;</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//</span><span>安装自己的完成例程</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>irpSp-&gt;CompletionRoutine = MyIoCompletion;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>irpSp-&gt;Context = NULL;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>irpSp-&gt;Control = SL_INVOKE_ON_SUCCESS;<span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//OK</span><span>，</span><span>call</span><span>下去。</span></p>
<p><span>ntStatus = g_ pOrgDispatch ( pDeviceObject, Irp);</span></p>
<p><span>return ntStatus;</span></p>
<p><span>}</span></p>
<p>&nbsp;</p>
<span>在</span><span>MyIoCompletion</span><span>当然就是同样的标准</span><span>hook</span><span>操作咯，处理数据，</span><span>call</span><span>原来的</span><span>IoCompletion</span><span>。需要注意的是很多</span><span>Irp</span><span>并没有安装完成例程。</span>
<img src ="http://www.cnitblog.com/cc682/aggbug/43264.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/cc682/" target="_blank">NetRoc</a> 2008-05-04 14:59 <a href="http://www.cnitblog.com/cc682/articles/43264.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows内核分析之一 —— 内核入口函数</title><link>http://www.cnitblog.com/cc682/articles/43261.html</link><dc:creator>NetRoc</dc:creator><author>NetRoc</author><pubDate>Sun, 04 May 2008 06:57:00 GMT</pubDate><guid>http://www.cnitblog.com/cc682/articles/43261.html</guid><wfw:comment>http://www.cnitblog.com/cc682/comments/43261.html</wfw:comment><comments>http://www.cnitblog.com/cc682/articles/43261.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/cc682/comments/commentRss/43261.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/cc682/services/trackbacks/43261.html</trackback:ping><description><![CDATA[&nbsp;
<p align=center><span>NetRoc/cc682</span></p>
<p>&nbsp;</p>
<p><span>前段时间和</span><span>yuewang</span><span>和一块三毛钱商量着写写</span><span>Windows</span><span>分析的文章，我来开个头吧，哈哈。既然是开头，所以就选择了内核入口点开始，我向来不怎么会写文章，也就当流水账记记吧，看能不能引出他们更好的分析出来</span><span><span>J</span></span></p>
<p><span>Ntoskrnl</span><span>的入口点函数名是</span><span>KiSystemStartup</span><span>，这是</span><span>bootloader</span><span>执行了一些基本的初始化之后跳转到的内核入口函数，用汇编语言实现。</span></p>
<p><span><span>一、</span></span><span>KiSystemStartup</span><span>功能介绍</span></p>
<p><span>KiSystemStartup</span><span>第一次运行于</span><span>processor 0</span><span>，主要是初始化一些系统硬件状态，调用一些系统初始化过程，然后就进入调度程序，开始系统调度过程。而对于其他</span><span>processor</span><span>，初始化的时候也是进入</span><span>KiSystemStartup</span><span>，但是做的工作有所区别而已。</span></p>
<p>&nbsp;</p>
<p><span><span>二、</span></span><span>Processor 0(</span><span>以后简称</span><span>P0)</span><span>开始执行</span><span>KiSystemStartup</span><span>时的系统环境</span></p>
<p><span>这个运行环境是由</span><span>bootloader</span><span>准备好的：</span></p>
<p><span><span>1、<span> </span></span></span><span>一个精简版的</span><span>IDT</span><span>环境，从</span><span>0</span><span>到</span><span>0x1F</span><span>号中断已经被准备好</span></p>
<p><span><span>2、<span> </span></span></span><span>一个完整的</span><span>GDT</span><span>被初始化出来并且</span><span>Load</span><span>。</span></p>
<p><span><span>3、<span> </span></span></span><span>完整的</span><span>TSS</span><span>被初始化并且</span><span>Load</span><span>。</span></p>
<p><span><span>4、<span> </span></span></span><span>页面映射经过了基本的初始化，并且设置好了初始化所需的最少的页面。虚拟内存的最低</span><span>4M</span><span>被直接映射到物理内存中。</span></p>
<p><span><span>5、<span> </span></span></span><span>ntoskrnl.exe</span><span>被装载到它内存描述符中的地址。也即编译时确定的基地址。</span></p>
<p><span><span>6、<span> </span></span></span><span>DS=ES=SS</span><span>，</span><span>ESP</span><span>指向一个可用的栈中。</span></p>
<p><span><span>7、<span> </span></span></span><span>中断被关闭。</span></p>
<p>&nbsp;</p>
<p><span><span>三、</span></span><span>其他</span><span>Processor</span><span>开始执行</span><span>KiSystemStartup</span><span>的环境</span></p>
<p><span>IDT, GDT, TSS, stack, selectors, PCR</span><span>全部初始化完成并可用，页表设置为当前运行的页表</span><span>(</span><span>这一点偶也不太明白，可能还需要看看以后的代码才能理解</span><span>)</span><span>，具备一个</span><span>LoaderBlock</span><span>，作为在该处理器上执行</span><span>KiSystemStartup</span><span>的参数。</span></p>
<p>&nbsp;</p>
<p><span><span>四、</span></span><span>大致流程</span></p>
<p><span><span>1、<span> </span></span></span><span>KiSystemStartup</span><span>将参数</span><span>KissLoaderBlock</span><span>放到全局变量</span><span>_KeLoaderBlock</span><span>中</span></p>
<p><span><span>2、<span> </span></span></span><span>取出</span><span>_KeNumberProcessors</span><span>，并判断是否是</span><span>0</span><span>。</span><span>_KeNumberProcessors</span><span>保存了系统中的处理器数目，这个变量被初始化为</span><span>0</span><span>，所以当</span><span>Ntoskrnl</span><span>开始执行时，这个变量还没有被填充。因此判断</span><span>_KeNumberProcessors</span><span>是否是</span><span>0</span><span>，就可以知道当前是不是第一次执行</span><span>KiSystemStartup</span><span>。</span></p>
<p><span><span>3、<span> </span></span></span><span>如果是</span><span>P0</span><span>，会将</span><span>_KiInitialThread</span><span>和</span><span>P0BootStack</span><span>的地址分别保存</span> <span>到</span><span>_KeLoaderBlock</span><span>中的对应字段中。</span><span>_KiInitialThread</span><span>是系统启动之后的初始线程，而</span><span>P0BootStack</span><span>应该是初始化时临时使用的内核堆栈，定义为</span><span>db<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>KERNEL_STACK_SIZE dup (?)</span><span>。</span><span>KERNEL_STACK_SIZE</span><span>在</span><span>i386</span><span>中是</span><span>0x3000</span><span>，在</span><span>AMD64</span><span>中是</span><span>0x6000</span><span>。然后会设置</span><span>fs</span><span>为</span><span>0x30</span><span>，这是内核</span><span>_KPCR</span><span>结构的在</span><span>GDT</span><span>中序号。最后，会将处理器序号，也就是</span><span>0</span><span>，保存到</span><span>_KPCR</span><span>中对应位置，这个位置在</span><span>i386</span><span>和</span><span>AMD64</span><span>中也是不同的。</span></p>
<p><span><span>4、<span> </span></span></span><span>下面又是所有处理器都会执行的代码了，设置初始线程的</span><span>_ETHREAD:: Tcb:: ApcState:: ApcListHead[0]</span><span>，将</span><span>_LIST_ENTRY</span><span>的</span><span>Flink</span><span>和</span><span>Blink</span><span>都设置为自身。</span></p>
<p><span><span>5、<span> </span></span></span><span>调用</span><span>_KiInitializeMachineType</span><span>过程，会设置一下机器类型。不过这里做得很简单，这个函数可能在未来也会有较大更改。主要的机器类型信息可能包含了总线类型、</span><span>CPU</span><span>大致的系列等简单信息。</span></p>
<p><span><span>6、<span> </span></span></span><span>然后又判断是否是</span><span>P0</span><span>，如果不是，会跳过一大段初始化代码。</span></p>
<p><span><span>7、<span> </span></span></span><span>在</span><span>P0</span><span>的情况下，调用</span><span>GetMachineBootPointers</span><span>函数，获取由</span><span>bootloader</span><span>初始化过的一些信息。从这个函数返回后，</span><span>edi</span><span>中保存</span><span>gdt</span><span>基地址，</span><span>esi</span><span>中保存</span><span>pcr</span><span>基地址，</span><span>edx</span><span>保存</span><span>tss</span><span>基地址，</span><span>eax</span><span>保存</span><span>idt</span><span>基地址。</span><span>KiSystemStartup</span><span>接下来会将这些值保存到自己的局部变量中使用。</span></p>
<p><span><span>8、<span> </span></span></span><span>Bootloader</span><span>初始化的</span><span>TSS</span><span>是</span><span>16</span><span>位的，</span><span>KiSystemStartup</span><span>在这里会将它的标志改为</span><span>32</span><span>位，然后连续调用</span><span>_KiInitializeTSS2</span><span>和</span><span>_KiInitializeTSS</span><span>初始化</span><span>TSS</span><span>。</span><span>KiInitializeTSS2</span><span>初始化了内核</span><span>TSS</span><span>结构在</span><span>GDT</span><span>中描述符的界限大小，以及初始化</span><span>IOPM</span><span>的相关结构。</span><span>_KiInitializeTSS</span><span>在</span><span>TSS</span><span>中首先设置不使用</span><span>IOPM</span><span>，然后设置</span><span>Tss-&gt;Flags = 0</span><span>，将</span><span>EFLAGS</span><span>清空。最后将</span><span>LDT</span><span>和</span><span>ss0</span><span>都设置为</span><span>0</span><span>。设置完成后，重新装载</span><span>TR</span><span>寄存器。</span></p>
<p><span><span>9、<span> </span></span></span><span>接下来设置了</span><span>double fault task gate</span><span>。这里会设置</span><span>IDT</span><span>中的</span><span>08</span><span>号中断，设置成了一个任务门，并填充相应的</span><span>TSS</span><span>结构，是用于</span><span>#DF</span><span>异常时的。</span></p>
<p><span><span>10、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>设置用于</span><span>NMI fault </span><span>的</span><span>task gate</span><span>，设置</span><span>IDT</span><span>的</span><span>02</span><span>号中断。这是用于不可屏蔽中断的中断号。同样也调用</span><span>_KiInitializeTSS</span><span>填充了另外一个</span><span>TSS</span><span>结构。上面两条详细的原理参考</span><span>Intel</span><span>手册关于</span><span>IDT</span><span>和</span><span>task gate</span><span>的描述。</span></p>
<p><span><span>11、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>调用</span><span>_KiInitializePcr</span><span>初始化了当前的</span><span>pcr</span><span>。</span></p>
<p><span><span>12、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>将初始进程的</span><span>_EPROCESS</span><span>地址，即</span><span>_KiInitialProcess</span><span>的地址设置到了初始线程的</span><span>_ETHREAD:: Tcb:: ApcState:: Process</span><span>中。</span></p>
<p><span><span>13、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>设置</span><span>PCR-&gt;Teb = 0</span><span>。</span></p>
<p><span><span>14、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>设置</span><span>PCR-&gt;PrcbData.ProcessorState.SpecialRegisters.KernelDr6</span><span>和</span><span>PCR-&gt;PrcbData.ProcessorState.SpecialRegisters.KernelDr7</span><span>为</span><span>0</span><span>。这里是为了初始化内核调试器相关的东西，具体作用可能只有分析到相关代码才能知道了。</span></p>
<p><span><span>15、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>调用</span><span>_KiSwapIDT</span><span>转换</span><span>IDT</span><span>描述符的格式。</span><span>IDTENTRY</span><span>定义如下：</span></p>
<p><span>typedef struct tagIDTENTRY </span></p>
<p><span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>unsigned short OffsetLow;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>unsigned short Selector;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>unsigned char&nbsp;Reserved;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>unsigned char&nbsp;Type:4;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>unsigned char&nbsp;Always0:1;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>unsigned char&nbsp;Dpl:2;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>unsigned char&nbsp;Present:1;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>unsigned short OffsetHigh;</span></p>
<p><span>} IDTENTRY, *PIDTENTRY;</span></p>
<p><span>这个函数将</span><span>ntoskrnl</span><span>定义的</span><span>IDT</span><span>表项数组中，选择子的</span><span>Selector</span><span>和</span><span>OffsetHigh</span><span>字段对换。这里估计是在初始化这些表项的时候，为了方便直接将处理代码的地址填到了</span><span>&amp;OffsetLow</span><span>中，所以</span><span>Selector</span><span>保存了高位的地址，然后到后面来统一替换。详细的原理参见</span><span>Intel</span><span>手册。</span></p>
<p><span><span>16、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>将</span><span>ds</span><span>和</span><span>es</span><span>的值设置为</span><span>0x23</span><span>，也就是</span><span>Ring3</span><span>下的</span><span>ds</span><span>和</span><span>es</span><span>值。</span></p>
<p><span><span>17、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>将</span><span>ntoskrnl</span><span>中</span><span>_IDT</span><span>数组的内容复制到当前的</span><span>IDT</span><span>表中。前面设置的</span><span>double fault</span><span>和</span><span> nmi fault</span><span>的表项不会被覆盖掉，而是使用新设置的内容。</span></p>
<p><span><span>18、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>接下来又是所有处理器都会执行的操作了。调用</span><span>_KiProcessorStart</span><span>初始化处理器。这个函数会根据</span><span>KiProcessorStartControl</span><span>的不同值进行不同的操作，例如获取一些处理器信息、启动或者停止处理器等等。由于</span><span>P0</span><span>已经不需要初始化了，所以在</span><span>P0</span><span>阶段这个函数直接返回。</span></p>
<p><span><span>19、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>获取</span><span>_KiFreezeExecutionLock</span><span>这个锁，用于修改一些和处理器相关的全局资源。主要是</span><span>_KPCR</span><span>里面的处理器相关的信息。然后调用了</span><span>_HalInitializeProcessor</span><span>函数，初始化该处理器的</span><span>IDT</span><span>。估计这个函数会继续为每个处理器调用</span><span>KiSystemStartup</span><span>函数。不过没能确认。</span></p>
<p><span><span>20、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>将</span><span>IRQL</span><span>的信息保存下来。这是</span><span>hal</span><span>由参数传过来的。</span></p>
<p><span><span>21、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>在</span><span>_KeActiveProcessors</span><span>中设置初始化完成的处理器</span><span>MASK</span><span>。</span></p>
<p><span><span>22、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>调用</span><span>_KiInitializeAbios</span><span>初始化</span><span>ABIOS</span><span>结构。这里的详细原理就不太清楚了，因为没能分析过相关部分。</span></p>
<p><span><span>23、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>将</span><span>_KeNumberProcessors</span><span>加</span><span>1</span><span>，增加已初始化完成的处理器数量。然后就会释放掉</span><span>_KiFreezeExecutionLock</span><span>锁了。</span></p>
<p><span><span>24、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>接下来调用</span><span>_KdInitSystem</span><span>函数。这里应该会初始化内核调试器。只在</span><span>P0</span><span>上调用。</span></p>
<p><span><span>25、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>后面将会初始化内核了，首先会将</span><span>IRQL</span><span>提升到</span><span>HIGH_LEVEL</span><span>，并初始化调用内核初始化函数使用的寄存器，包括传递参数的</span><span>eax,ebx,edx</span><span>，以及用于堆栈访问的</span><span>esp</span><span>和</span><span>ebp</span><span>。然后就调用</span><span>_KiInitializeKernel</span><span>进行内核初始化。这个函数相当复杂，也够一篇文章，这里就不写了。呵呵</span></p>
<p><span><span>26、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>出来之后设置</span><span>idle thread</span><span>的优先级为</span><span>0</span><span>，开中断，降低</span><span>IRQL</span><span>到</span><span>DISPATCH_LEVEL</span><span>。然后检查并等待</span><span>_KiBarrierWait</span><span>这个锁。对</span><span>P0</span><span>来说，由于</span><span>_KiBarrierWait</span><span>初始化为</span><span>0</span><span>，所以直接就跳到</span><span>idle</span><span>线程了，其他处理器会一直等待</span><span>_KiBarrierWait</span><span>，直到允许他们运行。</span></p>
<p><span><span>27、<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>最后通过一个长跳转到</span><span>KiIdleLoop</span><span>函数，开始系统的处理和调度，整个系统初始化过程就完成了。</span></p>
<p>&nbsp;</p>
<p><span><span>五、</span></span><span>后记</span></p>
<p><span>唉，真的写起来才发现文章不好写啊。自己再看的时候都感觉不清不楚的，呵呵。不过暂时就这样吧</span><span><span>J</span></span></p>
<img src ="http://www.cnitblog.com/cc682/aggbug/43261.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/cc682/" target="_blank">NetRoc</a> 2008-05-04 14:57 <a href="http://www.cnitblog.com/cc682/articles/43261.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XTrap驱动分析</title><link>http://www.cnitblog.com/cc682/articles/43262.html</link><dc:creator>NetRoc</dc:creator><author>NetRoc</author><pubDate>Sun, 04 May 2008 06:57:00 GMT</pubDate><guid>http://www.cnitblog.com/cc682/articles/43262.html</guid><wfw:comment>http://www.cnitblog.com/cc682/comments/43262.html</wfw:comment><comments>http://www.cnitblog.com/cc682/articles/43262.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cnitblog.com/cc682/comments/commentRss/43262.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/cc682/services/trackbacks/43262.html</trackback:ping><description><![CDATA[&nbsp;
<p><span>最近拿到一个使用</span><span>XTrap</span><span>的游戏，据说此物乃</span><span>NP</span><span>和</span><span>HS</span><span>之外的第三大反外挂系统，</span><span>so</span><span>拿来瞧了瞧。</span></p>
<p><span>Ring3</span><span>层包括几个</span><span>dll</span><span>和一个进程。看里面貌似使用了</span><span>pipe</span><span>相关的函数，运行时也起了一个进程。所以</span><span>XTrap</span><span>的架构应该和</span><span>NP</span><span>很类似，但是实现上就要弱很多了。</span></p>
<p><span><span>1、<span> </span></span></span><span>现在还没发现有</span><span>ring3</span><span>全局注入的</span><span>dll</span><span>。</span></p>
<p><span><span>2、<span> </span></span></span><span>大量工作放到了作为和游戏接口的</span><span>dll</span><span>里面。通过</span><span>dll</span><span>方式提供游戏使用这点不同于</span><span>NP</span><span>的</span><span>lib</span><span>库，而更类似</span><span>HS</span><span>。这种方式一大弱点就是那个</span><span>dll</span><span>容易被模拟，并且比较难发现。</span></p>
<p><span><span>3、<span> </span></span></span><span>驱动相对来说应该是三个系统里面最弱的了，原因下面会讲到。花了</span><span>5</span><span>天时间逆出了整个驱动的源码，好像没有那么多硬编码的东西，呵呵。不过倒是发现了一些编程的</span><span>BUG</span><span>什么的。基本的功能点只有三个：</span><span>HOOK SSDT</span><span>实现的跨进程访问控制、通过对</span><span>IoAccessMap</span><span>的设置关闭对鼠标键盘端口访问权限、通过挂接</span><span>Int 1</span><span>中断获得调试信息。</span></p>
<p>&nbsp;</p>
<p><span>大概的流程如下：</span></p>
<p><span><span>1、<span> </span></span></span><span>DriverEntry</span><span>：通过</span><span>PsGetVersion</span><span>判断系统版本，并根据不同的版本保存要</span><span>Hook</span><span>的在</span><span>SSDT Shadow</span><span>表中服务的</span><span>ID</span><span>。而</span><span>SSDT</span><span>表中的则是由后面</span><span>IoControl</span><span>里面</span><span>Ring3</span><span>传下来的。目前来看已经支持</span><span>Vista</span><span>了。通过</span><span>KeQuerySystemTime</span><span>拿了一下系统时间并保存下来，不过后面就没有再使用了，估计以后为了反调试会做时间检查什么的东西吧。申请了</span><span>0x2000</span><span>长度的内存，这是用于后面设置</span><span>IoAccessMap</span><span>的。然后就是例行的</span><span>IoCreateDevice</span><span>和</span><span>IoCreateSymbolicLink</span><span>，设置</span><span>Dispatch</span><span>例程。</span><span>XTrap</span><span>的</span><span>IRP_MJ_DEVICE_CONTROL</span><span>、</span><span>IRP_MJ_CREATE</span><span>、</span><span>IRP_MJ_CLOSE</span><span>、</span><span>IRP_MJ_CLEANUP</span><span>是在同一个例程中处理的。最后有一个莫名其妙的调用</span><span>KfLowerIrql( KeRaiseIrqlToDpcLevel());</span><span>偶的水平实在是还难以理解高丽棒子为啥要这样做，嘿嘿。</span></p>
<p><span><span>2、<span> </span></span></span><span>剩下的就是通过</span><span>DeviceIoControl</span><span>来控制的了，我这个版本的</span><span>XTrap</span><span>一共有</span><span>17</span><span>个</span><span>ControlCode</span><span>。</span><span>Dispatch</span><span>例程的代码如下</span></p>
<p><span>NTSTATUS</span></p>
<p><span>XDvaDispatchAll( IN PDEVICE_OBJECT&nbsp;DeviceObject, IN PIRP&nbsp;Irp)</span></p>
<p><span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>PIO_STACK_LOCATION pIrpStack;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>PVOID pSystemBuffer;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>PVOID pOutBuffer;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ULONG ulMajorFunction;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>NTSTATUS ntStatus;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pIrpStack = IoGetCurrentIrpStackLocation( Irp);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Irp-&gt;IoStatus.Status = STATUS_SUCCESS;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Irp-&gt;IoStatus.Information = 0;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pSystemBuffer = Irp-&gt;AssociatedIrp.SystemBuffer;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ulMajorFunction = pIrpStack-&gt;MajorFunction;</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>switch( ulMajorFunction)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>case IRP_MJ_DEVICE_CONTROL:</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if( (pIrpStack-&gt;Parameters.DeviceIoControl.IoControlCode &amp; 0x3) == 0x3)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&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; </span>pOutBuffer = Irp-&gt;UserBuffer;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>else</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&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; </span>pOutBuffer = pSystemBuffer;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return DoDeviceIoControl( Irp, pIrpStack-&gt;FileObject, 1, pSystemBuffer, </span></p>
<p><span><span>&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; </span>pIrpStack-&gt;Parameters.DeviceIoControl.InputBufferLength, </span></p>
<p><span><span>&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; </span>pOutBuffer, pIrpStack-&gt;Parameters.DeviceIoControl.OutputBufferLength, </span></p>
<p><span><span>&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; </span>pIrpStack-&gt;Parameters.DeviceIoControl.IoControlCode,</span></p>
<p><span><span>&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; </span>&amp;Irp-&gt;IoStatus, DeviceObject);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>case IRP_MJ_CLOSE:</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>HookSSDT( g_HookInfo.NtOpenProcessInfo.Id, (ULONG)g_pNtOpenProcess, (ULONG)NewNtOpenProcess);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>HookSSDT( g_HookInfo.NtDeviceIoControlFileInfo.Id, (ULONG)g_pNtDeviceIoControlFile, (ULONG)NewNtDeviceIoControlFile);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>HookSSDT( g_HookInfo.NtWriteVirtualMemoryInfo.Id, (ULONG)g_pNtWriteVirtualMemory, (ULONG)NewNtWriteVirtualMemory);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>HookSSDT( g_HookInfo.NtOpenSectionInfo.Id, (ULONG)g_pNtOpenSection, (ULONG)NewNtOpenSection);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>HookSSDT( g_HookInfo.NtProtectVirtualMemoryInfo.Id, (ULONG)g_pNtProtectVirtualMemory, (ULONG)NewNtProtectVirtualMemory);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>HookSSDT( g_HookInfo.NtTerminateProcessInfo.Id, (ULONG)g_pNtTerminateProcess, (ULONG)NewNtTerminateProcess);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>HookSSDT2( g_dwNtGdiGetPixelId, (ULONG)g_pNtGdiGetPixel, (ULONG)NewNtGdiGetPixel);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>HookSSDT2( g_dwNtUserSendInputId, (ULONG)g_pNtUserSendInput, (ULONG)NewNtUserSendInput);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>HookSSDT2( g_dwNtUserCallNextHookExId, (ULONG)g_pNtUserCallNextHookEx, (ULONG)NewNtUserCallNextHookEx);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>HookSSDT2( g_dwNtUserPostMessageId, (ULONG)g_pNtUserPostMessage, (ULONG)NewNtUserPostMessage);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>HookSSDT2( g_dwNtUserTranslateMessageId, (ULONG)g_pNtUserTranslateMessage, (ULONG)NewNtUserTranslateMessage);</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if( g_byIsSuccess)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&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; </span>g_byIsSuccess = FALSE;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if( g_byIsReboot)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&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; </span>_asm cli;</span></p>
<p><span><span>&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; </span>WRITE_PORT_UCHAR( (PUCHAR)0x64, (UCHAR)0xFE);</span></p>
<p><span><span>&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; </span>_asm hlt;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>else</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&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; </span>ntStatus = STATUS_SUCCESS;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>break;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>case IRP_MJ_CREATE:</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if( g_arrSomeCode[0] == 0)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&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; </span>memcpy( g_arrSomeCode, MyInt1, 5*sizeof( ULONG));</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ntStatus = STATUS_SUCCESS;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>break;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>case IRP_MJ_CLEANUP:</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ntStatus = STATUS_SUCCESS;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>break;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>default:</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Irp-&gt;IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ntStatus = STATUS_INVALID_DEVICE_REQUEST;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>IofCompleteRequest( Irp, IO_NO_INCREMENT);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return ntStatus;</span></p>
<p><span>}</span></p>
<p>&nbsp;</p>
<p><span>IRP_MJ_DEVICE_CONTROL</span><span>的处理是在另外一个函数里面，由于太复杂，影响</span><span>blog</span><span>的美观，就不写出来了，哈哈。这里面可以看到，</span><span>XTrap</span><span>采用了和</span><span>NP</span><span>一样的办法重起电脑，就是往</span><span>64</span><span>端口写</span><span>0xFE</span><span>。挺白痴的是居然通过</span><span>WRITE_PORT_UCHAR</span><span>，难道以为只有他会</span><span>Hook~</span></p>
<p><span>IRP_MJ_CREATE</span><span>里面把自己的</span><span>Int 1 </span><span>函数的代码复制了一段出来，这个会用于后面再覆盖回去，是用于对付</span><span>Inline hook</span><span>的伎俩。</span></p>
<p><span>其他就没什么好说的了。</span></p>
<p><span><span>3、<span> </span></span></span><span>关于</span><span>SSDT</span><span>的</span><span>Hook</span></p>
<p><span>SSDT</span><span>中</span><span>Hook</span><span>的函数有以下几个：</span><span>NtOpenProcess</span><span>、</span><span>NtDeviceIoControlFile</span><span>、</span><span>NtWriteVirtualMemory</span><span>、</span><span>NtOpenSection</span><span>、</span><span>NtProtectVirtualMemory</span><span>、</span><span>NtTerminateProcess</span></p>
<p><span>Shadow Table</span><span>中</span><span>Hook</span><span>的函数有下面几个：</span><span>NtGdiGetPixel</span><span>、</span><span>NtUserSendInput</span><span>、</span><span>NtUserCallNextHookEx</span><span>、</span><span>NtUserPostMessage</span><span>、</span><span>NtUserTranslateMessage</span><span>。</span></p>
<p><span>所有函数</span><span>Hook</span><span>的目的都很清楚，没有什么古怪的地方，呵呵。不过相当部分的钩子都只是简单的</span><span>pass</span><span>过去，并没有任何实质性的处理。可以看出来</span><span>XTrap</span><span>仍然是一个非常不完善的系统，这些部分应该都是留到以后进行功能扩充的。</span></p>
<p><span>关于</span><span>Shadow Table</span><span>的处理有一些特别的地方。</span><span>Shadow Table</span><span>的地址获取采用了硬编码</span><span>+</span><span>验证的方式。这一点偶个人觉得还是在</span><span>KeAddSystemServiceTable</span><span>中去取比较好，至少说在出现新的系统的时候很大可能并不用修改代码。另外，取到</span><span>Shadow Table</span><span>地址之后，除了将</span><span>KSERVICE_TABLE_DESCRIPTOR</span><span>地址保存之外，还将</span><span>Shadow Table</span><span>的</span><span>Base</span><span>保存到了</span><span>KeServiceDescriptorTable</span><span>第二项的</span><span>Base</span><span>中，以后在</span><span>Hook</span><span>或者其他操作的时候就直接到</span><span>KeAddSystemServiceTable</span><span>地址</span><span>+0x10</span><span>去取了。这一点我也觉得有些奇怪，保存到全局变量什么的不就好了，为什么要去修改系统本身的东西，虽然目前那个位置并没有什么用。大约是为了反调试。</span></p>
<p><span><span>4、<span> </span></span></span><span>关于</span><span>Int 1</span><span>的处理</span></p>
<p><span>这里貌似也没什么好说的，记录了一下断点被触发的次数、</span><span>dr0</span><span>到</span><span>dr4</span><span>的内容什么的，然后</span><span>IoControl</span><span>里面</span><span>Ring3</span><span>会取走这些信息。不过有个很搞笑的</span><span>BUG</span><span>，</span><span>Hook</span><span>中断的函数里面的</span><span>cli</span><span>没有对应的</span><span>sti</span><span>。</span></p>
<p><span><span>5、<span> </span></span></span><span>关于</span><span>IoAccessMap</span><span>的处理</span></p>
<p><span>这里没什么好说的，是由</span><span>Ring3</span><span>触发，</span><span>Ring0</span><span>实现。贴一段</span><span>DeviceIoContrl</span><span>里面的代码就明白了。</span></p>
<p><span>case 0x85000044:</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ntStatus = STATUS_INVALID_PARAMETER;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if( !pSystemBuffer || ulInputBufferLength != 4)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&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; </span>break;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>PsLookupProcessByProcessId( *((ULONG*)pSystemBuffer), pSystemBuffer);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>((PUCHAR)g_pIoAccessMap)[0x0C] |= 0xFF;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>((PUCHAR)g_pIoAccessMap)[0x0D] |= 0xFF;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Ke386IoSetAccessProcess( pSystemBuffer, 1);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Ke386SetIoAccessMap( 1, g_pIoAccessMap);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ntStatus = STATUS_SUCCESS;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>break;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>现在模拟键盘的所谓硬件模式，大部分人都是使用了网上一些开源工具，例如</span><span>WinIo</span><span>，基本原理就是通过</span><span>IoAccessMap</span><span>打开</span><span>ring0</span><span>的端口读写权限</span><span>(</span><span>啰嗦一句，上次看到某人拿来的一个</span><span>sys</span><span>，貌似将整个机器的</span><span>io</span><span>都打开了，实在是无比暴力&#8230;&#8230;。寒一个</span><span>)</span><span>。所以对应办法就是也通过改写</span><span>IoAccessMap</span><span>关闭掉权限。</span></p>
<p><span>这也是我现在比较推荐使用的方法，对使用</span><span>WinIo</span><span>的按键精灵什么的外挂，都有药到病除的疗效。而且，影响范围比较小，只关闭了有限的端口。对于某些特殊情况下的程序，也可以发现之后再单独处理。不过对于自己写驱动读写端口的一类外挂来说，任何办法都没用了。</span><span>In~~~out~~~~in~~~~out~~~~~in~~~~~~out~~~~~~</span><span><span>J</span></span></p>
<p><span><span>6、<span> </span></span></span><span>下面选一些函数贴出来吧</span><span><span>J</span></span></p>
<p><span>ULONG __stdcall</span></p>
<p><span>NewNtGdiGetPixel( PVOID hDC, LONG XPos, LONG YPos)</span></p>
<p><span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>BOOLEAN blIsBlock = TRUE;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if ( g_dwCurrentProcessId == (ULONG)PsGetCurrentProcessId())</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>blIsBlock = FALSE;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//</span><span>这里奇怪</span><span>,</span><span>不知道为什么这么搞</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if ( XPos == 0)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if( YPos != 0)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&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; </span>if( YPos == 0x5A)</span></p>
<p><span><span>&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; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>blIsBlock = FALSE;</span></p>
<p><span><span>&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; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>else</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&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; </span>blIsBlock = FALSE;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if( g_byIsSuccess == TRUE &amp;&amp; blIsBlock == TRUE)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return 0;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return g_pNtGdiGetPixel( hDC, XPos, YPos);</span></p>
<p><span>}</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span>ULONG</span></p>
<p><span>__stdcall NewNtUserSendInput(</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;ULONG nInputs,</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;LPINPUT pInput,</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;ULONG cbSize)</span></p>
<p><span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if( (g_byIsSuccess != TRUE) || (g_byAllowUserSendInput == TRUE))</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return g_pNtUserSendInput( nInputs, pInput, cbSize);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>else</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return 1;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span>}</span></p>
<p>&nbsp;</p>
<p><span>NTSTATUS</span></p>
<p><span>__stdcall NewNtOpenProcess (</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>PHANDLE ProcessHandle,</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ACCESS_MASK DesiredAccess,</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>POBJECT_ATTRIBUTES ObjectAttributes,</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>PCLIENT_ID ClientId</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>)</span></p>
<p><span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if( g_dwCurrentProcessId != 0)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if( (ULONG)ClientId-&gt;UniqueProcess == g_dwCurrentProcessId)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&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; </span>if( DesiredAccess != 0x478)</span></p>
<p><span><span>&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; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>DesiredAccess &amp;= 0xFFFFFFCF;//</span><span>清掉</span><span>PROCESS_VM_READ</span><span>和</span><span>PROCESS_VM_WRITE</span></p>
<p><span><span>&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; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if( g_dwProtectPid2 != 0)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if( g_dwProtectPid2 == (ULONG)ClientId-&gt;UniqueProcess)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&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; </span>DesiredAccess &amp;= 0x0FFFFFFFE; //</span><span>清掉</span><span>PROCESS_TERMINATE</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if( g_dwCurrentProcessId == (ULONG)ClientId-&gt;UniqueProcess)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>g_dwIsSomeoneOpenMe = 1;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return g_pNtOpenProcess( ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);</span></p>
<p><span>}</span></p>
<p>&nbsp;</p>
<p><span>NTSTATUS</span></p>
<p><span>__stdcall NewNtWriteVirtualMemory(</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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; </span>&nbsp;HANDLE ProcessHandle,</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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; </span>&nbsp;PVOID BaseAddress,</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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; </span>&nbsp;CONST VOID *Buffer,</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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; </span>&nbsp;SIZE_T BufferSize,</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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; </span>&nbsp;PSIZE_T NumberOfBytesWritten</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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; </span>&nbsp;)</span></p>
<p><span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>BOOLEAN blIsNeedSkip = FALSE;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>PROCESS_BASIC_INFORMATION stProcessInfo;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>HANDLE Handle;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>HANDLE hCurrentPid;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>RtlZeroMemory( &amp;stProcessInfo, sizeof(stProcessInfo));</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if( STATUS_SUCCESS == </span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ZwDuplicateObject( (HANDLE)0xFFFFFFFF, </span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ProcessHandle,</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>(HANDLE)0xFFFFFFFF,</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&amp;Handle,</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>0x400,</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>0, </span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>0)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ZwQueryInformationProcess( Handle, 0, &amp;stProcessInfo, 0x18, 0);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ZwClose( Handle);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if( g_dwCurrentProcessId == (ULONG)stProcessInfo.UniqueProcessId)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>blIsNeedSkip = TRUE;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>hCurrentPid = PsGetCurrentProcessId();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if( (ULONG)hCurrentPid == g_dwSafePid1 ||</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>(ULONG)hCurrentPid == g_dwSafePid2 ||</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>(ULONG)hCurrentPid == g_dwSafePid3)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>blIsNeedSkip = FALSE;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if( (ULONG)hCurrentPid == g_dwCurrentProcessId)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if( (g_dwFromUser2 | 0xFFFFF0F) == 0xFFFFF1F)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&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; </span>blIsNeedSkip = FALSE;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if ( !g_byIsSuccess || !blIsNeedSkip)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return g_pNtWriteVirtualMemory( ProcessHandle, BaseAddress, Buffer, BufferSize, NumberOfBytesWritten);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return 0;</span></p>
<p><span>}</span></p>
<p>&nbsp;</p>
<p><span>ULONG __stdcall NewNtUserTranslateMessage(PMSG lpMsg, ULONG dwhkl)</span></p>
<p><span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>CHAR ucScanCode, ucScanCode2;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>UCHAR blNeedSkip = FALSE;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if( lpMsg-&gt;message == 0x100 || lpMsg-&gt;message == 0x101)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{//WM_KEYDOWN,WM_KEYUP</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ucScanCode2 = IsNeedSkipKeyMsg( lpMsg-&gt;wParam);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if( ucScanCode2)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&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; </span>ucScanCode = (lpMsg-&gt;lParam &amp; 0x00FF0000) &gt;&gt; 16;</span></p>
<p><span><span>&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; </span>if( ucScanCode == ucScanCode2)</span></p>
<p><span><span>&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; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>blNeedSkip = TRUE;</span></p>
<p><span><span>&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; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if( !g_byIsSuccess || !blNeedSkip)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return g_pNtUserTranslateMessage( lpMsg, dwhkl);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return 1;</span></p>
<p><span>}</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>后记：</span></p>
<p><span>不知不觉做反</span><span>XX</span><span>工作已经快两年了，再加上做</span><span>XX</span><span>工作的时间，突然发现搞这些东西居然这么久了。貌似接触的东西都没什么新意了，万变不离其宗。</span><span>XX</span><span>和反</span><span>XX</span><span>也就那么几招，倒不如直接找人去砍来得方便快捷。至此三大系统全部告破，呵呵。</span></p>
<p><span>众里寻她千百度，蓦然回首，偶还是喜欢</span><span>.NET</span><span>。</span></p>
<p><span>奇怪，我的</span><span>MSIME</span><span>打不出来&#8220;蓦&#8221;。</span></p>
<img src ="http://www.cnitblog.com/cc682/aggbug/43262.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/cc682/" target="_blank">NetRoc</a> 2008-05-04 14:57 <a href="http://www.cnitblog.com/cc682/articles/43262.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>模拟键盘鼠标操作——IoAccessMap介绍</title><link>http://www.cnitblog.com/cc682/articles/43256.html</link><dc:creator>NetRoc</dc:creator><author>NetRoc</author><pubDate>Sun, 04 May 2008 06:52:00 GMT</pubDate><guid>http://www.cnitblog.com/cc682/articles/43256.html</guid><wfw:comment>http://www.cnitblog.com/cc682/comments/43256.html</wfw:comment><comments>http://www.cnitblog.com/cc682/articles/43256.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/cc682/comments/commentRss/43256.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/cc682/services/trackbacks/43256.html</trackback:ping><description><![CDATA[&nbsp;
<p align=center><span>NetRoc&nbsp;2007.06.25</span></p>
<p><span>关键词：</span><span>I/O Permission Bit Map</span><span>、按键精灵、模拟键盘鼠标</span></p>
<p><span>今天又被恶心了，上班不想工作。来谈谈</span><span>IoAccessMap</span><span>相关的一些东西吧。</span></p>
<p><span>我在上一篇</span><span>XTrap</span><span>驱动分析的文章里面提到过，现在的一些模拟键盘鼠标输入的程序使用了一种所谓硬件模式的东西，例如按键精灵。其实就是使用了</span><span>WinIo</span><span>这样一些打开进程在</span><span>Ring3</span><span>访问端口权限的库。这里会详细分析一下他们的实现机制，以及对付这些工具的推荐方法。</span></p>
<p><span>首先摘抄一段</span><span>WinIo</span><span>驱动里面的代码：</span></p>
<p><span>case IOCTL_WINIO_ENABLEDIRECTIO:</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>OutputDebugString("IOCTL_WINIO_ENABLEDIRECTIO");</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pIOPM = MmAllocateNonCachedMemory(sizeof(IOPM));</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if (pIOPM)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;RtlZeroMemory(pIOPM, sizeof(IOPM));</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Ke386IoSetAccessProcess(PsGetCurrentProcess(), 1);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Ke386SetIoAccessMap(1, pIOPM);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>else</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Irp-&gt;IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>break;</span></p>
<p>&nbsp;</p>
<p><span>ok</span><span>，打开端口权限的所有秘密就在这里了。不过我们要先介绍一下</span><span>Inter CPU</span><span>对</span><span>IoAccessMap</span><span>的定义。</span></p>
<p><span>I386</span><span>架构下，每个进程拥有的</span><span>TSS</span><span>块包含一个</span><span>I/O Permission Bit Map</span><span>，其中定义了该进程对各个端口的读写权限。</span><span>I/O Permission Bit Map</span><span>的每一位对应一个端口。例如和鼠标键盘相关的端口对应于</span><span>bit60</span><span>和</span><span>bit64</span><span>。另外，在</span><span>EFLAGS</span><span>寄存器中的</span><span>bit12</span><span>、</span><span>bit13</span><span>指示了</span><span>IN, INS, OUT, OUTS, CLI, STI</span><span>这几条指令需要的</span><span>IOPL</span><span>。当</span><span>CPL</span><span>大于</span><span>IOPL</span><span>时，</span><span>IO</span><span>访问时就会再查询</span><span>I/O Permission Bit Map</span><span>里面对应</span><span>bit</span><span>是否为</span><span>0</span><span>，如果为</span><span>0</span><span>则允许</span><span>IO</span><span>访问，否则会触发</span><span>general-protection exception (#GP)</span><span>。</span></p>
<p><span>所以，如果要打开某个进程的</span><span>IO</span><span>权限，只需要修改它的</span><span>I/O Permission Bit Map</span><span>就可以了。</span></p>
<p><span>Windows</span><span>为每个进程保存的</span><span>TSS</span><span>结构如下：</span></p>
<p><span>typedef struct _KTSS {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT&nbsp;Backlink;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT&nbsp;Reserved0;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>ULONG<span>&nbsp;&nbsp; </span>Esp0;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT&nbsp;Ss0;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT&nbsp;Reserved1;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>ULONG<span>&nbsp;&nbsp; </span>NotUsed1[4];</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>ULONG<span>&nbsp;&nbsp; </span>CR3;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>ULONG<span>&nbsp;&nbsp; </span>Eip;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>ULONG<span>&nbsp;&nbsp; </span>EFlags;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>ULONG<span>&nbsp;&nbsp; </span>Eax;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>ULONG<span>&nbsp;&nbsp; </span>Ecx;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>ULONG<span>&nbsp;&nbsp; </span>Edx;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>ULONG<span>&nbsp;&nbsp; </span>Ebx;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>ULONG<span>&nbsp;&nbsp; </span>Esp;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>ULONG<span>&nbsp;&nbsp; </span>Ebp;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>ULONG<span>&nbsp;&nbsp; </span>Esi;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>ULONG<span>&nbsp;&nbsp; </span>Edi;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT&nbsp;Es;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT&nbsp;Reserved2;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT&nbsp;Cs;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT&nbsp;Reserved3;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT&nbsp;Ss;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT&nbsp;Reserved4;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT&nbsp;Ds;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT&nbsp;Reserved5;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT&nbsp;Fs;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT&nbsp;Reserved6;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT&nbsp;Gs;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT&nbsp;Reserved7;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT&nbsp;LDT;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT&nbsp;Reserved8;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT&nbsp;Flags;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>USHORT&nbsp;IoMapBase;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>KIIO_ACCESS_MAP IoMaps[IOPM_COUNT];</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>//</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>// This is the Software interrupt direction bitmap associated with</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>// IO_ACCESS_MAP_NONE</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>//</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp; </span>KINT_DIRECTION_MAP IntDirectionMap;</span></p>
<p><span>} KTSS, *PKTSS;</span></p>
<p>&nbsp;</p>
<p><span>其中的</span><span>IOPM_COUNT</span><span>定义为</span><span>1</span><span>。貌似本来</span><span>Windows</span><span>想为每个</span><span>Process</span><span>保存多个</span><span>IoAccessMap</span><span>，默认只保存了一个。在访问相关函数时，如果制定</span><span>MapNumber</span><span>为</span><span>0</span><span>，则表示不使用</span><span>IoAccessMap</span><span>。所以</span><span>0</span><span>号</span><span>map</span><span>是虚拟出来的，这点在</span><span>wrk1.2</span><span>代码中可以确认。</span></p>
<p><span>以下三个函数用于访问</span><span>IoAccessMap</span><span>：</span></p>
<p><span>BOOLEAN Ke386QueryIoAccessMap(ULONG MapNumber, PKIO_ACCESS_MAP IoAccessMap);</span><span>用于查询</span><span>IoAccessMap</span></p>
<p><span>BOOLEAN Ke386SetIoAccessMap(ULONG MapNumber, PKIO_ACCESS_MAP IoAccessMap);</span><span>用于设置</span><span>IoAccessMap</span></p>
<p><span>BOOLEAN Ke386IoSetAccessProcess(PKPROCESS Process, ULONG MapNumber);</span><span>用于设置某个</span><span>Process</span><span>使用的</span><span>IoAccessMap</span><span>号</span></p>
<p><span>下面分别讲一下三个函数的作用。</span></p>
<p><span>Ke386QueryIoAccessMap</span><span>将系统</span><span>KTSS</span><span>中的</span><span>IoMaps</span><span>复制出来，也就是查询当前的</span><span>IoAccessMap</span><span>。</span><span>MapNumber</span><span>传入</span><span>Map</span><span>号，当为</span><span>0</span><span>的时候表示指定</span><span>IO_ACCESS_MAP_NONE</span><span>，此时将传入</span><span>IoAccessMap</span><span>的所有位置</span><span>1</span><span>，当</span><span>MapNumber</span><span>为其他值时，复制对应的</span><span>Map</span><span>。</span></p>
<p><span>Ke386SetIoAccessMap</span><span>将</span><span>IoAccessMap</span><span>中的内容复制到指定</span><span>MapNumber</span><span>的内容中，当为</span><span>0</span><span>时返回</span><span>FALSE</span><span>，当为其他合法值时，</span><span>Ke386SetIoAccessMap</span><span>会创建一个</span><span>DPC</span><span>，并在</span><span>DPC</span><span>中将</span><span>IoAccessMap</span><span>的内容复制到进程</span><span>TSS</span><span>的</span><span>IoMaps</span><span>中。</span></p>
<p><span>Ke386IoSetAccessProcess</span><span>则是设置</span><span>Process</span><span>使用的</span><span>IoAccessMap</span><span>号。同样，会创建一个</span><span>DPC</span><span>，并由</span><span>DPC</span><span>修改指定进程的</span><span>EPROCESS</span><span>中的</span><span>IopmOffset</span><span>。</span></p>
<p>&nbsp;</p>
<p><span>Ok</span><span>，回过头来看</span><span>WinIo</span><span>的代码就一目了然了</span></p>
<p><span>pIOPM = MmAllocateNonCachedMemory(sizeof(IOPM));</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if (pIOPM)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>RtlZeroMemory(pIOPM, sizeof(IOPM));</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Ke386IoSetAccessProcess(PsGetCurrentProcess(), 1);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Ke386SetIoAccessMap(1, pIOPM);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span>首先</span><span>Alloc</span><span>一块内存，大小总是为</span><span>0x2000</span><span>字节，并将所有位置为</span><span>0</span><span>，也就是说打开</span><span>0~0x10000</span><span>端口的读写权限。</span></p>
<p><span>Ke386IoSetAccessProcess</span><span>的调用是确认使用</span><span>IoAccessMap</span><span>，然后通过</span><span>Ke386SetIoAccessMap</span><span>将</span><span>map</span><span>设置进去。</span></p>
<p><span>这样的方式似乎有点暴力了，如果改良一下的话，可以设置为只打开需要的端口。</span></p>
<p>&nbsp;</p>
<p><span>这种方式其实为系统打开了很大的漏洞，在</span><span>ring3</span><span>为一个进程打开了权限，实际上就是为任何人打开了权限。再加上往</span><span>64</span><span>端口写东西又可以重起机器什么的，呵呵&#8230;&#8230;不说了。</span></p>
<p><span>当然，如果要关掉对应的权限，就可以反其道而行之，将</span><span>map</span><span>中对应位设置为</span><span>1</span><span>即可。这就是我在上篇文章中提到的方法了。</span></p>
<p>&nbsp;</p>
<p><span>话说回来，</span><span>wrk</span><span>真是好东西，哈哈。</span></p>
<img src ="http://www.cnitblog.com/cc682/aggbug/43256.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/cc682/" target="_blank">NetRoc</a> 2008-05-04 14:52 <a href="http://www.cnitblog.com/cc682/articles/43256.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>