C/C++逆向:循环语句逆向分析

news2024/9/26 1:29:01

在逆向分析中,循环语句通常会以特定的汇编模式或结构体现出来。常见的循环语句包括 for 循环、while 循环和 do-while 循环。由于不同的编译器会根据代码优化的级别生成不同的汇编代码,分析循环的模式也可能会有所不同。以下是三种常见循环语句的汇编分析要点:

1. for循环的逆向分析

典型的 C 代码:

for (int i = 0; i < n; i++) {
    // 循环体
}
汇编特征:
初始化:i = 0 通常表现为一个寄存器赋初始值。
条件检查:比较寄存器与终止条件(如 n),可能使用跳转指令如 JLE、JGE。
循环体:位于条件检查后的指令块。
递增:通过 ADD 或 INC 操作来递增寄存器的值。
汇编示例:
mov     eax, 0          ; 初始化 i = 0
cmp     eax, n          ; 比较 i 和 n
jge     end_loop        ; 如果 i >= n,跳转到 end_loop
loop_body:              ; 循环体开始
; (循环体指令)
add     eax, 1          ; 递增 i
cmp     eax, n          ; 再次比较 i 和 n
jl      loop_body       ; 如果 i < n,跳回到 loop_body
end_loop:               ; 结束
逆向分析技巧:

找到初始化的代码片段,如给寄存器赋值的操作;寻找条件比较部分,通常使用 CMP 或 TEST,接着跟踪跳转指令(如 JLE, JL),确定循环的边界。递增操作(ADD, INC)通常位于循环体的末尾或条件检查前。

2.while 循环的逆向分析

典型的 C 代码:

while (i < n) {
    // 循环体
}

汇编特征:

条件检查:在进入循环体之前,首先比较寄存器的值,若不满足条件则直接跳出循环。
循环体:条件检查通过后,执行循环体代码。
递增:递增通常在循环体内完成,然后再次检查条件。
汇编示例:
cmp     eax, n          ; 比较 i 和 n
jge     end_while       ; 如果 i >= n,跳转到 end_while
while_body:             ; 循环体开始
; (循环体指令)
add     eax, 1          ; 递增 i
cmp     eax, n          ; 比较 i 和 n
jl      while_body      ; 如果 i < n,跳回到 while_body
end_while:              ; 结束

当条件和索引的初始值都确定的情况下,编译器可以判断第一次会不会执行

逆向分析技巧:

条件检查通常位于循环体之前,通过 CMP 和跳转指令控制,循环体代码位于条件检查之后,跟踪跳转位置可以定位循环体的结束。确定计数器或条件变量的更新位置,并检查跳转逻辑。

3.do-while 循环的逆向分析

典型的 C 代码:

do {
    // 循环体
} while (i < n);
汇编特征:
循环体:无条件执行一次循环体。
条件检查:循环体执行后检查条件,决定是否跳回循环。
跳转:条件满足时跳回到循环体的起始处。
汇编示例:
do_while_body:          ; 循环体开始
; (循环体指令)
add     eax, 1          ; 递增 i
cmp     eax, n          ; 比较 i 和 n
jl      do_while_body   ; 如果 i < n,跳回到 do_while_body
逆向分析技巧:

do-while 循环的特点是循环体在条件检查之前执行,因此逆向时首先识别无条件执行的代码块,条件检查位于循环体之后,查看 CMPTEST 等操作判断是否跳回;循环体通常使用跳转指令(如 JL, JG)回到循环体开头。

逆向分析示例

下面是一个包含 for 循环、while 循环 和 do-while 循环的 C 代码示例,我们可以将它编译成可执行文件,使用IDAx64dbg进行逆向分析,观察它们对应的汇编代码差异。

