滴水逆向三期笔记与作业——02C语言——10 Switch语句反汇编

news2024/11/17 3:00:52

滴水逆向三期笔记与作业——02C语言——10 Switch语句反汇编

  • 一、Switch语句
    • 1、switch语句 是if语句的简写
    • 2、break加与不加有什么特点?default语句可以省略吗?
    • 3、游戏中的switch语句(示例)
    • 4、添加case后面的值,一个一个增加,观察反汇编代码的变化(何时生成大表).
    • 5、将3中的常量值的顺序打乱,观察反汇编代码(观察顺序是否会影响生成大表).
    • 6、将case后面的值改成从100开始到109(连续),观察汇编变化(观察值较大时是否生成大表).
    • 7、将连续的10项中抹去1项或者2项,观察反汇编有无变化(观察大表空缺位置的处理).
    • 8、在10项中连续抹去,不要抹去最大值和最小值(观察何时生成小表).
    • 9、将case后面常量表达式改成毫不连续的值,观察反汇编变化.
    • 10、部分连续,部分差值非常大
  • 二、do/while反汇编
    • 1、do/while的语法
    • 2、do/while的反汇编
    • 3、example
    • 4、总结
  • 三、while反汇编
    • 1、while语句的语法
    • 2、while语句反汇编
    • 3、example
    • 4、总结
  • 四、for循环反汇编
    • 1、for语句的语法
    • 2、for循环的执行次序
    • 3、example
    • 4、总结
  • 五、作业
    • 1、写一个Switch语句,不生产大表也不生产小表,贴出对应反汇编
    • 2、写一个Switch语句,只生成大表,贴出对应反汇编
    • 3、写一个Switch语句,生成大表和小表,贴出对应反汇编
    • 4、为do/while语句生成的反汇编填写注释
    • 5、为while语句生成的反汇编填写注释
    • 6、为for语句生成的反汇编填写注释

一、Switch语句

1、switch语句 是if语句的简写

  • if语句
if(表达式 == 常量1)
{
	//...代码
}
else if(表达式 == 常量2)
{
	//...代码
}
else if(表达式 == 常量3)
{
	//...代码
}
else
{
	//...代码
}

  • switch语句
switch(表达式)                
{                
    case 常量表达式1:
    	语句;
    	break;
	case 常量表达式2:
		语句;
		break;
	case 常量表达式3:
		语句;
		break;
	case 常量表达式3:
		语句;
		break;
	default:        
		语句;
		break;
}

switch要求:

1、case后面必须是常量表达式

2、case后常量表达式的值不能一样

3、switch后面表达式必须为整数

2、break加与不加有什么特点?default语句可以省略吗?

不写break时,编译可以通过,但会将不写break的case全部执行一遍。
default语句可以省略,当所有条件都不满足的时候,会默认执行default中的代码,如果不存在default,但所有条件不满足,则不执行代码。

3、游戏中的switch语句(示例)

F1  F2  F3  F4  F5  F6  F7  F8
0   1   2   3   4   5   6   7
switch(表达式)
{
	case 1:
		打坐....
		break;
	case 2:
		加红....        
		break;
	case 3:
		加蓝....        
		break;
	case 4:
		释放技能....
		break;
	default:
		语句;
		break;
}

4、添加case后面的值,一个一个增加,观察反汇编代码的变化(何时生成大表).

我的环境是64位的vscode,与海哥教程中存在较大差异。

  • 少分支Switch结构
void Function(int x){
switch (x){
case 1:
printf("1");
break;
case 2:
printf("2");
break;
case 3:
printf("3");
break;
default:
printf("4");
break;
}
}
 
int main(int argc, char* argv[]){
Function(2);
 
return 0;
}

在这里插入图片描述

由汇编可见,少分支的Switch与if相似,所以正向代码中,分支较少时建议不使用Switch

  • 多分支Switch结构
