首先说,这篇文章是很久以前为了玩成某游戏的HOOK找到的资料,虽然一直没用上,但是还是让我保留下来了。直接贴上了。。看不懂也不要问我,我都没看。

也许看得懂的人对他们来说这是一个思路,不懂的就当垃圾文不看就好。。

我们要想拥有自己的窗口,那么就必须在诸仙的进程启动之前得到Direct3DCreate8接口(诸仙用Direct3D8)。所以启动过程如下:

//启动诸仙并获取诸仙进程句柄
ZhuXianProc.OpenExe("C:\\游戏目录\\诛仙\\element\\elementclient.exe");
if(!ZhuXianProc.GetProcess())
{
MessageBox(NULL,
" 无法正常启动《诸仙》主程序\n\n获取帮助请与本工作室技术人员联系",
"天涯工作室程序运行错误提示!",MB_OK);
return TRUE;
}
//在程序运行之前先HOOK住所需要HOOK的API
HookApi("C:\\游戏目录\\诛仙\\element\\elementclient.exe","C:\\游戏目录\\诛仙\\element\\ZxDll.dll");
ZhuXianFunc();
ZhuXianProc.CloseAllHandle();

关于ZhuXianProc是一个CGetProc类型,这个类主要是打开进程和取得进程的一些信息,GetProcess()取的改进程的句柄。这个类里面要解释下的是:

void CGetProc::OpenExe(CString str)
{
memset(&si,0,sizeof(si));
si.cb=sizeof(si);
si.wShowWindow=SW_SHOW;
si.dwFlags=STARTF_USESHOWWINDOW;
CreateProcess(str,NULL,NULL,FALSE,NULL,Create_SUSPENDED,NULL,NULL,&si,&pi);
} 

“Create_SUSPENDED”指明该进程并不是一开始就让他运行,原因是我们要想得到Direct3DCreate8接口就必须在运行进程之前注入我们的DLL,并让我们的DLL里的HOOK Direct3DCreate8接口跑到他的初始化之前。

我们来看看HookApi()的内容:

bool CUIThread::HookApi(char* pszFileExe,char* pszFileDll)
{ //让程序启动的时候JMP到自己的DLL中去
HANDLE hProcess = ZhuXianProc.GetProcess();
// 在目标进程申请空间,存放字符串pszDllName,作为远程线程的参数
int cbSize = (strlen(pszFileDll) + 1);
LPVOID lpRemoteDllName = ::VirtualAllocEx(hProcess, NULL, cbSize, MEM_COMMIT, PAGE_READWRITE);
::WriteProcessMemory(hProcess, lpRemoteDllName, pszFileDll, cbSize, NULL);
// 取得LoadLibraryA函数的地址,我们将以它作为远程线程函数启动
HMODULE hModule=::GetModuleHandle ("kernel32.dll");
LPTHREAD_START_ROUTINE pfnStartRoutine = (LPTHREAD_START_ROUTINE)::GetProcAddress(hModule, "LoadLibraryA");
// 启动远程线程
::ResumeThread(ZhuXianProc.GetThread());
HANDLE hRemoteThread = ::CreateRemoteThread(hProcess, NULL, 0, pfnStartRoutine, lpRemoteDllName, 0, NULL);
if(hRemoteThread == NULL)
{ ::CloseHandle(hProcess); return FALSE;
}
::CloseHandle(hRemoteThread);
return TRUE;
}

这段关键是在:

// 启动远程线程
::ResumeThread(ZhuXianProc.GetThread());
HANDLE hRemoteThread = ::CreateRemoteThread(hProcess, NULL, 0, pfnStartRoutine, lpRemoteDllName, 0, NULL);

必须这样,ResumeThread诸仙进程之后立即启动我们的DLL。呵呵,也不能弄反,如果进程没启动,我们注入的DLL就启动了,进程可能就崩溃了。 在这里有个小技巧,诸仙进程启动不代表就立即进行Direct3DCreate8初始化,他还有些事情要做,到他初始化的时候我们的DLL早就跑了一段了:)。

