汇编语言

学习汇编的意义

  1. 开发时调试
  2. 逆向时候的代码阅读
  3. 某些特殊技术的使用(如shellcode、壳)

shellcode:可以运行在任意位置的代码(汇编语言)

壳:加壳或脱壳都需要用的汇编语言

环境配置

  • Ollydbg

  • Visual Studio 2015

16位/32位/64位汇编的区别

区别

16位:实模式,16位处理器内的内部,最多可以处理存储的长度为16位。

32位:保护模式,32位处理器内的内部,最多可以处理存储的长度为32位。

64位:保护模式,64位处理器内的内部,最多可以处理存储的长度为64位。

通用寄存器简介

位数通用寄存器扩展
16AX BX CX DX SI DI BP SPR8W R9W R10W R11W R12W R13W R14W R15W
32EAX EBX ECX EDX ESI EDI EBP ESPR8D R9D R10D R11D R12D R13D R14D R15D
64RAX RBX RCX RDX RSI RDI RBP RSPR8 R9 R10 R11 R12 R13 R14 R15

基本执行环境

graph LR A[32];B[64] A --->a1[8个32位通用寄存器] A --->a2[标志寄存器EFLAGS] A --->a3[指令指针寄存器EIP] B --->b1[16个64位通用寄存器] B --->b2[标志寄存器RFLAGS] B --->b3[指令指针寄存器RIP]

EFLAGS寄存器

Eflags寄存器,Eflags寄存器包含了独立的二进制位,用于控制CPU操作。或是反应一些CPU操作的结果。有些指令可以测试和控制这些单独的处理器标志位。

MMX寄存器

在实现高级多媒体和通信应用时,MMX技术提高了Intel处理器的性能。8个64位MMX寄存器支持成为SIMD的特殊指令。顾名思义,MMX指令对MMX寄存器中的数据值直接进行并行操作。虽然它们看上去是独立的寄存器,但是MMX寄存器实际上是浮点单元中使用的同样寄存器的别名。

通用寄存器

eax:累加器,操作数和结果数据累加器,返回值运算结果一般都存储在这里

image20210811183106370.png

ebx:基地址,DS段的数据指针,在内存寻址的时候存放基地址

image20210811183206737.png

ecx:计数器,字符串和循环操作的计数器

image20210811183244169.png

edx:用于存储部分乘法结果和部分除法被除数

image20210811183411998.png

ebp:基址指针,SS段的数据指针

image20210811183548209.png

esp:栈帧指针,一般指向栈顶,所以也被称为栈顶指针

image20210811183809151.png

edi:字符串操作的目标指针,ES段的数据指针

image20210811183910749.png

esi:字符串操作的源指针,SS段的数据指针

image20210811184031993.png

冯诺依曼

计算机科学的奠基者

  • 艾伦·麦锡森·图灵 - - - 图灵机
  • 约翰·冯·诺依曼 - - - 数据存储的体系结构

约翰·冯·诺依曼

1903年 出生犹太家庭

1926年 布达佩斯大学数学博士学位

1930年 接受了普林斯顿大学客座教授的职位

1931年 普林斯顿大学终身教授

1933年 普林斯顿高等研究院

1937年 美国公民

1938年 获博修奖

1954年 美国原子能委员会委员

1957 在华盛顿德里医院去世

冯诺依曼体系

计算机由控制器、运算器、存储器、输入设备、输出设备五部分组成。

冯诺依曼提出的计算机体系结构,奠定了现代计算机的结构理念

image20210811190118360.png

内存基础

什么是内存

在冯诺依曼结构中用来存储程序和数据的部件叫做存储器,我们的计算机可以正常的运行,主要依靠的就是存储器的记忆能力。存储器分为主存储器和辅助存储器,主存储器也叫内存储器,也就是我们常说的内存

内存寻址范围

现在主流的系统是32位系统和64位系统

32位系统内存的寻址范围是0x00000000-0xFFFFFFFF