void Function(int x){
switch (x){
case 1:
printf("1");
break;
case 2:
printf("2");
break;
case 3:
printf("3");
break;
case 4:
printf("4");
break;
default:
printf("5");
break;
}
}
 
int main(int argc, char* argv[]){
Function(2);
 
return 0;
}

在这里插入图片描述
未发现大表寻址过程

  • 多分支Switch结构
void Function(int x){
switch (x){
case 1:
printf("1");
break;
case 2:
printf("2");
break;
case 3:
printf("3");
break;
case 4:
printf("4");
break;
case 5:
printf("5");
break;
case 6:
printf("6");
break;
default:
printf("7");
break;
}
}
int main(int argc, char* argv[]){
Function(3);
return 0;
}

在这里插入图片描述
存在大表寻址过程,已优化

  • 总结
    1、分支少于4的时候,使用Switch没有意义,因为编译器会生成类似if/else之类的反汇编;
    2、case后面的常量表达式可以是无序的,并不影响大表的生成

• 分支较少时,不生成大表,也不生成小表,会生成if…else语句
• 分支达到一定数量时,生成大表,且大表跟顺序无关
• 大表可以理解为一个存储了多个地址的连续表,通过Register*4可以来寻址。
• 分支达到一定数量,生成大表,但是中间缺少很多case时,还会生成一张小表。
• 小表的作用可以理解为把大表的空缺地址,移动到了小表,把空缺的case值所在的地方填为default的地址

5、将3中的常量值的顺序打乱,观察反汇编代码(观察顺序是否会影响生成大表).

并不影响大表生成

6、将case后面的值改成从100开始到109(连续),观察汇编变化(观察值较大时是否生成大表).

  • 代码
void Function(int x){
switch (x){
case 100:
printf("100");
break;
case 101:
printf("101");
break;
case 102:
printf("102");
break;
case 103:
printf("103");
break;
case 104:
printf("104");
break;
case 105:
printf("105");
break;
case 106:
printf("106");
break;
case 107:
printf("107");
break;
case 108:
printf("108");
break;
default:
printf("109");
break;
}
}
int main(int argc, char* argv[]){
Function(103);
return 0;
}

  • 反汇编
    在这里插入图片描述

如果[参数-100]大于[max-min],说明传入参数小于case最小值或者大于case最大值,此时直接执行default即可;
反之说明参数在min到max之间,而此时eax中存储的是[参数-100]的数值,而编译器已经维护了一张表,根据eax的位置,像一维数组查数一样根据公式,eax=基址+eax代表的内存的数据,跳转到eax的执行地址即可(jmp rax)。

7、将连续的10项中抹去1项或者2项,观察反汇编有无变化(观察大表空缺位置的处理).

在这里插入图片描述

被删除的部分并不会被填充0,大表会把抹去的分支项原先所对应的地址全部给填充为default默认地址.

8、在10项中连续抹去,不要抹去最大值和最小值(观察何时生成小表).

小表是将大表的地址移动到小表,空缺的地方填充为到default的偏移量。
海哥的教程中删除一定的case分支后,生成小表,但本地环境win64+VSCOde中,未生成小表,删除一定的分支后,直接转换成if/else形式(我也很疑惑……)。

9、将case后面常量表达式改成毫不连续的值,观察反汇编变化.

类似于if/else的结构

10、部分连续,部分差值非常大

  • 代码
void Function(int x){
switch (x){
case 300:
printf("300");
break;
case 301:
printf("301");
break;
case 302:
printf("302");
break;
case 303:
printf("303");
break;
case 304:
printf("304");
break;
case 305:
printf("305");
break;
case 306:
printf("306");
break;
case 307:
printf("307");
break;
case 3:
printf("3");
break;
default:
printf("309");
break;
}
}
int main(int argc, char* argv[]){
Function(303);
return 0;
}

  • 反汇编
    在这里插入图片描述
    与if/else相同,下图为海哥教程图
    在这里插入图片描述

