CTF Show逆向4reserve wp--mingyue

news2024/9/20 16:32:33

(本题难度较大,分析起来比较复杂,针对该题本文对其中比较重要的部分做了较详细的概述,有问题的地方,请指正)

第一步    查壳。本题为64位

第二步 各部分函数分析

(一)

分析main函数。

函数签名

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)

  • int __cdecl __noreturn:这表明这是一个main函数,使用__cdecl调用约定,且带有__noreturn修饰符,这表示该函数永远不会返回。这个修饰符通常用于那些程序会在函数结束时终止进程的情况下,比如通过调用exit()或是进入一个无限循环。
  • main(int argc, const char **argv, const char **envp):这是标准的main函数签名,其中:
    • argc是命令行参数的数量。
    • argv是指向参数字符串的指针数组。
    • envp是指向环境变量字符串的指针数组。

变量定义

qword_140004618 = (__int64)malloc(0x10ui64);

qword_140004620 = qword_140004618;

  • qword_140004618 和 qword_140004620 是两个全局变量,可能是64位整型的变量(从名字中的qword可以推测)。具体来看:
    • qword_140004618 = (__int64)malloc(0x10ui64);:调用malloc分配了16字节(0x10ui64)的内存,并将其地址转换为__int64类型,存储在qword_140004618中。
    • qword_140004620 = qword_140004618;:将qword_140004618的值(即刚分配的内存地址)复制到qword_140004620。

内存操作

*(_QWORD *)(qword_140004618 + 8) = 0i64;

  • *(_QWORD *)(qword_140004618 + 8) = 0i64;:这是一个指针操作,具体做了以下事情:
    • qword_140004618 + 8计算了刚刚分配内存块的第8个字节位置。
    • _QWORD代表64位的整数类型,*(...)表示解引用。
    • 这行代码把0存储在内存块的第8到第15字节位置。

也就是说,分配的16字节内存中,第8个字节到第15个字节的位置被设置为0

字符串输出与输入

sub_140001020("请输入正确的数字:\n");

sub_140001080("%lld");

  • sub_140001020("请输入正确的数字:\n");:调用函数sub_140001020,参数是一个字符串 "请输入正确的数字:\n",这个函数可能是用于输出提示信息的,比如让用户输入数字。
  • sub_140001080("%lld");:调用另一个函数sub_140001080,参数为格式化字符串"%lld",这个函数可能是用于接收输入的。"%lld"是用于读取长长整型(long long)的格式说明符。

函数调用

((void (__fastcall *)())sub_1400010E0)();

  • ((void (__fastcall *)())sub_1400010E0)();:这是一个类型转换和调用,分两部分:
    • ((void (__fastcall *)())sub_1400010E0)将sub_1400010E0函数指针转换为一个使用__fastcall调用约定的函数指针,该函数不带参数且返回类型为void。
    • ()紧接在这个类型转换后的指针上,表示立即调用这个函数。

小结一下:

  1. 分配了一段16字节的内存,将其地址保存到两个全局变量qword_140004618和qword_140004620中。
  2. 将分配内存的第8到第15字节位置设置为0。
  3. 输出提示信息要求用户输入一个数字。
  4. 可能通过格式化字符串读取用户输入。
  5. 最后调用了一个sub_1400010E0的函数指针

(二)

分析sub_140001020

函数签名:

int sub_140001020(char *Format, ...)

这个函数名为 sub_140001020,返回类型是 int,接受一个字符指针(char *Format)和可变参数(...)。函数中的 Format 通常用于格式化输出。

局部变量:

FILE *v2; // rbx

unsigned __int64 *v3; // rax

va_list va; // [rsp+58h] [rbp+10h] BYREF

  • v2 是一个指向 FILE 类型的指针,保存在寄存器 rbx 中。
  • v3 是一个指向 unsigned __int64 类型的指针,保存在寄存器 rax 中。
  • va 是一个 va_list 类型的变量,用来处理可变参数列表。

可变参数处理:

va_start(va, Format);

  • va_start 宏初始化 va_list 变量,准备访问可变参数列表。这里的 va 变量将会存储传递给函数的可变参数信息。

获取标准输出流:

