恶意软件分析-汇编基础

admin 2024年12月2日22:43:53评论4 views字数 10941阅读36分28秒阅读模式

欢迎加入我的知识星球,目前正在更新免杀相关的东西,129/永久,每100人加29,每周更新2-3篇上千字PDF文档。文档中会详细描述。

加好友备注(星球)!!!

恶意软件分析-汇编基础

恶意软件分析-汇编基础

恶意软件分析-汇编基础

恶意软件分析-汇编基础

计算机基础

CPU

CPU是计算机的大脑,负责执行指令和处理数据,CPU内部包含寄存器,他是一些告诉存储单元,用于临时存储正在处理的数据和指令。

内存

内存用于存储CPU运行过程中所需的数据和程序指令,如下图将内存分为两部分,分别是数据和代码,分别表示用户数据和程序指令。

输入/输出设备

输入设备和输出设备是用户与计算机之间交互的媒介,输入设备入键盘,鼠标等用于向计算机传递指令和数据。输出设备如显示器,打印机等用于将计算结果反馈给用户。

如下图中的箭头连接,CPU与内存之间的双向箭头表示数据的双向流动,CPU可以从内存中读取指令和数据,也可以将处理结果返回给内存。

CPU与输入/输出设备之间的箭头表示CPU与这些设备之间的数据交互,接收输入数据或发送输出数据。

恶意软件分析-汇编基础

位(bit)是信息的最小单位,每一个位都可以表示两种状态,分别是0或1。

字节

8个位组成一个字节,一个字节通常用两个16进制数字表示,而每个十六进制数字由4个位组成,称为半字节。

如下图这里有一个字节为5D,它是8位组成的,如果我们从中间切割开了,那么0101就是5,而1101就是D

恶意软件分析-汇编基础

在计算机科学中,WordDWORDQword定义如下:

Word大小为2个字节,Dword大小为4个字节,Qword大小为8个字节。

如下图中Byte 每一个字节包含了8位,这里的5D是一个字节。

Word类型是由2个字节组成的,这里的8BEC是2个字节。

DWORD类型是由4个字节组成的,这里的000136CF是4个字节。

Qword类型是由8个字节组成的,这里的000136cf000136cf是8个字节。

那么Word类型也可以分为2个1字节的,Dword类型也可以分为2个2字节,Qword也可以分为两个4字节。

恶意软件分析-汇编基础

数据字节解释

一个字节或字节序列可以被不同的解析,比如5D可以表示二进制数: 01011101 十进制数: 93 字符: ] 此外字节5D还可以表示一条机器指令: pop ebp

示例二: 由两个字节88 EC组成的序列可以表示机器指令: mov ebp,esp

示例三: 一个双字(DWORD)值0x010F1000可以表示一个内存地址。

内存

主内存(RAM)用于存储计算机的代码(机器码)和数据。主内存是计算机运行时暂时存储数据的关键组件。

计算机的内存可以看作是一个字节数组,每一个字节都被分配了唯一的编号,成为它的地址。

如下图中显示了主内存中每个地址与存储的数据之间的关系,比如说0x10F10090x10F1008等等,每一个地址都对应主内存中的一个字节。

数据是以字节为单位存储的,通常是以16进制的方式表示,比如0x10F1009存储值为450x10F1008存储的值为FC

数据如何存储在内存中

数据在内存中按照小端格式存储,什么是小端格式? 小端格式指的是低位字节存储在低地址处,而高位字节存储在较高的内存地址中。

比如说我们有一个4字节的整数值0x12345678 并将其存储到内存地址从0x1000开始的地方,整数0x12345678的每个字节是:

最低有效字节(LSB): 0x78第二字节:0x56第三字节:0x34最高有效字节(MSB): 0x12
地址        数据0x1000     0x78 (最低有效字节)0x1001     0x560x1002     0x340x1003     0x12 (最高有效字节)
程序编译

程序的源代码是使用高级语言,比如C或C++来编写的。源代码通过编译器运行,编译器将高级语言的语句翻译为一种中间形式,称之为目标文件(Object File)或机器码,这种中间格式是不可读的,皆在由处理器执行,目标代码通过链接器(Linker)处理,将目标文件与所需的库文件(比如动态链接库)链接在一起,最终生成一个可执行的文件。

恶意软件分析-汇编基础

可执行文件在磁盘上

当一个程序被编译时,编译器会将数据和代码分离到磁盘上的不同部分,为了简化理解,我们可以将其可执行文件当看做包含如下几个部分。

代码段: .text节 存储程序的可执行代码。

数据段: .data 节存储程序中的全局变量或静态变量 这些变量在程序运行时是可以被修改的。.rdata存储只读数据,例如字符串常量,这些数据在运行时不能被修改。

可执行文件运行时

当可执行文件被双击时,操作系统会为其分配内存,并由操作系统的加载程序将可执行文件加载到分配的内存中,需要注意的是可执行文件在磁盘上的结构和他的内存中的结构是非常相似的。

具体细节如下:

  1. 磁盘上的可执行文件: PE Header头,代码段,数据段。

  2. 内存中的结构: 经过加载后,内存会将这些部分分配到不同的区域,低地址部分包含堆栈。其他内容如PE Header 代码段,数据段会被映射到相应的内存区域。

程序执行时的步骤
  1. 加载程序到内存中,程序中包含的代码和数据都会被加载到内存中,为后续的操作做好准备。

  2. CPU从内存中获取机器指令,对这些指令进行解码,最后执行解码之后的指令。

  3. CPU从内存中获取所需的数据,同时也可以将处理后的数据写回到内存中。

  4. 如果需要,CPU会与输入/输出系统进行交互,比如读取外部设备数据或输出结果。

内存结构图解:

  1. Stack(栈): 用于函数调用和局部变量存储。

  2. Heap(堆): 动态分配的内存空间。

  3. PE Header: 包含程序的头部信息。

  4. .Code: 保存可执行的机器指令。

  5. .Data: 存储初始化和非初始化的数据 例如静态变量 只读数据等等。

CPU的任务:

CPU负责解释并执行存储在内存中的机器代码,它通过从内存读取指令和数据来完成计算,并将计算结果写回到内存或输出设备。

如下图解释:

CPU的职责是解析和执行机器代码,具体流程包括:

  1. 从内存中加载机器指令,例如558BEC51等等。

  2. 依次解码每一条指令,理解其操作逻辑。

  3. 执行这些指令,完成对应的任务,比如读取数据,运算或写回内存。

内存部分:

  1. Stack主要用于函数调用和局部变量存储。每次函数调用时会在栈中分配内存,用于存储局部变量,函数返回地址等等。

  2. 栈是一种后进后出的数据结构,空间是动态分配的。

  3. 堆主要适用于动态内存分配,在程序运行时可以通过指令动态分配和释放内存。比如C中的malloc函数会分配堆内存。

CPU和内存的交互流程如下:

  1. 加载程序到内存中,程序被操作系统加载到内存中,各部分比如.Code和.Data段都会被映射到相应的内存区域。

  2. CPU从.Code段中读取指令并解码执行。

  3. 如果指令需要操作数据,那么CPU会从.Data或Heap区域读取/写入数据。

  4. 函数调用时,CPU会在栈上分配临时变量和存储返回地址。

这里我们简单举一个例子,如下代码:

#include <stdio.h>int main(){    char *string = "this is ";  printf("%s",string);  return 0;}

我们编译之后我们使用PE Internals打开,其实就是一个PE解析工具,这里也可以使用其他的PE解析工具。

下载地址如下:

https://download.cnet.com/download/pe-internals/3000-2352_4-75824346.html

我们来到.data节这里,我们之前说过.data节中存储了相关的数据。那么这里的This is a simple program字符串也就是数据,我们查看.data节可以看到里面存储着我们的字符串。

恶意软件分析-汇编基础

我们前面也说过,代码指令是存储在.Code段的,也就是代码段,所对应的就是.text节。这个代码是需要进行解码的,解码之后CPU才能执行。

