【Windows逆向】【Qt】资源解析

news2024/11/17 13:25:41

▒ 目录 ▒

    • 🛫 导读
      • 需求
      • 开发环境
    • 1️⃣ 分析思路
      • 思路
      • 获取资源路径的方法
    • 2️⃣ c++正向编码
      • 编码
      • 使用流程
      • 不使用Qt方式获取思路
    • 3️⃣ frida方式获取Origin平台资源
      • win32 - 定位目标资源
      • win32 - 查找API含义
      • win32 - 查找《符号》构造frida本地函数
      • win32 - 全部代码
      • win64 - TODO
    • 🛬 文章小结
    • 📖 参考资料

🛫 导读

需求

Qt是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架。
Qt使用还是很广泛的,为了大家有一个直观的概念,我用Everything搜索了下我电脑上的qt5core.dll,部分结果如下图所示:
Everything搜索qt5core.dll结果

从图中可以看到,android模拟器、魔兽战网平台、Origin游戏平台、x64dbg都使用了qt框架,除此之外还有很多应用使用了Qt,市面上对Qt的逆向也很多,在这里我们将分析如何导出Qt中的图片资源,其他资源暂时未找到方法,有大神知道的不吝赐教。

开发环境

版本号描述
文章日期2022-12-08

1️⃣ 分析思路

思路

通过Qt官网文档可以知道,项目中的res.qrc文件,会被编译为qrc_res.cpp。我们通过Hex Workshop查看文件二进制内容;通过python查看文件大小;通过Qt Creator打开qrc_res.cpp。我们先看下下面截图内容:
在这里插入图片描述

  • 在文件qrc_res.cpp中的注释,我们可以知道,qt_resource_data数组保存了logo.ico文件内容;
  • 查看文件大小为67,646 字节,通过python查看文件大小为0x1083e;0x1083e也的确被保存在了qt_resource_data数组中,内容为0x0,0x1,0x8,0x3e,;
  • 比对Hex Workshop文件内容和qt_resource_data数组,可以发现内容是不一样的,显然内容被压缩了。

分析到这里,可以确定文件不是简单的被保存的PE文件的资源段中的,而且有可能被压缩处理了。那就换个思路,通过调用资源文件的方式将文件调用到内存中。
Qt中加载文件是通过路径“:/new/prefix1/logo.ico”加载的,直接构造对象QPixmap,即可加载图片资源,调用QPixmap的save函数即可将文件保存起来,那么我们写个dll,直接执行这些函数是不是就可以了呢。

获取资源路径的方法

  • CE搜索字符串:/
  • OD、IDA字符串删选:/
  • 关注资源,对应的构造函数,下断点或者IDA查找一下,都能定位资源路径

2️⃣ c++正向编码

编码

由于我使用的MingW的工程写的Demo,我们这里也使用MingW的编译器创建工程mydll,工程为dll工程。内容很简单,创建一个类Mydll,并创建个全局对象Mydll g_dll;,在构造函数中调用保存文件的逻辑,具体代码如下:

Mydll g_dll;
 
Mydll::Mydll()
{
    char *res = ":/new/prefix1/logo.ico";
    QString localname = QString("D") + res;
    QPixmap icon(res);
    icon.save(localname);
    return;
}

使用流程

按照下图方式操作即可,需要使用代码注入器.exe,代码注入CSDN下载地址 https://download.csdn.net/download/kinghzking/87254853
在这里插入图片描述

不使用Qt方式获取思路

如果只有vs,不使用qt,需要构造相关的数据结构,比如QString等;或者直接调用Qt5Core.dll导出函数构造相关的数据结构。简单的包含一此头文件,编译会失败的。

3️⃣ frida方式获取Origin平台资源

frida作为脚本工具,方便调试和试错,一直是一个不错的选择,下面我们讲解怎么使用frida实现图片保存。
其实也就是把《C++正向编码》通过frida实现一遍,其中一些细节需要处理一下。

win32 - 定位目标资源

通过CE搜索Origin.exe进程内.png的字符串
在这里插入图片描述

我们可以查看到一个叫:/origin.png的图片资源。
在这里插入图片描述

win32 - 查找API含义

C++编码中,调用函数有默认值,参数可以忽略不传。但是frida中必须了解所有函数参数,所以我们需要根据官网文档了解函数含义。

从上面文章分析,我们知道,我们需要用到QPixmap的下面两个函数,通过官网文档https://doc.qt.io/Qt-5/qpixmap.html,查看其接口含义

构造函数QPixmap(const QString &fileName, const char *format = nullptr, Qt::ImageConversionFlags flags = Qt::AutoColor)

在这里插入图片描述在这里插入图片描述
最后一个参数传递默认值Qt::AutoColor,也就是0。
在这里插入图片描述

