设为首页收藏本站喵玉殿官方微博

 找回密码
 少女注册中
搜索
查看: 18497|回复: 12

[编程算法] FXTZ的控制流程。

  [复制链接]
发表于 2011-4-20 21:40:43 | 显示全部楼层 |阅读模式
本帖最后由 十二 于 2011-4-21 10:48 编辑

FXTZ的控制流程被包含在DirectInput中。虽然IAT中没有DirectInputCreate这样类似的助手函数(大部分程序IAT中都会导入d3d9.dll、dinput.dll其中会导入DirectInputCreate、Direct3DCreate9之类的助手函数。)方便返回接口的指针来方便调用。

以前一直以为所有的windows程序都是用windows消息循环来执行call back function来实现自定义的逻辑,直到主席提到dxinput,才改变了我的看法。

windows是以API为基础用消息来驱动的。但是消息并不只是WM_规范的这些,消息很广义可以为一个信号,也可以是一个值,这对程序流程而言都可以看做一个消息。并非只指WIN规范WM_消息。

从消息队列取走消息然后处理,效率是相当低下的所以DXinput出现了。

以上全是废话,下面进入正题。

FXTZ的IAT中并没有导入dinput.dll和其助手函数DirectInputCreate来得到IDirectInput接口的指针,(吐槽那你怎么知道用了dxinput)。

dx组件的调用并非必须用助手函数来得到接口指针,dx组件是基于COM的详见,http://bbs.nyasama.com/forum.php?mod=viewthread&tid=1887&extra=page%3D1

如果拥有组件的CLSID和IID可以通过CoCreateInstance函数来得到IDirectInput接口,很巧FXTZ就用的这种方法。

F3载入th123.exe

bp  CoCreateInstance

栈信息如下:



0012FB30处是CLSID可在注册表中找到。

0012FB3C处是IID可在 http://bbs.nyasama.com/forum.php?mod=viewthread&tid=1887&extra=page%3D1 此贴10L中的附件中找到

0012FB40处记录的指针0088D17C中就是IDirectInput8W接口的指针了。

Alt+F9返回。  

  1. 0040D20B  |.  85C0          TEST EAX,EAX
  2. 0040D20D  |.  7D 1E         JGE SHORT th123_汉.0040D22D
  3. 0040D20F  |.  8B0D 78D18800 MOV ECX,DWORD PTR DS:[88D178]
  4. 0040D215  |.  6A 00         PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL
  5. 0040D217  |.  68 D0E38500   PUSH th123_汉.0085E3D0                    ; |Title = "DInput-Error"
  6. 0040D21C  |.  68 80E38500   PUSH th123_汉.0085E380                    ; |Text = "DirectInput对象创建失败#0"
  7. 0040D221  |.  51            PUSH ECX                                 ; |hOwner = 002EAA64
  8. 0040D222  |.  FF15 4C628400 CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA
  9. 0040D228  |.  32C0          XOR AL,AL
  10. 0040D22A  |.  C2 0800       RETN 8
  11. 0040D22D  |>  A1 7CD18800   MOV EAX,DWORD PTR DS:[88D17C]
  12. 0040D232  |.  8B4C24 08     MOV ECX,DWORD PTR SS:[ESP+8]             ;  th123_汉.00400000
  13. 0040D236  |.  8B10          MOV EDX,DWORD PTR DS:[EAX]
  14. 0040D238  |.  8B52 1C       MOV EDX,DWORD PTR DS:[EDX+1C]
  15. 0040D23B  |.  68 00080000   PUSH 800
  16. 0040D240  |.  51            PUSH ECX
  17. 0040D241  |.  50            PUSH EAX
  18. 0040D242  |.  FFD2          CALL EDX
  19. 0040D244  |.  85C0          TEST EAX,EAX
  20. 0040D246  |.  7D 1D         JGE SHORT th123_汉.0040D265
  21. 0040D248  |.  A1 78D18800   MOV EAX,DWORD PTR DS:[88D178]
  22. 0040D24D  |.  6A 00         PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL
  23. 0040D24F  |.  68 D0E38500   PUSH th123_汉.0085E3D0                    ; |Title = "DInput-Error"
  24. 0040D254  |.  68 A8E38500   PUSH th123_汉.0085E3A8                    ; |Text = "DirectInput对象创建失败#1"
  25. 0040D259  |.  50            PUSH EAX                                 ; |hOwner = NULL
  26. 0040D25A  |.  FF15 4C628400 CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA
  27. 0040D260  |.  32C0          XOR AL,AL
  28. 0040D262  |.  C2 0800       RETN 8
  29. 0040D265  |>  B0 01         MOV AL,1
  30. 0040D267  \.  C2 0800       RETN 8

复制代码



可以看到会出现判断EAX的值来确定是否获得IDirectInput8接口指针。

0088D17C 中也返回了 IDirectInput8 的接口指针,右键数据跟随00126AA1C。



来到这里



再跟随一次。



这里就是 IDirectInput8接口下的方法了对照http://bbs.nyasama.com/forum.php?mod=viewthread&tid=1887&extra=page%3D1此贴10L中的附件

DECLARE_INTERFACE_(IDirectInput8W, IUnknown)
{
    /*** IUnknown methods ***/
    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
    STDMETHOD_(ULONG,Release)(THIS) PURE;

    /*** IDirectInput8W methods ***/
    STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICE8W *,LPUNKNOWN) PURE;
    STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKW,LPVOID,DWORD) PURE;
    STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE;
    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE;
    STDMETHOD(FindDevice)(THIS_ REFGUID,LPCWSTR,LPGUID) PURE;
    STDMETHOD(EnumDevicesBySemantics)(THIS_ LPCWSTR,LPDIACTIONFORMATW,LPDIENUMDEVICESBYSEMANTICSCBW,LPVOID,DWORD) PURE;
    STDMETHOD(ConfigureDevices)(THIS_ LPDICONFIGUREDEVICESCALLBACK,LPDICONFIGUREDEVICESPARAMSW,DWORD,LPVOID) PURE;
};