恶意软件分析-汇编基础

如上是在磁盘上的可执行文件,我们再来看看运行时的可执行文件,这里使用x32dbg打开。

我们在x32dbg中查看该可执行程序加载到内存中的内存映射。

恶意软件分析-汇编基础

我们可以看到数据部分被加载到了0x00B33000这个地址,我们可以双击进去查看。可以看到这里其实就是我们的数据。这其实和我们在磁盘上看到的是一样的。

恶意软件分析-汇编基础

接下来我们查看.text节。右键->在内存窗口中转到。

恶意软件分析-汇编基础

恶意软件分析-汇编基础

我们可以看到在.text节中的内容。

恶意软件分析-汇编基础

其实对应的就是我们反汇编的指令了。我们这里可以看到比如55对应push ebp指令,8bEC对应mov ebp,esp指令。

恶意软件分析-汇编基础

CPU寄存器

x86 CPU有八个通用32位寄存器,他们分别是: EAX,EBX,EDX,ESP,EBP,ESI,EDI。

每个32位寄存器的低16位可以分别通过以下名称访问: AX,BX,CX,DX,SP,BP,SI,DI。

对于寄存器 EAX、EBX、ECX 和 EDX,它们的低 8 位可以分别通过以下名称访问:AL、BL、CL 和 DL。同时,高 8 位也可以通过以下名称访问:AH、BH、CH 和 DH。

指令指针寄存器(EIP):

CPU中有一个特殊寄存器称之为EIP,它包含了下一个将要执行的指令的地址,当一条指令被执行后,EIP会指向内存中的下一条指令。

恶意软件分析-汇编基础

EFLAGS寄存器:

EFLAGS是一个32位的寄存器,其中的每一位都是一个标志位。EFLAGS中的标志位用于指示计算机的状态以及控制CPU的操作。

数据传输指令

所谓数据传输指令就是从内存中获取数据或者将数据写入到内存中。

mov指令:

mov指令用于将数据从一个位置移动到另一个位置。

mov dst, src  ; 相当于 dst = src

我们来看一下mov指令的变体,mov指令的第一个变体是将常量或一个数值移动到寄存器中。

mov eax,10mov bx,7mov eax,6h

恶意软件分析-汇编基础

从一个寄存器移动值到另外一个寄存器中。

mov ebx,10mov eax,ebx

恶意软件分析-汇编基础

那么如果当你定义了一个变量会发生什么?

int val = 100;

一个整数在内存中占用了4个字节,数值100在内存中将以4个字节的序列存储,00 00 00 64

这4个字节以小端格式存储:在小端格式中,最低有效字节存储在最低地址处,在该示例中,内存地址0x403000存储64。高位字节00存储在更高的地址中。

我们也可以使用mov指令将内存地址中的值移动到寄存器中。这里其实就是将0x00b33000的地址的值存到eax寄存器中。

mov eax,[0x00b33000]

恶意软件分析-汇编基础

方括号的作用:

方括号 [] 表示内存地址,括号内可以包含:寄存器,寄存器加常量,一个寄存器加上另一个寄存器。

需要记住的一个简单的规则就是方括号内的内容代表一个地址。

mov eax,[ebx] //将寄存器EBX指定的地址处的值移动到寄存器EAX中mov eax,[ebx+ecx] //将寄存器EBX和ECX的值相加所表示的地址处的值移动到EAX寄存器中。mov ebx,[ebp-4] //将寄存器EBP减去4的地址处的值移动到ebx寄存器中。

lea指令

Lea的全称是Load Effective Address 用于加载地址而不是加载地址中的值。

lea ebx,[0x403000] //将地址0x403000加载寄存器EBX中lea eax,[ebx] //如果EBX=0x403000 则EAX也会加载0x403000

恶意软件分析-汇编基础

DWORD PTR

DWIRD PTR表示从内存地址中读取4字节的值。

mov eax, dword ptr [ebp-4] //从EBP-4指定的内存地址中读取4字节值到EAX寄存器中

