当前位置:   article > 正文

软件安全预备知识_()是还没有公开的漏洞。这类漏洞通常对用户不会有什么影响,但会导致攻击者瞄准的

()是还没有公开的漏洞。这类漏洞通常对用户不会有什么影响,但会导致攻击者瞄准的

用csdn记录软件安全知识,方便复习以及为挖掘漏洞打好基础
由于是在本地写的,导入到csdn时由于gitee图床不能使用,文章的图片加载不出来,后续找到合适的图床,会更新。
后续考虑直接在csdn的编辑器里写文章
附上.md文件和图片的网盘链接:https://pan.baidu.com/s/1HqM36eGLe41hHtgnML4G1Q
提取码:kcef


基本概念

病毒和木马

病毒(computer Virus)

”指编制或者在计算机程序中插入的破坏计算机功能或者破坏数据,影响计算机使用并且能够自我复制的一组计算机指令或者程序代码“。

特性
  • 感染性
  • 潜伏性
  • 特定的触发性
  • 破坏性
满足两个条件
  • 自我执行

    它通常将自己的代码置于另一个程序的执行路径中

  • 自我复制

    它可能用受病毒感染的文件副本替换其他可执行文件,病毒既可以感染个人计算机,也可以感染网络服务器。

蠕虫(worm)病毒

蠕虫病毒是一种常见的计算机病毒,它利用网络进行复制和传播。蠕虫病毒是自包含的程序(或是一套程序),它能传播自身功能的拷贝或自身的某些功能到其他的计算机系统中(通常是经过网络连接)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2zxn9Nr3-1655128427961)(c96ec693fffa9f03903747f1e5412daa.png)]

普通病毒和蠕虫病毒的区别

  • 复制方式

    普通病毒需要传播受感染的驻留文件来进行复制,而蠕虫不使用驻留文件即可在系统之间进行自我复制。

  • 传染目标

    普通病毒的传染能力主要是针对计算机内的文件系统而言,而蠕虫病毒的传染目标是*互联网内的所有计算机

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MRtpUQ5T-1655128427962)(a5cb3abf300b2f984350b4a72815e299.png)]

木马

木马(Trojan Horse),是指那些表面上是有用的软件,实际目的却是危害计算机安全并导致严重破坏的计算机程序。

  • 是一种基于远程控制的黑客工具

  • 具有非授权性

    是指一旦控制端与服务端连接后,控制端将窃取到服务端的很多操作权限,一旦中了木马,你的系统很可能门户大开,毫无秘密可言。

  • 具有隐蔽性

    是指木马的设计者为了防止木马被发现,会采用多种手段隐藏木马,这样服务端即使发现感染了木马,也难以确定其具体位置。

病毒和木马的区别

  • 木马不具有感染性,它不能像病毒那样复制自身,也并不刻意地感染其他文件,它主要通过将自身伪装起来,吸引用户下载执行。
  • 木马一般主要以窃取用户相关信息隐蔽性控制为主要目的。

相对病毒而言,可以简单地说,病毒破坏你的信息,而木马窥视你。

软件漏洞

软件安全漏洞

缺陷和漏洞

计算机软件是由计算机程序员开发出来的,不同程序员的编程水平不一样,就会造成软件存在这样或者那样的问题,这些问题可能会造成软件崩溃不能运行,我们称这些问题为软件缺陷(Bug)。

软件中存在的一些问题,可以在某种情况下被利用来对用户造成恶意攻击,比如给用户计算机上安装木马病毒,或者直接盗取用户计算机上的秘密信息,等等。这个时候软件的这些问题就不再是bug,而是一个软件安全漏洞,简称”软件漏洞“。

电脑肉鸡

受别人控制的远程电脑。肉鸡可以是各种系统,如windows,linux,unix等;更可以是一家公司、企业、学校甚至是政府军队的服务器。如果服务器软件存在安全漏洞, 攻击者可以发起“主动”进攻,植入木马,将该服务器变为一个任人宰割的“肉鸡”。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3eueq9Q9-1655128427963)(124f32991e24ff4830822dfe12bed4cc.png)]


漏洞产生的原因

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NMvb0dhe-1655128427964)(d9b9f2b4055ca7050db492e8cdc73326.png)]

漏洞分类

按照漏洞生命周期的阶段进行分类:

0Day漏洞

指还处于未公开状态的漏洞。这类漏洞只在攻击者个人或者小范围黑客团体内使用,网络用户和厂商都不知情,因此没有任何防范手段,危害非常大。

0day漏洞也是当前网络战中的核武器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZJkn0E2G-1655128427966)(79b895f2ae6cf1bddd27738943112d77.png)]

1Day漏洞

通常指发布补丁时间不长的漏洞。由于了解此漏洞并且安装补丁的人还不多,这种漏洞仍然存在一定的危害。

已公开漏洞

已公开漏洞是指厂商已经发布补丁或修补方法,大多数用户都已打过补丁的漏洞。这类漏洞从技术上因为已经有防范手段,并且大部分用户已经进行了修补,危害比较小。

漏洞产业链

网络黑客产业链是指黑客们运用技术手段入侵服务器获取站点权限,以及各类账户信息并从中谋取非法经济利益的一条产业链。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HdRYxo72-1655128427967)(55a038bd3353732c638ec94bcb4369f5.png)]

漏洞库

大量软件漏洞需要一个统一的命名和管理规范,以便开展针对软件漏洞的研究,提升漏洞的检测水平,并为软件使用者和厂商提供有关软件漏洞的确切信息。

漏洞信息数据库,可以找到操作系统和应用程序的特定版本所包含的漏洞信息,甚至针对某些漏洞的专家建议、修复办法和专门的补丁程序。极少的漏洞库还提供检测、测试漏洞的POC。POC(proof-of-concepts,为观点提供证据): 样本验证代码。

CVE

MITRE公司建立的通用漏洞列表CVE(Common Vulnerabilities and Exposures)相当于软件漏洞的一个行业标准实现了安全漏洞命名机制的规范化和标准化

NVD

美国国家漏洞数据库NVD(National Vulnerabilities Database)

NVD同时收录三个漏洞数据库的信息,CVE漏洞公告、US-CERT漏洞公告、US- CERT安全警告,也自己发布的漏洞公告和安全警告,是目前世界上数据量最大, 条目最多的漏洞数据库之一

CNNVD

中国国家信息安全漏洞库CNNVD(China National Vulnerability Database of Information Security)

CNVD

国家信息安全漏洞共享平台CNVD(China National Vulnerability Database)

CNVD是CNCERT联合国内重要信息系统单位、基础电信运营商、 网络安全厂商建立的信息安全漏洞信息共享知识库,致力于建立国家 统一的信息安全漏洞收集、发布、验证、分析等应急处理体系。

渗透测试

渗透测试是通过模拟恶意黑客的攻击方法,来评估计算机网络系统安全的一种评估方法。这个过程包括对系统的任何弱点、技术缺陷或漏洞的主动分析,这个分析是从一个攻击者可能存在的位置来进行的,并且从这个位置有条件主动利用安全漏洞。

换句话来说,渗透测试是指渗透人员**在不同的位置 **(比如从内网、从外网等位置)利用各种手段对某个特定网络进行测试,以期发现和挖掘系统中存在的漏洞,然后输出渗透测试报告,并提交给网络所有者。网络所有者根据渗透人员提供的渗透测试报告,可以清晰知晓系统中存在的安全隐患和问题

实验环境

Kali Linux(Kali)是专门用于渗透测试的Linux操作系统。在Kali和DVWA(Damn Vulnerable Web Application)环境下,演示渗透测试Web安全的实验。

Kali是基于Debian类型的Linux系统版本。其包含在线、离线两种软件包管理工具,dpkg和apt。

  • dpkg(Debian Package)管理工具,软件包名以.deb后缀。这种方法适合系统不能联网的情况下。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TnVUDJyd-1655128427968)(bb10acd5e3a6392a96e887b581eff686.png)]

  • APT(Advanced Packaging Tool)高级软件工具。这种方法适合系统能够连接互联网的情况。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LyxG3kFo-1655128427968)(59b786fd940c21f619ee5e99bb84d128.png)]

两个显著特点

  • 渗透测试是一个渐进的并且逐步深入的过程。
  • 渗透测试是选择不影响业务系统正常运行的攻击方法进行的测试。

渗透测试方法

黑箱测试

黑箱测试又称为所谓的“Zero-Knowledge Testing”,渗透者完全处于对系统一无所知的状态, 通常这类型测试,最初的信息获取来自于DNS、 Web、Email及各种公开对外的服务器

白盒测试

测试者可以通过正常渠道向被测单位取得各种资料,包括网络拓扑、员工资料甚至网站或其它程序的代码片断,也能够与单位的其它员工(销售、程序员、管理者…)进行面对面的沟通。

隐秘测试

通常情况下,接受渗透测试的单位网络管理部门会收到通知:在某些时段进行测试。因此能够监测网络中出现的变化。隐秘测试则被测单位也仅有极少数人知晓测试的存在,因此能够有效地检验单位中的信息安全事件监控、响应、恢复做得是否到位。

linux基本命令

基本指令功能
ls显示文件或目录
mkdir创建目录
cd切换目录
touch创建空文件
cat查看文件内容
cp拷贝
mv移动或重命名
find在文件系统中搜索某文件
stat显示指定文件的详细信息,比ls更详细
who显示在线登陆用户
whoami显示当前操作用户
hostname显示主机名
uname显示系统信息
top动态显示当前耗费资源最多进程信息
ps显示瞬间进程状态 ps -aux
du查看目录大小 du -h /home带有 单位显示目录信息
df查看磁盘大小 df -h 带有单位显示磁盘信息
ifconfig查看网络情况
ping测试网络连通
netstat显示网络状态信息
man命令不会用了?用man指令,如:man ls
clear清屏
kill杀死进程,可以先用ps或top命令查看进程的id,然后再用kill命令

堆栈基础

问题回顾

编制程序的四个步骤

编辑、编译、链接、运行

编译——检查语法并对单个文件产生可执行程序

链接——多个可执行文件进行关联(函数调用信息),增加启动程序等

如何认识BUG和漏洞

BUG就是缺陷,一种表现就是用户部分操作导致程序崩溃,比如输入过长、除以0等。

程序崩溃就意味着用户的输入会影响程序正常执行,意味着可能通过BUG提供的入口输入构造的恶意程序让程序做非法的事情。因此,在安全人眼中,BUG是一种软件漏洞

漏洞是网络安全的源起之地。

内存区域

一个进程可能被分配到不同的内存区域去执行:

  • 代码区

    通常是指用来存放程序执行代码的一块内存区域,这个区域存储着被装入执行的二进制机器代码,处理器会到这个区域取值并执行

  • 静态数据区

    通常是指用来存放程序运行时的全局变量静态变量等的内存区域。通常,静态数据区包括初始化数据区(Data Segment)和未初始化数据区(BSS Segment)两部分。未初始化数据区存放的是未初始化的全局变量和静态变量,特点是可读写,在程序执行之前BSS段会自动清0。

  • 堆区

    用于动态地分配进程内存。进程可以在堆区动态地请求一定大小的内存,并在用完之后归还给堆区。动态分配和回收是堆区的特点。

  • 栈区

    用于支持进程的执行,动态地存储函数之间的调用关系、局部变量等,以保证被调用函数在返回时恢复到母函数中继续执行。

进程内存的精确组织形式依赖于操作系统、编译器、链接器以及载入器,不同操作系统有不同的内存组织形式。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zY6GjWvP-1655128427970)(81bb40449472799328aa022873cbedd8.png)]

堆区和栈区

程序在执行的过程需要两种不同类型的内存来协同配合,即栈区和堆区。

栈区

栈(stack)区主要存储函数运行时的局部变量、数组等。栈变量在使用时不需要额外的申请操作,系统栈会根据函数中的变量声明自动为其预留内存空间; 同样,栈变量的释放也无需程序员参与,由系统栈跟随函数调用的结束自动回收

栈区是向低地址扩展的数据结构,是一种先入后出的特殊结构。栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的默认大小是2M,如果申请的空间超过栈的剩余空间时,将提示溢出

堆区

堆(heap)区是一种程序运行时动态分配的内存。所谓动态,就是说所需内存的大小在程序设计时不能预先确定或者内存过大无法在栈区分配,需要在程序运行的时候参考用户的反馈。

堆区在使用的时候需要程序员使用专有的函数进行申请,如C语言的malloc函数、C++语言的new函数等。 它是向高地址扩展的数据结构,堆的大小受限于计算机的虚拟内存。

堆区和栈区的区别
  • 申请方式

    栈:由系统自动分配。例如,声明一个局部变量int b,系统自动在栈中为b开辟空间。

    堆:需要程序员自己申请并指明大小。c中malloc函数p1 = (char *)malloc(5)。

  • 申请效率

    栈由系统自动分配,速度较快,但程序员是无法控制的。

    堆是由程序员分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来方便。

堆结构

堆的内存组织如下表,包括堆块堆表两部分。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2eozSNVF-1655128427971)(cec95756179f041920adbf1e6569966d.png)]

  • 堆表

    堆块是堆的基本组织单位,包括两个部分,即块首和块身。块首是用来标识这个堆块自身的信息,例如块大小、空闲还是占用等;块身紧随其后,是最终分配给用户使用的数据区。

  • 堆表

    堆表一般位于整个堆区的开始位置,用于索引堆区中所有堆块的重要信息,包括堆块的位置、堆块的大小、空闲还是占用等。

    堆表的数据结构决定了整个堆区的组织方式,是快速检索空闲块保证块分配效率的关键。堆表在设计的时候,可能会采用平衡二叉树等高效数据结构用于优化查找效率。现代操作系统的堆表往往不止一种数据结构。

堆块

堆块会有两种状态:占有态和空闲态

空闲态的堆块会被链入空链表中,由系统管理。 而占有态的堆块会返回一个由程序员定义的句柄,通常是一个堆块指针,来完成对堆块内存的读、写和释放操作,由程序员管理。

对于空闲态堆块而言,块首额外存储了两个4字节的指针:Flink指针和Blink指针,用于链接系统中的其他空闲堆块。其中,Flink前向指针存储了前一个空闲块的地址,Blink后向指针存储了后一个空闲块的地址

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vXBRMmLU-1655128427971)(9bb0ad0162f17f668985cbad2656b031.png)]

注意:指向堆块的指针或者句柄,指向的是块身的首地址。也就是,我们使用函数申请得到的地址指针都会越过8字节(32位系统)的块首,直接指向数据区(块身)。

堆块的大小包括块首在内,如果申请32字节,实际会分配40字节,8字节的块首+32 字节的块身。

堆块的单位是8字节,不足8字节按8字节分配。

堆表

在Windows系统中,占有态的堆块被使用它的程序索引,而堆表只索引所有空闲态的堆块。其中,最重要的堆表有两种:空闲双向链表freelist(简称空表)和快速单向链表lookaside(简称快表)。快表是为了加速堆块分配而采用的堆表,从来不发生堆块合并。由于堆溢出一般不利用快表,故不作详述。

空表包含空表索引(Freelist array)和空闲链块两个部分。空表索引也叫空表表头,是一 个大小为128的指针数组,该数组的每一项包括两个指针,用于标识一条空表。

空表

空表索引的第二项(free[1])标识了堆中所有大小为8字节的空闲堆块。之后每个索引项指示的空闲堆块递增8字节。把空闲堆块按照大小的不同链入不同的空表,可以方便堆管理系统高效检索指定大小的空闲堆块。空表索引的第一项free[0]所标识的空表相对比较特殊,这条双向链表链入了所有大于等于1024字节小于512KB的堆块,升序排列。这个空表通常又称为零号空表。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Un1VKLgr-1655128427972)(c2153b233d139fe412989a4f2e506d58.png)]

堆块的分配和释放

以空表为例,来讲解堆块的分配、释放和合并

堆块分配

依据既定的查找空闲堆块的策略,找到合适的空闲堆块之后,将其状态修改为占用态、把它从堆表中“卸下”、返回一个指向堆块块身的指针给程序使用。

  1. 普通空表分配时首先寻找最优的空闲块分配,若失败,一个稍大些的块会被用于分配。这种次优分配发生时,会先从大块中按请求的大小精确地“割”出一块进行分配,然后给剩下的部分重新标注块首,链入空表。也就是说,空表分配存在找零钱的情况。
  2. 零号空表中按照大小升序链着大小不同的空闲块,故在分配时先从free[0]反向查找最后一 个块(即最大块),看能否满足要求,如果满足要求,再正向搜索最小能满足要求的空闲堆块进行分配。

堆块释放

堆块的释放操作包括将堆块状态由占用态改为空闲态、链入相应的堆表。所有释放的堆块都链入相应的表尾。

堆块合并

堆块的分配和释放操作可能引发堆块合并,即当堆管理系统发现两个空闲堆块相邻时,就会进行堆块合并操作。

堆块的合并包括几个动作:将堆块从空表中卸下、合并堆块、修改合并后的块首、链接入新的链表(合并的时候还有一种操作叫内存紧缩)。

函数调用

函数调用时候将借助系统栈来完成函数状态的保存和恢复。

函数调用例子

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x4I3HRwr-1655128427973)(16b723b65327a1cd15e44686af1b2e7a.png)]

CPU是怎么知道要去func_A的代码区取指,在执行完func_A后又是怎么知道跳回到main函数(而不是func_B的代码区)的呢?这些跳转地址我们在代码中并没有直接说明,CPU是从哪里获得这些函数的调用及返回的信息的呢?

这些代码区中精确的跳转都是在与系统栈巧妙地配合过程中完成的。

当函数被调用时,系统栈会为这个函数开辟一个新的栈帧,并把它压入栈中。

每个栈帧对应着一个未运行完的函数。栈帧中保存了该函数的返回地址和局部变量。从逻辑上讲,栈帧就是一个函数执行的环境:函数参数、函数返回地址、函数局部变量等等。

当函数返回时,系统栈会弹出该函数所对应的栈帧。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UP7zuISO-1655128427974)(64becc14564324010655532db6a758bf.png)]

函数调用步骤

  • 参数入栈

    将参数从右向左压入系统栈中。

  • 返回地址入栈

    将当前代码区调用指令的下一条指令地址压 入栈中,供函数返回时继续执行。

  • 代码区跳转

    处理器从当前代码区跳转到被调用函数的入口处。

  • 栈帧调整

    1. 保存当前栈帧状态值,已备后面恢复本栈帧时使用。(EBP入栈)
    2. 将当前栈帧切换到新栈帧。(将ESP值赋值EBP,更新栈帧底部)

函数栈帧中包含的信息

  • 局部变量

    为函数局部变量开辟的内存空间。

  • 栈帧状态值

    保存前栈帧的顶部和底部(实际上只保存前栈帧的底部,前栈帧的顶部可以通过 堆栈平衡计算得到),用于在本帧被弹出后恢复出上一个栈帧。

  • 函数返回地址

    保存当前函数调用前的** “断点”信息**,也就是函数调用前的指令位置,以便在函数返回时能够恢复到函数被调用前的代码区中继续执行指令。

常用寄存器

寄存器(register)是中央处理器CPU的组成部分。寄存器是有限存贮容量的高速存贮部件。它们可用来暂存指令数据地址。我们常常看到32位CPU、64位CPU这样的名称,其实指的就是寄存器的大小。32位CPU的寄存器大小就是4个字节。

CPU本身只负责运算,不负责储存数据。数据一般都储存在内存之中,CPU要用 的时候就去内存读写数据。但是,CPU的运算速度远高于内存的读写速度,为了 避免被拖慢,CPU自带一级缓存和二级缓存。基本上,CPU缓存可以看作是读写速度较快的内存。但是,CPU缓存还是不够快,另外数据在缓存里面的地址是不固定的,CPU每次读写都要寻址也会拖慢速度。因此,除了缓存之外,CPU使用寄存器来储存最常用的数据。也就是说,那些最频繁读写的数据(比如循环变量),都会放在寄存器里面,CPU优先读写寄存器,再由寄存器跟内存交换数据

与栈相关的寄存器

每一个函数独占自己的栈帧空间。当前正在运行的函数的栈帧总是在栈顶。Win32系统提供两个特殊的寄存器用于标识位于系统栈顶端的栈帧:

  • ESP

    栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。

  • EBP

    基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WSuXgZtm-1655128427975)(52d45c9a7c63b2441090dc66890e052a.png)]

指令寄存器EIP

指令寄存器(extended instruction pointer),其内存放着一个指针,该指针永远指向下一条等待执行的指令地址。可以说如果控制了EIP寄存器的内容,就控制了进程——我们让EIP指向哪里, CPU就会去执行哪里的指令。

主要寄存器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f4UAxseR-1655128427976)(3da3fe25e44f9456b5d92b8c12ca5b0c.png)]

数据寄存器

数据寄存器主要用来保存操作数和运算结果等信息,从而节省读取操作数所需占用总线和访问存储器的时间。

32位CPU有4个32位的通用寄存器EAX、EBX、ECX和EDX。对低16位数据的存取,不会影响高16位的数据。这些低16位寄存器分别命名为:AX、BX、CX和DX,它和先前CPU中的寄存器相一致。

4个16位寄存器又可分割成8个独立的8位寄存器(AX:AH-AL、 BX:BH-BL、CX:CH-CL、DX:DH-DL),每个寄存器都有自己的名称,可独立存取。程序员可利用数据寄存器的这种“可分可合”的特性,灵活地处理字/字节的信息。

EAX

累加器(Accumulator)

可用于乘、 除、输入/输出等操作,它们的使用频率很高。EAX还通常用于**存储函数的返回值**。

EBX

基地址寄存器(Base Register)

它可作为存储器指针来使用,用来访问存储器。

ECX

计数寄存器(Count Register)