二、do/while反汇编

1、do/while的语法

do
{
	//执行代码
}while(表达式)
 

2、do/while的反汇编

在这里插入图片描述

3、example

在这里插入图片描述

4、总结

  1. 根据条件跳转指令所跳转到的地址,可以得到循环语句块的起始地址。
  2. 根据条件跳转指令所在的地址,可以得到循环语句块的结束地址。
  3. 条件跳转的逻辑与源码相同。

三、while反汇编

1、while语句的语法

while(表达式)        
{
	//执行代码
}

2、while语句反汇编

在这里插入图片描述

3、example

在这里插入图片描述

4、总结

  1. 根据条件跳转指令所跳转到的地址,可以得到循环语句块的结束地址;
  2. 根据jmp 指令所跳转到的地址,可以得到循环语句块的起始地址;
  3. 在还原while 比较时,条件跳转的逻辑与源码相反。

四、for循环反汇编

1、for语句的语法

for(表达式1;表达式2;表达式3)
{
//执行的代码
}

2、for循环的执行次序

表达式1
表达式2
执行的代码(大括号里面的内容)
表达式3

表达式2 //如果表达式2成立
执行的代码(大括号里面的内容)
表达式3

表达式2 //如果表达式2成立
执行的代码(大括号里面的内容)
表达式3

表达式2 //如果不成立
跳出循环

3、example

在这里插入图片描述

4、总结

  1. 第一个jmp 指令之前为赋初值部分
  2. 第一个jmp 指令所跳转的地址为循环条件判定部分起始
  3. 判断条件后面的跳转指令条件成立时跳转的循环体外面
  4. 条件判断跳转指令所指向的地址上面有一个jmp jmp地址为表达式3的起始位置

五、作业

1、写一个Switch语句,不生产大表也不生产小表,贴出对应反汇编

void Function(int x)
{
switch(x)
{
case 1:
	printf("1");
	break;
case 2:
	printf("2");
	break;
case 3:
	printf("3");
	break;
default:
	printf("Error");
	break;
}
}
 
int main(int argc, char* argv[]){
	Function(2);
	return 0;
}

在这里插入图片描述

2、写一个Switch语句,只生成大表,贴出对应反汇编

void Function(int x)
{
switch(x)
{
case 1:
	printf("1");
	break;
case 2:
	printf("2");
	break;
case 3:
	printf("3");
	break;
case 4:
	printf("4");
	break;
case 5:
	printf("5");
	break;
case 6:
	printf("6");
	break;
default:
	printf("Error");
	break;
}
}
 
int main(int argc, char* argv[]){
Function(5);
    return 0;
}

在这里插入图片描述

3、写一个Switch语句,生成大表和小表,贴出对应反汇编

void Function(int x)
{
switch(x)
{
case 100:
	printf("100");
	break;
case 101:
	printf("101");
	break;
case 110:
	printf("110");
	break;
case 3:
	printf("3");
	break;
case 1:
	printf("1");
	break;
default:
	printf("Error");
	break;
}
}
int main(int argc, char* argv[]){
	Function(101);
    return 0;
}

我的是if/else结构,博客站中是大小表结构。

4、为do/while语句生成的反汇编填写注释

void Function(int i)
{
	do
	{
		printf("%d\n", i);
		i++;
	} while (i>3);
 
}
int main(int argc, char* argv[]){
	Function(0);
    return 0;
}

在这里插入图片描述

5、为while语句生成的反汇编填写注释

void Function(int i)
{
	while (i<3)
	{
		printf("%d\n", i);
		i++;
	}
 
}
int main(int argc, char* argv[]){
	Function(0);
    return 0;
}
 

在这里插入图片描述

6、为for语句生成的反汇编填写注释

void Function(int x)
{
	for (int i = 0; i < x; i++)
	{
		printf("%d\n", i);
	}
}
int main(int argc, char* argv[]){
	Function(5);
    return 0;
}
 