恶意软件分析-汇编基础

从寄存器移动值到内存

通过交换操作数的位置,可以将值从寄存器移动到内存,在这种情况下,内存地址位于左侧,而寄存器位于右侧。

mov [0x403000],eax //将寄存器EAX中的4字节值移动到内存地址0x403000开始的地方mov [ebx],eax //将寄存器中的4字节值移动到寄存器EBX指定的地址

Dword ptr 表示一个双字的值被移动到内存为止中,word ptr表示一个字的值被移动到内存位置中。

mov dword ptr [402000h],13498h //将4字节值13498h移动到内存地址0x402000。mov dword ptr [ebx],100 //将4字节值100移动到由寄存器EBX指定的地址。mov word ptr [ebx],100 //将2字节值100移动到由急促器EBX指定的内存地址。

这里只需要记住dword ptr表示操作的是是4字节数据,word ptr表示操作的是2字节的数据。

如下反汇编代码请理解为C语言

mov dword ptr [ebp-4], 1mov eax,dword ptr [ebp-4]mov dword ptr [ebp-8],eax

需要注意的是变量在计算机的本质上只不过是内存的引用权或指向内存的另一个别名,具体来说,变量是程序对内存中某个地址的抽象,它允许我们以更便捷的方式访问和操作内存中的数据。

比如说我们在高级语言中可以声明: int x = 5 而在底层这实际上是在内存中某地址存储了5,并用x作为这个地址的引用。

而在反汇编中,变量通常会被映射为栈帧(ebp-4这种偏移)或寄存器(比如eax)。

所以我们需要做的是识别所有内存引用代码,可以看到方括号中的ebp-4是一个内存地址,ebp-4这个内存地址表示当前栈帧的一个局部变量,比如我们假设为var1

然后从内存地址ebp-4中读取到eax寄存器,此时寄存器eax中的值等于变量var1的值。然后将其寄存器eax的值(也就是变量var1的值)复制到另一个由ebp-8指定的内存中,ebp-8表示另外一个局部变量,假如是局部变量var2

还有一种非常简单的方式,我们可以将其mov dword ptr [ebp-4],1看成mov dword ptr [a],1 ,也可以将其mov dword ptr [ebp-8],eax看成mov dword ptr [b],eax

那么我们就可以理解为a=1eax=ab=eax。进一步来看,在CPU执行期间,寄存器用于存储临时的值,我们可以将寄存器的名字用右边的值代替,比如用eax的值替换为它所存储的a的值。其实就变成了a=1b=a

那么其实就可以还原到如下的代码了。

int a = 1;int b = var1;

恶意软件分析-汇编基础

ADD指令

ADD指令是用于加法的,ADD指令会将源操作数加到目标操作数上,结果存储在目标操作数上。格式: add destination, source

我们来看几个简单示例:

add eax,42 //将42加到寄存器eax的值上 等效于:eax = eax +42add eax,ebx //将寄存器ebx的值加到寄存器eax中 等效于: eax = eax + ebxadd [ebx],42 //将42加到ebx寄存器所指向的地址的值 等效于: *[ebx] = *[ebx] + 42

SUB指令

从目标操作数中减去源操作数,结果存储在目标操作数中。sub destination, source

这里有一个示例:

sub eax,64h //从寄存器eax的当前值中减去十六进制数64h 也就是十进制的100 等价表达: eax = eax - 0x64

恶意软件分析-汇编基础

恶意软件分析-汇编基础

恶意软件分析-汇编基础

自增和自减

在汇编语言中,有专门的的指令用于自增和自减,这些指令可以对寄存器或内存地址的值进行加1或减1的操作。

首先是自增指令INC

inc eax  //其实等效于 eax = eax+1

恶意软件分析-汇编基础

接下来是自减指令DEC.

dec eax //其实等效于 eax = eax - 1

恶意软件分析-汇编基础

乘法指令:

