[原创]逆向学习笔记之汇编

初学逆向,学习滴水的课程整理出的笔记,不足之处敬请各位老师傅指正
十六进制可看作二进制的一种简写形式

数据宽度

计算机中数据有长度限制,超过最高宽度的数据会被丢弃。

1
2
3
4
1.位(bit):一个01
2.字节(byte):8
3.字(word):16
4.双字(doubleword):32

存储范围

1
2
3
1.字节:0~0xFF
2.字:0~0xFFFF
3.双字:0~0xFFFFFFFF

有符号数和无符号数

无符号数的编码规则

无符号数没有负数,全为正数,这个数是多少就存多少
例:1001 1010=0x9A

有符号数的编码规则

若有符号数最高位是0时为正数,最高位是1时为负数。

1
2
3
1.原码:最高位为符号位,其余各位为数值本身的绝对值
2.反码:正数:反码与原码相同。负数:符号位为1,其余位对原码取反
3.补码:正数:补码与原码相同。负数:符号位为1,其余位对原码取反后加1

总结:正数原码存储,负数补码存储。

这个圆,从下面的点开始,逆时针数右半圆为从0到127,顺时针数左半圆为-1到-128
对于一个字节
无符号数:0~FF
有符号数:正数:0~7F,负数:FF~80(因为正数最高位必为0,负数最高位必为1)

计算机运算

位运算

1
2
3
4
5
6
7
8
与运算(and &):两个位都为1时,结果才为1
或运算(or |):只要有一个为1就是1
异或运算(xor ^):不一样的时候是1
非运算(not ~):0就是11就是0
左移(shl <<):各二进制位全部左移若干位,高位丢弃,低位补0
右移:各二进制位全部右移若干位,低位丢弃,高位补0或者补符号位
    汇编:shr--高位补0,sar--高位补符号位
    C语言:>>,通过数据类型判断,无符号数补0,有符号数补符号位

四则运算

加法

1
2
3
4
5
1.异或运算(无进位时结果与按位加一样)
2.与运算(判断是否有进位,因为只有两个1才会进位)
3.异或运算(2的结果左移1位后和1的结果进行异或,左移是因为2判断了哪里需要进位)
4.与运算(再次判断是否有进位)
5.如此重复直到与运算的结果为0,最终结果即为最后一次异或运算的结果

减法

1
减法就是加法,例如4-5=4+-5

乘法

1
乘法本质就是循环的加法

除法

1
除法的本质是减法,就是看一个数能减去一个数多少次

寄存器

寄存器就是CPU内的存储器(cache)
存储格式:
32位CPU:8 16 32
64位CPU:8 16 32 64

通用寄存器

1
2
3
4
5
6
7
8
9
10
16位是32位的低位,两个8位组成一个16位。
32位   16位    8
EAX    AX    AH+AL
ECX    CX    CH+CL
EDX    DX    DH+DL
EBX    BX    BH+BL
ESP    SP    
EBP    BP    
ESI    SI    
EDI    DI

MOV指令

1
2
1.把数存到寄存器。例:MOV EAX,1
2.把寄存器的值存到另一寄存器。例:MOV EDX,EAX(注意是后面的值赋给前面)

内存

内存地址

每个内存地址对应1Byte,内存地址大小为32位,前面的0可以省略,表示时用十六进制。
每个应用程序都有独立的4GB空间就是这个大小,但是这并非是完全可用的,使用前需要先申请。
从0x00000000到0xFFFFFFFF

MOV指令

1
2
3
4
5
6
7
注意前后数据宽度一致,大于一个字节的数据是从给的编号开始,向后存储。
1.数到内存,例如:MOV BYTE PTR DS:[0018FFF0],1  注:内存空间是要被申请的才行
2.寄存器到内存,例如:MOV DWORD PTR DS:[0018FFFC],EAX  注:EAX是4个字节(DWORD),AX是2个字节(WORD),AL是1个字节(BYTE)
3.内存到寄存器,例如:MOV EAX,DWORD PTR DS:[0018FFF8]
4.MOV WORD PTR DS:[xxxxxxxx],1
在这个命令中,WORD PTR的作用是指明了要访问的内存单元的大小为2字节
DS为内存单元的段地址,因为命令中的内存地址实质上是偏移地址,仅靠偏移地址无法读取,还需要段地址。

