第2324讲恶意代码-汇编基础.ppt

上传人:本田雅阁 文档编号:3128219 上传时间:2019-07-14 格式:PPT 页数:44 大小:826.52KB
返回 下载 相关 举报
第2324讲恶意代码-汇编基础.ppt_第1页
第1页 / 共44页
第2324讲恶意代码-汇编基础.ppt_第2页
第2页 / 共44页
第2324讲恶意代码-汇编基础.ppt_第3页
第3页 / 共44页
第2324讲恶意代码-汇编基础.ppt_第4页
第4页 / 共44页
第2324讲恶意代码-汇编基础.ppt_第5页
第5页 / 共44页
点击查看更多>>
资源描述

《第2324讲恶意代码-汇编基础.ppt》由会员分享,可在线阅读,更多相关《第2324讲恶意代码-汇编基础.ppt(44页珍藏版)》请在三一文库上搜索。

1、第23&24讲 恶意代码-汇编基础,答疑地点:12J810|12J806 网络答疑:QQ:252175436 答疑时间:周三上午9:30-11:00,2019/7/14,2,汇编基础,汇编是逆向工程的基础; 汇编语言是一切程序的起点和终点,毕竟所有的高级语言都是建立在汇编基础之上的。 在许多高级语言中我们都需要相对明确的语法,但是在汇编中,我们会使用一些单词缩写和数字来表达程序。,2019/7/14,3,I. 单元、位和字节,BIT(位) - 电脑数据量的最小单元,可以是0或者1。 例:00000001 = 1;00000010 = 2;00000011 = 3 BYTE(字节) - 一个字节

2、包含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 个字节,2019

3、/7/14,4,II. 寄存器,2019/7/14,5,寄存器是计算机储存数据的“特别地方”。你可以把寄存器看作一个小盒子,我们可以在里面放很多东西:比如名字、数字、一段话 如今Win+Intel CPU组成的计算机通常有9个32位寄存器 (w/o 标志寄存器)。它们是: EAX: 累加器 EBX: 基址寄存器 ECX: 计数器 EDX: 数据寄存器 ESI: 源变址寄存器 EDI: 目的变址寄存器 EBP: 扩展基址指针寄存器 ESP: 栈指针寄存器 EIP: 指令指针寄存器,通常来说寄存器大小都是32位 (四个字节) 。它们可以储存值为从0-FFFFFFFF (无符号)的数据。起初大部分寄

4、存器的名字都暗示了它们的功能,比如ECX=计数,但是现在你可以使用任意寄存器进行计数 (只有在一些自定义的部分,计数才必须用到ECX)。当我用到EAX、EBX、ECX、EDX、ESI和EDI这些寄存器时我才会详细解释其功能,所以我们先讲EBP、ESP、EIP。,2019/7/14,6,EBP: EBP在栈中运用最广,刚开始没有什么需要特别注意的 ;) ESP: ESP指向栈区域的栈顶位置。栈是一个存放即将会被用到的数据的地方,你可以去搜索一下push/pop 指令了解更多栈知识。 EIP: EIP指向下一个将会被执行的指令。,2019/7/14,7,寄存器的类型,还有一件值得注意的事:有一些寄

5、存器是16位甚至8位的,它们是不能直接寻址的。,2019/7/14,8,32位寄存器,通常一个寄存器可以这样看: 由图可知,EAX是这个32位寄存器的名字,EAX的低16位部分被称作AX,AX又分为高8位的AH和低8位的AL两个独立寄存器。,2019/7/14,9,i. 单字节寄存器,顾名思义,这些寄存器都是一个字节 (8位) AL and AH BL and BH CL and CH DL and DH,2019/7/14,10,ii. 单字(16位)寄存器:,这些寄存器大小为一个字 (=2 字节 = 16 位)。一个单字寄存器包含两个单字节寄存器。我们通常根据它们的功能来区分它们。 1 通

