当前位置: 首页 > news >正文

Windows逆向安全(一)之基础知识(八)

if else嵌套

这次来研究if else嵌套在汇编中的表现形式,本次以获取三个数中最大的数这个函数为例子,分析if else的汇编形式

求三个数中的最大值

首先贴上代码:

#include "stdafx.h"int result=0;
int getMax(int i,int j,int k){if(i>j){if(i>k){return i;}else{return k;}}else{if(j>k){return j;}else{return k;}}
}int main(int argc, char* argv[])
{result=getMax(1,2,3);printf("%d\n",result);result=getMax(1,3,2);printf("%d\n",result);result=getMax(2,1,3);printf("%d\n",result);result=getMax(2,3,1);printf("%d\n",result);result=getMax(3,1,2);printf("%d\n",result);result=getMax(3,2,1);printf("%d\n",result);return 0;
}

先验证执行的结果是正确的:

在这里插入图片描述

确认可以函数是可以取出三个数的最大值的,于是开始分析该函数

为方便观看,将多余的验证删去,直接改为

getMax(1,2,3);

在这里插入图片描述

汇编代码

然后我们观察汇编代码

函数外部

28:       getMax(1,2,3);
0040D7C8   push        3
0040D7CA   push        2
0040D7CC   push        1
0040D7CE   call        @ILT+10(func) (0040100f)
0040D7D3   add         esp,0Ch

依次压入参数,然后调用函数,最后再堆栈外平衡,重点在函数内部,进去看看

函数内部

7:    int getMax(int i,int j,int k){
0040D760   push        ebp
0040D761   mov         ebp,esp
0040D763   sub         esp,40h
0040D766   push        ebx
0040D767   push        esi
0040D768   push        edi
0040D769   lea         edi,[ebp-40h]
0040D76C   mov         ecx,10h
0040D771   mov         eax,0CCCCCCCCh
0040D776   rep stos    dword ptr [edi]
8:        if(i>j){
0040D778   mov         eax,dword ptr [ebp+8]
0040D77B   cmp         eax,dword ptr [ebp+0Ch]
0040D77E   jle         getMax+32h (0040d792)
9:            if(i>k){
0040D780   mov         ecx,dword ptr [ebp+8]
0040D783   cmp         ecx,dword ptr [ebp+10h]
0040D786   jle         getMax+2Dh (0040d78d)
10:               return i;
0040D788   mov         eax,dword ptr [ebp+8]
0040D78B   jmp         getMax+42h (0040d7a2)
11:           }else{
12:               return k;
0040D78D   mov         eax,dword ptr [ebp+10h]
0040D790   jmp         getMax+42h (0040d7a2)
13:           }
14:
15:       }else{
16:           if(j>k){
0040D792   mov         edx,dword ptr [ebp+0Ch]
0040D795   cmp         edx,dword ptr [ebp+10h]
0040D798   jle         getMax+3Fh (0040d79f)
17:               return j;
0040D79A   mov         eax,dword ptr [ebp+0Ch]
0040D79D   jmp         getMax+42h (0040d7a2)
18:           }else{
19:               return k;
0040D79F   mov         eax,dword ptr [ebp+10h]
20:           }
21:       }
22:   }
0040D7A2   pop         edi
0040D7A3   pop         esi
0040D7A4   pop         ebx
0040D7A5   mov         esp,ebp
0040D7A7   pop         ebp
0040D7A8   ret

函数内部有不少代码是用来保护现场 初始化堆栈 恢复现场的,这里将其过滤掉,看判断语句:

判断语句

8:        if(i>j){
0040D778   mov         eax,dword ptr [ebp+8]
0040D77B   cmp         eax,dword ptr [ebp+0Ch]
0040D77E   jle         getMax+32h (0040d792)
9:            if(i>k){
0040D780   mov         ecx,dword ptr [ebp+8]
0040D783   cmp         ecx,dword ptr [ebp+10h]
0040D786   jle         getMax+2Dh (0040d78d)
10:               return i;
0040D788   mov         eax,dword ptr [ebp+8]
0040D78B   jmp         getMax+42h (0040d7a2)
11:           }else{
12:               return k;
0040D78D   mov         eax,dword ptr [ebp+10h]
0040D790   jmp         getMax+42h (0040d7a2)
13:           }
14:
15:       }else{
16:           if(j>k){
0040D792   mov         edx,dword ptr [ebp+0Ch]
0040D795   cmp         edx,dword ptr [ebp+10h]
0040D798   jle         getMax+3Fh (0040d79f)
17:               return j;
0040D79A   mov         eax,dword ptr [ebp+0Ch]
0040D79D   jmp         getMax+42h (0040d7a2)
18:           }else{
19:               return k;
0040D79F   mov         eax,dword ptr [ebp+10h]
20:           }
21:       }
22:   }

