wn32拦截ExtTextOut屏幕取词

来源:互联网 发布:three.js全景图的原理 编辑:程序博客网 时间:2024/05/20 17:25

在windows下,要实现屏幕取词,可以通过拦截 ExtTextOutA,ExtTextOutW,TextOutA,TextOutW,这4个API来实现,另外4个DrawTextExA,DrawTextExW,DrawTextA,DrawTextW 貌似是调用前面4个去实现的,具体我没有去验证过。


本文示例为通过拦截 ExtTextOutW 这个API可以实现屏幕取词的部分功能。

它的函数定义为:

BOOL  WINAPI ExtTextOutW(HDC hdc, int x, int y, UINT options, CONST RECT * lprect, LPCWSTR lpString, UINT c, CONST INT * lpDx);

其中lpString参数包含了字符串地址信息,我们只需要到目标进程拦截这个API,然后读取lpString里面的字符数据,然后显示到一个文本框里面,就行了。


要实现这个功能,需要做两件事:

1. 安装一个全局鼠标钩子,拦截WM_MOUSEMOVE消息。

2. 如果检查到鼠标在屏幕的某处停留时间超过1秒,则在鼠标所在的窗口进程挂上API钩子,取得所需信息后,立即摘掉API钩子。


注意该程序必须在Release版本下运行,如果是DeBug版本的话,因为编译器没做优化和加了一些debug代码,所以会内存读写报错

===========================================

下面是生成mousehook.dll的代码:

// dllmain.cpp : 定义 DLL 的初始化例程。//#include "stdafx.h"#include <afxwin.h>#include <afxdllx.h>#include "MyMouseHook.h"#ifdef _DEBUG#define new DEBUG_NEW#endifextern HINSTANCE hInstanceHook;static AFX_EXTENSION_MODULE MouseHookDLL = { NULL, NULL };extern "C" int APIENTRYDllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved){// 如果使用 lpReserved,请将此移除UNREFERENCED_PARAMETER(lpReserved);if (dwReason == DLL_PROCESS_ATTACH){TRACE0("MouseHook.DLL 正在初始化!\n");// 扩展 DLL 一次性初始化if (!AfxInitExtensionModule(MouseHookDLL, hInstance))return 0;// 将此 DLL 插入到资源链中// 注意: 如果此扩展 DLL 由//  MFC 规则 DLL (如 ActiveX 控件)隐式链接到,//  而不是由 MFC 应用程序链接到,则需要//  将此行从 DllMain 中移除并将其放置在一个//  从此扩展 DLL 导出的单独的函数中。使用此扩展 DLL 的//  规则 DLL 然后应显式//  调用该函数以初始化此扩展 DLL。否则,//  CDynLinkLibrary 对象不会附加到//  规则 DLL 的资源链,并将导致严重的//  问题。new CDynLinkLibrary(MouseHookDLL);hInstanceHook=hInstance;//WM_MY_MOUSEMOVE=RegisterWindowMessage(WM_MY_MOUSEMOVE_MSG);}else if (dwReason == DLL_PROCESS_DETACH){TRACE0("MouseHook.DLL 正在终止!\n");// 在调用析构函数之前终止该库AfxTermExtensionModule(MouseHookDLL);}return 1;   // 确定}


//MyMouseHook.h//#pragma once#define WM_MY_MOUSEMOVE (WM_USER+10)// CMyMoueHook 命令目标class AFX_EXT_CLASS CMyMouseHook : public CObject{public:CMyMouseHook();virtual ~CMyMouseHook();public:BOOL StartHook(HWND hWnd); //安装钩子函数BOOL StopHook(HWND hWnd); //卸载钩子函数};