bool save(const QString &fileName, const char *format = nullptr, int quality = -1) const
在这里插入图片描述
在这里插入图片描述

win32 - 查找《符号》构造frida本地函数

通过x64dbg(选32位的,因为Origin是32位的),按照下面步获取到《符号》
在这里插入图片描述

参考frida官网文档 https://frida.re/docs/javascript-api/#nativefunction,编写NativeFunction

// 地址=79157BD0
// 类型=导出
// 序号=530
// 符号=??0QPixmap@@QAE@ABVQString@@PBDV?$QFlags@W4ImageConversionFlag@Qt@@@@@Z
// 符号(已解码)=public: __thiscall QPixmap::QPixmap(class QString const &,char const *,class QFlags<enum Qt::ImageConversionFlag>)
var fnQPixmap_QPixmap2 = new NativeFunction(
  Module.findExportByName('qt5gui.dll', '??0QPixmap@@QAE@ABVQString@@PBDV?$QFlags@W4ImageConversionFlag@Qt@@@@@Z'),
  'pointer', 
  ['pointer', 'pointer', 'pointer', 'int'],
  'thiscall'
);

// 参数含义解析:
// oQPixmap:this指针,作为第一个参数传递进去
// qStrPointer:自己封装的函数,构造一个QString对象,具体看后面的全部代码
// ptr(0): 传递一个值为0的指针
// 0:枚举类型Qt::AutoColor对应的值,frida中直接用整数就行了。
var oQPixmap = Memory.alloc(400);
var qStrPointer = ez_fnQString_fromUtf8(':/origin.png')
fnQPixmap_QPixmap2(oQPixmap, qStrPointer, ptr(0), 0)

win32 - 全部代码


var fnQString_fromUtf8 = new NativeFunction(
  Module.findExportByName('Qt5Core.dll', '?fromUtf8@QString@@SA?AV1@PBDH@Z'),
  'void', 
  ['pointer','pointer', 'int'],
  'mscdecl'
);
function ez_fnQString_fromUtf8(jsStr){
  var retQString = Memory.alloc(Process.pointerSize);
  var cStrPointer = Memory.allocUtf8String(jsStr);
  fnQString_fromUtf8(retQString, cStrPointer, -1);
  return retQString;
}

// 地址=79157C90
// 类型=导出
// 序号=533
// 符号=??0QPixmap@@QAE@QBQBD@Z
// 符号(已解码)=public: __thiscall QPixmap::QPixmap(char const * const * const)
var fnQPixmap_QPixmap = new NativeFunction(
  Module.findExportByName('qt5gui.dll', '??0QPixmap@@QAE@QBQBD@Z'),
  'pointer', 
  ['pointer', 'pointer'],
  'thiscall'
);
// 地址=79157BD0
// 类型=导出
// 序号=530
// 符号=??0QPixmap@@QAE@ABVQString@@PBDV?$QFlags@W4ImageConversionFlag@Qt@@@@@Z
// 符号(已解码)=public: __thiscall QPixmap::QPixmap(class QString const &,char const *,class QFlags<enum Qt::ImageConversionFlag>)
var fnQPixmap_QPixmap2 = new NativeFunction(
  Module.findExportByName('qt5gui.dll', '??0QPixmap@@QAE@ABVQString@@PBDV?$QFlags@W4ImageConversionFlag@Qt@@@@@Z'),
  'pointer', 
  ['pointer', 'pointer', 'pointer', 'int'],
  'thiscall'
);


// 地址=7A0A2E68
// 类型=导入
// 符号=qt5gui.?save@QPixmap@@QBE_NABVQString@@PBDH@Z
// 符号(已解码)=public: bool __thiscall QPixmap::save(class QString const &,char const *,int)const
// bool	save(const QString &fileName, const char *format = nullptr, int quality = -1) const
var fnQPixmap_save = new NativeFunction(
  Module.findExportByName('qt5gui.dll', '?save@QPixmap@@QBE_NABVQString@@PBDH@Z'),
  'void', 
  ['pointer', 'pointer', 'pointer', 'int'],
  'thiscall'
);


function ezSave(uri) {
  // 构造QPixmap
  var oQPixmap = Memory.alloc(400);
  var qStrPointer = ez_fnQString_fromUtf8(':/origin.png')
  console.log('1111111111111111')
  fnQPixmap_QPixmap2(oQPixmap, qStrPointer, ptr(0), 0)
  console.log('2222222222')

  // 保存图片
  var savePath = ez_fnQString_fromUtf8('D:\\origin.png')
  console.log('33333333')
  fnQPixmap_save(oQPixmap, savePath, ptr(0), -1)
  console.log('444444444444')
}

