风君雪科技博客

  • 首页
  • 业界
  • 前端
  • 运维
  • 建站
  • 软件
  • 生活
  • 后端
  • 创投
  • 运营
  • 程序人生
    • 影视
    • 游戏
    • 句子
    • 资源
  • 其他
    • 说说
  • 关于本站
  1. 首页
  2. 软件
  3. 正文

hook qq 聊天内容(转)

2023年8月23日 24点热度 0人点赞 0条评论

做这件事难点在于,QQ2010 的聊天框用的是无窗口RichEdit,因此不能像普通的RichEdit那样通过FindWindow找到窗口然后发送WM_GETTEXT来获取文本,但是是不是就没有办法了呢,当然不是,这篇文章就要告诉大家抓取QQ2010(以及之后版本)的QQ聊天框信息的一些基本思路。
大家先用Dependency Walker看一下RICHED20.dll这个文件,这个文件位于Tencent\QQ\Bin目录下,同样也位于Windows\System32目录下,可以看到该文件导出了几个函数:
Ordinal ^ Hint Function Entry Point
2 (0x0002) 1 (0x0001) IID_IRichEditOle 0x00014C60
3 (0x0003) 2 (0x0002) IID_IRichEditOleCallback 0x00014C50
4 (0x0004) 0 (0x0000) CreateTextServices 0x0000D882
5 (0x0005) 5 (0x0005) IID_ITextServices 0x00014C20
6 (0x0006) 3 (0x0003) IID_ITextHost 0x00014C30
7 (0x0007) 4 (0x0004) IID_ITextHost2 0x00014C40
8 (0x0008) 6 (0x0006) REExtendedRegisterClass 0x0004BA5C
9 (0x0009) 7 (0x0007) RichEdit10ANSIWndProc 0x0003DB01
10 (0x000A) 8 (0x0008) RichEditANSIWndProc 0x00015681

这里大家需要注意的是CreateTextServices函数,在MSDN上查询后得知,该函数的原型如下:
HRESULT CreateTextServices( IUnknown *punkOuter,
  ITextHost *pITextHost,
  IUnknown **ppUnk
);

第一个参数不用管,第二个参数暂时也不用管,至于第三个参数,返回一个ppUnk,通过这个ppUnk,我们可以通过调用QueryInterface得到ITextServices接口指针,比如:
ITextServices* lpTs;
((IUnknown*)(*ppUnk))->QueryInterface(IID_ITextServices, (void**)(&lpTs));

这时候在MSDN上查询一下ITextServices接口,可以看到它的成员函数
HRESULT TxGetText( BSTR *pbstrText
);
通过这个函数,我们就可以得到创建的无窗口RichEdit中的文本了。

让我们来理一理思路,综上所述,我们需要做的就是Hook一下CreateTextServices函数,然后得到ppUnk这个指针,关于Hook API的方法我这里就不多说了,我采用的是一个比较简单的方法,大家可以参考这篇文章
http://www.codeproject.com/KB/COM/cominterfacehookingpart.aspx
简单说一下这篇文章的思路,主要的方法就是我们自己实现一个RICHED20.dll,并且把这个DLL复制到Tencent\QQ\Bin目录下覆盖源文件,然后导出前面的几个函数,用自己的函数来代替,比如CreateTextServices,我们可以这样实现:

#define NEW_DLL_NAME _T("\\RichEd20.Dll")

HRESULT WINAPI CreateTextServices(IUnknown *punkOuter, ITextHost *pITextHost, IUnknown **ppUnk)
{
TCHAR szLib[MAX_PATH]; //255 is enough
DWORD dw = GetSystemDirectory(szLib, MAX_PATH);
if(dw == 0) return 0;
szLib[dw] = TCHAR('\0');
::lstrcat(szLib, NEW_DLL_NAME);
HMODULE hLib = LoadLibrary(szLib);
  if(!hLib) return 0;

  lpCreateTextServices _CreateTextServices = (HRESULT (__stdcall *) 
(IUnknown*, ITextHost*, IUnknown**))
::GetProcAddress(hLib, "CreateTextServices");
if(!_CreateTextServices) return 0;

HRESULT hr = (_CreateTextServices)(punkOuter, pITextHost, ppUnk);

ITextServices* lpTx;
((IUnknown*)(*ppUnk))->QueryInterface(IID_ITextServices, (void**)(&lpTx));

//这里是为了获取聊天窗口的句柄,因为RichEdit是Windowless,所以只能通过这种方式获取hostwindow
pITextHost->TxSetCapture(TRUE);
HWND hWnd = GetCapture();
pITextHost->TxSetCapture(FALSE);
TCHAR szText[200] = {0};
WINDOWINFO wi = {sizeof(wi)};
GetWindowInfo(hWnd,&wi);
if (wi.dwStyle == 0x860F0000 && wi.dwExStyle == 0x300) //这个风格,表示是聊天窗口
{
g_mapTextServices.insert(std::make_pair(hWnd,lpTx));
}

return hr;
}