在循环和字符串操作时,要用它来控制循环次数;在位操作中,当移多位时, 要用CL来指明移位的位数。

EDX

数据寄存器(Data Register)

在进行乘、除运算时,可作为默认操作数参与运算,也可用于存放I/O的端口地址

变址寄存器

变址寄存器主要用来存放操作数的地址,用于堆栈操作变址运算中计算操作数的有效地址。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6bQysPuX-1655128427977)(b5104542b844c26803b2304134bd25ad.png)]

指针寄存器

寄存器EBP、ESP称为指针寄存器(Pointer Register),主要用于存放堆栈内存储单元的偏移量,用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。指针寄存器不可分割成8位寄存器。作为通用寄存器,也可存储算术逻辑运算的操作数和运算结果。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AP2hhmSA-1655128427978)(f08a5c2c49ea053bdd83af882fb8dc6f.png)]

段寄存器

段寄存器是根据内存分段的管理模式而设置的。内存单元的物理地址由段寄存器的值和一个偏移量组合而成的,标准形式为“段:偏移量”,这样可用两个较少位数的值组合成一个可访问较大物理空间的内存地址。

可以认为,一个段是一本书的某一页,偏移量是一页的某一行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IFm72a8Y-1655128427978)(af635cb9272cbb09f95904428a9ccb12.png)]

指令指针寄存器

指令寄存器IR,Instruction Register),是临时放置从内存里面取得的程序指令的寄存器,用于存放当前从主存储器读出的正在执行的一条指令。当执行一条指令时,先把它从内存取到数据寄存器(DR,Data Register)中,然后再传送至IR。指令划分为操作码和地址码字段,由二进制数字组成。

指令指针寄存器用英文简称为IP(Instruction Pointer),它虽然也是一种指令寄存器,但是严格意义上和传统的指令寄存器有很大的区别。指令指针寄存器存放下次将要执行的指令在代码段的偏移量。在计算机工作的时候,CPU会从IP中获得关于指令的相关内存地址,然后按照正确的方式取出指令,并将指令放置到原来的指令寄存器中。

32位CPU把指令指针扩展到32位,并记作EIP

标志寄存器

标志寄存器在32位操作系统中大小是32位的,也就是说,它可以存32个标志。

实际上标志寄存器并没有完全被使用,重点认识三个标志寄存器:ZF (零标志)OF(溢出标志)CF(进位标志)

Z-Flag(零标志):它可以设成0或者1。

O-Flag(溢出标志):反映有符号数加减运算是否溢出。如果运算结果超过了有符号数的表示范围,则OF置1,否则置0。例如:EAX的值为7FFFFFFFF,如果你此时再给EAX加1,OF寄存器就会被设置成1,因为此时EAX寄存器的最高有效位改变了。

C-Flag(进位标志):用于反映运算是否产生进位或借位。如果运算结果的最高位产生一个进位或借位,则CF置1,否则置0。例,假如某寄存器值为FFFFFFFF,再加上1就会产生进位。


汇编语言

汇编—寻址方式

寻址方式就是处理器根据指令中给出的地址信息来寻找有效地址的方式,是确定本条指令的数据地址以及下一条要执行的指令地址的方法。

指令寻址

指令的寻址方式有以下两种:

顺序寻址方式

由于指令地址在内存中按顺序安排,当执行一段程序时,通常是一条指令接一条指令地顺序进行。通常,需要使用指令计数器来完成顺序指令寻址。

指令计数器是计算机处理器中的一个包含当前正在执行指令地址的寄存器, 在X86架构中称为指令指针IP(Instruction Pointer)寄存器,在ARM或C51架构中也称为程序计数器(PC)。每执行完一条指令时,指令计数器中的地址或自动加1或由转移指针给出下一条指令的地址。

跳跃寻址方式

当程序转移执行的顺序时,指令的寻址就采取跳跃寻址方式。**所谓跳跃,是指下条指令的地址码不是由程序计数器给出,而是由本条指令给出。**注意,程序跳跃后按新的指令地址开始顺序执行。因此,程序计数器的内容也必须相应改变,以便及时跟踪新的指令地址。

采用指令跳跃寻址方式,可以实现程序转移或构成循环程序, 从而能缩短程序长度,或将某些程序作为公共程序引用。指令系统中的各种条件转移或无条件转移指令,就是为了实现指令的跳跃寻址而设置的。注意跳跃的结果是当前指令修改PC程序计数器的值,所以下一条指令仍是通过程序计数器PC给出。

操作数寻址

形成操作数的有效地址的方法称为操作数的寻址方式。

