OllyDbg

本文通过吾爱破解论坛上提供的OllyDbg版本为例,讲解该软件的使用方法

F2对鼠标所处的位置打下断点,一般表现为鼠标所属地址位置背景变红
F3加载一个可执行程序,进行调试分析,表现为弹出打开文件框
F4执行程序到光标处
F5缩小还原当前窗口,表现为所有打开的窗口都进行缩小
F7单步步入,进入函数实现内,进步到CALL地址处
F8单步步过,越过函数实现
F9直接运行程序,遇到断点处暂停
Ctrl+F2重新运行程序到起始处,用于重新调试程序
Ctrl+F9执行到函数返回处
Alt+F9执行到用户代码处,用于快速跳出系统函数(不好用)
Ctrl+G输入十六进制地址,在反汇编或数据窗口中快速定位到该地址处

 修改数据

找到要修改数据的地址所对应的HEX数据,双击该数据,弹出对应的编辑数据对话框,去掉对"保持大小"的勾选,可向后修改数据。由于C\C++中字符串以00结尾,需要将字符串最末尾的数据修改为00。选择十六进制编码文本框,在最末尾处插入00。单击“确定”按钮。

 

 字串参考

顾名思义,就是在程序中搜索特定的字符串或者编码,对于定位操作有很大的作用

一般操作是:

鼠标右键->search for(查找)->all referenced text string(所有参考文本字串)出现以下界面

可以同过右键点击->查找查找字符串,也可以双击直接跳转到目标位置

为了看看是否还有其他的参考,可以通过右键选择查找参考(find reference to)->立即数: 

OllyDbg 显示程序的某些部分时是 不正确的,错误的将可执行代码解释为数据.这种情况,你可以在反汇编窗口中右击选择 Analysis(分析) -> Remove analysis from module(从模块中删除分析) 手动删除分析结果
高亮显示 jumps 和 calls ,你使用它可能会更为方便但我个人不 喜欢(这会有不 同的体验),右键点击,选择 选项->界面选项->代码高亮

L 图标或 View-> Log,显示日志窗口, 通过配置,可以显示 OllyDbg 启动时保存在日志窗口 的不同类型信息,也涉及条件断点的信息。如果需要将日志进行导出,则右键->记录到文件

 

E 按钮 View ->Executables 显示程序 运行使用的模块:exe,,dll,,ocx 和 其它。 

 

M 按钮或 View->Memory 显示我们的程 序映射到内存的信息,一个内存块可能 被分为几个部 分
右键点击可以搜索不同种类的字符串, 可以在访问上设置中断

T 按钮或 View->Threads 显示程序的线程窗口
W 按钮或 View-> Windows 显示程序窗口

 

H 按钮或 View-> Handles,句柄窗口 

C 按钮或 View->CPU,允许我们返回到 O llyDbg 的主窗口,CPU 窗口。
P按钮或 View->Patches,如果程序经过 了修改,这里显示修改的信息,现在我们的程序还没
有被修改过,所以为空白。

K 按钮或 View->Call stack 显示调用堆 栈的窗口信息,可以尝试反向跟踪函数的
调用顺序。
B 按钮或 View->Breakpoints 显示程序 普通断点的列表窗口,这里不显示硬件 断点和内存断点。

 

R 按钮或 View->Reference 参考窗口, 显示我们在 OllyDbg 中搜索的结果。

 

 “...”按钮或 View->Run trace 显示 RUN TRACE(RUN 跟踪)命令的结果。

 寄存器

显示有 EAX,ECX,,EDX,,EBX , ESP, EBP,,ESI,,EDI 和 EIP 等 它们都被称为 32 位寄存器。 在 OllyDbg 中,它们的内容以十六进制 显示。例如,EAX 的最小值为 00000000 ,最大值为 FFFFFFFF,用二进制表示将 是 11111111111111111111111111111111 。

 ESP 指向堆栈最顶端的地址我们看到寄存器显示了在我们的堆栈最上 方的值,打个比方,它就是一堆信件最上 方的那一 封。

EIP – 另一个非常重要的寄存器,它指 向当前将要执行的指令如果你按下 F7,那么将执行第一条指令,然后切到第二条将执行的指令。

 同样我们可以对寄存器的值进行修改,选中对应的寄存器->修改 即可

