逆向通达信 x 逆向微信 x 逆向Qt

qt · 浏览次数 : 0

小编点评

本文主要讨论了在Windows平台使用Qt进行UI开发的几种技术和方法,包括DirectUI、Alien Widget、QWindow等概念,以及它们在Qt中的应用和优势。 **主要内容概述如下**: 1. **[win32窗口嵌入Qt UI]**: 介绍了如何在Windows平台上嵌入Qt UI,以及如何使用DirectUI和Alien Widget等技术来实现这一目标。 2. **[反斗玩转signal-slot]**: 讨论了在Qt中如何使用signal-slot机制,以及如何通过反射技术来动态地修改signal-slot连接关系。 3. **[Qt Alien Widget]**: 探讨了Alien Widget的概念,它是如何在Qt中实现的,以及它与DirectUI的关系。 4. **[Qt界面不必一定依赖QApplication::exec才能运行]**: 分析了Native Widget和QWindow的区别,以及它们在Qt界面编程中的应用场景。 5. **[比较和联系Native Widget 和 QWindow]**: 对比了Native Widget和QWindow的特性和使用场景,以及它们在Qt中的不同作用。 6. **[通达信 x 微信 x Qt 做手术]**: 通过一个实际的例子,展示了如何使用Qt和微信进行集成,并讨论了相关的迁移解决方案。 7. **[逆向WeChat(四,mars)]**: 介绍了逆向WeChat的技术,包括Event Center和WeUIEngine的使用。 8. **[逆向WeChat(三, EventCenter)]**: 继续深入探讨逆向WeChat的技术,特别是Event Center的实现。 9. **[逆向WeChat (二, WeUIEngine)]**: 最后一部分讨论了WeUIEngine的使用,以及如何通过逆向工程来分析其功能和实现。 总的来说,本文通过详细的分析和实例,展示了在Windows平台使用Qt进行UI开发的多种技术和方法,为读者提供了宝贵的学习资源和实践指导。

正文

本篇在博客园地址https://www.cnblogs.com/bbqzsl/p/18252961

本篇内容包括:

win32窗口嵌入Qt UI。反斗玩转signal-slot。最后 通达信 x 微信 x Qt 做手术。

 

Qt Alien Widget是一种广义的DirectUI。

在UI技术中,DirectUI和Alien Widget的概念有所重叠,但具体实现和应用场景有所不同。为了更好地理解它们之间的关系,让我们先定义清楚这几个概念。

DirectUI

DirectUI 是一种界面绘制技术,主要特点是通过直接绘制UI元素,而不是依赖操作系统提供的原生控件。这种方式有以下几个特点:

  • 跨平台一致性:不依赖操作系统的控件,因此在不同操作系统上可以实现一致的外观和行为。
  • 高性能:直接绘制可以优化绘制路径,减少不必要的开销,从而提高性能。
  • 高自由度:开发者可以完全控制UI元素的绘制和交互,灵活性更高。

Native Widget

Native Widget 是由操作系统提供和管理的控件,这些控件直接使用操作系统的窗口和绘图资源。

  • 系统控件:直接由操作系统管理和绘制,提供与操作系统一致的外观和行为。
  • 平台相关:在不同的操作系统上,控件的行为和外观可能不同。

Alien Widget

Alien Widget 是指那些不依赖于操作系统提供的控件,而是由应用程序自身实现和管理的控件。在Qt中,默认控件(如QPushButton, QLineEdit等)都是Alien Widget。

  • 跨平台一致性:在不同操作系统上可以实现一致的外观和行为。
  • 独立性:不依赖操作系统的控件。
  • 灵活性和定制性:开发者可以完全控制控件的外观和行为。

Qt的Alien Widget和DirectUI的关系

Qt的Alien Widget可以看作是DirectUI的一种实现,因为它们都强调不依赖操作系统的原生控件,通过直接绘制实现跨平台一致性和高自由度。

主要特点:

  1. 绘制机制:Qt的Alien Widget是通过Qt的绘图系统(如QPainter)来进行绘制的,这类似于DirectUI技术中直接绘制的概念。
  2. 跨平台一致性:由于Qt的Alien Widget不依赖于操作系统的控件,它们在不同操作系统上提供了一致的外观和行为。
  3. 高自由度和定制性:开发者可以使用Qt提供的丰富API来自定义控件的外观和行为。