6、用寄存器 AX (单字=16位) = AH + AL - 其中+号并不代表把它们代数相加。AH和AL寄存器是相互独立的,只不过都是AX寄存器的一部分,所以你改变AH或AL (或者都改变) ,AX寄存器也会被改变。 - accumulator(累加器):用于进行数学运算 BX - base(基址寄存器):用来连接栈(之后会说明) CX - counter(计数器): DX - data(数据寄存器):大多数情况下用来存放数据 DI - destination index(目的变址寄存器): 例如将一个字符串拷贝到DI SI - source index(源变址寄存器): 例如将一个字符串从SI拷

7、贝,2019/7/14,11,2. 索引寄存器(指针寄存器): BP - base pointer(基址指针寄存器):表示栈区域的基地址 SP - stack pointer(栈指针寄存器):表示栈区域的栈顶地址,2019/7/14,12,3. 段寄存器: CS - code segment(代码段寄存器):用于存放应用程序代码所在段的段基址(之后会说明) DS - data segment(数据段寄存器):用于存放数据段的段基址(以后会说明) ES - extra segment(附加段寄存器):用于存放程序使用的附加数据段的基地址 SS - stack segment(栈段寄存器):用于存

8、放栈段的段基址(以后会说明),2019/7/14,13,4. 指令指针寄存器: IP - instruction pointer(指令指针寄存器):指向下一个指令 ;),2019/7/14,14,iii. 双字(32位)寄存器:,2 字= 4 字节= 32 位, EAX、EBX、ECX、EDX、EDI 如果16位寄存器前面加了E,就代表它们是32位寄存器。例如,AX=16位,EAX=32位。,2019/7/14,15,III. 标志寄存器,标志寄存器代表某种状态。在32位CPU中有32个不同的标志寄存器,不过不用担心,我们只关心其中的3个:ZF、OF、CF。在逆向工程中,了解了标志寄存器就能知

9、道程序在这一步是否会跳转,标志寄存器就是一个标志,只能是0或者1,它们决定了是否要执行某个指令。 Z-Flag(零标志): ZF是破解中用得最多的寄存器(通常情况下占了90%),它可以设成0或者1。若上一个运算结果为0,则其值为1,否则其值为0。 The O-Flag(溢出标志): OF寄存器在逆向工程中大概占了4%,当上一步操作改变了某寄存器的最高有效位时,OF寄存器会被设置成1。例如:EAX的值为7FFFFFFFF,如果你此时再给EAX加1,OF寄存器就会被设置成1,因为此时EAX寄存器的最高有效位改变了(你可以使用电脑自带计算器将这个16进制转化成2进制看看)。还有当上一步操作产生溢出时

10、(即算术运算超出了有符号数的表示范围),OF寄存器也会被设置成1。 The C-Flag(进位标志): 进位寄存器的使用大概占了1%,如果产生了溢出,就会被设置成1。例,假如某寄存器值为FFFFFFFF,再加上1就会产生溢出,你可以用电脑自带的计算器尝试。,2019/7/14,16,IV. 段偏移,内存中的一个段储存了指令(CS)、数据(DS)、堆栈(SS)或者其他段(ES)。每个段都有一个偏移量,在32位应用程序下,这些偏移量由 00000000 到 FFFFFFFF。段和偏移量的标准形式如下: 段:偏移量 = 把它们放在一起就是内存中一个具体的地址。 可以这样看: 一个段是一本书的某一页:

11、偏移量是一页的某一行,2019/7/14,17,V. 栈,栈是内存里可以存放稍后会用到的东西的地方。 可以把它看作一个箱子里的一摞书,最后一本放进去的永远是最先出来的。 或者把栈看作一个放纸的盒子,盒子是栈,而每一张纸就代表了一个内存地址。 总之记住这个规则:最后放的纸最先被拿出来。 push命令就是向栈中压入数据, pop命令就是从栈中取出最后放入的数据并且把它存进具体的寄存器中。,2019/7/14,18,VI. 指令 (字母表排序),请注意,所有的值通常是以16进制形式储存的。 大部分指令有两个操作符 (例如:add EAX, EBX),有些是一个操作符 (例如:not EAX),还有一

