从特定内存区域恢复无父 Qt 对象

问题描述 投票:0回答:1

我的代码将自身注入到闭源 Qt5 应用程序中。在启动过程中,应用程序创建了一些我想要访问的全局对象。这些对象始终在

QApplication
QQmlApplicationEngine
之间的同一内存区域中创建(Gammaray 屏幕截图)。

image

条目之间的偏移量和顺序不一致,但内存位置始终相同。它们没有父级 (

QObject(0x0)
),因此没有简单的方法来访问它们。 GammaRay 通过使用 LD_PRELOAD 挂钩对象创建来获取此信息,这是不可取的。

这是我的想法:以 4 字节间隔遍历

qApp
QQmlApplicationEngine
之间的内存,并检查该地址是否是有效的 QObject:

auto b = qmlEngine(someQmlEntity);
auto qAppEngine = (char *) qobject_cast<QQmlApplicationEngine *>(b);
char *p = (char *) qApp;
while (p < qAppEngine) {
    QObject *obj;
    obj = (QObject *) (void *) p;
    printf("class name %s\n", obj->metaObject()->className());
    p = p + 4;
}

此代码在第一次迭代后失败,因为

(char*)qApp + 4
不是有效的
QObject
。将
obj->metaObject()
包装到 try-catch 块中也会导致应用程序崩溃。

有没有一种方法可以很好地恢复这些对象?我是不是选错了?

c++ qt casting reverse-engineering
1个回答
0
投票

有一个未记录的 API 旨在允许挂钩对象创建。像这样使用它:

#include <QtCore/private/qhooks_p.h>

void addCallback(QObject* obj)
{
    std::printf("Created object at %p\n", obj);
}

int main(int argc, char** argv)
{
    qtHookData[QHooks::AddQObject] = reinterpret_cast<quintptr>(&addCallback);
    QApplication app(argc, argv);
    ...
}

请注意,无法以线程安全的方式删除或更改回调,至少按照 C++ 标准的字母,但实际上,如果您只需将值设置回零以禁用挂钩,它应该可以工作。

如果您使用 CMake,请像这样链接以使挂钩的私有标头可见:

target_link_libraries(your_app Qt::CorePrivate ...)
© www.soinside.com 2019 - 2024. All rights reserved.