反汇编窗口:
作用:ollydbg在这里显示反汇编代码
在此可以进行调试
这里可以进行关闭分析
寄存器窗口:
堆栈窗口:
数据窗口:
其他窗口:
第二章:
数制系统
最常用的数制系统是二进制,十进制和十六进制。了解它们,最主要的你要知道是:
· 二进制:只有符号0和1,因此称为二进制。
· 十进制:出现10个字符(从0到9),因此称为十进制。
· 十六进制:从0到F(0-9,A,B,C,D,E和F,总共16个字符)。
通常,除非另有说明,当我们提及某一具体数字时都将其认作十六进制。我们不使用将数值从一种数制转换为其它数制的令人不太愉快的数学公式。当前,Cracker们一般使用Windows自带的计算器,它将更加快捷和容易使用,以避免繁冗的工作。
堆栈是什么?它是内存的一块区域,用于短暂存储数据,这些数据稍后不久就要恢复取出。就像在桌上放一叠信件或纸牌,最新的信件或纸牌都是放在最顶部,如果一张张地取走信件或纸牌,总会从最上面的开始取。
第三章:
什么是寄存器,有什么作用
寄存器用来做什么,什么是寄存器?处理器在执行程序时需要一个助手。当执行一条指令时,例如将两个内存单元中存放的内容相加,处理器需要先把其中一个的内容置入寄存器,然后再把另一个内容置入,这是使用寄存器的一个例子(寄存器是CPU内部的高速存储单元,访问速度比常规内存快很多。)
1.ESP指向堆栈最顶端的地址,现在来看一下这个CrueHead'a CrackMe
2.
EIP – 另一个非常重要的寄存器,它指向当前将要执行的指令。
(F7是切换指令);
在这里,显示有EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI和EIP等
它们都被称为32位寄存器。
什么是标志寄存器
就像我们在第一章看到的,在OllyDbg寄存器信息的下方显示的就是标志寄存器。
1)O标志(溢出标志)溢出标志在当操作改变了符号位,返回错误值时被设置(译注4)。看一下以下在OllyDbg中的例子,同样使用CrueHead'a的CrackMe。
我们按照前面讲述的方法将EAX的值改为7FFFFFFF,即最大的正数。
2)A标志(辅助进位标志)完成操作后,用其它的某种形式对其进行记录。目前我们不需要关心此标志。
3)P标志(奇偶标志)
如果指令的结果用二进制表示,该二进制数中的1的总个数为偶数时,P标志被设置。例如:1010,1100,1111000.
4)Z标志(零标志)
这是在Cracking过程中最著名最有用的一个标志。当运算产生的结果为0时被设置。
5)S标志(符号标志)
这个标志在运算结果为负时设置为1。来看一下它是如何运作的,改变EAX的数值为FFFFFFF8,它等于十进制-8
6)C标志进位标志
(无符号运算的结果)在超过最大数值时设置,可能是寄存器的值,例如,将EAX设为FFFFFFFF,然后加1,我们会看到,进位标志位设为1。
第四章:
NOP(无操作)
运行这条指令不会对寄存器,内存以及堆栈造成任何影响,英文单词的意思是”无操作”,也就是说,它没有特殊的用途。例如,你用一个短指令来替换一个长指令的话,如果处理器没有错误,多余的空间将会被NOP填充。
PUSH
PUSH指令-将操作数压入堆栈中。我们可以看到,CrueHead'а(CrackMe的作者)的CrackMe的第一条指令就是PUSH指令。
POP
POP指令是出栈:它会取出堆栈顶部的第一个字母或者第一个值,然后存放到指定的目标地址内存单元中。例如,POP EAX从栈顶中取出第一个值存放到EAX中,随后的一个值随即变成栈顶。
PUSHAD
PUSHAD指令把所有通用寄存器的内容按一定顺序压入到堆栈中,PUSHAD也就相当于’PUSH EAX,PUSH ECX,PUSH EDX,PUSH EBX,PUSH ESP,PUSH EBP,PUSH ESI, PUSH EDI’。
POPAD
该指令与PUSHAD正好相反,它从堆栈中取值,并将它们放到相应的寄存器中。POPAD等价于“POP EDI,POP ESI,POP EBP,POP ESP,POP EBX,POP EDX,POP ECX,POP EAX”。
MOV
该指令将第二个操作数赋值给第一个操作数
第五章:
INC和DEC
这两个指令分别是执行增加和减少的操作,如果是INC指令的话,就加1,如果是DEC指令的话,就减1。
我们跟之前一样用OD打开cruehead的CrackMe。
ADD
ADD指令有两个操作数,相加后的结果存放到第一个操作数中。ADD EAX,1等价于INC EAX。ADD也将两个寄存器相加,我们可以到OD里面看一看。
MUL(无符号数的乘法)
有两种乘法,第一个种是MUL,这种是无符号数乘法,只有一个操作数,另一个操作数是EAX,结果存放到EDX:EAX中。
例如:
逻辑指令
逻辑指令有两个操作数,两操作数按位运算,并将结果存放到第一个操作数中。
AND
只有两个二进制位都为1的时候结果才为1,其他情况,结果都为0.
1 and 1 = 1
1 and 0 = 0
0 and 1 = 0
0 and 0 = 0
OR
该指令AND的不同之处在于,两位中只要有一位为1,结果就取1。
1 or 1 = 1
1 or 0 = 1
0 or 1 = 1
0 or 0 = 0
XOR
该指令时异或运算,当两位不同时取1,相同时取0。
1 xor 1 = 0
1 xor 0 = 1
0 xor 1 = 1
0 xor 0 = 0
NOT
该指令是简单的按位取反。
not 1 = 0
not 0 = 1
第六章:
CMP
该指令是比较两个操作数,实际上,它相当于SUB指令,但是相减的结构并不保存到第一个操作数中。只是根据相减的结果来改变零标志位的,当两个操作数相等的时候,零标志位置1。
JUMPS
所有的跳转指令都会指向程序将会跳转到的地址。我们在下面的列表中可以看到各种不同类型的跳转指令。
JMP – 跳转
JE, JZ – 结果为零则跳转
JNE, JNZ – 结果不为零则跳转
JS – 结果为负则跳转
JNS – 结果不为负则跳转
JP, JPE – 结果中1的个数为偶数则跳转
JNP, JNPE – 结果为1的个数为奇数则跳转
JO – 结果溢出了则跳转
JNO – 结果没有溢出则跳转
JB, JNAE – 小于则跳转 (无符号数)
JNB, JAE – 大于等于则跳转 (无符号数)
JBE, JNA – 小于等于则跳转 (无符号数)
JNBE, JA – 大于则跳转(无符号数)
JL, JNGE – 小于则跳转 (有符号数)
JNL, JGE – 大于等于则跳转 (有符号数)
JLE, JNG – 小于等于则跳转 (有符号数)
JNLE, JG – 大于则跳转(有符号数)
第七章:
call和ret
Call指令是将转移到指定的子程序处,它的操作数就是给定的地址。
第八章:
MOV ECX,15h
将计数器初始化为循环次数15h。接下来就是循环体了:
Label:
DEC ECX
该计数器每次递减1。
其实就是循环体了,循环体里面可以是任意指令。
最后,你需要添加一个判断计数器是否为0的指令以及条件跳转指令。
CMP ECX,0
JNE Label
第一次判断,计数器的值为14h,因为14h不为0,所以将继续执行循环,以此类推,直到计数器为0为止。
我们完整的来写一遍上面的循环:
XOR ECX,ECX
ADD ECX,15h
Label:
DEC ECX
;循环体
TEST ECX,ECX
JNE Label
第九章-第二十章:
普通断点
这是一个很普通的断点,我们前面章节已经使用了。在SoftIce中我们可以使用BPX命令来设置断点。OD中可以使用BP命令或者F2快捷键来设置断点。也可以再按一次F2快捷键来取消断点。
Remove:从列表中删除断点。
Disable:禁用断点但并不将断点从列表中删除。禁用时,断点并不会触发。
Edit condition:给断点设置触发条件,我们后面再来讨论。
Follow in disassembler:在反汇编窗口中显示断点。
Disable all or enable all:禁用/启用列表中的全部断点。这里没有启用的选项,因为列表中唯一的断点没有被禁用。
Copy to Clipboard:把选中断点的信息复制到剪贴板。
内存断点
内存访问断点有时候也称之为BPM,但是不要与SoftIce中的BPM弄混淆了,这二者是完全不同的。
这种类型的断点修改内存页的访问属性。当前我们设置了内存断点。任何代码访问(读,写或者执行代码)了该处代码的话,都会触发异常。
硬件断点
硬件断点(简称:HBP)是处理器的特性之一,它的工作原理我不是很了解,但是我们会用就行了,我们可以设置硬件断点使程序中断下来。
条件断点
条件断点实际上就是普通的CC断点,只不过该断点的触发需要满足设置的条件,如果满足设置的条件,那么程序就会中断下来,如果不满足条件的话,就和没有设置CC断点差不多。
条件记录断点
条件记录断点跟刚刚介绍的条件断点差不多,区别在于,我们可以通过设置该断点来记录下设置的条件的精确值。我们举个例子,我们给一个API函数设置条件记录断点,程序中有很多地方调用了这个API函数,通过该条件记录断点我们可以精确的记录程序中每处调用该API函数传递给它的内容。
Windows窗口程序至少有一个消息循环,消息循环有特定的API函数构成,最常见的是GetMessage和DispatchMessage函数,有的消息循环也会用到其他的API函数。想要深入了解Windows的消息的话,可以参考下面的链接中的教程”理解消息循环”