32位系统内存最大寻址范围是0xFFFFFFFF+1(4294967296) - - - 4GB

64位内存的寻址范围是0x0000000000000000-0xFFFFFFFFFFFFFFFF

image20210811191257593.png

内存和寄存器的区别

寄存器:数量少,在CPU内部,速度极快,但是价格昂贵

内存:数量庞大,相对寄存器而言,速度较慢,但是价格便宜

内存的五种表现形式

立即数:

MOV EAX, DWORD PTR DS:[0x???????]

寄存器:

MOV EBX, 0x????????
MOV EAX, DWORD PTR DS:[EBX]

寄存器+立即数

MOV EBX, 0x???????
MOV EAX, DWORD PTR DS:[EBX+4]

比例因子:[REG+REG*{1,2,4,8}]

数组元素地址=数组首地址+元素索引*数组元素占用空间

MOV EAX, 0x????????
MOV EBX, 0x2
MOV ECX, DWORD PTR DS:[EAX+EBX*4]

比例因子+立刻数:

MOV EAX, 0x????????
MOV EBX, 0x2
MOV ECX, DWORD PTR DS:[EAX+EBX*4+1]

数据存储模式

大端序:数据高位在内存低位,数据低位在内存高位

小端序:数据高位在内存高位,数据低位在内存低位

地址0x77 66 55 44

大端序:念的时候是77 66 55 44

小端序:念的时候是44 55 66 77

大端序常用于ARM架构

小端序常用于x86、AMD64架构

EFLAGS寄存器

CF:进位借位标志位

PF:奇偶标志位

AF:辅助进位标志位

ZF:0标志位

SF:符号标志位

TF:单目标志位

IF:中断标志位

DF:方向标志位

OF:溢出标志位

数学运算

加法

加法指令 ADD(Addition)

格式:ADD OPRD1, OPRD2

功能:两数相加

加法指令运算的结果对CF、SF、OF、PF、ZF、AF都会有影响

不允许OPRD1与OPRD2同时为存储器


带进位加法指令 ADC(Addition Carry)

格式:ADC OPRD1, OPRD2

功能:OPRD1 = OPRD1 + OPRD2 + CF

减法

减法指令 SUB(Subtract)

格式:SUB OPRD1, OPRD2

功能:两个操作数的相减,即从OPRD1中减去OPRD2,其结果放在OPRD1中。指令的类型及对标志位的影响与ADD指令相同,注意立即数不能用于目的操作数,两个存储器操作数之间不能直接相减,操作数可为8位或16位的无符号数或带符号数。


带借位减法指令 SBB(Subtraction with Borrow)

格式:SBB OPRD1, OPRD2

功能:进行两个操作数的相减再减去CF进位标志位,即从OPRD1 = OPRD1 - OPRD2 -CF,其结果放在OPDR1中。

乘法

无符号数乘法指令 MUL(Multiply)

格式:MUL OPRD


带符号数乘法指令 IMUL(Integer Multiply)

格式:IMUL OPRD、

功能:乘法操作

OPRD为通用寄存器或寄存器操作数

本指令影响标志位CF及OF

除法

无符号数除法指令 DIV(Division)

格式:DIV OPRD

功能:实现两个无符号二进制数除法运算


带符号数除法指定 IDIV(Integer Division)

格式:IDIV OPRD

功能:这实现两个带符号数的二进制除法运算

16bit,分存2个8bit AH:AL 商AL 余AH

32bit,分存2个16bit DX:AX 商AX 余DX

64bit,分存2个32bit EDX:EAX 商EAX 余EDX

128bit,分存2个64bit RDX:RAX 商RAX 余RDX

自增

加1指令 INC(Increment by 1)

格式:INC OPRD

功能:OPRD = OPRD + 1

自减

减1指令 DEC(Decrement by 1)

格式:DEC OPRD

功能:OPRD = OPRD - 1

逻辑运算