3.来看看我们的重点,我们注入的ZXDLL.DLL到底做了些什么事情。

#pragma comment(lib, "d3d8.lib")
// CZxDllAppBEGIN_MESSAGE_MAP(CZxDllApp, CWinApp)
END_MESSAGE_MAP()
// CZxDllApp 构造CZxDllApp::CZxDllApp()
{// TODO: 在此处添加构造代码,// 将所有重要的初始化放置在 InitInstance 中
}// 唯一的一个 CZxDllApp 对象
CZxDllApp theApp;CAPIHook hookapi2("d3d8.dll","Direct3DCreate8",(PROC)NewDirect3DCreate8);
// CZxDllApp 初始化BOOL CZxDllApp::InitInstance()
{CWinApp::InitInstance();return TRUE;
}

看完DLL的这一段小程序,基本上是VC向导完成的,只有一句:
CAPIHook hookapi2("d3d8.dll","Direct3DCreate8",(PROC)NewDirect3DCreate8);
这句在DLL一运行的时候他就运行了,并把Direct3DCreate8给变成了新的入口地址NewDirect3DCreate8了,那么当诸仙运行的时候这个函数就跑到我们的NewDirect3DCreate8里来了,呵呵,正好,我们抓住了Direct3DCreate8接口了,来我们一起看看NewDirect3DCreate8函数里的内容。

IDirect3D8 * WINAPI NewDirect3DCreate8(UINT SDKVersion)
{static int count = 0;static IDirect3D8* test = NULL;hookapi2.Unhook();IDirect3D8 * m = Direct3DCreate8(SDKVersion);hookapi2.Rehook();//程序一共3个3维平面驱动count++;if(count==2){//1,窗口模式请用2,全屏模式请用3lpD3D = m;//替换VTable,实现对IDirect3Draw 的 COM接口的挂钩NewlpD3d = new MyIDirect3D8;m = (IDirect3D8*)NewlpD3d;}return m;
}

呵呵,诸仙对IDirect3D8接口其实是驱动了3次,我没查出来第一次是干什么的,但是后两次一个是在窗口模式下用的,一个是在全屏模式下用的。光得到IDirect3D8接口是没用的这里我们还要进行COM HOOK 获得Direct3DDevice8(D3D 设备) 的接口的指针从而得到我们的Render该放到什么地方。
COM HOOK其实就是写一个同样的类用来替换COM的VTable,不做详细的解释,实在搞不懂就google(俺也是这么得来的:))。MyIDirect3D8就是一个新的IDirect3D8类,他是从IDirect3D8继承来的,定义如下:

class MyIDirect3D8 : public IDirect3D8
{
public:HRESULT APIENTRY QueryInterface(REFIID riid, void** ppvObj);ULONG APIENTRY AddRef();ULONG APIENTRY Release();/*** IDirect3D8 methods ***/HRESULT APIENTRY RegisterSoftwareDevice(void* pInitializeFunction);UINT APIENTRY  GetAdapterCount();HRESULT APIENTRY GetAdapterIdentifier(UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER8* pIdentifier);UINT APIENTRY  GetAdapterModeCount(UINT Adapter);HRESULT APIENTRY EnumAdapterModes(UINT Adapter,UINT Mode,D3DDISPLAYMODE* pMode);HRESULT APIENTRY GetAdapterDisplayMode(UINT Adapter,D3DDISPLAYMODE* pMode);HRESULT APIENTRY CheckDeviceType(UINT Adapter,D3DDEVTYPE CheckType,D3DFORMAT DisplayFormat,D3DFORMAT BackBufferFormat,BOOL Windowed);HRESULT APIENTRY CheckDeviceFormat(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat);HRESULT APIENTRY CheckDeviceMultiSampleType(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType);HRESULT APIENTRY CheckDepthStencilMatch(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat);HRESULT APIENTRY GetDeviceCaps(UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS8* pCaps);HMONITOR APIENTRY  GetAdapterMonitor(UINT Adapter);HRESULT APIENTRY CreateDevice(UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice8** ppReturnedDeviceInterface);MyIDirect3D8(void);IDirect3D8 * lpD3D;IDirect3DDevice8 * lpD3DD8;IDirect3DDevice8 * lpD3DD8bak;ULONG m_count;
};