v2 = _acrt_iob_func(1u);

  • _acrt_iob_func 是一个微软C运行时库(CRT)中的内部函数,通常用于获取标准输入输出流。
  • _acrt_iob_func(1u) 返回标准输出流 stdout,即 v2 指向标准输出的 FILE 对象。

调用另一个函数:

v3 = (unsigned __int64 *)sub_140001000();

  • sub_140001000 是另一个函数,被调用后返回一个 unsigned __int64 * 类型的指针,并赋值给 v3。这个指针可能指向某种控制结构或特定数据。

执行格式化输出:

return _stdio_common_vfprintf(*v3, v2, Format, 0i64, va);

  • _stdio_common_vfprintf 是一个低级别的格式化输出函数,它负责处理带有可变参数的格式化输出。
  • 这个函数的参数分别为:
    • *v3: 通过解引用 v3 得到的值,这个值可能代表某种标志或格式化选项。
    • v2: 指向标准输出的 FILE 对象。
    • Format: 字符串格式,用于定义如何格式化输出。
    • 0i64: 通常是一个与选项标志相关的值,这里指定为0。
    • va: 处理后的可变参数列表。
  • 函数的返回值是 _stdio_common_vfprintf 的返回值,即该函数成功写入的字符数,或者是遇到错误时的负值。

(三)

分析sub_140001080

  1. 函数声明:

int sub_140001080(char *Format, ...)

  1. 这是一个函数定义,返回类型为int,接受一个格式化字符串Format作为第一个参数,以及一个可变参数列表。

  1. 局部变量声明:

FILE *v2; // rbx

_QWORD *v3; // rax

va_list va; // [rsp+58h] [rbp+10h] BYREF

  1. v2 是一个指向 FILE 结构的指针(通常用于表示文件流)。
  2. v3 是一个 _QWORD 类型的指针,通常 _QWORD 是一个 64 位整数类型,用于存储 8 字节的数据。
  3. va_list va 是一个用于存储可变参数列表的对象。

     3.初始化可变参数列表:

va_start(va, Format);

  1. 使用 va_start 宏初始化 va_list 对象 va,并使其指向 Format 之后的第一个可变参数。

      4.获取标准输入流:

v2 = _acrt_iob_func(0);

  1. _acrt_iob_func(0) 是一个获取标准输入流 stdin 的函数,返回一个指向 FILE 结构的指针,并赋值给 v2

      5.调用非标准库函数:

v3 = (_QWORD *)sub_140001010();

  1. sub_140001010 是一个自定义的函数,返回一个 _QWORD 类型的指针,并将其结果赋值给 v3。该函数的具体实现未知,但返回值的使用表明它可能与格式化输入处理相关。

       6.调用标准库函数:

return _stdio_common_vfscanf(*v3 | 1i64, v2, Format, 0i64, va);

  1. _stdio_common_vfscanf 是一个底层标准输入函数,用于根据提供的 Format 格式从 v2(通常是 stdin)中读取输入,并将结果存储到与可变参数 va 对应的变量中。
  2. *v3 | 1i64 代表对返回的 _QWORD 指针进行位或操作,可能是设置某个标志位(具体用途取决于 sub_140001010 的实现)。

(四)

进入sub_1400010E0(重点)

      1.变量初始化和赋值:

v2 = 0;

v3 = (__int64)a1;

v2被初始化为0v3被赋值为a164位整型值。

      2.条件判断和循环:

if ( a1 )

{

    v4 = &v9;

    do

    {

        ++v4;

        ++v2;

        a1 = &a4890572163qwe[-26 * (v3 / 26)];

        v5 = a1[v3];

        v3 /= 26i64;

        a2 = v3;

        *(v4 - 1) = v5;

    }

    while ( v3 );

}

a1不为空的情况下执行。它初始化v4v9的地址,然后进入一个do-while循环:

  • ++v4;:v4指针递增,指向下一个元素。
  • ++v2;:v2计数器递增。
  • a1 = &a4890572163qwe[-26 * (v3 / 26)];:这里有一个数组a4890572163qwe,a1被重新赋值为该数组的一个元素地址,该元素的索引是通过v3除以26并乘以-26计算得到的。
  • v5 = a1[v3];:v5被赋值为a1指针所指向的数组元素的值。
  • v3 /= 26i64;:v3整除26。
  • a2 = v3;:将v3的值赋给a2。
  • *(v4 - 1) = v5;:将v5的值赋给v4指针前一个位置的元素。