参数分析

在这里插入图片描述

i>j

先来看看i>j的反汇编语句

0040D778   mov         eax,dword ptr [ebp+8]
0040D77B   cmp         eax,dword ptr [ebp+0Ch]
0040D77E   jle         getMax+32h (0040d792)

比较第一个参数和第二个参数

jle:jump less equal,小于等于则跳转(有符号数)

跳转地址:0040d792

16:           if(j>k){
0040D792   mov         edx,dword ptr [ebp+0Ch]

i>k

9:            if(i>k){
0040D780   mov         ecx,dword ptr [ebp+8]
0040D783   cmp         ecx,dword ptr [ebp+10h]
0040D786   jle         getMax+2Dh (0040d78d)

比较第一个和第三个参数

jle:jump less equal,小于等于则跳转(有符号数)

跳转地址:0040d78d

11:           }else{
12:               return k;
0040D78D   mov         eax,dword ptr [ebp+10h]
0040D790   jmp         getMax+42h (0040d7a2)

可以分析出,如果第一个参数小于等于第三个参数则跳转到0040D78D,并将第三个参数赋值给eax作为返回值,这条线路为(k>i>j)

否则执行返回指令,将第一个参数赋给eax作为返回值,这条线路为(i>j且i>k)

10:               return i;
0040D788   mov         eax,dword ptr [ebp+8]
0040D78B   jmp         getMax+42h (0040d7a2)

j>k

16:           if(j>k){
0040D792   mov         edx,dword ptr [ebp+0Ch]
0040D795   cmp         edx,dword ptr [ebp+10h]
0040D798   jle         getMax+3Fh (0040d79f)

比较第二个和第三个参数

jle:jump less equal,小于等于则跳转(有符号数)

跳转地址:0040d79f

18:           }else{
19:               return k;
0040D79F   mov         eax,dword ptr [ebp+10h]

可以分析出,如果第二个参数小于等于第三个参数则跳转到0040D79F,并将第三个参数赋值给eax作为返回值,这条线路为(i<=j<=k)

否则返回执行返回命令,将第二个参数赋值给eax作为返回值,这条线路为(i<=j且k<=j)

17:               return j;
0040D79A   mov         eax,dword ptr [ebp+0Ch]
0040D79D   jmp         getMax+42h (0040d7a2)

总结

不难发现,三个数求最大值,只需两两比较就可以得出结果

分析if else的关键在于观察涉及的参数和jcc语句

此案例中就是直接采取了cmp 外加 jle来进行分支的选择和跳转

因为不符合条件的才要跳转走,所以在条件比较中,是大于的比较如i>j,所使用的汇编为jle 小于等于的比较

不按套路比较

此次案例并不能代表所有情况,实际分析要具体看情况来采取分析,有的程序可能就是不按套路出牌,先看看按套路出牌的程序,然后我们自己来模拟个不按套路的

正常套路

拿两个数的比较为例

#include "stdafx.h"
int getMax2(int i,int j){if(i>j){return i;}else{return j;}
}
int main(int argc, char* argv[])
{getMax2(1,2);return 0;
}

先看一般的汇编代码:

9:        if(i>j){
0040D778   mov         eax,dword ptr [ebp+8]
0040D77B   cmp         eax,dword ptr [ebp+0Ch]
0040D77E   jle         getMax2+25h (0040d785)
10:           return i;
0040D780   mov         eax,dword ptr [ebp+8]
0040D783   jmp         getMax2+28h (0040d788)
11:       }else{
12:           return j;
0040D785   mov         eax,dword ptr [ebp+0Ch]
13:       }
14:   }

依旧是采用cmp 和 jle来进行判断,和套路一致

不按套路

完整代码

#include "stdafx.h"
int __declspec(naked) myGetMax(int i,int j){__asm{                                //保留调用前堆栈push ebp//提升堆栈mov ebp,espsub esp,0x40//保护现场push ebxpush esipush edi//初始化提升的堆栈,填充缓冲区mov eax,0xCCCCCCCCmov ecx,0x10lea edi,dword ptr ds:[ebp-0x40]rep stosd//函数核心功能//取出参数mov eax,dword ptr ds:[ebp+8]//比较参数cmp eax,[ebp+0xC]jge _retmov eax,[ebp+0xC]
_ret://恢复现场pop edipop esipop ebx//降低堆栈mov esp,ebppop ebp                //返回ret }
}
int main(int argc, char* argv[])
{int result=myGetMax(1,2);printf("%d\n",result);result=myGetMax(4,3);printf("%d\n",result);return 0;
}

功能代码分析

这里截取出我们自己实现比较的那段代码

                //函数核心功能//取出参数mov eax,dword ptr ds:[ebp+8]//比较参数cmp eax,[ebp+0xC]jge _retmov eax,[ebp+0xC]
_ret://恢复现场pop edipop esipop ebx//降低堆栈mov esp,ebppop ebp                //返回ret 

首先我们这里将第一个参数赋值给eax

然后比较eax和第二个参数,也就是比较第一个参数和第二个参数

这边使用的就不是jle而是jge了

jge:jump greater equal,即大于等于则跳转

前面已经将第一个参数赋值给了eax,而eax又是作为返回值来传递的

当第一个参数大于等于第二个参数时,就可以直接返回了

如果不是则不跳转,执行下面的将第二个参数赋值给eax作为返回值

这里注意到我在汇编中自己定义了一个段:_ret,来作为跳转的地址来使用

最后测试一下结果:

在这里插入图片描述

可以正确得到两个数中的最大值

相关文章:

Windows逆向安全(一)之基础知识(八)

if else嵌套 这次来研究if else嵌套在汇编中的表现形式&#xff0c;本次以获取三个数中最大的数这个函数为例子&#xff0c;分析if else的汇编形式 求三个数中的最大值 首先贴上代码&#xff1a; #include "stdafx.h"int result0; int getMax(int i,int j,int k)…...

PyCharm+PyQt5+pyinstaller打包labelImg.exe

0 开头 labelImg是一款标注软件&#xff0c;作为一个开源项目&#xff0c;它的源码可以在github上找到。官方仓库地址为&#xff1a; https://github.com/heartexlabs/labelImg 小白安装时的最新版本编译出来的界面长这样&#xff1a; 之前在小白的博客里&#xff0c;也教过…...

JavaScript里实现继承的几种方式

JavaScript 中的继承可以通过以下几种方式来实现&#xff1a; 1、原型链继承&#xff1a;通过将子类的原型对象指向父类的实例来实现继承。这种方式的优点是实现简单&#xff0c;缺点是父类的私有属性和方法子类是不能访问的。 function Parent() {this.name parent;this.ag…...

前端:运用HTML+CSS+JavaScript实现迷宫游戏

最近感到挺无聊的,于是想到了大学期间关于栈的应用知识,于是就写了这篇博客! 运用HTML+CSS+JavaScript实现迷宫游戏 1. 运行结果2. 实现思路3. 参考代码1. 运行结果 前端:做个迷宫玩玩,不会迷路吧! 2. 实现思路 如果有一个迷宫,有入口,也有出口,那么怎样找到从入口到出…...

NoSQL数据库简介

NoSQL代表“不仅是SQL”&#xff0c;指的是一种数据库管理系统&#xff0c;旨在处理大量非结构化和半结构化数据。与使用具有预定义架构的表格格式的传统SQL数据库不同&#xff0c;NoSQL数据库是无模式的&#xff0c;并且允许灵活和动态的数据结构。 NoSQL数据库是必需的&…...

面试马铭泽

为什么报考这个岗位 首先&#xff0c;我对军人从小有崇敬之情&#xff0c;梦想着穿着庄严的军装&#xff0c;更对祖国有强烈的热爱之心。我的大舅是一名现役军人&#xff0c;老舅也曾服过兵役&#xff0c;从他们的谈吐以及教育中&#xff0c;让我对部队一直充满向往之情&#…...

查看AWS S3的目录

要查看AWS S3存储桶&#xff08;Bucket&#xff09;的目录&#xff0c;您可以通过AWS管理控制台或AWS CLI&#xff08;命令行界面&#xff09;来实现。 在AWS管理控制台中查看&#xff1a; 登录AWS管理控制台。选择S3服务。在S3存储桶列表中选择要查看的存储桶。在对象列表中…...

分布式系统概念和设计-操作系统中的支持和设计

分布式系统概念和设计 操作系统支持 中间件和底层操作系统的关系&#xff0c;操作系统如何满足中间件需求。 中间件需求:访问物理资源的效率和健壮性&#xff0c;多种资源管理策略的灵活性。 任何一个操作系统的目标都是提供一个在物理层&#xff08;处理器&#xff0c;内存&a…...

【redis】bitmap、hyperloglog、GEO案例

【redis】bitmap、hyperloglog、GEO案例 文章目录 【redis】bitmap、hyperloglog、GEO案例前言一、面试题二、统计的类型聚合统计排序统计问题&#xff1a;思路 二值统计 0和1基数统计 三、hyperloglog1、名词理解UV 独立访客PV 页面浏览量DAU 日活跃用户MAU 月活跃度 2、看需求…...

第二章:集合与区间

1.集合 1.内容概述 1.了解集合的意义2.了解常见集合符号的含义3.云用常见的集合符号来表示集合之间的关系、元素与集合之间的关系2.基本概念 1.集合:把一些确定的对象看成一个整体就形成了一个集合。集合一般使用大写字母A、B、C…来表示2.元素:集合中每一个对象叫做这个集合…...

Mysql8.0版本安装

一,使用yum方式安装 1,配置mysql安装源: sudo rpm -Uvh https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm2,安装mysql8.0: sudo yum --enablerepo=mysql80-community inst...

开放式耳机真的比封闭式强很多吗?推荐几款主流的开放式耳机

​开放式耳机&#xff0c;顾名思义&#xff0c;就是通过骨头振动来传导声音的耳机。相比于传统耳机&#xff0c;它的声音传输更加开放&#xff0c;不会对耳膜造成压迫感&#xff0c;也不会对耳膜旁的内毛细胞造成损害。因此开放式耳机既是运动蓝牙耳机&#xff0c;又是音乐蓝牙…...

Doris(7):数据导入(Load)之Routine Load

例行导入功能为用户提供了义中自动从指定数据源进行数据导入的功能 1 适用场景 当前仅支持kafka系统进行例行导入。 2 使用限制 支持无认证的 Kafka 访问&#xff0c;以及通过 SSL 方式认证的 Kafka 集群。支持的消息格式为 csv 文本格式。每一个 message 为一行&#xff0c;…...

linux 安装php8.1 ZipArchive和libzip最新版扩展安装

1、概述 安装前咱们先看下我本地环境 [rootelk php8]# cat /etc/redhat-release Red Hat Enterprise Linux Server release 7.9 (Maipo) [rootelk php8]# [rootelk php8]# ./bin/php -v PHP 8.1.18 (cli) (built: Apr 17 2023 13:15:17) (NTS) Copyright (c) The PHP Group Z…...

大数据 | 实验一:大数据系统基本实验 | 熟悉常用的HBase操作

文章目录 &#x1f4da;HBase安装&#x1f407;安装HBase&#x1f407;伪分布式模式配置&#x1f407;测试运行HBase&#x1f407;HBase java API编程环境配置 &#x1f4da;实验目的&#x1f4da;实验平台&#x1f4da;实验内容&#x1f407;HBase Shell 编程命令实现以下指定…...

Linux command(split)

原理 在split.c中&#xff0c;首先处理传递给split命令的参数&#xff0c;包括需要拆分的文件、拆分大小/行数等选项。然后&#xff0c;通过调用open()函数打开需要拆分的文件&#xff0c;并获取文件信息。接着根据选项计算每个拆分文件的大小/行数&#xff0c;并根据需要创建输…...

开放式耳机好用吗,盘点几款口碑不错的开放式耳机

​开放式耳机作为一种全新的耳机形态&#xff0c;已经成为了当前市场上非常火爆的一款产品。由于无需入耳佩戴&#xff0c;可以很好的避免了耳膜受到损伤&#xff0c;而且也能够让我们在佩戴眼镜时也能够正常使用。加上开放式耳机的音质和舒适度都要优于其他类型的耳机&#xf…...

法规标准-ISO 16787标准解读

ISO 16787是做什么的&#xff1f; ISO 16787全称为智能运输系统-辅助泊车系统&#xff08;APS&#xff09;-性能要求和测试程序&#xff0c;其中主要描述了对APS系统的功能要求及测试规范 APS类型 根据目标停车位类型将APS系统分为两类&#xff1a; 1&#xff09;APS类型I&a…...

脑力劳动-英文单词

标题 前言必学场景词汇及用法会议简报电话出差市场调研广告与媒介电脑情境常用单词会议简报电话市场调研广告与媒介电脑前言 加油 必学场景词汇及用法 会议 1meeting [ˈmitɪŋ] n.会议hold / have / call off a meeting举办/取消会议be in a meeting在开会The meeting w…...

机器学习中的三个重要环节:训练、验证、测试

本文重点 模型训练、验证和测试是机器学习中的三个重要环节。这三个环节之间存在着紧密的关系,它们相互作用,共同构建出一个完整的机器学习模型。在本文中,我们将详细介绍模型训练、验证和测试之间的关系。 模型训练、验证和测试之间的关系 模型训练是机器学习中最基本的…...

ComfyUI-FramePackWrapper功能选择指南:如何根据资源控制与使用便捷性选择最优方案

ComfyUI-FramePackWrapper功能选择指南&#xff1a;如何根据资源控制与使用便捷性选择最优方案 【免费下载链接】ComfyUI-FramePackWrapper 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI-FramePackWrapper ComfyUI-FramePackWrapper作为一款高效的AI视频生成插…...

OpenClaw开源项目深度体验:对比其与星图GPU平台Qwen3-14B-Int4-AWQ部署差异

OpenClaw开源项目深度体验&#xff1a;对比其与星图GPU平台Qwen3-14B-Int4-AWQ部署差异 1. 项目概览与核心功能 OpenClaw是近期备受关注的开源大模型项目&#xff0c;主打轻量化和易部署特性。它采用混合专家架构(MoE)&#xff0c;在保持模型性能的同时显著降低了计算资源需求…...

西门子PLC存储区全解析:从M区到DB块的实战避坑指南

西门子PLC存储区全解析&#xff1a;从M区到DB块的实战避坑指南 第一次接触西门子PLC编程时&#xff0c;面对M区、L区和DB块这些存储区概念&#xff0c;我完全摸不着头脑。记得有次调试设备&#xff0c;明明在线监控看到M0.0已经置位&#xff0c;但程序就是不执行相应动作&#…...

无噪音RS1 ROSAHL 电解式除湿器 3D 打印耗材盒/户外摄像头/激光器精准除湿设备

RS1 是 ROSAHL&#xff08;日本 Ryosai Technica 生产&#xff09;推出的一款超紧凑型电解式除湿器&#xff0c;采用全球领先的固体聚合物电解质&#xff08;SPE&#xff09;膜技术&#xff0c;通过电化学原理主动将密闭空间内的水分子分解并以气态形式排出。它具备无噪音、无振…...

卷积计算常见误区解析:为什么你的结果和理论值对不上?

卷积计算常见误区解析&#xff1a;为什么你的结果和理论值对不上&#xff1f; 在图像处理和深度学习领域&#xff0c;卷积操作是基础中的基础。但令人惊讶的是&#xff0c;即使是经验丰富的开发者&#xff0c;在实际编码时也常常遇到计算结果与预期不符的情况。这就像做菜时严格…...

[Python3高阶编程] - 异步编程深度学习指南一: 基础知识( 源代码)

异步编程深度学习指南 原文: https://blog.csdn.net/andylin02/article/details/159649164?spm1001.2014.3001.5502 #!/home/admin/.pyenv/versions/3.9.12/bin/python # -*- coding: utf-8 -*-o import aiohttp import asyncio from asyncio import Semaphoreasync def fetc…...

别再只用命令行!华为防火墙USG6000V的Web界面到底怎么玩?eNSP实战演示

华为USG6000V防火墙Web界面高效操作指南&#xff1a;从CLI到图形化的思维转换 对于习惯了命令行操作的老牌网络工程师来说&#xff0c;第一次接触华为USG6000V防火墙的Web管理界面时&#xff0c;往往会陷入一种矛盾心理——既惊叹于可视化操作的直观&#xff0c;又担心图形化界…...

Ryujinx:C编写的Nintendo Switch模拟器技术解析与应用指南

Ryujinx&#xff1a;C#编写的Nintendo Switch模拟器技术解析与应用指南 【免费下载链接】Ryujinx 用 C# 编写的实验性 Nintendo Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/ry/Ryujinx Ryujinx是一款用C#编写的实验性Nintendo Switch模拟器&#xff…...

别再死记硬背时序了!用Arduino+DS18B20,5分钟搞定温度监测(附完整代码)

用ArduinoDS18B20快速搭建温度监测系统 在创客和物联网项目中&#xff0c;温度监测是最基础也最常用的功能之一。传统单片机教程往往要求学习者从底层时序开始啃起&#xff0c;这对于初学者来说无异于一道高墙。而今天我要分享的方法&#xff0c;将让你在5分钟内完成从硬件连接…...

SimpleMem:基于语义无损压缩的三阶段 Agent 终身记忆框架

&#x1f4cc; 一句话总结&#xff1a; 本工作提出 SimpleMem&#xff0c;一个基于语义结构化压缩的终身记忆系统&#xff0c;通过“压缩—合成—规划”三阶段机制&#xff0c;在固定上下文预算下显著提升 LLM Agent 的长期交互能力与检索效率。 &#x1f50d; 背景问题&…...