<?xml version="1.0" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="css/rss.xslt"?>
<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>hbs' blog - {C/C++相关}</title><link>http://www.hb4.org/</link><description>fuck by fuck! - </description><generator>RainbowSoft Studio Z-Blog 1.8 Walle Build 100427</generator><language>zh-CN</language><copyright>Copyright 2007-2010 Your WebSite. Some Rights Reserved.</copyright><pubDate>Tue, 07 Sep 2010 07:33:33 +0800</pubDate><item><title>Ring3新的键盘记录方法-适合盗号木马</title><author>a@b.com (hbslover)</author><link>http://www.hb4.org/Article/22.htm</link><pubDate>Tue, 09 Mar 2010 15:51:16 +0800</pubDate><guid>http://www.hb4.org/Article/22.htm</guid><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 看了VXK的文章提示咱们:可以用dinput来捕获键盘输入值,想想,能够干什么呢?</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 哈哈,记录密码啦~~~用的就是<span lang="EN-US" style="font-size: 10pt; color: black; font-family: Tahoma; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><strong>DirectInput</strong></span><span lang="EN-US" style="font-size: 10pt; color: black; font-family: Tahoma; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"> ... 不多说.贴代码:</span></p><p>=========================无聊的分割线======================</p><p><span lang="EN-US" style="font-size: 10pt; color: black; font-family: Tahoma; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><span style="font-size: 10pt; color: black">游戏编程可不仅仅是图形程序的开发工作，实际上包含了许多方面，本文所要讲述的就是关于如何使用</span><span style="font-size: 10pt; color: black"> <b>DirectInput</b> </span><span style="font-size: 10pt; color: black">来对键盘编程的问题。</span><span style="font-size: 10pt; color: black"><br /><br /></span><span style="font-size: 10pt; color: black">　　在</span><span style="font-size: 10pt; color: black"> DOS </span><span style="font-size: 10pt; color: black">时代，我们一般都习惯于接管键盘中断来加入自己的处理代码。但这一套生存方式在万恶的</span><span style="font-size: 10pt; color: black"> Windows </span><span style="font-size: 10pt; color: black">社会下是行不通的，我们只能靠领</span><span style="font-size: 10pt; color: black"> API </span><span style="font-size: 10pt; color: black">或者</span><span style="font-size: 10pt; color: black"> DirectInput </span><span style="font-size: 10pt; color: black">的救济金过活。</span><span style="font-size: 10pt; color: black"><br /><br /></span><span style="font-size: 10pt; color: black">　　在</span><span style="font-size: 10pt; color: black"> Windows </span><span style="font-size: 10pt; color: black">的</span><span style="font-size: 10pt; color: black"> API </span><span style="font-size: 10pt; color: black">中，有一个</span><span style="font-size: 10pt; color: black"> GetAsyncKeyState() </span><span style="font-size: 10pt; color: black">的函数可以返回一个指定键的当前状态是按下还是松开。这个函数还能返回该指定键在上次调用</span><span style="font-size: 10pt; color: black"> GetAsyncKeyState() </span><span style="font-size: 10pt; color: black">函数以后，是否被按下过。虽然这个函数听上去很不错，但现在领这种救济金的程序员是越来越少了。原因无它，只因为</span><span style="font-size: 10pt; color: black"> DirectInput </span><span style="font-size: 10pt; color: black">的救济金比这丰厚，而且看上去似乎更专业？</span><span style="font-size: 10pt; color: black"><br /><br /></span><span style="font-size: 10pt; color: black">　　为了早日成为职业的救济金用户，我们就从学习</span><span style="font-size: 10pt; color: black"> DirectInput </span><span style="font-size: 10pt; color: black">的键盘编程开始吧。</span><span style="font-size: 10pt; color: black"><br /><br />DIRECTINPUT </span><span style="font-size: 10pt; color: black">的初始化</span><span style="font-size: 10pt; color: black"><br /><br /></span><span style="font-size: 10pt; color: black">　　前面讲</span><span style="font-size: 10pt; color: black"> DirectDraw </span><span style="font-size: 10pt; color: black">时，曾经提到，微软是按</span><span style="font-size: 10pt; color: black"> COM </span><span style="font-size: 10pt; color: black">来设计</span><span style="font-size: 10pt; color: black">DirectX</span><span style="font-size: 10pt; color: black">的，所以就有了一个</span><span style="font-size: 10pt; color: black"> DIRECTINPUT </span><span style="font-size: 10pt; color: black">对象来表示输入设备，而某个具体的设备由</span><span style="font-size: 10pt; color: black"> DIRECTINPUTDEVICE </span><span style="font-size: 10pt; color: black">对象来表示。</span><span style="font-size: 10pt; color: black"><br /><br /></span><span style="font-size: 10pt; color: black">　　实际的建立过程是先创建一个</span><span style="font-size: 10pt; color: black"> DIRECTINPUT </span><span style="font-size: 10pt; color: black">对象，然后在通过此对象的</span><span style="font-size: 10pt; color: black"> CreateDevice </span><span style="font-size: 10pt; color: black">方法来创建</span><span style="font-size: 10pt; color: black"> DIRECTINPUTDEVICE </span><span style="font-size: 10pt; color: black">对象。</span><span style="font-size: 10pt; color: black"><br /><br /></span><span style="font-size: 10pt; color: black">　　示例如下：</span><span style="font-size: 10pt; color: black"><br /><br /></span><span style="font-size: 10pt; color: black">#include &lt;dinput.h&gt;<br /><br />#define DINPUT_BUFFERSIZE 16<br /><br />LPDIRECTINPUT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lpDirectInput;&nbsp; // DirectInput object<br />LPDIRECTINPUTDEVICE&nbsp;&nbsp;&nbsp;&nbsp; lpKeyboard;&nbsp;&nbsp;&nbsp;&nbsp; // DirectInput device<br /><br />BOOL InitDInput(HWND hWnd)<br />{<br />&nbsp;&nbsp;&nbsp; HRESULT hr;<br /><br />&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">创建一个</span><span style="font-size: 10pt; color: black"> DIRECTINPUT </span><span style="font-size: 10pt; color: black">对象</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp; hr = DirectInputCreate(hInstanceCopy, DIRECTINPUT_VERSION, &amp;lpDirectInput, NULL);<br /><br /></span></span></p><div align="left"><span style="font-size: 10pt; color: black">if FAILED(hr)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">失败</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FALSE;<br />&nbsp;&nbsp;&nbsp; }<br /><br />&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">创建一个</span><span style="font-size: 10pt; color: black"> DIRECTINPUTDEVICE </span><span style="font-size: 10pt; color: black">界面</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp; hr = lpDirectInput-&gt;CreateDevice(GUID_SysKeyboard, &amp;lpKeyboard, NULL);<br />&nbsp;&nbsp;&nbsp; if FAILED(hr)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">失败</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FALSE;<br />&nbsp;&nbsp;&nbsp; }<br /><br />&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">设定为通过一个</span><span style="font-size: 10pt; color: black"> 256 </span><span style="font-size: 10pt; color: black">字节的数组返回查询状态值</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp; hr = lpKeyboard-&gt;SetDataFormat(&amp;c_dfDIKeyboard);<br />&nbsp;&nbsp;&nbsp; if FAILED(hr)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">失败</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FALSE;<br />&nbsp;&nbsp;&nbsp; }<br /><br />&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">设定协作模式</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp; hr = lpKeyboard-&gt;SetCooperativeLevel(hWnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);<br />&nbsp;&nbsp;&nbsp; if FAILED(hr)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">失败</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FALSE;<br />&nbsp;&nbsp;&nbsp; }<br /><br />&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">设定缓冲区大小</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">如果不设定，缓冲区大小默认值为</span><span style="font-size: 10pt; color: black"> 0</span><span style="font-size: 10pt; color: black">，程序就只能按立即模式工作</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">如果要用缓冲模式工作，必须使缓冲区大小超过</span><span style="font-size: 10pt; color: black"> 0<br />&nbsp;&nbsp;&nbsp; DIPROPDWORD&nbsp;&nbsp;&nbsp;&nbsp; property;<br /><br />&nbsp;&nbsp;&nbsp; property.diph.dwSize = sizeof(DIPROPDWORD);<br />&nbsp;&nbsp;&nbsp; property.diph.dwHeaderSize = sizeof(DIPROPHEADER);<br />&nbsp;&nbsp;&nbsp; property.diph.dwObj = 0;<br />&nbsp;&nbsp;&nbsp; property.diph.dwHow = DIPH_DEVICE;<br />&nbsp;&nbsp;&nbsp; property.dwData = DINPUT_BUFFERSIZE;<br /><br />&nbsp;&nbsp;&nbsp; hr = lpKeyboard-&gt;SetProperty(DIPROP_BUFFERSIZE, &amp;property.diph);<br /><br />&nbsp;&nbsp;&nbsp; if FAILED(hr)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">失败</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FALSE;<br />&nbsp;&nbsp;&nbsp; }<br /><br /><br />&nbsp;&nbsp;&nbsp; hr = lpKeyboard-&gt;Acquire();<br />&nbsp;&nbsp;&nbsp; if FAILED(hr)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">失败</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FALSE;<br />&nbsp;&nbsp;&nbsp; }<br /><br />&nbsp;&nbsp;&nbsp; return TRUE;<br />}</span></div><div align="left"><span style="font-size: 10pt; color: black">　　在这段代码中，我们首先定义了</span><span style="font-size: 10pt; color: black"> lpDirectInput </span><span style="font-size: 10pt; color: black">和</span><span style="font-size: 10pt; color: black"> lpKeyboard </span><span style="font-size: 10pt; color: black">两个指针，前者用来指向</span><span style="font-size: 10pt; color: black"> DIRECTINPUT </span><span style="font-size: 10pt; color: black">对象，后者指向一个</span><span style="font-size: 10pt; color: black"> DIRECTINPUTDEVICE </span><span style="font-size: 10pt; color: black">界面。</span><span style="font-size: 10pt; color: black"><br /><br /></span><span style="font-size: 10pt; color: black">　　通过</span><span style="font-size: 10pt; color: black"> DirectInputCreate(), </span><span style="font-size: 10pt; color: black">我们为</span><span style="font-size: 10pt; color: black"> lpDirectInput </span><span style="font-size: 10pt; color: black">创建了一个</span><span style="font-size: 10pt; color: black"> DIRECTINPUT </span><span style="font-size: 10pt; color: black">对象。然后我们调用</span><span style="font-size: 10pt; color: black"> CreateDevice </span><span style="font-size: 10pt; color: black">来建立一个</span><span style="font-size: 10pt; color: black"> DIRECTINPUTDEVICE </span><span style="font-size: 10pt; color: black">界面。参数</span><span style="font-size: 10pt; color: black"> GUID_SysKeyboard </span><span style="font-size: 10pt; color: black">指明了建立的是键盘对象。</span><span style="font-size: 10pt; color: black"><br /><br /></span><span style="font-size: 10pt; color: black">　　接下来</span><span style="font-size: 10pt; color: black"> SetDataFormat </span><span style="font-size: 10pt; color: black">设定数据格式，</span><span style="font-size: 10pt; color: black">SetCooperativeLevel </span><span style="font-size: 10pt; color: black">设定协作模式，</span><span style="font-size: 10pt; color: black">SetProperty </span><span style="font-size: 10pt; color: black">设定缓冲区模式。因为这些函数方法的参数很多，我就不逐个去详细解释其作用了，请直接查看</span><span style="font-size: 10pt; color: black"> DirectX </span><span style="font-size: 10pt; color: black">的帮助信息，那里面写得非常清楚。</span><span style="font-size: 10pt; color: black"><br /><br /></span><span style="font-size: 10pt; color: black">　　完成这些工作以后，我们便调用</span><span style="font-size: 10pt; color: black"> DIRECTINPUTDEVICE </span><span style="font-size: 10pt; color: black">对象的</span><span style="font-size: 10pt; color: black"> Acquire </span><span style="font-size: 10pt; color: black">方法来激活对设备的访问权限。在此要特别说明一点，任何一个</span><span style="font-size: 10pt; color: black"> DIRECTINPUT </span><span style="font-size: 10pt; color: black">设备，如果未经</span><span style="font-size: 10pt; color: black"> Acquire</span><span style="font-size: 10pt; color: black">，是无法进行访问的。还有，当系统切换到别的进程时，必须用</span><span style="font-size: 10pt; color: black"> Unacquire </span><span style="font-size: 10pt; color: black">方法来释放访问权限，在系统切换回本进程时再调用</span><span style="font-size: 10pt; color: black"> Acquire </span><span style="font-size: 10pt; color: black">来重新获得访问权限。</span><span style="font-size: 10pt; color: black"><br /><br /></span><span style="font-size: 10pt; color: black">　　所以，我们通常要在</span><span style="font-size: 10pt; color: black"> WindowProc </span><span style="font-size: 10pt; color: black">中做如下处理：</span><span style="font-size: 10pt; color: black"><br /><br /></span><span style="font-size: 10pt; color: black">long FAR PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)<br />{<br />&nbsp;&nbsp;&nbsp; switch(message)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp; case WM_ACTIVATEAPP:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(bActive)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(lpKeyboard) lpKeyboard-&gt;Acquire();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(lpKeyboard) lpKeyboard-&gt;Unacquire();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp; ...<br />}</span></div><div align="left"><span style="font-size: 10pt; color: black">　　哦，对了，前一段例程中还提到了立即模式和缓冲模式。在</span><span style="font-size: 10pt; color: black"> DirectINPUT </span><span style="font-size: 10pt; color: black">中，这两种工作模式是有区别的。</span><span style="font-size: 10pt; color: black"><br /><br /></span><span style="font-size: 10pt; color: black">　　如果使用立即模式的话，在查询数据时，只能返回查询时的设备状态。而缓冲模式则将记录所有设备状态变化过程。就个人喜好而言，笔者偏好后者，因为这样一般不会丢失任何按键信息。对应的，如果在使用前者时的查询频度太低，则很难保证采集数据的完整性。</span><span style="font-size: 10pt; color: black"><br /><br />DIRECTINPUT </span><span style="font-size: 10pt; color: black">的数据查询</span><span style="font-size: 10pt; color: black"><br /><br /></span><span style="font-size: 10pt; color: black">　　立即模式的数据查询比较简单，请看下面的示例：</span><span style="font-size: 10pt; color: black"><br /><br /></span><span style="font-size: 10pt; color: black">BYTE diks[256]; // DirectInput keyboard state buffer </span><span style="font-size: 10pt; color: black">键盘状态数据缓冲区</span><span style="font-size: 10pt; color: black"><br /><br />HRESULT UpdateInputState(void)<br />{<br />&nbsp;&nbsp;&nbsp; if(lpKeyboard != NULL)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">如果</span><span style="font-size: 10pt; color: black"> lpKeyboard </span><span style="font-size: 10pt; color: black">对象界面存在</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HRESULT hr;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hr = DIERR_INPUTLOST;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">为循环检测做准备</span><span style="font-size: 10pt; color: black"><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // if input is lost then acquire and keep trying<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(hr == DIERR_INPUTLOST)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">读取输入设备状态值到状态数据缓冲区</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hr = lpKeyboard-&gt;GetDeviceState(sizeof(diks), &amp;diks);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(hr == DIERR_INPUTLOST)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // DirectInput </span><span style="font-size: 10pt; color: black">报告输入流被中断</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">必须先重新调用</span><span style="font-size: 10pt; color: black"> Acquire </span><span style="font-size: 10pt; color: black">方法，然后再试一次</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hr = lpKeyboard-&gt;Acquire();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(FAILED(hr))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return hr;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(FAILED(hr))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return hr;<br />&nbsp;&nbsp;&nbsp; }<br /><br />&nbsp;&nbsp;&nbsp; return S_OK;<br />}</span></div><div align="left"><span style="font-size: 10pt; color: black">　　在上面的示例中，关键处就是使用</span><span style="font-size: 10pt; color: black"> GetDeviceState </span><span style="font-size: 10pt; color: black">方法来读取输入设备状态值以及对异常情况的处理。通过使用</span><span style="font-size: 10pt; color: black"> GetDeviceState </span><span style="font-size: 10pt; color: black">方法，我们把输入设备的状态值放在了一个</span><span style="font-size: 10pt; color: black"> 256 </span><span style="font-size: 10pt; color: black">字节的数组里。如果该数组中某个数组元素的最高位为</span><span style="font-size: 10pt; color: black"> 1</span><span style="font-size: 10pt; color: black">，则表示相应编码的那个键此时正被按下。例如，如果</span><span style="font-size: 10pt; color: black"> diks[1]&amp;0x80&gt;0</span><span style="font-size: 10pt; color: black">，那么就表示</span><span style="font-size: 10pt; color: black"> ESC </span><span style="font-size: 10pt; color: black">键正被按下。</span><span style="font-size: 10pt; color: black"><br /><br /></span><span style="font-size: 10pt; color: black">　　学会了立即模式的数据查询以后，下面我们开始研究缓冲模式的情况：</span><span style="font-size: 10pt; color: black"><br /><br /></span><span style="font-size: 10pt; color: black">HRESULT UpdateInputState(void)<br />{<br />&nbsp;&nbsp;&nbsp; DWORD&nbsp;&nbsp; i;<br /><br />&nbsp;&nbsp;&nbsp; if(lpKeyboard != NULL)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DIDEVICEOBJECTDATA&nbsp; didod[DINPUT_BUFFERSIZE];&nbsp; // Receives buffered data<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dwElements;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HRESULT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hr;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hr = DIERR_INPUTLOST;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(hr != DI_OK)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dwElements = DINPUT_BUFFERSIZE;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hr = lpKeyboard-&gt;GetDeviceData(sizeof(DIDEVICEOBJECTDATA), didod, &amp;dwElements, 0);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (hr != DI_OK)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">发生了一个错误</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">这个错误有可能是</span><span style="font-size: 10pt; color: black"> DI_BUFFEROVERFLOW </span><span style="font-size: 10pt; color: black">缓冲区溢出错误</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">但不管是哪种错误，都意味着同输入设备的联系被丢失了</span><span style="font-size: 10pt; color: black"><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">这种错误引起的最严重的后果就是如果你按下一个键后还未松开时</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">发生了错误，就会丢失后面松开该键的消息。这样一来，你的程序</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">就可能以为该键尚未被松开，从而发生一些意想不到的情况</span><span style="font-size: 10pt; color: black"><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">现在这段代码并未处理该错误</span><span style="font-size: 10pt; color: black"><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">解决该问题的一个办法是，在出现这种错误时，就去调用一次</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // GetDeviceState()</span><span style="font-size: 10pt; color: black">，然后把结果同程序最后所记录的状态进行</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">比较，从而修正可能发生的错误</span><span style="font-size: 10pt; color: black"><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hr = lpKeyboard-&gt;Acquire();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(FAILED(hr))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return hr;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(FAILED(hr))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return hr;<br />&nbsp;&nbsp;&nbsp; }<br /><br />&nbsp;&nbsp;&nbsp; // GetDeviceData() </span><span style="font-size: 10pt; color: black">同</span><span style="font-size: 10pt; color: black"> GetDeviceState() </span><span style="font-size: 10pt; color: black">不一样，调用它之后，</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp; // dwElements </span><span style="font-size: 10pt; color: black">将指明此次调用共读取到了几条缓冲区记录</span><span style="font-size: 10pt; color: black"><br /><br />&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">我们再用一个循环来处理每条记录</span><span style="font-size: 10pt; color: black"><br /><br />&nbsp;&nbsp;&nbsp; for(int i=0; i&lt;dwElements; i++)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">此处放入处理代码</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // didod[i].dwOfs </span><span style="font-size: 10pt; color: black">表示那个键被按下或松开</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // didod[i].dwData </span><span style="font-size: 10pt; color: black">记录此键的状态，低字节最高位是</span><span style="font-size: 10pt; color: black"> 1 </span><span style="font-size: 10pt; color: black">表示按下，</span><span style="font-size: 10pt; color: black">0 </span><span style="font-size: 10pt; color: black">表示松开</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 10pt; color: black">一般用</span><span style="font-size: 10pt; color: black"> didod[i].dwData&amp;0x80 </span><span style="font-size: 10pt; color: black">来测试</span><span style="font-size: 10pt; color: black"><br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; return S_OK;<br />}</span></div><div align="left"><span style="font-size: 10pt; color: black">　　其实，每条记录还有</span><span style="font-size: 10pt; color: black"> dwTimeStamp </span><span style="font-size: 10pt; color: black">和</span><span style="font-size: 10pt; color: black"> dwSequence </span><span style="font-size: 10pt; color: black">两个字段来记录消息发生的时间和序列编号，以便作更复杂的处理。本文是针对初学者写的，就不打算去谈论这些内容了。</span><span style="font-size: 10pt; color: black"><br /><br />DIRECTINPUT </span><span style="font-size: 10pt; color: black">的结束处理</span><span style="font-size: 10pt; color: black"><br /><br /></span><span style="font-size: 10pt; color: black">　　我们在使用</span><span style="font-size: 10pt; color: black"> DIRECTINPUT </span><span style="font-size: 10pt; color: black">时，还要注意的一件事就是当程序结束时，必须要进行释放处理，其演示代码如下：</span><span style="font-size: 10pt; color: black"><br /><br /></span><span style="font-size: 10pt; color: black">void ReleaseDInput(void)<br />{<br />&nbsp;&nbsp;&nbsp; if (lpDirectInput)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(lpKeyboard)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Always unacquire the device before calling Release().<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lpKeyboard-&gt;Unacquire();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lpKeyboard-&gt;Release();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lpKeyboard = NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lpDirectInput-&gt;Release();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lpDirectInput = NULL;<br />&nbsp;&nbsp;&nbsp; }<br />}</span></div><p><span style="font-size: 10pt; color: black">　　这段代码很简单，就是对</span><span style="font-size: 10pt; color: black"> DIRECTINPUT </span><span style="font-size: 10pt; color: black">的各个对象去调用</span><span style="font-size: 10pt; color: black"> Release </span><span style="font-size: 10pt; color: black">方法来释放资源。这种过程同使用</span><span style="font-size: 10pt; color: black"> DIRECTX </span><span style="font-size: 10pt; color: black">的其它部分时是基本上相同的。</span></p>]]></description><category>{C/C++相关}</category><comments>http://www.hb4.org/Article/22.htm#comment</comments><wfw:comment>http://www.hb4.org/</wfw:comment><wfw:commentRss>http://www.hb4.org/feed.asp?cmt=22</wfw:commentRss><trackback:ping>http://www.hb4.org/cmd.asp?act=tb&amp;id=22&amp;key=fd4bc9da</trackback:ping></item><item><title>二种ring3下很是另类的DLL注入方式&amp;lt;能过大多数HIPS,AV的保护&amp;gt;</title><author>a@b.com (hbslover)</author><link>http://www.hb4.org/Article/dll_injection.htm</link><pubDate>Mon, 16 Nov 2009 20:16:04 +0800</pubDate><guid>http://www.hb4.org/Article/dll_injection.htm</guid><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 比如你想修改某些进程的内存,以前似乎有很多方式,但是由于病毒的猖獗,HIPS和AV等一些安全软件不得不HOOK掉相关的API</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当你修改内存时,一般HIPS都会弹窗提示你是否允许(当然你可以模拟点击过过它,但是这种方式实现不是那么完美)</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所以,导致咱们想修改一些进程的内存是比较难的,尤其是修改游戏的内存,当然这也是反外挂的手段啦~</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 然而,难道就没有方式去修改远程进程的内存了吗???no,如果没有的话??那么做外挂的靠什么吃饭???</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 据我所知:方法是有很多很多种的,当然,很多方式都会被拦截,所以这里不废话了,直接进入主题,我说要描述的是使用DLL注入,</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 而这两种方式目前能过市面大多数的HIPS,AV,我简要的描述一下,下面就直接上点代码</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一.输入法注入&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;虽然这种方式有一定局限性,目标程序不知道输入法就没法注入.而且必须两个DLL,一个是有输入法管理器来管理的后缀为.IME的,另一个是你邪恶的DLL</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当然,目前我相信绝大多数的支持中文的程序来讲,不支持输入法绝对是一种灾难这种方式对于做外挂来讲,是很爽快的一件事情.</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;因为游戏里面绝对会支持输入法的,聊天啊,什么的~经过我测试,可以顺利的注入一些有np,HIPS,AV保护的游戏进程</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当然,也注进冰刃,360等进程了,这个启发来自网上的火星文输入法,当然,网上关于火星文输入法的技术文中不在少数,我也不再罗嗦了!!!</p><p>&nbsp; &nbsp;&nbsp; 二:SPI注入&nbsp; (目前这种方式我还没测试过,没有发言权.不过,我测试过,腾讯的QQ医生就是依靠这种方式注入所有进程的)</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我在vckbase上找了一篇关于SPI的文章:http://www.vckbase.com/document/viewdoc/?id=643,有机会测试一下</p><p>&nbsp;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (这源码来自网上,报不报毒,别来找我,实在报毒,你自己修改源码)</p><p><a href="http://www.hb4.org/upload/2009/11/拦截并修改输入法.rar" target="_blank"><span style="font-size: large"><span style="color: #ff0000"><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;拦截并修改输入法.rar</strong></span></span></a></p>]]></description><category>{C/C++相关}</category><comments>http://www.hb4.org/Article/dll_injection.htm#comment</comments><wfw:comment>http://www.hb4.org/</wfw:comment><wfw:commentRss>http://www.hb4.org/feed.asp?cmt=10</wfw:commentRss><trackback:ping>http://www.hb4.org/cmd.asp?act=tb&amp;id=10&amp;key=60bd2022</trackback:ping></item><item><title>多任务超精小下载者,目前免杀-&amp;lt;源码&amp;gt;</title><author>a@b.com (hbslover)</author><link>http://www.hb4.org/Article/downloader_code.htm</link><pubDate>Fri, 13 Nov 2009 16:27:51 +0800</pubDate><guid>http://www.hb4.org/Article/downloader_code.htm</guid><description><![CDATA[<p><table style="width: 100%; table-layout: fixed">    <tbody>        <tr>            <td>            <div id="blog_text" class="cnt">            <p>无聊时写的,没有多少技术含量,5个任务,速度快,稳定.<br />            &nbsp;&nbsp;&nbsp;&nbsp; 生成的服务端超级精小,目前免杀,穿墙</p>            <p>===============================</p>            <p>&nbsp;<a target="_blank" href="http://hb4.org/upload/2009/11/200911131629347615.rar"><span style="color: #ff0000"><span style="font-size: medium"><strong>源码</strong></span></span></a></p>            </div>            </td>        </tr>    </tbody></table></p>]]></description><category>{C/C++相关}</category><comments>http://www.hb4.org/Article/downloader_code.htm#comment</comments><wfw:comment>http://www.hb4.org/</wfw:comment><wfw:commentRss>http://www.hb4.org/feed.asp?cmt=3</wfw:commentRss><trackback:ping>http://www.hb4.org/cmd.asp?act=tb&amp;id=3&amp;key=bfe53f1d</trackback:ping></item></channel></rss>
