最近学习了下DLL注入,是通过hook方式来注入的。暂且不扯,新建个MFC dll,let's go。
首先得需要几个函数:
HHOOK SetWindowsHookEx(
int idHook, //要安装的钩子类型 (参考下面的IdHook取值)
HOOKPROC lpfn, //钩子过程的指针 ,也即拦截到指定系统消息后的预处理过程,须定义在DLL中,
HINSTANCE hMod, //应用程序实例的句柄 如果是全局钩子, hInstance是DLL句柄(DllMain中给的模块地址。就是包含HookProc的动态库加载地址。否则给0就可以了,即勾自己。
DWORD dwThreadId; //要安装钩子的线程ID ,指定被监视的线程,如果明确指定了某个线程的ID就只监视该线程,此时的钩子即为线程钩子;如果该参数被设置为0,则表示此钩子为监视系统所有线程的全局钩子。);
LRESULT CALLBACK HookProc(int nCode,WPARAM wParam,LPARAM lParam)//钩子回调函数
FindWindow(lpClassName,lpWindowName: PChar)//查找窗体
GetWindowThreadProcessId(hWnd: HWND,lpdwProcessId)//获取线程id/
且看回调函数:
- LRESULT CALLBACK HookProc(int nCode,WPARAM wParam,LPARAM lParam)
- {AFX_MANAGE_STATE(AfxGetStaticModuleState());
- //显示窗口
- if(wParam==VK_HOME && ((lParam&(1<<31))==0))
- {
- if(gameDlg==NULL)
- {
- dlg=new DLG;
- //这里是根据窗体资源的ID来创建窗体
- dlg->Create(IDD_DLG);
- }
- dlg->ShowWindow(true);
- //::AfxMessageBox("home按下");
- }
- //隐藏窗口
- if(wParam==VK_END && ((lParam&(1<<31))==0))
- {
- gameDlg->ShowWindow(false);
- }
- return CallNextHookEx(0,nCode,wParam,lParam);
- }
在这里当按下home建的时候回弹出个窗体,那么还需要在dll工程中插入窗体资源,就不在阐述了。
窗体资源创建好后,关联类,然后在dll.cpp中导入窗体关联的类的头文件:
#include "DLG.h"
DLG *dlg;
安装钩子函数,这里我们hook的是计算器
- void setHook()
- {AFX_MANAGE_STATE(AfxGetStaticModuleState());
- HWND hw=::FindWindow(NULL,"计算器");
- if(hw==0)
- {
- ::AfxMessageBox("查找窗口失败");
- }
- DWORD threadId=::GetWindowThreadProcessId(hw,NULL);
- if(threadId==0)
- {
- ::AfxMessageBox("获取线程失败");
- }
- ::SetWindowsHookEx(WH_KEYBOARD,HookProc,::GetModuleHandle("dll_dlg.dll"),threadId); //关键
- }
当dll中插入窗体资源时,在被hook对象中显示出窗体时,如果关闭了注入的程序,那么被注入的程序就会崩溃退出,原因是退出的时候没有清理创建窗体时申请的资源。
重写ExitInstance()
- int CDll_dlgApp::ExitInstance()
- {
- delete dlg;
- dlg=NULL;
- return CWinApp::ExitInstance();
- }
如果发现编译出错,说是ExitInstance没定义,需要在头文件中定义一下ExitInstance即可。如果需要设定哪些函数可以被其他对象调用,可以在dll.def中带出要被调用的函数:setHook;那么setHook就是我们希望被调用的函数
dll程序就这些,下面看下注入程序exe。
在注入程序中需要将dll编译生成的dll.dll和dll.lib文件复制到注入文件的工程目录里面,然后在注入文件中导入:
#pragma comment(lib,"dlg.lib");
__declspec(dllexport) void setHook();
然后在某个地方调用setHook()即可,效果如图所示: