首页 > 其他分享 >QT初步逆向分析一:由信号发送的地方找到槽

QT初步逆向分析一:由信号发送的地方找到槽

时间:2022-11-30 11:57:19浏览次数:70  
标签:逆向 QT mySignal int void mySlot 发送 信号 父类

环境

msvc 2019 64位 Release
QT 5.15.1

源码

tsignal.h

#include <QMainWindow>
#include <QObject>
// 必须继承QObject才能使用信号和槽
class TsignalApp :public QMainWindow
{
public:
    TsignalApp();
    void slotFileNew();
    Q_OBJECT
        // 信号声明区
signals:
    // 声明信号 mySignal()
    void mySignal();
    // 声明信号 mySignal(int)
    void mySignal(int x);
    // 声明信号 mySignalParam(int,int)
    void mySignalParam(int x, int y);
    // 槽声明区
public slots:
    // 声明槽函数 mySlot()
    void mySlot();
    // 声明槽函数 mySlot(int)
    void mySlot(int x);
    // 声明槽函数 mySignalParam (int,int)
    void mySlotParam(int x, int y);
};

tsignal.cpp

#include "tsignal.h"
#include <QMessageBox>
TsignalApp::TsignalApp()
{
    // 将信号 mySignal() 与槽 mySlot() 相关联
    connect(this, SIGNAL(mySignal()), SLOT(mySlot()));
    // 将信号 mySignal(int) 与槽 mySlot(int) 相关联
    connect(this, SIGNAL(mySignal(int)), SLOT(mySlot(int)));
    // 将信号 mySignalParam(int,int) 与槽 mySlotParam(int,int) 相关联
    connect(this, SIGNAL(mySignalParam(int, int)), SLOT(mySlotParam(int, int)));
}
// 定义槽函数 mySlot()
void TsignalApp::mySlot()
{
    QMessageBox::about(this, "Tsignal", "This is a signal/slot sample withoutparameter.");
}
// 定义槽函数 mySlot(int)
void TsignalApp::mySlot(int x)
{
    QMessageBox::about(this, "Tsignal", "This is a signal/slot sample with oneparameter.");
}
// 定义槽函数 mySlotParam(int,int)
void TsignalApp::mySlotParam(int x, int y)
{
    char s[256];
    sprintf(s, "x:%d y:%d", x, y);
    QMessageBox::about(this, "Tsignal", s);
}
void TsignalApp::slotFileNew()
{
    // 发射信号 mySignal()
    emit mySignal();
    // 发射信号 mySignal(int)
    emit mySignal(5);
    // 发射信号 mySignalParam(5,100)
    emit mySignalParam(5, 100);
}

main.cpp

#include "tsignal.h"
#include <QApplication>

int main(int argc, char* argv[])
{
    QApplication a(argc, argv);
    TsignalApp w;
    w.slotFileNew();
    return a.exec();
}

材料

用于分析的测试程序
https://wwmf.lanzout.com/iYx5G0haftbi

获取已知信息

我们使用IDA和x64dbg定位到 emit mySignal();信号发送的地方,看看我们已知的信息有哪些

void __fastcall sub_140001470(struct QObject *a1)
{
  QMetaObject::activate(a1, (const struct QMetaObject *)&qword_140006100, 0, 0i64);
}

struct QObject *a1
是发送信号的对象
const struct QMetaObject qword_140006100
元数据对象
int local_signal_index
信号在信号发送类的本地索引
void **argv
传递的参数
后面我们所有的信息都是通过这几个数得到的

获取发送信号在类中的全局索引

信号全局索引(signal_index)是由元数据对象local_signal_index得到的
元数据对象

 struct { // private data
        SuperData superdata;	// 0x0 父类元数据对象的指针   由此可知这是一个链表结构
        const QByteArrayData *stringdata;
        const uint *data; //0x10 类的元数据  里面包含信号数量
        typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **);
        StaticMetacallFunction static_metacall;
        const SuperData *relatedMetaObjects;
        void *extradata; //reserved for future use
    } d;

const uint *data

struct QMetaObjectPrivate
{
    int revision;
    int className;
    int classInfoCount, classInfoData;
    int methodCount, methodData;
    int propertyCount, propertyData;
    int enumeratorCount, enumeratorData;
    int constructorCount, constructorData;
    int flags;
    int signalCount; //0x34  类的信号数量(不包含基类)
}

获取所有父类的信号数量

我们通过SuperData superdata;获取父类的元数据对象,然后通过data.signalCount获取父类的信号数量,不断重复,直到superdata值为0,说明没有父类了,把这些信号数量累积起来就可以得到所有基类的信号总数了

image
由上图可知,元数据对象的地址为0x0000000140021100,在内存窗口打开
image
由上图可知,父类的元数据对象的地址为0x00007FFF7C34EE08,在内存窗口中打开
image
由上图可知,由于data的偏移为0x10,故data的地址为0x00007FFF7C34EC20,在内存窗口中打开
image
由于 signalCount偏移为0x34 ,所以这个父类的signalCount为3
回到0x00007FFF7C34EE08
image
找到下一个父类的元数据对象地址 0x00007FFF7C4DD130
image
按照相同的办法找到signalCount 这里为4
继续找下一个父类的元数据对象地址 0x00007FFF7BDFB700
image
发现SuperData superdata;的值为0,说明没有父类了
image
这里的signalCount为3

所有父类的信号数量为3+4+3 = 10

获取本地信号索引(local_signal_index)

image
由上图可知,local_signal_index值为0

signal_index = local_signal_index + 所有父类的信号数量 = 10

标签:逆向,QT,mySignal,int,void,mySlot,发送,信号,父类
From: https://www.cnblogs.com/czlnb/p/16937572.html

相关文章