加密解密教程之必备基础知识

第1章 前言&基础知识

很多人都想学学做cracker,好象破了一个程序很风光的,人人都很佩服。 可是做一个cracker其实很累,需花费大量的时间,而且经常会碰壁,三五天毫无进展是极为平常的事情。

做cracker的五个必要条件是: 1. 知识 2. 经验 3. 感觉 4. 耐心 5. 运气 。

如果你刚开始学crack,也许你遇到不少麻烦,并且有点想退却,其实你不要着急,只要你认真学习,成功就在眼前。没有人是生来就什么都会的,如果你有问题,就大胆的去问你周围的人,多来我主页论坛请教。计算机水平不高怎么办?没关系,我也不是学计算机的,我自己的专业与电脑不沾边。只要努力学习就能成功。

所谓知识只要你肯学就可以了,刚入门时如你没汇编知识是不行的,你要掌握一下这门编程语言,能看懂就能上手,但是你想很顺手的话,除了把汇编掌握好,还有编程的基本功夫,保护模式等技术。

经验是跟你破解软件时间,掌握程度有关,接触多了,拿到一软件应该知道用哪种法比较省事,比较有把握。

感觉这点不可言传,就象我们做语文题目时,一句话有语法错误一看就知道,这时我们有可能从语法上也说不上什么道道,就知它是错的,这就是语感。我们crack多了,也会有这方面的体会,拿一软件跟踪,到关键点时凭感觉就找到。

耐心就不多说,成功与失败的关键也在这一步。

运气也很关键,但运气是建立在你的扎实的基础功上的。

另外我还要谈的一事是,当cracker目的不是破解软件,而是通过跟踪软件,了解程序思路,这样提高自己,使自己能写出更好的程序。 并且破解不在多,而在于你要掌握它,尽量了解注册码计算原理,最好能写出注册机,不能写也没关系,要弄懂它的算法。

第一节 软件保护

软件的破解技术与保护技术这两者之间本身就是矛与盾的关系,它们是在互相斗争中发展进化的。这种技术上的较量归根到底是一种利益的冲突。软件开发者为了维护自身的商业利益,不断地寻找各种有效的技术来保护自身的软件版权,以增加其保护强度,推迟软件被破解的时间;而破解者则或受盗版所带来的高额利润的驱使,或出于纯粹的个人兴趣,而不断制作新的破解工具并针对新出现的保护方式进行跟踪分析以找到相应的破解方法。从理论上说,几乎没有破解不了的保护。对软件的保护仅仅靠技术是不够的,而这最终要靠人们的知识产权意识和法制观念的进步以及生活水平的提高。但是如果一种保护技术的强度强到足以让破解者在软件的生命周期内无法将其完全破解,这种保护技术就可以说是非常成功的。软件保护方式的设计应在一开始就作为软件开发的一部分来考虑,列入开发计划和开发成本中,并在保护强度、成本、易用性之间进行折衷考虑,选择一个合适的平衡点。
在桌面操作系统中,微软的产品自然是独霸天下,一般个人用户接触得最多,研究得自然也更多一些。在DOS时代之前就有些比较好的软件保护技术,而在DOS中使用得最多的恐怕要算软盘指纹防拷贝技术了。由于DOS操作系统的脆弱性,在其中运行的普通应用程序几乎可以访问系统中的任何资源,如直接访问任何物理内存、直接读写任何磁盘扇区、直接读写任何I/O端口等,这给软件保护者提供了极大的自由度,使其可以设计出一些至今仍为人称道的保护技术;自Windows 95开始(特别是WinNT和Windows 2000这样严格意义上的多用户操作系统),操作系统利用硬件特性增强了对自身的保护,将自己运行在Ring 0特权级中,而普通应用程序则运行在最低的特权级Ring 3中,限制了应用程序所能访问的资源,使得软件保护技术在一定程度上受到一些限制。开发者要想突破Ring 3的限制,一般需要编写驱动程序,如读写并口上的软件狗的驱动程序等,这增加了开发难度和周期,自然也增加了成本。同时由于Win32程序内存寻址使用的是相对来说比较简单的平坦寻址模式(相应地其采用的PE文件格式也比以前的16-bit的EXE程序的格式要容易处理一些),并且Win32程序大量调用系统提供的API,而Win32平台上的调试器如SoftICE等恰好有针对API设断点的强大功能,这些都给跟踪破解带来了一定的方便。