在汇编中,乘法操作使用MUL指令,MUL指令只接受一个操作数,该操作数会与以下调试器的值相乘。操作数MUL 指令只接受一个操作数(可以是寄存器或内存位置),它会与特定的寄存器值相乘。

8 位操作数:与 AL 寄存器的值相乘。16 位操作数:与 AX 寄存器的值相乘。32 位操作数:与 EAX 寄存器的值相乘。

结果存储方式如下:

8 位操作数:结果存储在 AX 中(16 位:高位 8 位 + 低位 8 位)。16 位操作数:结果存储在 DX:AX 中: 16 位存储在 DX。 16 位存储在 AX。32 位操作数:结果存储在 EDX:EAX 中: 32 位存储在 EDX。 32 位存储在 EAX。

这里什么意思呢?比如我们拿8位操作数来看,8位操作数的大小占用1个字节,值的范围为0-255。如果我们写的汇编指令是mul 0x2A 他会和寄存器AL的值进行相乘,相乘的结果会存储在AX寄存器中。

这里我们举一个例子,

比如说AL的值为8E 我们要使用的汇编指令为mul cl。那么就变成了cl * 8E。最后结果存储在AX寄存器中。

恶意软件分析-汇编基础

可以看到eax寄存器中的值变成了00c8136A

恶意软件分析-汇编基础

我们再来看一个32位操作数,比如说我们执行如下指令:mul ecx

那么结果其实就是高32位存储在EDX寄存器中,而低32位存储在EAX寄存器中。我们可以看到这里乘eax之后的值为:2725ada251f42c 这意味着002725ad是高32位。存储在EDX寄存器中,a251f42c是低32位。存储在EAX寄存器中。

恶意软件分析-汇编基础

如下图注意EAX寄存器和EDX寄存器中的值。

恶意软件分析-汇编基础

无符号整数除法指令:

整数触发指令使用DIV指令,DIV 指令只接受一个操作数(可以是寄存器或内存地址)。这个指令用的其实是比较少的,这里可以不太去关注了。

练习:

mov dword ptr [ebp-4], 16h  //mov dwodr [a],16h  //a = 16h // int a = 22mov dword ptr [ebp-8], 5    //mov dword [b],5 //b = 5 // int b = 5mov eax, [ebp-4]   //mov eax,[a] // eax = a add eax, [ebp-8]   //eax = eax + [b] // a = a + bmov [ebp-0Ch], eax  // mov [c],eax // c = eaxmov ecx, [ebp-4]    // mov ecx,[a] // ecx = asub ecx, [ebp-8]   // ecx = ecx - b // a = a - bmov [ebp-10h], ecx  //mov [d],ecx //d = a
int a = 22;int b = 5;int c  = a+b;c = aint a = a -bint d = a

NOT指令

NOT指令是一个位操作指令,用于对操作数中的所有位执行按位取反的操作,其实就是将将0变成1,1变成0。NOT指令只会接受一个操作数,这个操作数既是输入值,也是取反后的结果存储位置。对于 32 位的寄存器或内存地址,NOT 指令会逐位取反,并将结果存回原位置。

比如说EAX寄存器的值为:FF FF 00 00 转换成二进制就是11111111 11111111 00000000 00000000 那么如果执行了not取反指令,就变成了00000000 00000000 11111111 11111111 转换为16进制则是00 00 FF FF

那么如果用伪代码来解释的话,其实逻辑如下:

EAX = ~EAX;  // 按位取反 EAX 的值

我们来举一个例子:这里eax寄存器的值为:A251 F42C 转换为二进制为:

1010 0010 0101 0001 1111 0100 0010 1100取反:0101 1101 1010 1110 0000 1011 1101 0011

取反之后的值转换为16进制其实就是5DAE 0BD3

恶意软件分析-汇编基础

AND OR 和 XOR指令

在汇编语言中,ANDORXOR指令用于按位操作目标操作数和源操作数,并将其结果存储在目标操作数中。

AND指令很简单,其实就是对两个操作数进行按位(AND)操作,只有两个操作数对应位都是1时,结果位才是1