#include <stdio.h>
​
int main() {
    int sum_for = 0;
    int sum_while = 0;
    int sum_do_while = 0;
​
    // for 循环
    for (int i = 0; i < 5; i++) {
        sum_for += i;
    }
​
    // while 循环
    int j = 0;
    while (j < 5) {
        sum_while += j;
        j++;
    }
​
    // do-while 循环
    int k = 0;
    do {
        sum_do_while += k;
        k++;
    } while (k < 5);
​
    printf("sum_for: %d\n", sum_for);
    printf("sum_while: %d\n", sum_while);
    printf("sum_do_while: %d\n", sum_do_while);
    system("pause");
    return 0;
}

此时使用Visual Studio对该代码进行编译,生成exe文件,对应的编译配置为Debug-x86;本文只针对Debug-x86程序进行分析,其他编译配置分析方式也大同小异。

静态分析:

将生成的程序载入IDA中进行静态分析

在为了不模糊重点,我们直接在Functon Window中定位main函数(关于定位main函数的各种方法有兴趣请查看前面的文章)。

接下去开始逐步对进行代码分析,正文代码从后线以下开始:

首先代码先初始化了四个局部变量var_8var_14var_20var_2C,并将其值全部设置为0。

mov     [ebp+var_8], 0
mov     [ebp+var_14], 0
mov     [ebp+var_20], 0
mov     [ebp+var_2C], 0
jmp     short loc_41185F

在初始化变量后进行了跳转,跳转的目标地址为loc_41185F

①for循环

可以看到在跳转到loc_41185F时,中间跳过了三条指令,这三条指令做的就是自增的操作,我们就可以通过这个特征就判断出这段代码就是for循环结构(该特征是for循环和while循环最明显的区别),接着我们来解析以下这个代码:

loc_411856:                             ; CODE XREF: _main+5E↓j
                mov     eax, [ebp+var_2C]
                add     eax, 1
                mov     [ebp+var_2C], eax
loc_41185F:                             ; CODE XREF: _main+44↑j
                cmp     [ebp+var_2C], 5
                jge     short loc_411870
                mov     eax, [ebp+var_8]
                add     eax, [ebp+var_2C]
                mov     [ebp+var_8], eax
                jmp     short loc_411856

跳转至loc_41185F后:cmp [ebp+var_2C], 5局部变量var_2C先于5进行比较(可以看出来5就是这个循环的边界值),jge short loc_411870若局部变量var_2C大于等于5则跳转到loc_411870地址(也就是跳出循环),若不大于则继续往下执行。 mov eax, [ebp+var_8]var_8的值存入寄存器eaxadd eax, [ebp+var_2C]将局部变量的var_2C的值于eax中的值相加,mov [ebp+var_8], eax再将eax中存储的两数之和存储至var_8中。jmp short loc_411856最后跳转至loc_411856地址处执行局部变量var_2C自增代码。自增完成后再执行loc_41185F处指令。

总结:
初始化:var_2C 初始化为 0。
条件检查:每次循环开始时,比较 var_2C 是否小于 5。
递增计数器:在每次循环结束时,var_2C 增加 1。
累加操作:每次循环中,将 var_2C 的值加到 var_8 中。
循环终止:当 var_2C >= 5 时,跳出循环。

伪代码如下:

for(int var_2C = 0;var_2C < 5;var_2C++);
{
    var_8 += var_2C;
}
②while循环

根据上述代码可知第一个循环结束后跳出循环,来到地址loc_411870进行执行,代码如下:

loc_411870:                             ; CODE XREF: _main+53↑j
                mov     [ebp+var_38], 0
loc_411877:                             ; CODE XREF: _main+7F↓j
                cmp     [ebp+var_38], 5
                jge     short loc_411891
                mov     eax, [ebp+var_14]
                add     eax, [ebp+var_38]
                mov     [ebp+var_14], eax
                mov     eax, [ebp+var_38]
                add     eax, 1
                mov     [ebp+var_38], eax
                jmp     short loc_411877

mov [ebp+var_38], 0将局部变量 var_38 初始化为 0,这个变量可能是用作循环计数器。

cmp [ebp+var_38], 5比较 var_38 的值和 5,var_38 是循环计数器。

jge short loc_411891如果 var_38 的值大于或等于 5,则跳转到 loc_411891,这意味着循环结束(跳出循环)。