第二节 8088 汇编速查手册


一、数据传输指令
───────────────────────────────────────
  它们在存贮器和寄存器、寄存器和输入输出端口之间传送数据.
  1. 通用数据传送指令.
      MOV    传送字或字节.
      MOVSX  先符号扩展,再传送.
      MOVZX  先零扩展,再传送.
      PUSH    把字压入堆栈.
      POP    把字弹出堆栈.
      PUSHA  把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈.
      POPA    把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈.
      PUSHAD  把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈.
      POPAD  把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈.
      BSWAP  交换32位寄存器里字节的顺序
      XCHG    交换字或字节.( 至少有一个操作数为寄存器,段寄存器不可作为操作数)
      CMPXCHG 比较并交换操作数.( 第二个操作数必须为累加器AL/AX/EAX )
      XADD    先交换再累加.( 结果在第一个操作数里 )
      XLAT    字节查表转换.
              ── BX 指向一张 256 字节的表的起点, AL 为表的索引值 (0-255,即
              0-FFH); 返回 AL 为查表结果. ( [BX+AL]->AL )
  2. 输入输出端口传送指令.
      IN      I/O端口输入. ( 语法: IN 累加器, {端口号│DX} )
      OUT    I/O端口输出. ( 语法: OUT {端口号│DX},累加器 )
        输入输出端口由立即方式指定时, 其范围是 0-255; 由寄存器 DX 指定时,
        其范围是 0-65535.
  3. 目的地址传送指令.
      LEA    装入有效地址.
        例: LEA DX,string  ;把偏移地址存到DX.
      LDS    传送目标指针,把指针内容装入DS.
        例: LDS SI,string  ;把段地址:偏移地址存到DS:SI.
      LES    传送目标指针,把指针内容装入ES.
        例: LES DI,string  ;把段地址:偏移地址存到ES:DI.
      LFS    传送目标指针,把指针内容装入FS.
        例: LFS DI,string  ;把段地址:偏移地址存到FS:DI.
      LGS    传送目标指针,把指针内容装入GS.
        例: LGS DI,string  ;把段地址:偏移地址存到GS:DI.
      LSS    传送目标指针,把指针内容装入SS.
        例: LSS DI,string  ;把段地址:偏移地址存到SS:DI.
  4. 标志传送指令.
      LAHF    标志寄存器传送,把标志装入AH.
      SAHF    标志寄存器传送,把AH内容装入标志寄存器.
      PUSHF  标志入栈.
      POPF    标志出栈.
      PUSHD  32位标志入栈.
      POPD    32位标志出栈.
二、算术运算指令
───────────────────────────────────────
      ADD    加法.
      ADC    带进位加法.
      INC    加 1.
      AAA    加法的ASCII码调整.
      DAA    加法的十进制调整.
      SUB    减法.
      SBB    带借位减法.
      DEC    减 1.
      NEC    求反(以 0 减之).
      CMP    比较.(两操作数作减法,仅修改标志位,不回送结果).
      AAS    减法的ASCII码调整.
      DAS    减法的十进制调整.
      MUL    无符号乘法.
      IMUL    整数乘法.
        以上两条,结果回送AH和AL(字节运算),或DX和AX(字运算),
      AAM    乘法的ASCII码调整.
      DIV    无符号除法.
      IDIV    整数除法.
        以上两条,结果回送:
            商回送AL,余数回送AH, (字节运算);
        或  商回送AX,余数回送DX, (字运算).
      AAD    除法的ASCII码调整.
      CBW    字节转换为字. (把AL中字节的符号扩展到AH中去)
      CWD    字转换为双字. (把AX中的字的符号扩展到DX中去)
      CWDE    字转换为双字. (把AX中的字符号扩展到EAX中去)
      CDQ    双字扩展.    (把EAX中的字的符号扩展到EDX中去)

三、逻辑运算指令
───────────────────────────────────────
      AND    与运算.
      OR      或运算.
      XOR    异或运算.
      NOT    取反.
      TEST    测试.(两操作数作与运算,仅修改标志位,不回送结果).
      SHL    逻辑左移.
      SAL    算术左移.(=SHL)
      SHR    逻辑右移.
      SAR    算术右移.(=SHR)
      ROL    循环左移.
      ROR    循环右移.
      RCL    通过进位的循环左移.
      RCR    通过进位的循环右移.
        以上八种移位指令,其移位次数可达255次.
            移位一次时, 可直接用操作码.  如 SHL AX,1.
            移位>1次时, 则由寄存器CL给出移位次数.
              如  MOV CL,04
                  SHL AX,CL
