滴水逆向学习笔记(3)
只能push16位或者32位的寄存器或者内存。
栈顶在push或者pop之后加几,取决于指令之后是多少位的寄存器或者内存,比如push eax ,ac转为a8,之后pop ax,a8转为aa
pushad指令
ebp(栈底)esp(栈顶)的值不能乱改,因为里面的内存是系统分配的。
将六个寄存器的值改的明显一点,使用pushad指令
pushad指令就将八个寄存器的值存入了堆栈中。然后我们就可以更改寄存器里的值,改完之后,通过popad还原原本寄存器里的值
标志寄存器
1、进位标志CF
如果运算结果的最高位产生了一个进位或者借位,那么,其值为1,否则其值为0.
EFL转化为二进制:0000001000010010(能看到AF为1)
2、奇偶标志PF
用于反映运算结果中“1”的个数的奇偶性。如果“1”的个数为偶数,则PF的值为1,否则其值为0.
现在总数为6二进制就是0110,两个“1”是偶数,所以右边的p为1.
3、辅助进位标志AF
在发生下列情况时,辅助进位标志AF的值变为1,否则为0
(1)在字操作时,发生低字节向高字节进位或借位时;
(2)在字节操作时,发生低4位向高4位进位或借位时;
FFFFFFFF FFFF FF(也就是加粗的位置发生进位,AF就会变为1)
4、零标志位ZF
用来反映运算结果是否为0。为0则ZF=1,反之为0
XOR:异或,用XOR EAX,EAX 可以达到清零的作用
MOV EAX,0也可以
但是区别在于:MOV指令不修改寄存器的值,且不影响标志寄存器
5、符号表示SF
反映运算结果的符号位,它与运算结果的最高位相同
6、溢出标志OF
有符号数的溢出用OF,无符号数的溢出用CF
溢出主要给有符号运算使用的,在有符号运算中,规律如下:
正 + 正 = 正 如果结果有负数,说明溢出。
负 + 负 = 负 如果结果有正数,说明溢出。
正 + 负 永远都不会溢出
ADC指令(带进位加法)
格式:ADC R/M,R/M/IMM(R是寄存器M是内存IMM是立即数,两边不能都是内存,且宽度要一样)
也就是ADC X,Y结果为:X=X+Y+CF
执行指令之后为B也就是9+1+1(CF)=B
SBB指令(带借位减法)
格式:SBB R/M,R/M/IMM(两边不能都是内存,且宽度要一样)
SBB X,Y结果为X=X-Y-CF
XCHG指令(交换指令)
格式:XCHG R/M,R/M(两边不能都是内存,且宽度要一样)
MOVS指令(移动数据)
MOVS BYTE PTR DS:[EDI],BYTE PTR DS:[ESI] 简写:MOVSB
MOVS WORD PTR DS:[EDI],WORD PTR DS:[ESI] 简写:MOVSW
MOVS DWORD PTR DS:[EDI],DWORD PTR DS:[ESI] 简写:MOVSD
7、方向标志DF
当DF为0的时候:MOVS WORD PTR DS:[EDI],WORD PTR DS:[ESI],这两个寄存器的值各自加2。
当DF为1的时候:MOVS WORD PTR DS:[EDI],WORD PTR DS:[ESI],这两个寄存器的值各自减2.(DWORD的时候是-4或者+4)
STOS指令
将AL/AX/EAX的值存储到[EDI]指定的内存单元
STOS BYTE PTR ES:[EDI] 简称为STOSB
STOS WORD PTR ES:[EDI] 简称为STOSW
STOS DWORD PTR ES:[EDI] 简称为STOSD
REP指令
按计数寄存器(ECX)中指定的次数重复执行字符串命令
REP STOSD(不停的向EDI中存储EAX的值,+4或者-4每次存完都会向上或向下移动栈,DF=0就是加,反之减)
JMP指令
修改eip。只影响eip。
mov eip,寄存器/立即数 简写为 jmp 寄存器。立即数
CALL指令
我们执行一个:call 0x776bb82a
执行完后我们发现堆栈窗口里所要执行的下一个指令正是反汇编窗口call指令下面的指令(776bb17)(那为什么是17呢,12+5才是17,这从哪里来的呢,答:看12里面E8 13 00 00 00 一共五个字节,所以是12+5=17)17下面的18也是这个道理。
JMP和CALL相同点:都会改变eip的值
不同点:call会把下一行的指令的地址压到栈里
call指令就是出去旅游,还会回来(有返回地址
jm指令就是云游,可能不回来了
ret相当于pop eip
下断点:F2
CMP指令
比较两个操作数,相当于sub指令,但是相减的结果不保存到第一个操作数中,而是根据相减的结果改变零标志位,所以当两个操作数相等时,零标志位是1(Z位为1)第一个操作数小于第二个观察S位
指令格式:CMP R/M,R/M/IMM(R是寄存器M是内存IMM是立即数,不能同时为内存)
CMP只修改标志寄存器的值
TEST指令
指令格式:TEST R/M,R/M/IMM
一定程度上与CMP指令相似,两个数值进行与操作,结果不保存,但会改变相应标志位
常见用法:查看某寄存器里的值是否为0
JCC只认识标志寄存器
1、JZ,JE(jump if equal) 结果为零则跳转(相等时跳转 ZF=1
2、JNE,JNZ(jump not zero) 结果不为零则跳转(不相等时跳转 ZF=0
3、JS 结果为负则跳转 SF=1
4、JNS 结果不为负则跳转 SF=0
5、JP,JPE 结果中1的个数为偶数则跳转 PF=1
6、JNP、JP0
7、JO 结果溢出了则跳转 OF=1
8、JNO 结果没有溢出则跳转 OF=0
9、JB、JNAE 小于则跳转(无符号数) CF=1
10、JNB、JAE 大于等于则跳转(无符号数) CF=0
11、JBE、JNA 小于等于则跳转(无符号数) CF=1 or ZF=1
12、JNBE、JA 大于则跳转(无符号数) CF=0 and ZF=0
13、JL、JNGE 小于则跳转(有符号数) SF ≠ OF
14、JNL、JGE 大于等于则跳转(有符号数) SF=OF
15、JLE、JNG 小于等于则跳转(有符号数) ZF=1 or SF≠OF
16、 JNLB、JG 大于则跳转(有符号数) ZF=0 and SF=OF