结论

可以认为Qt的Alien Widget是DirectUI技术的一种实现形式。两者都不依赖于操作系统的原生控件,通过直接绘制来实现跨平台一致性和高自由度。Qt的Alien Widget利用Qt框架的强大功能,实现了与DirectUI类似的目标。因此,从这个角度来看,Qt的Alien Widget确实可以被视为一种DirectUI技术。

 

Qt界面不必一定依赖QApplication::exec才能运行

Native Widget 和 QWindow 在 Qt 的图形用户界面编程中有不同的用途和特性。以下是对它们的详细对比和解释:

Native Widget

  • 定义:Native Widget 是由操作系统提供和管理的控件。这些控件直接使用操作系统的窗口和绘图资源,不依赖于 Qt 的绘图系统。
  • 特性
    • 系统控件:直接由操作系统管理和绘制,提供与操作系统一致的外观和行为。
    • 不依赖 Qt 事件循环:可以在不依赖于 QApplication::exec() 的情况下运行,因为它们由操作系统管理事件循环。
    • 平台相关:在不同的操作系统上,控件的行为和外观可能不同。
  • 使用场景:需要与系统深度集成,或使用特定平台功能时使用。例如嵌入系统控件到 Qt 应用程序中。

QWindow

  • 定义:QWindow 是 Qt 的一个抽象类,表示一个独立的窗口。它提供了一个轻量级的窗口对象,可以用于显示内容,但不提供高级的控件功能。
  • 特性
    • Qt 窗口对象:QWindow 是 Qt 提供的窗口类,可以与 Qt 的绘图系统和事件系统无缝集成。
    • 依赖 Qt 事件循环:QWindow 依赖于 QApplication::exec()QGuiApplication::exec() 来运行事件循环。
    • 跨平台一致性:Qt 提供了一致的 API 和行为,不论运行在什么平台上,Qt 窗口的行为和外观都是一致的。
  • 使用场景:用于创建自定义窗口、渲染 OpenGL/Vulkan 内容或其他需要低级别窗口访问的场景。

比较和联系

  • 事件循环:Native Widget 不依赖 Qt 的事件循环,可以独立于 QApplication::exec() 运行。而 QWindow 需要 Qt 的事件循环才能正常工作。
  • 管理和绘制:Native Widget 由操作系统管理和绘制,提供原生外观和行为。QWindow 由 Qt 管理,可以使用 Qt 的绘图系统来绘制内容。
  • 灵活性和集成:Native Widget 适用于需要直接访问操作系统功能和外观一致性的场景。QWindow 提供更高的灵活性和跨平台一致性,适用于需要使用 Qt 提供的高级功能和自定义绘图的场景。

结论

Native Widget 和 QWindow 是 Qt 中不同层次的组件,分别适用于不同的使用场景。Native Widget 更适合需要深度集成操作系统功能的应用,而 QWindow 则更适合需要使用 Qt 的绘图和事件系统的应用。两者的选择应根据具体的需求和应用场景来决定。


 

以上是AI提供的分析。

由上述可知,Alien Widget可以作为一种dui方案使用,为保证跨平台一致性,请使用QApplication::exec()。

main()
{
  QApplication app;
  QMainWindow mainWin;
  mainWin.show();
  app.exec();  
}

QApplication跟QMainWindow为固定定式。这个定式能够保证跨平台 一致性。

但是,在windows平台的软件,就有混合使用UI框架的需求。

所以针对windows平台还有一个特殊解决方案:https://github.com/qtproject/qt-solutions/tree/master/qtwinmigrate。

里面包含了三种迁移方案,分别是QMfcApp,QWinHost,QWinWidget。

QMfcApp是方便QApplication跟QMainWindow定式的使用,将QApplication跟CWinApp整合在一起,CWinApp::Run时绑定QApplication::exec。

QWinHost能够将其它框架(不限于MFC)的OS native window嵌入到QWidget。

QWinWidget能够QWidget嵌入到OS native window,以一个native widget hwnd挂到父hwnd。

native widget是由platforms/plugin/qwindows.dll支持的。代码路径在qtbase/src/plugins/platforms/windows,其中qwindowswindow.cpp实现了native window的WndProc,qWindowsWndProc。并将消息转换QtWindows::WindowsEventType由QWindowsContext::windowsProc进行处理。

通达信用的是qt5.5。