四、串指令
───────────────────────────────────────
           DS:SI  源串段寄存器  :源串变址.
          ES:DI  目标串段寄存器:目标串变址.
          CX      重复次数计数器.
          AL/AX  扫描值.
          D标志  0表示重复操作中SI和DI应自动增量; 1表示应自动减量.
          Z标志  用来控制扫描或比较操作的结束.
      MOVS    串传送.
          ( MOVSB  传送字符.    MOVSW  传送字.    MOVSD  传送双字. )
      CMPS    串比较.
          ( CMPSB  比较字符.    CMPSW  比较字. )
      SCAS    串扫描.
          把AL或AX的内容与目标串作比较,比较结果反映在标志位.
      LODS    装入串.
          把源串中的元素(字或字节)逐一装入AL或AX中.
          ( LODSB  传送字符.    LODSW  传送字.    LODSD  传送双字. )
      STOS    保存串.
          是LODS的逆过程.
      REP            当CX/ECX<>0时重复.
      REPE/REPZ      当ZF=1或比较结果相等,且CX/ECX<>0时重复.
      REPNE/REPNZ    当ZF=0或比较结果不相等,且CX/ECX<>0时重复.
      REPC          当CF=1且CX/ECX<>0时重复.
      REPNC          当CF=0且CX/ECX<>0时重复.
五、程序转移指令
───────────────────────────────────────
   1>无条件转移指令 (长转移)
      JMP    无条件转移指令
      CALL    过程调用
      RET/RETF过程返回.
  2>条件转移指令 (短转移,-128到+127的距离内)
      ( 当且仅当(SF XOR OF)=1时,OP1<OP2 )
      JA/JNBE 不小于或不等于时转移.
      JAE/JNB 大于或等于转移.
      JB/JNAE 小于转移.
      JBE/JNA 小于或等于转移.
        以上四条,测试无符号整数运算的结果(标志C和Z).
      JG/JNLE 大于转移.
      JGE/JNL 大于或等于转移.
      JL/JNGE 小于转移.
      JLE/JNG 小于或等于转移.
        以上四条,测试带符号整数运算的结果(标志S,O和Z).
      JE/JZ  等于转移.
      JNE/JNZ 不等于时转移.
      JC      有进位时转移.
      JNC    无进位时转移.
      JNO    不溢出时转移.
      JNP/JPO 奇偶性为奇数时转移.
      JNS    符号位为 "0" 时转移.
      JO      溢出转移.
      JP/JPE  奇偶性为偶数时转移.
      JS      符号位为 "1" 时转移.
  3>循环控制指令(短转移)
      LOOP            CX不为零时循环.
      LOOPE/LOOPZ    CX不为零且标志Z=1时循环.
      LOOPNE/LOOPNZ  CX不为零且标志Z=0时循环.
      JCXZ            CX为零时转移.
      JECXZ          ECX为零时转移.
  4>中断指令
      INT    中断指令
      INTO    溢出中断
      IRET    中断返回
  5>处理器控制指令
      HLT    处理器暂停, 直到出现中断或复位信号才继续.
      WAIT    当芯片引线TEST为高电平时使CPU进入等待状态.
      ESC    转换到外处理器.
      LOCK    封锁总线.
      NOP    空操作.
      STC    置进位标志位.
      CLC    清进位标志位.
      CMC    进位标志取反.
      STD    置方向标志位.
      CLD    清方向标志位.
      STI    置中断允许位.
      CLI    清中断允许位.
六、伪指令
───────────────────────────────────────
      DW      定义字(2字节).
      PROC    定义过程.
      ENDP    过程结束.
      SEGMENT 定义段.
      ASSUME  建立段寄存器寻址.
      ENDS    段结束.
      END    程序结束.第三节 8088 汇编跳转一、状态寄存器PSW(Program Flag)程序状态字寄存器,是一个16位寄存器,由条件码标志(flag)和控制标志构成,如下所示:

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0





OF

DF

IF

TF

SF

ZF


AF


PF


CF