如果你要用到 EAX 寄存器的一部分,AX 是 EAX 的一部分,是 16 位寄存器,我们在 CommandBar 中 进行输入也可以看到。 ? AX(问号也可用于查询寄存器的值)
OllyDbg 可以更改寄存 器的值。我们在 EAX 上进行的一切操作同样适用于 其它寄存器:检查寄存器, 看哪一个是你想要更改的,然后右键点击 它选择 Modify。但 EIP 是唯一一个例外 的,它指向下一条将要执行的指令。 要改变头的值,需要如下操作。 EIP 指向将要执行的指令,只需简单的在 反汇编窗口中选择新的指令起始点一旦选择,例如 40101A,在其上点击鼠标右键,选择 New origin here( 汉化 版翻译为: 处为新的 EIP),EIP 就会改变为 40101A,这样,程序就将会从这条指令执行。
在 OllyDbg 寄存器信息的下方显示的就是标志寄存器我们看到,这里的标志分为 C,P,A,Z
,S,T,D 和 O。 我们还看到,它们只能是两个数字值,0 和 1。某一具体指
令的执行可以改变它们的含义。 我们一起来看看这些标志:
1) O 标志(溢出标志)溢出标志在当操作改变了符号位,返回错误值时被设置 
该标志的目的:当 指令的结果超出了它可能存取的最大值 ,将被设置
2) A 标志(辅助进位标志) 完成操作后,用其它的某种形式对其进行记录。
3) P 标志(奇偶标志) 如果指令的结果用二进制表示,该二进 制数中的的 1 的总个数为偶数时,P 标志被设置
4) Z 标志(零标志) 这是在 Cracking 过程中最著名最有用的 一个标志。当运算产生的结果为 0 时被设置。
5) S 标志(符号标志) 这个标志在运算结果为负时设置为 1。
6) C 标志进位标志( 无符号运算的结果 )在超过最大数值时 设置,可能是寄存器的值
以上的标志可以通过双击的方式进行修改。

常见汇编指令

NOP(无操作):运行这段指令不会对寄存器,内存以及堆栈造成任何影响,适当数目的nop指令可以将其指令完全替换掉;在一些情况下,如果想要对一些跳转操作进行绕过,可以直接使用nop语句进行替换

修改方式:选中指定的汇编代码,右键,选择(汇编)或者空格快捷键  可以进行修改,默认有使用nop填充的选项

 撤销指令的修改:在数据窗口或者反汇编窗口中,鼠标选中两个字节,然后单击右键,选择撤销选择修改

PUSH:push指令将操作数压入堆栈中,PUSH EAX 将保存的EAX的值压入堆栈中,同样也可以压入特定内存地址中的值

POP:指令为出栈,他会取出堆栈顶部的第一个字母或者第一个值,然后存放到指定目标地址内存单元中。例如:POP EAX从栈顶中取出第一个值放置到EAX中,随后的一个值变为栈顶

PUSHAD:把所有通用寄存器的内容按一定顺序压倒堆栈中,PUSHAD也就相当于PUSH EAX,PUSH ECX,PUSH EDX,PUSH EBX,PUSH ESP ,PUSH EBP,PUSH ESI,PUSH EDI,POP AD同理

MOV:将第二个操作数赋值给第一个操作数 MOV EAX,EBX,将EBX值赋值给EAX

MOVSX (带符号扩展的传送指令):第二个操作数可能一个寄存器也可能是内存单元,第一个操作数的位数比第二个操作数多,第二个操作数的符号位填充第一个操作数剩余部分。
LEA (取地址指令):类似于MOV指令, 但是第一个操作数是一个通用寄存器,并且第二个操作数是一个内存单元。
XCHG (交换 寄存器/内存单元 和 寄存 器) :该指令交换两个操作数的值
INC和DEC: 这两个指令分别是执行增加和减少的操作 ,如果是INC指令的话,就加1,如果是DEC指
令的话,就减1。也可以增加或者减少内存单元中的值,但是前提是我们对该内存具有写的权限
ADD : ADD指令有两个操作数,相加后的结果存放 到第一个操作数中。
ADC(带进位的加法): 在这种情况下,两个操作数的和加上进位 标志的值,结果存放到第一个操作数中。
SUB : 这个指令与ADD刚好相反-它将第一个操作 数减去第二个操作数的值存放到第一个操作数中
另外也可以使用该指令来计算寄存器的值 来寄存器的值,寄存器的值减去内存单元的值。同样需要写权限
SBB: 该指令跟ADC正好相反,它计算两个操作数 的差值,并且还要减去进位标志,结果存放到第一个操作数中。
MUL(无符号数的乘法): 有两种乘法,第一个种是MUL,这种是无符 号数乘法,只有一个操作数,另一个操作数 是EAX,结果存放到EDX:EAX中。
MUL ECX 这里是无符号数EAX,ECX相乘,结果存放到 EDX:EAX中。
NEG: 该指令的目的是将操作数的符号取反,即如果我们有一个32位的16进制数,用NEG操作以后,结果就会取反。
AND: 只有两个二进制位都为1的时候结果才为1 ,其他情况,结果都为0。
XOR: 该指令时异或运算,当两位不同时取1,相同时取0。

比较和条件跳转