// MyMoueHook.cpp : 实现文件//#include "stdafx.h"#include "MyMouseHook.h"#pragma data_seg("mydata")HWND hWnd_Mouse=NULL; //设置需要捕获鼠标消息的窗口句柄,即所有鼠标消息都会另外发送一份消息到该窗口#pragma data_seg()#pragma comment(linker,"/SECTION:mydata,RWS")HHOOK hHook=NULL; //鼠标钩子句柄HINSTANCE hInstanceHook=NULL; //插入保存DLL实例句柄extern "C" LRESULT WINAPI MouseProc(int nCode, WPARAM wParam, LPARAM lParam){if(nCode < 0){ CallNextHookEx(hHook, nCode, wParam, lParam); return 0;}if(nCode>=0){LPMSG msg=(LPMSG)lParam;if(msg->message==WM_MOUSEMOVE || msg->message==WM_NCMOUSEMOVE){PostMessage(hWnd_Mouse, WM_MY_MOUSEMOVE, 0, 0);//PostMessage(hWnd_Mouse, WM_MOUSEMOVE, 0, 0);}}return CallNextHookEx(hHook,nCode,wParam,lParam); //继续传递钩子信息}// CMyMoueHookCMyMouseHook::CMyMouseHook(){}CMyMouseHook::~CMyMouseHook(){//StopHook();}// CMyMoueHook 成员函数BOOL CMyMouseHook::StartHook(HWND hWnd){if(hHook==NULL){hHook=SetWindowsHookExW(WH_GETMESSAGE,(HOOKPROC)MouseProc,hInstanceHook,0);if(hHook!=NULL){hWnd_Mouse=hWnd; //设置需要捕获鼠标消息的窗口句柄return TRUE;}}else{if(hWnd_Mouse!=NULL){if(hWnd_Mouse==hWnd){return FALSE; //该窗口句柄已经hook了}else{hWnd_Mouse=hWnd; //设置需要捕获鼠标消息的窗口句柄,这样将会覆盖前一个句柄return TRUE;}}}return FALSE; //failed to set hook}BOOL CMyMouseHook::StopHook(HWND hWnd){if(hWnd!=hWnd_Mouse || hWnd==NULL){return FALSE;}BOOL bResult=UnhookWindowsHookEx(hHook);if(bResult){hWnd_Mouse=NULL;hHook=NULL;}return bResult;}

==========================

下面是实现屏幕取词的代码:

// pingmuquciDlg.h : 头文件//#pragma once#include "afxwin.h"#include "../mousehook/MyMouseHook.h"#define WM_HOOK_TEXTOUT (WM_USER+101)typedef struct _RemoteParam{DWORD dwTextOut;DWORD dwExtTextOut;DWORD dwPostMessage;DWORD dwSendMessage;DWORD dwGetCurrentProcess;DWORD dwWriteProcessMemory;DWORD dwMessageBox;unsigned char oldCode[10];unsigned char newCode[10];DWORD FunAddr;BOOL bHookAlready; //是否挂上API钩子HWND hwnd; //安放钩子的那个窗口句柄LPCWSTR lpString; //专门用于保存TextOut的字符串地址wchar_t info[260];} RemoteParam, * pRemoteParam;// CpingmuquciDlg 对话框class CpingmuquciDlg : public CDialogEx{// 构造public:CpingmuquciDlg(CWnd* pParent = NULL);// 标准构造函数// 对话框数据enum { IDD = IDD_PINGMUQUCI_DIALOG };protected:virtual void DoDataExchange(CDataExchange* pDX);// DDX/DDV 支持// 实现protected:HICON m_hIcon;// 生成的消息映射函数virtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();DECLARE_MESSAGE_MAP()public:CMyMouseHook m_mouse_hook;CEdit m_edit;BOOL is_quci_open;CString m_edit_str;HWND m_hwnd_hook;BOOL bHookAlready; //是否挂钩子的标志unsigned char oldcode[10]; //用来保存API的原始代码    unsigned char newcode[10]; //用来保存API修改后的代码DWORD dwFunAddr;DWORD dwPramaAddr;HANDLE m_hProcess;DWORD m_dwProcessId;int size_Func;int size_Pramam;RemoteParam m_RParam;public:BOOL enableDebugPriv(); //提升进程访问权限DWORD processNameToId(LPCTSTR lpszProcessName); //根据进程名称得到进程ID,如果有多个运行实例的话,返回第一个枚举到的进程的IDBOOL ClearHook(HANDLE hProcess); //清理钩子代码BOOL HookOn(HANDLE hProcess); //挂上API钩子BOOL HookOff(HANDLE hProcess); //摘掉API钩子BOOL InitHook(HANDLE hProcess); //初始化API钩子public:afx_msg void OnBnClickedButton1(); //开启屏幕取词afx_msg void OnBnClickedButton2(); //关闭屏幕取词afx_msg void OnTimer(UINT_PTR nIDEvent);protected:afx_msg LRESULT OnHookTextout(WPARAM wParam, LPARAM lParam);afx_msg LRESULT OnMyMousemove(WPARAM wParam, LPARAM lParam);};