条件码:
①OF(Overflow Flag)溢出标志。溢出时为1,否则置0。
②SF(Sign Flag)符号标志。结果为负时置1,否则置0.
③ZF(Zero Flag)零标志,运算结果为0时ZF位置1,否则置0.
④CF(Carry Flag)进位标志,进位时置1,否则置0.
⑤AF(Auxiliary carry Flag)辅助进位标志,记录运算时第3位(半个字节)产生的进位置。有进位时1,否则置0.
⑥PF(Parity Flag)奇偶标志。结果操作数中1的个数为偶数时置1,否则置0.控制标志位:
⑦DF(Direction Flag)方向标志,在串处理指令中控制信息的方向。
⑧IF(Interrupt Flag)中断标志。
⑨TF(Trap Flag)陷井标志。

二、 直接标志转移(8位寻址)

指令格式

机器码

测试条件

如...则转移



指令格式

机器码

测试条件

如...则转移

JC

72

C=1

有进位

JNS

79

S=0

正号

JNC

73

C=0

无进位

JO

70

O=1

有溢出

JZ/JE

74

Z=1

零/等于

JNO

71

O=0

无溢出

JNZ/JNE

75

Z=0

不为零/不等于

JP/JPE

7A

P=1

奇偶位为偶

JS

78

S=1

负号

JNP/IPO

7B

P=0

奇偶位为奇

三、间接标志转移(8位寻址)

指令格式

机器码

测试格式

如...则转移

JA/JNBE(比较无符号数)

77

C或Z=0

>  高于/不低于或等于

JAE/JNB(比较无符号数)

73

C=0

>=  高于或等于/不低于

JB/JNAE(比较无符号数)

72

C=1

<  低于/不高于或等于

JBE/JNA(比较无符号数)

76

C或Z=1

<=  低于或等于/不高于

JG/JNLE(比较带符号数)

7F

(S异或O)或Z=0

>  大于/不小于或等于

JGE/JNL(比较带符号数)

7D

S异或O=0

>=  大于或等于/不小于

JL/JNGE(比较带符号数)

7C

S异或O=1

<  小于/不大于或等于

JLE/JNG(比较带符号数)

7E

(S异或O)或Z=1

<=  小于或等于/不大于

四、无条件转移指令(fisheep译 fisheep@sohu.com)
操作码伪码指令含义

EB  cb

JMP rel8相对短跳转(8位),使rel8处的代码位下一条指令

E9  cw

JMP rel16相对跳转(16位),使rel16处的代码位下一条指令

FF  /4

JMP r/m16绝对跳转(16位),下一指令地址在r/m16中给出

FF  /4

JMP r/m32绝对跳转(32位),下一指令地址在r/m32中给出

EA  cb

JMP ptr16:16远距离绝对跳转, 下一指令地址在操作数中

EA  cb

JMP ptr16:32远距离绝对跳转, 下一指令地址在操作数中

FF  /5

JMP m16:16远距离绝对跳转, 下一指令地址在内存m16:16中

FF  /5

JMP m16:32远距离绝对跳转, 下一指令地址在内存m16:32中
五、16位/32位寻址方式(fisheep译 fisheep@sohu.com)

操作码

伪码指令

跳转含义

跳转类型

跳转的条件(标志位)

0F 87  cw/cd

JA rel16/32

大于

near

(CF=0 and ZF=0)

0F 83  cw/cd

JAE rel16/32

大于等于

near

(CF=0)

0F 82  cw/cd

JB rel16/32

小于

near

(CF=1)

0F 86  cw/cd

JBE rel16/32

小于等于

near

(CF=1 or ZF=1)

0F 82  cw/cd

JC rel16/32

进位

near

(CF=1)

0F 84  cw/cd

JE rel16/32

等于

near

(ZF=1)

0F 84  cw/cd

JZ rel16/32

为0

near

(ZF=1)

0F 8F  cw/cd

JG rel16/32

大于

near

(ZF=0 and SF=OF)

0F 8D  cw/cd

JGE rel16/32

大于等于

near

(SF=OF)

0F 8C  cw/cd

JL rel16/32

小于

near

(SF<>OF)

0F 8E  cw/cd

JLE rel16/32

小于等于

near

(ZF=1 or SF<>OF)

0F 86  cw/cd

JNA rel16/32

不大于

near

(CF=1 or ZF=1)

0F 82  cw/cd

JNAE rel16/32

不大于等于

near

(CF=1)

0F 83  cw/cd

JNB rel16/32

不小于

near