汇编中绝大多数指令不允许从内存到内存。

内存地址的五种形式

1
2
3
4
5
6
前面MOV指令中[]的内容
1.立即数,例如:0x13FFC4
2.reg,reg为8个通用寄存器中的任意一个,例如:EAX,此时就是把EAX中的数据当做内存地址
3.reg+立即数,例如:EAX+4
4.reg+reg*{1,2,4,8},数组赋值的汇编一般是这种形式,例如:EAX+ECX*4
5.reg+reg*{1,2,4,8}+立即数,例如:EAX+ECX*4+4

数据的存储模式

1
2
3
大端模式:数据高位存低位,数据低位存高位
小端模式:数据高位存高位,数据低位存低位
X86大多采用小端模式存储,ARM大多采用大端模式存储

DTdebug命令

1
2
3
db/dw/dd xxxxxxxx
db是一个字节为单位查看,dw是两个字节为单位查看,dd是四个字节为单位查看。后跟内存地址
注意:想查看存储模式时,要用db,直接用dd看不出来

常用汇编指令

MOV指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
r代表通用寄存器,m代表内存,imm代表立即数,即r8代表8位通用寄存器,m8代表8位内存,imm8代表8位立即数
MOV 目标操作数,源操作数
MOV r/m8,r8
MOV r/m16,r16
MOV r/m32,r32
MOV r8,r/m8
MOV r16,r/m16
MOV r32,r/m32
MOV r8,imm8
MOV r16,imm16
MOV r16,imm32
源操作数:立即数,通用寄存器,段寄存器,内存单元
目标操作数:通用寄存器,段寄存器,内存单元
二者数据宽度要保持一致且不能同时为内存单元

ADD指令

1
2
3
4
5
6
7
8
9
10
11
12
加法指令,最后结果存在前者中
ADD r/m8,imm8
ADD r/m16,imm16
ADD r/m32,imm32
ADD r/m16,imm8
ADD r/m32,imm8
ADD r/m8,r8
ADD r/m16,r16
ADD r/m32,r32
ADD r8,r/m8
ADD r16,r/m16
ADD r32,r/m32

SUB指令

1
2
3
4
5
6
7
8
9
10
11
12
减法指令,前者减去后者,结果存入前者
SUB r/m8,imm8
SUB r/m16,imm16
SUB r/m32,imm32
SUB r/m16,imm8
SUB r/m32,imm8
SUB r/m8,r8
SUB r/m16,r16
SUB r/m32,r32
SUB r8,r/m8
SUB r16,r/m16
SUB r32,r/m32

AND指令

1
2
3
4
5
6
7
8
9
10
11
12
与运算,结果保存到前者
AND r/m8,imm8
AND r/m16,imm16
AND r/m32,imm32
AND r/m16,imm8
AND r/m32,imm8
AND r/m8,r8
AND r/m16,r16
AND r/m32,r32
AND r8,r/m8
AND r16,r/m16
AND r32,r/m32

OR指令

1
2
3
4
5
6
7
8
9
10
11
12
或运算,结果保留到前者
OR r/m8,imm8
OR r/m16,imm16
OR r/m32,imm32
OR r/m16,imm8
OR r/m32,imm8
OR r/m8,r8
OR r/m16,r16
OR r/m32,r32
OR r8,r/m8
OR r16,r/m16
OR r32,r/m32

XOR指令

1
2
3
4
5
6
7
8
9
10
11
12
异或运算,结果保留到前者
XOR r/m8,imm8
XOR r/m16,imm16
XOR r/m32,imm32
XOR r/m16,imm8
XOR r/m32,imm8
XOR r/m8,r8
XOR r/m16,r16
XOR r/m32,r32
XOR r8,r/m8
XOR r16,r/m16
XOR r32,r/m32