mov eax, [ebp+var_14]将局部变量 var_14 的值加载到 eax 寄存器中。var_14 可能是一个用于累加的变量。

add eax, [ebp+var_38]var_38(循环计数器)的值加到 eax 中。

mov [ebp+var_14], eax将累加后的结果存回 var_14,即更新了累加器。

mov     eax, [ebp+var_38]
add     eax, 1
mov     [ebp+var_38], eax

后面三条指令就是对var_38局部变量进行自增的操作。

最后jmp short loc_411877无条件跳转到 loc_411877,重新执行循环体,继续下一次迭代。

这段代码是一个典型的 while循环,其中 var_38 是一个循环计数器,从 0 开始,直到计数器达到 5 时结束循环。循环中,var_38 的值不断累加到 var_14 中。

伪代码表示如下:

int var_38 = 0;  // 计数器初始化
while (var_38 < 5) {
    var_14 += var_38;  // 累加操作
    var_38++;  // 计数器递增
}
③do-while循环

第二个循环结束后,根据上述代码可知跳入第三个循环loc_411891(红线以上部分):

loc_411891:                             ; CODE XREF: _main+6B↑j
                mov     [ebp+var_44], 0
loc_411898:                             ; CODE XREF: _main+9E↓j
                mov     eax, [ebp+var_20]
                add     eax, [ebp+var_44]
                mov     [ebp+var_20], eax
                mov     eax, [ebp+var_44]
                add     eax, 1
                mov     [ebp+var_44], eax
                cmp     [ebp+var_44], 5
                jl      short loc_411898

mov [ebp+var_44], 0始化局部变量 var_44 为 0。var_44 作为循环计数器,用来控制循环执行的次数。

mov eax, [ebp+var_20]将局部变量 var_20 的值加载到 eax 寄存器中。var_20 可能是一个用于累加操作的变量。

add eax, [ebp+var_44]var_44(计数器)的值加到 eax 中,累加操作。

mov [ebp+var_20], eax将累加后的结果存回 var_20,更新累加器。

mov eax, [ebp+var_44]将计数器 var_44 的值加载到 eax 寄存器中。

add     eax, 1
mov     [ebp+var_44], eax
cmp     [ebp+var_44], 5

后面三条指令则是局部变量var_44(循环计数器)自增。

cmp [ebp+var_44], 5比较 var_44 和 5,判断计数器是否小于 5。

jl short loc_411898如果 var_44 小于 5,则跳转回 loc_411898,继续循环。这是一个 "jump if less" 指令,意味着只要 var_44 小于 5,循环继续。

总结

这段代码实现了一个 do-while 循环,其中 var_44 作为循环计数器,从 0 开始,每次循环中都会将计数器的值累加到 var_20,直到计数器达到 5 后,循环结束。

伪代码表示如下:

int var_44 = 0;
do {
    var_20 += var_44;  // 累加操作
    var_44++;  // 计数器递增
} while (var_44 < 5);

最后一部分代码则是分别打印第一个循环到第三个循环获得的值,并执行system(pause)代码。

分析起来比较简单且并不是本文重点,所以就不再赘述了。

动态分析

动态分析代码与静态分析基本一致,在这我们将特征代码进行标注:

①for循环

②while循环

③do-while循环

动态分析代码与静态分析基本一致,这边就不再过多赘述了。

在逆向分析循环语句的过程中,通过仔细观察循环的初始化、条件判断和循环体的逻辑,我们能够准确识别出不同类型的循环结构,如 forwhiledo-while。这些循环的识别不仅帮助我们理解程序的控制流,还为进一步的分析和优化提供了线索。无论是通过静态分析还是动态调试,掌握循环的逆向分析方法将大大提高我们对程序行为的洞察力,并为复杂程序的深入解析奠定基础。

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

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

相关文章

【源码+文档+调试讲解】人事管理系统设计与实现Python