QPlatformWindow, qtbase/src/gui/kernel/qplatformwindow.h

QWindowsWindow, qtbase/src/plugins/platforms/windows/qwindowswindow.h

QWindow, qtbase/src/gui/kernel/qwindow.h

QMainWindow, qtbase/src/widgets/widgets/qmainwindow.h

QWidgetWindow, qtbase/src/widgets/kernel/qwidgetwindow_qpa_p.h

QWidget QSurface QPlatformSurface
QMainWindow QWindow QPlatformWindow
  QWidgetWindow QWindowsWindow
  "yes, i do." "you own me?"

 

尽管这几个都叫Window,单从名字好容易迷惑,它们不尽是QWindow。QWindow与QPlatformWindow是窗口的两个面,QWindow是跨平台的封装,QPlatformWindow则是底层支持。QWidgetWindow是一个私有类,将QWidget与QWindow能够联系在一起,QWidget从而能够依附在一个底层窗口分派事件。

QApplication::exec只是一个幌,隐藏了许多真相。QWidget分派事件需要的窗口过程是由QPlatformWindow提供支持的,但是Qt事件分派器却依赖QApplication,QApplication是一个QObject,QObject设计成绑定于一个线程上运行。所以使得QWidget依赖于QApplication所绑定的线程。因此一个进程范围内只允许有一个Qt的UI线程,而这个线程跟QApplication绑定在一起。

真相是,只有在QApplication绑定的线程上,QPlatformWindow才能在native窗口的消息循环中正常分派Qt事件。所以运行Qt UI的必要条件是QPlatformWindow,QApplication,并且在同一线程,这个线程上有消息循环。QApplication::exec是充分条件但不是必要的。

QPlatformWindow对应一个系统窗口,在跨平台层对应一个QWindow,其中它的继承类QWidgetWindow可以承载QWidget。QMainWindow是一个QWidget并且自带QWidgetWindow。所以QWindow对应着一个系统窗口。自然地QMainWindow也对应着一个系统窗口,同时成为所有子QWidget的窗口设备根基。迁移解决方案的QWinWidget就是用来替代QMainWindow的位置,为QWidget提供窗口设备根基。

QPlatformWindow由平台相关的qwindows.dll进行支持,在windows平台就是QWindowsWindow。必须依赖QApplication进行Object event filter。而QApplication只能绑定在一个线程上。同一进程同一时间,只能有一个线程上的QPlatformWindow以及Widgets可以正常运行。如果在QApplication之外的线程创建的QPlatformWindow以及Widgets是不能正常分派事件的,当它们需要响应事件的时候,QApplication就会警告“Object event filter cannot be in a different thread.”而不能响应。

下图演示,在两个线程分别创建QWinWidget,只有跟随QApplication同一个线程的QWidget能够正常响应事件。

 

为了演示,我将通达信君的tdxzdview100.dll插入到微信MM的体内,在微信MM体内分别诞生QWinWidget,QWindow,还有QMainWindow。微信MM体内是个没有被MFC污染的洁净环境。演示过程展示了只要有消息循环,就可以运行qt框架的UI。

 

接下来就是逆向Qt。

Qt以metaObject行了类型反射之实。

定义

反射(Reflection)是一种程序能够在运行时自我检查和操作其结构和行为的机制。通过反射,程序可以动态地获取类型信息,并操作对象、方法、属性等。

涵盖的操作

