恶意代码分析实战 Lab 4 习题笔记

Lab 4

本身Lab 4是没有习题

然后本身在大学就学过两个学期两门课的汇编(第一门好像是和数电更接近一点,另一门就是汇编语言

然后这章,如果大学学的不是信息安全,或者连计算机都不是的同学, 我还是建议大家买本有关汇编的书看看,这样后面的分析可能会更有用一点

然后我们这次来讲讲汇编的各种跳转指令(这是我写到Lab 7-2的时候觉得还有是必要写一下,因为中文搜索引擎是找不到特别详细的介绍的,只有一些肤浅的内容)

这图是一些基本的计算的原理架构

图片


我们先从跳转开始吧,其他的简单就先不讲,以后看有这个必要再来讲讲

1.跳转

这是从外网的一个大神的网站扒下来的内容

注:signedness代表符号类型,unsigned代表无符号(数的运算判断跳转才可以用),signed代表有符号(数的运算判断跳转才可以用)

InstructionDescriptionsigned-nessFlagsshort jump opcodesnear jump opcodes
JOjump if overfolwOF=1700F 80
JNOJump if not overflowOF=0710F 81
JSJump if signSF = 1780F 88
JNSJump if not signSF=0790F 89
JEJump is equalZF=1740F 84
JZJump is zeroZF=1740F 84
JNEJump is not equalZF=0750F 85
JNZJump is not zeroZF=0750F 85
JBJump if belowunsignedCF=1720F 82
JNAEJump if not above of equalunsignedCF=1720F 82
JCJump if carryunsignedCF=1720F 82
JNBJump if not belowunsignedCF=0730F 73
JAEJump if above or equalunsignedCF=0730F 73
JNCJump if not carryunsignedCF=0730F 73
JBEJump if below or equalunsignedCF=1 or ZF=1760F 86
JNAJump if not aboveunsignedCF=1 or ZF=1760F 86
JAJump if aboveunsignedCF=0 or ZF=0770F 87
JNBEJump if not below or equalunsignedCF=0 or ZF=0770F 87
JLJump if lesssignedSF<>OF7C0F 8C
JNGEJump if not greater or equalsignedSF<>OF7C0F 8C
JGEJump is greater or equalsignedSF=OF7D0F 8D
JNLJump if not lesssignedSF=OF7D0F 8D
JLEJump if less or equalsignedZF=1 or SF<>OF7E0F 8E
JNGJump if not greatersignedZF=1 or SF<>OF7E0F 8E
JGJump if greatersignedZF=0 or SF=OF7F0F 8F
JNLEJump if not less or equalsignedZF=1 or SF=OF7F0F 8F
JPJump if parityPF=17A0F 8A
JPEJump if parity evenPF=17A0F 8A
JNPJump if not parityPF=07B0F 8B
JPOJump if parity oddPF=07B0F 8B
JCXZJump if %CX register is 0%CX=0E3
JECXZJump if %ECX register is 0%ECX=0E3

说明一下<>是不等于的意思,等同!=


常见的几个标志位是这样的,其他不常用的我们就不介绍了

CF标志位

CF - carry flag
进位标志位
Set on high-order bit carry or borrow; cleared otherwise
设置在高位位进位或借位;否则清除
进位标志CF主要用来反映运算是否产生进位或借位。如果运算结果的最高位产生了一个进位或借位,那么,其值为1,否则其值为0。

PF标志位

PF - parity flag
奇偶标志位
Set if low-order eight bits of result contain an even number of “1” bits; cleared otherwise
如果低8位结果包含偶数“1”位,则置位;否则清除
奇偶标志PF用于反映运算结果中“1”的个数的奇偶性。如果“1”的个数为偶数,则PF的值为1,否则其值为0。

ZF标志位

ZF - zero flags
零标志位
Set if result is zero; cleared otherwise
如果结果为零则置位;否则清除
零标志ZF用来反映运算结果是否为0。如果运算结果为0,则其值为1,否则其值为0。在判断运算结果是否为0时,可使用此标志位。

SF标志位

SF - sign flag
符号标志位
Set equal to high-order bit of result (0 if positive 1 if negative)
设置为等于结果的高位(如果为负,则为0,如果为负)
符号标志SF用来反映运算结果的符号位,它与运算结果的最高位相同。运算结果为正数时,SF的值为0,否则其值为1。

OF标志位

OF - overflow flag
溢出标志位
Set if result is too large a positive number or too small a negative number (excluding sign bit) to fit in destination operand; cleared otherwise
设置结果是否太大,正数或太小的负数(不包括符号位)以适合目的地操作数;否则清除
溢出标志OF用于反映有符号数加减运算所得结果是否溢出。如果运算结果超过当前运算位数所能表示的范围,则称为溢出,OF的值被置为1,否则,OF的值被清为0(主要是结果是否超过计算机最大能标识的数值注意和进位不是一个概念)


然后常见的会影响标志位的,也是常见的会根据计算影响的标志位跳转的操作如下(以后可能会遇到了新的会来补充一下)

2.影响标志位跳转的操作

我发现现在国内网上的一些标志位影响的介绍都很简单,我们好好研究研究

CMP

cmp指令其实就是sub指令不影响操作数只影响标志位的一个变形指令

假设指令为cmp AX, BX的时候

CF
如果二进制减法运算中最高有效位有向最高位借位(AX<BX
CF=1
如果二进制减法运算中不用借位(AX>=BX
CF=0


PF
如果运算结果中1的个数为偶数
PF=1
如果运算结果中的1的个数为奇数
PF=0


ZF
如果计算结果为0的话(AX=BX
ZF=1
如果计算结果不为0的话(AX<>BX
ZF=0


SF
如果运算结果为正数的时候
SF=0
如果运算结果为负数的时候
SF=1


OF
如果两个数的符号相反(正数减负数,或负数减正数),而结果符号与减数相同
OF=1
你可能会说,OF不是判断溢出的嘛,怎么开始比较符号了,这句话就是表示溢出判断这个意思,只是表达比较拗口
稍微解释一下,方便大家理解
考虑如以下有符号数运算(假设我们的系统是8位的,无符号数无负数所以不考虑)

F0h(1111 0000b)(-16d)-78h(0111 1000b)(+120d)=178h(0001 0111 1000)(-136d理论值)(+120溢出值也是系统中显示的值)

我们的系统只是8位的系统,然后最后的运算结果是9位的,所以溢出了(验证了上面的负数减正数,结果和减数相同就溢出)
然后可能就是有的同学不理解,为什么(1111 0000b)不等于(-112d)而是等于(-16d)
稍微解释一下就是在计算机中,比如-1这个数,并不是表示成1000 0001而是1111 1111这个要说就很长了,大家可以看看汇编的书或者文章啥的补补
(-16d)这个数是怎么通过(1111 0000)计算得到的呢?
先将(1111 0000)减去1,然后再取反码,去除符号位换算成十进制,就是(16d),最后加上符号位就是(-16d)
这里已经溢出,一看就看得出来(对照那句话就是结果(+120d)和减数(+120d)符号相同),所以OF=1
这是稍微解释一下
那如果两个数符号相同(正数减正数,或负数减负数),结果符号与减数不同
OF=0

一般cmp汇编中会用到的就是ZF位,就像这样

cmp 10h, 01h
jnz loc_40123

这里我们两个数是同符号数的,且结果不为0,因为10h>01h,则ZF=0,然后jnz就开始跳转了


TEST

test会其实就是and指令不保存运算结果的一个变形指令,对标志位的影响和and一样

假设语句是

test AX, BX

CF & OF
指令执行后
CF=0
OF=0


PF
结果操作数中的1的个数为偶数时
PF=1
反之为1的个数为奇数时
PF=0


ZF
如果AX=BX=0and之后,运算结果都是0,所以
运算结果为0的时候
ZF=1
其他如果AX=BX<>0,或者AX<>BX
<>就是!=(不等于)
ZF=0


SF
运算结果为正数的话
SF=0
运算结果为负数的话
SF=1

一般test指令之后会跟jnz或者jz之流
但是有时候你会遇到这种变态的跳转

test eax, eax
jl   short loc_401085

如果eax0,则test之后,我们一个标志位一个标志位的来分析
首先是没有产生借位这个运算,所以CF=0
然后是如果eax0的话,1的个数是00是偶数,所以PF=1
然后是运算结果是0,所以ZF=1
因为最后的结果是个正数,所以SF=0
溢出标志位么,肯定没产生溢出,所以OF=0

这么大概一分析下来之后,我们再看jl的跳转条件

jlJump if lessSF<>OF

这个 跳转条件是SF!=OF,现在我们的SF=0OF=0,所以在eax=0的情况之下,是不会跳转的,那如果eax不为0

我们先大概回顾一下and与运算的法则

① 0∧0=0

② 0∧1=0

③ 1∧0=0

④ 1∧1=1

然后是or或运算的法则

① 0∨0=0

② 0∨1=1

③ 1∨0=1

④ 1∨1=1

知道了这些之后我们继续分析

如果eax>0的话
一样的test指令之后,CF=0
相同的数做and运算,结果不确定,所以这里PF=#(代表PF的值不确定)
然后运算结果不确定的话,所以ZF=#
结果是正数,所以SF=0
溢出的话,因为是and运算,不存在进位,所以OF=0
所以jl也不跳转

eax还有一种情况就是eax<0
照上面的过程分析
CF=0, PF=#, ZF=#, SF=1(这个应该想得通吧,1∧1=1,结果还是负数,所以SF=1), OF=0
然后这里SF<>OF了,所以jl开始跳转

所以分析到现在的话,就是

test eax, eax
jl   short loc_401085

eax>=0的时候,不跳转
eax<0的时候,开始跳转


DEC

然后还有这个会被汇编中用的比较多的用法

dec本身就是将数减一的操作,但是这个也会影响标志位的跳转

CF
decCF标志位没有影响


PF
这个主要看计算的数字,不是定值


ZF
如果最后一直减,减到结果为0的话
ZF=1
如果没有为0的话
ZF=0


SF
这个主要是看最后结果的正负,如果结果为正数
SF=0
反之
SF=1


OF
这个还是看数值有没有溢出
如果溢出了
OF=1
如果没有溢出
OF=0

考虑以下汇编代码

loc_401126
move esi, 14h
call somefunction
dec esi
jnz short loc_401126

我们这里并没有用到cmp或者test这样的指令,但是我们有个dec指令

这个指令最后会影响到ZF(如果最后结果为0的话)

所以这个会一直循环,知道最后esi减到了0的时候,这也是一种汇编的循环方式,大家以后看到这种语句不要觉得一头雾水就行了,实在记不得是影响什么标志位,回来翻翻博客就行了


暂时就先写这么多,其他遇到了新的什么值得注意,再来补充

本文完

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值