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

在逆向分析中,循环语句通常会以特定的汇编模式或结构体现出来。常见的循环语句包括 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↓jmov     eax, [ebp+var_2C]add     eax, 1mov     [ebp+var_2C], eax
loc_41185F:                             ; CODE XREF: _main+44↑jcmp     [ebp+var_2C], 5jge     short loc_411870mov     eax, [ebp+var_8]add     eax, [ebp+var_2C]mov     [ebp+var_8], eaxjmp     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↑jmov     [ebp+var_38], 0
loc_411877:                             ; CODE XREF: _main+7F↓jcmp     [ebp+var_38], 5jge     short loc_411891mov     eax, [ebp+var_14]add     eax, [ebp+var_38]mov     [ebp+var_14], eaxmov     eax, [ebp+var_38]add     eax, 1mov     [ebp+var_38], eaxjmp     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↑jmov     [ebp+var_44], 0
loc_411898:                             ; CODE XREF: _main+9E↓jmov     eax, [ebp+var_20]add     eax, [ebp+var_44]mov     [ebp+var_20], eaxmov     eax, [ebp+var_44]add     eax, 1mov     [ebp+var_44], eaxcmp     [ebp+var_44], 5jl      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.rhkb.cn/news/432108.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uni-app+vue3开发微信小程序使用本地图片渲染不出来报错[渲染层网络层错误]Failed to load local image resource

我把图片放在assets里面页面通过相对路径引入。结果一直报错。 最后我把图片放在static文件夹下面。然后修改路径指向static就可以了 或者是我们必须先import 这个图片然后在使用 import banner1 from ../../assets/images/banner/banner1.png; <image :src"banner…

【时时三省】(C语言基础)指针笔试题5

山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 笔试题5 这个a数组代表着5行5列 如下图 a[4][2]是第5行的数组 第五行下标为2的位置 取出的是这个位置的地址

【Linux学习】1-2 新建虚拟机ubuntu环境

1.双击打开VMware软件&#xff0c;点击“创建新的虚拟机”&#xff0c;在弹出的中选择“自定义&#xff08;高级&#xff09;” 2.点击下一步&#xff0c;自动识别ubuntu光盘映像文件&#xff0c;也可以点击“浏览”手动选择&#xff0c;点击下一步 3.设置名称及密码后&#xf…

kibana开启访问登录认证

编辑es配置文件&#xff0c;添加以下内容开启es认证 vim /etc/elasticsearch/elasticsearch.yml http.cors.enabled: true http.cors.allow-origin: "*" http.cors.allow-headers: Authorization xpack.security.enabled: true xpack.security.transport.ssl.enable…

WPF一个控件根据另一个控件的某种状态的改变从而改变自身某种状态

WPF 一个控件根据另一个控件的某种状态的改变从而改变自身某种状态 前提&#xff0c;这里根据 Image 控件 Source 属性为 null 时&#xff0c;让 Label 控件可见&#xff0c;不为 null 时, Label 控件不可见为例子展示&#xff0c;代码如下&#xff1a; <Canvas><Ima…

Qt基础之四十七:管理员权限

在Windows系统中,以管理员身份运行的意思是,用系统管理最高权限运行程序。一般来说,只有当某些操作涉及系统保护区域时,才会需要用户授权管理员运行。如此一来,程序、命令在运行过程中,就有了足够权限,更改系统设置或注册表。 一.Qt程序加入管理员权限的几种方式 1.MS…

理解和使用语言模型的监督微调 (SFT)

大型语言模型&#xff08;LLM&#xff09;的训练通常分为几个阶段&#xff0c;包括预训练和几个微调阶段&#xff1b;见下文。 虽然预训练的成本很高&#xff08;即几十万美元的计算费用&#xff09;&#xff0c;但微调 LLM&#xff08;或执行上下文学习&#xff09;的成本却很…

开源链动 2+1 模式 S2B2C 商城小程序:社交电商团队为王的新引擎

摘要&#xff1a;本文深入探讨在社交电商领域中&#xff0c;团队的重要性以及如何借助开源链动 21 模式 S2B2C 商城小程序&#xff0c;打造具有强大竞争力的团队&#xff0c;实现个人价值与影响力的放大&#xff0c;创造被动收入&#xff0c;迈向财富自由之路&#xff0c;同时为…