接下来让我一步一步说明这个函数的功能
1. 首先获取System32目录,然后载入System32下真正的RICHED20.dll,
2. 用GetProcAddress获取真正的CreateTextServices函数
3. 调用CreateTextServices函数,得到ppUnk指针
4. 调用ppUnk的QueryInterface得到ITextServices指针
到这一步的时候,就有两个个问题,首先,我们如何保存得到的ITextServices指针;其次,如何获取聊天窗口的句柄,下面我们一个一个来讲。
因为QQ在创建聊天窗口时不只一次的调用了CreateTextServices,事实上每创建一个窗口,就会调用三次,经过我后面的验证,第一次调用时创建的是发送新消息框,第二次调用时创建的是消息显示框,所以这里我采用的方法,是定义一个multimap<HWND,ITextServices*>类型的map,然后把跟每个窗口对应的三个ITextServices指针插入到该map中,这样以后如果我需要得到某个窗口的聊天框内容,只需要根据该窗口的句柄,然后经过map的查找得到相应的迭代器,将迭代器++,就可以得到对应的聊天框ITextServices指针。但是问题是如何获取聊天窗口的窗口句柄呢?因为我查遍了ITextServices相关的接口,包括ITextHost等,没有任何返回HWND的函数,所以这里我用了一个小技巧,ITextHost接口中有一个TxSetCapture函数用以捕获鼠标,当外部调用我们的CreateTextServices时,会传进来一个ITextHost*类型的指针,我们调用它的TxSetCapture(TRUE)函数,然后紧接着调用一下GetCapture,这样得到的就是RichEdit的HostWindow的窗口句柄了,对应于QQ的聊天窗口,就是QQ聊天窗口的句柄了。
5. 在得到了窗口句柄以后,我们需要判断一下调用CreateTextServices的HostWindow是不是聊天窗口,通过SPY++,我们发现聊天窗口具有0x860F0000的风格以及0x300的扩展风格,这时候我们调用一下GetWindowInfo,获取到窗口的一些信息,然后将取到的窗口风格与这两个值做一个比较,如果相同,我们就认为它是一个聊天窗口,并将它插入到map中。
到此,主要的工作已经基本完成,接下来就是如何从map获取聊天窗口的ITextServices指针,并且调用它的TxGetText函数获取聊天窗口中的信息问题了,这里我就不多说了,大家可以根据自己的需要来进行改造。

如果大家需要源码,可以与我联系,我的邮箱是oldmanzhao@163.com

 原文地址:http://topic.csdn.net/u/20110429/18/02b4aa15-19aa-4da5-8f0a-ef6ac2bb9ce2.html

标签: hook qq 聊天内容(转)
最后更新:2023年8月23日

风君子

独自遨游何稽首 揭天掀地慰生平

点赞
< 上一篇
下一篇 >

猜你喜欢

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

风君子

独自遨游何稽首 揭天掀地慰生平

最新 热点 随机
最新 热点 随机
LG 新款 27GR82Q 显示器预售:2K 180Hz 98% DCI-P3 色域,2199 元 迎广推出新款 DUBILI 机箱,售价 1699 元起 树莓派 5 超频测试:CPU 从 2.4GHz 到 3.0GHz、GPU 从 800MHz 到 1.1GHz,性能提升 25% 《碟中谍 7:致命清算(上)》今日网播上线 OnePlus Buds 3黑色渲染图曝光 将支持48dB主动降噪 超级Mate馆国庆19省24城路演开启 北京王府井朝阳大悦城同步启动 到底什么是 LPO? 汽车行业的DMS系统 IT不变应万变 加班画了一晚上的图忘记保存怎么办? 很多朋友认为Pr剪辑视频很难,其实掌握这几点,你也可以轻松上手
常用的四种电脑截图方法如何使用电脑截图Win7密码破解大法如何破译电脑密码消息称英特尔 14 代酷睿 i9 / i7 / i5 桌面处理器 10 月 17 日发布,首发 K 系列和 KF 系列如何绑定电脑和路由器如何绑定路由器管理器梅干菜能用热水泡吗 梅干菜发霉了还能吃吗查全国有多少个重名的(重名查询包括自己吗)RX6800和RTX4060Ti哪款好 RX6800和RTX4060Ti对比评测中国空调排名(中国空调排名前十名)怎么用手机远程控制电脑手机如何远程操控电脑非参数估计——核密度估计(Parzen窗)
通货紧缩和通货膨胀的区别 消息称任天堂 4 月开始提高 Switch 产量,迎接新作《塞尔达传说:王国之泪》 浦发天天爱消除信用卡申请多久下卡 iQOO Z1 5G正式亮相:天玑1000 Plus/144Hz竞速屏/超级液冷散热系统 比亚迪李云飞:新能源汽车核心在中国 三一重工、电信、华为发布装备制造业首个5G全连接工厂 5G大数据助力 2019我国农业科技进步贡献率达到59.2% 《原神》核弹流机制与队伍配置解析 咖啡豆和可可豆(咖啡豆怎么来的) 建行App上线数字货币钱包 数字金融时代将带来哪些影响?
标签聚合
身份证 股票 IT资讯 银行卡 利息 中国 电动车 信用卡 业界 投资者 利率 美国 借款人 显卡 特斯拉 AMD 办公软件教程 智能手机 银行 手机 投资理财 马斯克 理财知识 快科技 京东 芯片 支付宝 股价 程序 小米 贷款 游戏 秘籍 信用 比亚迪 华为 来了 荣耀 处理器 三星 微软 汽车 APP 苹果 额度 路由器 iphone 教程 腾讯 科技

COPYRIGHT © 2023 风君雪博客园. ALL RIGHTS RESERVED.

粤ICP备2022155369号