循环继续执行,直到v30

        3.第二个循环:

v6 = v2;

while ( v6 )

{

    v7 = *(&v8 + v6--);

    sub_1400011E0(v7 ^ 7u, a2, v3);

}

这里,v6被赋值为v2,然后进入一个while循环:

  • v7 = *(&v8 + v6--);:v7被赋值为v8偏移v6个位置的元素的值,然后v6递减。
  • sub_1400011E0(v7 ^ 7u, a2, v3);:调用一个名为sub_1400011E0的函数,传入参数为v7与7进行异或操作的结果、a2和v3。

循环继续执行,直到v60

        4.函数调用:

sub_140001220(a1, a2, v3);

最后,调用一个名为sub_140001220的函数,传入参数为a1a2v3

(五)

进入sub_140001220(重点)

  1. 变量初始化:

v0 = qword_140004620;

v1 = 0;

v2 = 0i64;

v0被初始化为全局变量qword_140004620的值,v1v2分别被初始化为0。

       2.无限循环:

while ( 1 )

{

这里是一个无限循环,它将一直执行直到遇到break语句。

      3.循环体内的操作:

v3 = *(_BYTE *)v0;

v4 = v1 + 1;

v5 = *(_QWORD *)(v0 + 8);

  • v3被赋值为v0指向的字节。
  • v4被赋值为v1加1。
  • v5被赋值为v0加8地址处的64位值。

      4.条件判断和赋值:

if ( v3 != aV4pY59[v2 - 1] )

  v4 = v1;

qword_140004620 = v5;

if ( !v5 )

  break;

  • 如果v3不等于数组aV4pY59中v2-1索引处的值,则v4被重新赋值为v1。
  • 更新全局变量qword_140004620为v5的值。
  • 如果v5为0,则退出循环。

      5.更多的循环体内操作:

v6 = *(_BYTE *)v5;

v7 = v4 + 1;

v0 = *(_QWORD *)(v5 + 8);

if ( v6 != aV4pY59[v2] )

  v7 = v4;

qword_140004620 = v0;

  • v6被赋值为v5指向的字节。
  • v7被赋值为v4加1。
  • v0被赋值为v5加8地址处的64位值。
  • 如果v6不等于数组aV4pY59中v2索引处的值,则v7被重新赋值为v4。
  • 更新全局变量qword_140004620为v0的值。

    6.更新循环变量:

if ( v0 )

{

  v2 += 2i64;

  v1 = v7;

  if ( v2 < 14 )

    continue;

}

  • 如果v0不为0,则v2增加2,v1被赋值为v7。
  • 如果v2小于14,则跳过后续代码,继续下一次循环。

     7.无条件跳转:

goto LABEL_11;

如果v00v2等于或大于14,则跳转到标签LABEL_11

     8.循环结束后的操作:

v7 = v4;

LABEL_11:

if ( v7 == 14 )

  sub_1400012E0();

sub_1400012B0();

  • 循环结束后,v7被赋值为v4。
  • 如果v7等于14,则调用函数sub_1400012E0。
  • 不论条件如何,都会调用函数sub_1400012B0。

以上两个数组如下

第三步   编写脚本

分析一下脚本:

1. 变量定义

a4890572163qwe = ")(*&^%489$!057@#><:2163qwe"

aV4pY59 = "/..v4p$!>Y59-"

2. equal 函数

def equal(a, str1):

    for i in range(0, 26):

        if str1[i] == a:

            return i

    return -1

  • equal 函数的作用是:在 str1 的前 26 个字符中找到字符 a 的位置(索引)。如果找到了,就返回这个索引;如果没找到,则返回 -1。
  • 注意,这里假设 str1 至少有 26 个字符,否则可能会引发越界错误。

3. 主体逻辑分析

flag = 0

newarray = []

for i in range(14):

    flag *= 26

 

    if i < len(aV4pY59):

        index = equal(chr(ord(aV4pY59[i]) ^ 7), a4890572163qwe)

        newarray.append(index)

        flag += index

    else:

        break 

  • 初始化 flag 为 0 和 newarray 为空列表。
  • 进入一个循环,循环次数为 14 次。

循环体内的操作:

  • 每次循环开始时,flag 被乘以 26,这意味着 flag 正在逐步扩展为一个 26 进制数。
  • 接下来,通过判断 i < len(aV4pY59),确保不会超出 aV4pY59 的长度。
  • 通过 ord(aV4pY59[i]) ^ 7 对 aV4pY59 中第 i 个字符执行异或操作,得到一个新的字符,然后用 chr() 将其转化为对应的字符。
  • 使用 equal 函数查找这个新字符在 a4890572163qwe 中的位置(索引),并将结果保存到 index 中。
  • 将 index 添加到 newarray 中,同时将 index 累加到 flag 上。
  • 如果 i 达到了 aV4pY59 的长度,则退出循环。

验证成功

flag{2484524302484524302}

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

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

相关文章

达梦数据库事务管理

目录 一、事务简介 二、事务特性 1.原子性 2.一致性 3.隔离性 4.持久性 三、事务提交 1.自动提交模式 2.手动提交模式 3.隐式提交 四、事务回滚 1.自动回滚 2.手动回滚 3.回滚到保存点 4.语句级回滚 五、事务锁定 1.锁模式 &#xff08;1&#xff09;共享锁 …

WebGIS与WebGL是什么,两者之间的关系?

WebGL和 WebGlS 都是 web 技术领域的重要内容&#xff0c;特别是这几年webgis开发领域&#xff0c;和webgl打交道是必然的&#xff0c;常见的WebGL开发的基础上&#xff0c;比如二维的Leaflet、三维的Cesium也都是热门。 WebGL是一种基于 HTML5 Canvas 元素的 JavaScriptAPI&a…

sqli-labs靶场通关攻略(61-65)

Less-61 步骤一&#xff1a;查看数据库 ?id1)) and updatexml(1,concat(1,(select database())),1)-- 步骤二&#xff1a;查看表名 ?id1)) and updatexml(1,concat(1,(select group_concat(table_name) from information_schema.tables where table_schemasecurity)),1)--…

【专题】2024年中国游戏出海洞察报告合集PDF分享(附原数据表)

原文链接&#xff1a;https://tecdat.cn/?p37570 2023 年全球游戏市场规模高达 6205.2 亿美元&#xff0c;且预计未来持续增长&#xff0c;这清晰地展示了该市场的巨大潜力和良好前景。 中国游戏在全球移动游戏市场的份额于 2023 年已达 37%&#xff0c;产业贡献超 30% 的市场…

手动添加jar包到本地仓库

依赖包不存在于任何的maven仓库中&#xff0c;所以要手工添加进本地仓库&#xff0c;过程如下&#xff1a; 将EasyModbusJava.jar包复制到maven目录的 bin目录下&#xff1b;执行cmd到该bin目录路径下执行以下指令 mvn install:install-file -DfileEasyModbusJava.jar -Dgroup…

C++笔记15•数据结构:二叉树之二叉搜索树•

二叉搜索树 1.二叉搜索树 概念&#xff1a; 二叉搜索树又称二叉排序树也叫二叉查找树&#xff0c;它可以是一棵空树。 二叉树具有以下性质: 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值 若它的右子树不为空&#xff0c;则右子树上所有节点的值都…

STM32CubeMX CAN收发数据

目录 一、CAN总线 1. 差分信号 2. CAN收发器 3. CAN帧结构 4. CAN波特率设置 5. 标识符筛选 二、CubeMX配置 三、Keil代码 一、CAN总线 CAN&#xff08;Controller Area Network&#xff0c;控制器局域网络&#xff09;是一种用于车辆、工业自动化等领域的通信协议&…

数分基础(05)中心极限定理、假设检验与AB测试简介

文章目录 1. 中心极限定理1.1 概念1.2 直观理解1.3 重要性 2. 示例2.1 数据集2.2 验证思路&#xff08;1&#xff09;获取一个样本均值&#xff08;2&#xff09;假设抽取1000次&#xff08;3&#xff09;增大样本容量 2.3 实现2.4 结果 2. 假设检验2.1 总体思路2.2 比较两种运…

环信高质量全球网络——70%丢包环境,消息100%送达,抗弱网能力大幅提升!

在当今数字化时代&#xff0c;稳定而高效的即时通讯已成为企业和个人不可或缺的工具。环信即时通讯&#xff08;IM&#xff09;云服务一直致力于为用户提供优质的通信体验。如今&#xff0c;环信IM通过自研传输协议&#xff0c;实现了在弱网环境下的卓越表现&#xff0c;确保消…

.NET 一款具备签名用于绕过防护的工具

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

踩坑-pycharm-终端闪退

问题&#xff1a; pycharm打开终端&#xff0c;终端直接闪退&#xff0c;打开其他项目&#xff0c;没事 原因&#xff1a; 之前在其他项目下载了allure&#xff0c;不知道怎么终端的path改了 解决&#xff1a; 此处&#xff0c;终端路径修改为如下即可&#xff1a;

HTML+CSS+Query实现二级菜单

在网页设计中&#xff0c;导航菜单是非常重要的部分之一&#xff0c;尤其是具有二级下拉菜单的导航栏&#xff0c;可以提升用户体验。本文将通过HTML、CSS和jQuery实现一个具有二级菜单标题的导航栏&#xff0c;并详细讲解每一步的实现过程。 <!DOCTYPE html> <html …

[数据集][目标检测]街头摊贩识别检测数据集VOC+YOLO格式758张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;758 标注数量(xml文件个数)&#xff1a;758 标注数量(txt文件个数)&#xff1a;758 标注类别…

信捷 XD PLC 双精度浮点数的初始化及传输

在用信捷XDH PLC进行运动控制时&#xff0c;加减速时间是个64位的双精度的浮点数&#xff0c;那么如果不在人机界面写到PLC&#xff0c;PLC自身也是可以初始化的&#xff0c;比如0.005,怎么办呢。 用FLT指令把 整数出单精度浮点数&#xff0c;然后EDIV指令把两个单精度浮点数相…

2025第五届广州国际新能源汽车产业智能制造技术展览会

2025第五届广州国际新能源汽车产业智能制造技术展览会 展会时间&#xff1a;2025年11月20日-22日 展会地点&#xff1a;广州保利世贸博览馆(PWTC Expo) 主题&#xff1a;能源绿色化&#xff0c;制造低碳化 400多家参展商&#xff1b;20000多名观众&#xff1b;20000平方米展出…

mysql索引,事务,约束

MySQL事务 1.什么事务 用于保证数据的一致性,它是由一组相关的dml语句组成,该租的dml语句要么全部成功要么全部失败. 2.事务和锁 当执行事务操作时(dml),MySQL会在表上加锁,防止其它用户改表的数据,这对用户来说很重要 mysql 数据库控制台事务的几个重要操作(基本操作 tra…

鸿蒙开发—黑马云音乐之播放页面(下)

目录 1.用户随意控制播放进度 2.歌曲暂停和播放控制和歌曲上一首、下一首播放控制 3.歌曲列表 4.歌曲列表数据动态化和背景雾化 5.唱针效果 6.结语 1.用户随意控制播放进度 src/main/ets/services/AvPlayerManager.ets&#xff1a; // 让播放对象从某个时间点开始播放 …

本地大语言模型部署及应用

01 模型 2024-07-24&#xff0c;Meta 正式发布新一代开源大模型 Llama 3.1 系列&#xff0c;该模型共有三个版本&#xff1a; 8B70B405B meta评估了超过 150 个语言覆盖范围广的基准数据集。比较了 Llama 3.1 与竞争性模型在真实世界场景下的表现。实验评估表明&#xff0c;L…

动态住宅IP代理的搭建指南:实现高效网络访问

在互联网的复杂环境中&#xff0c;动态住宅IP代理逐渐成为提升网络隐私和绕过IP限制的热门选择。相比于数据中心代理IP&#xff0c;动态住宅IP代理具有更高的隐蔽性和真实性&#xff0c;能够有效模拟真实用户的网络行为。本文将详细介绍动态住宅IP代理的搭建方法&#xff0c;帮…

iPhone、微信二选一?苹果、腾讯官方回应

KlipC报道&#xff1a;9月2日&#xff0c;有消息称&#xff0c;腾讯和苹果正在就APPStore的抽成问题在不断交涉&#xff0c;如若谈崩有可能导致微信下架&#xff0c;iPhone一旦升级到 iOS 18.2 系统可能将无法使用微信。 对此&#xff0c;苹果中国区技术顾问表示&#xff0c;“…