////拦截 ExtTextOut(...),并实现一个粗糙的屏幕取词功能////作者:过客      //邮箱:386520874@qq.com      //日期:2014.04.27//// pingmuquciDlg.cpp : 实现文件//#include "stdafx.h"#include "pingmuquci.h"#include "pingmuquciDlg.h"#include "afxdialogex.h"#include <TlHelp32.h>#ifdef _DEBUG#define new DEBUG_NEW#endif#define TIME_ID_1 1#pragma comment(lib,"../Debug/mousehook.lib")// 用于应用程序“关于”菜单项的 CAboutDlg 对话框class CAboutDlg : public CDialogEx{public:CAboutDlg();// 对话框数据enum { IDD = IDD_ABOUTBOX };protected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持// 实现protected:DECLARE_MESSAGE_MAP()};CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD){}void CAboutDlg::DoDataExchange(CDataExchange* pDX){CDialogEx::DoDataExchange(pDX);}BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)END_MESSAGE_MAP()// CpingmuquciDlg 对话框CpingmuquciDlg::CpingmuquciDlg(CWnd* pParent /*=NULL*/): CDialogEx(CpingmuquciDlg::IDD, pParent){m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);is_quci_open=FALSE;m_edit_str=_T("");m_hwnd_hook=NULL;bHookAlready=FALSE;dwFunAddr=NULL;dwPramaAddr=NULL;m_hProcess=NULL;m_dwProcessId=NULL;size_Func=0;size_Pramam=0;::memset(oldcode,0,10);::memset(newcode,0,10);}void CpingmuquciDlg::DoDataExchange(CDataExchange* pDX){CDialogEx::DoDataExchange(pDX);DDX_Control(pDX, IDC_EDIT1, m_edit);}BEGIN_MESSAGE_MAP(CpingmuquciDlg, CDialogEx)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_BUTTON1, &CpingmuquciDlg::OnBnClickedButton1)ON_BN_CLICKED(IDC_BUTTON2, &CpingmuquciDlg::OnBnClickedButton2)ON_MESSAGE(WM_HOOK_TEXTOUT, &CpingmuquciDlg::OnHookTextout)ON_WM_TIMER()ON_MESSAGE(WM_MY_MOUSEMOVE, &CpingmuquciDlg::OnMyMousemove)END_MESSAGE_MAP()// CpingmuquciDlg 消息处理程序BOOL CpingmuquciDlg::OnInitDialog(){CDialogEx::OnInitDialog();// 将“关于...”菜单项添加到系统菜单中。// IDM_ABOUTBOX 必须在系统命令范围内。ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){BOOL bNameValid;CString strAboutMenu;bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);ASSERT(bNameValid);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动//  执行此操作SetIcon(m_hIcon, TRUE);// 设置大图标SetIcon(m_hIcon, FALSE);// 设置小图标// TODO: 在此添加额外的初始化代码return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE}void CpingmuquciDlg::OnSysCommand(UINT nID, LPARAM lParam){if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialogEx::OnSysCommand(nID, lParam);}}// 如果向对话框添加最小化按钮,则需要下面的代码//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,//  这将由框架自动完成。void CpingmuquciDlg::OnPaint(){if (IsIconic()){CPaintDC dc(this); // 用于绘制的设备上下文SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);// 使图标在工作区矩形中居中int cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// 绘制图标dc.DrawIcon(x, y, m_hIcon);}else{CDialogEx::OnPaint();}}//当用户拖动最小化窗口时系统调用此函数取得光标//显示。HCURSOR CpingmuquciDlg::OnQueryDragIcon(){return static_cast<HCURSOR>(m_hIcon);}//==========================================================================//typedef HANDLE (__stdcall * PFN_CREATEFILE)(LPCWSTR,DWORD,DWORD,LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE);typedef int (__stdcall * PFN_MESSAGEBOX)(HWND, LPCWSTR, LPCWSTR, DWORD);typedef BOOL (__stdcall * PFN_WRITEPROCESSMEMORY)(HANDLE,LPVOID,LPCVOID,SIZE_T,SIZE_T*);typedef HANDLE (__stdcall * PFN_GETCURRENTPROCESS)(void);//typedef BOOL (__stdcall * PFN_TEXTOUT)(HDC, int, int, LPCSTR, int);typedef BOOL (__stdcall * PFN_TEXTOUT)(HDC, int, int, LPCWSTR, int);//typedef BOOL (__stdcall * PFN_EXTTEXTOUT)(HDC, int, int, UINT, CONST RECT*, LPCSTR, UINT, CONST INT*);typedef BOOL (__stdcall * PFN_EXTTEXTOUT)(HDC, int, int, UINT, CONST RECT*, LPCWSTR, UINT, CONST INT*);typedef BOOL (__stdcall * PFN_POSTMESSAGE)(HWND, UINT, WPARAM, LPARAM);typedef BOOL (__stdcall * PFN_SENDMESSAGE)(HWND, UINT, WPARAM, LPARAM);typedef int (__stdcall * PFN_MESSAGEBOX)(HWND, LPCWSTR, LPCWSTR, DWORD);void HookTextOut(LPVOID lParam){RemoteParam* pRP=(RemoteParam*)lParam;        DWORD dwParamaAddr=0; //自定义结构体的地址DWORD NextIpAddr=0; //CPU下一个IP地址HDC hdc=NULL; //设备描述表句柄,画图用的int x=0; //字符串的开始位置 x坐标int y=0; //字符串的开始位置 y坐标UINT options=0;CONST RECT *lprect=NULL;LPCWSTR lpString=NULL; //字符串指针int c=0; //字符串中字符的个数CONST INT * lpDx=NULL;    BOOL Res=FALSE; //API TextOut 的返回值//下面的汇编代码是将TextOut(...)里面的6个参数和另外两个变量(dwParamaAddr和NextIpAddr)保存到变量中,以便后面调用__asm { MOV EAX,[EBP+8] //注意是[EBP+8],而不是[EBP+4]MOV [dwParamaAddr], EAXMOV EAX,[EBP+12]MOV [NextIpAddr], EAXMOV EAX,[EBP+16]MOV [hdc], EAXMOV EAX,[EBP+20]MOV [x], EAXMOV EAX,[EBP+24]MOV [y], EAXMOV EAX,[EBP+28]MOV [options], EAXMOV EAX,[EBP+32]MOV [lprect], EAXMOV EAX,[EBP+36]MOV [lpString], EAXMOV EAX,[EBP+40]MOV [c], EAXMOV EAX,[EBP+44]MOV [lpDx], EAX}PFN_GETCURRENTPROCESS pfnGetCurrentProcess=(PFN_GETCURRENTPROCESS)pRP->dwGetCurrentProcess;PFN_WRITEPROCESSMEMORY pfnWriteProcessMemory=(PFN_WRITEPROCESSMEMORY)pRP->dwWriteProcessMemory;PFN_TEXTOUT pfnTextOut=(PFN_TEXTOUT)pRP->dwTextOut;PFN_EXTTEXTOUT pfnExtTextOut=(PFN_EXTTEXTOUT)pRP->dwExtTextOut;PFN_POSTMESSAGE pfnPostMessage=(PFN_POSTMESSAGE)pRP->dwPostMessage;PFN_SENDMESSAGE pfnSendMessage=(PFN_SENDMESSAGE)pRP->dwSendMessage;PFN_MESSAGEBOX pfnMessageBox=(PFN_MESSAGEBOX)pRP->dwMessageBox;//恢复API原来的样子,即摘掉API钩子pfnWriteProcessMemory(pfnGetCurrentProcess(), (LPVOID)pfnExtTextOut, (LPCVOID)pRP->oldCode, 10, NULL);//调用正常的TextOut//Res=pfnTextOut(hdc, x, y, lpString, c);Res=pfnExtTextOut(hdc, x, y, options, lprect, lpString, c, lpDx);//下面的代码是将TextOut里面的lpString悄悄发送给我们挂钩子的windows应用程序if(pRP->hwnd!=NULL){pRP->lpString=lpString;//pfnPostMessage(pRP->hwnd, WM_HOOK_TEXTOUT, MAKELONG(0,0), MAKELONG(0,0)); //进程间通信pfnSendMessage(pRP->hwnd, WM_HOOK_TEXTOUT, MAKELONG(0,0), MAKELONG(0,0)); //进程间通信}//int allowFlag = pfnMessageBox(NULL, lpString, pRP->info, MB_ICONWARNING | MB_YESNO);//下面代码是善后工作,这个非常重要,如果没有的话,EIP将回不到调用TextOut(...)的下一条命令,这条命令在"notepad.exe"的领空//而不是kernel32.dll的领空,要切记。__asm {POP EDIPOP ESIPOP EBXMOV EDX, [NextIpAddr] //调用TextOut(...)这一命令的下一条命令地址MOV EAX, [Res] //函数返回值要放到EAX寄存器里,这一句可省略,原因是pfnTextOut(...)会自动将结果存入EAXMOV ESP, EBPPOP EBP//MOV ESP, EBPADD ESP, 11*4 //此处为了平衡栈,可以进一步优化PUSH EDXRET //ret指令用栈中的数据(即edx里面的地址),修改IP的内容,注意不修改CS的内容,retf才是 }}BOOL CpingmuquciDlg::enableDebugPriv(){HANDLE hToken;      LUID sedebugnameValue;      TOKEN_PRIVILEGES tkp;      if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))      {          return FALSE;      }      if(!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue))      {          CloseHandle(hToken);          return FALSE;      }      tkp.PrivilegeCount = 1;      tkp.Privileges[0].Luid = sedebugnameValue;      tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; //特权启用      if(!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) //启用指定访问令牌的特权      {          CloseHandle(hToken);          return FALSE;      }      return TRUE;}DWORD CpingmuquciDlg::processNameToId(LPCTSTR lpszProcessName){HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);    PROCESSENTRY32 pe;    pe.dwSize = sizeof(PROCESSENTRY32);    if(!Process32First(hSnapshot, &pe))    {        MessageBox(_T("The frist entry of the process list has not been copyied to the buffer"), _T("Notice"), MB_ICONINFORMATION | MB_OK);          return 0;    }    while(Process32Next(hSnapshot, &pe)) //循环查找下一个进程    {        if(!strcmp(lpszProcessName, pe.szExeFile)) //找到了        {            return pe.th32ProcessID;        }    }    return 0;}BOOL CpingmuquciDlg::InitHook(HANDLE hProcess){//提升进程访问权限if(!enableDebugPriv()) { printf("提升进程访问权限 Error!\n"); return -1; }//定义线程体的大小,实际分配的内存大小是页内存大小的整数倍size_Func=1024*8;dwFunAddr = (DWORD)VirtualAllocEx(hProcess, NULL, size_Func, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if((LPVOID)dwFunAddr == NULL) {printf("申请线程内存失败!\n"); CloseHandle(hProcess); return FALSE; }size_Pramam=sizeof(RemoteParam);dwPramaAddr = (DWORD)VirtualAllocEx(hProcess, NULL, size_Pramam, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);if((LPVOID)dwPramaAddr == NULL) { printf("申请参数内存失败!\n"); CloseHandle(hProcess); return FALSE; }//RemoteParam m_RParam;ZeroMemory(&m_RParam, sizeof(m_RParam));HMODULE hKernel32 = LoadLibrary("kernel32.dll");HMODULE hUser32 = LoadLibrary("user32.dll");HMODULE hGdi32 = LoadLibrary("gdi32.dll");m_RParam.dwTextOut = (DWORD)GetProcAddress(hGdi32, "TextOutW");m_RParam.dwExtTextOut = (DWORD)GetProcAddress(hGdi32, "ExtTextOutW");m_RParam.dwGetCurrentProcess = (DWORD)GetProcAddress(hKernel32, "GetCurrentProcess");m_RParam.dwWriteProcessMemory = (DWORD)GetProcAddress(hKernel32, "WriteProcessMemory");m_RParam.dwPostMessage = (DWORD)GetProcAddress(hUser32, "PostMessageW");m_RParam.dwSendMessage = (DWORD)GetProcAddress(hUser32, "SendMessageW");m_RParam.dwMessageBox = (DWORD)GetProcAddress(hUser32, "MessageBoxW");m_RParam.bHookAlready=TRUE;m_RParam.hwnd=m_hwnd_hook;m_RParam.lpString=NULL; wchar_t str2[]={L"我拦截API成功了,哈哈^o^"};      ::wmemcpy_s(m_RParam.info,sizeof(m_RParam.info),str2,sizeof(str2));      for(int i=15; i<31; i++){m_RParam.info[i]=L'\0';}//unsigned char oldcode[10]; //unsigned char newcode[10]; int praadd = (int)dwPramaAddr; int threadadd = (int)dwFunAddr; newcode[4] = praadd>>24; newcode[3] = (praadd<<8)>>24; newcode[2] = (praadd<<16)>>24; newcode[1] = (praadd<<24)>>24; newcode[0] = 0x68; //0x68: push newcode[1..4],参数先压栈int offsetaddr = threadadd - (int)m_RParam.dwExtTextOut - 10 ; newcode[9] = offsetaddr>>24; newcode[8] = (offsetaddr<<8)>>24; newcode[7] = (offsetaddr<<16)>>24; newcode[6] = (offsetaddr<<24)>>24; newcode[5] = 0xE8; //0xE8: call newcode[6..9],然后调用函数for(int i = 0; i < 10; i++){m_RParam.newCode[i]=newcode[i];}CString str_oldcode;str_oldcode="m_RParam.NewCode: ";for(int i = 0; i< 10; i++){CString str;str.Format("0x%.2x ", m_RParam.newCode[i]);str_oldcode+=str;}str_oldcode+="\r\n";DWORD dwRead = 0;if(!ReadProcessMemory(GetCurrentProcess(), (LPCVOID)m_RParam.dwExtTextOut, oldcode, 10, &dwRead)) {printf("read error");CloseHandle(hProcess);FreeLibrary(hKernel32);FreeLibrary(hUser32);FreeLibrary(hGdi32);return FALSE;}strcat((char*)m_RParam.oldCode, (char*)oldcode);m_RParam.FunAddr = dwFunAddr;str_oldcode+="m_RParam.OldCode: ";for(int i = 0; i< 10; i++){CString str;str.Format("0x%.2x ", m_RParam.oldCode[i]);str_oldcode+=str;}str_oldcode+="\n";DWORD dwWrite = 0;if(!WriteProcessMemory(hProcess, (LPVOID)dwFunAddr, (LPVOID)&HookTextOut, size_Func, &dwWrite)){printf("WriteRemoteProcessesMemory Error 1 !\n");CloseHandle(hProcess);FreeLibrary(hKernel32);FreeLibrary(hUser32);FreeLibrary(hGdi32);return FALSE;}if(!WriteProcessMemory(hProcess, (LPVOID)dwPramaAddr, (LPVOID)&m_RParam, sizeof(RemoteParam), &dwWrite)){printf("WriteRemoteProcessesMemory Error 2 !\n");CloseHandle(hProcess);FreeLibrary(hKernel32);FreeLibrary(hUser32);FreeLibrary(hGdi32);return FALSE;}FreeLibrary(hKernel32);FreeLibrary(hUser32);FreeLibrary(hGdi32);CString str;str.Format("m_RParam.dwExtTextOut:%.8x\r\nRParam.dwMessageBox:%.8x\r\nRParam.dwGetCurrentProcess:%.8x\r\nRParam.dwWriteProcessMemory:%.8x\r\nRParam.FunAddr:%.8x\r\ndwPramaAddr=%.8x\r\n",   m_RParam.dwExtTextOut, m_RParam.dwMessageBox, m_RParam.dwGetCurrentProcess, m_RParam.dwWriteProcessMemory, m_RParam.FunAddr, dwPramaAddr);str+=str_oldcode;m_edit.SetWindowText(str);return TRUE;}BOOL CpingmuquciDlg::ClearHook(HANDLE hProcess){HookOff(m_hProcess);VirtualFreeEx(m_hProcess, (LPVOID)dwFunAddr, 0, MEM_RELEASE); //MEM_DECOMMIT仅标示内存空间不可用,内存页还将存在。MEM_RELEASE完全回收。VirtualFreeEx(m_hProcess, (LPVOID)dwPramaAddr, 0, MEM_RELEASE); //MEM_DECOMMIT仅标示内存空间不可用,内存页还将存在。MEM_RELEASE完全回收。dwFunAddr=NULL;dwPramaAddr=NULL;m_hProcess=NULL;return TRUE;}BOOL CpingmuquciDlg::HookOn(HANDLE hProcess){DWORD dwWrite=0;if(!WriteProcessMemory(hProcess, (LPVOID)m_RParam.dwExtTextOut, (LPVOID)newcode, 10, &dwWrite)) //挂上API钩子{printf("WriteRemoteProcessesMemory Error 4 !\n");return FALSE;}return TRUE;}BOOL CpingmuquciDlg::HookOff(HANDLE hProcess){DWORD dwWrite=0;if(!WriteProcessMemory(hProcess, (LPVOID)m_RParam.dwExtTextOut, (LPVOID)oldcode, 10, &dwWrite)) //摘掉API钩子{printf("WriteRemoteProcessesMemory Error 5 !\n");return FALSE;}return TRUE;}void CpingmuquciDlg::OnBnClickedButton1() //打开API钩子{m_hwnd_hook=this->GetSafeHwnd(); //将对话框设置为安装API钩子的元凶m_mouse_hook.StartHook(m_hwnd_hook); //开启全局鼠标钩子}void CpingmuquciDlg::OnBnClickedButton2() //关闭API钩子{m_mouse_hook.StopHook(m_hwnd_hook); //关闭全局鼠标钩子}afx_msg LRESULT CpingmuquciDlg::OnHookTextout(WPARAM wParam, LPARAM lParam){wchar_t str[200];ZeroMemory(str, sizeof(str)/sizeof(wchar_t));RemoteParam RParam;ZeroMemory(&RParam, sizeof(RParam));DWORD dwRead=0;if(!ReadProcessMemory(m_hProcess, (LPCVOID)dwPramaAddr, &RParam, sizeof(RParam), &dwRead)){printf("read error");CloseHandle(m_hProcess);return 1;}if(!ReadProcessMemory(m_hProcess, (LPCVOID)RParam.lpString, str, sizeof(str), &dwRead)){printf("read error");CloseHandle(m_hProcess);return 1;}char sss[400];ZeroMemory(sss, sizeof(sss)/sizeof(char));int len=WideCharToMultiByte(CP_ACP,0,str,-1,NULL,0,NULL,NULL);WideCharToMultiByte(CP_ACP,0,str,-1,sss,len,NULL,NULL); //宽字符转多字节字符m_edit.SetWindowText(sss); //将截取来的字符串显示到对话框的文本框里面return 0;}void CpingmuquciDlg::OnTimer(UINT_PTR nIDEvent){// TODO: 在此添加消息处理程序代码和/或调用默认值if(nIDEvent==TIME_ID_1){this->KillTimer(TIME_ID_1);POINT pt;GetCursorPos(&pt);CWnd* pWnd=WindowFromPoint(pt);if(pWnd!=NULL){HWND hwnd=pWnd->GetSafeHwnd();DWORD dwProcessId=NULL;GetWindowThreadProcessId(hwnd, &dwProcessId); //获取进程IDif(dwProcessId!=NULL){if(m_dwProcessId!=dwProcessId){if(m_hProcess!=NULL){ClearHook(m_hProcess);}m_hProcess=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ, FALSE, dwProcessId);m_dwProcessId=dwProcessId;InitHook(m_hProcess);}HookOn(m_hProcess); //挂上API钩子RECT rc;rc.left=pt.x-2;rc.right=pt.x+2;rc.top=pt.y;rc.bottom=pt.y+4;pWnd->ScreenToClient(&rc);pWnd->InvalidateRect(&rc); //使矩形区域失效,放入WM_PAINT消息pWnd->UpdateWindow(); //强制更新HookOff(m_hProcess); //摘掉API钩子}}}CDialogEx::OnTimer(nIDEvent);}afx_msg LRESULT CpingmuquciDlg::OnMyMousemove(WPARAM wParam, LPARAM lParam){this->KillTimer(TIME_ID_1);this->SetTimer(TIME_ID_1,1000,NULL); //设置鼠标在屏幕某处停留1秒的时钟return 0;}

=================================================

效果截图:





0 0
原创粉丝点击