比如EAX寄存器的值为: 5DAE 0BD3 转换为二进制为: 0101 1101 1010 1110 0000 1011 1101 0011

EBX寄存器的值为:00582000。转换为二进制为:0101 1000 0010 0000 0000 0000

0101 1101 1010 1110 0000 1011 1101 00110000 0000 0101 1000 0010 0000 0000 0000and eax,ebx0000 0000 0000 1000 0000 0000 0000 0000 //转换为16进制8000

恶意软件分析-汇编基础

OR指令,是用于对两个操作数进行按位(OR)操作,只要两个操作数中有一个位是1,结果位就是1.

再次拿上面的举例子。

0101 1101 1010 1110 0000 1011 1101 00110000 0000 0101 1000 0010 0000 0000 0000or eax,ebx0101 1101 1111 1110 0010 1011 1101 0011 //转换为16进制为: 5DFE 2BD3

恶意软件分析-汇编基础

XOR指令用于对两个操作数进行异或(XOR操作) 当两个操作数对应位值不同时,结果位为1,否则为0.当操作数是同一个寄存器时,例如 xor eax, eax,可以快速将寄存器清零(EAX = 0)。

恶意软件分析-汇编基础

SHL指令和SHR指令:

SHL指令用于将目标寄存器或内存地址的位左移指定的次数。左移时,低位补零(向右填充 0)。高位超出的部分会被丢弃。等效操作destination = destination << count(与 C 或 Python 中的左移操作相同)。

比如说AL的值为4,对应的二进制为0000 0100 指令shl al,2 将AL中的值向左移动2位,变成了0001 0000

恶意软件分析-汇编基础

而SHR指令用于右移,将目标寄存器或内存地址的位向右移动指定的次数。低位超出的部分会被丢弃。右移时,左侧用零填充(对于无符号数)。

比如说AL的值为4,对应的二进制为0000 0100 指令shr al,2 将AL中的值向右移动2位,变成了0000 0001

恶意软件分析-汇编基础

ROL & ROR指令

ROL指令用于将操作数的位向左循环移动指定的次数。左移动过程中被移出的最高位重新进入最低位。

比如说AL的值为: 0x44 转换为二进制为: 0100 0100 执行rol al,2指令之后会将AL中的值向左循环移动2位

移动两位之后就变成了0001 0001。

恶意软件分析-汇编基础

ROR指令用于将操作数的位向右循环移动指定的次数 右移过程中 被移出的最低位重新进入最高位 位的循序循环移动 而不会丢失任何位。

比如说AL的值为: 0x44 转换为二进制为: 0100 0100 执行ror al,2指令之后会将AL中的值向右循环移动2位

右移两位就变成了0001 0001。

恶意软件分析-汇编基础

分支指令

程序在执行过程中,经常需要根据条件转向不同的代码路径,例如: if/else条件语句 循环语句 函数调用等等。

分支指令的作用是将程序的控制权转移到另外一个内存地址,通过修改CPU的指令指针,或者程序计数器实现跳转到其他内存地址执行代码。

分支指令主要分为两种类型,一种是有条件跳转,一种是无条件跳转。有条件跳转依赖于特定条件的判断结果,比如JE JNE指令,一般都是if/else语句,无条件跳转是JMP指令 他会跳转到某个代码块,

例如实现无线循环或跳到函数入口地址。

首先我们来简单看一下无条件跳转,无条件跳转是一种直接跳转指令,当执行到该指令时,程序总时跳转到指定的内存地址执行,无需任何条件。

它的实现方式其实就是通过修改指令指针或程序计数器来强制改变程序的执行流,无条件跳转指令是JMP指令,JMP指令告诉CPU跳转到指定的内存地址,并从该地址开始执行。

类似于C语言中的goto语句,Jmp指令语法如下: jmp <jump_Address> 这里的<jump_Address>是跳转的目标内存地址,可以是绝对地址也可以是相对地址。

恶意软件分析-汇编基础