12、些是三个操作符 (例如:IMUL EAX、EDX、64)。 如果你使用 “DWORD PTR XXX”就表示使用了内存中偏移量为XXX的的数据。 注意:字节在内存中储存方式是倒过来的(Win+Intel的电脑上大部分采用”小端法”, WORD PTR XXX(双字节)和 BYTE PTR XXX(单字节)也都遵循这一规定)。,2019/7/14,19,大部分有两个操作符的指令都是以下这些形式(以add指令举例):,2019/7/14,20,ADD (加) 语法: ADD 被加数, 加数 加法指令将一个数值加在一个寄存器上或者一个内存地址上。 add eax,123 = eax=eax+123;

13、 加法指令对ZF、OF、CF都会有影响。 AND (逻辑与) 语法: AND 目标数, 原数 AND运算对两个数进行逻辑与运算。 AND指令会清空OF,CF标记,设置ZF标记。,2019/7/14,21,例如: 1001010110 0101001101 如果对它们进行AND运算,结果是0001000100 即同真为真(1),否则为假(0),你可以用计算器验证。,2019/7/14,22,CALL (调用) 语法:CALL something CALL指令将当前的相对地址(IP)压入栈中,并且调用CALL 后的子程序 CALL 可以这样使用: CALL 404000 ; 最常见: CALL 地

14、址 CALL EAX ; CALL 寄存器 - 如果寄存器存的值为404000,那就等同于第一种情况 CALL DWORD PTR EAX ; CALL EAX偏移量所指向的地址 CALL DWORD PTR EAX+5 ; CALL EAX+5偏移量所指向的地址,2019/7/14,23,CDQ Syntax: CDQ CDQ指令第一次出现时通常不好理解。它通常出现在除法前面,作用是将EDX的所有位变成EAX最高位的值, 比如当EAX=80000000h时,其二进制最高位为1,则EDX被32位全赋值为1,即FFFFFFFF 若EAX80000000,则其二进制最高位为0,EDX为000000

15、00。 然后将EDX:EAX组成新数(64位):FFFFFFFF 80000000,2019/7/14,24,CMP (比较) 语法: CMP 目标数, 原数 CMP指令比较两个值并且标记CF、OF、ZF:,2019/7/14,25,CMP EAX, EBX ; 比较eax和ebx是否相等,如果相等就设置ZF为1 CMP EAX,404000 ; 比较eax和偏移量为404000的值是否相等 CMP 404000,EAX ; 比较404000是否与eax相等,2019/7/14,26,DEC (自减) 语法: DEC something dec用来自减1,相当于c中的 dec可以有以下使用方式

16、:,2019/7/14,27,dec eax ; eax自减1 dec eax ; 偏移量为eax的值自减1 dec 401000 ; 偏移量为401000的值自减1 dec eax+401000 ; 偏移量为eax+401000的值自减1 dec指令可以标记ZF、OF,2019/7/14,28,DIV (除) 语法: DIV 除数 DIV指令用来将EAX除以除数(无符号除法),被除数通常是EAX,结果也储存在EAX中,而被除数对除数取的模存在除数中。 例: mov eax,64 ; EAX = 64h = 100 mov ecx,9 ; ECX = 9 div ecx ; EAX除以ECX,

17、2019/7/14,29,在除法之后 EAX = 100/9 = 0B(十进制:11) 并且 ECX = 100 MOD 9 = 1 div指令可以标记CF、OF、ZF,2019/7/14,30,IDIV (整除) 语法: IDIV 除数 IDIV执行方式同div一样,不过IDIV是有符号的除法 idiv指令可以标记CF、OC、ZF IMUL (整乘) 语法:IMUL 数值 IMUL 目标寄存器、数值、数值 IMUL 目标寄存器、数值 IMUL指令可以把让EAX乘上一个数(INUL 数值)或者让两个数值相乘并把乘积放在目标寄存器中(IMUL 目标寄存器, 数值,数值)或者将目标寄存器乘上某数值

18、(IMUL 目标寄存器, 数值) 如果乘积太大目标寄存器装不下,那OF、CF都会被标记,ZF也会被标记,2019/7/14,31,INC (自加) 语法: INC something INC同DEC相反,它是将值加1 INC指令可以标记ZF、OF INT 语法: int 目标数 INT 的目标数必须是产生一个整数(例如:int 21h),类似于call调用函数,INT指令是调用程序对硬件控制,不同的值对应着不同的功能。,2019/7/14,32,JUMPS 这些都是最重要的跳转指令和触发条件(重要用*标记,最重要用*标记): 指令 条件 条件 JA* - 如果大于就跳转(无符号) - CF=0