逻辑与运算指令 AND

格式:AND OPRD1, OPRD2

功能:对两个操作数实现按位逻辑与运算,结果送至目的操作数。本指令可以进行字节或字的 ‘与‘ 运算,OPRD1 < - - OPRD1 and OPRD2.

本指令影响标志位PF、SF、ZF,使CF=0、OF=0.例如,在同一个通用寄存器自身相与时, 操作数虽不变,但使CF置零。本指令主要用于修改操作数或置某些位为零。

逻辑或指令 OR

格式:OR OPRD1, OPRD2

功能:OR指令完成对两个操作数按位的 ‘或’ 运算,结果送至目的操作数中,本指令可以进 - - - - 行字节或字的 ‘或’ 运算。OPRD1 < - - OPRD1 OR OPRD2。

异或操作

逻辑异或运算指令 XOR

格式:XOR OPRD1, OPRD2

功能:实现两个操作数按位 ‘异或’ 运算,结果送至目的操作数中。OPRD1 < - - OPRD1 XOR OPRD2

非运算

逻辑操作符 NOT

格式:NOT exp

功能:按位求反

堆栈操作

什么是堆栈

  1. 栈是一个后进先出的存储区域,位于堆栈段中,SS段寄存器描述的就是堆栈段的地址
  2. 栈的数据出口位于栈顶,也就是esp寄存器所指向的位置
  3. 栈顶是低位,也就是地址较小的一侧,由ebp寄存器指向的栈底,并不会改变

栈操作指令

PUSH:压栈操作,32位汇编首先ESP-4,留出一个空间,然后把要压入栈中的内容压入

POP:出栈指令,32位汇编首先将栈顶的数据弹出给指定的目标,然后ESP+4,清掉空间

栈的作用

  1. 存储少量数据
  2. 保存寄存器环境
  3. 传递参数

数据移动指令

MOV指令

数据传送指令MOV

格式:MOV OPRD1, OPRD2

功能:本指令将一个源操作数送到目的操作数中,即OPRD1 < - - OPRD2

说明:

  • OPRD1为目的操作数,可以是寄存器、存储器、累加器
  • OPRD2为源操作数,可以是寄存器、存储器、累加器和立即数

LEA指令

有效地址传送指令 LEA

格式:LEA OPRD1,OPRD2

功能:将源操作数给出的有效地址传送到指定的寄存器中

OPRD1必须是寄存器

XCHG指令

数据交换指令 XCHG

格式:XCHG OPRD1, OPRD2 其中的OPRD1为目的操作数,OPRD2为源操作数

功能:将两个操作数相互交换位置,该指令把源操作数OPRD2与目的操作数OPRD1交换

比较指令

CMP指令

比较指令 CMP(Compare)

格式:CMP OPRD1, OPRD2

功能:对两数进行相减,进行比较

TEST指令

测试指令 TEST

格式:TEST OPRD1,OPRD2

功能:其中OPRD1、OPRD2的含义同AND指令一样,也是对两个操作数进行按位的 ‘与’ 运算,- - - - 唯一不同之处是不将 ‘与’ 的结果送目的操作数,即本指令对两个操作数的内容均不进行修改,仅是在逻辑与操作后,对标志位重新置位

JCC条件转移指令

常用的JCC指令

JMP:无条件跳转

JZ/JE:ZF = 1 等于0或相等跳转

JNZ/JNE:ZF = 0 不等于0或者不相等跳转

JBE/JNA:CF = 1/ZF = 1 低于等于/不高于跳转

JNBE/JA:CF = 0/ ZF = 0 不低于等于/高于跳转

JL/JNGE:SF!=OF 小于/不大于等于跳转

JNL/JGE:SF = OF 不小于/大于等于跳转

JCC表