NOT指令

1
2
3
4
非运算
NOT r/m8
NOT r/m16
NOT r/m32

MOVS指令

1
2
3
4
内存与内存间移动数据,使用ESI和EDI寄存器,其中保存的是两个需要操作的内存地址。每次执行后,ESI与EDI都会改变。此改变是加还是减取决于DF为是0还是1,加减数取决于指令操作位数。
MOVS BYTE PTR ES:[EDI],BYTE PTR ES:[ESI] 简写为:MOVSB
MOVS WORD PTR ES:[EDI],WORD PTR ES:[ESI] 简写为:MOVSW
MOVS DWORD PTR ES:[EDI],DWORD PTR ES:[ESI] 简写为:MOVSD

STOS指令

1
2
3
4
将AL/AX/EAX中的值存储到[EDI]指定的内存单元
STOS BYTE PTR ES:[EDI] 简写为:STOSB,对应AL
STOS WORD PTR ES:[EDI] 简写为:STOSW,对应AX
STOS DWORD PTR ES:[EDI] 简写为:STOSD,对应EAX

REP指令

1
2
3
4
按计数寄存器(ECX)中指定的次数重复执行字符串命令
例如:
MOV ECX,10
REP MOVSD

堆栈

什么是堆栈?

1
2
程序执行的过程中由操作系统分配可使用的一块内存,要是用超了就是堆栈溢出。
ESP寄存器被称为栈指针寄存器,存储了当前的堆栈用到了哪里。

堆栈的使用

1
堆栈使用时是大地址往小地址用,每次使用后要修改栈顶指针ESP寄存器,防止数据被顶掉

PUSH指令

1
2
3
4
5
6
7
8
向堆栈压入数据,修改栈顶指针ESP寄存器(减)
PUSH imm8/imm16/imm32
PUSH r16/r32
PUSH m16/m32
例如:PUSH EAX等于
SUB ESP,4
MOV DWORD PTR DS:[ESP],EAX

POP指令

1
2
3
4
5
6
7
将栈顶数据存到寄存器或内存,修改栈顶指针ESP寄存器(加)
POP r16/r32
POP m16/m32
例如:POP EAX等于
MOV EAX,DWORD PTR DS:[ESP]
ADD ESP,4

修改EIP的指令

EIP中记录的是CPU下一次要执行的地址,不可用普通的MOV指令修改

JMP指令

1
2
修改EIP的值
JMP imm32/r32/m32

CALL指令

1
2
修改EIP的值,并把当前指令的下一行地址存入堆栈中(修改了堆栈,所以ESP的值也会改动)。
CALL imm32/r32/m32

RET指令

1
2
3
4
本质上就是
ADD ESP,4
MOV EIP,[ESP-4]
RET后面可以跟一个imm,表示ESP加上这个imm,即在函数返回后再修改一次栈顶指针寄存器,用途为释放函数数据占用的堆栈。

反调试

1
2
单步步入(F7)单步步过(F8)
CALL指令时F7是一步一步执行,F8是全执行完

调试器实现原理

1
2
3
4
5
6
7
8
断点:0xCC
单步步入:设置EFLAGS的TF位
单步步过:在下一行设置断点,即无论你CALL有多少指令,最后都要停在CALL的下一行
小小的一个反调试的方法(仅对单步步过有用):
在CALL跳转的位置写:
MOV DWORD PTR DS:[ESP],004183D7(内存地址随意)
RET
这样的话,相当于修改了栈顶的值,使得RET返回时不会回到CALL的下一行,而是跳转到你输入的那个内存地址。

反调试思路

1
写大量的CALL,大量的无意义代码,使得单步步入非常消耗耐心。

汇编眼中的函数

什么是函数?