摘 要 人事管理系统的目的是让使用者可以更方便的将人、设备和场景更立体的连接在一起。能让用户以更科幻的方式使用产品&#xff0c;体验高科技时代带给人们的方便&#xff0c;同时也能让用户体会到与以往常规产品不同的体验风格。 与安卓&#xff0c;iOS相比较起来&#xff…

【数据结构】剖析二叉树(Binary Tree)

目录 &#x1f4af;引言 &#x1f4af;二叉树的定义与基本概念 &#xff08;一&#xff09;定义 &#xff08;二&#xff09;节点结构 &#xff08;三&#xff09;二叉树的形态 &#x1f4af;二叉树的遍历 &#xff08;一&#xff09;前序遍历&#xff08;Preorder Trav…

机器人控制器设计与编程基础实验高效版本-ESP32等单片机实验报告

只需要课程大纲或进度表wokwi 大模型工具&#xff0c;就可以完全掌握嵌入式系统基础实验的所有核心点。 LCD // Learn about the ESP32 WiFi simulation in // https://docs.wokwi.com/guides/esp32-wifi https://wokwi.com/projects/321525495180034642#include <WiFi.h>…

【AI学习】Lilian Weng:What are Diffusion Models?

读OpenAI 的 Lilian Weng博客《What are Diffusion Models?》 文章链接:https://lilianweng.github.io/posts/2021-07-11-diffusion-models/ 通过浏览器的在线翻译&#xff0c;直接截图了。翻译的有些问题&#xff0c;但是基本能大概看明白了。 我只是个人的记录&#xff0c;…

开发经验总结: 读写分离简单实现

背景 使用mysql的代理中间件&#xff0c;某些接口如果主从同步延迟大&#xff0c;容易出现逻辑问题。所以程序中没有直接使用这个中间件。 依赖程序逻辑&#xff0c;如果有一些接口可以走读库&#xff0c;需要一个可以显示指定读库的方式来连接读库&#xff0c;降低主库的压力…

降准降息一揽子措施点燃 A 股激情,4% 大涨之后趋势深度剖析

文章目录 牛回速归原因分析引爆点情绪和信心一根大阳线&#xff0c;千军万马来相见阴霾是否一扫而空还未可知 流动性和增量 潜在隐患等待经济复苏配套政策期待中美关系进展 短期内趋势分析空军短期内仍有余力如何看待第2日的回撤外围 趋势分析结论短期内可能仍有波折中长期会是…

【数学分析笔记】第3章第4节闭区间上的连续函数(1)

3. 函数极限与连续函数 3.4 闭区间上的连续函数 3.4.1 有界性定理 【定理3.4.1】 f ( x ) f(x) f(x)在闭区间 [ a , b ] [a,b] [a,b]上连续&#xff0c;则 f ( x ) f(x) f(x)在闭区间 [ a , b ] [a,b] [a,b]上有界。 【证】用反证法&#xff0c;假设 f ( x ) f(x) f(x)在 [ …

2-103 基于matlab的光电信号下血氧饱和度计算

基于matlab的光电信号下血氧饱和度计算&#xff0c;光转换成电信号时&#xff0c;由于动脉对光的吸收有变化而其他组织对光的吸收基本不变&#xff0c;得到的信号就可以分为直流DC信号和交流AC信号。提取AC信号&#xff0c;就能反应出血液流动的特点。这种技术叫做光电容积脉搏…

【Linux学习】2-1 Linux系统下运行C语言输出hello word

1.双击打开VMware软件&#xff0c;点击开启此虚拟机后&#xff0c;等待点击头像输入密码进入 2.“CtrlAltt”调出命令行终端&#xff0c;输入命令sudo apt-get install vim安装vim&#xff0c;输入命令sudo apt-get install gcc安装gcc 3.输入命令vi hello.c进入C语言编写环境&…

Linux —— Socket编程(一)

一、本篇重点 1. 认识IP地址、端口号、网络字节序等网络编程中的基本概念 2. 学习Socket api的基本用法 3. 能够实现一个简单的udp客户端/服务器 二、基本概念 1. 理解源IP地址和目的IP地址 简单的理解&#xff0c;IP地址是用于标识一台机器的&#xff0c;我们通过IP地址去…