(CF=0)

0F 87  cw/cd

JNBE rel16/32

不小于等于

near

(CF=0 and ZF=0)

0F 83  cw/cd

JNC rel16/32

不进位

near

(CF=0)

0F 85  cw/cd

JNE rel16/32

不等于

near

(ZF=0)

0F 8E  cw/cd

JNG rel16/32

不大于

near

(ZF=1 or SF<>OF)

0F 8C  cw/cd

JNGE rel16/32

不大于等于

near

(SF<>OF)

0F 8D  cw/cd

JNL rel16/32

不小于

near

(SF=OF)

0F 8F  cw/cd

JNLE rel16/32

不小于等于

near

(ZF=0 and SF=OF)

0F 81  cw/cd

JNO rel16/32

未溢出

near

(OF=0)

0F 8B  cw/cd

JNP rel16/32

不是偶数

near

(PF=0)

0F 89  cw/cd

JNS rel16/32

非负数

near

(SF=0)

0F 85  cw/cd

JNZ rel16/32

非零(不等于)

near

(ZF=0)

0F 80  cw/cd

JO rel16/32

溢出

near

(OF=1)

0F 8A  cw/cd

JP rel16/32

偶数

near

(PF=1)

0F 8A  cw/cd

JPE rel16/32

偶数

near

(PF=1)

0F 8B  cw/cd

JPO rel16/32

奇数

near

(PF=0)

0F 88  cw/cd

JS rel16/32

负数

near

(SF=1)

0F 84  cw/cd

JZ rel16/32

为零(等于)

near

(ZF=1)


注:一些指令操作数的含义说明:
  rel8      表示 8 位相对地址
  rel16    表示 16 位相对地址
  rel16/32  表示 16或32 位相对地址
  r/m16    表示16位寄存器
  r/m32    表示32位寄存器 第四节 浮点指令对下面的指令先做一些说明:
st(i):代表浮点寄存器,所说的出栈、入栈操作都是对st(i)的影响
src,dst,dest,op等都是指指令的操作数,src表示源操作数,dst/dest表示目的操作数
mem8,mem16,mem32,mem64,mem80等表示是内存操作数,后面的数值表示该操作数的内存位数(8位为一字节)
x <- y 表示将y的值放入x,例st(0) <- st(0) - st(1)表示将st(0)-st(1)的值放入浮点寄存器st(0)1.
数据传递和对常量的操作指令
dest<- st(0) (mem80);然后再执行一次出栈操作

指令格式指令含义执行的操作
FLD src装入实数到st(0)st(0) <- src (mem32/mem64/mem80)
FILD src装入整数到st(0)st(0) <- src (mem16/mem32/mem64)
FBLD src
装入BCD数到st(0)st(0) <- src (mem80)
FLDZ0.0装入st(0)st(0) <- 0.0
FLD11.0装入st(0)st(0) <- 1.0
FLDPIpi装入st(0)st(0) <- ?(ie, pi)
FLDL2Tlog2(10)装入st(0)st(0) <- log2(10)
FLDL2Elog2(e)装入st(0)st(0) <- log2(e)
FLDLG2log10(2)装入st(0)st(0) <- log10(2)
FLDLN2loge(2)装入st(0)st(0) <- loge(2)
FST dest保存实数st(0)destdest <- st(0) (mem32/mem64)
FSTP destdest <- st(0) (mem32/mem64/mem80);然后再执行一次出栈操作
FIST destst(0)以整数保存到destdest <- st(0) (mem32/mem64)
FISTP destdest <- st(0) (mem16/mem32/mem64);然后再执行一次出栈操作
FBST destst(0)BCD保存到destdest <- st(0) (mem80)
FBSTP dest