在这里插入图片描述

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

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

相关文章

故障树分析蒙特卡洛仿真程序(附MATLAB完整代码)

故障树是一种特殊的倒立树状逻辑因果关系图&#xff0c;它用事件符号、逻辑门符号和转移符号描述系统中各种事件之间的因果关系&#xff0c;通过对引起系统故障的各种因素进行逻辑因果分析&#xff0c;确定导致故障发生的各种可能的原因&#xff0c;并通过定性和定量分析找出系…

如何限制 IP 多次重新访问

随着互联网的快速发展&#xff0c;网络安全问题日益突出。恶意 IP 多次重新访问是一种常见的手段&#xff0c;可能导致服务器负载过高、资源浪费、网站响应速度下降等问题。为了提高网络安全性&#xff0c;我们需要采取有效的措施来限制恶意 IP 的多次重新访问。下面简单的介绍…

Linux下安装openresty

Linux下安装openresty 十一、Linux下安装openresty11.1.概述11.2.下载OpenResty并安装相关依赖&#xff1a;11.3.使用wget下载:11.4.解压缩:11.5.进入OpenResty目录:11.6.编译和安装11.7.进入OpenResty的目录&#xff0c;找到nginx&#xff1a;11.8.在conf目录下的nginx.conf添…

C++笔记之作用域解析符::和命名空间、作用域的关系

C++笔记之作用域解析符::和命名空间、作用域的关系 —— 杭州 2024-01-26 code review 文章目录 C++笔记之作用域解析符::和命名空间、作用域的关系1.`命名空间`和`作用域`两个术语的联系和区别命名空间(Namespace)作用域(Scope)联系与区别2.`作用域解析符::`和`命名空间`…

分段函数线性化方法matlab测试