pGame就是我们的外挂的主类包括界面处理等等,在下一点讲解。 IpD3DDevice是Direct3DDevice8(D3D 设备) 的接口的指针,我们也要想办法解决,不急,等下慢慢说。

替换VTable其实很简单,我们只需要new一个我们自己的的MyIDirect3D8把老的IDirect3D8的指针内容直接替换就行了,呵呵:

//替换VTable,实现对IDirect3Draw 的 COM接口的挂钩
NewlpD3d = new MyIDirect3D8;
m = (IDirect3D8*)NewlpD3d;Direct3DDevice8(D3D 设备) 的接口的指针是在IDirect3D8里面Create的我们再看看MyIDirect3D8的CreateDevice函数如何定义:HRESULT APIENTRY MyIDirect3D8::CreateDevice(UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice8** ppReturnedDeviceInterface)
{static MyIDirect3DDevice8 * id3dd8 = NULL;HRESULT m = lpD3D->CreateDevice(Adapter,DeviceType,hFocusWindow,BehaviorFlags,pPresentationParameters,ppReturnedDeviceInterface);lpD3DD8 = *ppReturnedDeviceInterface;//Hook IDirect3DDevice8::ShowWindow(hFocusWindow,SW_HIDE);lpD3D->CreateDevice(Adapter,DeviceType,hFocusWindow,BehaviorFlags,pPresentationParameters,&lpD3DD8bak); ::ShowWindow(hFocusWindow,SW_SHOW);::SetFocus(hFocusWindow);id3dd8 = new MyIDirect3DDevice8(lpD3DD8bak);*ppReturnedDeviceInterface = (IDirect3DDevice8*)id3dd8;return m;
}

至于::ShowWindow(hFocusWindow,SW_HIDE);初始化后::ShowWindow(hFocusWindow,SW_SHOW);保证进程不挂,呵呵。
IDirect3DDevice8要想得到IDirect3DDevice8的里面的内容,我们也采用同样方法的偷粱换柱子。MyIDirect3DDevice8定义就不再贴出来了,浪费页面。要解释下的地方是

HRESULT APIENTRY MyIDirect3DDevice8::BeginScene()
{return g_pD3DDevice->BeginScene();
}HRESULT APIENTRY MyIDirect3DDevice8::EndScene()
{if(pGame!=NULL) pGame->Render();return g_pD3DDevice->EndScene();
}

我们的画图函数按道理讲要放到BeginScene()之后,但是我们不是写自己的3D游戏,而是在做外挂,
程序是这么处理的:
别人调用BeginScene();
别人Render();
别人调用EndScene();
看看这个,我们把自己的pGame->Render();放到MyIDirect3DDevice8::BeginScene()里,结果就是自己的画图全被别人的图覆盖了,所有选择放到MyIDirect3DDevice8::EndScene()里去。
到这里我们从诸仙得到的东西已经能满足我们的需求了,那我们就专心的干我们的事情吧,做外挂界面吧。

转载于:https://www.cnblogs.com/briny/p/3265188.html