和上面的地址指针的顺序是一样的。

判断得到IDirectInput8后会调用Initialize进行初始化。然后会调用一个重要的方法。CreateDevice来得到LPDIRECTINPUTDEVICE8的接口指针。调试的时候别数错了同上一样跟踪。

顺道就全部贴出来了。

DECLARE_INTERFACE_(IDirectInputDevice8W, IUnknown)
{
    /*** IUnknown methods ***/
    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
    STDMETHOD_(ULONG,Release)(THIS) PURE;

    /*** IDirectInputDevice8W methods ***/
    STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE;
    STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW,LPVOID,DWORD) PURE;
    STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE;
    STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE;
    STDMETHOD(Acquire)(THIS) PURE;
    STDMETHOD(Unacquire)(THIS) PURE;
    STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE;
    STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
    STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE;
    STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE;
    STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE;
    STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW,DWORD,DWORD) PURE;
    STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW) PURE;
    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE;
    STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE;
    STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKW,LPVOID,DWORD) PURE;
    STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOW,REFGUID) PURE;
    STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE;
    STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE;
    STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE;
    STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE;
    STDMETHOD(Poll)(THIS) PURE;
    STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
    STDMETHOD(EnumEffectsInFile)(THIS_ LPCWSTR,LPDIENUMEFFECTSINFILECALLBACK,LPVOID,DWORD) PURE;
    STDMETHOD(WriteEffectToFile)(THIS_ LPCWSTR,DWORD,LPDIFILEEFFECT,DWORD) PURE;
    STDMETHOD(BuildActionMap)(THIS_ LPDIACTIONFORMATW,LPCWSTR,DWORD) PURE;
    STDMETHOD(SetActionMap)(THIS_ LPDIACTIONFORMATW,LPCWSTR,DWORD) PURE;
    STDMETHOD(GetImageInfo)(THIS_ LPDIDEVICEIMAGEINFOHEADERW) PURE;
};

可以看到这下面有很多方法,想折腾的人可以去MSDN找原型,或者去百度找找DXinput的具体流程,这里不熬述。

这里有两个重要的方法GetDeviceState,GetDeviceData。这两个函数是把键盘数据送给缓冲区然后做为消息让FXTZ实现键盘按键后的游戏逻辑。

FXTZ没有用GetDeviceData,因为格斗游戏要求即使操作,所以用GetDeviceState来得到即时缓冲。

断到GetDeviceState方法内部。

发表于 2011-4-20 22:41:30 | 显示全部楼层
QAQ這是FXTZ的運行原理麼...
回复

使用道具 举报

 楼主| 发表于 2011-4-20 22:46:59 | 显示全部楼层
紅魔の月時計 发表于 2011-4-20 22:41
QAQ這是FXTZ的運行原理麼...

并不全是见最后一句话。而且后面的具体流程也没贴。

点评

程序項目什麼的真的很要命啊QAQ  发表于 2011-4-20 22:51
回复

使用道具 举报

发表于 2011-4-20 23:27:34 | 显示全部楼层
我想说有的图挂了
能贴多一次么
回复

使用道具 举报

 楼主| 发表于 2011-4-21 10:50:16 | 显示全部楼层
本帖最后由 十二 于 2011-4-21 10:55 编辑


可以看到栈信息:


回复

使用道具 举报

 楼主| 发表于 2011-4-21 10:55:46 | 显示全部楼层
跟踪0088D198



可以看到GetDeviceState指向了一个256字节的0区空间。

然后F9还是会断在这里,几乎游戏的每一帧都会断下。根本没有办法按FXTZ按键来看这里的变化。(这里怎么办?)

取消断点F9运行,然后拿出你的CE,用CE打开你得FXTZ进程。

然后内存浏览来到0088D198处。然后切回你的FXTZ。按住Z可以看到0088D1C4处被填充80。但是有时按了却不被填充。

但是为什么是按住了就填充了0x80,为了确认是否和键盘同步更新buffer数据,在OD来证明。

关掉CE切回OD 在 731C69DD    8BFF            MOV EDI,EDI  这句下条件断点。

Shift+F2写入[0088D1C4]==80点击确定,然后发现程序还是在运行中的。这时候回到FXTZ按下Z。程序被断下,0088D1C4被填入0x80。Alt+F9返回可以看到程序接到0088D1C4=0x80更改相应的游戏流程。

当然还有相应问题,是什么来调用GetDeviceState来检测键盘数据的,是SetTimer还是Event ?  
回复

使用道具 举报

发表于 2011-4-21 11:13:29 | 显示全部楼层
看到十二神触的帖子我又内牛满面了
回复

使用道具 举报

发表于 2011-4-21 11:35:07 | 显示全部楼层
太专业了
各种看不懂

点评

+1  发表于 2011-4-23 12:35
回复

使用道具 举报

 楼主| 发表于 2011-4-21 11:41:02 | 显示全部楼层
渣包一个如有纰漏还望见谅。顺便求解SetTimer下的Timerproc始终指向NULL

如果是Event,渣包不甚了解。

望各神触跟帖指教,FXTZ的GetDeviceState调用循环

回复

使用道具 举报

发表于 2011-4-24 15:29:15 | 显示全部楼层
本帖最后由 pa001024 于 2011-5-3 21:30 编辑

疯了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 少女注册中

本版积分规则

合作与事务联系|无图版|手机版|小黑屋|喵玉殿

GMT+8, 2025-10-31 11:37

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表