职场能力强的人都在做什么---今日头条

【职场里,能力强的人都在做哪些事... - 今日头条】https://m.toutiao.com/is/ikn6kt9q/ 知识雷达 2024-09-21 16:33 目录 职场里,能力强的人都在做哪些事呢? 1、复盘; 2、多角度思考;3、记录信息; 4、永远积极主动;5、主动获取信息差; 6、明确人和人的关系;7、…

蓝桥杯备赛---引言

我是来自成都锦城学院的2021级学生&#xff0c;第一次参加第十五届蓝桥杯嵌入式赛道获得了国二的名次&#xff0c;接下来将为大家分享各个模块的代码&#xff0c;可以速成省一&#xff0c;但想要取得国一的成绩则需要补偿数据结构、基本c语言函数等相关知识&#xff0c;很遗憾没…

低代码BPA(业务流程自动化)技术探讨

一、BPA流程设计平台的特点 可视化设计工具 大多数BPA流程设计平台提供直观的拖拽式界面&#xff0c;用户可以通过图形化方式设计、修改及优化业务流程。这种可视化的方式不仅降低了门槛&#xff0c;还便于非技术人员理解和参与流程设计。集成能力 现代BPA平台通常具备与其他系…

栈的基本概念和及具体实现

今天给大家介绍一下栈的基本概念及实现&#xff01;话不多说&#xff0c;立即开始&#xff01; 1.栈的概念&#xff1a; 一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈 顶&#xff0c;另一端称为栈底。栈中的…

基于遗传优化算法的多AGV栅格地图路径规划matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 栅格地图表示 4.2 路径编码 4.3 目标函数 5.完整程序 1.程序功能描述 基于遗传优化算法的多AGV栅格地图路径规划matlab仿真&#xff0c;分别测试单个AGC的路径规划和多个AGV的路径规划…

SpringBoot Validation不生效该怎么办?

SpringBoot Validation不生效该怎么办&#xff1f; 确认maven依赖查看依赖关系并处理验证&#xff1a;校验生效&#xff0c;成功反思 能问出这个问题说明你已经使用了Null、NotEmpty等等等校验注解&#xff0c;但是没有生效&#xff0c;我也出现过这种情况&#xff0c;请看我修…

计算机毕业设计之:宠物服务APP的设计与实现(源码+文档+讲解)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

[OpenGL]使用OpenGL绘制带纹理三角形

一、简介 本文介绍了如何使用使用OpenGL绘制带纹理三角形。 在绘制带纹理的三角形时&#xff0c; 首先使用.h读取准备好的.png格式的图片作为纹理&#xff0c;然后在fragment shader中使用 ... in vec2 textureCoord; uniform sampler2D aTexture1; void main() {FragColor …

Backend - Eclipse 软件写 java 项目

目录 一、下载并安装 1. 下载 2. 下载 java ee packages 3. 创建安装文件夹 二、创建java项目 1. 打开eclipse软件 2. 创建项目 3. 创建包与类 4. eclipse工作目录 三、eclipse基础配置 1. eclipse配置快捷提示 2. eclipse 查看源码配置 3. 浏览目录用树状显示 四…

VIVADO IP核之FIR抽取器多相滤波仿真

VIVADO IP核之FIR抽取器多相滤波仿真&#xff08;含有与MATLAB仿真数据的对比&#xff09; 目录 前言 一、滤波器系数生成 二、用MATLAB生成仿真数据 三、VIVADO FIR抽取多相滤波器使用 四、VIVADO FIR抽取多相滤波器仿真 五、VIVADO工程下载 总结 前言 关于FIR低通滤波…

OpenHarmony(鸿蒙南向)——平台驱动开发【Regulator】

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 持续更新中…… 概述 功能简介 Regulator模块用于控制系统中各类设备的电压/电流…

有关shell指令练习2

写一个shell脚本&#xff0c;将以下内容放到脚本中 在家目录下创建目录文件&#xff0c;dir dir下创建dir1和dir2 把当前目录下的所有文件拷贝到dir1中&#xff0c; 把当前目录下的所有脚本文件拷贝到dir2中 把dir2打包并压缩为dir2.tar.xz 再把dir2.tar.xz移动到dir1中 …