汇编指令MOV 目的操作数, 源操作数

表示将一个数据从源地址传送到目标地址。

立即寻址

指令的地址字段给出的不是操作数的地址,而是操作数本身, 这种寻址方式称为立即寻址。立即寻址方式的特点是指令执行时间很短,因为它不需要访问内存取数,从而节省了访问内存的时间。

MOV CL, 05H表示将05H这个数值存储到CL寄存器中。

直接寻址

直接寻址是一种基本的寻址方法,其特点是在指令中直接给出操作数的有效地址。由于操作数的地址直接给出而不需要经过某种变换,所以称这种寻址方式为直接寻址方式。

MOV AL,[3100H]表示将地址[3100H]中的数据存储到AL中,地址要写在括号“[”,“]”内。

在通常情况下,操作数存放在数据段中。所以,默认情况下操作数的物理地址由数据段寄存器 DS 中的值和指令中给出的有效地址直接形成

上述指令中,操作数的物理地址应为DS:3100H。如果在指令中使用段超越前缀指定使用的段,则可以从其他段中取出数据,如:MOV AL, ES:[3100H]

间接寻址

间接寻址是相对直接寻址而言的,在间接寻址的情况下,指令地址字段中的形式地址不是操作数的真正地址,而是操作数地址的指示器,或者说此形式地址单元的内容才是操作数 的有效地址。

如:MOV [BX], 12H

这是一种寄存器间接寻址,BX寄存器存操作数的偏移地址,操作数的物理地址应该是DS:BX。表示将12H这个数据存储到DS:BX中。

如果操作数存放在寄存器中,通过指定寄存器来获取数据,则称为寄存器寻址。如:MOV BX, 12H表示将12H这个数据存储到BX寄存器中。

相对寻址

操作数的有效地址是一个基址寄存器(BX, BP)变址寄存器(SI, DI)的值加上指令中给定的偏移量之和

如:MOV AX, [DI + 1234H] 操作数的物理地址应该是DS: DI + 1234H。

与间接寻址相比,可以认为相对寻址是在间接寻址基础上,增加了偏移量

基址变址寻址

基址寄存器的内容,加上变址寄存器的内容而形成操作数的有效地址。

如:MOV EAX, [EBX+ESI]

也可以写成MOV EAX, [BX][SI]MOV EAX, [SI][BX]

相对基址变址寻址

在基址变址寻址方式融合相对寻址方式,即增加偏移量。

如:MOV EAX, [EBX+ESI+1000H]

也可以写成MOV EAX, 1000H [BX][SI]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wYCDCRHv-1655128427979)(daf6b3eec9401e39862c30d968378f6a.png)]

汇编—主要指令

数据传送指令

数据传送指令功能
MOV 目的操作数,源操作数把源操作数送给目的操作数
LEA 目的数, 源数将有效地址传送到指定的寄存器
XCHG交换两个操作数的数据
PUSH,POP把操作数压入或取出堆栈
PUSHF,POPF,PUSHA,POPA堆栈指令群
LEA,LDS,LES取地址至寄存器

mov al,[3100H]; 表示将3100H中的数值写入AL寄存器。

lea eax, dword ptr [4*ecx+ebx]

源数为”dword ptr [4*ecx+ebx]”,即地址为4*ecx+ebx里的数值

dword ptr是告诉地址里的数值是一个dword型数据。上述lea语句则是将源数的地址4*ecx+ebx赋值给eax。

位运算指令

位运算指令功能
AND,OR,XOR,NOT,TEST执行BIT与BIT之 间的逻辑运算
SHR,SHL,SAR,SAL移位指令
ROR,ROL,RCR,RCL循环移位指令

AND (逻辑与)语法: AND 目标数, 源数

AND运算对两个数进行逻辑与运算 (当且仅当两操作数对应位都为“1”时,结果的相应位为“1”,否则结果相应位为“0”),目标数=目标数 AND 原数。AND指令会清空OF、CF标记,设置ZF标记。

算数运算指令

算数运算指令功能
ADD,ADC加法指令
SUB,SBB减法指令
INC,DEC将OP的值加一或减一
NEG将OP的符号反相(取二进制补码)
MUL,IMUL乘法指令
DIV,IDIV除法指令

ADD语法ADD 被加数, 加数

加法指令将一个数值加在一个寄存器上或者一个内存地址上

add eax,123; 相当于 eax=eax+123 加法指令对ZF、OF、CF都会有影响。

程序流程控制指令