函数就是一系列指令的集合,为了完成某个会重复使用的特定功能
调用函数:JMP和CALL指令,一般用CALL,因为用RET就能很方便的回来
参数:保存到堆栈,一般调用函数完的返回值保存到EAX

堆栈平衡

1
2
1.如果要返回父程序,则当我们在堆栈中进行堆栈的操作时,一定要保证在RET这条指令之前,ESP指向的是我们压入栈的地址,即RET能正确返回。
2.如果通过堆栈传递参数了,那么在函数执行完毕后,要平衡常数导致的堆栈变化。例如:先向堆栈压入了函数所用的数据,但是函数执行完成后却没有释放数据占用的堆栈,浪费空间。

ESP寻址

1
2
3
4
5
ESP--栈顶指针寄存器,存储了堆栈现在用到的地方
优点:调用方便
缺点:如果函数同时使用多个寄存器,则寄存器的值要保存入栈,此时ESP的值会发生改变
所以在读取堆栈中所需数据时,要灵活使用ESP+4,8,16
最后注意堆栈平衡!

EBP寻址

1
2
3
4
5
6
7
8
9
10
11
12
EBP--栈底指针寄存器
具体为在进入函数前让EBP的值等于ESP,这样后续存入的数据影响ESP的值
但是我们使用未受影响的EBP进行寻址,同时让ESP减去一个自然数,相当于开辟了一块空间专供此函数使用
PUSH EBP
MOV EBP,ESP
SUB ESP,10
XXXXXXXXXXXXXXXXX(函数内容)
MOV ESP,EBP
POP EBP
RET
优点:EBP不会随着你向堆栈添加数据而改变,位置相对固定。
注意:最后也要堆栈平衡。

标志寄存器(EFL)

几个重要的标志寄存器

  • 进位标志寄存器(CF carry Flag):如果运算结果最高位产生了一个进位或借位,那么其值位1,否则为0,这个标志通常用来指示无符号整型运算的溢出状态

  • 奇偶标志寄存器(PF Parity Flag):奇偶编制PF用于反映运算结果中“1”的个数的奇偶性,“1”为偶数个则该位置为1,奇数个则为0。通常用于传输数据过程中的奇偶校验。

  • 辅助进位标志寄存器(AF Auxiliary Carry Flag)

    • 一般用于BCD运算中

    • 如果算数操作在结果的第三位发生进位或者错位,则辅助进位标志AF的值
      被置为1,否则其值为0:

  • 零标志寄存器(ZF Zero Flag):零标志ZF用来反映运算结果是否为0。如果运算结果为0,则其值为0。在判断运算结果是否为0时,可使用此标志位。(经常与CMP或TEST等指令一起使用)

    • 附:CMP指令相当于SUB指令,但结果仅修改标志寄存器而不把结果保存到第一个操作数中,常用与判断两个值是否相同。TEST指令相当于AND指令,但结果仅修改标志寄存器而不把结果保存到第一个操作数中,常用与判断某个值是否为0.

  • 符号标志寄存器(SF Sign Flag):符号标志SF用来反映运算结果的符号位,它与运算结果的最高位相同

  • 溢出标志寄存器(OF Overflow Flag):溢出标志OF用于反映有符号数加减运算所得结果是否溢出。如果运算结果超过当前运算为数所能表示的范围,则成为溢出,OF的值被置为1,否则,OF的值被清为0

    • 进位标志表示无符号数运算结果是否超出范围

    • 溢出标志表示有符号位运算结果是否超出范围

    • 溢出主要给有符号运算使用的,在有符号的运算中,有如下规律:

    • 正 + 正 = 正,如果结果为负数,则说明有溢出

    • 负 + 负 = 负,如果结果为正数,则说明有溢出

    • 正 + 负 永远都不会有溢出

    • 无符号、有符号都不溢出

    • 最高位进位与溢出的区别:

  • 方向标志寄存器(DF Direction Flag):设置DF标志使得串指令自动递减(从高地址向低地址方向处理字符串),清除该标志则使得串指令自动递增。涉及指令:MOVS,CMPS,SCAS,LODS,STOS。STD及CLD指令分别用于设置及清除DF标志。