我们知道,某些指令的指令会影响到标志位,最常见的就是零标志位Z。
CMP: 该指令是比较两个操作数,实际上,它相 当于SUB指令,但是相减的结构并不保存
到第一个操作数中。只是根据相减的结果 来改变零标志位的,当两个操作数相等的 时候,零标志位置1。
CMP EAX, ECX
EAX与ECX相减,它们本身的值并不改变,只是根据它们相减的结果来决定零标志位Z是否置1
条件跳转:
有两种可能性:根据标志的值来决定跳转还是不跳转。最简单的例子就是 配合JZ指令,如果Z标志被置为1,就跳转,否则,就不跳转。
如果有两个序列号做比较,例如EAX存放 的是你输入的序列号,ECX存放的是正确的序列号,该程序使用CMP指令来比较, 如果它们两个是相等的,那么零标志位Z 就置为1,后面JZ指令就会跳转到注册成功的部分。如果EAX不等于ECX的话,那么零标志位就会置0,那么就不会跳转到注
册成功的部分
TEST(逻辑比较):
该指令在一定程序上和CMP指令时类似的 ,两个数值进行与操作,结果不保存,但 是会改变相应标志位(比如说,SF,ZF,PF标志位),程序可以根据结果来决定是否跳转到相应的分支。
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 – 大于则跳转(有符号数)
JMP这是一个无条件跳转指令,即总是跳转到指定的地址。
在OD中有几个选项,可以使跳转指令突出显示
选项->界面选型->代码高亮->选择跳转

同样,由于上述的跳转方式,我们可以通过对标志位进行修改来该表跳转流程。

一般情况下,在改变程序代码后不要忘了重新分析代码。有的时候,代码分析可能是错的
Ctrl+A 右键->分析->分析代码

Call和Ret

Call指令是将转移到指定的子程序处,它的操作数就是给定的地址。例如:
Call 401362表示将转移到地址401362处, 将调用401362处的子程序,一旦子程序调用完毕就返回到Call指令的下一条语句处 。
针对于call指令,OD提供了一些有用的跟踪机制:
如果想继续跟进子程序内部,你可以按F7键跟进。如果只是想先看看子程序里面的内容再决定要不要跟进的话,可以单击鼠标右键-“跟随” 。
最后,如果我们不想继续跟踪该子程序了,我们可以按下F8键,继续执行call指令的下一条语句。
ret指令就是子程序的结束。OD中还可以写成retn。执行完ret指令以后 ,程序就会返回到call指令的下一条指令。这个程序可能包含了成千上万个堆栈操作(push,pop等),在堆栈中添加或者删除了
各种各样的值,但是当我们执行到ret指令的时候,栈顶存放的一般是子程序的返回地址。
ret指令可不仅仅用于子程序的返回,例如:
PUSH 401256
RET
这里将401256压入堆栈。下面的ret指令会将401256当做子程序的返回地址,其实 它并不是返回地址,但是执行ret指令后我们依然可以转移到401256地址处。这段代码和JMP 401256指令的功能是一样的

循环_字符串指令和寻址方式

你可以将任意通用寄存器指定为计数器(通常ECX作为计数器使用),你可以将其初始化为需要循环的次数,然后执行循环体,接着计数器递减1,判断计数器 是否为0,如果计数器不为0继续重复前面 的过程,如果计数器为0,就不继续循环了, 而直接执行下面的代码。
XOR ECX,ECX
MOV ECX,15h
将计数器初始化为循环次数15h。
Label:
DEC ECX
该计数器每次递减1。
CMP ECX,0
JNE Label
你需要添加一个判断计数器是否为0的指令以及条件跳转指令。
当我们牵扯到一些地址数据的修改时,就需要判断出数据的存放位置,此时寻址方式就非常重要
直接寻址:
这是最简单的一种寻址方式-该指令的操作数中包含一个具体的地址。
MOV DWORD PTR [00513450], ECX
MOV AX, WORD PTR [00510A25]
MOV AL, BYTE PTR [00402811]
CALL 452200
JMP 421000
不需要进行任何有关地址解析的计算,地址的值是纯数字
间接寻址:
MOV DWORD PTR[EAX], ECX
CALL EAX
JMP [EBX + 4]
要想在指令执行之前看到真实地址,需要 在该指令上下断点,断下来以后查看寄存器的值或者查看解释窗口中的提示信息。 许多程序使用间接寻址来完成一些复杂的操作,因此刚开始分析调试的时候真实地址并不会显示出来。直到我们执行到这条指令的时候,查看相应寄存器的值才能够看到真实的地址。
函数入口点:程序刚刚被加载第一条指令的地址。当用OD加载应用程序后,调试器就会停在入口点处,分析代码并且等待用户的进一步提示。
大部分(99%)的程序启动的时候都会停在入口点处。还有一些程序通过一些修改方
式让其在启动的时候不停在入口点处。这些方法就是我们常说的反调试。
Windows操作系统支持的所谓的动态链接库(扩展名为DLL文件),它们与正常的可执行文件EXE具有相同的格式。动态链接库可导出函数供其他可执行文件(EXE和DLL)调用。不是在多个可执行文件中有相同的静态副本,而是把功能放置在DLL中。如果一个功能的代码量很大,那么这样就可以缩减可执行文件的大小,更重要的是可以节省内存。Windows的基本功能:文件,内存,进程,线程,图形,声音,网络等都是在标准的动态链接库中实现的。
  • 0
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值