反射技术涵盖了以下几类操作:

  1. 类型检查和获取元数据

    • 获取类型信息:通过反射,可以在运行时获取对象的类型信息,如类名、方法、属性、字段等。
    • 检查类型成员:检查类型的成员(如方法、属性、事件、构造函数等)的名称、参数、返回类型等信息。
  2. 动态创建对象

    • 实例化类型:通过反射,可以动态地创建类型的实例,而不需要在编译时指定类型。
  3. 调用方法

    • 动态调用方法:可以在运行时调用对象的方法,而不需要在编译时知道方法的名称。
  4. 访问和修改属性和字段

    • 动态访问属性和字段:在运行时读取或修改对象的属性和字段。
  5. 检索和操作特性(注解)

    • 获取和操作特性(注解):通过反射,可以获取和操作应用在类型、方法、属性等上的特性(如C#中的属性,Java中的注解)。

Meta Object可以看作一个小型数据库,提供类型信息。

metacast负责反射类型转换。

metacall是所有反射操作的接口函数。原型类似于ioctl, fcntl。接受包括方法调用,属性访问等。

对于signal-slot的场合,本篇的metacall专指(QMetaObject::Call == InvokeMetaMethod)。

声明过signal跟slot的方法,本质上就是能够通过反射进行调用的方法,我们需要将QObject具体类的成员方法声明为signal或slot,然后还要用moc生成相关的metaobject代码,才能注册到反射。

signal-slot本质就变成了metacall的传递。connect就是对象的metacall连接成拓扑关系,使得metacall可以按拓扑关系进行传递。

signal-slot字面上局限了想象。connect must from signal to slot。然而connect实质是accept from signal to method which can be slot or signal as well.

我们换一下表达式,signal [, signal, ...] - slot,这样就开阔了。

反射不仅提供了类型信息,也可以修改类型信息。简直就是送上门让人逆向。

下图演示通过metaobject查询类型信息,对象方法

下图演示通过跟踪QObject::connect,收集所有signal-slot。这种方法在各Qt版本中比较通用。比较好忽略版本的差异。

下图演示,通过类型反射直接调用对象的slot方法。 

下图演示几种修改signal-slot连接关系的方法。通过dynamic meta,或者修改connection,将qt按钮连接到微信按钮,将qt编辑框连接到微信按钮,通过反射来调用按钮的clicked(),调用编辑框的textChanged(QString)。

对于逆向,不需要编译器,不需要头文件,不需要因为slot而去找代码moc编译QObject。

反射的一个特性就是动态修改,那就直接修改。

插入我的slot到signal。signal-slot定式限制了想象,好像只能有一条出路,我必须要有一个slot,方法类型需要对上signal。我必须要写一个QObject达成一个slot,用moc去生成代码。

但是,正如我在上面转换的定式,signal [,signal,... ] -slot,这样一来,signal的下一跳不一定必要是slot,而可以是signal。

拿QPushButton举例,signal clicked() 连接到一个影子QPushButton的signal clicked(),就可以除去一大票工作。

思路一, 通过dynamic meta。

要是我将QPushButton的metacall修改了signal clicked()的处理,必然导致全部QPushButton不能正常工作。意外地,Qt贴心地为我提供了Dynamic MetaObject,解决了我的烦恼。那么我需要moc编译另一个MetaObject吗?不,我以经将moc丢进垃圾桶了。我们可以直接将QPushButton的MetaObject连根复制一份。正所谓CopyOnWrite。我们只要修改副本的qt_static_metacall,将signal clicked()处理修改即可。最后将副本放到影子QPushButton的Dynamic MetaObject。手术完成。缺点是要将其它signal的处理也在同一个qt_static_metacall中修改,不灵活。另外,像clicked()是在父类QAbstractButton中声明为signal的,当其作为connect的receiver端时,并不是用QPushButton的MetaObject::qt_static_metacall分派,而是用QAbstractButton::qt_static_metacall进行分派。十分不方便。这个可以通过QMetaObjectPrivate::connect方法获知继承树中哪个类的MetaObject被选用。

思路二,通过Connection。

Qt5又一贴心设计,QObject::connect返回的不再是冰冷的bool,取而代之是热气腾腾的Connection。不同版本有所差异。但基本三要素没有变,sender, recver, metacall。That's good. Connection还直接指明了metacall函数指针。思路一的工作都可以直接删减了。一个Connection的method_index是固定,所以自已写一个metacall修改起来就简单得多,单一处理,灵活性大大提高。

思路三,自已跟自已。

经过前两次思路进化后,最后我又注意到,影子QPushButton还必要吗?nai, hitsuyu ga nai. 自已跟自已connect,直接省事。谨记,要将修改操作原子地在sender同一线程上进行,不然sender抢先signal一下,也就小狗追尾巴直到天荒地老了。如果需要代码在自已希望的线程上分派,那么还得依靠一个影子QPushButton绑定一个线程。

思路四,Qt5.5也可以connect到Functor。

虽然,Qt5.7才支持connect到Functor。但是在编程时,应用上面的思路,完全可以实现达到目标。

看啦,就这么简单好玩,祝大家也玩得开心。

本篇到这里,下一篇再见。

 

逆向WeChat(四,mars)

逆向WeChat(三, EventCenter)

逆向WeChat (二, WeUIEngine)

我还有逆向通达信系列

我还有一个K线技术工具项目KTL可以用C++14进行公式,QT,数据分析等开发。

与逆向通达信 x 逆向微信 x 逆向Qt相似的内容:

逆向通达信 x 逆向微信 x 逆向Qt

本篇在博客园地址https://www.cnblogs.com/bbqzsl/p/18252961 本篇内容包括: win32窗口嵌入Qt UI。反斗玩转signal-slot。最后 通达信 x 微信 x Qt 做手术。 Qt Alien Widget是一种广义的DirectUI。 在UI技术中,D

4.1 探索LyScript漏洞挖掘插件

在第一章中我们介绍了`x64dbg`这款强大的调试软件,通过该软件逆向工程师们可以手动完成对特定进程的漏洞挖掘及脱壳等操作,虽然`x64dbg`支持内置`Script`脚本执行模块,但脚本引擎通常来说是不够强大的,LyScript 插件的出现填补了这方面的不足,该插件的开发灵感来源于`Immunity`调试器中的`ImmLib`库,因`Immunity`调试器继承自`Ollydbg`导致该调试器无

【iOS逆向与安全】iOS远程大师:通过H5后台远程查看和协助iPhone设备

在移动设备测试和远程协助的过程中,能够远程查看和协助iPhone设备是一项非常实用的功能。为了解决这一需求,我开发了一款名为**iOS远程大师**的产品,允许用户通过H5后台界面查看和协助越狱或非越狱的iPhone设备。本文将详细介绍iOS远程大师的开发过程和技术实现。

【逆向专题】【危!!!刑】(一)使用c#+Win32Api实现进程注入到wechat

引言 自从上篇使用Flaui实现微信自动化之后,这段时间便一直在瞎研究微信这方面,目前破解了Window微信的本地的Sqlite数据库,使用Openssl,以及Win32Api来获取解密密钥,今天作为第一张,先简单写一下,获取微信的一些静态数据,以及将自己写的c语言dll通过Api注入到微信进程里面

精准测试之覆盖

测试的覆盖通常是指需求范围的执行程度,如需求、测试用例、缺陷的正向与逆向的双向追溯。便于对其相关属性的度量,即使用了覆盖率。

4.4 x64dbg 绕过反调试保护机制

在Windows平台下,应用程序为了保护自己不被调试器调试会通过各种方法限制进程调试自身,通常此类反调试技术会限制我们对其进行软件逆向与漏洞分析,我们以第一种`IsDebuggerPresent`反调试为例,该函数用于检查当前程序是否在调试器的环境下运行。函数返回一个布尔值,如果当前程序正在被调试,则返回True,否则返回False。函数通过检查特定的内存地址来判断是否有调试器在运行。具体来说,该

安全测试之探索 windows 游戏扫雷

扫雷游戏相信很多人都从小玩过,在那个电脑游戏并不多的时代,扫雷成为玩的热度蛮高的一款游戏之一,然而就在有一次,接触到了一次不寻常的扫雷过程,使得后来我也有了这个冲动,也来做一次。通过动态调试,逆向和C来写一个扫雷辅助工具从而提高逆向与编码技能。

EQ 均衡器

EQ 的全称是 Equalizer,EQ 是 Equalizer 的前两个字母,中文名字叫做“均衡器”。最早是用来提升电话信号在长距离的传输中损失的高频,由此得到一个各频带相对平衡的结果,它让各个频带的声音得到了均衡。 EQ 的主要功能是:通过多个滤波器对声音某一个或多个频段进行增益或衰减处理。 滤

C#希尔排序算法

前言 希尔排序简单的来说就是一种改进的插入排序算法,它通过将待排序的元素分成若干个子序列,然后对每个子序列进行插入排序,最终逐步缩小子序列的间隔,直到整个序列变得有序。希尔排序的主要思想是通过插入排序的优势,减小逆序对的距离,从而提高排序效率。 希尔排序实现原理 首先要确定一个增量序列(初始间隔),

逆向WeChat(四)

本篇在博客园地址https://www.cnblogs.com/bbqzsl/p/18209439 mars 先回顾一下,在上两篇《WeUIEngine》,《EventCenter》。我对wechat如何使用chrome::base框架的分析中需要更正补充。首先要指出,逆向分析是一个过程。需要经过不