JCC指令

[培训] 优秀毕业生寄语:恭喜id咸鱼炒白菜拿到远超3W月薪的offer,《安卓高级研修班》火热招生!!!

最后于 2021-4-17 07:55 被PlumpBoy编辑 ,原因: 错别字
(0)

相关推荐

  • CPU 指令

    表白:黑白圣堂血天使,天剑鬼刀阿修罗.  讲解对象:/CPU 指令 作者:融水公子 rsgz 汇编教程 汇编教程 http://www.rsgz.top/post/91.html 我们通过函数来理解一 ...

  • 陈守孚心意拳学习笔记汇编

    二十四把: 龙:龙调膀/刃劲/小龙形/大龙形/龙抱球/十字裹横/大劈/乌牛摆头/一头搠碑. 蛇:蛇拨草/蛇出洞/蛇摆尾/蛇吐舌. 熊:单把/双把/白熊戏球. 虎:虎形(虎蹬山.虎扑.虎摆尾)/ 虎抱头 ...

  • 【原创】★★葡萄‘拉花、无核、膨大处理’学习笔记

    一. 前言 老农天台种休闲种养,面积不大.品种五花八门,其中葡萄品种就有夏黑.巨峰.玫瑰香等等6-7个,夏黑的自然果粒真的是太小太小,其它葡萄品种的籽粒也让人讨厌,因此便盟发了对葡萄'拉花.无核保果. ...

  • 【原创】VBA学习笔记(12)VBA的数组 array

    一 数组 array 1.1 什么是数组?具体的例子 以这个语句为例子 arr1=array(1, 2, 3) 左边:变量名=数组名 右边:数组,集合,多个元素集合,多个数据集合, 右边的单个内容,1 ...

  • 【原创】完善住房租赁有关税收政策学习笔记

      财政部税务总局住房城乡建设部关于完善住房租赁有关税收政策的公告 财政部 税务总局 住房城乡建设部公告2021年第24号    [学习笔记]      第一类问题:出租住房增值税问题     一.住 ...

  • 什么是DUMP阀?今天分享上汽调节保安系统学习笔记(原创一)

    东汽调节保安系统图,已标注,适合初学者 耗时两个小时,对EH油系统图进行标注 东汽调节保安系统学习笔记链接: (原创一)东汽调节保安系统的遮断阀.隔离阀.主遮断电磁阀结构 (原创二)挂闸和遮断,低压保 ...

  • 复习挂闸、打闸等油路状态。上汽调节保安系统学习笔记(原创二)

    昨天简单学习了一下上汽与哈汽的调节保安系统不同之处:什么是DUMP阀?今天分享上汽调节保安系统学习笔记(原创一).今天继续学习上汽某60万机组的调节保安系统,这个系统与哈汽系统基本一致,相当于重复学习 ...

  • 神农本草经学习笔记(原创)

    ​神农本草经学习笔记(原创) 2015-07-16 08:33阅读:2,518 铜镜先生 为了不躺在医院的ICU病房里,全身插满管子孤独地死去且耗尽家人的钱财. 为了帮助相信中医的人. 你可以买陀飞轮 ...

  • 一则公报案例学习笔记:对修改股东出资期限应否适用资本多数决规则的思考|审判研究

    一.问题的提出 2021年第3期<最高人民法院公报案例>刊登了鸿大(上海)投资管理有限公司与姚锦城公司决议纠纷上诉案,裁判要旨为:"公司股东滥用控股地位,以多数决方式通过修改出资 ...

  • JAVA多线程学习笔记整理

    多线程: 三种创建方法 继承Thread类,以线程运行内容重写run方法,创建Thread对象并用start方法启动该线程. (匿名内部类) (Lambda表达式) 实现Runable接口,以线程运行 ...