[转] Windows下Hook DirectX相关推荐

  1. Windows下Hook API技术

    Windows下Hook API技术 什么叫Hook API?所谓Hook就是钩子的意思,而API是指Windows开放给程序员的编程接口,使得在用户级别下可以对操作系统进行控制,也就是一般的应用程序 ...

  2. Windows下Hook API技术小结 (转)

    1.基本概念 钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的.当消息到达后,在目标窗口处理函数之前 ...

  3. C/C++:Windows编程—Hook IE浏览器实现URL拦截及更改(下)

    Hook IE浏览器实现URL拦截及更改(下) 前言 接上一篇 C/C++:Windows编程-Hook IE浏览器实现URL拦截及更改(上),本节为了实现上一篇待优化部分.实现IE进程时时监控,当有 ...

  4. Windows下x86和x64平台的Inline Hook介绍

    原文链接:https://blog.csdn.net/PeaZomboss/article/details/129095200?spm=1001.2014.3001.5501 前言 我在之前研究文明6 ...

  5. 在Windows下使用MinGW静态编译Assimp

    使用MinGW静态编译Assimp 到了5月份了,没有写一篇日志,于是自己从知识库里面拿出一篇文章充数吧.这次将要解说怎样在Windows下使用MinGW静态编译Assimp. Assimp是眼下比較 ...

  6. windows下捕获dump

    一般要捕获异常只需要两个函数:SetUnhandledExceptionFilter截获异常:MiniDumpWriteDump写dump文件.但是由于CRT函数可能会在内部调用SetUnhandle ...

  7. Windows下使用apache模块实现合并多个js、css提高网页加载速度

    这篇文章主要介绍了Windows下使用apache模块实现合并多个js.css提高网页加载速度,本文使用的模块是基于mod_concat自己修改的,需要的朋友可以参考下 现在的网站表现力越来越丰富,页 ...

  8. Windows 下的 7 种 DLL 劫持技术

    本文讲的是Windows 下的 7 种 DLL 劫持技术,在本文中,我将列出半打可以在Windows运行用户模式的进程中使用DLL注入技术.也许可能会有更多类似的技术,但我正在和你分享的是我所拥有的第 ...

  9. 用CMD开启Windows下的服务命令 转载

    用CMD开启Windows下的服务命令   CMD运行指令   开始→运行→CMD→键入以下命令即可:   gpedit.msc-----组策略 sndrec32-------录音机   Nslook ...

最新文章

  1. 爱好历史的程序员,不容错过!
  2. 【转】日邮物流:实现智慧物流,这个云上对了!
  3. 9511王锋刘婧捐100万元,支持中国科大计算机学院
  4. native react 更新机制_React Native - 组件的生命周期详解(附:各阶段调用的方法)...
  5. 【clickhouse】BAT 都在追捧的 ClickHouse ,到底有多快 笔记
  6. 用Tensorflow基于Deep Q Learning DQN 玩Flappy Bird
  7. 解决Linux下使用QQ的问题
  8. 水准网测量平差matlab_基于MATLAB的测量平差计算
  9. 【C语言练习——打印空心下三角及其变形】
  10. 笔记本电脑Haswell黑苹果opencore睡眠实战
  11. 输入框字母自动转换大写
  12. wireshark常用筛选命令
  13. 短链接服务架构设计概览
  14. 使用MAC中碰到的各种问题
  15. C++基础知识 —— 内存分区模型、引用、函数重载、类和继承、this指针、友元、多态、文件操作
  16. wps2019数据分析加载项_《07版office办公软件中的excle中,为什么在加载项里选择了分析工具库,数据分析还是显示不出来?》 wps数据分析加载项...
  17. pvpgn mysql d2gs_pvpgn战网命令集
  18. js 获取数组最后一个元素
  19. 防止表单重复提交方法
  20. tomcat(非安装版) 服务不能启动但是startup 却可以启动的问题

热门文章

  1. python时分秒_python时间时分秒与秒数的互相转换
  2. 冷暖自知!4年Java小伙收获美团Offer,分享他的社招Java岗4面面经
  3. Hadoop学习之SSH免密登录配置(以三台虚拟机为例,完全分布式)
  4. 教育网校搭建哪个好?
  5. 2022年进口葡萄酒市场分析
  6. Java解析XML的一些个人总结及感悟。(webService、xml、xsd)
  7. 改善技术简历的47条原则
  8. 人工智能——搜索策论2
  9. 采用简化原型法进行软件项目需求分析
  10. 学习笔记1-归一化与标准化