条件跳转和无条件跳转不同,条件跳转指令是需要根据条件将程序的控制权转移到指定的内存地址,所以条件跳转是需要依赖于标志位(Flags)的,这些标志位的值会在前面的运算或

比较指令中被设置或清除,条件跳转通过检查 CPU 的标志寄存器(如零标志 ZF、进位标志 CF)决定是否跳转。标志位一般是由前一条运行或比较指令修改。

CMP指令用于比较两个操作数,他的作用类似于减法运算,但是不会存储结果,只会根据比较的结果设置标志位。CMP destination, source 相当于 destination - source,但不会改变操作数的值。这里我们举一个例子:

cmp eax,5 这里假设eax寄存器中的值为5,那么5-5 = 0,设置零标志位ZF被设置为1,因为结果是0。那么条件跳转指令je会去检查零标志位(ZF)是否为1,如果ZF为1,则跳转。

恶意软件分析-汇编基础

TEST指令

TEST指令是一种特殊的位操作指令,主要用于对操作数进行按位(AND)运行,并根据结果设置或清除标志寄存器中的标志位,而不存储运算结果。使用如下:

test destination, source

destinationsource 是两个操作数,通常为寄存器或内存地址。执行逻辑:对 destinationsource 执行按位与运算,将结果用于设置标志位。

对于TEST和CMP指令的区别在于,CMP指令执行减法运算,但是不存储结果,而TEST指令执行按位与运算,也不存储结果。TEST指令会影响如下标志位:如果TEST的结果为0,那么ZF标志位设置为1,如果非0,ZF设置为0,如果结果最高位为1,SF设置位1,如果结果最高位为0,SF设置为0。

恶意软件分析-汇编基础

条件跳转指令表如下:

指令 描述 别名 标志位条件
JZ 跳转当结果为零(Jump if Zero) JE(Jump if Equal) ZF = 1
JNZ 跳转当结果不为零(Jump if Not Zero) JNE(Jump if Not Equal) ZF = 0
JL 跳转当结果小于(Jump if Less) JNGE(Jump if Not Greater or Equal) SF ≠ OF
JLE 跳转当结果小于或等于(Jump if Less or Equal) JNG(Jump if Not Greater) ZF = 1 或 SF ≠ OF
JG 跳转当结果大于(Jump if Greater) JNLE(Jump if Not Less or Equal) ZF = 0 且 SF = OF
JGE 跳转当结果大于或等于(Jump if Greater or Equal) JNL(Jump if Not Less) SF = OF
JC 跳转当有进位(Jump if Carry) JB(Jump if Below),JNAE(Jump if Not Above or Equal) CF = 1
JNC 跳转当无进位(Jump if Not Carry) JNB(Jump if Not Below),JAE(Jump if Above or Equal) CF = 0

指令 描述 别名 标志位条件
JZ 跳转当结果为零(Jump if Zero) JE(Jump if Equal) ZF = 1
JNZ 跳转当结果不为零(Jump if Not Zero) JNE(Jump if Not Equal) ZF = 0
JL 跳转当结果小于(Jump if Less) JNGE(Jump if Not Greater or Equal) SF ≠ OF
JLE 跳转当结果小于或等于(Jump if Less or Equal) JNG(Jump if Not Greater) ZF = 1 或 SF ≠ OF
JG 跳转当结果大于(Jump if Greater) JNLE(Jump if Not Less or Equal) ZF = 0 且 SF = OF
JGE 跳转当结果大于或等于(Jump if Greater or Equal) JNL(Jump if Not Less) SF = OF
JC 跳转当有进位(Jump if Carry) JB(Jump if Below),JNAE(Jump if Not Above or Equal) CF = 1
JNC 跳转当无进位(Jump if Not Carry) JNB(Jump if Not Below),JAE(Jump if Above or Equal) CF = 0

感谢您的观看,期待和您的下次相遇!!!!

原文始发于微信公众号(Relay学安全):恶意软件分析-汇编基础

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年12月2日22:43:53
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   恶意软件分析-汇编基础http://cn-sec.com/archives/3460113.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息