2.比较指令
指令格式指令含义执行的操作
FCOM实数比较将标志位设置为 st(0) - st(1) 的结果标志位
FCOM op实数比较将标志位设置为 st(0) - op (mem32/mem64)的结果标志位
FICOM op和整数比较Flags值设置为st(0)-op 的结果op (mem16/mem32)
FICOMP op和整数比较st(0)op比较op(mem16/mem32)后;再执行一次出栈操作
FTST
零检测
st(0)0.0比较
FUCOM st(i)
比较st(0) st(i)
[486]
FUCOMP st(i)
比较st(0) st(i),并且执行一次出栈操作
FUCOMPP st(i)
比较st(0) st(i),并且执行两次出栈操作
FXAM
Examine: Eyeball st(0) (set condition codes)
3.运算指令
指令格式指令含义执行的操作
加法
FADD加实数st(0) <-st(0) + st(1)
FADD srcst(0) <-st(0) + src (mem32/mem64)
FADD st(i),stst(i) <- st(i) + st(0)
FADDP st(i),st
st(i) <- st(i) + st(0);然后执行一次出栈操作
FIADD src
加上一个整数st(0) <-st(0) + src (mem16/mem32)
减法
FSUB减去一个实数st(0) <- st(0) - st(1)
FSUB srcst(0) <-st(0) - src (reg/mem)
FSUB st(i),stst(i) <-st(i) - st(0)
FSUBP st(i),stst(i) <-st(i) - st(0),然后执行一次出栈操作
FSUBR st(i),st用一个实数来减st(0) <- st(i) - st(0)
FSUBRP st(i),stst(0) <- st(i) - st(0),然后执行一次出栈操作
FISUB src减去一个整数st(0) <- st(0) - src (mem16/mem32)
FISUBR src用一个整数来减st(0) <- src - st(0) (mem16/mem32)
乘法
FMUL乘上一个实数st(0) <- st(0) * st(1)
FMUL st(i)st(0) <- st(0) * st(i)
FMUL st(i),stst(i) <- st(0) * st(i)
FMULP st(i),stst(i) <- st(0) * st(i),然后执行一次出栈操作
FIMUL src乘上一个整数st(0) <- st(0) * src (mem16/mem32)
除法
FDIV
除以一个实数st(0) <-st(0) /st(1)
FDIV st(i)st(0) <- st(0) /t(i)
FDIV st(i),stst(i) <-st(0) /st(i)
FDIVP st(i),stst(i) <-st(0) /st(i),然后执行一次出栈操作
FIDIV src
除以一个整数st(0) <- st(0) /src (mem16/mem32)
FDIVR st(i),st用实数除st(0) <- st(i) /st(0)
FDIVRP st(i),stFDIVRP st(i),st
FIDIVR src
用整数除st(0) <- src /st(0) (mem16/mem32)
FSQRT平方根st(0) <- sqrt st(0)
FSCALE2st(0)次方st(0) <- 2 ^ st(0)
FXTRACTExtract exponent:st(0) <-exponent of st(0); and gets pushedst(0) <-significand of st(0)
FPREM
取余数st(0) <-st(0) MOD st(1)
FPREM1取余数(IEEE),同FPREM,但是使用IEEE标准[486]
FRNDINT
取整(四舍五入)st(0) <- INT( st(0) ); depends on RC flag
FABS求绝对值st(0) <- ABS( st(0) ); removes sign
FCHS改变符号位(求负数)st(0) <-st(0)
F2XM1计算(2 ^ x)-1
st(0)
<- (2 ^ st(0)) - 1
FYL2X
计算Y * log2(X)st(0)Yst(1)X;将st(0)st(1)变为st(0) * log2( st(1) )的值
FCOS余弦函数Cosst(0) <- COS( st(0) )
FPTAN正切函数tanst(0) <- TAN( st(0) )
FPATAN反正切函数arctanst(0) <- ATAN( st(0) )
FSIN正弦函数sinst(0) <- SIN( st(0) )
FSINCOSsincos函数st(0) <-SIN( st(0) ),并且压入st(1)st(0) <- COS( st(0) )
FYL2XP1
计算Y * log2(X+1)st(0)Y st(1)X
st(0)st(1)变为st(0) * log2( st(1)+1 )的值
处理器控制指令
FINIT初始化FPU
FSTSW AX保存状态字的值到AXAX<- MSW
FSTSW dest保存状态字的值到destdest<-MSW (mem16)
FLDCW srcsrc装入FPU的控制字FPU CW <-src (mem16)
FSTCW destFPU的控制字保存到destdest<- FPU CW
FCLEX
清除异常
FSTENV dest保存环境到内存地址dest
保存状态字、控制字、标志字和异常指针的值
FLDENV src从内存地址src处装入保存的环境
FSAVE dest保存FPU的状态到dest 94字节
FRSTOR srcsrc处装入由FSAVE保存的FPU状态
FINCSTP增加FPU的栈指针值st(6) <-st(5); st(5) <-st(4),...,st(0) <-?
FDECSTP减少FPU的栈指针值st(0) <-st(1); st(1) <-st(2),...,st(7) <-?
FFREE st(i)标志寄存器st(i)未被使用
FNOP
空操作,等同CPUnopst(0) <-st(0)
WAIT/FWAIT同步FPUCPU:停止CPU的运行,直到FPU完成当前操作码
FXCH交换指令,交换st(0)st(1)的值st(0) <-st(1)st(1) <- st(0)

 

