恶意代码汇编基础_第1页
恶意代码汇编基础_第2页
恶意代码汇编基础_第3页
恶意代码汇编基础_第4页
恶意代码汇编基础_第5页
已阅读5页,还剩37页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

恶意代码汇编基础2023/3/202汇编基础汇编是逆向工程的基础;汇编语言是一切程序的起点和终点,毕竟所有的高级语言都是建立在汇编基础之上的。在许多高级语言中我们都需要相对明确的语法,但是在汇编中,我们会使用一些单词缩写和数字来表达程序。2023/3/203I.单元、位和字节BIT(位)

-

电脑数据量的最小单元,可以是0或者1。例:00000001

=

1;00000010

=

2;00000011

=

3

·BYTE(字节)

-

一个字节包含8个位,所以一个字节最大值是255(0-255)。为了方便阅读,我们通常使用16进制来表示。

·WORD(字)

-

一个字由两个字节组成,共有16位。一个字的最大值是0FFFFh

(或者是

65535d)

(h代表16进制,d代表10进制)。·DOUBLE

WORD(双字DWORD)

-

一个双字包含两个字,共有32位。最大值为0FFFFFFFF

(或者是

4294967295d)。·KILOBYTE(千字)

-

千字节并不是1000个字节,而是1024

(32*32)

个字节。·MEGABYTE

-

兆字节同样也不是一兆个字节,而是1024*1024=1,048,576

个字节2023/3/204II.寄存器寄存器是计算机储存数据的“特别地方”。你可以把寄存器看作一个小盒子,我们可以在里面放很多东西:比如名字、数字、一段话……如今Win+IntelCPU组成的计算机通常有9个32位寄存器(w/o标志寄存器)。它们是:EAX:

累加器EBX:

基址寄存器ECX:

计数器EDX:

数据寄存器ESI:

源变址寄存器EDI:

目的变址寄存器EBP:

扩展基址指针寄存器ESP:

栈指针寄存器EIP:

指令指针寄存器2023/3/205通常来说寄存器大小都是32位(四个字节)。它们可以储存值为从0-FFFFFFFF(无符号)的数据。起初大部分寄存器的名字都暗示了它们的功能,比如ECX=计数,但是现在你可以使用任意寄存器进行计数(只有在一些自定义的部分,计数才必须用到ECX)。当我用到EAX、EBX、ECX、EDX、ESI和EDI这些寄存器时我才会详细解释其功能,所以我们先讲EBP、ESP、EIP。2023/3/206EBP:

EBP在栈中运用最广,刚开始没有什么需要特别注意的

;)

ESP:

ESP指向栈区域的栈顶位置。栈是一个存放即将会被用到的数据的地方,你可以去搜索一下push/pop

指令了解更多栈知识。

EIP:

EIP指向下一个将会被执行的指令。2023/3/207寄存器的类型还有一件值得注意的事:有一些寄存器是16位甚至8位的,它们是不能直接寻址的。2023/3/20832位寄存器通常一个寄存器可以这样看:由图可知,EAX是这个32位寄存器的名字,EAX的低16位部分被称作AX,AX又分为高8位的AH和低8位的AL两个独立寄存器。2023/3/209i.单字节寄存器顾名思义,这些寄存器都是一个字节(8位)AL

and

AHBL

and

BHCL

and

CHDL

and

DH2023/3/2010ii.单字(16位)寄存器:这些寄存器大小为一个字(=2字节=16位)。一个单字寄存器包含两个单字节寄存器。我们通常根据它们的功能来区分它们。1通用寄存器

AX

(单字=16位)

=

AH

+

AL

->

其中‘+’号并不代表把它们代数相加。AH和AL寄存器是相互独立的,只不过都是AX寄存器的一部分,所以你改变AH或AL

(或者都改变)

,AX寄存器也会被改变。

->

'accumulator'(累加器):用于进行数学运算BX

->

'base'(基址寄存器):用来连接栈(之后会说明)CX

->

'counter'(计数器):DX

->

'data'(数据寄存器):大多数情况下用来存放数据DI

->

'destination

index'(目的变址寄存器):

例如将一个字符串拷贝到DISI

->

'source

index'(源变址寄存器):

例如将一个字符串从SI拷贝2023/3/20112.索引寄存器(指针寄存器):

BP

->

'base

pointer'(基址指针寄存器):表示栈区域的基地址SP

->

'stack

pointer'(栈指针寄存器):表示栈区域的栈顶地址2023/3/20123.段寄存器:CS

->

'code

segment'(代码段寄存器):用于存放应用程序代码所在段的段基址(之后会说明)DS

->

'data

segment'(数据段寄存器):用于存放数据段的段基址(以后会说明)ES

->

'extra

segment'(附加段寄存器):用于存放程序使用的附加数据段的基地址SS

->

'stack

segment'(栈段寄存器):用于存放栈段的段基址(以后会说明)2023/3/20134.指令指针寄存器:IP

->

'instruction

pointer'(指令指针寄存器):指向下一个指令

;)2023/3/2014iii.双字(32位)寄存器:2字=4字节=32位,EAX、EBX、ECX、EDX、EDI……