使用 UWA Gears 测试小游戏性能

UWA Gears 是UWA最新发布的无SDK性能分析工具。针对移动平台&#xff0c;提供了实时监测和截帧分析功能&#xff0c;帮助您精准定位性能热点&#xff0c;提升应用的整体表现。 随着小游戏的规模和用户量持续增长&#xff0c;玩家对于小游戏的性能要求也越来越高。为了能够给玩…

力扣234 回文链表 Java版本

文章目录 题目描述代码 题目描述 给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为 回文链表 。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,2,1] 输出&#xff1a;true 示例 2&…

【ASE】第三课_山丘颜色梯度效果

今天我们一起来学习ASE插件&#xff0c;希望各位点个关注&#xff0c;一起跟随我的步伐 今天我们来学习山丘的颜色梯度显示&#xff0c;根据不同的高度显示不同的颜色 最终效果&#xff1a; 思路&#xff1a; 1.先加载模型的纹理贴图和法线贴图 2. 获得模型世界顶点Y向量&am…

【渗透测试】-灵当CRM系统-sql注入漏洞复现

文章目录 概要   灵当CRM系统sql注入漏洞&#xff1a;   具体实例&#xff1a;  技术名词解释  小结 概要 近期灵当CRM系统爆出sql注入漏洞&#xff0c;我们来进行nday复现。 灵当CRM系统sql注入漏洞&#xff1a; Python sqlmap.py -u "http://0.0.0.0:0000/c…

当okhttp网络库遇到不规范的http状态码

如题&#xff0c;最近工作遇到的问题&#xff0c;我们的 Android 应用网络请求埋点报表&#xff0c;收集到了奇怪的网络请求异常&#xff1b;通过日志收集与分析&#xff0c;确定到是服务器返回了不规范的状态码所导致。 如上是根据线上的业务场景&#xff0c;本地写个简单的M…

二进制位运算题

本期介绍&#x1f356; 主要介绍&#xff1a;1. 在不创建临时变量的情况下交换两个变量&#xff0c;2. 计算变量在内存中存放2进制位“1”的个数&#xff0c;3. 求两个数的二进制中不同位的个数&#xff0c;4. 分别打印整数的二进制中奇数位和偶数位&#xff0c;5. 判断一个整数…

SentencePiece进行文本分类

SentencePieces 前言 Step1:故事 SentencePiece 是一个无监督的文本分词器和 detokenizer(还原回去的&#xff1f;)主要用于词汇表大小是预定的文本生成系统中它拓展了原始句子的训练&#xff0c;实现子词单元如 BPE 和 unigram language model技术亮点 纯数据驱动&#xff…

Qemu开发ARM篇-6、emmc/SD卡AB分区镜像制作

文章目录 1、AB分区镜像制作2、uboot修改3、镜像启动 在上一篇 Qemu开发ARM篇-5、buildroot制作根文件系统并挂载启动中&#xff0c;我们通过buildroot制作了根文件系统&#xff0c;并通过 SD卡的形式将其挂载到设备并成功进行了启动&#xff0c;但上一章中&#xff0c;我们的…

车载应用的多功能需求与公安、金融等行业的应用特点

随着科技的快速发展&#xff0c;车载应用的功能需求也日益多样化。除了基本的视频监控功能外&#xff0c;现代车载应用还需满足一系列高级功能&#xff0c;如无线网络视频监控、GPS卫星定位、车辆调度、语音报站、行驶信息记录以及多媒体娱乐广告播放等。这些功能在公安、金融等…

2024年数字化转型与管理国际学术会议(DTM 2024)

目录 重要信息 大会简介 大会组委 征稿主题 论文出版 会议议程 参会方式 重要信息 大会官网&#xff1a;www.icemme.org&#xff08;点击了解大会&#xff0c;投稿等详细信息&#xff09; 大会时间&#xff1a;2024年11月22-24日 大会地点&#xff1a;中国-大连 大会…