ezSave(':/origin.png')

至此,我们就将资源保存到本地了。
在这里插入图片描述

win64 - TODO

win64和win32调用有差异,需要特殊处理的,以后有需要再写。

🛬 文章小结

  • 不要用中文路径,可能编译失败。
  • debug和release调用的qt库是不一样的,需要特别注意。
  • MingW的工程和VS的工程也是不一样的,需要特别注意。
  • 测试下一个Qt5.6的某exe,使用Qt5.8的dll,依然可以将文件导出。

📖 参考资料

  • github源码 https://github.com/ninecents/MyOpen
  • [Qt] 00_Qt资源解析 https://bbs.pediy.com/thread-250691.htm
  • 代码注入下载地址 https://download.csdn.net/download/kinghzking/87254853
  • Qt官网文档 https://doc.qt.io/Qt-5/qpixmap.html
  • frida官网文档 https://frida.re/docs/javascript-api/#nativefunction

**ps:**文章中内容仅用于技术交流,请勿用于违规违法行为。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/72986.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【ESP32+freeRTOS学习笔记-(一)freeRTOS介绍】

目录FreeRTOS基本情况FreeRTOS的特色发行版的目录结构与文件说明原生程序的下载与目录结构FreeRTOS的主要文件说明头文件说明关于FreeRTOSConfig.h的说明主要的数据类型说明重要数据类型 -- TickType_t重要数据类型 -- BaseType_t一些默认的规则变量名的规则函数的命名规则宏的…

你在网络上发布的内容真的归你所有吗?有Web3.0和元宇宙的未来是什么样的?

欢迎来到Hubbleverse &#x1f30d; 关注我们 关注宇宙新鲜事 &#x1f4cc; 预计阅读时长&#xff1a;9分钟 本文仅代表作者个人观点&#xff0c;不代表平台意见&#xff0c;不构成投资建议。 你认为你在微博、抖音等社交媒体上发布的内容是属于你的吗&#xff1f;事实并非…

Dashed lines generator for 3dMax 虚线生成器插件使用教程

Dashed lines generator虚线生成器是一个3DMAX建模工具&#xff0c;可以通过简单的步骤自动生成所有类型的虚线&#xff1a;它可以用于模拟交通标志标准&#xff1b;使用“蒙皮修改器SKIN MODIFIER”选项&#xff0c;可以非常容易地操纵创建的虚线&#xff0c;更改其位置和方向…

关于Pytorch模型检查点大小和参数量的一些观察

目录 背景和需求 一、模型的参数量统计 二、模型检查点大小查看 三、检查点大小和模型参数量之间的关系 总结 背景和需求 一个Pytorch模型的大小可以从两个方面来衡量&#xff1a;检查点大小和模型的参数量。现在我从两个方面都拿到了具体数值&#xff0c;想要验证它们两个是否…

数据开源 | Magic Data开源DMS驾驶员行为数据集

由于近几年人工智能、芯片技术的发展&#xff0c;自动驾驶被资本市场越炒越热。目前大部分车企正在朝着完全自动驾驶努力&#xff0c;大部分已经落地的无人驾驶技术仍然是L2与L3级。同时&#xff0c;汽车行业也逐渐在汽车上集成了辅助自动驾驶和智能助手等功能&#xff0c;让驾…

C语言结构体详解

邀请加入嵌入式社区&#xff0c;您可以在上面发布问题&#xff0c;博客链接&#xff0c;公众号分享&#xff0c;行业消息&#xff0c;招聘信息等。 目录 结构体有什么用&#xff1f; 结构体声明 正常的结构体声明 匿名结构体 匿名结构体只有在创建的时候可以建立变量 两个…

vuex通过Mutations来修改状态的原理及devtools插件的下载

状态修改&#xff1a; 通过Mutations来修改状态&#xff0c;并配合devtools调试工具会记录这个状态何时被修改过&#xff1b; 好处是因为所有组件都可以访问和修改状态&#xff0c;通过Mutations配合调试工具能知道状态被哪个组件什么时候被修改过&#xff0c;方便追溯&#…

如何让 ChatGPT 写短篇小说?

故事一 请根据下面内容续写故事&#xff0c;要求800字。 在一个晴朗的秋日下午&#xff0c;男主人 Jack 抱着他的妻子 Rose&#xff0c;两人坐在沙发上看着电视。 这是&#xff0c;Jack对Rose说&#xff1a;”亲爱的&#xff0c;我们来玩一个游戏吧。” ChatGPT回答&#xff1a…

华为机试 - 端口合并

目录 题目描述 输入描述 输出描述 用例 题目解析 算法源码 题目描述 有M(1<M<10)个端口组&#xff0c; 每个端口组是长度为N(1<N<100)的整数数组&#xff0c; 如果端口组间存在2个及以上不同端口相同&#xff0c;则认为这2个端口组互相关联&#xff0c;可以…

