【reverse】逆向5 标志寄存器
1、引言
通过一个creak.exe文件的爆破,引出现阶段需要学习的知识
2、标志寄存器
标志寄存器有上图这么多个
记住这几个寄存器的位置和名称
下面是6个状态标志位
1.进位标志CF(Carry Flag)
如果运算结果的最高位产生了一个进位或者借位,那么其值为1,否则为0
做个实验
我们先给eax一个5555FFFF的数据,然后再加1
然后将c变成0
运行这两句汇编
发现eax虽然进位了,但不是最高位进位,因为eax是32位的
我们再试一试al
把所有标记寄存器归为0
运行这两句汇编
al是FF,加1之后溢出,但是实际上最高位也就是第八位,进位了,所以c为1
所以,一定要注意是最高位
2. 奇偶标志PF(Parity Flag)
奇偶标志PF用于反映运算结果中最低有效字节中“1”的个数的奇偶性
注意是最低有效字节,也就是只看最后两位
如果“1”的个数为偶数,则PF的值为1,反之为0(一定转为二进制来看)
我们运行下面的指令
首先将al赋值0
然后让al+0x3
hex中0+3 = 3
转为2进制,3 = 0011,有两个1,所以p为1
再执行+3的指令
hex中3+3 = 6
转为2进制,6 = 0110,有两个1,所以p为1
再执行+2的指令
hex中6 + 2 = 8
转为2进制,8 = 1000,只有1个1,所以p=0
3.辅助进位标志AF(Auxiliary Carry Flag)
发生下列情况的时候,辅助进位标志AF的值被置为1,否则为0
- 在字操作时,发生低字节向高字节进位或者借位时
- 再字节操作时,发生低4位向高4位进位或者借位时
看我绿笔画的圈,这个位置的数进不进位,进位就是1,否则是0
4.零进位标志ZF(Zero Flag)
零标志位ZF用来反映运算结果是否为0
如果运算结果为0,ZF=1,否则为0
mov指令不算运算
看这句指令,让eax和自己异或,两个相同的数字异或=0,所以计算结果为0,所以ZF= 1
5.符号标志SF(Sign Flag)
符号标志SF用来反映运算结果的符号位,它与运算结果的最高位相同
首先确定一点,mov指令不影响标志寄存器
第一句汇编,让al存0x7F (0111 1111)
第二句汇编,让al+2
0111 1111 + 0000 0010 = 1000 0001
符号位(也就是从左向右第一位)运算后是1,所以SF=1
6.溢出标志OF(Overflow Flag)
溢出标志OF用于反映有符号数加减运算所得结果是否溢出
如果运算结果超过当前运算位数所能表示的范围,则称为溢出,OF的值置为1,否则OF的值被清为0
如何辨别CF和OF?
CF是最高位进位,而OF时有符号数的溢出
有符号数的范围:
- 正数:0~7F
- 负数:FF~80
有无符号是程序员代码规定的,不是计算机规定的,计算机内相同的数——FF,如果是有符号,那就是-1,如果无符号,那就是15
举几个例子
8位,无符号范围是0~FF
有符号数的范围:正数:0~7F;负数:FF~80
-
无符号、有符号都不溢出
mov al,8 add al,8
-
无符号溢出,有符号不溢出(-1+2)
mov al,0xff add al,2
-
无符号不溢出(小于FF),有符号溢出(最大的正数还+2,溢出,成为负数)
mov al,7f add al,2
-
无符号(大于FF)、有符号(最小的负数还加负数,两负数相加得到正数)都溢出
mov al,0xfe add al,0x80
然后计算机最底层的处理OF标志其实是这样的:
- 判断符号位是否有进位,有进位,标志1,无进位,标志0
- 判断最高有效数值位向符号位产生进位否,有进位,标志1,无进位,标志0
- 将第一步和第二部得到的数字xor一下,得到的数字就是OF标志位的数字
我们看下面这个例子(OF的前提是必须是有符号数)
3、指令
1.ADC指令
adc指令就是带进位的加法(这个进位就看CF进位标志,是1就进位,0就不进)
格式:adc R/M,R/M/IMM
R是寄存器,M是内存,IMM是立即数
两边不能同时为内存,且宽度要一样
adc al,cl
adc byte ptr ds:[12ffc4],2
adc byte ptr ds:[12ffc4],al
2.SBB指令
sbb就是带借位的减法(借位也是看CF标志,是1就借位,反之不借)
格式:adc R/M,R/M/IMM
R是寄存器,M是内存,IMM是立即数
两边不能同时为内存,且宽度要一样
sbb al,cl
sbb byte ptr ds:[12ffc4],2
sbb byte ptr ds:[12ffc4],al
3.XCHG指令
xchg指令是交换数据的指令
格式:XCHG R/M,R/M 两边不能同时为内存,宽度要一样
xchg al,cl
xchg dword ptr ds:[12ffc4],eax
xchg byte prt ds:[12ffc4],al
4.MOVS指令
movs指令是移动数据的指令,这个指令必须对edi和esi使用
这个指令有点特殊,我们之前学习的指令都是不能两边同时为内存的
但是这个指令,他必须两边都是内存,且都是edi和esi使用的!
movs byte ptr es:[edi],byte ptr ds:[esi] 简写为:movsb
movs word ptr es:[edi],word ptr ds:[esi] 简写为:movsw
movs dword ptr es:[edi],dword ptr ds:[esi] 简写为:movsd
movsb:移动esi中地址数据到edi中,同时esi、edi都加1
movsw:移动esi中地址数据到edi中,同时esi、edi都加2
movsd:移动esi中地址数据到edi中,同是esi、edi都加4
esi和edi的加和减是由DF标志寄存器决定的,DF=0就是加,DF=1就是减
5.STOS指令
stos指令是将al/ax/eax的值存到[edi]指定的内存单元
stos byte ptr es:[edi] 简写为stosb
stos word ptr es:[edi] 简写为stosw
sots dword ptr es:[edi] 简写为stosd
存哪个寄存器由是数据宽度决定的
byte是al
word是ax
dword是eax
同样的
edi的加和减是由DF标志寄存器决定的,DF=0就是加,DF=1就是减。
加减的值也是和位数相关
byte +- 1
word +- 2
dword +- 4
6.REP指令
按计数寄存器 (ECX) 中指定的次数重复执行字符串指令
mov ecx,10
rep movsd
rep stosd
这里给ecx存10是hex形式,所以循环了16次
rep movsd就是循环16次将esi的值赋给edi,当然,因为刚刚我们提到了DF标志位,所以会根据DF的值来自增或自减。这里是dword,所以是+-4
rep stosd就是将eax中的值存入edi中16次,这里的edi的+-也是通过DF标志位来的。DF=1是减,DF=0是加
4、本节练习
海哥布置的作业,有机会补上!