19、 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* - 如果小于就跳转(有符号)

20、 - SF != OF (!= is not) JLE* - 如果小于或等于就跳转(有符号 - ZF=1 and OF != OF JMP* - 跳转 - 强制跳转,2019/7/14,33,JNA - 如果不大于就跳转(无符号) - 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=

21、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

22、JS - 如果SF被标记就跳转 - SF=1 JZ - 如果等于0就跳转 - ZF=1,2019/7/14,34,LEA (有效地址传送) 语法:LEA 目的数、源数 LEA可以看成和MOV差不多的指令LEA ,它本身的功能并没有被太广泛的使用,反而广泛运用在快速乘法中: lea eax,dword ptr 4*ecx+ebx 将eax赋值为 4*ecx+ebx,2019/7/14,35,MOV (传送) 语法: MOV 目的数,源数 这是一个很简单的指令,MOV指令将源数赋值给目的数,并且源数值保持不变 这里有一些MOV的变形: MOVS/MOVSB/MOVSW/MOVSD EDI, ESI

23、:这些变形能将ESI指向的内容传送到EDI指向的内容中去 MOVSX:MOVSX指令将单字或者单字节扩展为双字或者双字节传送,原符号不变 MOVZX:MOVZX扩展单字节或单字为双字节或双字并且用0填充剩余部分(通俗来说就是将源数取出置于目的数,其他位用0填充),2019/7/14,36,MUL (乘法) 语法:MUL 数值 这个指令同IMUL一样,不过MUL可以乘无符号数。 NOP (无操作) 语法:NOP 这个指令说明不做任何事 所以它在逆向中运用范围最广,2019/7/14,37,OR (逻辑或) 语法:OR 目的数,源数 OR指令对两个值进行逻辑或运算 这个指令会清空OF、CF标记,设

24、置ZF标记 为了更好的理解OR,思考下面二进制串: 1001010110 0101001101,2019/7/14,38,如果对它们进行逻辑与运算,结果将是1101011111。 只有当两边同为0时其结果为0,否则就为1。,2019/7/14,39,POP 语法:POP 目的地址 POP指令将栈顶第一个字传送到目的地址。 每次POP后,ESP(栈指针寄存器)都会增加以指向新栈顶 PUSH 语法:PUSH 值 PUSH是POP的相反操作,它将一个值压入栈并且减小栈顶指针值以指向新栈顶。 REP/REPE/REPZ/REPNE/REPNZ 语法: REP/REPE/REPZ/REPNE/REPNZ

25、 ins 重复上面的指令:直到CX=0。ins必须是一个操作符,比如CMPS、INS、LODS、MOVS、OUTS、SCAS 或 STOS,2019/7/14,40,RET (返回) 语法:RET RET digit RET指令的功能是从一个代码区域中退出到调用CALL的指令处。 RET digit在返回前会清理栈 SUB (减) 语法:SUB 目的数,源数 SUB与ADD相反,它将源数减去目的数,并将结果储存在目的数中 SUB可以标记ZF、OF、CF,2019/7/14,41,TEST 语法:TEST 操作符、操作符 这个指令99%都是用于”TEST EAX, EAX”,它执行与AND相同的功能,但是并不储存数据。如果EAX=0就会标记ZF,如果EAX不是0,就会清空ZF XOR 语法:XOR 目的数,源数 XOR指令对两个数进行异或操作 这个指令清空OF、CF,但会标记ZF 为了更好的理解,思考下面的二进制串: 1001010110 0101001101,2019/7/14,42,如果异或它们,结果将是1100011011 如果两个值相等,则结果为0,否则为1, 很多情况下我们会使用”XOR EAX, EAX”,这个操作是将EAX赋值为0,因为当一个值异或其自身,就过都是0。,2019/7/14,43,VII. 逻辑操作符,2019/7/14,44,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1