CentOS部署主从DNS服务器

几个概念&#xff1a; 域名解析为IP地址&#xff1a;正向解析 IP地址解析为域名&#xff1a;反向解析 主DNS服务器&#xff1a;在特定区域内具有唯一性&#xff0c;负责维护该区域内的域名和IP地址之间的对应关系。 从DNS服务器&#xff1a;从服务器中获得域名和IP地址对应关系…

PCIE2PCI104载板转接卡

功能型号 PCIE2PCI104 此无源扩展卡允许开发人员将PCI104或PC/104plus卡安装到通用PCI总线系统中。适配器配备了一个堆栈式连接器。 功能描述 规格 适用于标准&#xff1a;Universal.3.3V或5V PCI插槽 工业温度工作范围&#xff1a;-40至85 C 连接器/接口&#xff1a;包括一个带…

干货 | 肖特基二极管4大特性

前言 肖特基二极管是重要的电子元器件&#xff0c;因为其承载着保护电路的重要作用&#xff0c;所以显得格外的不可或缺&#xff0c;我们都知道在选择肖特基二极管时&#xff0c;主要看它的正向导通压降、反向耐压、反向漏电流等。 但我们却很少知道其在不同电流、不同反向电压…

固定支撑约束在ANSYS有限元计算中的三大注意事项

固定支撑是在结构有限元中&#xff0c;大家最常用的一种约束条件了。如图1所示给出了设置固定支撑操作的方法。 图1 设置固定支撑操作方法 固定支撑约束&#xff0c;可以应用在点&#xff0c;线和面特征上。固定支撑表示被约束为位置为刚性&#xff0c;但是在现实工程结构中&a…

解决“Vector Hardware Manager无法连接This Computer”(能够独立解决问题,体现一个人的综合能力)

1. 引子 Vector Hardware Manager是先前配置工具Vector Hardware Config的继承者,是Vector Hardware Config工具的升级版或替代产品 什么是Vector Hardware Config? CANoe里打开: 界面: 而Vector Hardware Manager其实就是把Vector Hardware Config里的功能搬到了这里实…

UE5 + VS2022和UE4 + VS2019 编译踩坑

1&#xff0c;卡住且没有cl.exe进程 &#xff08;1&#xff09;&#xff0c;卸载Incredibuild&#xff0c;Incredibuild也是利用进程虚拟化技术&#xff0c;加速包括编译的方法&#xff0c;和firstbuild是一样的&#xff0c;所以优先选择了Incredibuild的方式&#xff0c;但是2…

PDF文件添加水印怎么添加?只需要两步轻松添加水印

PDF文件添加水印怎么添加&#xff1f;我们在处理工作文件时&#xff0c;都非常在意文件的隐私性&#xff0c;我们经常会使用一些方法来确保我们文件的内容不被别人窃取&#xff0c;其中一种方法就是给PDF文件添加水印&#xff0c;这样文件的内容就不会轻易被窃取了&#xff01;…

ControllerAdvice统一异常处理失效

问题描述 在common模块增加统一异常处理代码&#xff0c;如下。在service业务处理类中抛出异常&#xff0c; 但是接口返回的为spring统一的500错误。 package com.tea.common.exception; import com.tea.common.entity.ResponseResult; import com.tea.common.entity.Status…

基于java springboot的小说阅读微信小程序含后台管理系统源码

系统运行环境 开发工具 eclipse(idea)&#xff0c;mysql5.7&#xff08;大于5.5&#xff09;&#xff0c;navicat&#xff0c;小程序开发工具 硬件要求 windows操作系统 cpu&#xff1a;2.4GHz 内存&#xff1a;4G 硬盘&#xff1a;100G 开发及运行环境 windows10操作…

ArcGIS基础:栅格数据中的NoData数值(空值)的处理

先看下实验操作数据&#xff0c;也是原始数据&#xff0c;如下所示&#xff1a; 是一个非常普通的DEM栅格数据&#xff0c;中间空了一大块&#xff0c;也就是nodata&#xff0c;那么如果进行数据运算处理时&#xff0c;nodata值的像元是不参与&#xff0c;因此&#xff0c;需要…

Google Earth Engine(GEE)——将每小时降水量转化为逐日的降水量

很多时候我们获取影像的时间分辨率为逐小时,但是如何获取影像的累积降水量?这里的整体思路就是获取不同时间影像的时间序列,然后分别获取每天的降水量,最后同一秋累计值,如果要进行时序图片展示的情况,我们就可以再秋累计值的时候就可以建立一个时间属性,这样可以建立时…