已逆出64位的QQ Mojo Ipc通信过程, 请点击下方链接下载QQImpl项目, 此项目将QQ的Mojo Ipc和WeChatOCR独立了出来, 可以在任何项目中使用:
https://github.com/EEEEhex/QQImpl
采用QQImpl的成品在下方链接下载:
链接:QQScreenShotNT-Plus(https://pan.baidu.com/s/1v5M6EGO6aDN6uiBwEEIGSw?pwd=ctjs)
提取码:ctjs
QQ出Electron版了, 将截图独立出来了(应该是个过渡, 之后感觉会采用Electron重写), 并且使用的OCR改成了TencentOCR(低版本的WeChatOCR)
0x00 逆向调用QQ截图NT
0x01 前期调研
Invitation简单来说就是创建子进程, 并给它传命令行--mojo-platform-channel-handle=xxx。
显然QQ就是从这个基础上改了一个命令行参数, 本质就是采用Mojo IPC进行通信。
那就开逆! (一开始分析的是QQNT 64位版本的, 后面为了方便分析用的是9.9.0.14619 x86版本的, 可能地址会变化)
0x02 分析QQScreenshot.exe
这个main函数跟我以前逆的结果差不多哇, 总的来说就是启动QQ截图的环境, 图上画框的函数是启动IPC的, 进去看看:
(其实可以发现parent-ipc-core-x86.dll和child-ipc-core-x86.dll是同一个代码编译的DLL)
那QQ也很有可能是通过加载parent-ipc-core再动态获取COM对象实现的
DllGetClassObject = GetProcAddress(LibraryA, "DllGetClassObject");
0x03 分析parent-ipc-core-x86.dll
看一下这个COM对象的实现了哪些方法:
只介绍一下pCOM->LaunchChildProcess(...)方法:
0x04 LaunchChildProcess方法
通过动调可以发现LaunchChildProcess方法的第5个参数是用来设置接收IPC MSG函数的
下面进LaunchQQScreenShot函数看看:
整个函数完全就是参考文章[1]里面介绍的Invitation机制。
这个函数其实是LaunchChildProcessInternal, 是LaunchChildProcess的内部函数,用来创建子进程:
pIMojoIpc
-
>LaunchChildProcess(wchar_t
*
path, (char
*
)[] cmdlines, DWORD64 cmdlines_num, LPVOID callback, LPVOID lpClass);
/
/
最后一个参数是callback的第一个参数 是一个类指针
而LaunchChildProcess的最后一个参数是接收IPC消息回调函数的第一个参数。
0x10 逆向调用WeChatOCR
QQ采用的TencetnOCR就是低版本的WeChatOCR, 他们也是采用Mojo IPC进行通信
0x11 前期调研
0x12 定位OCR调用函数
0x13 分析OCRdoInit函数
在SetMMMojoEnvironmentCallbacks函数里设置了接收IPC消息的函数这个后面分析。
0x14 分析SendOCRTask函数
先不管了 既然发送函数分析不出来那就先去看接收IPC MSG的函数。
0x15 分析接收IPC MSG的函数
我们直接大胆猜测writeinfo、readinfo全是protobuf! 把数据扣下来测试一下(用protobuf-inspector这个工具):
0x16 分析protobuf格式
比如发送的格式:
message OcrRequest {
int32 unknow = 1;//必定为0
int32 task_id = 2;
message PicPaths {
repeated string pic_path = 1;
}
PicPaths pic_path = 3;
}
message OcrResponse {
int32 type = 1;//第一次运行OCR会有push一次type1, 正常OCR结束type0
int32 task_id = 2;
int32 err_code = 3;
message OcrResult {
message ResultPos { //四个角的坐标 左上 右上 右下 左下
message PosXY {
float x = 1;
float y = 2;
}
repeated PosXY pos = 1;
}
message SingleResult {//SingleResult是一行结果 OneResult是单字的
ResultPos single_pos = 1;
bytes single_str_utf8 = 2;//UTF8格式的字符串
float single_rate = 3;//单行的识别率
message OneResult {
ResultPos one_pos = 1;
bytes one_str_utf8 = 2;
}
repeated OneResult one_result = 4;
float lx = 5;//识别矩形的左上和右下的坐标? 可能是
float ly = 6;
float rx = 7;
float ry = 8;
int32 unknown_0 = 9;//未知
ResultPos unknown_pos = 10;//未知
}
repeated SingleResult single_result = 1;//repeated 每行的结果
int32 unknown_1 = 2;
int32 unknown_2 = 3;
}
OcrResult ocr_result = 4;
}
成品展示
结束语
具体的细节都可以去看附件的代码, 文章中没写出来的代码里都有哦(只能使用Release x86配置编译)。
参考文章
(https://source.chromium.org/chromium)
看雪ID:0xEEEE
https://bbs.kanxue.com/user-home-901761.htm
# 往期推荐
3、安卓加固脱壳分享
球分享
球点赞
球在看
原文始发于微信公众号(看雪学苑):逆向调用QQ截图NT与WeChatOCR
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论