如果16位寄存器前面加了‘E’,就代表它们是32位寄存器。例如,AX=16位,EAX=32位。2023/3/2015III.标志寄存器标志寄存器代表某种状态。在32位CPU中有32个不同的标志寄存器,不过不用担心,我们只关心其中的3个:ZF、OF、CF。在逆向工程中,了解了标志寄存器就能知道程序在这一步是否会跳转,标志寄存器就是一个标志,只能是0或者1,它们决定了是否要执行某个指令。Z-Flag(零标志):ZF是破解中用得最多的寄存器(通常情况下占了90%),它可以设成0或者1。若上一个运算结果为0,则其值为1,否则其值为0。TheO-Flag(溢出标志):OF寄存器在逆向工程中大概占了4%,当上一步操作改变了某寄存器的最高有效位时,OF寄存器会被设置成1。例如:EAX的值为7FFFFFFFF,如果你此时再给EAX加1,OF寄存器就会被设置成1,因为此时EAX寄存器的最高有效位改变了(你可以使用电脑自带计算器将这个16进制转化成2进制看看)。还有当上一步操作产生溢出时(即算术运算超出了有符号数的表示范围),OF寄存器也会被设置成1。

TheC-Flag(进位标志):进位寄存器的使用大概占了1%,如果产生了溢出,就会被设置成1。例,假如某寄存器值为FFFFFFFF,再加上1就会产生溢出,你可以用电脑自带的计算器尝试。

2023/3/2016IV.段偏移

内存中的一个段储存了指令(CS)、数据(DS)、堆栈(SS)或者其他段(ES)。每个段都有一个偏移量,在32位应用程序下,这些偏移量由00000000到FFFFFFFF。段和偏移量的标准形式如下:段:偏移量

=

把它们放在一起就是内存中一个具体的地址。可以这样看:

一个段是一本书的某一页:偏移量是一页的某一行

2023/3/2017V.栈栈是内存里可以存放稍后会用到的东西的地方。可以把它看作一个箱子里的一摞书,最后一本放进去的永远是最先出来的。或者把栈看作一个放纸的盒子,盒子是栈,而每一张纸就代表了一个内存地址。总之记住这个规则:最后放的纸最先被拿出来。’push’命令就是向栈中压入数据,‘pop’命令就是从栈中取出最后放入的数据并且把它存进具体的寄存器中。2023/3/2018VI.指令(字母表排序)

请注意,所有的值通常是以16进制形式储存的。大部分指令有两个操作符(例如:addEAX,EBX),有些是一个操作符(例如:notEAX),还有一些是三个操作符(例如:IMULEAX、EDX、64)。如果你使用“DWORDPTR[XXX]”就表示使用了内存中偏移量为[XXX]的的数据。注意:字节在内存中储存方式是倒过来的(Win+Intel的电脑上大部分采用”小端法”,WORDPTR[XXX](双字节)和BYTEPTR[XXX](单字节)也都遵循这一规定)。2023/3/2019大部分有两个操作符的指令都是以下这些形式(以add指令举例):2023/3/2020ADD(加)语法:ADD被加数,加数加法指令将一个数值加在一个寄存器上或者一个内存地址上。

addeax,123=eax=eax+123;

加法指令对ZF、OF、CF都会有影响。

AND(逻辑与)

语法:AND目标数,原数

AND运算对两个数进行逻辑与运算。

AND指令会清空OF,CF标记,设置ZF标记。2023/3/2021例如:1001010110

0101001101如果对它们进行AND运算,结果是0001000100

即同真为真(1),否则为假(0),你可以用计算器验证。2023/3/2022CALL(调用)语法:CALLsomethingCALL指令将当前的相对地址(IP)压入栈中,并且调用CALL后的子程序CALL可以这样使用:

CALL

404000

;;

最常见:

CALL

地址

CALL

EAX

;;

CALL

寄存器

-

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

CALL

DWORD

PTR

[EAX]

;;

CALL

[EAX]偏移量所指向的地址

CALL

DWORD

PTR

[EAX+5]

;;

CALL

[EAX+5]偏移量所指向的地址

2023/3/2023CDQ

Syntax:CDQCDQ指令第一次出现时通常不好理解。它通常出现在除法前面,作用是将EDX的所有位变成EAX最高位的值,

比如当EAX>=80000000h时,其二进制最高位为1,则EDX被32位全赋值为1,即FFFFFFFF若EAX<80000000,则其二进制最高位为0,EDX为。然后将EDX:EAX组成新数(64位):FFFFFFFF800000002023/3/2024CMP(比较)

语法:CMP目标数,原数CMP指令比较两个值并且标记CF、OF、ZF:2023/3/2025CMP

EAX,

EBX

;;

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

CMP

EAX,[404000]

;;

比较eax和偏移量为[404000]的值是否相等

CMP

[404000],EAX

;;

比较[404000]是否与eax相等

2023/3/2026DEC(自减)

语法:DECsomethingdec用来自减1,相当于c中的–

dec可以有以下使用方式:

2023/3/2027dec

eax

;;

eax自减1

dec

[eax]

;;

偏移量为eax的值自减1