目录 1 使用0-1变量将分段函数转换为线性约束 2 连续函数采用分段线性化示例 3 matlab程序测试 4 matlab测试结果说明 5 分段线性化应用 1 使用0-1变量将分段函数转换为线性约束 2 连续函数采用分段线性化示例 3 matlab程序测试 clc;clear all; gn10;tn1; x_pfsdpvar(1, t…

桥接模式解析

桥接模式 意图 将抽象与其实现相分离&#xff0c;使得两者可以独立变化。 解释 案例&#xff1a;考虑武器有不同的特效&#xff0c;你想让不同的武器可以有不同的特效&#xff0c;你应该怎么做&#xff1f; 为每个武器创建不同的副本使得有不同的特效&#xff0c;还是你只单独…

记录一道ctf web题

0x00 前言 某同学发在群里一道不知道什么ctf的web题 0x01 bypass open_basedir 开始没想那么多&#xff0c;看到了可以执行phpinfo&#xff0c;直接先eval一个一句话上去看看什么情况&#xff1a; 接着发现了没有权限去读取/var/www/html以外的目录&#xff0c;那么我开始想的…

uniapp 使用echarts做折线图条形图。

提前10天把中烟活动做完了&#xff0c;以为能打酱油到除夕那天&#xff0c;结果又要做什么数据看板&#xff0c;方便烟草领导过年查看数据&#xff0c;还只给5天时间&#xff0c;真实压榨剥削啊&#xff0c;下辈子再也不‘拍黄片’了&#xff0c;不&#xff01;下份工作我就转前…

破解Windows系统密码(保姆级教学)

前言: 本篇博客只是技术分享并非非法传播知识,实验内容均是在虚拟机中进行,并非真实环境 正文: 看到题目大家都已经晓得这篇博客是干嘛了,我也不废话了,直接上win7素材 需要windows10破解过程的关注后在下面评论"已关注,请私聊"我会私发给你 一.windows7电脑密码破解…

JAVA_Set系列集合:HashSet、LinkedHashSet、TreeSet底层详解

先看看 Set 系列集合的位置&#xff1a; Set 系列集合的特点&#xff1a; 无序&#xff1a;存取顺序不一致 如存入张三、李四、王五。而遍历获取到的是李四, 张三, 王五 不重复&#xff1a;可以去除重复无索引&#xff1a;没有带索引的方法&#xff0c;所以不能使用普通for循…

MTE内存扩展精讲与实战

思考 1、常见的内存安全问题有哪些&#xff1f;举例说明&#xff1f; 2、内存安全的软件缓解技术有哪些&#xff1f;在optee上的应用&#xff1f; 3、MTE下的内存安全性如何保证&#xff1f;空间安全性&#xff1f;时间安全性&#xff1f; 4、MTE的架构细节&#xff1f;硬件原…

8.14划分字母区间(LC763-M)(附.length,.length(),.size()使用原理)

算法&#xff1a; 在遍历的过程中相当于是要找每一个字母的边界&#xff0c;如果找到之前遍历过的所有字母的最远边界&#xff0c;说明这个边界就是分割点了。 此时前面出现过所有字母&#xff0c;最远也就到这个边界了。 步骤&#xff1a; 统计每一个字符最后出现的位置从…

【代码随想录-数组】长度最小的子数组

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

adb测试冷启动和热启动 Permission Denial解决

先清理日志 adb shell logcat -c 打开手机模拟器中的去哪儿网&#xff0c;然后日志找到包名和MainActivity adb shell logcat |grep Main com.Qunar/com.mqunar.atom.alexhome.ui.activity.MainActivity 把手机模拟器的去哪儿的进程给杀掉 执行 命令 adb shell am start -W…

2013年苏州大学837复试机试C/C++

2013年苏州大学复试机试 第一题 题目 假设有一堆数字&#xff08;小于100个&#xff09;需要对其做如下处理&#xff1a; 求平均数求标准差求方差 可用函数实现也可以不用 代码 #include <iostream> #include <sstream> //字符串流 #include <cmath> …

LabVIEW振动信号分析

LabVIEW振动信号分析 介绍如何使用LabVIEW软件实现希尔伯特-黄变换&#xff08;Hilbert-Huang Transform, HHT&#xff09;&#xff0c;并将其应用于振动信号分析。HHT是一种用于分析非线性、非平稳信号的强大工具&#xff0c;特别适用于旋转机械等复杂系统的振动分析。开发了…

【linux】Debian防火墙

Debian系统默认没有安装防火墙&#xff0c;但用户可以根据需要自行选择并安装一个防火墙以增强系统安全性。 一、查看Debian 桌面系统的防火墙是否关闭 在Debian及其他基于Linux的桌面系统中&#xff0c;防火墙功能通常是由iptables或nftables规则集控制的&#xff0c;而ufw&…

《WebKit技术内幕》学习之十五(3): Web前端之未来

3 Web应用和Web运行环境 3.1 Web应用 HTML5提供了强大的能力&#xff0c;而不是支持Web网页这么简单。就目前而言&#xff0c;它已经初步提供了支持Web网页向Web应用方向发展的能力。相对于本地应用&#xff08;Native Application&#xff09;&#xff0c;Web前端领域也能够…

如何在yolov8中验证时计算FPS

ultralytics-main/ultralytics/engine/validator.py文件下&#xff0c;第200行左右&#xff0c;添加如下代码 LOGGER.info(fFPS:{(1000 / sum(self.speed.values())):.2f}) speed.values()是一个字典&#xff0c;包括preprocess,inference,loss,postprocess的时间&#xff0c;所…

SpringSecurity(15)——OAuth2密码模式

工作流程 将用户和密码传过去&#xff0c;直接获取access_token&#xff0c;用户同意授权动作是在第三方应用上完成&#xff0c;而不是在认证服务器&#xff0c;第三方应用申请令牌时&#xff0c;直接带用户名和密码去向认证服务器申请令牌。这种方式认证服务器无法判断用户是…