JCC指令中文含义英文原意检查符号位典型C应用
JZ/JE若为0则跳转;若相等则跳转jump if zero;jump if equalZF=1if (i == j);if (i == 0);
JNZ/JNE若不为0则跳转;若不相等则跳转jump if not zero;jump if not equalZF=0if (i != j);if (i != 0);
JS若为负则跳转jump if signSF=1if (i < 0);
JNS若为正则跳转jump if not signSF=0if (i > 0);
JP/JPE若1出现次数为偶数则跳转jump if Parity (Even)PF=1(null)
JNP/JPO若1出现次数为奇数则跳转jump if not parity (odd)PF=0(null)
JO若溢出则跳转jump if overflowOF=1(null)
JNO若无溢出则跳转jump if not overflowOF=0(null)
JC/JB/JNAE若进位则跳转;若低于则跳转;若不高于等于则跳转jump if carry;jump if below;jump if not above equalCF=1if (i < j);
JNC/JNB/JAE若无进位则跳转;若不低于则跳转;若高于等于则跳转;jump if not carry;jump if not below;jump if above equalCF=0if (i >= j);
JBE/JNA若低于等于则跳转;若不高于则跳转jump if below equal;jump if not aboveZF=1或CF=1if (i <= j);
JNBE/JA若不低于等于则跳转;若高于则跳转jump if not below equal;jump if aboveZF=0或CF=0if (i > j);
JL/JNGE若小于则跳转;若不大于等于则跳转jump if less;jump if not greater equalSF != OFif (si < sj);
JNL/JGE若不小于则跳转;若大于等于则跳转;jump if not less;jump if greater equalSF = OFif (si >= sj);
JLE/JNG若小于等于则跳转;若不大于则跳转jump if less equal;jump if not greaterZF != OF 或 ZF=1if (si <= sj);
JNLE/JG若不小于等于则跳转;若大于则跳转jump if not less equal;jump if greaterSF=0F 且 ZF=0if(si>sj)

串操作指令

MOVS指令

字符串传送指令 MOVS

格式:MOVS OPRD1, OPRD2 MOVSB MOVSW

功能:OPRD1 < - - OPRD2

说明:

  1. 其中OPRD2为源串符号地址,OPRD1为目的串符号地址

STOS指令

字符串存储指令 STOS

格式:STOS OPRD

功能:把AL(字节)或AX(字)中的数据存储到DI为目的串地址指针所寻址的存储器单元中去指针DI将根据DF的值进行自动调整

REP指令

重复前缀说明

格式:

  • REP ;CX<>0 重复执行字符串指令
  • REPZ/REPE ;CX<>0 且ZF=1重复执行字符串指令
  • REPNZ/REPNE ;CX<>0 且ZF=0重复执行字符串指令

功能:在串操作指令前加上重复前缀,可以对字符串进行重复处理。由于加上重复前缀后,对应的指令代码是不同的,所以指令的功能便具有重复处理的功能,重复的次数存放在CX寄存器中

CALL与RETN

CALL指令

过程调用指令 CALL

格式:CALL OPRD

功能:过程调用指令

相当于:

push eip
jmp OPRD

RETN指令

​ 返回指令,相当于:

pop eip
jmp eip

函数

过程调用-函数

function proc
	code
function end

参数传递方式:

  1. 寄存器传参
  2. 堆栈传参

WIN32汇编入门

什么是API?

API(Application Programming Interface, 应用程序接口)是一些预先定义的函数,或指软件系统不同组成部分衔接的约定。目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问原码,或理解内部工作机制的细节

Windows系统除了协调应用程序的执行、内存的分配、系统资源的管理外,同时他也是一个很大的服务中心。调用这个服务中心的各种服务(每一种服务就是一个函数)可以帮助应用程序达到开启视窗、描绘图形和使用周边设备等目的,由于这些函数服务的对象是应用程序,所以称之为Application Programming Interface, 简称API函数。WIN32 API也就是Microsoft Windows 32位平台的应用程序编程接口

凡是在 Windows 工作环境底下执行的应用程序,都可以调用Windows API

Q.E.D.