dest<- st(0) (mem80);然后再执行一次出栈操作

 

第五节 分析技术

在进行软件的破解、解密以及计算机病毒分析工作中,一个首要的问题是对软件及病毒进行分析。这些软件都是机器代码程序,对于它们分析必须使用静态或动态调试工具,分析跟踪其汇编代码。

一、从软件使用说明和操作中分析软件

欲破解一软件,首先应该先用用这软件,了解一下功能是否有限制,最好阅读一下软件的说明或手册,特别是自己所关心的关键部分的使用说明,这样也许能够找点线索。

二、静态反汇编

 所谓静态分析即从反汇编出来的程序清单上分析,从提示信息入手进行分析。目前,大多数软件在设计时,都采用了人机对话方式。所谓人机对话,即在软件运行过程中,需要由用户选择的地方,软件即显示相应的提示信息,并等待用户按键选择。而在执行完某一段程序之后,便显示一串提示信息,以反映该段程序运行后的状态,是正常运行,还是出现错误,或者提示用户进行下一步工作的帮助信息。为此,如果我们对静态反汇编出来的程序清单进行阅读,可了解软件的编程思路,以便顺利破解。 常用的静态分析工具是W32DASM、IDA和HIEW等。

三、动态跟踪分析

 虽然从静态上可以了解程序的思路,但是并不可能真正了解地了解软件的细节,如静态分析找不出线索,就要动态分析程序,另外,碰到压缩程序,静态分析也无能为力了,只能动态分析了。所谓动态分析是利用SOFTICE或TRW2000一步一步地单步执行软件。为什么要对软件进行动态分析呢?这主要是因为:
1、许多软件在整体上完成的功能,一般要分解成若干模块来完成,而且后一模块在执行时,往往需要使用其前一模块处理的结果,这一结果我们把它叫中间结果。如果我们只对软件本身进行静态地分析,一般是很难分析出这些中间结果的。而只有通过跟踪执行前一模块,才能看到这些结果。另外,在程序的运行过程中,往往会在某一地方出现许多分支和转移,不同的分支和转移往往需要不同的条件,而这些条件一般是由运行该分支之前的程序来产生的。如果想知道程序运行到该分支的地方时,去底走向哪一分支,不进行动态地跟踪和分析是不得而知的。

2、有许多软件在运行时,其最初执行的一段程序往往需要对该软件的后面各个模块进行一些初始始化工作,而没有依赖系统的重定位。

3、有许多加密程序为了阻止非法跟踪和阅读,对执行代码的大部分内容进行了加密变换,而只有很短的一段程序是明文。加密程序运行时,采用了逐块解密,逐块执行和方法,首先运行最初的一段明文程序,该程序在运行过程中,不仅要完成阻止跟踪的任务,而且还要负责对下一块密码进行解密。显然仅对该软件的密码部分进行反汇编,不对该软件动态跟踪分析,是根本不可能进行解密的。

由于上述原因,在对软件静态分析不行的条件下,就要进行动态分析了。哪么如何有效地进行动态跟踪分析呢?一般来说有如下几点:

1、对软件进行粗跟踪
所谓粗跟踪,即在跟踪时要大块大块地跟踪,也就是说每次遇到调用CALL指令、重复操作指令REP.循环操作LOOP指令以及中断调用INT指令等,一般不要跟踪进去,而是根据执行结果分析该段程序的功能。

2、对关键部分进行细跟踪

 对软件进行了一定程度的粗跟踪之后,便可以获取软件中我们所关心的模块或程序段,这样就可以针对性地对该模块进行具体而详细地跟踪分析。一般情况下,对关键代码的跟踪可能要反复进行若干次才能读懂该程序,每次要把比较关键的中间结果或指令地址记录下来,这样会对下一次分析有很大的帮助。软件分析是一种比较复杂和艰苦的工作,上面的几点分析方法,只是提供了一种基本的分析方法。要积累软件分析的经验需要在实践中不断地探索和总结。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值