程序流程控制指令功能
CMP比较OP1和IOP2的值
JMP跳转到指定地址执行
LOOP循环指令集
CALL,RET子程序调用,返回指令
INT,IRET中断调用及返回指令。在执行INT时,CPU会自动将标志寄存器的值入栈,在执行IRET时,则会将堆栈中的标志值弹回寄存器。
REP, REPE, REPNE重复前缀指令集

CMP语法CMP 目标数, 源数

CMP指令比较两个值并且标记CF、OF、ZF

CMP EAX, EBX比较eax和ebx是否相等,如果相等就设置ZF为1

CALL语法CALL something

CALL指令将当前EIP中的指令地址压入栈中,并且调用CALL后的子程序

CALL可以这样使用:

CALL 404000 最常见: CALL 地址

CALL EAX CALL 寄存器 - 如果寄存器存的值为404000,那就等同于第一种情况。

RET语法RET

RET指令的功能是从一个代码区域中退出到调用CALL的指令处。

条件转移命令

JXX: 当特定条件成立则跳往指定地址执行。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6KPNYSzs-1655128427980)(fd4327f68407eb9d8d96f4bfa8282060.png)]

字符串操作指令集

字符串操作指令集功能
MOVSB,MOVSW,MOVSD字符串传送指令
CMPSB,CMPSW,CMPSD字符串比较指令
SCASB,SCASW字符串搜索指令
LODSB,LODSW,STOSB,STOSW字符串载入或存贮指令

汇编—函数调用示例

一个简单的C语言程序(VC6,Win32控制台程序)

#include<iostream>
int add(int x,int y){
    int z=0;
    z=x+y;
    return z;
}
void main(){
    int n=0;
    n=add(1,3);
    printf("%d\n",n);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4JenMmKe-1655128427981)(24e2b5e7af27117de1d235e0fe077d97.png)]

函数调用前

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EfRD6LQs-1655128427981)(a4e46bd11cf82cffd92bfe85bd7dad74.png)]

函数调用时

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jwaHbLDV-1655128427982)(bbd54a92cf3501d3eced78f2e2b9872f.png)]

Add函数的汇编代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tAoQ5Zap-1655128427983)(28e95c3a1bd18ff7a05a4a653aa97423.png)]

栈帧切换

004113A0 push ebp; 将EBP的值入栈。

004113A1 mov ebp,esp;将ESP的值赋值给EBP。

004113A3 sub esp, 0CCh;将ESP抬高。

上面三行汇编代码完成了栈帧切换,即保存了主函数栈帧的EBP的值,也通过改变EBP和 ESP寄存器的值,为add函数分配了栈帧空间。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g6PYg1Eh-1655128427984)(cfc053dd354c536a5935c831d2b5f078.png)]

函数状态保存

004113A9 push ebx;用于保存现场,ebx作为内存偏移指针使用。

004113AA push esi;用于保存现场,esi是源地址指针寄存器

004113AB push edi;用于保存现场,edi是目的地址指针寄存器。

004113AC lea edi,[ebp-0CCh];将ebp-0CCh地址装入EDI。

栈帧切换

004113B2 mov ecx,33h;设置计数器数值,即将ECX寄存器赋值为33h

004113B7 mov eax,0CCCCCCCCh;向寄存器EAX赋值

004113BC rep stos dword ptr es:[edi];循环将栈区数据都初始化为CCh。

rep指令的目的是重复其上面的指令。ECX的值是重复的次数。STOS指令的作用是将eax中的值拷贝到ES:EDI指向的地址。

执行函数体

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YIVPfb4D-1655128427984)(09afb116ea9376c09bff4a6bd13b2964.png)]

栈帧情况

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gG9ZAVFU-1655128427985)(4b4adb29f00c0174e43347b043193e83.png)]

[x]=[ebp+8]

[y]=[ebp+0ch]

[z]=[ebp-8]这个是基于VS2005编译的

恢复状态

函数调用完毕,而函数的返回值将存储在EAX寄存器中。之后,函数调用完毕后,将恢复栈状态到main函数:

004113D1 pop edi;恢复寄存器值 
004113D2 pop esi;恢复寄存器值 
004113D3 pop ebx;恢复寄存器值
0004113D4 mov esp,ebp;恢复寄存器值
004113D6 pop ebp;恢复寄存器值 
004113D7 ret;根据返回地址恢复EIP值,相当于pop EIP。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Guff_9hys/article/detail/925813
推荐阅读
相关标签
  

闽ICP备14008679号