dec

[401000]

;;

偏移量为401000的值自减1

dec

[eax+401000]

;;

偏移量为eax+401000的值自减1dec指令可以标记ZF、OF

2023/3/2028DIV(除)

语法:DIV除数DIV指令用来将EAX除以除数(无符号除法),被除数通常是EAX,结果也储存在EAX中,而被除数对除数取的模存在除数中。

例:

mov

eax,64

;;

EAX

=

64h

=

100

mov

ecx,9

;;

ECX

=

9

div

ecx

;;

EAX除以ECX

2023/3/2029在除法之后EAX=100/9=0B(十进制:11)并且ECX=100MOD9=1div指令可以标记CF、OF、ZF2023/3/2030IDIV(整除)语法:IDIV除数IDIV执行方式同div一样,不过IDIV是有符号的除法

idiv指令可以标记CF、OC、ZFIMUL(整乘)

语法:IMUL数值IMUL目标寄存器、数值、数值IMUL目标寄存器、数值IMUL指令可以把让EAX乘上一个数(INUL数值)或者让两个数值相乘并把乘积放在目标寄存器中(IMUL目标寄存器,数值,数值)或者将目标寄存器乘上某数值(IMUL目标寄存器,数值)

如果乘积太大目标寄存器装不下,那OF、CF都会被标记,ZF也会被标记

2023/3/2031INC(自加)

语法:INCsomethingINC同DEC相反,它是将值加1

INC指令可以标记ZF、OFINT

语法:int目标数INT的目标数必须是产生一个整数(例如:int21h),类似于call调用函数,INT指令是调用程序对硬件控制,不同的值对应着不同的功能。

2023/3/2032JUMPS

这些都是最重要的跳转指令和触发条件(重要用*标记,最重要用**标记):指令

条件

条件

JA*

-

如果大于就跳转(无符号)

-

CF=0

and

ZF=0

JAE

-

如果大于或等于就跳转(无符号)-

CF=0

JB*

-

如果小于就跳转(无符号)

-

CF=1

JBE

-

如果小于或等于就跳转(无符号)-

CF=1

or

ZF=1

JC

-

如果CF被标记就了跳转

-

CF=1

JCXZ

-

如果CX等于0就跳转

-

CX=0

JE**

-

如果相等就跳转

-

ZF=1

JECXZ

-

如果ECX等于0就跳转

-

ECX=0

JG*

-

如果大于就跳转(有符号)

-

ZF=0

and

SF=OF

(SF

=

Sign

Flag)

JGE*

-

如果大于或等于就跳转(有符号)

-

SF=OF

JL*

-

如果小于就跳转(有符号)

-

SF

!=

OF

(!=

is

not)

JLE*

-

如果小于或等于就跳转(有符号

-

ZF=1

and

OF

!=

OF

JMP**

-

跳转

-

强制跳转

2023/3/2033JNA

-

如果不大于就跳转(无符号)

-

CF=1

or

ZF=1

JNAE

-

如果不大于等于就跳转(无符号)

-

CF=1

JNB

-

如果不小于就跳转(无符号)

-

CF=0

JNBE

-

如果不小于等于就跳转(无符号)

-

CF=0

and

ZF=0

JNC

-

如果CF未被标记就跳转

-

CF=0

JNE**

-

如果不等于就跳转

-

ZF=0

JNG

-

如果不大于就跳转(有符号)

-

ZF=1

or

SF!=OF

JNGE

-

如果不大于等于就跳转(有符号)

-

SF!=OF

JNL

-

如果不小于就跳转(有符号)

-

SF=OF

JNLE

-

如果不小于等于就跳转(有符号)

-

ZF=0

and

SF=OF

JNO

-

如果OF未被标记就跳转

-

OF=0

JNP

-

如果PF未被标记就跳转

-

PF=0

JNS

-

如果SF未被标记就跳转

-

SF=0

JNZ

-

如果不等于0就跳转

-

ZF=0

JO

-

如果OF被标记就跳转

-

OF=1

JP

-

如果PF被标记就跳转

-

PF=1

JPE

-

如果是偶数就跳转

-

PF=1

JPO

-

如果是奇数就跳转

-

PF=0

JS

-

如果SF被标记就跳转

-

SF=1

JZ

-

如果等于0就跳转

-

ZF=1

2023/3/2034LEA(有效地址传送)

语法:LEA目的数、源数LEA可以看成和MOV差不多的指令LEA,它本身的功能并没有被太广泛的使用,反而广泛运用在快速乘法中:

leaeax,dwordptr[4*ecx+ebx]

将eax赋值为4*ecx+ebx2023/3/2035MOV(传送)

语法:MOV目的数,源数这是一个很简单的指令,MOV指令将源数赋值给目的数,并且源数值保持不变

这里有一些MOV的变形:

MOVS/MOVSB/MOVSW/MOVSDEDI,ESI:这些变形能将ESI指向的内容传送到EDI指向的内容中去

MOVSX:MOVSX指令将单字或者单字节扩展为双字或者双字节传送,原符号不变

MOVZX:MOVZX扩展单字节或单字为双字节或双字并且用0填充剩

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论