Copyright: Copyright (C) 2000-2004 Oleh Yuschuk


OllyDbg
OllyDbg v1.10

概述

什么是 OllyDbg

1.10版新增的功能

官方资料

法律条款

隐私和安全

注册

技术支持

关于汉化

OllyDbg 汉化

TT小组

准备工作

系统要求

安装

组件

一般原理

反汇编器

汇编器

分析器

Object 扫描器

Implib 扫描器

OllyDbg的使用

如何开始调试 	［How to start debugging session］

CPU 窗口 	［CPU window］

断点 	［Breakpoints］

数据	［Dump］

模块 	［Modules］

内存映射 	［Memory map］

窗口 	［Windows］

监视与监察器 	［Watches and inspectors］

线程 	［Threads］

调用栈 	［Call stack］

调用树 	［Call tree］

选项 	［Options］

搜索 	［Search］

自解压文件（SFX） 	［Self-extracting(SFX) files］

单步执行 	［Step-by-step execution］

Hit 跟踪 	［Hit trace］

Run 跟踪 	［Run trace］

快捷键 	［Shortcuts］

插件 	［Plugins］

技巧提示 	［Tips and tricks］

其他功能

调试独立的DLL 	［Debugging of stand-alone DLLs］

解码提示 	［Decoding hints］

表达式 	［Expressions］

自定义函数	［Custom function descriptions］

问题和致歉申明

已知的bugs和问题

致歉申明

OllyDbg � 2000-2004 Oleh Yuschuk, 保留以下所有权利：

OllyDbg（包括相关附件及这个帮助文件）中使用的商标名，产品名，注册商标以及买卖双方名称等。如若转载请保留原文的完整性。


What is OllyDbg?
什么是 OllyDbg？

OllyDbg 是一种具有可视化界面的 32 位汇编-分析调试器。它的特别之处在于可以在没有源代码时解决问题，并且可以处理其它编译器无法解决的难题。

Version 1.10 是最终的发布版本。 这个工程已经停止，我不再继续支持这个软件了。但不用担心：全新打造的 OllyDbg 2.00 不久就会面世！

运行环境： OllyDbg 可以以在任何采用奔腾处理器的 Windows 95、98、ME、NT 或是 XP（未经完全测试）操作系统中工作，但我们强烈建议您采用300-MHz以上的奔腾处理器以达到最佳效果。还有，OllyDbg 是极占内存的，因此如果您需要使用诸如追踪调试［Trace］之类的扩展功能话，建议您最好使用128MB以上的内存。

支持的处理器： OllyDbg 支持所有 80x86、奔腾、MMX、3DNOW！、Athlon 扩展指令集、SSE指令集以及相关的数据格式，但是不支持SSE2指令集。

配置： 有多达百余个（天呀！）选项用来设置 OllyDbg 的外观和运行。

数据格式： OllyDbg 的数据窗口能够显示的所有数据格式：HEX、ASCII、UNICODE、 16/32位有/无符号/HEX整数、32/64/80位浮点数、地址、反汇编（MASM、IDEAL或是HLA）、PE文件头或线程数据块。

帮助： 此文件中包含了关于理解和使用 OllyDbg 的必要的信息。如果您还有 Windows API 帮助文件的话（由于版权的问题 win32.hlp 没有包括在内），您可以将它挂在 OllyDbg 中，这样就可以快速获得系统函数的相关帮助。

启动： 您可以采用命令行的形式指定可执行文件、也可以从菜单中选择，或直接拖放到OllyDbg中，或者重新启动上一个被调试程序，或是挂接［Attach］一个正在运行的程序。OllyDbg支持即时调试。OllyDbg根本不需要安装，可直接在软盘中运行！

调试DLLs： 您可以利用OllyDbg调试标准动态链接库 (DLLs)。OllyDbg 会自动运行一个可执行程序。这个程序会加载链接库，并允许您调用链接库的输出函数。

源码级调试： OllyDbg 可以识别所有 Borland 和 Microsoft 格式的调试信息。这些信息包括源代码、函数名、标签、全局变量、静态变量。有限度的支持动态（栈）变量和结构。

代码高亮： OllyDbg 的反汇编器可以高亮不同类型的指令（如：跳转、条件跳转、入栈、出栈、调用、返回、特殊的或是无效的指令）和不同的操作数（常规［general］、FPU/SSE、段/系统寄存器、在栈或内存中的操作数，常量）。您可以定制个性化高亮方案。

线程： OllyDbg 可以调试多线程程序。因此您可以在多个线程之间转换，挂起、恢复、终止线程或是改变线程优先级。并且线程窗口将会显示每个线程的错误（就像调用 GETLASTERROR 返回一样）。

分析：OllyDbg 的最大特点之一就是分析。它会分析函数过程、循环语句、选择语句、表［tables］、常量、代码中的字符串、欺骗性指令［tricky constructs］、API调用、函数中参数的数目，import表等等。. 这些分析增加了二进制代码的可读性，减少了出错的可能性，使得我们的调试工作更加容易。

Object扫描。 OllyDbg 可以扫描Object文件/库（包括 OMF 和 COFF 格式），解压代码段［code segments］并且对其位置进行定向。

Implib扫描。 由于一些DLL文件的输出函数使用的索引号，对于人来说，这些索引号没有实际含义。如果您有与DLL相应的输入库［import library］，OllyDbg 就可以将序号转换成符号名称。

完全支持Unicode： 几乎所有支持 ASCII 的操作同时也支持 UNICODE，反之亦然。

名称： OllyDbg 可以根据 Borland 和 Microsoft 格式的调试信息，显示输入/输出符号及名称。Object 扫描器可以识别库函数。其中的名称和注释您可任意添加。如果DLL中的某些函数是通过索引号输出的，则您可通过挂接输入库［import library］来恢复原来的函数名称。不仅如此，OllyDbg还能识别大量的常量符号名（如：窗口消息、错误代码、位域［bit fields］…）并能够解码为已知的函数调用。

已知函数：OllyDbg 可以识别 2300 多个 C 和 Windows API 中的常用函数及其使用的参数。您可以添加描述信息、预定义解码。您还可以在已知函数设定 Log 断点并可以对参数进行记录。

函数调用： OllyDbg 可以在没有调试信息或函数过程使用非标准的开始部分［prolog］和结尾部分［epilog］的情况下，对递归调用进行回溯。

译者注：

004010D0   push  ebp	\

004010D1   mov   ebp,esp	|

004010D3   sub   esp,10h	|prolog

004010D6   push  ebx	 	|

004010D7   push  esi 	|

004010D8   push  edi	/

……

004010C5   pop   edi	\

004010C6   pop   esi 	|

004010C7   pop   ebx	|epilog

004010C8   mov   esp,ebp	|

004010CA   pop   ebp	|

004010CB   ret	/

栈：在栈窗口中，OllyDbg 能智能识别返回地址和栈框架［Stack Frames］。并会留下一些先前的调用。如果程序停在已知函数上，堆栈窗口将会对其参数进行分析解码。

译者注：栈框架［Stack Frames］是指一个内存区域，用于存放函数参数和局部变量。

SEH 链： 跟踪栈并显示结构化异常句柄链。全部链会显示在一个单独的窗口中。

搜索：方法真是太多了！可精确、模糊搜索命令或命令序列，搜索常数，搜索二进制、文本字符串，搜索全部命令地址，搜索全部常量或地址域［address range］，搜索所有能跳到选定地址的跳转，搜索所有调用和被调用的函数，搜索所有参考字符串，在不同模块中搜索所有调用、搜索函数名称，在全部已分配的内存中搜索二进制序列。如果搜索到多个结果，您可以对其进行快速操作。

窗口：OllyDbg 能够列出关于调试程序中的各种窗口，并且可以在窗口、类甚至选定的消息上设置断点。

资源：如果 Windows API 函数使用了参考资源串，OllyDbg 可以显示它。其支持显示的类型仅限于附带资源［attached resources］的列表、数据显示及二进制编辑、。

断点： OllyDbg 支持各种断点：一般断点、条件断点、记录断点（比如记录函数参数到记录窗口）、内存读写断点、硬件断点（只适用于ME/NT/2000）等。在Hit跟踪情况下，可以在模块的每条命令上都设置INT3断点。在使用500-MHZ处理器的 Windows NT 中，OllyDbg 每秒可以处理高达 5000 个中断。

监视与监察器：每个监视都是一个表达式并能实时显示表达式的值。您可以使用寄存器、常数、地址表达式、布尔值以及任何复杂代数运算，您还可以比较ASCII和UNICODE字符串。监察器［inspectors］是一种包含了两个的索引序列的监视［Watches］，它以二维表的形式呈现，可以对数组和结构进行解码分析。

Heap walk.：在基于Win95的系统中，OllyDbg 可以列出所有的已分配的堆。

句柄：在基于NT的系统中，OllyDbg 可列出被调试程序的所有系统句柄。

执行：.您可以单步执行、步入子程序或者步过子程序。您也可以执行程序直到函数返回时、执行到指定地址处，还可以自动执行。当程序运行时，您仍然可以操纵程序并能够查看内存、设置断点甚至修改代码。您也可以任意的暂停或重启被调试的程序。

Hit跟踪：.Hit跟踪可以显示出目前已执行的指令或函数过程，帮助您检验代码的各个分支。Hit跟踪会在指定指令到达之前设置断点，而在这个指令执行后，会把这个断点清除掉。

译者注：Hit在英文中是“击中”的意思，指令如果运行了就表示这个指令被“击中”了，没有执行的指令就是“未击中”，这样我们就很容易看出被调试程序哪些部分运行了，而哪些没有运行。

Run跟踪： Run跟踪可以单步执行程序，它会在一个很大的循环缓冲区中模拟运行程序。这个模拟器包含了除了SSE指令集以外的所以寄存器、标志、线程错误、消息、已经函数的参数。您可以保存命令，这样可以非常方便地调试自修改代码（译者注：比如加壳程序）。您可以设置条件中断，条件包括地址范围、表达式、命令。您可以将Run跟踪信息保存到一个文件中，这样就可以对比两次运行的差别。Run跟踪可以回溯分析已执行过的上百万条命令的各种细节。

统计： 统计［Profiler］可以在跟踪时计算某些指令出现的次数。因此您就能了解代码的哪一部分被频繁执行。

补丁： 内置汇编器能够自动找到修改过的代码段。二进制编辑器则会以ASCII、UNICODE或者十六进制的形式同步显示修改后的数据。修改后的数据同其它数据一样，能够进行复制-粘贴操作。原来的数据会自动备份，以便数据恢复时使用。您可以把修改的部分直接复制到执行文件中，OllyDbg会自动修正。OllyDbg还会记录以前调试过程中使用的所有补丁。您可以通过空格键实现补丁的激活或者禁止。

自解压文件： 当调试自解压文件时，您往往希望跳过解压部分，直接停在程序的原始入口点。OllyDbg的自解压跟踪将会使您实现这一目的。如果是加保护的自解压段，自解压跟踪往往会失败。而一旦OllyDbg找到了入口点，它将会跳过解压部分，并准确的到达入口点。

插件：您可以把自己的插件添加到 OllyDbg 中，以增加新的功能。OllyDbg 的插件能够访问几乎所有重要的数据的结构、能够在 OllyDbg 的窗口中添加菜单和快捷键，能够使用100个以上的插件API函数。插件API函数有详细的说明文档。默认安装已经包含了两个插件：命令行插件和书签插件。

UDD：OllyDbg 把所有程序或模块相关的信息保存至单独的文件中，并在模块重新加载时继续使用。这些信息包括了标签、注释、断点、监视、分析数据、条件等等

定制：您可以自定义字体、颜色或者高亮等等。

更多：这里介绍的功能，仅仅是 OllyDbg 的部分功能。因为其具有如此丰富的功能，以至于 OllyDbg 能成为非常方便的调试器！


What's new in version 1.08
1.10新增功能［What's new in version 1.10］

1.10版是最终版本。这个工程已经结束，我不再作开发了。但不用用担心：不久就会推出全新打造的OllyDbg 2.00！

•	最重要的新功能：

- 调试单独的DLL（不需要主程序）；

- SEH 链窗口；

- 分析提示，以帮助分析器解码不明确的代码片断；

- 支持记录断点和跟踪条件，向OllyDbg传递一个计数器，这个计数器告诉 OllyDbg 在断点执行了 n 次或在 Run 跟踪缓冲区中记录了 n 条命令以后暂停执行

- 中断时，条件记录断点可以传递给命令行文本给插件，来进行自动控制；

- 您可以标记 DLL 为系统的或者不是系统的，这在 Run 跟踪时需要跳过系统的DLL时非常有用；

- 新的安全选项“保存模块外的用户数据到主 .udd 文件”以允许您保存不属于任何特定模块和代码的断点或注释；

- Run 跟踪可以有选择的显示或记录文件修改标志；

- 参数最大串长，从1024增加到4096个字符；

- 您可以在单步跟踪中指定当前命令之后保持几条命令可见。

•	新的插件函数：

- 当被调试程序暂停时，都会调用回调用函数 ODBG_Paused(int reason,t_reg *registers) 或其的扩展版本 ODBG_Pausedex(int reasonex,int extmode,reg *registers,DEBUG_EVENT *debugevent)；

- 当应用程序因条件断点暂停，并且断点包含有传递给插件的命令，都会调用回调函数 ODBG_Plugincmd(int reason,t_reg *registers,char *cmd).

- 函数Function Settracecount(ulong count) 用于设置命令执行多少次后Run跟踪暂停；

- 函数 Settracepauseoncommands(char *cmdset) s用于指定暂停的命令集；

- 函数 Getbreakpointtypecount(ulong addr,ulong *passcount) 和 Setbreakpointext(ulong addr,ulong type,char cmd,ulong passcount) 支持传递条件断点中的计数器；

- 函数 Listmemory() 用于实现内存块列表。

•	Bug修正：

- 寄存器菜单选项“复制所有的寄存器到剪切板［Copy all registers to clipboard］”现在也可以复制 EAX了；

- 在不符合区块对齐标准地代码中，分析器和显示的代码不同步，因此单击某些行时，会选中不同的行；

- 菜单“跟进到数据窗口［Follow in Dump］” 可以显示更直观的选项，假如操作数之一隐式地指向堆栈（如PUSH）；

- OllyDbg 现在可以正确地反汇编两个Win95驱动使用的命令 VxDCall 和 VxDJump ，但汇编它们为相同的命令。在用户要使用这一伪命令的极端情况下（这是一种近乎不可能的情况）， 用户必须设置二进制位0x00008000来区分 Call 和 Jump；

- OllyDbg 接受无用命令像 REP STOS FWORD [EDI] 并将其编译为 REP STOS DWORD [EDI];

- 在新加载模块时，名称窗口有时会丢失内容；

- 汇编器支持 IMUL命令的简单形式。 IMUL reg,const （反汇编为 IMUL reg,reg,const）；

- 反汇编器使用地址大小代替操作数大小，来解码偏移大小（JMP FAR ssss:oooooooo）；

- 在反汇编窗口中的注释栏或信息面板的tab显示为一个长方形。现在Tab会显示为8个空格；

- ARPL 的操作数被解码32位大小（正确的解码为：ARPL r/m16,r16）；

- OllyDbg 现在可以在多监视配置下正常工作（但我不能肯定）；

- 2字节 INT 3 (CD 03) 处理错误；

- “句柄［Handle］”栏从线程窗口中移除。该栏错误显示 OllyDbg 指定给线程的句柄。这个句柄是对调试程序来说是无含义的；

- 分析器在处理很大的模块时会崩溃，这是由于跳转跟踪表溢出；

- 非标准模块（没有按照4096标准对齐）丢失所有用户自定义的信息，像断点或注释；

- 在尝试步过调用 ExitThread() or ExitProcess()时，OllyDbg尝试在下一个命令上设置 INT3 断点，在某些情况下，这个位置是数据；

- 在需要直接一起将Run跟踪数据到文件时，写了无效命令；

- OllyDbg 不检查.ini文件指定的.udd目录是否存在；

- 在二进种编辑后，反汇编窗口不能立即更新选择部分，这样可能只有部分命令被选中；

- OllyDbg 在接受“a.exe %.622496x”类似形式的命令行时，发生崩溃；

- 数据窗口重定位地址的下划线超出了数据内存区域；

- 但用户从一个显示位置到移动另外一个位置时，十六进制编辑窗口行为不可预知，并且有些字符显示不完整；

- FSAVE/FRSTOR 和 FLDENV/FSTENV 显示无效的操作数长度，当使用66前缀时。

- 分析器会被挂起（永远和几分钟）如果参数不足的函数被置于内存块开始处附近；

- 低级失误：“保存文件［Save file］” 窗口调用了函数 GetOpenFileName() ，而不是函数GetSaveFileName();

- ESP 将不记录到Run跟踪打开的文件中，即使相应的选项已经设置；

- 给定（无效）命令MOV QWORD [1234],0 (或许多其他的内存地址和常量之间的操作)，汇编器鲁莽地将其编译为8字节的立即数；

- 当第二次打开都引用参数行的可执行文件 (a.exe "ab" "cd")，OllyDbg会移除多余的引号（a.exe ab" "cd）。说实话，这不是我的错，而是GetPrivateProfileString()的问题！

1.09c版新增功能

•	新功能：

- 在跟踪时，反汇编窗口会尝试在当前命令之后保持1到2行可见；

- Run跟踪保存标志寄存器的高16位；

- 增加全局快捷键 Ctrl+P 用于打开补丁窗口；

- OllyDbg 两个新的输出函数： int Attachtoactiveprocess(int newprocessid) 和 HWND Createpatchwindow(void)。

•	Bug修正：

- PEXTRW 交换两个操作数（MMX 或通用寄存器）；

- 当设置为总在最上方时，某些错误消息会被主窗口隐藏；

- OllyDbg识别某些绝对正确的PE文件失败，由于节定位错误；

- LOCK 不允许在寄存器与寄存器之间操作，如果不写内存的话；

- 汇编器报告 IN 命令为无效助记符，因为扫描器将助记符与 IN 混淆了；

- 增加支持非标准的短 PE 可选头；

- 当因为硬断点暂停后，OllyDbg不能步过某个命令，如果自动硬断点允许的话；

- 太长的程序参数（大于256字节）导致OllyDbg由于缓冲区溢出而崩溃；

- 命令 LEA 带有16位地址，会报告“多余的前缀”，因为其标记了不能访问的内存；

- NEAR/FAR 高亮显示为随机颜色；

- 转换日本语UNICDOE文本到多字节时出现问题（这没有检查，因为我不会日本语）；

- 当 ModRegRM 域没有使用寄存器但不等于0时，命令SETZ, SETO 不能识别。现在如果“非标准命令形式”关闭时，OllyDbg会发出警告信息；

- OllyDbg 在编译或反汇编无效命令 MOV CS,R16 没有警告；

- 如果按Alt+F2 （或在工具栏上的 X）) 但后来没有结束被调试进程，OllyDbg仍然移除所有进程数据，使调试不可能；

- I如果执行代码大小小于节的大小或模块的大小，分析数据会在滚动代码时消失。

1.09b版新增功能：

•	新功能：

- 补丁管理器可能是最重要的新功能。OllyDbg会记住所有在调试过程中对被调试程序的所有修改。从补丁窗口，您可以快速应用补丁或恢复原始代码；

- 使用一个命令，您可以复制模块中所有修改过的地方到可执行文件；

- 一个MDI窗口可以声明为“总在最上方”。注意：为了支持这个功能，插件必须传递WM_WINDOWPOSCHANGED 到函数Tablefunction()；

- 您可以指定OllyDbg将.udd文件保持在哪里，以及插件的路径

- 如果选择的命令是一个跳转的目的地址，OllyDbg会显示“Jump from”路径；

- 在基于NT的系统下，具体句柄窗口用于显示被调试程序的所有句柄；

- 您可以不必关闭选项对话框，而直接从调试选项转换外观。

•	增强的分析功能：

- “搜索所有模块间调”包含了预测的调用；

- 选项在整个函数过程中号跟踪寄存器。以前分析器只是在线性代码段（没有跳到外面的跳转）上预测寄存器；

- 选项让分析器对未知函数的寄存器EBX, ESI 和 EDI 进行保护。如果这不是正确的，寄存器中以此的结果可能是错误的。因此选择该项请小心。

•	Bug修正：

- 在调用树中，OllyDbg 有时会忘记先前由寄存器跟踪而预测的调用；

- 有时，OllyDbg 在调试完成后，创建新的.udd文件（xxx_1, xxx_2，等等）。

1.09版新增功能：

•	新功能：

- 除了 MASM 和 IDEAL 两种反汇编模式，1.09版又增加了HLA语法（High Level Assembly，由Randall Hyde开始）。HLA是一个公开在网上的软件，可能连同源代码一起下载它 http://webster.cs.ucr.edu；

- 分析器知道有些调用不会返回，比如kernel32.ExitThread() 和 kernel32.ExitProcess() 并解释他们作为过程的中止；

- 如果某些模块的8.3格式文件名相同，OllyDbg会将其重命名为xxx_1, xxx_2 等等；

- 为了当主文件与DLL文件重名或者DLL有相同的文件名而不在同一个目录时，避免.udd混淆文件的问题，OllyDbg增加_1, _2 以视区分。这个功能在选项“安全|忽略路径和扩展名”关闭时，才有新；

- 选项同步CPU与源当面；

- OllyDbg 支持含有由BCC 5.5生成的调试信息中显示相关源代码；

- 调试引擎，现在可以步入未知命令，如SSE2指令集 （新的安全选项）；

- 选项锁定栈（也就是说栈窗口不会滚动，在跟踪时）；

- 寄存器窗口显示调试寄存器DR0..3,6,7。调试寄存器不能保存到Run跟踪中，并且您不能修改它们。警告插件作者：t_reg结构的大小已经改变！

- 从可执行文件数据中，您能够跳转到反汇编窗口或CPU数据面板的内存映像中；

- OllyDbg识别“真”（未公开）SAL 指令，但由于在Intel的文档中假定其为SHL。两个指令有相同的效果；

- 新的未公开的操作数： ICEBP (INT1)；

- 在栈中搜索地址和二进制串（现在还不是正式支持）；

- 选项保存列宽到.ini文件种；

- 增加了新的跳转。在CPU信息面板，列出了关于选择指令的所有已知的跳转并显示相关的菜单（本地或模块区调用）；

- 如果您在一个对话框中浏览分支、跳转、调用，那么当您改变选择时，反汇编窗口会跳到相应的命令。在取消后，会恢复以前选择的位置。

•	Bug修正：

- 如果您关闭调试程序（Alt+F2）， OllyDbg 现在会正确关闭所有已分配的句柄。打开句柄使得不可能再编译可执行文件；

- 在某些情况下，某些文件名包含空格，空格后面的符号会解释为命令行的参数。例如，程序奇怪的消失

- OllyDbg 可以正确的挂接任务管理器。警告：即时调试器记录格式保存在注册表的（增加引用文件名），因此新的版本不识别旧版本的即时调试器申明；

- 短（无操作数）形式的INS and OUTS 可以识别为 I/O 命令；

- 修正SSE指令集的MOVHLPS 与 MOVLPS 的无效解码。 Intel公司使得这个处理非常困难： MOVHLPS 是寄存器到寄存器，而MOVLPS 是寄存器到内存。它们的命令相同，但行为不同……

- 有时，OllyDbg会在运行“执行到返回”时发生崩溃。嗯，这是因为我忘记检查 NULL 指针的问题；

- 主模块即使放在系统目录中，还会认为其是用户代码；

- 另外，改进了其他一些低级失误。

1.08版新增功能：

OllyDbg 1.08 是继1.06版后又一个“稳定”的版本。我将把奇数版本认为是测试版，并且只在我个人的网站发表。（但您可以免费下载并再分发它们）。注册的OllyDbg用户将会得到每个新版本的通知。

如果自1.06版以后的全部更新都列在这里，会是非常非常的长。这里只列出最重要的一部份：

•	新功能：

- 通过使用dbghelp.dll实现了支持微软格式的调试信息。这包括CodeView, COFF, PDB  SYM 格式以及（希望）将来会支持的其他任何格式；

- 调用栈能够嵌套，即使函数过程没有使用标准的 prologs 和 epilogs；

- 调用树可以分析每个函数过程调用的哪些函数，会被哪些函数调用。另外，调用树识别递归函数（自记直接或间接的调用自己）和纯函数（除了修改栈里的变量外，没有调用任何函数，也不修改内存）；

- 堆列表可以识别所有已分配的内存块，不幸的这这个选项不能在基于NT的系统（NT、2000、XP）下使用；

- 代码高亮。您可以高亮不同类型的命令。比如FPU/MMX/SSE、 跳转与条件跳转、入栈与出栈、调用、返回、特权、坏命令以及填充命令。选择高亮操作数，通用寄存器、FPU/SSE与段与系统寄存器、在栈中的内存操作（也是就是要通过 ESP or EBP）以及普通内存。还有有效的内存地址常量和其他的常量是不同的。您可以创建自定义的高亮方案；

- 基本窗口信息列表（窗口类、窗口函数、父窗口、窗口风格）可以显示，并且允许在窗口类、单窗口、或者选择的消息或消息组上设置断点；

- 您可以搜索所有的模块间调用，包括间接的（例如，用GetProcAddress()加载的）。还可以在一次在对某个函数的所有的调用上设置断点。命令行插件利用这个功能实现了“bpx API”命令。

•	增强的分析功能：

- 函数过程识别速度大大加快；

- 识别循环。循环的定义是一个封闭的，只有一个入口，任意多个出口的命令序列（最后一条命令是一个跳到第一条命令的跳转）。注意：入口不一定是循环的第一条命令；

- 识别Switch语句。而且，OllyDbg甚至可以尝试分析每个单独 Case 语句的含义；

- 分析器识别使用RET语句代替的JMP （但其中间不能有PUSH、 POP 或 CALL）；识别4或8字节的浮点数入栈，如：ADD ESP,-4; FSTP [DWORD SS:EBP] 以及函数的结构异常处理；

- 分析器识别参数个数变化的函数。

•	安全：

- OllyDbg 尝试恢复代码节［Code section］的大小。当PE头中代码节的偏移和大小均为0时。

- 访问包含 INT3 内存断点（读或写）以及命令CLI 在Run跟踪期间均认为是可疑；

- 如果在NT系统下为非管理员权限，OllyDbg会警告；

- 如果随OllyDbg分发的 psapi.dll 或 dbghelp.dll 版本低于系统的目录中的，OllyDbg会建议您删除本地目录中的版本。

•	罕见或未公开的命令与助记符：

- AMD特有指令：SYSCALL 和 SYSRET;

- 未公开的指令： FFREEP STn;

- 汇编器您理解新的助记符：JNAE, JAE 和 SAL.

•	表达式：

- 表达式支持数千个符号常量，像 WM_PAINT 或 O_RDONLY;

- 新的操作符“IN”可以在表达式使用，这可以非常容易的指定范围；

- 新的伪函数 WINTEXT （别名 GetWindowText）可以在表达式返回指定窗口句柄的ASCII文本。注意：这个文本会被认为是字符串常量，因此比较长度而忽略大小写；

- 修正监视窗口语法高亮错误，以及在表达式中选择定位出错。

•	其他改进：

- 栈面板识别结构异常处理链；

- 当地址既有符号名又有序号名时，符号名优先；

- 如果条件跳转不发生，则跳转变灰；

- 自动唤醒执行了 WaitMessage() 的线程；

- 统计整个模块或整个应用程序，可以选择邻近的命令为一组与每个命令单独记数；

- 数据窗口支持直接复制修改的可执行文件；

- 模块窗口显示可执行文件的版本信息；;

- 二进制搜索对话框支持10项以前搜索过的历史记录；

- 多例程窗口（像单独的数据或名称窗口）可以记住上次选择的外观（字体、颜色及滚动条）。内存和文件数据窗口可以有不同的外观；

- 执行到用户代码（快捷键：Alt+F9）允许从系统DLL返回到用户代码。在系统文件夹中的DLL默认为系统DLL；

- 可以选择分析所有的模块；

- 执行Shift+鼠标左键选择数据或代码。

•	许多修正的Bug：

- SFENCE/LFENCE/MFENCE 命令解码错误；

- FXSAVE/FXRSTOR 命令导致通用保护错误，当OllyDbg尝试解码512字节操作数时；

- 当尝试编译SETcc 汇编器报错。

- FSTSW AX 编译不正确（带有16位前缀）；

- 在参考窗口中，有时不能跟进到反汇编窗口中；

- 字体（全部）/颜色（全部）不能在CPU数据面板上工作；

- 当OllyDbg尝试关闭被调试程序因为异常而终止时，有时OllyDbg会被锁定；

- 在调试窗口按 Ctrl+G 后，窗口内容没有更新（相应的菜单，可能正常工作）；

- 在表达式中的文本常量解释错误，如符号“\\”“\n”等等；

- 还有其他一些不很重要的错误。


Tips and tricks
技巧提示［Tips and tricks］

♦	OllyDbg 可以作为二进制编辑器使用。选择视图［View］→文件［File］并选定需要查看的文件。文件不能大于剩余内存数量。

♦	假使您修改了内存中的执行文件，这时您想恢复修改的部分，但是您忘记哪里被修改了，您可以把原始文件当作备份进行加载，这样您就可以找到修改的部分了。

♦	分析前，先扫描 OBJ 文件。这时 OllyDbg 会对已知 C 函数的参数进行解码。

♦	一些表格中包含了隐藏数据。可以通过增加列宽来显示出来。

♦	所有数据窗口（包括反汇编窗口），可以通过双击显示相对的地址。

♦	您可以通过 Ctrl +↑ 或 Ctrl+↓ 对数据窗口翻动一个字节。


Apologies
致歉申明［Apologies］

"We apologize for inconveniences"

D. A.

英语不是我的母语。请原谅我犯的语法错误。如果您能将文章中出现的令人不愉快的措辞以及替代方法告诉我，我会十分感谢您的。

请原谅我在C代码中的犯的语义错误。这些错误通常会导致程序弹出非法操作窗口，这个窗口上一般都写着由于在某处内存地址处发生命令或数据问题，导致处理器发生异常。当然这只能怪我的编译器不够优秀，因为它只是原样照搬我写的代码，而不是照搬我的想法［it did literally what I wrote, not what I meant］。请您能原谅这些事情，并将发生问题的地址连同 OllyDbg 版本号以及问题的简短描述发送给我。

所有给您带来的不便之处，我都表示歉意。如果您需要一些有用的功能，请写信给我，但是不要报太高的期望。


Problems with localized versions
本地化操作系统存在的问题［Problems with localized versions of operating system］

我认为如果您运行 OllyDbg 在非英文版本的 Microsoft Windows 操作系统应该没什么问题的，但是我没有进行任何测试。OllyDbg 使用了英语（我希望您能看明白）；但是在某些情况下，OllyDbg还依赖于操作系统，像资源中的语言标识等等。结果，有时您可能看到英语与本地语言在 OllyDbg中被混合使用。如果本地文字出现乱码，请尝试使用 UNICODE 字体（Courier 或 Lucida）。

一些用户报告说 OllyDbg 不能运行在 Windows XP 的本地语言版本。但我不能够再现这种情况。


System requirements
系统最低配置［Minimal system requirements］

为了 OllyDbg 能顺利运行，您的计算机至少有以下的配置：

- 586 处理器 （推荐166 MHz 以上）

- Microsoft Windows 95 (OSR2)，Windows 98，Windows ME，Windows NT 4.0 (Service Pack 2+)，Windows 2000 或者 Windows XP（名称只用于辨别操作系统版本，完整的名称应该有注册商标的标志）

- 64 MB 物理内存（推荐128MB以上）

- 至少有 1MB 剩余硬盘空间

- 屏幕分辨率 800x600 （强烈推荐 1024x768 或更高）

- 鼠标或兼容设备（必需）

调试 Windows NT，2000，或XP下的程序时，您应该具有管理员权限。

OllyDbg 不支持对.NET应用程序的调试。

Win32s （Microsoft Windows 3.1的32位扩展操作系统）不支持所有重要的调试函数。OllyDbg不能工作于Win32s操作系统。

相关信息： 本地化操作系统存在的问题［Problems with localized versions of operating system］


Installation
安装［Installation］

OllyDbg 不需要安装。只需简单的创建一个新的文件夹，并把 Odbg110.zip 压缩包内的所有文件释放到这个文件夹内即可。如果需要的话，可以用拖拽 ollydbg.exe 到桌面的方法，创建快捷方式。

如果在 Windows NT 4.0下运行OllyDbg的话，您需要有psapi.dll这个文件。如果需要读取 Microsoft 格式（CodeView、COFF、PDB 和 SYM）的符号调试信息，您需要有 dbghelp.dll 文件。这些文件均是Microsoft发放的文件，它们都已经放入压缩包中。不过某些系统安装时已经包含了这些链接库。如果OllyDbg发现系统中已经含有更高版本的链接库，或者不需要 psapi.dll，它就会询问您是否成 OllyDbg 的文件夹中删除这些不必要的文件。

在一些 Windows 95 的老版本中并不包含 VirtualQueryEx 和 VirtualProtectEx 这两个函数。但是这两个函数对于调试非常重要。如果OllyDbg报告这个两个函数不可用。正常的调试将不可能正常进行。请升级您的操作系统。

相关信息：隐私与安全［Your privacy and security］


Support
技术支持［Support］

有限的技术支持来自网上http://home.t-online.de/home/Ollydbg。从这里您将可以下载最新修正的版本。如果想及时得到更新通知，请注册。如果您有什么问题，请发信至 Ollydbg[AT]t-online.de。通常我会在一个星期内回复。我会保留将您的信件贴到我的网站上的权利，除非您明确提出不允许。

我已经免费公开了基于GPL授权的反汇编器（不包括分析器和SSI支持）和汇编器代码（不包括SSI）的源代码。您可以从我的网站下载。

全部的源代码您也可以得到，但您需要花费一些费用。毕竟这些代码花费了我一年多的时间。代码多达32MB并有非常好的注释文档，可以方便日后的维护。这些代码非常“干净”，绝对没有包含任何第三方代码。您既可以订购全部源代码，也可以只订购其中的一部分，如反汇编器、汇编器或分析器的代码。想获得这方面的更多细节，请写信联系。

.udd的文件格式只要您需要，即可免费获得。


Registration
注册［Registration］

OllyDbg 1.10版权所有 2000-2004 Oleh Yuschuk。这不是一个免费软件。您若长期使用或者出于商业目的，您必须注册。注册是完全免费的，并且不需要您履行金融或其他方面的义务。我仅仅是想知道谁喜欢用我的软件。注册中的任何关于您的个人资料都是可选的（您可以使用您的昵称或笔名）。

如果您将 OllyDbg 同 Randall Hyde 的 HLA （高级汇编语言［High Level Assembly］）一起使用，那么您可以不必注册（当然您也可以注册）。

在注册时，您可以订阅关于这个软件的新版本信息（电子邮件）。请不要把这些信息当作垃圾邮件，因为一年绝不会超过4封，内容也不会是第三方广告。如果您不希望收到这封邮件，那么请您告诉我，我会立即将您的地址从我的数据库里删除掉。

如果您已经是 OllyDbg 的注册用户，那么您不需要再次注册这个版本。

否则，请您阅读授权协议, ，添写注册表格（register.txt） 或者从帮助文件中复制并填写以下各部分，并把它寄到 Ollydbg[AT]t-online.de。我将秘密保留您的信息，保证不会给第三个人，除非法律强迫。

             Registration form for OllyDbg v1.10

To use OllyDbg, you must agree with  all  of  the  terms  and

conditions of the accompanying License  Agreement. All  other

answers are optional.

Name      ___________________________________________________

Title     ___________________________________________________

Company   ___________________________________________________

City,state___________________________________________________

Country   ___________________________________________________

Where did you find OllyDbg __________________________________

          ___________________________________________________

Are you going to write your own plugins

          (____) Yes    (____) No    (____) Don't know

I agree with all the terms and condition of the  accompanying

License Agreement (Very important! Please mark!)

          (____) Yes    (____) No

Date of registration ________________________________________

If you want to  receive  notifications when  OllyDbg 2.00 and

subsequent versions will be  ready, please  enter your  email

address here:

_____________________________________________________________

Thank you. If you have ideas how to improve OllyDbg and  make

it easier in use, or want to have some  new  features, please

let me know. Your opinion helps me a lot!

Your first idea: ____________________________________________

_____________________________________________________________

Your second idea: ___________________________________________

_____________________________________________________________

Your third idea: ____________________________________________

_____________________________________________________________


Legal part
法律部份［Legal part］

商标信息

OllyDbg（包括相关附件及这个帮助文件）中使用的商标名，产品名，注册商标以及买卖双方名称等，仅是用于鉴别目的。

授权协议

该授权协议（以下简称“协议”）仅限于 OllyDbg 1.10 版、OllyDbg 插件开发工具包1.10版，以及相关文件（以下简称“软件”）。在使用本软件时，您必须同意遵照本协议的全部条款。

本软件分发时必须保证完整性，不需要任何形式的授权，包括明确或含蓄的；但若要用于特殊目的，则必须授权才能使用。，由于使用或错误使用该软件而造成特殊的、偶然的、间接的或其他任何损失（包括任何失去的利润或储蓄），本作者不承担任何责任，尽管作者已经尽可能的考虑过避免这种危害发生的办法。

本软件属于 Oleh Yuschuk （以下简称“作者”） 并且版权所有 (c) 2000-2004 Oleh Yuschuk。您若长期使用或者出于商业目的，您必须注册。您需要填写注册表格 并发送给做作者。如果您专门使用 Randall Hyde 的 High Level Assembly，那么您不需要注册。如果您已经是 OllyDbg的用户，那么您不需要再注册本软件。如果本软件注册给一个公司或组织，则该公司或组织的任何人都可以使用它来工作。您可以在任何存储设备上安装注册过的本软件，比如硬盘、软盘等等。并且允许有本软件的多个拷贝。

您不能够修改，反汇编，逆向本软件，除非相关法律明确允许这样做。您不能独立分发或使用本软件。您可以分发本软件，如果满足以下条件：

a)	拷贝包含所有原始文件，并保持这些文件没有任何变化；

b)	如果您其他文件（比如，插件）与本软件一起分发，他们必须明确表示这些文件不能有比本协议更多的限制条件。

c)	即使您附加了别的文件，您也不能收费（除了传播介质费用，如CD或磁盘）。

您可以开发并分发您自己的插----一种连接本软件的动态链接库并会增加本软件的功能----免费提供：

a)	您的插件不能以任何形式强迫用户注册，或对未注册的插件有功能上的限制；

b)	允许您以类似本软件的条款免费分发您的插件

c)	您不能收费（除了传播介质费用，如CD或磁盘）。

如果您希望开发商业插件，请与作者联系以获得特殊的协议。

分发包含了 PSAPI.DLL 和 DBGHELP.DLL 两个文件，他们都属于 Microsoft(R) 可再分发文件。这些文件应该放在本软件所在的文件夹内。只有在 Windows NT(R) 4.0 平台上时，您才需要 PSAPI.DLL 文件的支持。不允许您单独分发本软件中 PSAPI.DLL 和/或 DBGHELP.DLL 文件。

本协议仅适用于当前的 OllyDbg 1.10 版和 OllyDbg 插件开发包。其他版本都有各自适用的许可协议。

公平使用

许多软件制作商明确不允许您尝试反汇编、逆向工程或修改他们程序。这个限制同样适用于您的应用程序所使用的第三方动态链接库，包括系统链接库。如果您有任何疑问，请联系版权的拥有者。这里所有的“公平使用”条款可能会让人误解。您可能需要与律师一起讨论这是否适用于您的情况。请不要将OllyDbg用于非法目的！


Your privacy and security
隐私与安全［Your privacy and security］

以下声明适用于 1.00-110 之间的全部版本，以及我在网上（“原始的 OllyDbg”）更新的相应文档（包括 OllyDbg.exe及其支持文件）。该声明不适用于任何第三方插件。

我保证原始的OllyDbg：

- 没有监视除被调试程序以外的进程，没有网络客户端或服务端的行为，不会以任何手段（除非用户自己指定远程文件）发送任何数据到其他计算机中，也不会有任何的特洛伊木马行为；

- 既不读取也不修改系统注册表，除非您明确要求。并且需要修改的注册表键也仅限于以下6个：

HKEY_CLASSES_ROOT\exefile\shell\Open with OllyDbg

HKEY_CLASSES_ROOT\exefile\shell\Open with OllyDbg\command

HKEY_CLASSES_ROOT\dllfile\shell\Open with OllyDbg

HKEY_CLASSES_ROOT\dllfile\shell\Open with OllyDbg\command

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug\Debugger HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug\Auto

- 不会在系统目录内创建，重写或修改任何文件；

- 不会在任何计算机上修改任何可执行文件或DLL，包括OllyDbg本身，除非您明确要求；

- 仅在您明确要求时（除了保存了文件历史的ollydbg.ini和带有调试信息的*.udd文件），才会记录您的调试活动。甚至我可以保证没有您的允许，OllyDbg创建或修改的文件将仅限于自己的目录；

- 最后（当然还有很多没有提到），不包含任何显示或隐藏的“警告”框，以强迫您注册这个共享软件，也不会在某个时间后限制 OllyDbg 的某些功能。

如果您需要相关的 OllyDbg 插件也有类似的隐私与安全声明，请与相关插件的作者联系。我对任何第三方插件不负责任。因为插件 bookmark.dll 是免费发放的，我对此插件出现的问题也不负责任，除非您是直接从我的网站下载的。

小心病毒。 尽管我已经使用了多种扫描器对原始文档进行检查，但请您在分发OllyDbg 时不要假定它不会含有病毒，或是假定它不会是伪装成OllyDbg 或支持程序样子的特洛伊木马。对于附在压缩包内的任何木马和病毒或者第三方修改的 OllyDbg，对您的机器造成的任何破坏，我均不负责任。


General principles
一般原理［General principles］

我希望您能对80x86系列处理器的内部结构有所了解，同时具有一定的编写汇编程序的能力。对于Microsoft Windows方面的知识，您也要熟悉。

OllyDbg是运行在Windows 95、Windows 98、Windows ME、Windows NT 和 Windows 2000系统下的一个单进程、多线程的分析代码级调试工具。它可以调试PE格式的执行文件及动态链接库，并可以对其打补丁。“代码级”意味着您可以直接与比特、字节或处理器指令打交道。OllyDbg 仅使用已公开的 Win32 API 函数，因此它可以在所有 Windows 操作系统及后继版本中使用。但是由于我没有对 XP 系统进行彻底测试，因此不能保证 OllyDbg 功能的充分发挥。注意：OllyDbg 不支持对 .NET 程序的调试。

OllyDbg不是面向编译器的。它没有特别的规则规定必须是哪一个编译器产生的代码。因此，OllyDbg可以非常好的处理通过编译器生成的代码，或是直接用汇编写入的代码。

OllyDbg可以并行调试程序。您无须暂停执行程序，就可以浏览代码和数据，设置断点、停止或恢复线程，甚至直接修改内存。（这可以视为一种软件调试的模式，与之相对的硬件模式则是当进程在运行时调试器被阻滞，反之亦然）。假使所需的操作比较复杂，OllyDbg会让进程终止一小段时间，但是这种暂停对于用户来说是透明的。

有时进程会发生非法操作。您可以把OllyDbg设置成即时［just-in-time］调试器，它会挂接出错程序，并停在程序产生异常的地方。

通过OllyDbg，您可以调试单独的DLL［standalone DLLs］文件。操作系统不能直接运行 DLL 文件，因此 OllyDbg 将一个可以加载 DLL 的小程序压缩到资源里，这个程序允许您调用最多10个参数的输出函数。

OllyDbg是完全面向模块[module-oriented]的。模块［Module］包括可执行文件（扩展名通常为.EXE）和在启动时加载或需要时动态加载的动态链接库（扩展名通常为.DLL）。在调试期间，您可以设置断点［breakpoints］、定义新的标签［labels］、注释［comment］汇编指令，当某个模块从内存中卸载［unload］时，调试器会把这些信息保存在文件中，文件名就是模块的名称，扩展名为.UDD（表示 用户自定义文件［User-Defined Data］）当OllyDbg下一次加载该模块时，它会自动恢复所有的调试信息，而不管是哪一个程序使用这个模块。假设您正在调试程序Myprog1，这个程序使用了Mydll。您在 Mydll 中设置了一些断点，然后您开始调试Myprog2，这个程序同样使用了Mydll。这时您会发现，所有 Mydll 中的断点依然存在，即使 Mydll 加载到不同的位置！

一些调试器把被调试进程的内存当作一个单一的（并且大部分是空的）大小为2 ^32字节的区域。OllyDbg采用了与之不同的技术：在这里，内存由许多独立的块组成，任何对内存内容的操作都被限制在各自的块内。在大多数情况下，这种方式工作得很好并且方便了调试。但是，如果模块包含好几个可执行段［executable sections］，您将不能一次看到全部代码，然而这种情况是非常少见的。

OllyDbg 是一个很占用内存的程序［memory-hungry application］。它在启动时就需要 3 MB，并且当您第一次装载被调试的程序时还需要一到两兆的内存。每一次的分析、备份、跟踪或者文件数据显示都需要占用一定的内存。因此当您调试一个很大的项目，发现程序管理器显示有 40 或 60 兆内存被占用时，请不要惊慌。

为了有效地调试一些不带源码的程序，您必须首先理解它是如何工作的。OllyDbg 包含的大量特性可以使这种理解变得非常容易。

首先，OllyDbg包含一个内置的代码分析器。分析器遍历整个代码，分出指令和数据，识别出不同的数据类型和过程，分析出标准API函数（最常用的大约有1900个）的参数并且试着猜出未知函数的参数数目。您也可以加入自己的函数说明［your own function descriptions］。它标记出程序入口点和跳转目的地，识别出跳转表［table-driven switches］和指向字符串的指针，加入一些注释，甚至标示出跳转的方向等等。在分析结果的基础上，调用树［call tree］显示哪些函数被指定过程调用（直接或间接）并且识别出递归调用、系统调用和叶子过程［leaf procedures］。如果需要的话，您可以设置解码提示［decoding hints］来帮助分析器解析那些不明确的代码或数据。

OllyDbg还包含Object扫描器［Object Scanner］。如果您有库文件［libraries］或目标文件［object files］，扫描器会在被调试的程序中定位这些库函数。在全部函数调用中，对标准函数的调用占很重要的一部分（据我估计可达70%）。如果您知道正要被调用的函数的功能，您就不必把注意力集中在这个函数上，可以简单地单步步过［step over］这个call。分析器知道400多个标准C函数，比如fopen和memcpy。然而我必须承认当前版本的OllyDbg不能定位很短的函数（比一个return命令多不了多少的）或相似的函数（只在重定位上有不同）。

Object扫描器[Object scanner]也能够识别输入库[import libraries]。如果某个DLL是按序号输出的，您不会看到函数名，只会发现一堆无意义的神秘数字。这种DLL的开发者通常会提供一个输入库来实现函数符号名与序号间的对应。让OllyDbg使用这个输入库，它就会恢复原始的函数符号名。

面向对象的语言（如C++），使用了一种叫做名称修饰［name mangling］的技术，把函数类型和参数都加入函数名中。OllyDbg 可以解码［demangle］这种函数名，使程序更易读。

译者注：C++的名称修饰是编译器将函数的名称转变成为一个唯一的字符串的过程，这个字符串会对函数的类、其命名空间、其参数表，以及其他等等进行编码。C++的名称修饰适用于静态成员函数，也适用于非静态成员函数。静态函数的名称修饰的一个好处之一，是能够在不同的类里使用同一个名称来声明两个或者更多的静态成员函数----而不会发生名称上的冲突。

OllyDbg完全支持 UNICODE，几乎所有对 ASCII 字符串的操作都可以同样应用于 UNICODE。

汇编指令都是很相似的。您经常会搞不清自己是不是已经跟踪过某一段代码。在 OllyDbg 中您可以加入自己的标签［labels］和注释［comments］。这些极大地方便了调试。注意一旦您注释了某个DLL，以后每次加载这个DLL时，注释和标签都有效----尽管您在调试不同的程序。

OllyDbg可以跟踪标准的栈帧［stack frames］（由PUSH EBP; MOV EBP,ESP所创建的）。现代编译器有禁止产生标准栈框架的选项，在这种情况下分配栈［stack walk］是不可能的。当程序运行到已知的函数时，栈窗口［stack window］解析它的参数，调用栈［Call stack］窗口显示到达当前位置所调用函数的序列。

现代的面向对象应用程序广泛地使用了一种叫做结构化异常处理［Structured Exception Handling,SHE］的技术。SHE窗口［SEH window］ 可以显示异常处理链。

多种不同的搜索［search］选项可以让您找到二进制代码或数据、命令或命令序列、常量或字符串、符号名或在 Run跟踪中的一条记录。

对于任何地址或常量，OllyDbg 可以找出参考［referencing］到该地址或常量的全部命令的列表。然后您可以在这个列表里找出对您来说是重要的参考。举例来说，某个函数可能被直接调用，或者经过编译器优化后把地址放入寄存器间接调用，或者把地址压入堆栈作为一个参数----没问题，OllyDbg 会找出所有这样的地方。它甚至能找到并列出所有和某个指定的位置有关的跳转。（真的？哦，天哪！……）

OllyDbg 支持所有标准类型的断点［breakpoints］----非条件和条件断点、内存断点（写入或访问）、硬件断点或在整个内存块上下断点（后两项功能只在Window ME,NT,2000,XP中有效）。条件表达式可以非常复杂（“当 [ESP+8] 的第 2 位被设置，并且 123456 位置处的字［word］小于10，或者 EAX 指向一个以“ABC”开头的 UNICODE 字串，但跳过前10次断点而在第11次中断”）。您可以设定一条或多条指令，当程序暂停时由OllyDbg传递给插件插件［plugins］。除了暂停，您还可以记录某个表达式的值（可以带有简短的说明），或者记录 OllyDbg 已知的函数的参数。在Athlon 2600+、Windows2000 环境下，OllyDbg 可以每秒处理多达 25000 个条件断点。

另一个有用的特性是跟踪。OllyDbg 支持两种方式的跟踪：hit和run。在第一种情况下，它对指定范围内的每条指令上设置断点（比如在全部可执行代码中）。当到达设断的指令后，OllyDbg 清除断点并且把该指令标记为hit。这种方法可以用来检测某段代码是否被执行。Hit跟踪速度惊人的快，在一个很短时间的启动后程序几乎达到了全速（译者注：这应该是与不进行调试时速度相比而言）。因为INT3断点可能对数据有灾难性的影响，所以我建议不要使用模糊识别过程。当代码没有被分析时Hit跟踪是不可以使用的。

Run跟踪［Run trace］ 是一步一步地执行程序，同时记录精确的运行历史和所有寄存器的内容、已知的参数和可选的指令（当代码是自修改时会有帮助）。当然，这需要大量的内存（每个指令需要15至50个字节，取决于调试的模式）但是可以精确地回溯和分析。您可以只在选定的一段代码甚至是一条指令中进行Run跟踪，或者您可以跳过无关紧要的代码。对于每个地址，OllyDbg能够计算这个地址在Run跟踪日志中出现的次数，虽然会导致执行缓慢但是可以得到代码执行的统计。比如说，某命令让您在每个已识别的过程入口处进行Run跟踪，那么统计［profile］就会给您每个过程被调用的次数。在到达某条指令、某个地址范围或指令计数器达到某一数值时Run跟踪可以自动地暂停［pause］。

在多线程程序里OllyDbg可以自动管理线程［threads］，如果您单步调试或跟踪程序，它会自动恢复当前线程而挂起其它线程。如果您运行程序，OllyDbg 会恢复先前的线程状态。

您可以为内存块建立快照（叫做备份）。OllyDbg会高亮显示所有的改动。您可以把备份保存到文件或从文件中读取出来，从而发现两次运行的不同之处。您可以查看备份，搜索下一处改动，恢复全部或选定的改动。补丁管理器［Patch manager］记录了上次应用到程序中的所有补丁，在下次调试时可以再次应用它们。

您可以很容易地把您的补丁加在可执行文件上。OllyDbg 会自动进行修正。

您不能在带有 Win32 的16位 Windows 下使用 OllyDbg。这种32位扩展操作系统无法实现某些必需的调试功能。

您既不能调试 DOS 程序也不能调试16位 NE（New Executable）格式文件，我也没有打算在未来的版本中支持这些。安息吧，古老而美好的命令提示符！


How to start
如何开始调试［How to start debugging session］

最简单的方法是：运行 OllyDbg，点击菜单上的文件［File］|打开［Open］，选择您想调试的程序。如果程序需要命令行参数，您可以在对话框底部的输入栏中，输入参数或者选择以前调试时输入过的一条参数。

OllyDbg 能够调试独立的DLL［stand-alone DLLs］。在这种情况下，OllyDbg 会创建并运行一个小的应用程序来加载链接库并根据您的需要调用输出函数。

如果您想重新启动上一次调试的程序，只要按一下 Ctrl+F2（这是重启程序的快捷键），这样 OllyDbg 会以同样的参数运行这个程序。另一种做法是在菜单中选择文件［File］，从历史列表中选择程序。您也可以在 Windows 资源管理器中将可执行文件或 DLL 文件拖拽到 OllyDbg 中。

当然，您可以在 OllyDbg 启动时，运行指定带有运行参数的被调试程序。例如：您可以在桌面创建一个 OllyDbg 的快捷方式，右击并选择“属性”，在“快捷方式”中的“目标”中添加调试的程序的全路径。这样，您每次双击快捷方式时，OllyDbg 将自动运行被调试程序。注意：DLL文件不支持这种方式。

您可以把正在运行的进程挂接到 OllyDbg 中。在菜单中打开 文件［File］|挂接［Attach］，从进程列表中选择要挂接的进程。注意：在您关闭 OllyDbg 的同时，这个进程也会被关闭。不要挂接系统进程，否则可能会导致整个操作系统的崩溃。（事实上在大多数情况下，操作系统禁止您挂接敏感进程）。

OllyDbg 可以作为即时［just-in-time］调试器。这需要在系统注册表中注册。在菜单中选择选项［Options］|即时调试［Just-in-time debugging］ 并在弹出的对话框中单击按钮“设置OllyDbg为即时调试器”［Make OllyDbg just-in-time debugger］。今后，如果某个应用程序发生了非法操作，系统将提示您是否用 OllyDbg 调试这个程序。操作系统会启动 OllyDbg 并直接停在发生异常的地方。如果您选择了“挂接时不询问”［attaching without confirmation］，则在即时调试时OllyDbg不会弹出询问对话框。如果想恢复成以前的即时调试器［Restore old just-in-time debuger］，按相应的按钮即可。

另一种方法是把 OllyDbg 添加到与可执行文件关联的快捷菜单中（这个想法是 Jochen Gerster 提出的）。在主菜单中，选择选项［Options］|添加到资源管理器中［Add to Explorer］。以后您可以在所有的文件列表中，右击可执行文件或DLL，在快捷菜单中选择OllyDbg。这个功能会创建四个注册表键值：

HKEY_CLASSES_ROOT\exefile\shell\Open with OllyDbg

HKEY_CLASSES_ROOT\exefile\shell\Open with OllyDbg\command

HKEY_CLASSES_ROOT\dllfile\shell\Open with OllyDbg

HKEY_CLASSES_ROOT\dllfile\shell\Open with OllyDbg\command

OllyDbg能够调试控制台程序（基于文字的）。

OllyDbg不能调试.NET应用程序。.NET程序是由微软的中间语言这种伪指令组成的，或是on-the-fly to native �86 commands编译的。

注意：如果您运行的是Windows NT、2000 或XP操作系统，您应该拥有管理员权限以便能够调试程序。。,


Debugging of stand-alone DLLs
调试独立的DLL［Debugging of stand-alone DLLs］

动态链接库［Dynamic-link libraries］包含被其他模块调用的函数，但并身不能直接执行。为了调试DLL，OllyDbg释放并运行一个小程序，用于加载DLL并允许传递给输出函数多达10个参数。

loaddll.exe （这里是源代码）这个程序被压缩存放在资源段里。如果OllyDbg所在文件夹内没有loaddll.exe，则OllyDbg会释放这个文件。Loaddll 包含了非常大的补丁区域，您可在这个区域里存放其它的指定任务代码。如果您不在需要这些代码，请删除 loaddll.exe ，OllyDbg 会在下次释放时清除。

打开DLL，也可以直接将其从资源管理器拖放到 OllyDbg 上。OllyDbg 会询问您并将该文件的全路径作为参数传递给loaddll.exe.。然后链接库被加载并停在代码的入口（<DllEntryPoint>）。您可以设置断点，运行或跟踪启动代码，等等。在初始化完成后，应该程序会再次暂停。这次停在标签名为 Firstbp 的位置，其在立即进入主消息循环之前。

现在，您可以调用DLL函数。从主菜单选择“调试［Debug］|调用DLL输出［Call DLL export］”。这时会弹出一个对话框。由于这个对话框是无模式对话框，因此您仍然能够使用OllyDbg的全部功能，比如查看代码、数据，查看断点，修改内存等等。

选择您想调用的函数。例如我们将开始使用 USER32.DLL 里的MessageBox 函数。注意loaddll.exe 已经使用了这个链接库，因此会假定这个 DLL 已经初始化而不再调用入口。MessageBox 这个函数名是通用函数名，实事上，这个函数有处理 ASCII 的 MessageBoxA 和处理 Unicode 的MessageBoxW 两种。我们继续往下看：

在我们选择这个函数后，右边的消息框中会出现 Number of arguments: 4（有四个参数）的字样。OllyDbg 会根据函数尾部的RET 10语句来正确识别参数的数量。RET nnn 是使用PASCAL调用约定的函数的典型特征。(参数被放入栈中，第一个参数会被最后一个压入栈中，函数调用完毕后，参数会被遗弃)。大多数的 Windows API 函数都是PASCAL形式的。

下一步，我们要设定栈中参数的个数。在这个例子中，不必做进行这个操作，因为OllyDbg已经知道了MessageBoxW函数的参数数量。但是，如果您愿意的话，也可以单击左边的复选框，改变成您认为合适的参数数量

现在填写参数列表。这个对话框中支持至多10个参数. 参数可以是任何有效的表达式，而不必使用寄存器。如果操作数指向了内存，则参数右边的缓冲区窗口会显示内存中的数据。Loaddll.exe 有10个大小为1K的缓冲区，这些缓冲区被标记为Arg1 .. Arg10,，您可以方便自由的使用它们。 另外，对话框还支持两个伪变量：由loaddll.exe创建的父窗口句柄<Hwnd>， 以及loaddll的实例句柄<Hinst>。为了方便您的使用，在您第一次使用调用输出函数时，OllyDbg就已经将这两个伪变量加到了历史列表中去了。

MessageBoxW e函数需要4个参数：

•	父窗口句柄。 这里我们选择<Hwnd> ；handle of owner window. Here, we simply select <Hwnd>;

•	在消息框中UNICODE文本的地址。选择Arg2并按回车。缓冲区窗口会以16进制的格式显现内存中的缓冲区。这个缓冲区初始化全是0。点击第一个字节，并按快捷键Ctrl+E（另外, 也可以从菜单中选择“二进制［Binary］|编辑［Edit］”）。这时会出现一个对话框，在对话框中键入“Text in box”或者其他希望显示的字符串；

•	消息框标题的UNICODE文本的地址。选择Arg3并在Unicode格式的内存中写上“Box title”；

•	消息框的风格。使用常量MB_xxx进行组合.OllyDbg 可以识别这些常量。在这里我们键入：MB_OK|MB_ICONEXCLAMATION。

这里不需要寄存器参数。

现在我们准备调用输出函数。选项“在调用时隐藏［Hide on call］”意思是说，当函数运行时对话框将会从屏幕消失。当我们执行一个会运行很长时间的函数，或者设置了断点的时候，这个选项非常的有用。您也可以手动关闭对话框。当函数执行完毕后，OllyDbg会重新自动打开。“调用输出函数”对话框。选项“在调用后暂停［Pause after call］”意思是说，在执行完函数后，loaddll将会被暂停。

按“调用［Call］按钮”后，OllyDbg 会自动备份所有的内存、校验、参数、寄存器等信息。并隐藏对话框，然后调用 MessageBoxW 函数。和期望的一样，消息框在屏幕中出现了：

函数 MessageBoxW 不会修改参数。如果您调用的函数更新了内存，比如函数 GetWindowName，修改的字节将会在数据区里高亮。注意：EAX 返回值为1，表示成功。

其他的例子请访问我的网站：

 http://home.t-online.de/home/Ollydbg/Loaddll.htm.

不幸的是，您不能通过这种方式调试OllyDbg的插件，插件关联到ollydbg.exe文件，Windows系统不能在同一个应用程序里加载并运行两个可执行文件。


Source code of LOADDLL.EXE
LOADDLL.EXE

这是 loaddll.exe 的完整源代码，可以在 Borland 的 TASM32 中用以下列命令编译：

tasm32 -mx -zi -m5 loaddll.asm,,loaddll.lst

tlink32 -v- -c -S:40000 -B:400000 -Tpe -aa -m loaddll,,,import32.lib

brc32 loaddll.rc -feloaddll.exe

程序从 START 标号处开始执行，loaddll 接受命令行参数，跳过可执行文件名（必须以双引号引用），解析DLL路径并传递给 LoadLibrary。如果发生错误，它将在固定位置设置指向错误信息的指针，并以退出码0x1001退出。如果加载成功，它将建立一个简单的主窗口并停在第一个断点上（标号为Firstbp）。该断点在启动时由OllyDbg设置。

所有与 OllyDbg 的通信行为都要借助128字节的关联区域。这个区域必须在标志性短语［keyphrase］之后从0x420020地址处立即开始。区域的头几个字包含了 OllyDbg 在 loaddll.exe 中用来设置断点和参数的地址、接着是待调用函数的地址［address of function to call］、寄存器的内容、参数个数以及参数本身。其中参数不得超过10个。如果将参数是指向内存区域的指针，那么您可以使用10个大小为1K字节的数据缓冲区，名字分别为Arg1、Arg2、……、Arg10。这些参数名以及其他的一些名称将被输出并通知OllyDbg。

每当loaddll执行完主窗口循环（WINLOOP），它会检测在PROCADR处的输出的函数地址是否为0。如果是的话，loaddll首先会保存ESP和EBP的内容同时将16个0压入堆栈。这是为了避免用户指定了无效的参数个数而导致的崩溃。然后它会把参数压入堆栈并设置寄存器。在Prepatch处有16个NOP指令，您可以在这里编写补丁。如果需要更多的空间，您可以跳到Patcharea处，那里有2K字节的空间。需要注意的是，如果以 loaddll.exe 为名的文件已经存在，则 OllyDbg 不会再把 loaddll.exe 从资源中释放出来。

输出函数在 CallDLL 处被调用。这个命令后面也紧跟了16个NOP。然后程序会保存修改过的寄存器以及调用之后ESP的偏移。如果您向遵循PASCAL约定的函数提供了无效的参数个数，OllyDbg将会向您报告这一错误。最后，loaddll 恢复ESP和EBP的值，清空PROCADR并在Finished地址处的INT3指令上中断下来。到达这里后，OllyDbg就得知执行已经结束。

请将 LOADDLL.ASM 当作自由软件对待。我不反对您在自己的程序中不带版权地使用这一程序代码的部分或全部，但请勿在与 OllyDbg 无关的项目中使用 GreenBug（LOADDLL.RC）图标……我的说明就这么多了，好好享用吧！

LOADDLL.ASM:

           P586                        ; 使用32位指令！

           MODEL FLAT,PASCAL

           IDEAL                       ; 我真的很喜欢它！

           LOCALS

           PUBLICDLL WndProc,Firstbp,Prepatch,CallDLL,Finished;

           PUBLICDLL Patcharea,Endpatch

           PUBLICDLL Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7,Arg8,Arg9,Arg10

           SEGMENT _DATA1 PARA PUBLIC USE32 'DATA'

           ; 下面的文本是OllyDbg用来确认LoadDll文件正常的标志性短语［keyphrase］。

           ; 它总是被加载到固定地址00420000处。 Never change! Note

           ; 不要修改！我是怎样一个胆小鬼啊：您不能替换版权，否则这段代码无法工作！

           DB "DLL Loader (C) 2004 Oleh Yuschuk"

           ; 关联区域［Link area］。不要修改下面32个双字变量定义或顺序！

ERRMSG     DD 0                        ;指向错误信息的指针

HINST      DD 0                        ;进程实例句柄

HWND       DD 0                        ; 主窗口句柄

DLLBASE    DD 0                        ; 被加载DLL的基址或者就是零

           DD OFFSET Firstbp           ; 第一个断点的地址

           DD OFFSET Prepatch          ; 函数调用之前的补丁区地址

           DD OFFSET Arg1              ; 10个参数x1024个字节的基址

           DD OFFSET Finished          ; 函数调用后的断点地址

DUMMY      DD 4 DUP(0)                 ; 保留未作使用

PROCADR    DD 0                        ; 过程地址，从这里开始执行

REGEAX     DD 0                        ; 寄存器参数

REGECX     DD 0

REGEDX     DD 0

REGEBX     DD 0

REGESI     DD 0

REGEDI     DD 0

NARG       DD 0                        ; 压栈参数的个数

ARGLIST    DD 10 DUP(0)                ; DLL参数列表

ESPDIFF    DD 0                        ; 代码导致ESP偏移

           DD 0                        ; 保留未作使用

WCLASS     = THIS DWORD                ; 手工构造的WNDCLASS结构

           DD 0000002Bh                ; CS_HREDRAW|VREDRAW|DBLCLKS|OWNDC

           DD WndProc                  ; 窗口过程

           DD 0                        ; 类附加字节

           DD 0                        ; 窗口附加字节

WCINST     DD 0                        ; 实例句柄

WCICON     DD 0                        ; 图标

HCURS      DD 0                        ; 光标r

HBGND      DD 0                        ; 背景刷

           DD 0                        ; 无菜单

           DD CLSNAME                  ; 类名

MSG        = THIS DWORD                ; 手工构造的MSG结构

           DD 0                        ; 窗口句柄

MSGID      DD 0                        ; 消息ID

           DD 0                        ; wParam

           DD 0                        ; lParam

           DD 0                        ; 时间戳

           DD 0                        ; X 坐标

           DD 0                        ; Y 坐标

PSTRUCT    = THIS DWORD                ; 手工构造的PAINTSTRUCT结构

           DD 0                        ; HDC

           DD 0                        ; fErase

           DD 0                        ; rcPaint.left

           DD 0                        ; rcPaint.top

           DD 0                        ; rcPaint.right

           DD 0                        ; rcPaint.bottom

           DD 0                        ; fRestore

           DD 0                        ; fIncUpdate

           DB 32 DUP(0)                ; rgbReserved

ORIGESP    DD 0                        ; 函数调用前的原始ESP

ORIGEBP    DD 0                        ; 函数调用前的原始EBP

EXPESP     DD 0                        ; 调用完成后ESP的预期值

WNDNAME    DB "OllyDbg DLL Loader",0

CLSNAME    DB "LoadDLLClass",0

ICONAME    DB "MAINICON",0             ; 绿色的喝醉的虫子图标

E_NONAM    DB "Missing DLL name",0     ; 错误通知给OllyDbg

E_NODLL    DB "Unable to load DLL",0

E_NPARM    DB "Too many parameters",0

           ALIGN 16

Arg1       DB 1024 DUP (?)             ; 10个内存参数，每个大小1K

Arg2       DB 1024 DUP (?)

Arg3       DB 1024 DUP (?)

Arg4       DB 1024 DUP (?)

Arg5       DB 1024 DUP (?)

Arg6       DB 1024 DUP (?)

Arg7       DB 1024 DUP (?)

Arg8       DB 1024 DUP (?)

Arg9       DB 1024 DUP (?)

Arg10      DB 1024 DUP (?)

           ENDS _DATA1

           SEGMENT _TEXT1 PARA PUBLIC USE32 'CODE'

           EXTRN GetModuleHandleA:     PROC

           EXTRN GetCommandLineA:      PROC

           EXTRN LoadIconA:            PROC

           EXTRN LoadCursorA:          PROC

           EXTRN GetStockObject:       PROC

           EXTRN RegisterClassA:       PROC

           EXTRN CreateWindowExA:      PROC

           EXTRN DestroyWindow:        PROC

           EXTRN PostQuitMessage:      PROC

           EXTRN ShowWindow:           PROC

           EXTRN Sleep:                PROC

           EXTRN BeginPaint:           PROC

           EXTRN EndPaint:             PROC

           EXTRN DefWindowProcA:       PROC

           EXTRN LoadLibraryA:         PROC

           EXTRN PeekMessageA:         PROC

           EXTRN TranslateMessage:     PROC

           EXTRN DispatchMessageA:     PROC

           EXTRN ExitProcess:          PROC

           ; LoadDLL主窗口的窗口过程。

           PROC WndProc

           ARG LP:DWORD,WP:DWORD,MS:DWORD,HW:DWORD

           PUSH EDX

           PUSH EDI

           PUSH ESI

           MOV EAX,[MS]

           CMP EAX,0001h               ; WM_CREATE

           JE RET0

           CMP EAX,0002h               ; WM_DESTROY

           JNE @@080

             PUSH 0

             CALL PostQuitMessage

             JMP RET0

@@080:     CMP EAX,000Fh               ; WM_PAINT

           JNE @@100

             PUSH OFFSET PSTRUCT

             PUSH [HW]

             CALL BeginPaint

             PUSH OFFSET PSTRUCT

             PUSH [HW]

             CALL EndPaint

             JMP RET0

@@100:     CMP EAX,0010h               ; WM_CLOSE

           JNE @@200

             PUSH [HW]

             CALL DestroyWindow

             JMP RET0

@@200:     ; 以上没有列出的消息，传递给函数 DefWindowProc()处理。

           PUSH [LP]

           PUSH [WP]

           PUSH [MS]

           PUSH [HW]

           CALL DefWindowProcA

           JMP RETA

RET0:      XOR EAX,EAX

           JMP SHORT RETA

RET1:      MOV EAX,1

RETA:      POP ESI

           POP EDI

           POP EDX

           RET

           ENDP WndProc

START:     MOV EBP,ESP                 ; 这里开始运行

           PUSH 0

           CALL GetModuleHandleA

           MOV [DWORD DS:WCINST],EAX

           MOV [DWORD DS:HINST],EAX

           CALL GetCommandLineA        ; 引用中已包含LOADDLL的路径

           MOV ESI,EAX

           INC ESI                     ; 跳过第一个引用

@@10:        MOV AL,[BYTE DS:ESI]      ; 跳过LOADDLL.EXE的路径

             INC ESI

             OR AL,AL

             JNE @@12

               MOV [DWORD DS:ERRMSG],OFFSET E_NONAM

               JMP ERROR

@@12:        CMP AL,'"'

             JNE @@10

@@20:        MOV AL,[BYTE DS:ESI]      ; 跳过空格

             CMP AL,' '

             JNE @@30

             INC ESI

             JMP SHORT @@20

@@30:      PUSH ESI

           CALL LoadLibraryA           ; 加载DLL

           OR EAX,EAX

           JNE @@32

             MOV [DWORD DS:ERRMSG],OFFSET E_NODLL

             JMP ERROR

@@32:      MOV [DWORD DS:DLLBASE],EAX

           PUSH OFFSET ICONAME

           PUSH [DWORD DS:HINST]

           CALL LoadIconA

           MOV [DWORD DS:WCICON],EAX

           PUSH 7F88h                  ; IDC_NO

           PUSH 0                      ; 扩展资源

           CALL LoadCursorA

           MOV [DWORD DS:HCURS],EAX

           PUSH 0                      ; WHITE_BRUSH

           CALL GetStockObject

           MOV [DWORD DS:HBGND],EAX

           PUSH OFFSET WCLASS

           CALL RegisterClassA

           PUSH 0                      ; Parameters: none

           PUSH [DWORD DS:HINST]       ;实例

           PUSH 0                      ; 菜单：无

           PUSH 0                      ; 父窗口：无

           PUSH 100                    ; 宽度

           PUSH 200                    ; 高度

           PUSH 80000000h              ; CW_USEDEFAULT

           PUSH 80000000h              ; CW_USEDEFAULT

           PUSH 10CF0000h              ; WS_OVERLAPPEDWINDOW|WS_VISIBLE

           PUSH OFFSET WNDNAME         ; 窗口名

           PUSH OFFSET CLSNAME         ; 类名

           PUSH 0                      ; 无扩展风格

           CALL CreateWindowExA

           MOV [DWORD DS:HWND],EAX     ; 保存句柄

           PUSH 9                      ; SW_RESTORE

           PUSH EAX

           CALL ShowWindow

Firstbp:   NOP                         ; 第一个中断设在这里

WINLOOP:     CMP [DWORD DS:PROCADR],0  ; 需要调用南某个函数？

             JE NOCALL

               MOV [DWORD DS:ORIGESP],ESP

               MOV [DWORD DS:ORIGEBP],ESP

               PUSH 0                  ; 安全缓冲区（32字节）

               PUSH 0

               PUSH 0

               PUSH 0

               PUSH 0

               PUSH 0

               PUSH 0

               PUSH 0

               PUSH 0

               PUSH 0

               PUSH 0

               PUSH 0

               PUSH 0

               PUSH 0

               PUSH 0

               PUSH 0

               MOV ECX,[DWORD DS:NARG]

               JECXZ @@44

               CMP ECX,10

               JBE @@40

                 MOV [DWORD DS:ERRMSG],OFFSET E_NPARM

                 JMP ERROR

@@40:          MOV EAX,OFFSET ARGLIST

@@42:            PUSH [DWORD EAX]      ; 输入需要参数的个数

                 ADD EAX,4

                 LOOP @@42

@@44:          MOV [DWORD DS:EXPESP],ESP ; 返回后期望的返回值

               MOV EAX,[DWORD DS:REGEAX] ; 调整寄存器

               MOV ECX,[DWORD DS:REGECX]

               MOV EDX,[DWORD DS:REGEDX]

               MOV EBX,[DWORD DS:REGEBX]

               MOV ESI,[DWORD DS:REGESI]

               MOV EDI,[DWORD DS:REGEDI]

Prepatch:      NOP                     ; 在调用前的补丁区域

               NOP

               NOP

               NOP

               NOP

               NOP

               NOP

               NOP

               NOP

               NOP

               NOP

               NOP

               NOP

               NOP

               NOP

               NOP

CallDLL:       CALL [DWORD DS:PROCADR] ; 调用DLL函数

               NOP                     ; 调用后的补丁区域

               NOP

               NOP

               NOP

               NOP

               NOP

               NOP

               NOP

               NOP

               NOP

               NOP

               NOP

               NOP

               NOP

               NOP

               NOP

               MOV [DWORD DS:REGEAX],EAX ; 获得修改过的寄存器

               MOV [DWORD DS:REGECX],ECX

               MOV [DWORD DS:REGEDX],EDX

               MOV [DWORD DS:REGEBX],EBX

               MOV [DWORD DS:REGESI],ESI

               MOV [DWORD DS:REGEDI],EDI

               MOV EAX,ESP

               SUB EAX,[DWORD DS:EXPESP]

               MOV [DWORD DS:ESPDIFF],EAX

               MOV EBP,[DWORD DS:ORIGEBP]

               MOV ESP,[DWORD DS:ORIGESP]

               MOV [DWORD DS:PROCADR],0 ; 确认执行

               NOP

Finished:      INT 3                   ; 运行完后暂停

               NOP

NOCALL:      PUSH 0

             CALL Sleep                ; 留给其他应用程序

             PUSH 1                    ; PM_REMOVE

             PUSH 0                    ; 处理所有消息

             PUSH 0

             PUSH 0                    ; 任何窗口

             PUSH OFFSET MSG

             CALL PeekMessageA

             OR EAX,EAX

             JZ WINLOOP

             PUSH OFFSET MSG

             CALL TranslateMessage

             PUSH OFFSET MSG

             CALL DispatchMessageA

             MOV EAX,[DWORD DS:MSGID]

             CMP EAX,12h               ; WM_QUIT

             JNE WINLOOP

           PUSH 0

           CALL ExitProcess            ; 退出！

ERROR:     PUSH 00001001h              ; 特殊返回代码，菜单错误

           CALL ExitProcess            ; 发生错误

           ALIGN 4

Patcharea: DB 2047 DUP(90h)            ; 大的补丁区域(2千个 NOP 命令)

Endpatch:  NOP

           ENDS _TEXT1

           END START

LOADDLL.RC:

MAINICON ICON                          // 绿色虫子

{

 '00 00 01 00 02 00 20 20 10 00 00 00 00 00 E8 02'

 '00 00 26 00 00 00 10 10 10 00 00 00 00 00 28 01'

 '00 00 0E 03 00 00 28 00 00 00 20 00 00 00 40 00'

 '00 00 01 00 04 00 00 00 00 00 80 02 00 00 00 00'

 '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'

 '00 00 00 00 80 00 00 80 00 00 00 80 80 00 80 00'

 '00 00 80 00 80 00 80 80 00 00 80 80 80 00 C0 C0'

 'C0 00 00 00 FF 00 00 FF 00 00 00 FF FF 00 FF 00'

 '00 00 FF 00 FF 00 FF FF 00 00 FF FF FF 00 00 00'

 '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'

 '00 00 00 00 02 A0 00 00 00 00 A2 00 00 00 00 00'

 '00 00 00 00 0A 20 00 00 00 0A 2A 2A 00 00 00 00'

 '00 00 00 00 A2 A2 00 00 00 A2 A2 A2 00 00 00 00'

 '00 00 00 00 2A 2A 00 00 0A 2A 2A 2A 00 00 00 00'

 '00 00 00 00 A2 A2 00 00 A2 A2 A2 A0 00 00 00 00'

 '00 00 00 00 2A 2A 00 0A 2A 2A 2A 20 00 00 02 A2'

 '00 00 00 00 02 A2 A0 A2 A2 A2 A2 00 00 00 0A 2A'

 '2A 2A 00 00 0A 2A 2A 2A 2A 2A 20 00 00 00 02 A2'

 'A2 A2 A0 00 02 A2 A2 A2 A2 A2 00 00 00 00 0A 2A'

 '2A 2A 2A 2A 2A 2A 2A 2A 2A 00 00 00 00 00 00 A2'

 'A2 A2 A2 A2 A2 A2 A2 A2 00 00 00 00 00 00 00 00'

 '2A 2A 2A 2A 2A 2A 2A 2A 00 00 00 00 00 00 00 00'

 '00 02 A2 A2 A2 A2 A2 A2 00 00 00 00 00 00 00 00'

 '00 00 0A 2A 2A 2A 2A 2A 2A 00 00 00 00 00 00 00'

 '00 00 02 A2 A2 A2 A2 A2 A2 A2 A2 00 00 00 00 00'

 '00 00 0A 2A 2A 2A 2A 2A 2A 2A 2A 20 00 00 00 00'

 '00 00 02 A2 A2 A2 A2 A2 A2 A2 A2 A2 A2 00 00 00'

 '00 00 0A 2A 2A 2A 2A 2A 00 00 2A 2A 2A 20 00 00'

 '00 00 A2 A2 A0 A2 A2 A0 00 00 02 A2 A2 A0 00 00'

 '00 00 2A 2A 00 0A 2A 20 00 00 00 2A 2A 20 00 00'

 '00 00 00 00 00 00 A2 A0 00 00 00 00 00 00 00 00'

 '00 00 00 00 00 00 2A 20 00 00 00 00 00 00 00 00'

 '00 00 00 00 00 00 A2 A0 00 00 00 00 00 00 00 00'

 '00 2A 20 00 00 00 2A 2A 00 00 00 00 00 00 00 00'

 'A2 A2 A0 00 00 00 A2 A2 00 00 00 00 00 00 00 00'

 '2A 2A 20 00 00 00 2A 2A 00 00 00 00 00 00 00 00'

 'A2 A2 A0 00 00 00 02 A2 00 00 00 00 00 00 00 0A'

 '2A 2A 20 00 00 00 0A 2A 00 00 00 00 00 00 00 02'

 'A2 A2 00 00 00 00 00 00 00 00 00 00 00 00 00 0A'

 '2A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'

 '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF F9'

 'FF 3F FF F0 FE 0F FF F0 FC 07 FF E0 78 07 FF E0'

 '70 07 FF E0 60 0F 8F E0 40 0F 00 F0 00 1F 00 70'

 '00 3F 00 10 00 7F 00 00 00 FF 80 00 03 FF C0 00'

 '0F FF E0 00 03 FF FC 00 00 3F FF 00 00 1F FF 00'

 '00 03 FF 00 00 01 FF 00 00 00 FE 00 0F 00 FE 04'

 '0F 80 FF 0E 0F C1 FF FE 0F FF FC 7E 0F FF F0 3E'

 '07 FF E0 3E 07 FF E0 3E 07 FF C0 3F 07 FF C0 3F'

 '07 FF C0 7F 0F FF C0 FF FF FF E3 FF FF FF 28 00'

 '00 00 10 00 00 00 20 00 00 00 01 00 04 00 00 00'

 '00 00 C0 00 00 00 00 00 00 00 00 00 00 00 00 00'

 '00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 80'

 '00 00 00 80 80 00 80 00 00 00 80 00 80 00 80 80'

 '00 00 80 80 80 00 C0 C0 C0 00 00 00 FF 00 00 FF'

 '00 00 00 FF FF 00 FF 00 00 00 FF 00 FF 00 FF FF'

 '00 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00'

 '00 AA 00 0A AA 00 00 00 00 AA 00 AA AA 00 00 00'

 '00 AA 0A AA A0 00 0A AA 00 0A AA AA 00 00 0A AA'

 'AA AA AA 00 00 00 00 0A AA AA AA 00 00 00 00 00'

 '0A AA AA A0 00 00 00 00 0A AA AA AA AA 00 00 00'

 'AA AA AA 00 AA A0 00 00 00 00 A0 00 00 00 00 00'

 '00 00 A0 00 00 00 00 0A 00 00 AA 00 00 00 00 AA'

 '00 00 AA 00 00 00 00 AA 00 00 00 00 00 00 00 00'

 '00 00 00 00 00 00 FC E3 00 00 F8 41 00 00 F8 01'

 '00 00 88 03 00 00 00 07 00 00 00 0F 00 00 80 1F'

 '00 00 E0 03 00 00 F0 01 00 00 E0 00 00 00 F0 31'

 '00 00 EE 3F 00 00 86 1F 00 00 86 1F 00 00 87 3F'

 '00 00 8F FF 00 00'

}


Analysis
分析器［Analysis］

OllyDbg 整合了一个快速而强大的代码分析器。您可以从快捷菜单，或者在CPU窗口的反汇编面板中按 Ctrl+A ，或者在可执行模块中选择“分析全部模块［Analyze all modules］”，来使用它。

分析器有很高的启发性。它能区分代码和数据，标记入口和跳转目的地址，识别转换表［switch tables］，ASCII 和 UNICODE 串，定位函数过程，循环，高阶转换［high-level switches］并且能解码标准API函数的参数（示例［example］）。OllyDbg 的其他部分也广泛的使用了分析后的数据。

这是如何实现的？我将为您揭开这一神秘面纱。第一遍，OllyDbg反汇编代码段中所有可能的地址，并计算调用的每个目的地址的个数。当然，很多调用是假的，但不可能两个错误的调用都指向了相同的命令，当然如果有三个的话，就更不可能了。因此如果有三个或者更多的调用指向了相同的地址，我可以肯定的说这个地址是某个频繁使用的子程序的入口。从定位的入口出发，我继续跟踪所有的跳转和函数调用，等等。按这种方法，我可能准确定位99.9% 的命令。但是，某些字节并不在这个链条上。我再用20多种高效的启发方法（最简单的方法，比如“直接访问前64K内存是不允许的，像在MOV [0],EAX中”）来探测他们

有时，分析器在您感兴趣的地方分析错误。有两种解决方法：或者从选中的部分移除分析（快捷键退格键），这样 OllyDbg 将使用默认的解码（反汇编）方式；或者设置解码提示［decoding hints］并重新分析。注意：在某些情况下，当分析器认为您的提示是不合适的，或者有冲突，则可能忽略您的设置。

探测程序的函数过程也很简单。在分析器眼中看来，程序只是一个连绵不断的代码，从一个入口开始，可能达到（至少从理论上）所有的命令（除了NOP以及类似的用于填充间隙的命令）。您可能指定三个识别级别。严格的函数过程要求有准确的一个入口，并且至少有一个返回。在启发级别下，分析器只要求过程有一个入口。而如果您选择模糊模式，差不多连贯的代码都会被识别为单独的过程。现代编译器进行全局代码优化，有可能把一个过程分成几个部份。在这种情况下，模糊模式非常有用。但是也会误识别的机率也就更高。

同样地，循环是一个封闭的连续的命令序列，并有一个到开始处的跳转作为一个入口，还有若干个出口。循环与高级操作命令 do, while 和 for 相对应。OllyDbg 能够识别任何复杂的嵌套循环。他们会在反汇编栏［Disassembly］中用长而粗括号标记。如果入口不是循环的第一个命令，OllyDbg会用一个小三角进行标记。

为了实现一个转换［switch］, 许多编译器，读取转换变量［switch variable］到寄存器中，然后减它，像如下的代码序列：

     MOV EDX,<switch variable>

     SUB EDX,100

     JB DEFAULTCASE

     JE CASE100        ; Case 100

     DEC EDX

     JNE DEFAULTCASE

     ...               ; Case 101

这个序列可能还包含一到两阶的转换表、直接比较、优化和其他元素。如果在比较或跳转的很深处，这就很难知道哪是一个分支［Case］。OllyDbg 会帮助您，它会标记所有的分支，包括默认的，甚至尝试分析每个分支的含义，如'A'、WM_PAINT 或者 EXCEPTION_ACCESS_VIOLATION。如果命令序列没有修改寄存器（也就是仅仅由比较组成），那么这可能不是转换，而很有可能是选择嵌套：

     if (i==0) {...}

     else if (i==5) {...}

     else if (i==10) {...}

如果需要OllyDbg将选择嵌套解码成选择语句，请在分析1［Analysis1］中设置相关选项。

OllyDbg包含多达1900条常用API函数，这些都作为内部预处理资源。这个列表包含了KERNEL32, GDI32, USER32, ADVAPI32, COMDLG32, SHELL32, VERSION, SHLWAPI, COMCTL32, WINSOCK, WS2_32 和 MSVCRT。您可以添加自己的函数描述［add your own descriptions］。如果分析器遇到的调用，使用了已知的函数名（或者跳转到这样的函数），它将在调用之前立即解码PUSH命令。因此，您只需略微一看就能明白函数调用的含义。OllyDbg还包含了大约400多种的标准C函数。如果您有原始的库文件，我推荐您在分析前扫描目标文件。这样OllyDbg将能解码这些C函数的参数。

如果选项“猜测未知函数的参数个数”开启，分析器将会决定这个调用函数过程使用的长度为双字的参数个数。并且标记他们为参数1［Arg1］，参数2［ Arg2］，等等。注意：无论如何，寄存器参数是无法识别的，所以不会增加参数的数目。分析器使用了一种比较安全的方法。例如，它不能识别的没有参数的函数过程，或者该过程POP命令直接做返回前的寄存器恢复，而不销毁参数。然而，识别出来的函数参数数目通常非常高，这大大加大了代码的可读性。

分析器能够跟踪整型寄存器的内容。现代优化编译器，特别是奔腾系列，频繁地使用寄存器读取常量和地址，或使用尽量少的使用内存。如果某个常量读取到寄存器中，分析器会注意它，并尝试解码函数和其参数。分析器还能完成简单的算术计算，甚至可以跟踪压栈和出栈。

分析器不能区分不同类的名称［different kinds of names］. 。如果您将某些函数指定为已知的名称，OllyDbg将会解码所有到该地址的调用。这是几个预定义的特殊名称WinMain, DllEntryPoint and WinProc。您可能使用这些标签标记主程序、DLL的的入口以及窗口过程（注意：OllyDbg不检查用户自定义的标签是否唯一）。另外，假定预定义参数assume predefined arguments是一种更好的方法

不幸的是，没有一般规则能够做到100%的准确分析。在某些情况下，例如当模块包含了P-Code或代码段中包换了大量的数据，分析器可能将一些数据解释成代码。如果统计分析显示代码部分很可能是压缩包或者经过加密了，分析器会发出警告。如果您想使用Hit跟踪［Hit trace］，我建议您不要使用模糊分析［fuzzy analysis］，因为设置断点的地方可能正是数据部分。

自解压文件［Self-extractable files］ 通常有一个自提取器，在“正式”代码段之外。如果您选择自解压选项［SFX option］中的“扩展代码段，包含提取器［Extend code section to include self-extractor］”，OllyDbg将会扩展代码段，形式上允许分析它，并可以使用Hit跟踪［Hit］ trace和Run跟踪［Run trace］。

相关信息： Object扫描器［Object scanner］, 分析选项1［Analysis options - part 1］, 分析选项2［Analysis options - part 2］, 分析选项3［Analysis options - part 3］, 调用树［Call tree］


Decoding hints
解码提示［Decoding hints］

在某些情况下，分析器不能区分代码和数据。让我们看看下面的例子：

const char s[11] = "0123456789";

...

for (i=0x30; i<0x3a; i++) t[i-0x30]=s[i-0x30];

好的编译器将会将上面的代码优化成如下样子： e

for (i=0x30; i<0x3a; i++) (t-0x30)[i]=(s-0x30)[i];

这里t-0x30 和 s-0x30 都是常量，并编译成如下形式：

MOV AL,[BYTE s_minus_30+EBX]

MOV [BYTE t_minus_30+EBX],AL

编译器也可能将常量字符串"0123456789"插入到执行代码中。在1.10版本中，我打算用寄存器的值来决定是否的数据或代码。当遇到上面的命令，分析器将假定地址s_minus_30处包含字符数据。但事实上，可能那里是代码。

万一出现上述问题，我们应该怎么办呢？有两种办法：最快最笨的办法是：将分析错误的部分删除（快捷键：退格键），这样OllyDbg将使用默认的反汇编器进行解码。

更好的办法是使用解码提示［decoding hints］。您可以告诉OllyDbg如何解释选中的内存内容。这种方法在重新分析（Ctrl+A）时，解释依然有效。

设置提示的方法：在反汇编窗口中，选中需要修正提示的代码或数据，然后在快捷菜单中选择 分析［Analysis］|在下次分析时，将选择部分视为［During next analysis, treat selection as］。选择以下选项之一：

命令［Command］ - 第一个被选中的字节开始的有效命令。这条命令，还有所有后面的部分，直到有Jump或Return命令出现，以及含有Jump或Call命令所到达位置的部分，都会被视为命令；

字节［Byte］，

字［Word］，

双字［Doubleword］ - 选中的前1、2、4字节视为对应大小的数据；

所有选中命令［Commands］ - 全部选中部分（直到第一个无效命令）和可以到达由有效命令集组成的目的地址；

字节［Bytes］，

字［Words］，

双字［Doublewords］， - 全部选中部分以1、2、或 4字节分组；

ASCII字符串［ASCII text］，

UNICODE字符串［UNICODE text］ - 全部选中部分为ASCII 或 UNICODE 字符串；

默认（移除提示）［Default (remove hints)］ - 从选中部分中移除全面提示；

移除全部提示［Remove all hints］ - 从全部模块中移除解码提示。

OllyDbg 保存提示到.udd文件中。


Object scanner
Object扫描器［Object scanner］

扫描器将特定的目标文件或者目标库（包括OMF和COFF两种格式），提取出代码段，然后将这些段定位在当前模块的代码节［Code section］中.如果段定位好了,扫描器将从目标文件中的调试信息提取名称（也就是所谓的库标签［library labels］）。这极大的增加了代码与数据的可读性.

扫描器并不会对已识别的目标文件进行标签匹配，所以它不能识别非常小或相似的函数（比如：两个函数只是在重定位有区别）。因此要经常检查扫描器发送到登陆窗口的警告列表！

相关信息： 分析器［Analysis］, Implib扫描器［Implib scanner］


Implib scanner
Implib扫描器 ［Implib scanner］

某些DLL的输出符号仅仅是一个序号。许多符号都是井号加数字（比如：MFC42.#1003），这非常不便于理解。幸运的是，软件零售商提供了输入连接库（implibs），它与序号符号名相关。

使用implib扫描器的方法：从主菜单中选择调试［Debug］|选择输入链接库［Select import libraries］。当您加载应用程序时，OllyDbg会读取链接库并从内置表格［internal tables］中提取符号名。每次遇到序号符号，而对应的链接库已经注册到OllyDbg中时，这个序号符号会被替换。

相关信息：分析器［Analysis］，Object扫描器［Object scanner］


Breakpoints
断点［Breakpoints］

OllyDbg支持数种不同类型的断点：

- 一般断点［Ordinary breakpoint］, 将您想中断的命令的第一个字节，用一个特殊命令INT3（调试器陷阱）来替代。您可以在反汇编窗口中选中要设断点的指令行并按下 F2 键就可以设定一个此类型的断点。也可以在快捷菜单中设置。再次按下 F2 键时，断点将被删除。注意，程序将在设断指令被执行之前中断下来。

INT3断点的设置数量是没有限制的。当您关闭被调试程序或者调试器的时候，OllyDbg将自动把这些断点保存到硬盘中，永远不要试图在数据段或者指令的中间设置这种断点，如果您试图在代码段以外设置断点，OllyDbg将会警告。您可以在安全选项［Security options］中永远关闭这个提示，在某些情况下调试器会插入自带的临时INT3断点。

- 条件断点［Conditional breakpoint］ （快捷键 Shift+F2） 是一个带有条件表达式的普通INT3断点。当调试器遇到这类断点时，它将计算表达式的值，如果结果非零或者表达式无效，将暂停被调试程序，当然，由条件为假的断点引起的开销是非常高的（主要归因于操作系统的反应时间）。在Windows NT、奔腾Ⅱ/450处理器环境下OllyDbg每秒最多处理2500个条件为假的断点。条件断点的一个典型使用情况就是在Windows消息上设置断点（比如 WM_PAINT）。为此，您可以将伪变量 MSG 同适当的参数说明联合使用。如果窗口被激活，参考一下后面的消息断点描述。

- 条件记录断点 ［Conditional logging breakpoint］ （Shift+F4）是一种条件断点，每当遇到此类断点或者满足条件时，它将记录已知函数表达式或参数的值。例如，您可以在一些窗口过程函数上设置记录断点并列出对该函数的所有调用。或者只对接收到的WM_COMMAND消息标识符设断，或者对创建文件的函数（CreateFile）设断，并且记录以只读方式打开的文件名等，记录断点和条件断点速度相当，并且从记录窗口中浏览上百条消息要比按上百次F9轻松的多，您可以为表达式选择一个预先定义好的解释说明。

您可以设置通过的次数 - 每次符合暂停条件时，计数器就会减一。如果通过计数在减一前，不等于零，OllyDbg就会继续执行。如果一个循环执行100次（十进制），在循环体内设置一个断点，并设置通过次数为99（十进制）。OllyDbg将会在最后一次执行循环体时暂停。

另外，条件记录断点允许您传递一个或多个命令给插件［plugins］。例如，您需要使用命令行插件改变一个寄存器的内容，然后继续执行程序。

- 消息断点［Message breakpoint］和条件记录断点基本相同，除了OllyDbg会自动产生一个条件，这个条件允许在窗口过程的入口处设置某些消息（比如WM_PSINT）断点，您可以在窗口［Windows］中设置它。

- 跟踪断点［Trace breakpoint］ 是在每个选中命令上设置的一种特殊的INT3断点。如果您设置了Hit跟踪［hit trace］ ，断点会在命令执行后移除，并在该地址处做一个标记。如果您使用的是Run跟踪［run trace］ ，OllyDbg会添加跟踪数据记录并且断点仍然是保持激活状态。

- 内存断点［Memory breakpoint］ OllyDbg每一时刻只允许有一个内存断点。您可以在反汇编窗口、CPU窗口、数据窗口中选择一部分内存，然后使用快捷菜单设置内存断点。如果有以前的内存断点，将被自动删除。您有两个选择：在内存访问（读，写，执行）时中断，或内存写入时中断。设置此类断点时，OllyDbg将会改变所选部分的内存块的属性。在与80x86兼容的处理器上将会有4096字节的内存被分配并保护起来。即使您仅仅选择了一个字节，OllyDbg 也会将整个内存块都保护起来。这将会引起大量的错误警告，请小心使用此类断点。某些系统函数（特别是在Windows95/98下）在访问受保护的内存时不但不会产生调试事件反而会造成被调试程序的崩溃。

- 硬断点［Hardware breakpoint］（仅在Windows ME，NT或2000下可用）在80x86兼容的处理器上，允许您设置4个硬件断点。和内存断点不同，硬件断点并不会降低执行速度，但是最多只能覆盖四个字节。在单步执行或者跟踪代码时，OllyDbg能够使用硬断点代替INT3断点。

- 内存访问一次性断点［Single-shot break on memory access］ （仅在Windows NT或2000下可用）。您可以通过内存窗口的快捷菜单（或按F2），对整个内存块设置该类断点。当您想捕捉调用或返回到某个模块时，该类断点就显得特别有用。中断发生以后，断点将被删除。

- 暂停Run跟踪［Run trace pause］ （快捷键：Ctrl+T）是在每一步Run跟踪［run trace］ 时都要检查的一个条件集.您可以在EIP进入某个范围或超出某个范围时暂停，某个条件为真时暂停，或者命令与指定的模式匹配时暂停，或者当命令可疑的时候暂停。注意，这一选择会极大的（高达20%）降低Run跟踪的速度。

OllyDbg也可以在一些调试事件［debugging events］上暂停程序执行。比如加载或卸载DLL，启动或终止线程，或者程序发出调试字符串的时候。


Shortcuts
快捷键［Shortcuts］

通用快捷键

反汇编窗口中的快捷键


Global shortcuts
通用快捷键［Global shortcuts］

无论当前的OllyDbg窗口是什么，这些快捷键均有效：

Ctrl+F2 - 重启程序，即重新启动被调试程序。如果当前没有调试的程序，OllyDbg会运行历史列表［history list］中的第一个程序。程序重启后，将会删除所有内存断点和硬件断点。

译者注：从实际使用效果看，硬件断点在程序重启后并没有移除。

Alt+F2 - 关闭，即关闭被调试程序。如果程序仍在运行，会弹出一个提示信息，询问您是否要关闭程序。

F3 - 弹出“打开32位.EXE文件”对话框［Open 32-bit .EXE file］，您可以选择可执行文件，并可以输入运行参数。

Alt+F5 - 让OllyDbg总在最前面。如果被调试程序在某个断点处发生中断，而这时调试程序弹出一个总在最前面的窗口（一般为模式消息或模式对话框［modal message or dialog］），它可能会遮住OllyDbg的一部分，但是我们又不能移动最小化这个窗口。激活OllyDbg（比如按任务栏上的标签）并按Alt+F5，OllyDbg将设置成总在最前面，会反过来遮住刚才那个窗口。如果您再按一下Alt+F5，OllyDbg会恢复到正常状态。OllyDbg是否处于总在最前面状态，将会保存，在下一次调试时依然有效。当前是否处于总在最前面状态，会显示在状态栏中。

F7 - 单步步入到下一条命令，如果当前命令是一个函数［Call］，则会停在这个函数体的第一条命令上。如果当前命令是是含有REP前缀，则只执行一次重复操作。

Shift+F7 - 与F7相同，但是如果被调试程序发生异常而中止，调试器会首先尝试步入被调试程序指定的异常处理（请参考忽略Kernel32中的内存非法访问）。

Ctrl+F7 - 自动步入，在所有的函数调用中一条一条地执行命令（就像您按住F7键不放一样，只是更快一些）。当您执行其他一些单步命令，或者程序到达断点，或者发生异常时，自动步入过程都会停止。每次单步步入，OllyDbg都会更新所有的窗口。所以为了提高自动步入的速度，请您关闭不必要成窗口，对于保留的窗口最好尽量的小。按Esc键，可以停止自动步入。

F8 - 单步步过到下一条命令。如果当前命令是一个函数，则一次执行完这个函数（除非这个函数内部包含断点，或发生了异常）。如果当前命令是含有REP前缀，则会执行完重复操作，并停在下一条命令上。

Shift+F8 - 与F8相同，但是如果被调试程序发生异常而中止，调试器会首先尝试步过被调试程序指定的异常处理（请参考忽略Kernel32中的内存非法访问）。

Ctrl+F8 - 自动步过，一条一条的执行命令，但并不进入函数调用内部（就像您按住F8键不放一样，只是更快一些）。当您执行其他一些单步命令，或者程序到达断点，或者发生异常时，自动步过过程都会停止。每次单步步过，OllyDbg都会更新所有的窗口。所以为了提高自动步过的速度，请您关闭不必要成窗口，对于保留的窗口最好尽量的小。按Esc键，可以停止自动步过。

F9 - 让程序继续执行。

Shift+F9 - 与F9相同，但是如果被调试程序发生异常而中止，调试器会首先尝试执行被调试程序指定的异常处理（请参考忽略Kernel32中的内存非法访问）。

Ctrl+F9 - 执行直到返回，跟踪程序直到遇到返回，在此期间不进入子函数也不更新CPU数据。因为程序是一条一条命令执行的，所以速度可能会慢一些。按Esc键，可以停止跟踪。

Alt+F9 - 执行直到返回到用户代码段，跟踪程序直到指令所属于的模块不在系统目录中，在此期间不进入子函数也不更新CPU数据。因为程序是一条一条执行的，所以速度可能会慢一些。按Esc键，可以停止跟踪。

Ctrl+F11 -Run跟踪步入，一条一条执行命令，进入每个子函数调用，并把寄存器的信息加入到Run跟踪的存储数据中。Run跟踪不会同步更新CPU窗口。

F12 - 停止程序执行，同时暂停被调试程序的所有线程。请不要手动恢复线程运行，最好使用继续执行快捷键或菜单选项（像 F9）。

Ctrl+F12 - Run跟踪 步过，一条一条执行命令，但是不进入子函数调用，，并把寄存器的信息加入到Run跟踪的存储数据中。Run跟踪不会同步更新CPU窗口。

Esc - 如果当前处于自动运行或跟踪状态，则停止自动运行或跟踪；如果CPU显示的是跟踪数据，则显示真实数据。

Alt+B - 显示断点窗口。在这个窗口中，您可以编辑、删除、或跟进到断点处。

Alt+C - 显示CPU窗口。

Alt+E - 显示模块列表［list of modules］。

Alt+K - 显示调用栈［Call stack］窗口。

Alt+L - 显示日志窗口。

Alt+M - 显示内存窗口。

Alt+O - 显示选项对话框［Options dialog］

Ctrl+P - 显示补丁窗口。

Ctrl+T - 打开 暂停 Run跟踪 对话框

Alt+X - 关闭 OllyDbg。

大多数窗口都支持以下的键盘命令：

Alt+F3 - 关闭当前窗口。

Ctrl+F4 - 关闭当前窗口。

F5 - 最大化当前窗口或将当前窗口大小改为正常化。

F6 - 切换到下一个窗口。

Shift+F6 - 切换到前一个窗口。

F10 - 打开与当前窗口或面板相关的快捷菜单。

左方向键 - 显示窗口左方一个字节宽度的内容。

Ctrl+左方向键 - 显示窗口左方一栏的内容。

右方向键 - 显示窗口右方一个字节宽度的内容

Ctrl+右方向键 - 显示窗口右方一栏的内容


CPU window
CPU 窗口［CPU window］

对于用户来说，CPU窗口在OllyDbg中是最重要的窗口。您调试自己程序的绝大部分操作都要在这个窗口中进行。它包括以下五个面板（这五个面板的大小都是可以调节的）：

反汇编［Disassembler］

信息［Information］

数据［Dump］

寄存器［Registers］

栈［Stack］

按TAB键，可以切换到下一个CPU面板中（顺时针方向）。

按Shift+TAB，可以切换到前一个CPU面板（逆时针方向）。

相关信息： API相关帮助［Context-sensitive API help］.


Context-sensitive API help
API相关帮助［Context-sensitive API help］

您可以把介绍API函数的帮助文件挂接到OllyDbg中，并且可以在反汇编［Disassembler］、名称［Names］和模块间调用［Intermodular calls］窗口中迅速获得API函数的相关帮助（快捷键：Ctrl+F1）。

通过主菜单中帮助［Help］|选择API帮助［Select API help］，来挂接API帮助。帮助文件（win32.hlp）没有放到odbg110.zip 压缩包中。


Disassembler window
反汇编窗口［Disassembler window］

CPU窗口中的反汇编面板（为了方便起鉴，我将称其为反汇编窗口）用于显示被调试程序的代码。它有四个栏，地址栏［address］、十六进制数据栏［hex dump］、反汇编代码栏［disassembled commands］和注释栏［comments］。最后一栏可以改变显示模式为：相关源代码或运行统计［run profile］，如果列标题栏可见的话，点列标题栏就可以改变显示模式。

双击某个栏，会运行对该栏最常用的操作：

地址栏［Address］ - 显示距双击地址处的相对地址。 再次双击基地址，则恢复为标准地址显示模式；

十六进制数据栏［Hex dump］ - 设置或取消非条件断点；

反汇编栏［Disassembly］ - 调用汇编器，修改命令；

注释栏［Comment］ - 允许您增加或修改与命令相关的注释。

如果反汇编窗口的列标题栏可见，并且备份［Backup］可用，则单击地址［Address］/备份［Backup］，可以在备份和正常显示模式间切换。单击第四列标题栏，则可以在注释［comment］、源代码［source code］ 和统计数据［profile data］间切换。

但程序暂停时，反汇编窗口会根据当前线程的EIP，自动翻动到EIP所指向的命令上。

反汇编窗口允许您浏览，分析，搜索，修改代码，复制修改到可执行文件，设置断点，等等。相关联的快捷菜单中包含了超过 150 菜单项。另外，菜单中只显示与当前选中命令相关的菜单项，如果多条命令被选中的话，菜单中显示的菜单项只与所有选中命令中的第一条（内存地址最靠前的那条）相关。

要想使用键盘选中多行，您可以按住 Shift 键不放，同时使用上/下方向键或 PageUp/PageDown 翻页键。

在反汇编窗口中翻动一个字节，您可以按住 Ctrl 键不放，同时按上/下方向键。

点击以下主题，您可以得到关于反汇编窗口的更多信息：

反汇编窗口菜单［Disassembler menu］

反汇编窗口快捷键［Disassembler shortcuts］

反汇编窗口选项［Disassembler options］

分析［Analysis］

断点［Breakpoints］

相关信息：信息窗口［Information window］, 数据窗口［Dump］


Step-by-step execution and animation
单步执行与自动执行［Step-by-step execution and animation］

您可以通过按 F7（单步步入）或 F8（单步步过），对程序进行单步调试。这两个单步执行操作的主要区别在于：如果当前的命令是一个子函数，按F7，将会进入子函数，并停在子函数的第一条命令上；而按 F8，将会一次运行完这个子函数。如果您单步步过的子函数中含有断点或其他调试事件，执行将会被暂停，但 OllyDbg 会在子函数的后一条命令上，自动下一个断点，而这个断点您迟早会碰到。

如果被调试程序停在异常上，您可以跳过它，并转到被调试程序建立的句柄处。只需简单的 Shift 键和任何一个单步命令。

如果需要连续按F7、F8键上百次，您可以使用自动执行（Ctrl+F7或者Ctrl+F8）功能。在这种情况下，OllyDbg 将自动重复F7或者F8操作，并且实时更新所有的窗口。这个过程会在下面情况停止：

- 按 Esc 键或发出任何单步命令

- OllyDbg 遇到断点

- 被调试程序发生异常

使用“+”和“-”按键，可以回朔以前的执行历史［execution history］.

注意：当执行停止时 OllyDbg 将会刷新大部分窗口。如果动态执行过程非常慢，可以尝试关掉或最小化没有用的窗口。

另外，更快捷的找到以前执行指令的办法是Run跟踪［run trace］。它将创建一个执行协议并告知您指定指令的执行时间和次数

相关信息: Hit跟踪［Hit trace］, 执行到返回［Execute till return］


Execute till return
执行到返回［Execute till return］

您可以跳过一些代码而返回到函数的调用者那里，OllyDbg可以跟踪程序执行过程中遇到的所有函数，并且停在遇到的第一个返回命令（RET、RETF，或者IRET）。从主菜单中选择“调试［Debug］ |执行直到返回［Execute till return］”或者按Ctrl+F9。单步执行相对较慢，在Windows NT、奔腾500下，最高为每秒5000条指令。如果追踪用了很多时间，按 Esc 键或者 F12 键，则停止执行。

如果您想执行返回指令并且停止在相应调用的下一条指令，则在跟踪选项［Trace options］里选中“执行到RET后，步过RET命令［After execution till RET, step over RET］”。

相关信息： 执行到用户代码［Execute till user code］, 执行到条件满足［Execute till condition］


Execute till user code
执行到用户代码［Execute till user code］

有时您的应用程序终止在系统代码很深的地方，为了返回到您所调试的应用程序中，您可以按Ctrl+F9（执行到返回［Execute till return］）若干次，并每次检查所处的位置。但有一种更快捷的方法。如果您按Alt+F9或者从主菜单中选择“调试［Debug］ |执行到用户代码［Execute till user code］”，OllyDbg将会单步执行直到到达第一个不在系统DLL中的指令为止。（从OllyDbg的角度来看，任何在驻留在系统目录或windows目录下的都是系统DLL）。单步执行相对较慢，在Windows NT、奔腾500下，最高为每秒5000条指令。如果追踪用了很多时间，按Esc键或者F12键，则停止执行。

警告：如果系统DLL调用了回调了用户函数，它会直接步过这个函数。为了避免这样的情况，您可以在用户代码段设置内存访问一次性断点［single-shot break on access］在（仅适用于window NT4.0 、2000和XP).

相关信息：执行到条件满足［Execute till condition］


Hit trace
Hit跟踪［Hit trace］

Hit跟踪能够让您辨别哪一部分代码执行了，哪一部分没有。OllyDbg的实现方法相当简单。它将选中区域的每一条命令处均设置一个INT3断点。当中断发生的时候，OllyDbg便把它去除掉，并把该命令标志为命中［hit］。因为每个跟踪断点只执行一次，所以这种方法速度非常快。

在使用Hit跟踪的时候，一定要注意不能在数据中设置断点，否则应用程序极有可能崩溃。因此，您必须打开相关的菜单选项，以进行代码分析［analyze］。我推荐您选择严格或启发式函数识别［strict or heuristical procedure recognition］。如果选择模糊［Fuzzy］的话，可能会产生很多难以容忍的错误，而且经常把本不是函数的代码段识别成函数。

只要您在模块中设置了跟踪断点，哪怕只设了一个，OllyDbg都会分配两倍于代码段大小的缓冲区。

注意：当您退出Hit跟踪的时候，Run跟踪也会同时退出。

相关信息：反汇编窗口菜单［Disassembler menu］、 Run跟踪［Run trace］、 跟踪选项［Trace options］


Run trace
Run 跟踪［Run trace］

Run跟踪是一种反方向跟踪程序执行的方式，可以了解以前发生的事件。您还可以使用Run跟踪来了解运行的简单统计［profile］。基本上，OllyDbg 是一步一步地执行被调试程序的，就像动画［animation］演示一样，但不会实时刷新窗口，最重要的是它能将地址、寄存器的内容、消息以及已知的操作数记录到Run跟踪缓冲区中。如果被调试的代码是自修改的，您就能够保存原始的命令。可以通过按Ctrl+F11（Run跟踪步入，进入子函数）或者Ctrl+F12（Run跟踪步过，一次执行完子函数）开始Run跟踪，并用F12或者Esc键停止跟踪。

您可以指定在Run跟踪时执行每一步的条件集（快捷键：Ctrl+T）。如果条件符合，Run跟踪将暂停。条件包括：

•	当EIP在某个地址范围内时暂停［Pause when EIP is in the address range］；

•	当EIP在某个地址范围之外时暂停［Pause when EIP is outside the address range］；

•	当某个条件为真时暂停［Pause when some condition is true］；

•	当下一条指令可疑时暂停［Pause when next command is suspicious］，比如： 可能为非法指令（根据在分析3［Analysis 3］中设定的规则而定），访问不存在的内存，设置了单步陷阱标志［single-step trap flag］或者越ESP界访问栈。注意这个选项会明显地(大约20%)减慢Run跟踪的速度；

•	当命令执行达到指定的次数（更确切的说，是添加到Run跟踪的缓冲区里面的命令数量）时暂停［Pause after specified number of commands is traced］。注意计数器不能自动归零。也就是说，如果您设置指令次数为10，则在第10次执行到该命令时暂停，并不是该命令每执行10次就暂停一次。

•	当下一条命令符合指定的样式之一时暂停［Pause when next command matches one of the specified patterns］。您可以使用模糊命令和操作数［imprecise commands and operands］及匹配32位寄存器RA和RB，像R32一样，这两个寄存器可以替代任何通用32位寄存器，但是在同一条命令中其值是不能变的。而 RA 和 RB 在同一条命令中，则一定是不同的。例如，在程序中含有 XOR EAX,EAX; XOR ESI,EDX 两条命令，两条命令均符合样式 XOR R32,R32；第一条命令符合样式XOR RA,RA；而等二条命令 XOR ESI,EDX 符合样式XOR RA,RB。

毫无疑问，Run跟踪需要足够的内存，每条命令平均需要占用16到35字节，同时速度也非常慢。在500-MHZ处理器、Windows NT环境下，它每秒能跟踪5000条指令。Windows95更慢：每秒钟仅2200条指令。但是在许多情况下，例如当一个程序跳转到不存在的地址的时候，这是找到原因的唯一方法。您可以在Run跟踪时将准线性命令序列（即序列尾部只有唯一出口）跳过。当OllyDbg遇到这些需跳过的命令序列时，会设置一个临时断点，然后跟进到序列中，并一次运行完。当然了，如果排除命令中返回或跳转的地址在跟踪范围之外，将可能导致跟踪发生错误；因此OllyDbg会检查您想跳过的代码块，如果存在上述情况，会向您询问。

在大多数情况下，您对跟踪系统API代码不感兴趣。跟踪选项总是跟过系统DLL［Always trace over system DLLs］允许您在 跟踪/自动 模式下跟过API函数。如果模块在系统目录下，OllyDbg就假设该模块是系统的。您可以在模块［Modules］窗口中标记任意DLL是系统的或者非系统的。

为了使执行速度更快，您可以通过设置Run跟踪断点，先将Run跟踪限制在选定的命令或代码块上，然后再运行程序。我把这种做法称作“强迫Run跟踪”。一般来说，删除Run跟踪断点不会移除Hit跟踪断点。但如果您删除了hit跟踪断点，同时您也移除了Run跟踪断点。

跟踪命令会保存到跟踪缓冲区中，这个缓冲区在跟踪开始时自动创建。您可以在选项中指定它的大小(最高64MB)。这个缓冲区是循环队列，当满了的时候，会丢弃老的记录。

您可以通过从OllyDbg主菜单中选择“调试［Debug］|打开或者清除Run跟踪［Open or clear run trace］”，来打开或者清除Run跟踪缓冲区。在Run跟踪缓冲区打开后，OllyDbg 会记录在执行过程中的所有暂停，甚至那些不是由Run跟踪引起的暂停。例如，您可以通过按 F7 或者 F8 单步执行程序，然后通过使用+键和-键来反方向跟踪程序的执行。注意：如果Run跟踪缓冲区已经关闭，则用这些键浏览的是历史［history］记录。在您查看Run跟踪记录时，寄存器和信息面板会变灰，来强调它们所显示的寄存器并不是实际的寄存器。跟踪缓冲区并不保存栈顶或由寄存器所指向的内容。寄存器、信息和栈在Run跟踪的时候使用实际的内存状态来解释寄存器的变化。

OllyDbg能够记下每个指令在Run跟踪缓冲区里面出现的次数。在反汇编窗口快捷菜单中，选择是“查看［View］|统计作为注释［Profile as comments］”。这个命令使用统计取代了注释栏。或者，如果列标题栏可见，则可以单击它几次直到它显示统计信息。注意显示出来的数字是动态的，而且不计算已经从跟踪缓冲区中丢弃的指令。您还可以在单独的统计窗口［Profile window］中，按触发次数排序，来查看整个模块的统计数据。

在反汇编窗口的快捷菜单中选择“Run跟踪［Run trace］|添加到所有函数入口处［Add entries of all procedures］”，这样能够检查每个可识别的函数被调用的次数。另一个命令“Run跟踪［Run trace］|添加到函数中所有的分支［Add branches in procedure］”会强行跟踪此函数中所有识别的跳转目的地址的内容。在这种情况下，统计功能能够找到最频繁执行的分支，您可以优化这部分的代码，以提高速度。

在反汇编窗口中的某条命令上使用快捷菜单中选择“搜索［Search for］|Run跟踪的最新记录［Last record in run trace］”用于查找该命令是否被执行过，如果执行过，最后一次执行在哪里。

Run跟踪窗口显示跟踪缓冲区的内容。对每个指令来说包括被指令改变的整数寄存器的内容(更准确的说是给定的记录变成下一条记录的变化)。如果您双击某条指令，窗口会选择在跟踪缓冲区里全部含有该命令的记录，而且您可以通过按+和-键来快速的浏览；如果您在调试选项［Debugging options］中设置了 “跟踪［Trace］|同步CPU和Run跟踪［Synchronize CPU and Run trace］”，双击记录则会跟进到对应的反汇编窗口中位置。

注意：当您退出Hit跟踪时，您同时也强行退出了Run跟踪。

相关信息： 反汇编窗口菜单［Disassembler menu］、Hit跟踪［Hit trace］、 跟踪选项［Trace options］


Self-extracting (SFX) files
自解压文件［Self-extracting (SFX) files］

自解压文件由提取程序和压缩的原程序两部分组成。当遇到自解压文件（SFX）文件时，我们通常希望跳过解压部分，而直接跳到原始程序的入口（真正的入口）。OllyDbg 包含了几个便于完成这一任务的功能。

通常提取程序的加载地址都在执行代码之外。在这种情况下，OllyDbg 将这类文件均视作为自解压文件(SFX)。

当自解压选项［SFX options］要求跟踪真正入口时，OllyDbg 在整个代码节［Code section］设置内存断点，最初这里是空的，或者只包含压缩数据。当程序试图执行某个在这个保护区域的命令，而这些命令不是 RET 和 JMP 时，OllyDbg 会报告真正的入口。这就是提取工作的原理。

上面的方法非常慢。有另外一种比较快的方法。每次读取数据发生异常时，OllyDbg 使这个4K内存区域变为可读，而使原先可读的区域变为无效。而每次发生写数据异常时，OllyDbg 使这个区域变为可写，而使原先可写的区域变为无效。当程序执行在保留的保护区域中的指令时，OllyDbg 报告真正的入口。但是，当真正的入口点在可读或可写区域内部时，报告的地址就可能有误。

您可以纠正入口位置，选择新的入口，从反汇编窗口的快捷菜单中选择“断点［Breakpoint］|设置真正的自解压入口［Set real SFX entry here］”。如果相应的SFX选项是开启的，OllyDbg下次可以迅速而可靠的跳过自提取程序。

注意：OllyDbg 在跟踪采取了保护或者反调试技术的解压程序时通常会失败。


Information window
信息窗口［Information window］

CPU窗口中的信息面板用于解码反汇编面板中选中的第一个命令的参数，信息面板也会显示隐含的参数，比如在REPE SCASB命令中的AL与ECX，或RETN命令的栈顶内容。为便于分析代码，该面板显示跳转到该处的命令列表。如果调试信息可用，该面板也显示与选中部分相应源代码内容。在这里，您可以跟进地址到数据窗口或反汇编窗口，也可以修改参数，或打开源文件。

任何程序都会非常频繁的使用寄存器，所以寄存器的内容会不断的变化。默认情况下，OllyDbg假设寄存器仅对当前执行的命令有效。如果您想对所有命令变量内容解码，请激活为任何IP解码寄存器［Decode registers for any IP］选项。

如果您在反向跟踪Run跟踪［run trace］日志，信息面板将呈灰色，以强调所显示寄存器是由跟踪数据产生的，而不是实际的。注意：Run跟踪并不保存内存的内容，显示的内容都是实际内容。

根据选择内容的不同，信息窗口快捷菜单可包含以下选项：

复制面板到剪切板［Copy pane to clipboard］ -复制全部不为空的行到剪切板。

修改寄存器［Modify register］ -允许您改变选中寄存器的内容。

跟进地址到反汇编面板［Follow address in Disassembler］ -跟进地址，并在反汇编面板中显示。

跟进值到反汇编面板［Follow value in Disassembler］ -通过选择的地址跟进到双字内存指针指向的内容，并在反汇编面板中显示。

跟进地址到数据面板Follow address in Dump］-跟进地址，并在CPU窗口的数据面板中显示。

跟进值到数据面板［Follow value in Dump］ -通过选择的地址跟进到双字内存指针指向的内容，并在数据面板中显示。

转到来自xxxx的CALL［Go to CALL from xxxx］,

转到来自xxxx的JMP［Go to JMP from xxxx,

转到来自xxxx的JNZ［Go to JNZ from xxxx,

转到来自xxxx的JMP[]［Go to JMP [ ] from xxxx］ 等 - 转到跳转或调用当前位置的命令。这可能是直接或间接的调用、无条件跳转、条件跳转、或表分支［table switch］。注意：来自其他模块的调用是不被列出的，即使它们在出现在调用树中。

显示全部跳转和本地调用［Show all jumps and local calls］ - 如果跳转到当前位置的数量超过16个，该菜单项目打开一个对话框，用户列出全部找到的跳转。

显示源代码［Show source］ -打开与所选命令位置相应的源文件。也可以通过双击信息窗口的源代码行［source line］做到这一点。

外观［Appearance］ - 细节描述请参考这里.


Registers window
寄存器窗口［Registers window］

寄存器窗口用于显示和解释当前所选线程的CPU寄存器内容。该窗口同样允许修改寄存器，并可以跟进地址到其它CPU面板。与各寄存器的关快捷菜单都非常容易理解，恕不赘述。

接下来是 EFL ，它用来显示当前条件命令是否能满足条件。比如下面的例子：

EFL 00000A86 (O,NB,NE,A,S,PE,GE,G),

这意味着 JO 和 JNE 将会发生跳转，而JB 和 JPO 将不会发生。

与之相似，后面的 FST 用于对 FPU标志（C0, C2 和 C3）进行解码，一般用于比较最后一次的FPU操作。

当被调试程序暂停执行时，OllyDbg 会高亮显示与上次暂停以来的所有不同之处。如果您修改了任何一项，OllyDbg 将会高亮显示全部被修改项目。

如果要切换某个标志，双击该标志，或者选择它并敲回车键。双击寄存器会弹出用于修改寄存器内容的对话框。然后输入新的内容，即可改变整数或浮点寄存器的值。选中某个整数寄存器，按加号键（+）与减号键（-）可将其的数值加1或减1。

您可以选择浮点、MMX或3DNow!任何一种方式显示FPU寄存器内容。如果窗口有列标题栏，则点击该列标题栏，就可以在三种形式之间切换。您也可以让OllyDbg通过最近一处中断时所处的命令，自动改变显示形式。您还可以选择显示调试寄存器DR0..DR3, DR6 以及 DR7，但您不能编辑调试寄存器。

如果您要调试SSE 代码，激活选项解码SSE寄存器［Decode SSE registers］ 以显示128位的SSE寄存器。注意：该选项开启后，速度会非常慢，有时还非常危险（特别应用程序是多线程的时候），除非绝对需要请不要使用。.

如果您回溯Run跟踪［Run trace］日志，寄存器面板将呈灰色以强调所显示寄存器是跟踪数据产生的，而并非是实际的。注意，Run跟踪并不保存内存、SSE和调试寄存器的内容，并且将读取被调试进程的实际内存内容来解码指针。

您可以显示一个线程的最后发生的一次错误（也就是调用API函数GetLastError的返回值)。该特色功可以通过显示最后一次错误［Show last error］开启。如果该功能被激活，最后错误将保存到Run跟踪日志中，但是会减慢（最大到20%）的跟踪速度。

您可以在该窗口的任何地方按住鼠标左键并移动以滚动寄存器面板。


Disassembler shortcuts
反汇编窗口中的快捷键［Disassembler shortcuts］

当CPU窗口中的反汇编面板［Disassembler pane］处于激活状态时，您可以使用以下快捷键：

回车键 - 将选中的命令添加到命令历史［command history］中，如果当前命令是一个跳转、函数或者是转换表的一个部分，则进入到目的地址。

退格键 - 移除选中部分的自动分析信息。如果分析器将代码误识别为数据，这个快捷键就非常有用。请参考解码提示［decoding hints］.

Alt+退格键 - 撤消所选部分的修改，以备份数据的相应内容替换所选部分。仅当备份数据存在且与所选部分不同时可用。

Ctrl+F1 -如果API帮助文件已经选择，将打开与首个选择行内的符号名相关联的帮助主题。

F2 -在首个选择的命令上开关INT3 断点［Breakpoint］，也可以双击该行第二列。

Shift+F2 -在首个选择命令设置条件断点，参见忽略Kernel32中内存访问异常［Ignore memory access violations in Kernel32］。

F4 -执行到所选行，在首个选择的命令上设置一次性断点，然后继续执行调试程序，直到OllyDbg捕获到异常或者停止在该断点上。在程序执行到该命令之前，该一次性断点一直有效。如有必要，可在断点窗口［Breakpoints window］中删除它。

Shift+F4 -设置记录断点（一种条件断点，当条件满足时一些表达式的值会记录下来）， 详情参见断点［Breakpoint］。

Ctrl+F5 -打开与首个选择的命令相对应的源文件。

Alt+F7 -转到上一个找到的参考。

Alt+F8 -转到下一个找到参考。

Ctrl+A -分析当前模块的代码段。

Ctrl+B - 开始二进制搜索。

Ctrl+C -复制所选内容到剪贴板。复制时会简单地按列宽截断不可见内容，如果希望排除不需要的列，可把这些列的宽度调整到最小。

Ctrl+E -以二进制（十六进制）格式编辑所选内容。

Ctrl+F -开始命令搜索。

Ctrl+G -转到某地址。该命令将弹出输入地址或表达式的窗口。该命令不会修改 EIP。

Ctrl+J -列出所有的涉及到该位置的调用和跳转，在您用这个功能之前，您必须使用分析代码功能。

Ctrl+K - 查看与当前函数相关的调用树［Call tree］。在您用这个功能之前，您必须使用分析代码功能。

Ctrl+L - 搜索下一个，重复上一次的搜索内容。

Ctrl+N - 打开当前模块的名称（标签）列表。

Ctrl+O - 扫描object文件。扫描Object文件。该命令会显示扫描Object文件对话框，您可以在该对话框中选择Object文件或者lib文件，并扫描这个文件，试图找到在实际代码段中用到的目标模块。

Ctrl+R -搜索所选命令的参考。该命令扫描激活模块的全部可执行代码，以找到涉及到首个选中的命令的全部相关参考（包括：常量、跳转及调用），您可以在参考中使用快捷键 Alt+F7 和 Alt+F8来浏览这些参考。为便于您使用，被参考的命令也包含在该列表中。

Ctrl+S -命令搜索。该命令显示命令查找［Find command］对话框供您输入汇编命令，并从当前命令开始搜索。

星号［Asterisk］(*) -转到原始位置（激活线程的EIP处）。

Ctrl+星号(*) - 指定新的起始位置，设置当前所选线程的EIP为首个选择字节的地址。您可以在选择EIP并撤消该操作。

加号［Plus］(+) -如果run跟踪［run trace］ 没有激活，则根据命令历史［command history］跳到下一条运行过命令的地方；否则跳到Run跟踪的下一个记录。

Ctrl+加号 - 跳到前一个函数开始处。（注意只是跳到，并不执行）

减号［Minus］(-) - 如果run跟踪［run trace］ 没有激活，则根据命令历史［command history］跳到前一条运行过命令的地方；否则跳到Run跟踪的前一个记录。

Ctrl+减号 - 跳到下一个函数开始处。（注意只是跳到，并不执行）

空格［Space］ - 修改命令。您可在显示对话框中以汇编语言修改实际指令或输入新指令，这些指令将替换实际代码，您也可以在想要修改的指令处双击鼠标。

冒号［Colon］(:) - 添加标签。显示添加标签窗口［Add label］或修改标签窗口［Change label］，您可在此输入与首个选择的命令中的第一个字节相关联的标签（符号名）。注意，在多种编程语言中，冒号可以是标签的一部分。

分号［Semicolon］(;) - 添加注释［comment］。显示添加注释窗口［Add label］或修改注释窗口［Change label］，您可在此输入与首条所选命令的第一个字节相关联的注释（注释串会显示在最后一列中）。注意，多种汇编语言使用分号作为注释开始。您也可以在注释列双击需要注释的命令行。


Command history
命令历史［Command history］

OllyDbg保存了多达1000条最近显示在反汇编窗口的命令。每当被调试程序停在断点或异常处，或者您单步到下一条命令，或者跟进到JUMP或CALL指令指向的地址处，或者您只是简单地按了一下回车键的时候，OllyDbg都会把当前的地址连同线程标志一起添加到命令历史[Command history]中。如果Run跟踪［run trace］没有激活，您可以按“+”和“-”键在历史记录里浏览。

在CPU数据窗口［CPU Dump］中也有相似的数据历史[data history]功能。


Backup functions
备份功能［Backup functions］

反汇编窗口、CPU数据窗口，以及其他数据窗口都可以创建内存块备份。

反汇编窗口和CPU数据窗口可以创建全局共享备份。如果您修改了代码或数据，备份会自动进行。每个内存块只能有一个全局备份。一旦备份建立，全局备份的生命期与原始内存块相同。补丁管理器［Patch manager利用这个全局备份来建立补丁列表。

独立的数据窗口会按您的要求建立本地私有备份，当您关闭数据窗口或者转换到另一个内存块时，备份会被删除。如果几个数据窗口显示的内存区域相同，则它们的备份相互独立。

如果备份是可用的，OllyDbg会把备份数据和当前数据的不同之处高亮显示。恢复备份数据的方法：选中要恢复的部分，在快捷菜单中选择恢复［Undo］，或者按 Alt+退格键。

您也可以把备份数据保存到文件中，并且以后再次读取。这样可以侦测出被调试程序在不同的运行情况下的区别。通过选择快捷菜单中的搜索［Search for］|修改的命令［Modified command］或搜索［Search for］|修改的数据［Modified data］，您可以很快地发现备份数据和当前数据间的所有不同。

下面是可用的备份功能：

查看备份［View backup］- 查看备份（而不是当前数据），如果窗口显示的是备份数据，所有的功能都不可用。如果列标题栏可见，则您可以按列标题栏上的“地址”［Address］按钮进行切换。

查看真实数据［View actual data］- 查看当前数据（而不是备份），如果列标题栏可见，则您可以按列标题栏上的“备份”［Backup］进行切换。

创建备份［Create backup］，

更新备份［Update backup］- 创建新的备份或更新已有的备份。

删除备份［Delete backup］ 删除备份。

读取备份从文件［Load backup from file］- 从文件中读取备份数据。如果备份数据的大小与当前数据的不同，则OllyDbg会发出警告。

保存备份到文件［Save backup to file］- 备份数据保存到文件中。默认的内存备份文件名为“MODULE_XXXXXXXX.mem”的形式，MODULE是模块名（如果超过八字节，则只保留前八字节；如果内存块不属于任何模块，则为空），XXXXXXXX是十六进制的内存基址。对于文件备份，默认文件名为原始文件名。

保存数据到文件［Save data to file］- 把原始数据保存到文件中。


Disassembler menu
反汇编窗口中的菜单［Disassembler menu］

反汇编窗口的快捷菜单可能是整个OllyDbg中最重要的部分。为了保证菜单整洁，它只显示与选择的反汇编代码相关的菜单项。如果一次选择了多行，那么菜单中的单行命令只对首个选择的命令行起作用。

备份功能［Backup functions］ - 详见这里.

复制［Copy］

到剪切板［To clipboard］ (Ctrl+C) - 复制选择的部分到剪切板。使用当前选择的栏目宽度。如果复制时要排除栏目，请减小其的宽度到最小（在这时，栏目的剩余部分呈灰色）。如果某些文本程度大于栏目宽度，OllyDbg将使用“>'”替代栏目中无法显示的字符。

到文件［To file］ - 复制选择的部分到文件。用法和复制选择部分到剪切板相同，但复制的大小没有限制。

选择全部［Select all］ - 选择反汇编窗口中可显示的全部代码。

选择过程［Select procedure］ - 选择当前可识别的函数过程。

二进制［Binary］

编辑［Edit］ (Ctrl+E) - 允许您以 ASCII、UNICODE 或十六进制格式编辑选择的部分。这三个编辑控件紧密联系，同步滚动（三个框内的第一个字符总是相同的），同步显示您对任何控件的修改。通过按 Ctrl+↑或 Ctrl+↓ 可以迅速移动到不同窗口的该字符相应位置。编辑的最大长度是256字节。未完成的字符用红色的问号表示。如果十六进制串中包含了半个字节，OllyDbg会用0补足。当“保持大小［Keep size］选项开启时，您将不能插入或删除字符，也不能在代码尾部追加字符。

用00填充［Fill with 00�s］ - 选择部分的代码用零填充。

用NOP填充［Fill with NOP�s］ - 选择的部分用命令NOP填充

二进制复制［Binary copy］ - 复制选择部分的代码为十六进制字符，并保存在剪切板中。

二进制粘贴［Binary paste］ - 从剪切板中粘贴十六进制数据到选择的部分。OllyDbg会在剪切板中扫描文本，并从中提取出十六进制数字（0..9, A..F, a..f）和疑问标记（?），而其他符号都会被忽略掉。没有选择的代码不会发生变化。如果最后一字节只包含一个十六进制数，那么它会被忽略掉。例如，�part of code� 解释出的是 AF CD 而不是 AF CD 0E。

二进制复制时标记重定位［Copy with masked fixups］ - 与复制二进制相同，但会用疑问标记替代所有重定位的地址，以方便搜索相似的代码片断。参见搜索二进制串［Search for binary strings］。

修改字节［Modify byte］ - 允许您以带符号十进制、无符号十进制、或十六进制形式编辑选中的字节。

修改整数［Modify integer］ -允许您以带符号十进制、无符号十进制、或十六进制形式编辑选中的整型常量。

修改浮点［Modify float］ -  允许您编辑选中的浮点常量。

修改MMX［Modify MMX］ -允许您以带符号十进制、无符号十进制、或十六进制的形式编辑选中的MMX常量。

修改3D Now！［Modify 3DNow!］ - 允许您以浮点数或十六进制两种形式编辑选中的3DNow!常量。

修改SSE［Modify SSE］ - 允许您以4精度浮点数或十六进制形式编辑选中的SSE 常量。

撤销选择［Undo selection］ （Alt+退格） - 用相应的备份数据替换转中部份的代码。仅在备份数据存在且与选中部分不同时有效。

编译［Assemble］ （空格） - 允许您以汇编语言编辑或重写一到几行代码。详情请看汇编器［Assembler］。

标签［Label］ (:) - 允许您设定首个选择地址上的用户自定义标签［Label］ 。

编辑标签［Edit label］ (:) - 允许您编辑或去除首个选择地址上的用户自定义标签［Label］ 。

注释［Comment］ (;) - 允许您向首个选择的地址添加注释。

编辑注释［Edit comment］ (;) - 允许您编辑或去除首个选择地址上的用户自定义注释。

断点［Breakpoint］

切换［Toggle］ (F2) - 在首个选择的命令上切换 INT3 断点［Breakpoint］。

条件［Conditional］ (Shift+F2) - 允许在首个选择命令上设置条件断点断点［Breakpoint］ 。

条件记录［Conditional log］（Shift+F4） - 允许设置记录断点。更多细节，请查看断点［Breakpoints］ 。

在WinProc中的消息断点［Message breakpoint on WinProc］ - 允许编辑消息断点。消息断点也可以在Window窗口中设置。

运行到选中行［Run to selection］（F4） - 在首个选择的命令上设置一次性断点，然后继续执行调试程序，直到OllyDbg捕获到异常或者停止在该断点上。在程序执行到该命令之前，该一次性断点一直有效。如有必要，可在断点窗口［Breakpoints window］中删除它。

访问内存［Memory, on access］ - 在选择的数据上设置内存断点。每次这部分内存被访问，程序都会暂停。OllyDbg 支持任何大小的单内存断点。内存断点会造成执行速度的大幅下降。在 Windows 95/98 下，当系统程序访问包含内存断点的内存块时，还可能导致被调试程序的崩溃。因此，除非必要，请不要使用。

写内存［Memory, on write］ -在选择的数据上设置内存断点。每次这部分内存被写入，程序都会暂停。OllyDbg 支持任何大小的单内存断点。内存断点会造成执行速度的大幅下降。在 Windows 95/98 下，当系统程序访问包含内存断点的内存块时，还可能导致被调试程序的崩溃。因此，除非必要，请不要使用。

移除内存断点［Remove memory breakpoint］ - 移除内存断点。

移除自解压内存断点［Remove SFX memory breakpoint］ -停止搜索自解压（SFX）程序.真实的入口。这个搜索使用了特殊类型的内存断点。

硬断点，执行时［Hardware, on execution］ - 在首个选择字节设置硬件内存断点。每次以这个字节作为开始的命令执行时，程序都会暂停。硬件断点仅在Windows ME、NT 或 2000系统下可用。80x86处理器支持最多4个硬件断点。如果OllyDbg不能找到可用的硬件断点，那么您会询问您是否移除某个已经存在的硬断点。您可以在CPU数据面板中设置硬断点，当数据被访问或写入时中断。

移除硬断点［Remove hardware breakpoint］ - 移除设置在命令首字节的硬断点。

Set real SFX entry here - 设置首个选择命令为自解压程序解压后的真实入口。如果

自解压真实入口被设定，同时选项“使用前次运行时得到的真实入口［Use real entry from previous run］”开启，那么OllyDbg就会迅速地跳过提取器，并准确定位到真正入口处。

Hit跟踪［Hit trace］ - 处理Hit跟踪命令，仅在分析过的代码中可用。

添加选择部分［Add selection］ - 选择的代码部分需要Hit跟踪

添加函数过程［Add procedure］ - 当前函数过程需要Hit跟踪。

添加所有可识别的函数过程［Add all recognized procedures］ - 在反汇编窗口显示代码中对所有被分析器［Analyzer］识别的函数过程设置Hit跟踪。为了避免崩溃，推荐大家使用严格或启发的函数过程识别模式

从选择的部分移除［Remove from selection］ - 从选择部分中移除Hit跟踪。如果这里也设置了Run跟踪，那么它也一并移除。

从选择的模块中移除［Remove from module］ - 从当前模块的代码段中移除所有Hit跟踪。如果这里也设置了Run跟踪，那么它也一并移除。

标记选择部分不跟踪［Mark selection as not traced］ - 选择代码中所有已设置Hit跟踪的命令，均不进行Hit跟踪。

标记模块不跟踪［Mark module as not traced］ - 当前模块中所有已设置Hit跟踪的命令，均不进行Hit跟踪。

Run跟踪［Run trace］ - 处理Run跟踪命令，仅在分析过的代码中可用。

添加选择部分［Add selection］ - 在选择的代码上强迫设置Run跟踪，同时也设置了Hit跟踪。

添加函数过程［Add procedure］ - 在当前函数过程上强迫设置Run跟踪，同时也设置了Hit跟踪。

添加过程中的分支［Add branches in procedure］ - 在当前函数过程中对所有可识别的跳转或调用目的地址强迫设置Run跟踪，并去除该过程中的其他Run跟踪。同时也在整个函数过程上设置了Hit跟踪。

添加所有函数过程入口［Add entries of all procedures］ - 在当前模块中对所有可识别函数活的入口处强迫设置Run跟踪，并去除其他的命令上的Run跟踪。同时在所有可识别的函数过程是设置了Hit跟踪。

跟踪时忽略选择部分［Skip selection when tracing］ - 从Run跟踪中排除选定的准线性代码。当Run跟踪遇到排除的代码时，他会在选择部分的尾部设置一个临时断点，然后运行代码。这对加速Run跟踪非常有效。

设置条件［Set condition］ （Ctrl+T） - 设置条件以暂停Run跟踪.

统计当前模块［Profile current module］ - 打开当前模块的统计数据窗口。

全部统计［Global profile］ -打开整个应用程序的统计数据窗口。收集全部的统计数据会非常费时。

从选择部分移除［Remove from selection］ - 从选择部分移除强迫Run跟踪。

从模块中移除［Remove from module］ - 从当前模块中移除强迫Run跟踪。

跟进［Follow］ （回车） - 跟进到跳转、调用、返回或转换语句的目的地址。详见命令历史［Command history］.

跟进到立即数［Follow immediate constant］ - 如果命令中的立即数指向了另一条命令，则跟进另一条命令的地址。

跟进到异常句柄［Follow SE handler］ （ENTER） - 如果目前的命令建立了结构异常处理（SEH），则跟进到异常处理程序的入口。

新EIP［New origin here］ （Ctrl+*） - 设置当前所选线程的EIP为首个选择字节的地址。您可以在寄存器面板中选择EIP并撤消该操作。

转到［Go to］

EIP［Origin］（*） - 转到当前线程的EIP所指向的地址。

前一个［Previous］（-） - 转到命令历史中的前一个地址。 当开启Run跟踪缓冲区后，您将不能浏览运行历史。

前一条Run跟踪记录［Previous run trace record］（-） - 转到Run跟踪缓冲区的前一条记录。

下一个［Next］ （+） -转到命令历史中的下一个地址。 当开启Run跟踪缓冲区后，您将不能浏览运行历史。

下一条Run跟踪［Next run trace record］（+） - 转到Run跟踪缓冲区的下一条记录。

表达式［Expression］ （Ctrl+G） - 允许您转到十六进制地址或表达式的值。对话框会保留上一次输入的地址。为了方便区分，您可以给地址添加注释，只要在地址（或表达式）或注释文本之间加个分号就可以了。

前一个函数过程［Previous procedure］ （Ctrl+减号键） - 转到前一个已识别的函数过程的开始处。

下一个函数过程［Next procedure］ （Ctrl+加号键） -转到下一个函数过程的开始处。

前一个参考［Previous reference］ （Alt+F7） - 转到前一个找到的参考。在参考窗口中选择某个命令，反汇编窗口会同步移动。

下一个参考［Next reference］ （Alt+F8） - 转到下一个找到的参考。

源文件［Source file］ （Ctrl+F5） - 打开源代码窗口，并显示对应第一条选中命令的源代码。这个选项只有在可执行文件包含有 Borland 格式的调试信息时才有效。

Switch语句基址［Switch base］,

默认case［Default case］,

Case xxxx - 如果命令是Switch语句的基地址，则此菜单项能够在可识别的转换分支上浏览。

更多Case�［More cases...］ - 如果Case分支多于10个。那么会打开一个窗口来显示Switch语句的所有Case分支。

CALL 来自 xxxx［CALL from xxxx］,

JMP 来自 xxxx［JMP  from xxxx］

JNZ 来自 xxxx［JNZ from xxxx］,

JMP [ ] 来自 xxxx［JMP[] from xxxx］等 - 转到跳转或调用当前位置的命令。这可能是直接或间接的本地（模块间）调用、无条件跳转、条件跳转、或表分支［table switch］。注意：来自其他模块的调用是不被列出的，即使它们在出现在调用树中。

更多的跳转和调用�［More jumps and calls...］ （Ctrl+J） -如果所有的涉及到该位置的调用和跳转数目超过10个，那么会打开一个窗口来显示。快捷键总是可用就，即使该项没有在菜单中出现。

调用DLL输出［Call DLL export］ - 打开 调用输出函数［Call export］ 对话框。仅在您调试一个单独的DLL，并且首个选择的行是这个DLL的输出函数入口时，这个选项才可用。

线程［Thread］ - 多线程应用程序中，在不同的线程间快速切换。

跟进到数据面板［Follow in Dump］

选择部分［Selection］ - 在CPU数据面板中重新打开内存块，并跟进到选择的地址。

常量［Constant］ - 跟进立即数到CPU窗口面板。

地址常量［Address constant］ - 跟进地址中的常量到数据面板。例如，当前选择的命令为：MOV [ESI+123456],543210。跟进后，数据面板会显示地址0x123456处的内容。

立即数［Immediate constant］ - 跟进立即数到数据面板。例如，当前选择的命令为：MOV [ESI+123456],543210。跟进后，数据面板会显示地址0x543210处的内容。

暗含栈地址［Implicit stack address］ - 跟进操作中暗含由 ESP 定位的地址，像命令 PUSH 和 RET。

内存地址［Memory address］，

第一个地址［First address］，

第二个地址［Second address］ - 跟进地址到数据面板。例如，当前选择的命令为：MOV [ESI+123456],543210，并且 ESI 等于0x10。那么跟进内存地址后，数据面板将显示0x123466的内容。某些命令，像 MOVS，有两个内存操作数。在这中情况下，第一个地址为目的操作数，而第二个地址为源操作数。

查看调用树［View call tree］ （Ctrl+K） - 打开 调用树［Call tree］ 窗口显示所有已知的当前函数过程被调用的地址，以及当前函数所有调用了的函数。如果您希望扩展树到不同的模块中，请分析这些模块。

搜索［Search for］

当前模块中的名称（标签）［Name (label) in current module］ （Ctrl+N） -在表格中显示当前模块中定义或使用的所有标签 （输出、输入、库、用户自定义）。

所有模块中的名称［Name in all modules ］- 在表格中显示所有已知的名称。

命令［Command］ （Ctrl+F） -允许您搜索汇编命令。OllyDbg将尝试查找所有可能的译码形式。例如，如果您搜索命令MOV EAX,[123456]，那么它将查找 A1 56341290 和 8B05 56341200.两个序列。您也可以指定模糊命令,，比如 MOV R32,[CONST]----这样命令 MOV EAX,[10000] 和 MOV ESI,[123456]都会查找到。但这样的搜索不能查找某些更加复杂的地址形式。为了得到更好的结果，请在搜索前进行分析。

命令序列［Sequence of commands］ （Ctrl+S） - 允许您搜索汇编命令序列。该序列可以包含模糊命令 、匹配寄存器，还可以忽略中间的命令。

常量［Constant］ - 允许您在代码中查找一个常量。这个常量可以是地址、立即数、跳转的相对偏移或者转换表［Switch Table］的元素。为了达到更好的结果，请在搜索前，请分析代码。

二进制串［Binary string］（Ctrl+B） - 显示对话框并指定搜索形式.。搜索最大为256字节。您可以从比对中排除某些字节或半字节。例如，您可以指定搜索形式为12 ?? ?6 78，这将匹配到12 34 56 78和12 00 06 78，但不会匹配到12 34 55 78。您还可以忽略ASCII/UNICODE 字符的大小写。

修改命令［Modified command］ - 搜索下一条与备份不同的命令。

跟踪Hit［Trace hit］ - 搜索下一个在Hit 跟踪时标记了已执行的邻近命令块。

下一个［Next］ (Ctrl+L) -从选择处重复搜索上一次查找内容。

所有模块间调用［All intermodular calls］ - 搜索所有调用（直接或间接，以及可能中间经过几次跳转）了驻留在其他模块.中函数的命令。这对查找通过函数GetProcAddress().加载的API函数特别有用。

所有命令［All commands］ - 查找所有符合指定汇编格式的命令。

所有命令序列［All sequences］ - 查找所有符合指定格式的命令序列。

所有常量［All constants］ - 在当前模块的代码段中，查找所有符合的常量。

所有转换语句［All switches］ - 显示在当前模块中所有可识别的转换语句的列表。、

所有参考文本串［All referenced text strings］ - 在当前模块代码段中，搜索所有参考的 ASCII 和 UNICODE 串。

用户自定义标签［User-defined label］ - 在表格中显示当前模块中所有用户自定义标签。

用户自定义注释［ser-defined comment］ - 在表格中显示当前模块中所有用户自定义注释。

在Run跟踪中最近的一条记录［Last record in run trace］ - 在Run跟踪 缓冲区中，搜索首个的选择命令最近发生的一条记录。

查找参考［Find references to］ - 以下各项用于对当前模块的代码段，搜索指定的命令参考。为了得到更好的结果，请在搜索前分析代码：

选择的命令［Selected command］ （Ctrl+R）,

选择的地址［Selected address］ （Ctrl+R） - 首个选择的地址；

选择的块［Selected block］ - 选择的范围；

立即数［Immediate constant］ - 首个选择命令中的立即数；

地址常量［Address constant］ - 首个选择命令中的地址常量；

调用目的地址［Call destination］ - 首个选择命令中的目的地址；

跳转目的地址［Jump destination］ - 首个选择命令中的跳转目的地址；

调用常量［Call constant］，

跳转常量［Jump constant］ - 首个选择命令中的目的地址常量。

停止直到返回Stop till return （Esc） - 停止执行直到返回［Execution till return］.

停止跟踪［Stop tracing］ （Esc） - 停止Run跟踪［Run tracing］.

停止自动跟踪［Stop animation］ （Esc） - 停止自动跟踪［Animation］.

查看［View］

源代码［Source file］ （Ctrl+F5） - 打开源代码窗口，并显示对应第一条选中命令的源代码。这个选项只有在可执行文件包含有Borland格式的调试信息时才有效。

原始注释［Original comments］ - 在反汇编窗口的第四栏显示注释。如果列标题栏可见，那么单击注释列标题栏，可以在注释［comments］、源代码［source］、统计［profile］间切换。

源代码作为注释［Source as comments］ - 在反汇编窗口的第四栏（通常显示注释）显示源代码命令。如果列标题栏可见，那么单击注释列标题栏，可以在注释、源代码、统计间切换。该选项仅在可执行文件包含 Borland 格式的调试信息时可用。

统计作为注释［Profile as comments］ - 显示每条命令在Run跟踪缓冲区中出现的次数 。如果列标题栏可见，那么单击注释列标题栏，可以在注释、源代码、统计间切换。该选项仅在统计数据打开后才可用。

可执行文件［Executable file］ -以首个选择的字节为偏移位置，显示可执行文件的全部数据。如果选择的不在文件中，则数据的偏移位置为0。

绝对地址［Absolute address］ - 在第一栏中显示绝对地址。

相对地址［Relative address］ - 显示与当前选择位置的相对地址。另外，您还可以在第一栏中双击某个地址，以作为基地址。

模块'xxx'［Module 'xxx'］ - 显示选择模块的可执行代码。

复制到可执行文件［Copy to executable］

选择部分［Selection］ - 复制选择部分到可执行文件。如果有重定位，OllyDbg会调整重定位，并警告您该操作可能会产生错误。

所有改动［All modifications］ - 复制全部高亮显示的修改部份（也就是真实代码与全局备份［Global backup］的不同之处）到可执行文件中。

分析［Analysis］

分析代码［Analyze code］ (Ctrl+A) - 分析 当前模块的代码段。如果分析数据可用，那么OllyDbg其他部分功能将更可靠。

移除分析［Remove analysis］ - 放弃当前模块的分析数据。

扫描目标文件［Scan object files］ （Ctrl+O） - 允许您选择 Object 文件或 Library 文件，并在当前模块的代码段中找到它们的位置。

移除目标扫描［Remove object scan］ - 放弃目标扫描的结果。

假定参数［Assume arguments］ - 允许对待选择的首个命令，为一个带预定义参数的函数入口。目前可用的函数类型包括：

WinProc(hWnd,msg,wParam,lParam) - 处理消息的窗口函数

WinMain(hInst,hPrevInst,CmdLine,ShowState) - 程序入口

DllEntryPoint(hInst,CallReason,pReserved) - DLL入口

Format(format,...) - 与printf类似的函数

Sformat(ptr,format,...) - 与sprintf类似的函数

StdFunc0(void) - 不带参数的函数

StdFunc1(int) - 带一个参数的函数

……

StdFunc8(int,int,int,int,int,int,int,int) - 带8个参数的函数

从选择部分移除分析［Remove analysis from selection］（退格键） - 从选择的部份移除分析。在分析器［Analyzer］ 将代码误认为是数据的情况下，这个选项非常有用。

在下次分析时，将选择部分视为［During next analysis, treat selection as］ - 设置解码提示.。

获得符号名相关帮助［Help on symbolic name］ - 如果首个选择的命令行包含符号名，并且API 帮助文件 已经挂接到OllyDbg上，则尝试打开关于该符号名的帮助主题。

外观［Appearance］ - 详见这里.


Appearance menu
外观菜单［Appearance menu］

在大多的OllyDbg窗口中都含有这个菜单。它允许自定义独立的窗口或面板的外观。

总在最上面［Always on top］ - 保持该窗口在其它MDI（多文档界面）窗口之上。最多同时仅允许一个MDI窗口总在最上面。注意，对于老的插件创建的窗口，这个选项可能是不正确的。

显示列标题栏［Show bar］ - 在窗口上显示列标题栏。在某些窗口上列标题栏可以进行排序，或改变数据形式，或切换真实数据与备份等用途。

隐藏列标题栏［Hide bar］ - 移除窗口的列标题栏。

显示水平滚动条［Show horizontal scroll］ - 显示水平滚动条，以便窗口可以左右滚动。另外您还可以使用滚动条两边的左右箭头。

隐藏水平滚动条［Hide horizontal scroll］ - 移除水平滚动条。

默认列宽［Default columns］ - 将表格中所有栏目的宽度恢复为默认值。

字体［Font］,

该窗口字体［Font (this)］,

全部字体［Font (all)］ - 允许您对当前选择的面板包括所有CPU窗口上面板，进行改变窗口中的字体操作。OllyDbg默认定义了以下几种字体：

OEM fixed font	- 标准字体
Terminal	- 紧凑易读的字体
System fixed font	- 标准字体
Courier	- 支持UNICODE
Lucida	- 支持UNICODE, 但一般在Windows 95/98系统下无法使用

您可以添加自己的字体，或修改已定义的字体。

颜色［Colors］,

该窗口颜色［Colors (this)］,

全部颜色［Colors (all)］ -允许您对当前选择的面板包括所有CPU窗口上面板，进行改变窗口中的颜色操作。OllyDbg默认定义了以下几种颜色方案：

白底黑字［Black on white］	- 白色背景，黑色字符
蓝底黄字［Yellow on blue］	- 深蓝背景，黄色字符
海蓝［Marine］	- 异样的蓝色调
大部分黑色［Mostly black］	- 黑色背景，白色字符

您可以创建自己的方案，或对已存在的进行编辑。

高亮［Highlighting］ - 允许您为反汇编的代码选择或禁止高亮显示 。您可以创建自己的高亮方案。有两个预定义的方案，Chrismas tree 和 Jumps'n'calls, 它们都在黑底白字［Black on white］颜色方案上表现最佳。.


Dump
数据窗口［Dump］

数据窗口用于显示内存或文件的内容。您可以从以下预处理格式［predefined formats］中选择一种显示方式：字节［byte］、文本［text］、整数［integer］、浮点数［float］、地址［address］,反汇编［disassembly］、 PE头［PE Header］。

所有的dump窗口支持备份［backup］、搜索和编辑操作。CPU 窗口［CPU window］的Dump面板允许您对可执行代码的数据和可执行文件（.exe，或.dll）的内存映射做如下操作：定义标签［labels］、设置 内存断点［memory breakpoints］, 查找参考［references］。数据菜单［Dump menu］只显示与选中部分相关的命令。

如果 备份［backup］可用，则单击第一个列标题栏，会在地址［Address］/备份［Backup］ 两种显示模式之间切换。点击其他列标题栏，会改变Dump模式。

像反汇编窗口一样，数据窗口也保存了大量查看内存地址的历史记录。您可以通过“+”和“-”键来访问您过去查看过的数据地址空间。

要翻动一字节的数据，可以按住Ctrl l键并按上/下方向键。


Dump menu
数据窗口的菜单［Dump menu］

备份［Backup］ - 请看这里

撤消选择部份［Undo selection］ （Alt+Backspace） -用相应的备份数据替换转中部份的代码。仅在备份数据存在且与选中部分不同时有效。

复制［Copy］

To clipboard (Ctrl+C) - 以当前格式复制选择部分到剪切板。如果复制时要排除栏目，请减小其的宽度到最小（在这时，栏目的剩余部分呈灰色）。如果某些文本程度大于栏目宽度，OllyDbg将使用“>'”替代栏目中无法显示的字符。

To file -复制选择的部分到文件。用法和复制选择部分到剪切板相同，但复制的大小没有限制。

Select all - 选择整个内存块。

二进制［Binary］

编辑［Edit］ （Ctrl+E 或十六进制数字） - 允许您以 ASCII、UNICODE 或十六进制格式编辑选择的部分。这三个编辑控件紧密联系，同步滚动（三个框内的第一个字符总是相同的），同步显示您对任何控件的修改。通过按 Ctrl+↑或 Ctrl+↓ 可以迅速移动到不同窗口的该字符相应位置。编辑的最大长度是256字节。未完成的字符用红色的问号表示。如果十六进制串中包换了半个字节，OllyDbg会用0补足。当“保持大小［Keep size］选项开启时，您将不能插入或删除字符，也不能在数据尾部追加字符。

用00填充［Fill with 00�s］ - 选择部分的数据用零填充。

用FF填充［Fill with FF�s］ - 选择部分的数据用零填充。

二进制复制［Binary copy］ - 复制选择部分的数据为十六进制字符，并保存在剪切板中。

二进制粘贴［Binary paste］ - 从剪切板中粘贴十六进制数据到选择的部分。OllyDbg会在剪切板中扫描文本，并从中提取出十六进制数字（0..9, A..F, a..f）和疑问标记（?），而其他符号都会被忽略掉。没有选择的数据不会发生变化。如果最后一字节只包含一个十六进制数，那么它会被忽略掉。例如，“part of data” 解释出的是 AF DA 而不是 AF DA 0A。

复制时标记重定位［Copy with masked fixups］ -与复制二进制相同，但会用疑问标记替代所有重定位的地址，以方便搜索相似的代码片断。参见搜索二进制串［Search for binary strings］。

修改［Modify］ - 允许您修改第一个选择项的值（整数或浮点形式）。

编译［Assemble］ - 允许您从选择的第一个字节开始，用一到多条汇编命令重写数据。详见汇编器［Assembler］。

修改字节［Modify byte］ - 允许您以带符号十进制、无符号十进制、或十六进制形式编辑选中的字节。

修改整数［Modify integer］ - 允许您以带符号十进制、无符号十进制、或十六进制形式编辑选中的整型常量。

修改浮点［Modify float］ -  允许您编辑选中的浮点常量。

修改标签［Label］（:） -允许您设定首个选择地址上的用户自定义标签［Label］ 。

编辑标签［Edit label］（:） - 允许您编辑或去除首个选择地址上的用户自定义标签［Label］ 。

断点［Breakpoint］

访问内存［Memory, on access］ - 在选择的数据上设置内存断点。每次这部分内存被访问，程序都会暂停。OllyDbg 支持任何大小的单内存断点。内存断点会造成执行速度的大幅下降。在 Windows 95/98 下，当系统程序访问包含内存断点的内存块时，还可能导致被调试程序的崩溃。因此，除非必要，请不要使用。

写内存［Memory, on write］ - 在选择的数据上设置内存断点。每次这部分内存被写入，程序都会暂停。OllyDbg 支持任何大小的单内存断点。内存断点会造成执行速度的大幅下降。在 Windows 95/98 下，当系统程序访问包含内存断点的内存块时，还可能导致被调试程序的崩溃。因此，除非必要，请不要使用。

移除内存断点［Remove memory breakpoint］ - 移除内存断点。

移除自解压内存断点［Remove SFX memory breakpoint］ - 停止搜索自解压（SFX）程序.真实的入口。这个搜索使用了特殊类型的内存断点。

硬断点，访问时［Hardware, on access］ - 在首个选择字节设置硬件内存断点，断点可能是1、2或4字节的并且必须对齐。每次这个内存被访问，程序都会暂停。硬件断点仅在 Windows ME、NT 或 2000 系统下可用。80x86处理器支持最多4个硬件断点。如果OllyDbg不能找到可用的硬件断点，那么您会询问您是否移除某个已存在的硬断点。

硬断点，写入时［Hardware, on write］ - 在首个选择字节设置硬件内存断点，断点可能是1、2或4字节的并且必须对齐。每次这个内存被写入，程序都会暂停。硬件断点仅在 Windows ME、 NT 或 2000 系统下可用。80x86处理器支持最多4个硬件断点。如果OllyDbg不能找到可用的硬件断点，那么您会询问您是否移除某个已存在的硬断点。

硬断点，执行时［Hardware, on execution］ - 在首个选择字节设置硬件内存断点。每次以这个字节作为开始的命令执行时，程序都会暂停。硬件断点仅在Windows ME、NT 或 2000系统下可用。80x86处理器支持最多4个硬件断点。如果OllyDbg不能找到可用的硬件断点，那么您会询问您是否移除某个已存在的硬断点。

搜索［Search for］

命令［Command］ （Ctrl+S） - 允许您搜索汇编命令。OllyDbg将尝试查找所有可能的译码形式。例如，如果您搜索命令MOV EAX,[123456]，那么它将查找 A1 56341290 和 8B05 56341200.两个序列。您也可以指定模糊命令,，比如 MOV R32,[CONST] ----这样命令 MOV EAX,[10000] 和 MOV ESI,[123456]都会查找到。但这样的搜索不能查找某些更加复杂的地址形式。

整数［Integer］，

地址［Address］ - 允许您在数据窗口中搜索16位或32位常量。搜索可以是对齐的，这时OllyDbg只搜索能显示在窗口中数据（也就是说搜索步长与显示元素的字长大小相同）；也可以是不对齐的，这时将搜索每个字节。

浮点［Float］ - 允许您在数据窗口中搜索32位、64位、或80位浮点常量。搜索可以是对齐的，这时OllyDbg只搜索能显示在窗口中数据（也就是说搜索步长与显示元素的字长大小相同）；也可以是不对齐的，这时将搜索每个字节。您也可以设置允许有0.1%的误差，这样对您搜索非整数常量十分有用，比如2/3=0.6666666...。

二进制串［Binary string］（Ctrl+B） - 显示对话框并指定搜索形式.。搜索最大为256字节。您可以从比对中排除某些字节或半字节。例如，您可以指定搜索形式为12 ?? ?6 78，这将匹配到12 34 56 78和12 00 06 78，但不会匹配到12 34 55 78。您还可以忽略ASCII/UNICODE 字符的大小写。

修改数据［Modified data］ - 搜索下一个与备份数据不同的地址。

下一个［Next］（Ctrl+L） - 从选择处重复搜索上一次查找内容。

名称（标签）［Name (label)］ （Ctrl+N） - 在表格中显示当前模块中所有的标签 （输出、输入、库、用户自定义）。

跟进DWORD到反汇编窗口［Follow DWORD in Disassembler］,

跟进到反汇编窗口［Follow in Disassembler］ - 跟进首个选择的四字节内容到反汇编窗口中。

跟进DWORD到数据［Follow DWORD in Dump］,

跟进到数据［Follow in Dump］ - 跟进首个选择的四字节内容到CPU数据面板中。

查找参考［Find references］（Ctrl+R） - 搜索在模块的代码段中所有对选择的地址范围进行操作的命令参考。为了得到更好的结果，请在搜索前对代码进行分析。

查看可执行文件［View executable file］ - 以首个选择的字节为偏移位置，显示可执行文件的全部数据。如果选择的不在文件中，则数据的偏移位置为0。

复制到可执行文件［Copy to executable file］ - 复制选择部分到可执行文件。OllyDbg会调整重定位，并会提示您这样做可能会产生问题。复制这部分数据时请小心，因为其中重要的初始化部分可能已经被代码修改过。

保存文件［Save file］ - 如果这是整个文件的数据，将其写到磁盘中。

转到表达式［Go to expression］，

转到地址［Go to address］，

转到偏移［Go to offset］ - 根据指定的地址或表达式的值（或该文件数据的偏移），定位数据地址。

转到［Go to］

表达式［Expression］ - 根据指定表达式的值定位数据地址。

前一个［Previous］ （减号键） - 转到数据历史［Dump History］中的前一个选择。.

下一个［Next］ （加号键） -转到数据历史中的后一个选择。

在反汇编窗口查看映射［View image in Disassembler］,

在CPU数据窗口查看映射［View image in CPU Dump］ - 如果在数据窗口显示某个模块加载的可执行文件（.exe或.dll），显示其在内存映射中。

十六进制［Hex］

Hex/ASCII（16字节）［Hex/ASCII (16 bytes)］ - 显示数据为十六进制和 ASCII 两种形式，16字节每行。

Hex/ASCII（8字节）［Hex/ASCII (8 bytes)］ - 显示数据为十六进制和 ASCII 两种形式，8字节每行。

Hex/UNICODE（16字节）［Hex/UNICODE (16 bytes)］ - 显示数据为十六进制和 UNICODE 两种形式，16字节每行。

Hex/UNICODE（8字节）［Hex/UNICODE (8 bytes)］ -显示数据为十六进制和 UNICODE 两种形式，8字节每行。

文本［Text］

ASCII（64个字符）［ASCII (64 chars)］ - 显示数据为 ASCII 形式，每行64个字符。

ASCII（32个字符）［ASCII (32 chars)］ - 显示数据为 ASCII 形式，每行32个字符。

UNICODE（64个字符）［UNICODE (64 chars)］ - 显示数据为 UNICODE 形式，每行64个（128字节）字符。按Ctrl+↑或Ctrl+↓可以只移动一个字节，从而改变数据对齐。

UNICODE（32个字符）［UNICODE (32 chars)］ -显示数据为 UNICODE 形式，每行32个（64字节）字符。

短整型［Short］

带符号十进制［Signed decimal］ - 显示数据为16位带符号十进制数（每行8个）。按Ctrl+↑或Ctrl+↓可以只移动一个字节，从而改变数据对齐。

无符号十进种［Unsigned decimal］ - 显示数据为16位无符号十进制数（每行8个）。

十六进制［Hex］ - 显示数据为16位十六进制数（每行8个）。

长整型［Long］

带符号十进制［Signed decimal］ -显示数据为32位带符号十进制数（每行4个）。按Ctrl+↑或Ctrl+↓可以只移动一个字节，从而改变数据对齐。

无符号十进制［Unsigned decimal］ - 显示数据为32位无符号十进制数（每行4个）。

十六进制［Hex］ - 显示数据为32位十六进制数（每行4个）。

地址［Address］ - 显示数据为32位地址，并尝试解码地址的含义。栈窗口就是这样的形式。

带ASCII数据的地址［Address with ASCII dump］ -显示数据为32位地址和ASCII数据两种形式，并尝试解码地址的含义。

带UNICODE数据的地址［Address with UNICODE dump］ -显示数据为32位地址和UNICODEI数据两种形式，并尝试解码地址的含义。.

浮点［Float］

32位浮点数［32-bit float］ - 显示数据为32位浮点数（每行4个）。如果数据不是有效的浮点数。OllyDbg 将显示数据类型（NAN［不是数］、INF［无穷］）并在后面跟上十六进制数据。按Ctrl+↑或Ctrl+↓可以只移动一个字节，从而改变数据对齐。

64位浮点数［64-bit double］ - 显示数据为64位浮点数（每行2个）。如果数据不是有效的浮点数。OllyDbg将显示数据类型（NAN、INF）并在后面跟上十六进制数据。

80位浮点数［80-bit long double］ -显示数据为80位浮点数（每行1个）。如果数据不是有效的浮点数。OllyDbg将显示数据类型（NAN、INF、UNORM［非正常］）并在后面跟上十六进制数据。

反汇编［Disassemble］ - 以代码的形式显示数据。

特殊［Special］

PE头［PE header］ - 以带注释的可执行文件COFF头格式显示数据。

外观［Appearance］ - 详细描述，请查看这里


Stack window
栈窗口［Stack window］

CPU窗口的栈面板用于显示当前线程的栈。当被调试程序暂停运行时，栈窗口一般会自动滚动将当前 ESP 指向的地址放在窗口的第一条。并且这个地址被高亮显示。在某些情况下禁止滚动会更方便一些，您可以通过快捷菜单或单击名为“地址［Address］”的列标题栏，来实现这一点。

OllyDbg能够识别可能的返回地址。如果栈中地址指向了一个调用的下条命令，OllyDbg会高亮显示这一行，并报告是那个函数调用地址。但是，您必须小心。经常（不是说，大多数）这样的地址可能是前一个调用的残余。

栈窗口还跟踪结构异常处理链（SEH），并注释处理地址和指向该链下一条记录的指针。SHE链的开始地址是相应线程数据块的前四字节。您可以用转到表达式 [FS:0] ，定位这个地址。

您可以让 OllyDbg 跟踪栈框架。函数执行PUSH EBP; MOV EBP,ESP 或 ENTER xxx,0命令便创建了栈框架。再次警告：我不保证找到的栈框架就是真实存在的。

如果 EIP 指向的调用或跳转是一个已知函数或指向已知函数本身，OllyDbg将会解码这个函数在栈中的参数。

如果调试信息可用，OllyDbg将会标记在栈中的这个函数的参数和局部变量。他们只有在栈框架创建后才可用。

栈快捷菜单包含以下功能：

地址［Address］

绝对［Absolute］ - 让OllyDbg显示绝对十六进制地址。

相对选择位置［Relative to selection］ - 让 OllyDbg 显示相对于选择位置的栈地址。如果您改变选择位置，基地址任保持不变。另外，您还可以通过双击地址来实现这个功能。

相对ESP［Relative to ESP］ - 让 OllyDbg 显示相对于当前线程 ESP 内容的栈地址。如果寄存器 ESP 的内容改变，则基地址也随之变化。

相对EBP［Relative to EBP］ -让 OllyDbg 显示相对于当前线程 EBP 内容的栈地址。如果寄存器 EBP 的内容改变，则基地址也随之变化。

显示ASCII数据［Show ASCII dump］ - 另建一栏，用于显示 ASCII 数据。

显示UNICODE数据［Show UNICODE dump］ -另建一栏，用于显示 UNICODE 数据。

隐藏数据［Hide dump］ - 关闭 ASCII 或 UNICODE 数据栏。

锁定栈［Lock stack］ - 在每次程序暂停时，禁止根据当前 ESP 的内容自动滚动栈窗口。您也可以单击名为“地址［Address］”的列标题栏来实现。滚动禁止后，列标题栏会变为“锁定［Locked］”。

解锁栈［Unlock stack］ -在每次程序暂停时，允许根据当前 ESP 的内容自动滚动栈窗口。您可以单击名为“锁定［Locked］” 的列标题栏来实现。滚动允许后，列标题栏会变为“地址［Address］”。

复制到剪切版［Copy to clipboard］ (Ctrl+C) - 复制选择部分到剪切板。如果复制时要排除栏目，请减小其的宽度到最小（在这时，栏目的剩余部分呈灰色）。如果某些文本程度大于栏目宽度，OllyDbg将使用“>'”替代栏目中无法显示的字符。

修改［Modify］ - 编辑首个选择地址的四字节内容。

编辑［Edit］ （Ctrl+E） - 以ASCII, UNICODE 或十六进制格式编辑选择部份。

Push DWORD - ESP 减 4。

Pop DWORD - ESP 加 4。

搜索地址［Search for address］ - 在栈中搜索内容。搜索可以是对齐的，也可以不是对齐。通常所有的常量入栈时都是对其的。

搜索二进制串［Search for binary string］（Ctrl+B） - 显示对话框并指定搜索形式.。搜索最大为256字节。您可以从比对中排除某些字节或半字节。例如）您可以指定搜索形式为12 ?? ?6 78，这将匹配到12 34 56 78和12 00 06 78，但不会匹配到12 34 55 78。您还可以忽略ASCII/UNICODE 字符的大小写。.

转到ESP［Go to ESP］（星号） -在栈窗口中转到当前线程寄存器的ESP所指向的地址。

转到EBP［Go to EBP］ - 在栈窗口中转到当前线程寄存器的EBP所指向的地址。

转到表达式［Go to expression］ (Ctrl+G) - 按指定表达式的值定位栈。

跟进到反汇编窗口［Follow in Disassembler］ （回车） - 跟进首个选择的四字节内容到反汇编窗口。

跟进到数据窗口［Follow in Dump］ - 跟进首个选择的四字节内容到数据面板。

跟进到栈［Follow in Stack］ - 跟进首个选择的四字节内容到栈面板。

外观［Appearance］ - 详见这里


Executable modules window
可执行模块窗口［Executable modules window］

可执行模块窗口（快捷键：Alt+E）列出了当前被调试进程加载的所有可执行模块。它也显示了很多有用的信息，比如模块大小、入口地址、模块版本、以及可执行文件路径等。一些信息，如以十进制显示的模块大小、入口地址的符号名、是否为系统模块等，通常是被隐藏的。如果想看，可以增加相应栏的宽度。快捷菜单支持以下操作：

刷新［Actualize］ - 重新扫描模块并去除对新加载模块的高亮显示。在大多数情况下，OllyDbg会自动完成该操作。

查看内存［View memory］ - 打开内存窗口，并定位到属于该模块镜像的第一个内存块处。

在CPU窗口中查看代码［View code in CPU］ （快捷键：回车键） - 在反汇编窗口中显示模块的可执行代码。

跟进到入口［Follow entry］ - 在反汇编窗口中跟进到模块的入口处。

在CPU窗口中查看数据［Dump data in CPU］ -在CPU窗口的数据面板中显示模块的数据段。块代码段。

显示名称［View names］ （快捷键：Ctrl+N） -显示当前模块定义或使用的全部名称［names］（包括输出表、引入表、链接库、用户自定义）。

标记为系统DLL［Mark as system DLL］，

标记为非系统DLL［Mark as non-system DLL］ - 将选中模块标记为系统或非系统属性。如果设置为系统属性，则在Run跟踪［Run trace］ 时会直接执行（不进行跟踪）这个模块，从而大大加快跟踪速度。默认情况下，所有驻留在系统目录（通常在Windows 95/98下为c:\windows\system ，在WinNT/2000/XP下为c:\winnt\system32）的模块都认为是系统模块。

立即更新.udd文件［Update .udd file now］ -向文件“<模块名>.udd”写入模块相关的全部数据，udd文件保存了在调试期间设置的断点、标签、注释、监视、分析等信息。当模块卸载时OllyDbg会自动创建.udd文件。

查看可执行文件［View executable file］ - 显示可执行文件的全部内容。

查看全部资源［View all resources］ - 以列表形式显示模块定义的全部资源，并带有一个简短信息。OllyDbg并不把资源当作单独实体来支持。您可以提取［Dump］并以二进制的形式进行编辑。

查看资源字符串［View resource strings］ -以列表形式显示资源字符串及其标识符。

查看Run跟踪的统计［View run trace profile］ - 在此模块中计算统计［profile］ 。相关信息：Run跟踪［Run trace］.

分析全部模块［Analyze all modules］ -允许同时分析全部模块。分析将从代码中提取大量的有用信息；代码经过分析后再进行调试，通常会非常快并且可靠。

鼠标双击某一行，将会在反汇编窗口中显示模块的执行代码。


Memory map
内存映射窗口［Memory map window］

内存映射窗口显示了被调试程序分配的所有内存块。因为没有标准的方法来完成这项任务，所以OllyDbg可能会把一个大的内存块分成几个部分。然而，在大多数情况下，并非一定要精确处理。如果想查看由应用程序通过调用GlobalAlloc()和LocalAlloc()等申请的内存块列表，请使用堆列表［Heap list］。

如果内存块是可执行模块的一个节，OllyDbg则会报告这个内存块所包含的数据类型：代码、数据、资源等。

Windows95/98是和WindowsNT/2000是有一些区别的。在Windows95/98下，OllyDbg是不能显示被映射文件的名称的。另外，Windows95/98不允许的访存类型为读和写，然而，在WindowsNT/2000下，OllyDbg却有拥有更多功能，包括执行访问，写复制［copy-on-write］以及监视标志位。OllyDbg忽略写复制［copy-on-write］属性。

如果OllyDbg发现程序分配了新内存或者重新分配了已经存在的内存块，它将在内存映射窗口中高亮显示相应的记录，去掉高亮度显示，可以选择快捷菜单中的刷新［Actualize］项。

您可以按Alt+M来调用内存窗口。

以下是快捷菜单中可以选择的菜单项：

刷新［Actualize］ - 更新已分配内存的列表并去除对新内存块的高亮显示。

在反汇编窗口中查看［View in Disassembler］ -在反汇编窗口中查看：在反汇编窗口中打开内存块，这一选项仅在某些模块的内存块中包含可执行代码或者自解压器时可用。

在CPU数据窗口中查看［Dump in CPU］ - 在CPU的数据窗口中显示内存块的内容。

数据窗口［Dump］ - 在单独窗口中显示内存块内容。如果内存块的类型已知，则OllyDbg会自动选择显示格式。

查看全部资源［View all resources］ - 如果内存块包含资源数据，则列出所有资源及相关数据。OllyDbg并不把资源当作单独实体来支持。您可以显示其数据并以二进制的形式进行编辑。

查看资源字符串［View resource strings］ - 如果内存块包含资源数据，则列出全部资源字符串及其标识符。

搜索［Search］ - 允许搜索所有的内存块，从选择处开始，搜索匹配的二进制串。如果找到，则OllyDbg将显示该内存块。内存映像窗口和数据窗口共享同一种搜索模式，所以您可以在弹出的数据窗口中立即继续搜索该二进制串出现的下一位置。按Esc键可以关闭数据窗口。

搜索下一个［Search next］（快捷键：Ctrl+L） - 继续上次搜索。

设置访问中断［Set break-on-access］ （快捷键：F2，仅在WindowsNT/2000下可用） - 保护整个内存块。当中断发生后OllyDbg暂停被调试程序并清除断点。这类断点在您想捕捉调用或返回到某个模块的时候特别有用。

清除访问中断［Remove break-on-access］ （快捷键：F2） - 从内存块中清除访问中断保护。

设置内存访问断点［Set memory breakpoint on access］ - 在整个内存块上设置断点，每当该内存块被访问时程序都将中断。OllyDbg只支持一个内存访问断点。在Windows95/98下，当系统程序访问含有内存断点的内存块时，可能会导致所被调试程序崩溃，因此，不到万不得已，请不要设置这种断点。

设置内存写入断点［Set memory breakpoint on write］ - 在整个内存块上设置断点，每当该内存块被写入数据时程序都将中断。在Windows95/98下，当系统程序访问含有内存断点的内存块时，可能会导致所被调试程序崩溃，因此，不到万不得已，请不要设置这种断点。

清除内存断点［Remove memory breakpoint］ - 清除内存断点。

清除自解压内存断点［Remove SFX memory breakpoint］ - 停止搜索自解压程序［self-extractable (SFX) program］的真实入口。这个搜索使用了特殊类型的内存断点。

访问设置［Set access］ -设置整个内存块的保护属性，可选择的有：

禁止访问［No access］

只读［Read only］

读/写［Read/write］

执行［Execute］

执行/读［Execute/read］

完全访问［Full access］

复制到剪切板［Copy to clipboard］

整行［Whole line］ -以多行文本（包括解释）的方式把所选记录复制到剪切板，如果复制时想排除某些列，可将该列的宽度置为最小（该栏剩余的边框将变灰）。

整个表格［Whole table］ -以多行文本的方式将整个内存映像信息复制到剪切板，该文本的第一行为窗口标题（"内存映射［Memory map］"）， 第二行为列标题栏，后面几行的内容为内存数据记录。复制将保持列的宽度。如果复制时想排除某些列，可将该列的宽度置为最小（该栏剩余的边框将变灰）。

外观［Appearance］ - 点击这里.


Watches and inspectors
监视与监察器［Watches and inspectors］

监视［Watch］ 窗口包含若干个表达式［expressions］。它在第二列里显示这些表达式的值。OllyDbg 会把这些表达式保存到主模块的.UDD文件中，因此它们在下一次调试时同样有效。

监察器［inspector］是显示若干变量、1/2维数组或是选定项目结构数组［selected items of array of structures］的独立窗口。它的表达式与监视窗口中的基本相同，只是多包含了两个参数：%A和%B。您可以指定这两个参数的界限，OllyDbg将会用所有可能的组合代替表达式中的%A和%B。从0开始一直到界限（不包含界限），并在表格中显示结果。参数%B（列数）的界限不能超过16。

例如，如果您指定了表达式%A+%B，并且限定%A和%B的上限为3，您将获得如下的表格：

译者注：监视窗口在view菜单中，监察器在debug菜单中。


Threads
线程［Threads］

OllyDbg 以简单而有效的线程管理为特色。如果您单步调试、跟踪、执行到返回或者执行到所选，则线程管理器将停止除当前线程以外的所有线程。即使当前线程被挂起，它也会将其恢复。在这种情况下，如果您手动挂起或者恢复线程，动作将被延期。如果您运行被调试的应用程序，OllyDbg将恢复最初的线程状态。（从调试器的角度来看，Hit跟踪［hit trace］和自由运行是等效的）。

依据这种方案，线程窗口可能会有如下五种线程状态：

激活［Active］	- 线程运行中，或被调试信息暂停t
挂起［Suspended］	- 线程被挂起
跟踪［Traced］	- 线程被挂起，但OllyDbg正在单步跟踪此线程
暂停［Paused］	- 线程是活动的，但OllyDbg临时将其挂起，并在跟踪其它的线程
结束［Finished］	- 线程结束
.

线程窗口同时也显示了最后的线程错误（GetlastError函数的返回值）并计算该线程以用户模式和系统模式（仅NT/2000/XP）运行的时间。线程窗口还会高亮主线程的标识符。

以下在快捷菜单中可用：

刷新［Actualize］ - 标记所有线程为旧的。

挂起［Suspend］ - 挂起线程。

恢复［Resume］ - 恢复先前挂起的线程。

设置优先级［Set priority］ - 调整进程中线程的优先级。以下选项可用：

空闲［Idle］	- 进程中线程的最低优先级
最低［Lowest］
低［Low］
标准［Normal］
高［High］
最高［Highest］
时间临界［Time critical］	- 最高优先级

在CPU窗口打开［Open in CPU］（双击）- 在CPU窗口中显示所选线程的当前状态。

复制到剪切板［Copy to clipboard］

整行［Whole line］ -全部行--以多行文本的形式并带注释将所选记录复制到剪切板。如果在复制时想排除某个栏目，可以将该栏的宽度置为最小（栏目的残留部分将变灰）。

整个表格［Whole table］ - 整个表格--以多行文本的形式将整个内存映象复制到剪切板，该文本的第一行包含窗口标题（“内存映射［Memory map］”），第二行是栏目标题，所有后继行是内存数据记录。复制将保持栏目的宽度。如果在复制时想排除某些栏目，可以将该栏的宽度置为最小（栏目的残留部分将变灰）。

外观 - 请查看这里.


Evaluation of expressions
表达式赋值［Evaluation of expressions］

OllyDbg能够支持非常复杂的表达式。表达式的语法格式将在这个主题的后面进行介绍，但我想您对此不一定真的感兴趣。那么我先举几个实例来说明：

10 - 常量 0x10 （无符号）。所有整数常量都认为是十六进制的，除非后面跟了点；

10. - 十进制常量10（带符号）；

'A' - 字符常量 0x41；

EAX - 寄存器EAX的内容，解释为无符号数；

EAX. -寄存器EAX的内容，解释为带符号数；

[123456] - 在地址123456处的无符号双字内容。默认情况，OllyDbg假定是双字长操作数；

DWORD PTR [123456] - 同上。关键字 PTR 可选；

[SIGNED BYTE 123456] - 在地址123456处带符号单字节。OllyDbg支持类MASM和类IDEAL两种内存表达式；

STRING [123456] - 以地址123456作为开始，以零作为结尾的ASCII字符串。中括号是必须的，因为您要显示内存的内容；

[[123456]] - 在地址123456处存储的双字所指向的地址内的双字内容；

2+3*4 - 值为14。OllyDbg 按标准C语言的优先级进行算术运行；

(2+3)*4 - 值为20。使用括号改变运算顺序。

EAX.<0. - 如果EAX在0到0x7FFFFFFF之间，则值为0，否则值为1。注意0也是有符号的。当带符号数与无符号数比较时，OllyDbg会将带符号数转成无符号数。

EAX<0 - 总为0（假），因为无符号数永远是正的。

MSG==111 - 如果消息为WM_COMMAND，则为真。0x0111是命令 WM_COMMAND 的数值。MSG只能用于设置在进程消息函数的条件断点内。

[STRING 123456]=="Brown fox" - 如果从地址0x00123456开始的内存为ASCII字符串"Brown fox"、"BROWN FOX JUMPS"、 "brown fox???"，或类似的串，那么其值为1。比较不区分大小写和文本长度。

EAX=="Brown fox" - 同上，EAX按指针对待。

UNICODE [EAX]=="Brown fox" - OllyDbg认为EAX是一个指向UNICODE串的指针，并将其转换为ASCII，然后与文本常量进行比较。

[ESP+8]==WM_PAINT - i在表达式中您可以使用上百种Windows API符号常量。

([BYTE ESI+DWORD DS:[450000+15*(EAX-1)]] & 0F0)!=0 - 这绝对是个有效的表达式。

现在我们介绍语法格式。在大括号（{}）内的每个元素都只能出现一次，括号内的元素顺序可以交换：

表达式 = 内存中间码|内存中间码<二元操作符>内存中间码

内存中间码 = 中间码| { 符号标志 大小标志 前缀} [表达式 ]

中间码 = （表达式）| 一元操作符 内存中间码 | 带符号寄存器 | 寄存器 | FPU寄存器 | 段寄存器 | 整型常量 | 浮点常量 | 串常量 | 参数 | 伪变量

一元操作符 = ! | ~ | + |

带符号寄存器 = 寄存器.

寄存器 = AL | BL | CL ... | AX | BX | CX ... | EAX | EBX | ECX ...

FPU寄存器 = ST | ST0 | ST1 ...

段寄存器 = CS | DS | ES | SS | FS | GS

整型常量 = <十进制常量>. | <十六进制常量> | <字符常量> | <API符号常量>

浮点常量 = <符点常量>

串常量 = "<串常量>"

符号标志 = SIGNED | UNSIGNED

大小标志 = BYTE | CHAR | WORD | SHORT | DWORD | LONG | QWORD | FLOAT | DOUBLE | FLOAT10 | STRING | UNICODE

前缀 = 中间码:

参数 = %A | %B	// 仅允许在监察器［inspector］ 中使用

伪变量 = MSG	// 窗口消息中的代码

这个语法并不严格。在解释[WORD [EAX]]或类似的表达式时会产生歧义。可以理解为以寄存器EAX所指向地址的两字节内容为地址，所指向的双字内容；也可以理解为以寄存器EAX所指向地址的四字节内容为地址，所指向的两字节内容。而OllyDbg会将修饰符尽可能的放在地址最外面，所以在这种情况下，[WORD [EAX]] 等价于 WORD [[EAX]]。

默认情况下，BYTE、WORD 和 DWORD 都是无符号的，而CHAR、SHORT 和 LONG都是带符号的。也可以使用明确的修饰符SIGNED 或 UNSIGNED。例如在二元操作时，如果一个操作数是浮点的，那么另外一个就要转成浮点数；或者如果一个是无符号胆，那么另外一个要转成无符号的。浮点类型不支持UNSIGNED。大小修饰符后面跟 MASM兼容关键字PTR（如：BYTE PTR）也允许的，也可以不要PTR。寄存器名和大小修饰符不区分大小写。

您可以使用下面类C的运算符（0级最高）：

优先级	类型	运算符
0	一元运算符	! ~ + -
1	乘除运算	* / %
2	加减运算	+ -
3	位移动	<< >>
4	比较	< <= > >=
5	比较	== !=
6	按位与	&
7	按位异或	^
8	按位或	|
9	逻辑与	&&
10	逻辑或	||

在计算时，中间结果以 DWORD 或 FLOAT10 形式保存。某些类型组合和操作是不允许的。例如：QWODRD 类型只能显示；STRING 和 UNICODE 只能进行加减操作（像C语言里的指针）以及与 STRING、UNICODE 类型或串常量进行比较操作；您不能按位移动 浮点［FLOAT］ 类型，等等。


Options
选项［Options］

外观选项［Appearance options］

常规［General］

默认［Defaults］

对话框［Dialogs］

目录［Directories］

字体［Fonts］

颜色［Colours］

代码高亮［Code highlighting］

调试选项［Debugging options］ (Alt+O)

安全［Security］

调试［Debug］

事件［Events］

异常［Exceptions］

跟踪［Trace］

自解压［SFX］

字符串［Strings］

地址［Addresses］

命令［Commands］

反汇编［Disasm］

CPU

寄存器［Registers］

栈［Stack］

分析1［Analysis 1］

分析2［Analysis 2］

分析3［Analysis 3］

即时调试［Just-in-time debugging］

添加到资源管理器［Add to Explorer］


General options
常规选项［General options］

全部选项

滚动工作区（启动选项）［Scroll workarea (startup option!)］

当该选项被开启并且OllyDbg主窗口客户区中的某些子窗无法完全的时候，通过滚动客户区域的滚动条，您将其显示出来，从而有效的增加它的大小。必须重新启动OllyDbg来才能使该选项生效。

无雪花显示（较慢）［Snow-free (slower) drawing］

当该选项关闭时，OllyDbg将直接绘制屏幕。该绘制模式较快但是会产生临时的雪花状效果，这可能会使您的眼睛感到不舒服。当该选项被选中时，OllyDbg在内存中准备了一块更新映像，并把它复制到屏幕上。在一些较老的系统上，这种方式可能会非常慢。

向历史中的文件添加参数［Append arguments to file names in history］

文件菜单下最近调试的六个程序。当该项开启时，OllyDbg将在程序名后面添加参数，这样他们看起来更像一个完整的命令行。

恢复窗口位置和外观［Restore window positions and appearance］

当一个窗口为仅允许一个实例存在的窗口（如内存或CPU窗口）时，OllyDbg会把它的位置，栏目宽度，字体和颜色等配置信息保存到预置文件中。如果该选项开启，OllyDbg将以相同的配置和外观恢复窗口。

恢复栏目列宽［Restore width of columns］

如果该选项开启，OllyDbg将恢复只允许有一个实例存在的窗口的栏目宽度。

高亮有序列［Highlight sorted column］

让OllyDbg高亮显示当前排序所按列的列标题栏。

显示工具栏［Show toolbar］

显示或隐藏工具栏，在当前版本中，工具栏不可自定义。

在工具栏中显示状态［Show status in toolbar］

当该选项被取消时，OllyDbg在主窗口的右下角显示被调试程序的状态（暂停［Paused］/运行［Running］/终止［Terminated］等），有时您可能想尽可能多的观看应用程序窗口而需要移动OllyDbg，那么该状态将会有可能看不到。在这种情况下如果您要使状态可见，可以显示工具栏并选中该项，状态就会显示在工具栏的第一项。

记录缓冲区的初始化大小［Startup size of log buffer］

该启动选项指定了OllyDbg分配的用来在记录窗口中显示数据的内存大小。


Defaults
默认［Defaults］

全部选项

表格中使用水平滚动条［Horizontal scroll bar in tables］

如果该选项开启，所有新创建的窗口都将包含一个水平滚动条。但是，滚动条可能掩盖了宝贵空间的重要部分，减少您在屏幕上能看到数据的数量。大多数OllyDbg窗口使用左右方向键来向左或向右滚动内容。

默认字体［Default font］

这里选择的默认字体将被所有新创建的窗口使用。默认情况下，OllyDbg提供了5种预设字体：

OEM fixed font

Terminal 6

System fixed font

Courier (UNICODE)

Lucida (UNICODE) （在Windows 95下不可用）

最后两种字体支持UNICODE扩展字符集。注意，该设置并不能改变已存在的窗口的字体，也不能改变从ini.file文件恢复位置和外观的窗口的字体。您可以从快捷菜单中选择“外观［Appearance］|字体［Font］”来改变已存在窗口的字体。您可以在字体选项［font options］中自定义字体。

默认颜色方案［Default color scheme］

选择的哪个颜色方案将新建的窗口使用。OllyDbg支持4种默认的颜色方案：

白底黑字［Black on white］

蓝底黄字［Yellow on blue］

海蓝［Marine］

大部分黑色［Mostly black］

注意：该设置并不改变已存在窗口的颜色，也不改变从ini.file文件恢复位置和外观的窗口颜色。您可以从快捷菜单中选择“外观［Appearance］|颜色［Color］”来改变已存在窗口的颜色，您可以在颜色［color options］中自定义颜色方案。

默认语法高亮［Default syntax highlighting］

选择哪个高亮显示方案将在CPU窗口、Run跟踪窗口和新创建的数据窗口作为默认值使用，或者禁止语法高亮显示。OllyDbg支持4种高亮显示方案。注意，所选颜色方案不受语法高亮颜色方案影响，所以某些颜色和高亮显示组合显示处，可能很难辨认内容。在这种情况下，您可能需要编辑高亮方案［edit highlighting scheme.


Dialog options
对话框选项［Dialog options］

All options

对齐选择的对话框［Align dialogs on selection］

当该选项被激活时，OllyDbg将对齐对话框，这样就不会遮挡其选择的部份。

对话框字体［Font used in dialogs］:

系统默认［System default］

如果该选项开启，对话框中的编辑框和列表框使用系统默认字体。

与父窗口相同［Same as in parent window］

编辑框和列表框使用调用该对话框的窗口字体。

指定［Specified here］

您可以在这里选择对话框使用的字体，选择的范围限制在这8种自定义［customizable］预设字体中。


Directory options
目录选项［Directory options］

全部选项

UDD路径［UDD path］

在这里指定OllyDbg在哪的文件夹中保存含有模块相关信息的.udd文件。

备份以前的.udd文件［Backup old .udd files］

选择Ollydbg是否对以前的.udd文件进行备份。

插件路径［Plugin path］

OllyDbg寻找插件［plugins］的路径。


Font options
字体选项［Font options］

全部选项

这里您可以自定义OllyDbg用来显示窗口内容的字体。首先选择8种可用字体之一。点击重命名［Rename］按钮改变字体原来的名称（同步更改外观菜单［Appearance menu］）。用改变［Change］按钮来选择不同的字体、风格和大小。

对某些字体来说，报告的与实际显示的高度会有较大的差别。在这种情况下，您可以通过对报告中高度增加或减少至多5个像素，对OllyDbg窗口中的行高进行调节。

如果需要恢复默认设置的字体，请按恢复默认值［Restore defaults］按钮。如果您按下了取消［Cancel］，OllyDbg将忽略您做的所有更改。


Colour options
颜色选项［Colour options］

全部选项

这里您可以自定义OllyDbg用来显示窗口内容的颜色方案。首先选择8中可用颜色方案之一，如果您想改变它原有的名称（同步更改外观菜单［Appearance menu］），请按重命名［Rename］按钮。

每个颜色方案均由8个元素组成：

元素	用于显示	白底黑字［Black on white］方案中的默认值
普通文本［Plain text］	普通文本、断点前景色、当前EIP	黑色
高亮文本［Highlighted text］	高亮文本、跳转地址、断点背景色	亮红色
灰色文本［Grayed text］	灰色文本	灰色
常规背景［Normal background］	常规背景	白色
选中背景［Selected background］	选中部份	亮灰色
分隔线［Separating line］	栏分隔线	灰色
辅助对象［Auxiliary object］	十六进制数据窗口分隔线、最小化栏分隔线	亮灰色
条件断点［Conditional breakpoint］	条件断点	洋红色

如果要改变颜色，首先选择一个元素，然后单击要分配的颜色，8个元素的设置方法均相同。OllyDbg将自动保存新设定到ollydbg.ini文件中。

如果需要恢复选定颜色方案的默认值，按恢复默认值［Restore defaults］按钮。如果您按下了取消［Cancel］，OllyDbg将忽略您做的所有更改。


Code highlighting options
代码高亮［Code highlighting］

全部选项

为了增加代码的可读性，您可能要高亮反汇编代码中的不同指令和操作数，在外观［Appearance］选项代码高亮［Code highlighting］标签中，您可以创建新的或编辑已有的代码高亮方案。

高亮显示支持以下几类指令：

FPU/MMX/SSE	所有使用了浮点、MMX或SSE操作数的命令
条件跳转［Cond jumps］	所有条件跳转命令A
无条件跳转［Jumps］	所有无条件跳转，包括间接跳转
PUSH/POP	PUSH 和 POP 命令
函数调用［Calls］	CALL 命令
返回命令［Returns］	RET 和 RET nn 命令（包括近的和远的）
特权命令［Privileged］	引起Ring3级异常的特权命令
无效命令［Bad commands］	无效命令
添充命令［Filling］	用来对齐函数而添充的两函数空白的命令
修改的代码［Modified code］	与备份不同的代码

如果“高亮显示操作数［Highlight operands］”选择框开启，则操作数将按照如下表格加亮显示：

通用寄存器［General registers］	通用整型寄存器（EAX,EBX……）。
FPU/SSE 寄存器［FPU/SSE registers］	浮点，MMX，3DNow!和SSE寄存器。
段/系统寄存器［Seg/sys registers］	段（DS, SS……）、 调试 (DR0...) 和控制（CR0……） 寄存器
栈内存［Stack memory］	经ESP或EBP访问的内存地址。
其它内存［Other memory］	其他内存操作数
地址常量［Address constants］	内存地址存在的常量
其它常量［Other constants］	其他常量

如果需要恢复选定高亮显示方案的默认设置，请按恢复默认值［Restore default］按钮。如果您按下了取消［Cancel］，OllyDbg 将忽略您做的所有更改。

您可以在反汇编窗口、CPU 数据窗口或其他独立的数据窗口的外观菜单［Appearance menu］设置高亮显示。

注意：默认的高亮显示方案中，Christmas tree 和 Jumps'n'calls 两个方案是为白底黑字［Black on white］方案专门设计的。


Security options
安全选项［Security options］

全部选项

当加载模块相关信息时：［When loading module-related information:］

忽略路径和扩展名［Ignore path and extention］

OllyDbg 将用户自定义的数据，如标签、注释、断点等保存到.udd文件中。通常这个文件会以可执行模块的名字命名，并且保存到 OllyDbg 的目录中。然而，可执行文件和DLL文件是可以具有相同名字的，不同目录中的DLL文件也可以具有相同名字。为了避免冲突，OllyDbg 1.09 在文件名中添加了后缀（_1,_2等）。这种做法的负面影响是如果您把被调试程序移动到其他文件夹时，以前的标签和断点将无法使用。选项“忽略路径和扩展名”［Ignore path and extention］在检查数据正确性时，会忽略 .udd 文件中的文件名后缀、路径和扩展名。

忽略时间戳［Ignore timestamp］

忽略代码段CRC检验［Ignore CRC of code section］

当应用程序加载新模块时，OllyDbg会在在恢复用户自定义的数据之前，先要将数据的最近改动、模块长度、代码段CRC校验，与文件中列出的对应内容进行比较。如果您有几个相同名字的DLL或相同程序的几个不同版本，这将是最低的安全限度，保证不会识别错误。您可以禁止CRC和时间戳比较。如果您修改了可执行模块，最后一个选项将特别有用。

保存在任何模块之外的用户数据到主.udd文件中［Save user data outside any module to main .udd file］

.UDD 文件与模块相关，如果您添加标签或注释，或在模块外地址上设置断点，OllyDbg 默认情况下会在调试结束后把这些信息销毁。如果您激活该选项，OllyDbg 将保存这些数据到主（.exe）模块的.udd文件中。注意，操作系统不能保证下次您的程序运行后，还会在相同的地址分配内存。

允许单步步入未知命令［Allow stepping into unknown commands］

当 OllyDbg 遇到未知的（也可能是无效的）命令时，他将不能计算命令的长度和适合的步进方式。如果该项开启，OllyDbg 会假设这个命令既不是函数调用也不是跳转，并使用一个单步陷阱来步入这条命令。

允许向获得的WinProc地址注入代码［Allow code injection to get address of WinProc］

在基于NT的操作系统下，允许向获得的窗口过程［window procedure］ 注入代码。代码注入非常耗时，也不是十分安全，特别是在多线程的应用程序中。

在代码段之外下断点时警告［Warn when breakpoint is outside the code section］

普通的断点只不过是一个大小为一字节的 INT3 命令。当处理器执行这个命令时，会产生一个OllyDbg能捕获的异常。这意味着 INT3 断点不能在数据上设置。当该项开启时，OllyDbg会询问您是否要在加载模块的代码段之外设置断点。如果您调试一个自解压文件，初始化代码通保存在单独的节中。为了避免频繁的消息询问，您可以关闭该项。

当结束激活的进程时警告［Warn when terminating active process］

为了结束被调试程序，OllyDbg 会调用API函数 TerminateProcess() 以立即关闭应用程序，这可能导致程序没有机会保存并清除数据。如果您不想在关闭时有提示，可以关闭该项。

当不是管理员身份时警告［Warn if not administrator］

在基于 NT 的操作系统下，非管理员在调试应用程序时会有许多限制。如果您以非管理员权限登录，OllyDbg 会在您启动时提示您。关闭该选项，则不再提示。


Debug options
调试选项［Debug options］

全部选项

当跟踪被调试进程时设置为高优先级［Set high priority when tracing debugged process］

在Windows95/98下，为所调试的进程设置高优先级将有效的加快处理调试事件的速度，比如，在Pentium/450处理器上，如果OllyDbg和被调试进程的优先级相同，则运行跟踪每秒执行1400条指令。如果被调试的进程有更高的优先级则每秒执行2700条指令。在基于NT的操作系统上，该选项对调试速度没有明显的影响（总是有较高的优先级并达到每秒5000条指令）。在调试进行的时候，为了不妨碍自身和其他程序，OllyDbg只是在自动执行或跟踪（但不是强迫跟踪）被激活的时候才增加它的优先级。

频繁条件中断时警告［Warn about frequent conditional breaks］

如果您设置了条件断点或内存断点，OllyDbg有可能遇到许多无效的调试事件。如果条件不满足或内存访问非法在指定区域（80X86兼容的处理器只能保护4096字节大小的内存）外发生时，OllyDbg将继续自动执行。调试事件会浪费OllyDbg和操作系统的大量资源，频繁为假的断点将使执行非常慢（最坏的情况下，在Pentium/450上每秒少于2000条指令），如果该选项被开启，并且为假的条件断点出现次数每秒超过50个，OllyDbg将弹出警告消息。

智能更新内存映射［Smart update of memory map］

如果该选项被关闭，OllyDbg将在每次调试事件发生时，更新被调试进程的内存。这将花费很多时间并极大的降低调试速度。当智能更新被开启时，OllyDbg只在必要的时候才更新内存映射，假定驱动程序和其他异步进程都没有分配内存。默认情况下该项是开启的。

压缩分析数据［Compress analysis data］

该选项控制.udd文件中的分析数据是否要进行压缩，压缩将缩小文件的大小但是会降低程序的启动速度。

搜索参考从［Search for references in］：

相应模块的可执行代码［Executable code of corresponding module］

反被编译窗口中选择的内存块［Memory block currently selected in Disassembler］

指定OllyDbg从哪里搜索参考参考［references］.

使用硬件断点单步执行或跟踪代码［Use hardware breakpoints to step or trace code］

如果您单步执行或跟踪代码，OllyDbg尝试使用单步陷阱。在某些情况下，比如，如果您想要单步步过某个子函数，或一次执行一连串命令，或执行到返回，OllyDbg必须设置临时断点。通常使用INT3命令。当操作系统支持硬件断点时，该选项是开启的并且至少有一个空闲的硬件断点，OllyDbg会来设置临时硬件断点。因为内部处理内存访问是非常费时的，所以硬件断点将加速Run跟踪的速度至少20%（跟踪步过［Trace over］）。注意，硬件断点是非破坏性的，也就是说不能改变内存的内容。这一特征是由Kab提出的。

隐藏不存在的源文件［Hide non-existing source files］

微软格式调试信息的某些类型包含源文件名，用于创建运行库和类似的东西。通常他们是不可用的。开启该选项，则将只能看到实际存在的源文件。


Event options
事件［Events］

全部选项

第一次暂停在［Make first pause at］：

系统断点［System breakpoint］

主模块入口［Entry point of main module］

WinMain（函数如果位置已知）［WinMain (if location is known)］

当调试器载入Win32应用程序时，操作系统将程序加载到内存并调用系统INT3断点。然后初始化动态链接库并调用启动程序。启动程序完成相关语言的初始化工作后，调用WinMain函数。该选项允许您选择OllyDbg第一次暂停程序执行的位置。注意：如果WinMain函数是未知的，OllyDbg将暂停在模块的入口。

当新模块（动态链接库）加载时中断［Break on new module (DLL)］

如果该选项开启，则当被调试程序加载新模块时，OllyDbg将停止执行。不同于一些其他的调试器，OllyDbg将一直等到模块被完全加载到内存才停止，所以您可以立即对这模块浏览，设置断点等操作。

当模块（动态链接库）卸载时中断［Break on module (DLL) unloading］.

如果该选项被激活，OllyDbg将在操作系统卸载某些模块时暂停被调试程序。注意，此时模块已经不可浏览。

当新线程运行时中断［Break on new thread］

如果想让OllyDbg在模块启动新线程时暂停执行，请开启该项。

当线程中止时中断［Break on thread end］

如果该选项被激活，OllyDbg将在某些线程结束时停止被调试程序。

当调试字符串时中断［Break on debug string］

如果想让OllyDbg在每次被调试程序发出调试字符串（通过调用OutputDebugString）时暂停，请选中该项。


Exceptions options
异常选项［Exceptions options］

全部选项

忽略KERNEL32中的内存非法访问［Ignore memory access violations in KERNEL32］

Windows API中包含了几个函数（IsBadReadPtr, IsBadStringPtr 等）用来检验进程是否访问指定范围的内存。这些函数位于Kernel32.dll中。实际上，他们只不过是试图访问内存并且在CPU报告内存非法访问时返回失败。如果您在OllyDbg下运行程序并且关闭了该选项，访问违规将报告给调试器。您可以通过按下Shift+F9来接受它，如果开启该项，那么任何 Kernel32 中的内存非法访问都将立即传递给标准错误处理程序。

忽略（传递给程序）以下异常［Ignore (pass to program) following exceptions］：

INT中断［INT3 breaks］

单步中断［Single-step break］

内存非法访问［Memory access violation］

整数除以0［Integer division by 0］

无效或特权指令［Invalid or privileged instruction］

所有FPU（浮点运算器）异常［All FPU exceptions］

如果上面所列异常之一发生并且相应选项被激活，OllyDbg将把异常传递给所调试程序自己的异常处理程序（另外一种做法是使用“shifted”组合键命令，像Shift+F7或Shift+F9把异常传递给异常处理程序）。

同时忽略以下自定义异常或异常范围［Ignore also following custom exceptions or ranges］：

这里您可以指定自定义的异常或指定范围内的所有异常，这些异常将传递给异常处理程序，如果您想忽略最近发现的异常，请按下“添加最近的异常［Add last exception］”按钮。


Trace options
跟踪选项［Trace options］

全部选项

Run跟踪缓冲区大小［Size of run trace buffer］

在这里您可以选择用来记录运行Run跟踪［run trace］的环形缓冲区的大小。记录的数量是不能确定的，这依赖于所调试的程序。只有分配新的Run跟踪缓冲区时选项才生效。

记录命令［Log commands］

要求Run跟踪［Run trace］将原始命令写入Run跟踪缓冲区。调试自修改代码时，这个功能很有用，但会减少缓冲区中的命令数量20%-30%。

显示ESP［Show ESP］

默认情况下，Run跟踪窗口并不显示堆栈指针的实际值，如果想查看它，请开启该项。

显示标志位［Show flags］

默认情况下，Run跟踪［Run trace］保存标志位到Run跟踪缓冲区，但并不在Run跟踪窗口中显示它们。选中该项，则在窗口和日志文件中显示标志位。

总是跟踪步过系统DLL［Always trace over system DLLs］

当该选项被激活并且OllyDbg自动［Animate］或跟踪［Trace］进程时，OllyDbg将不进入系统DLL。位于系统目录下（通常Windows 95是c:\windows\system，NT系统是c:\winnt\system32）的DLL会被认为是系统DLL。主程序（.exe）或调试单独的链接库（.dll）都会被认为用户代码，即使它位于系统目录下。您可以在模块［Modules］ 窗口切换是否为系统DLL。

总是跟踪步过串操作命令［Always trace over string commands］

当该项被激活并且OllyDbg自动［Animate］或跟踪［Trace］进程时，OllyDbg将一次性执行带有REP前缀的串操作命令，默认的做法是分别执行每条重复指令。该选项对单步步入［Step into］没有影响。

同步CPU与Run跟踪［Synchronize CPU and Run trace］

当该项被选中并且您在浏览运行跟踪时，CPU窗口与Run跟踪窗口将显示相同的回溯步伐。在速度较慢的电脑上，同步更新可能会花费很多时间。

在执行到返回后，步过RET［After Executing till RET, step over RET］

当关闭该项并选择执行到返回（Ctrl+F9）时，OllyDbg停在返回命令上，如果该项被激活，OllyDbg将在执行完返回指令后停止，大多数情况下停在函数调用的下一条命令上。

统计时将相邻的命令分为一组［Group adjacent commands in profile］

如果选中该项，OllyDbg会将相同的点击数的相邻命令分为一组，并只显示这一组的第一条命令。如果取消该项，OllyDbg将逐个显示每一条命令。


SFX options
自解压选项［SFX options］

全部选项［All options］

当主模块为自解压时：［When main module is self-extractable:］

扩展代码段，包含提取器［Extend code section to include extractor］

许多OllyDbg组件，比如分析器，仅对可执行模块的代码段进行操作。如果该项被选中并且是自解压模块的话，OllyDbg将扩大代码段范围，从而包含自提取器。

停在自提取器的入口处［Stop at entry of self-extractor］

这是标准的做法，OllyDbg不会尝试跟踪到真正的入口。

块方式跟踪真正入口处（不准确）［Trace real entry blockwise (inaccurate)］

OllyDbg使用4K大小的块单步通过压缩代码。这种方法找到的真正入口可能是错误的。详细解释请参考这里。

字节方式跟踪真正入口处（很慢）［Trace real entry bytewise (very slow)］

OllyDbg检查每一个解压字节，这种方法比块方式可靠的多，但是速度会非常慢。详细解释请参考这里。

使用前次运行时得到的真正入口［Use real entry from previous run］

一旦自解压代码的真正入口已经找到或已经由用户设置好了，则OllyDbg就会迅速地跳过提取器，并准确定位到真正入口处。该项允许使用已知的真正入口。

忽略自解压器的异常［Pass exceptions to SFX extractor］

该选项允许OllyDbg在跟踪自解压程序真正入口时，忽略自提取器产生的某些软件异常（内存非法访问、INT3中断、除零异常、无效或特权指令）。


String options
串选项［String options］

全部选项

解码Pascal风格的字符串常量［Decode Pascal-style string constants］

Pascal字符串常量，在字符串体（长度为0..255之间）前面包含有一个表示串长的字节，所以串的结尾不一定是零。一些高级语言，比如Delphi，使用的Pascal风格的常量。然而当选中该项时，也有可能造成解码出错。

无法打印的ASCII字符转存为圆点［Dump non-printable ASCII chars as dots］

当该项开启后，所有无法打印的ASCII字符都将被圆点取代。字符列表取决于是否允许显示区分符号。如果不允许，可打印的字符只包括TAB、CR、LF、空格及所有0x21..0x7E范围内的字符。如果允许，则可打印的字符集还包括那些带有区分符号（像�, �, �）的符号，货币符号及其他一些特殊符号

允许字符串中使用区分符号［Allow diacritical symbols in strings］

当OllyDbg试图辨认ASCII字符串并且该项未激活时，字符串只能包含标准ASCII字符（0x20..0x7E和一些附加字符TAB，CR，LF）。许多欧洲语言包含特殊字符或带有区分符号（像�, �, �, �）的字符。如果所调试的程序支持除英语以外的其他语言，请开启该项。然而，这可能会导致字符串的错误识别。默认情况下该项关闭。

字符串解码模式［Mode of string decoding］：

普通［Plain］

汇编［Assembler］

C

该选项影响注释栏中的ASCII和UNICODE字符串的显示方式，在普通模式下，不解码，所有字符按照原样显示在屏幕上。在汇编模式下，OllyDbg将无法打印的字符解码为十六进制数或特殊代码CR、LF 、TAB。而在C模式下，OllyDbg使用C语言的'\n', '\r', '\x01'。


Address options
地址选项［Address options］

全部选项

解码修饰符号名［Demangle symbolic names］

面向对象的语言，像C++，使用了一种叫名字修饰［name mangling］的技术，将类型和参数的信息添加到符号中。比如，函数Mainwp(HWND *, unsigned int, unsigned int, long)可能会修饰成@Mainwp$qqsp4HWNDuiuil这样很难理解的格式。该选项告诉OllyDbg在这些函数进入内部表时，重整符号名。改变该项不影响已处理过的名字。OllyDbg自动识别Borland和Microsoft格式的名字修饰。如果需解码使用了微软风格名字修饰，则您需要dbghelp.dll（已提供）。注意：解码修饰名字可能是（并且经常是）不准确的。

为引入表中的符号名添加序号［Prepend ordinals to IMPLIB names］

OllyDbg会以从引入链接库［import libraries］提取的更有含义的符号名来替代DLL中的序号，如果想同时使用序号和符号名，选开启该项。例如，某些名字可能会是如下形式：

序号	#123
符号	Symbol
带有序号的符号	#123_Symbol

以如下格式显示地址［Display address in form of］：

十六进制地址、符号名［HEX, Symbol］

符号名、十六进制地址［Symbol, HEX］

或者十六进制地址，或者符号名［Either HEX or Symbol］

如果某些内存地址没有符号名，OllyDbg将其显示为8位的十六进制数。如果地址有符号名（标签），该项有如下三种形式选择：

- 8位十六进制数，后跟符号名

- 符号名，后跟8位十六进制数

- 只显符号名

显示本地模块名［Show name of local module］

如果选中该项，OllyDbg将在数据窗口或反汇编窗口第一列的符号地址前添加模块名

高亮符号名［Highlight symbolic names］

当该选项开启时，OllyDbg将在数据窗口或反汇编窗口的第一列中高亮显示符号名（标签）。这将有助于理解代码。

默认名称窗口排序方式［By default, sort contents of Names window by］:

地址［Address］

名称［Name］

该选项指定名称窗口的默认排序模式。


Command options
命令选项［Command options］

全部选项

使用串的简易形式［Use short form of string commands］

该选项在串操作命令的简易形式（MOVSD, REP STOSB）和完整形式（MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI], REP STOS DWORD PTR ES:[EDI]）之间切换。

使用RET代替RETN［Use RET instead of RETN］

80x86 处理器区分近（RETN）与远（RETF）返回。在大多数情况下，Win32应用程序使用近返回形式。开启该项，则用RET助记命令代替RETN 。

指定16字节SSE操作数为［Specify size of 16-byte SSE operands as］：

DQWORD （双四字［Double Quadword］）

XMMWORD （扩展MMX操作数［eXtended MMX operand］）

这里您可以指定OllyDbg在汇编命令中如何解码128位SSE操作数。

解码大小敏感的16/32位中助记符为［Decode size-sensitive 16/32-bit mnemonics like］：

PUSHA/PUSHAD

PUSHAW/PUSHAD

PUSHAW/PUSHA

80x86指令集包含一些命令，其的助记符依赖于地址大小。这里您可以选择反汇编窗口中如何解码这些命令。

解码栈顶为［Decode top of stack as］：

ST(0)

ST

两种解码方式在汇编指令中具有相同的含义。这里您可以选择您更喜欢的解码形式。


Disassembler options
反汇编选项［Disasm options］

全部选项

反汇编语法［Disassembling syntax］：

MASM (Microsoft)］

IDEAL (Borland)

HLA (Randall Hyde)

Borland公司的TASM支持IDEAL模式，它要比MASM好的多（当然这是我个人的拙见）。不幸的是，微软的工具不支持它，所以为了兼容，程序员们经常使用离奇的MASM语法。IDEAL语法有一条要求，就是所有包含内存的操作数必须用一对方括号括起来。

高级汇编语言［High Level Assembly language］是由Randall Hyde发明的，能使初学者用汇编语言轻松地写出大的结构化程序，该语言使用了另一种实用的语法，即第一个操作数是源操作数。HLA是一个公开的软件，您可以从http://webster.cs.ucr.edu下载它的文档和源代码。比较一下：

MASM:	MOV EAX,DWORD PTR SS:[EAX+EBP+20]

IDEAL:	MOV EAX,[DWORD SS:EAX+EBP+20]

HLA:	mov( [type dword ss:eax+ebp+20], eax );

只有在HLA模式下才允许使用HLA语法格式编辑命令。默认情况下，OllyDbg使用MASM语法。

以小写形式反汇编［Disassemble in lowercase］

当该项开启时，反汇编指令中的命令、寄存器名、修饰符都以小写字母形式显示。关闭该项时，则以大写字母显示，该选项不影响标签和常量。

助记符和参数之间使用制表符［Tab between mnemonics and arguments］

当该项开启时，OllyDbg会对齐命令参数，这样参数都从8个字符宽的地方开始显示。

参数之间添加空格［Extra space between arguments］

当该项开启时，OllyDbg以逗号分隔指令操作数，逗号后面紧跟一个空格。当选项关闭时，操作数之间没有空格。

显示默认段［Show default segments］

80x86指令在访问内存时经常使用段寄存器（选择器）。如果段寄存器与指令默认的不同，您就必须考虑为指令添加段前缀。如果选中该项，反汇编代码总是包含段寄存器的名字。如果选项关闭，段寄存器只有在与默认不同时才显示。注意，在Win32环境下，所有默认段都以零为基数并指向相同的内存。

总是显示内存操作数的大小［Always show size of memory operands］

当该项开启时，反汇编后的内存地址总是包含数据大小修饰符（BYTE, WORD, DWORD等）。当选项关闭时，只有当数据大小修饰符不可忽视或者对指令来说不明显时才显示。比如，内存操作数在指令MOV [ESI],EAX中的大小为4字节，因为EAX是4字节长，但是在指令MOV [ESI],1中，则可能是1、2或4个字节长。

显示近跳修饰符［Show NEAR jump modifiers］

当选中该项时，即告诉OllyDbg在所有段内间接跳转或调用间接地址时添加NEAR修饰符。远跳及远调用在平坦的Win32寻址模式中很少用到。

显示本地模块么［Show local module name］

当该项开启时，反汇编窗口中将在所有符号地址或常量地址前添加目标模块名，这将有助于您理解代码。

显示符号地址［Show symbolic addresses］

当关闭该项时，反汇编窗口通常将常量解码为十六进制数。当该项开启并且常量有符号名时，反汇编窗口中将显示符号名。


CPU options
CPU选项［CPU options］

全部选项

同步源码和CPU［Synchronize source with CPU］

如果该项被选中，则源码窗口将自动跟随CPU反汇编窗口中的选中的部分。

重定位加下划线［Underline fixups］

几乎所有的DLL和一部分程序都包含重定位，这样就可以在内存中的不同基地址加载模块了。当该项开启时，CPU反汇编窗口或CPU数据窗口中的重定位地址都将添加下划线。

显示跳转方向［Show direction of jumps］

当该项被选中时，分析后代码的十六进制数据栏［Hex dump］处，将出现一个箭头，用于指向跳转的地址或者显示从哪里调用的。也可能是一个短的水平线，这表示如果跳转目的地属于程序的不同模块。

显示跳转路径［Show jump path］

如果跳转不发生显示为灰色路径［Show grayed path if jump is not taken］

显示跳转到选中命令的路径［Show jumps to selected command］

当该项被开启时，首先选中一条跳转指令，如果该跳转确实发生了，OllyDbg将在跳转指令和跳转目的地址之间画一个细小箭头记号，我叫它为“跳转路径”。默认情况下，跳转路径使用高亮文本［Highlighted text］的设置显示的（白底黑字颜色方案中是红色）。如果跳转没有发生的，则路径为灰色。如果您开启了“显示跳转到选中命令的路径”选项，并且先中的命令，被识别为某个跳转的目地地址，则OllyDbg会把所有到选中命令的跳转都显示出来。

在中间显示跟进的命令［Center 'Follow'-ed command］

当该项开启时，从其它窗口跟进到CPU反汇编窗口的命令显示在反汇编窗口的中间。否则，跟进的命令会显示在反汇编窗口的最前面。

步入下条命令时，保持后面还有几行可见［Number of visible lines after stepped command］

默认［Default］

1行［1 line］

...

10行［10 lines］

在您单步执行代码的时候，这个选项将指定反汇编窗口中当前命令后面需保留几行命令可见。

在反汇编窗口按下字母键，则［Letter key in Disassembler starts］：

新建标签［New label］

编辑汇编命令［Assembler］

添加注释［New comment］

与上一次选择相同［Object of last selected type］

当您在反汇编窗口中输入文本时，是新键标签，编辑汇编命令，还是添加注释取决于该项设置。


Register options
寄存器选项［Register options］

全部选项

为任何IP解码寄存器［Decode registers for any IP］

寄存器是使用和更改最频繁的处理器资源。大多数情况下，如果下一条命令没有执行，则对当前的寄存器或地址表达式的内容进行解码是没有任何意义的（比如：有一个地址与EIP的内容相同）。然而，您想提前预知程序的动向，您就需要开启该项，以便跟踪所有寄存器的改变状况。

自动选择FPU/MMX/3DNow!寄存器［Automatical FPU/MMX/3DNow! Registers］

当该项关闭时，您必须手动设置寄存器的解码模式（FPU，MMX，或者3DNow!）。当该项被开启并且程序停在上述所列类型之一的命令时，OllyDbg将自动设置与指令类型相匹配的解码模式。

解码SSE寄存器［Decode SSE registers］

当该项选开启时，OllyDbg将在CPU窗口的Registers面板中显示当前线程的128位 SSE寄存器，并在Information面板中解码寄存器的值。注意：该操作很慢并且需要向平调试程序中注入一段代码。除非绝对需要，否则不要使用该项！

显示最近的错误［Show last error］

如果想显示由线程检查到的最近的错误（GetLastError的返回值），请开启该项。该错误显示在寄寄存器［Registers］面板中，并将记录到Run跟踪［Run trace］日志中。该选项将降低20%的跟踪速度。


Analysis options - part 1
分析选项1［Analysis options - part 1］

全部选项

函数过程识别［Procedure recognition］：

严格［Strict］

启发［Heuristical］

模糊［Fuzzy］

选择分析器识别函数过程的方式。严格模式是指连续代码段必须含有唯一的已定义的入口，并且至少有一个返回。启发模式则仅要求函数过程中包含一个假定入口［assumed entry］。当您选择模糊模式时，任何一部分代码段将被视为独立的过程。如果编译器使用了全局代码优化［global code optimizations］，则模糊模式是最佳选择。但由此产生错误信息的几率也会上升，所以在此模式下不建议您使用hit跟踪［Hit trace］。

显示函数中的参数和局部变量［Show ARGs and LOCALs in procedures］

如果该项被开启并且代码经过分析，OllyDbg将在识别出的函数过程中，把形如 [SS:EBP+8] 和[SS:EBP-8]的地址分别显示为[ARG.1] 和[LOCAL.2]，这种显示方式暗示前面的地址是函数的第一个参数，而另一个地址则是在堆栈中分配的第二个局部变量。然而，高度优化的编译器和手工编写的程序，可能将EBP作为其他用途。参数的编号以十进制数1为基数增加的，对于OllyDbg一般规则来说这是一个例外。默认情况下该项关闭。

自动开始分析主模块［Auto start analysis of main module］

当该项开启并且是第一次分析某个应用程序是，OllyDbg将自动分析主模块的代码。

识别循环与分支语句［Recognize loops and switches］

如果该项被激活，则识别分支和循环语句。

解码IF嵌套语句为分支语句［Decode cascaded IFs as switches］

激活后，可以让分析器将实际上是IF嵌套［cascaded IF operators］ 识别为分支语句

解码欺骗代码序列［Decode tricky code sequences］

现在ollydbg识别一种欺骗手法：当该项被选开启时，它将正确的识别紧跟在PUSH和跳转指令以及ASCII字符串组合后面的CALL命令，就像下面的命令序列一样：

PUSH 0

CALL @1

DB 'title',0

@1:	CALL @2

DB 'message',0

@2:	PUSH 0

CALL MessageBoxA

这是一个有效的函数调用MessageBox(0,"message","title",0)。但该选项关闭，则OllyDbg将会将字符串解释为命令。这个欺骗手法由BlackArt报告。

灰色显示两函数过程间的添充代码［Gray commands that fill gaps between procedures］

分析器能够识别用于填充空缺以便对齐函数过程的无效指令。如果该项开启，它们在反汇编窗口中将被显示为灰色

在两次调试之间保持分析数据［Keep analysis between sessions］

当该项开启时，OllyDbg将分析数据保存到用户数据文件中，并在模块再次打开时将其自动载入。这将节省时间，但是会增加模块数据文件的大小。如果从软盘上启动OllyDbg，请关闭该项。


Analysis options - part 2
分析选项2［Analysis options - part 2］

全部选项

显示已知函数的参数［Show arguments of known functions］

OllyDbg包含大约1900个标准API 和 400 多C 函数的描述。分析器能够识别他们。并且注释他们的参数。另外，他标记函数范围［function scopes］，也就是函数参数被压入栈中的区域。

猜测未知函数参数的个数［Guess number of arguments of unknown functions］

当分析器［Analyzer］遇到未知函数并且该项开启时，OllyDbg尝试计算出函数压入栈中双字的个数。并且标记他们为参数1［Arg1］，参数2［ Arg2］，等等。注意：无论如何，寄存器参数是无法识别的，所以不会增加参数的数目。分析器使用了一种比较安全的方法。例如，它不能识别的没有参数的函数过程，或者该过程POP命令直接做返回前的寄存器恢复，而不销毁参数。然而，识别出来的函数参数数目通常非常高，这大大加大了代码的可读性。

跟踪寄存器内容［Trace contents of registers］：

关［Off］

在线形序列［In linear sequences］

在已识别的函数过程中［In recognized procedures］

该选项指定分析器是否或者如何预测寄存器内容［predicts contents of registers］.。如果您选择在在线形序列［In linear sequences］，分析器会在线形代码段（比如没有跳转或者函数调用）中，跟踪整型寄存器的内容。如果您选择在已识别的函数过程中［In recognized procedures］，分析器根据会从所有跳转到相同目标地址的情况进行递归综合预测。最后这种方式会非常耗时，但会得到更好的结果，特别是的对优化编译器生成的代码。OllyDbg 通过预测来解码调用为已知函数并分析其的参数。跟踪的参数会标注“=>”这个记号。（示例）。

使用这个跟踪选项风险自负［Use this tracing option at your own risk］：

未知函数保护EBX, ESI 和EDI ［Unknown functions preserve EBX, ESI and EDI］

大多数API函数都要保护这几个寄存器。分析器在跟踪寄存器时也会按此事实处理。如果函数不在已知函数列表中，并且该选项未开启，跟踪器将不预测 EBX, ESI 和 EDI 。如果开启该项，您便告之分析器所有的函数都遵循标准寄存器惯例。在某些时候（特别是使用汇编语言手工优化的代码），这可能导致预测无效。该项在调试时不会受影响。


Analysis options - part 3
分析选项3［Analysis options - part 3］

全部选项

有许多80x86命令几乎不会出现在Win32环境下的正常程序中。通常，分析器将此类指令认为是潜在的无效指令并且把它们视为二进制数据而不是代码。您可以在这里选择您愿意接受无效指令类型。相关信息暂停Run跟踪［Pause run trace］。

远调用和返回［Far calls and returns］.

远（段间或特权间或任务切换）调用和返回通常不出现在Win32程序中。

修改段寄存器［Modifications of segment registers］

Win32程序通常不修改段寄存器

特权命令［Privileged commands］

特权指令，比如HLT或LGDT，是不允许出现在用户代码中的。

输入输出命令［I/O commands］

Windows NT不允许应用程序直接访问I/O端口。然而，一些驱动程序能修改I/O端口的［许可位映射I/O Permission Bit］来允许此类访问。而Windows95/98并不如此严格。如果您怀疑被调试程序可能会直接访问I/O端口，请开启此项。

与NOP等效的命令［Commands that are equivalent to NOP］

编译器通常会避免在代码中包含无用指令。开启此项以便允许代码中包含形如NOP, XCHG EDX,EDX 或 LEA EAX,[EAX]的指令。

位移超出1�31的范围［Shifts out of range 1..31］

在开始位移之前，80x86兼容处理器用0x1F按位与（AND）位移计数器为，从而有效的将计数器的范围限制在范围0..31之内。计数0意味着NOP，并且几乎不可能因编译器产生。

冗余前缀［Superfluous prefixes］

如果您希望使用带有多重或矛盾前缀的命令（像MOV EAX,ES:FS:[ESI]），或带有内存相关前缀但却不访问内存的指令的命令（ES: XOR EAX,EAX），请开启该项。

LOCK前缀［LOCK prefixes］

应用程序自身通常不使用LOCK前缀，而使用系统函数比如EnterCriticalSection等作为替代。

不对齐栈操作［Unaligned stack operations］

Win32程序通常保持栈以双字对齐。像INC ESP 或 ADD ESP,7这样的指令是很少出现在应用程序中的。

非标准命令形式［Non-standard command forms］

某些命令，比如SETZ, 不使用Reg（ModRegRM地址字节的部分），Intel手册要求这时 Reg 应该是0，但目前所有的处理器会忽略Reg部份，当执行这类命令时。这可能在将来的处理器中发生改变。

VxD调用［Vxd calls］

基于DOS的Windows 95/98使用 VxD 调用与虚拟设备进行通讯。一般来说，这个调用是一个INT 20，它后跟随一个包含请求服务的双字。应用程序并不直接调用 VxD，但是如果尝试反汇编驱动文件将导致代码不可读。该选项在Windows95/98下默认是开启的。


Stack options
栈选项［Stack options］

全部选项

跟踪栈框架［Trace stack frames］

如果该选项开启，OllyDbg将尝试跟踪由PUSH EBP; MOV EBP,ESP 或者 ENTER xx,0命令创建的栈框架。发现的每组框架都会在栈数据的在左边用一个大括号标记起来。OllyDbg识别成错误的框架是经常发生的。例如，前一个调用的残余。现代优化编译器可以生成不使用标准栈框架的代码。

在函数过程中使用栈框架范围［Use stack frame scopes in procedures］

如果该选项开启，并且EBP指针指向了一个有效的栈框架，则栈将对已知函数的参数进行解码。

高亮返回［Highlight RETURNs］

如果该项被选中，OllyDbg将高亮显示栈中可识别的返回［recognized as returns］ 地址。同栈框架一样，返回地址也有可能由于前一个调用的残余而导致错误。最终决定地址是否有效，取决于您。OllyDbg不识别人造的Call（PUSH retaddr, JMP entrypoint）。

显示已知函数的参数［Show arguments of known functions］

但该项开启，并且EIP包含的调用或跳转地址是已知函数，或者是其的入口，OllyDbg会在栈窗口中解码已知函数的参数。

显示本地变量名［Show names of local variables］

如果调试信息可用同时该项开启，OllyDbg会显示参数名及当前函数在栈中本地变量。


Just-in-time debugging
即时调试［Just-in-time debugging］

全部选项

当某个程序产生异常，操作系统将会调用一个已注册的调试器，并把程序挂接到这个调试器上。这就叫做即时调试。

一些即时调试器只是谨慎地停在系统中断处，而OllyDbg会继续运行直到产生异常的地方。这对调试带来了极大的方便，但是这也导致了Windows 95操作系统下的一个问题：OllyDbg不能区分系统断点和DebugBreak()函数调用，结果应用程序遇到了DebugBreak()，OllyDbg仍然会继续运行。这个问题在Windows NT/2000下不存在。

即时调试与以下两个注册表键值相关：

•	HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug\Debugger - 保存调用调试器的命令；

•	HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug\Auto - 设定在挂接前是否询问。

奇妙的是，“Windows NT”这个键值同样适用于基于Windows95的系统。

设置OllyDbg成为即时调试器，请按“设置OllyDbg成为即时调试器［Make OllyDbg just-in-time debugger］”按钮。

恢复以前的设置，请按“恢复以前的即时调试器［Restore old just-in-time debugger］”

按钮“挂接前需确认［Confirm before attaching］” 和“挂接无需确认［Attach without confirmation］”用于设置OllyDbg或其它的外部调试器挂接是否需要确认。


Register tracing - an example
寄存器跟踪实例［Register tracing - an example］

分析器［Analyzer］

这是一个例子，以显示分析器是如何跟踪寄存器内容的。整个过程是一个线形代码序列。

004116E1   . C8 000000      ENTER 0,0

004116E5   . BB 22154500    MOV EBX,<JMP.&KERNEL32.GetPrivateProfile>

004116EA   . BE 1B174100    MOV ESI,OT.0041171B         ;  ASCII "inifile.ini"

004116EF   . BF 27174100    MOV EDI,OT.00411727         ;  ASCII "Key1"

004116F4   . B9 31174100    MOV ECX,OT.00411731         ;  ASCII "SectionName"

004116F9   . 33C0           XOR EAX,EAX

004116FB   . 51             PUSH ECX

004116FC   . 56             PUSH ESI                    ;  IniFileName => "inifile.ini"

004116FD   . 50             PUSH EAX                    ;  Default => 0

004116FE   . 57             PUSH EDI                    ;  Key => "Key1"

004116FF   . 51             PUSH ECX                    ;  Section => "SectionName"

00411700   . FFD3           CALL EBX                    ;  GetPrivateProfileIntA

00411702   . 8B4D 08        MOV ECX,[ARG.1]

00411705   . 8901           MOV [DWORD DS:ECX],EAX

00411707   . 59             POP ECX

00411708   . 83C7 05        ADD EDI,5

0041170B   . 83C8 FF        OR EAX,FFFFFFFF

0041170E   . 56             PUSH ESI                    ;  IniFileName => "inifile.ini"

0041170F   . 50             PUSH EAX                    ;  Default => FFFFFFFF (-1.)

00411710   . 57             PUSH EDI                    ;  Key => "Key2"

00411711   . 51             PUSH ECX                    ;  Section => "SectionName"

00411712   . FFD3           CALL EBX                    ;  GetPrivateProfileIntA

00411714   . 8B4D 0C        MOV ECX,[ARG.2]

00411717   . 8901           MOV [DWORD DS:ECX],EAX

00411719   . C9             LEAVE

0041171A   . C3             RETN

0041171B   . 69 6E 69 66 69>ASCII "inifile.ini",0

00411727   . 4B 65 79 31 00>ASCII "Key1",0

0041172C   . 4B 65 79 32 00>ASCII "Key2",0

00411731   . 53 65 63 74 69>ASCII "SectionName",0

函数GetPrivateProfileIntA 被描述为一个标准函数在数据基地址处。分析器假定他恢复栈和寄存器EBX, EBP, ESI, EDI。ECX的内容保护在栈中，因此它保存不变。命令ADD EDI,5

增加EDI以指向串"Key2"。用FFFFFFFF按位或EAX，使得EAX每个比特位［bit］都是1，这样它被完全指定。


Assembler
汇编器［Assembler］

OllyDbg内置的汇编器用于将文本命令转换成机器代码。许多80x86命令可能存在多种编码形式。在这种情况下，汇编器会选择最短的编码形式。汇编器和反汇编器［Disassembler］共享相同的译码表。因为如果某个命令能够被反汇编，那么他也能被编译。对于异常，16位地址模式并不支持。汇编器也理解简化和替代的助记符，像MOVSB （反汇编器解码为 MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]）或者JNE（解码为JNZ）。您不必选择，就可以直接输入或者微软的MASM语法或者Borland的IDEAL语法的汇编命令：

MOV EAX,DWORD PTR SS:[EBX*2][EDI+10.] 等价于

MOV EAX,[DWORD SS:EBX*2+EDI+10.]

汇编器会解释所有的常量为十六进制格式，除非常量以点作为结尾，才会把它识别为十进制。如果常量的第一个数字为字母（如ABCDEF），请不要忘记在最前面加数字0！

汇编器会把分号（;）以及后面跟随的全部字符作为注释。如果您给代码打补丁，这些注释将被加到命令的后面。

汇编器会自动决定哪个寄存器是索引，哪个是基地址。处理是如此的不可思议，就像这样：

MOV EAX,[ESI*9] （等价于 MOV EAX,[ESI+ESI*8]）

或者

MOV EAX,[ESI+EDI+ESI] (等价于 MOV EAX,[EDI+ESI*2])

汇编器也接受符号名［symbolic names］。以下是一些您需要知道的规则：

- OllyDbg不检查标签是否唯一，但相同标签中只接受第一个出现的。如果只搜索某个模块中标签，标签之前应加上模块名：JMP Myprog.Firstroutine

- 用户自定义标签可能包含空格和特殊字符。汇编器不能识别这样的标签。

- 如果使用引入标签［import labels］，您必须指定其驻存和目的模块：JMP Myprog.<&KERNEL32.VirtualFree>.

80x86指令集仅支持命令XCHG mem,reg 和 TST mem,reg，但汇编器还支持XCHG reg,mem and TST reg,mem 命令。

您将会被警告，如果您在某个命令前使用了LOCK前缀，因为汇编器不支持它。

模糊命令［Imprecise commands］

在搜索命令时，您可以使用模糊汇编指令。可以使用下面的关键字：

关键字	匹配
R8	任何8位寄存器(AL,BL, CL, DL, AH, BH, CH, DH)
R16	任何16位寄存器(AX, BX, CX, DX, SP, BP, SI, DI)
R32	任何32位寄存器 (EAX, EBX, ECX, EDX, ESP, EBP, ESI, EDI)
FPU	任何FPU寄存器(ST0..ST7)
MMX	任何MMX寄存器(MM0..MM7)
CRX	任何控制寄存器(CR0..CR7)
DRX	任何调试寄存器r (DR0..DR7)
CONST	任何常量
OFFSET	与CONST相同

和模糊命令：

命令	匹配
JCC	任何条件跳转(JE, JC, JNGE...)
SETCC	任何条件设置字节(SETE, SETC, SETNGE... )
CMOVCC	任何条件移动 (CMOVE, CMOVC, CMOVNGE...)

相关信息 搜索命令序列［Search for a sequence of commands］.


Disassembler
反汇编器［Disassembler］

反汇编器识别所有的标准80x86、保护、FPU、MMX和3DNow!指令集（包括Athlon扩展的MMX指令集）。但它不识别ISSI命令，尽管计划要在下个版本中支持这种命令。某些过时或者未公开的命令，像LOADALL，也不支持。

反汇编器可以正确解码16位地址。但它假设所有的段都是32位的（段属性使用32位）。这对于PE［Portable Executable］格式文件总是真的。OllyDbg不支持16位的NE［New Executables］格式。

如果您熟悉MASM或者TASM，那么反汇编的代码对于您没有任何问题。但是，一些特例也是存在的。以下命令的解码与Intel的标准不同：

AAD (ASCII Adjust AX Before Division) -

该命令的解码后的一般形式为：AAD imm8

AAM (ASCII Adjust AX After Multiply) -

该命令（非十进制数）的一般解码形式为：AAM imm8

SLDT (Store Local Descriptor Table register) -

操作数总被解码为16位。这个命令的32位形式会在目的操作数的低16位中存储段选择器，并保留高16位不变。

SALC (Sign-extend Carry bit to AL, undocumented) -

OllyDbg 支持这个未公开指令。

PINSRW (Insert Word From Integer Register, Athlon extension to MMX) -

在AMD的官方文档中，这个命令的内存形式使用了16位内存操作数；然而寄存器形式需要32位寄存器，但只使用了低16位。为了方便处理，反汇编器解码寄存器为16位形式。而汇编器两种形式都支持。

CVTPS2PI and CVTTPS2PI (Convert Packed Single-Precision Floating to Packed Doubleword, Convert with Truncation Packed Single-Precision Floating to Packed Doubleword) -

在这些命令中，第一个操作数是MMX寄存器，第二个或者是128位XMM寄存器或者是64位内存区域。为了方便处理，内存操作数也被解码为128位。

有些指令的助记符要依赖操作数的大小：

不分大小的形式	明确的16位形式	明确的32位形式
PUSHA	PUSHAW	PUSHAD
POPA	POPAW	POPAD
LOOP	LOOPW	LOOPD
LOOPE	LOOPWE	LOOPDE
LOOPNE	LOOPWNE	LOOPDNE
PUSHF	PUSHFW	PUSHFD
POPF	POPFW	POPFD
IRET	IRETW	IRETD

您可以改变解码大小敏感助记符［decoding of size-sensitive mnemonics］.。根据选项，反汇编器从三种可能中选择之一进行解码。这个选项也会影响汇编器的默认处理方式。

解码MMX和3DNow!指令总是开启的，尽管您的处理器并不支持这些指令。


Labels
标签［Labels］

一个标签就是一个符号名，用来对被调试程序线形地址空间中的某个地址命名。OllyDbg能够识别四种不同的标签：

- 输出［Exports］. 是一种方便其他模块调用的公用符号名。每个DLL都包含至少一个输出函数名。OllyDbg会添加一个特殊的输出伪函数名<ModuleEntryPoint>，它根据PE头的信息指向模块的入口。某些输出函数没有符号名，只有一个序号。OllyDbg会解码为#序号。如果设置相关选项，OllyDbg将在输出函数名加上模块名。

- 引入［Imports］. 大多数可执行模块都会调用其他模块的输出函数符号名。这些符号的地址直到调用的模块被加载到内存后才会知道。为了处理调用的函数符号名，可执行程序包含了一个引入表。在这个表中，每个调用的函数都包含这几项：调用的模块名、函数符号名（或者其的序号）和在符号名在模块中的32位接收地址。OllyDbg从引入表中给地址命名，并加上一个特殊的伪函数名<&扩展模块.扩展函数名> （或 <&扩展模块.#扩展序号>，如果扩展函数符号名只有序号的形式）。符号和“&”这里的表示引入函数名即不是扩展函数名本身，而是这个函数名的指针。尖括号“<>”表示该函数名不由调试器自动生成的。注意：引入标签不一定是唯一的，其的主要作用是更好的理解代码。

某些编译调用总扩展的函数的间接地址来调用扩展函数。OllyDbg会将其解码为<jmp.&扩展模块.扩展函数名>。

- 用户自定义标签［User-defined labels］. 您可以为任何已分配的地址指定符号名。如果地址属于某个模块，OllyDbg会在注销加载该模块时卸载时保存这个标签到用户数据文件中，而在该模块再次加载时（可以是不同的程序）自动读取。用户自定义标签不会检查是否唯一并允许包含任何字符。

如果希望一次找全当前模块中的全部用户自定义标签，请在反汇编窗口中选择“［搜索］Search for|用户自定义标签［User-defined label］”，所有包含用户自定义标签的命令都会显示在参考窗口［Reference window］中，您可以用Alt+F7 和 Alt+F8 在反汇编窗口中上下浏览列表中的命令。

- 通过Object扫描器从Obj文件中提取标签［Labels extracted from object files］ 或者通过Implib扫描器从Lib文件中提取库标签，或者从编译器生成的调试信息中提取。这些名称在名称列表中都会标记上“Library”。目前版本的OllyDbg不能保证从Object扫描器中提取的名称100％的正确。库标签的优先级最低。


User comments
用户注释［User comments］

您可以给调试代码添加自己的注释。如果这个代码属于某个模块，OllyDbg将在注销加载该模块时保存注释到用户数据文件中，而在该模块再次加载时（可以是不同的程序）自动读取。用户注释优先于自动生成的注释。

编译程序认为从分号以后都是注释，并会自动加到代码后面。

如果希望一次找全当前模块中的全部用户注释，请在反汇编窗口中选择“［搜索］Search for|用户自定义注释［User-defined comment］”，所有包含用户注释的命令都会显示在参考窗口［Reference window］中，您可以用Alt+F7 和 Alt+F8 在反汇编窗口中上下浏览列表中的命令。

。


References
参考［References］

参考就是在某个模块的可执行代码中常量出现的地方。OllyDbg允许您按地址、地址范围、当前选择命令中的常量，或任意某个常量等多种方式搜索参考。

例如， 假设您指定地址或常量0x401234，则以下的命令将会被识别为参考：

MOV EAX,401234

MOV EAX,DWORD PTR [00401234]

MOV BYTE PTR [EBX*4+EDI+00401234],AL

JNE 00401234

CALL 00401234

DD 00401234

分析［Analysis］ 不但加速搜索并准确的识别参考，并且允许在表中查找参考。

完整的参考列表显示在参考窗口［Reference window］中。为了操作方便，如果您是在反汇编窗口中搜索的，这个列表会包含在反汇编窗口中选中的第一条命令（高亮显示），因此，您可以快速返回到您开始搜索的地方。参考窗口同时会列出找到的命令、用户自定义标签或注释。

如果您搜索所有的模块间调用、全部命令或命令序列、转换语句［Switch］，或字符串参考，OllyDbg也会将结果放入参考窗口中。

在反汇编窗口中，您可以通过按Alt+F7 （前一个参考） 和 Alt+F8 （下一个参考）在反汇编窗口中上下浏览列表中的命令。

相关信息： 在反汇编窗口中的参考［References in Disassembler］, 在数据窗口中的参考［Refrences in Dump］, 用户注释［User comments］.


Known bugs and problems
已知的 bug 和问题［Known bugs and problems］

1.如果OllyDbg是即时调试器，并且在Windows 95下挂接执行了DebugBreak() 的应用程序，则这个应用程序在挂接后，还会运行。在基于NT的系统下，应用程序应该会在DebugBreak()暂停。

2. 命令 SMSW （保存机器状态字［Store Machine Status Word］）。 这个命令仅接受寄存器 AX 作为参数，而程序编译成EAX接受参数。


How the Analyzer works - an example
分析器工作原理 - 举例［How the Analyzer works - an example］

假设您有以下一段代码：

00440540  55 8B EC 83 C4 F8 DB 45 0C DC 0D B4 05 44 00 83  U......E.....D..

00440550  C4 F8 DD 1C 24 E8 7A 29 01 00 83 C4 08 E8 8A 28  ....$.z).......(

00440560  01 00 89 45 FC 89 45 F8 8B 45 08 83 F8 04 77 28  ...E..E..E....w(

00440570  8A 80 7D 05 44 00 FF 24 85 82 05 44 00 01 02 01  ..}.D..$...D....

00440580  02 01 98 05 44 00 8E 05 44 00 93 05 44 00 8B 45  ....D...D...D..E

00440590  F8 EB 1C 8B 45 FC EB 17 6A 10 68 1A 6D 46 00 68  ....E...j.h.mF.h

004405A0  08 6D 46 00 A1 18 FB 46 00 50 E8 50 4F 01 00 59  .mF....F.P.PO..Y

004405B0  59 5D C3 00 4A D8 12 4D FB 21 09 40 45 72 72 6F  Y]..J..M.!.@Erro

004405C0  72 21 00 49 6E 76 61 6C 69 64 20 70 61 72 61 6D  r!.Invalid param

004405D0  65 74 65 72 00                                   eter.

这会是什么？普通的反汇编器会生成以下的结果：

00440540  55                PUSH EBP

00440541  8BEC              MOV EBP,ESP

00440543  83C4 F8           ADD ESP,-8

00440546  DB45 0C           FILD DWORD PTR [EBP+C]

00440549  DC0D B4054400     FMUL QWORD PTR [4405B4]

0044054F  83C4 F8           ADD ESP,-8

00440552  DD1C24            FSTP QWORD PTR [ESP]

00440555  E8 7A290100       CALL 00452ED4

0044055A  83C4 08           ADD ESP,8

0044055D  E8 8A280100       CALL 00452DEC

00440562  8945 FC           MOV DWORD PTR [EBP-4],EAX

00440565  8945 F8           MOV DWORD PTR [EBP-8],EAX

00440568  8B45 08           MOV EAX,DWORD PTR [EBP+8]

0044056B  83F8 04           CMP EAX,4

0044056E  77 28             JA SHORT 00440598

00440570  8A80 7D054400     MOV AL,BYTE PTR [EAX+44057D]

00440576  FF2485 82054400   JMP DWORD PTR [EAX*4+440582]

0044057D  0102              ADD DWORD PTR [EDX],EAX

0044057F  0102              ADD DWORD PTR [EDX],EAX

00440581  0198 0544008E     ADD DWORD PTR [EAX+8E004405],EBX

00440587  05 44009305       ADD EAX,5930044

0044058C  44                INC ESP

0044058D  008B 45F8EB1C     ADD BYTE PTR [EBX+1CEBF845],CL

00440593  8B45 FC           MOV EAX,DWORD PTR [EBP-4]

00440596  EB 17             JMP SHORT 004405AF

00440598  6A 10             PUSH 10

0044059A  68 1A6D4600       PUSH 4405BC

0044059F  68 086D4600       PUSH 4405C3

004405A4  A1 18FB4600       MOV EAX,DWORD PTR [46FB18]

004405A9  50                PUSH EAX

004405AA  E8 504F0100       CALL 004554FF

004405AF  59                POP ECX

004405B0  59                POP ECX

004405B1  5D                POP EBP

004405B2  C3                RETN

004405B3  004A D8           ADD BYTE PTR [EDX-28],CL

004405B6  124D FB           ADC CL,BYTE PTR [EBP-5]

004405B9  2109              AND DWORD PTR [ECX],ECX

004405BB  40                INC EAX

004405BC  45                INC EBP

004405BD  72 72             JB SHORT OT.004600F1

004405BF  6F                OUTS DX,DWORD PTR [EDI]

004405C0  72 21             JB SHORT OT.004600A3

004405C2  0049 6E           ADD BYTE PTR [ECX+6E],CL

004405C5  76 61             JBE SHORT OT.004600E8

004405C7  6C                INS BYTE PTR [EDI],DX

004405C8  696420 70 6172616>IMUL ESP,DWORD PTR [EAX+70],6D617261

004405D0  65:74 65          JE SHORT OT.004600F8

004405D3  72 00             JB SHORT OT.00460095

嗯……，这看上去像是一个函数……至少创建了标准的栈框架（PUSH EBP; MOV EBP,ESP），并有返回。但在地址0044057D处发生了什么？这些命令非常可疑。在返回命令后面的那些是什么？一些ASCII文本，以及某些其他的……。让我们运行代码分析，并使用Objcect扫描。分析之后，代码看上去变得非常棒了：

Dummy     $ 55              PUSH EBP                     ;

00440541  . 8BEC            MOV EBP,ESP                  ;

00440543  . 83C4 F8         ADD ESP,-8                   ;

00440546  . DB45 0C         FILD [ARG.2]                 ;

00440549  . DC0D B4054400   FMUL QWORD PTR [4405B4]      ;

0044054F  . 83C4 F8         ADD ESP,-8                   ;

00440552  . DD1C24          FSTP QWORD PTR [ESP]         ;

00440555  . E8 7A290100     CALL Test._sqrt              ;

0044055A  . 83C4 08         ADD ESP,8                    ;

0044055D  . E8 8A280100     CALL Test.__ftol             ;

00440562  . 8945 FC         MOV [LOCAL.1],EAX            ;

00440565  . 8945 F8         MOV [LOCAL.2],EAX            ;

00440568  . 8B45 08         MOV EAX,[ARG.1]              ;

0044056B  . 83F8 04         CMP EAX,4                    ;

0044056E  . 77 28           JA SHORT Test.00440598       ;

00440570  . 8A80 7D054400   MOV AL,BYTE PTR [EAX+44057D] ;

00440576  . FF2485 82054400 JMP DWORD PTR [EAX*4+440582] ;

0044057D  . 01              DB 01                        ;  Index table to switch 00440582

0044057E  . 02              DB 02                        ;

0044057F  . 01              DB 01                        ;

00440580  . 02              DB 02                        ;

00440581  . 01              DB 01                        ;

00440582  . 98054400        DD Test.00440598             ;  Switch table used at 00440576

00440586  . 8E054400        DD Test.0044058E             ;

0044058A  . 93054400        DD Test.00440593             ;

0044058E  > 8B45 F8         MOV EAX,[LOCAL.2]            ;

00440591  . EB 1C           JMP SHORT Test.004405AF      ;

00440593  > 8B45 FC         MOV EAX,[LOCAL.1]            ;

00440596  . EB 17           JMP SHORT Test.004405AF      ;

00440598  > 6A 10           PUSH 10                      ;  fuStyle = MB_OK|MB_ICONHAND|MB_APPLMODAL

0044059A  . 68 1A6D4600     PUSH Test.004405BC           ;  lpszTitle = "Error!"

0044059F  . 68 086D4600     PUSH Test.004405C3           ;  lpszText = "Invalid parameter"

004405A4  . A1 18FB4600     MOV EAX,DWORD PTR [46FB18]   ;

004405A9  . 50              PUSH EAX                     ;  hwndOwner

004405AA  . E8 504F0100     CALL Test.MessageBoxA        ;  MessageBoxA

004405AF  > 59              POP ECX                      ;

004405B0  . 59              POP ECX                      ;

004405B1  . 5D              POP EBP                      ;

004405B2  . C3              RETN                         ;

004405B3     00              DB 00                        ;

004405B4   . 4AD8124DFB210940DQ FLOAT 3.141592600000000   ;

004405BC   . 45 72 72 6F 72 >ASCII "Error!",0             ;

004405C3   . 49 6E 76 61 6C >ASCII "Invalid paramete"     ;

004405D3   . 72 00           ASCII "r",0                  ;

看！这的的确确是一个函数过程。在0044057D处可疑的命令事实上是一个索引以及一个二阶转换表！分析器还识别并解码出一个标准API函数MessageBox (ASCII版)的调用。这个函数调用用来显示一个错误信息“Invalid parameter”并带有一个“OK”按钮。

004405B3处的一个字节是为对齐浮点常量（猜一下是怎么知道的？）到双字边界而填充的。两个文本串跟在浮点常量的后面。Object扫描器还识别出在另一内存区域中的库函数sqrt和 _ftol（后面一个函数用于浮点数为长整型）。

为了那些对源代码好奇的人，我展现一下源代码。我准备这一另类的无用代码，用来尽可能的举例说明分析器的特点：

int Dummy(int i,int j) {

  int a[2];

  a[0]=a[1]=sqrt(j*3.1415926);

  switch (i) {

    case 0:

    case 2:

    case 4:

      return a[0];

    case 1:

    case 3:

      return a[1];

    default:

      MessageBox(hwmain,"Invalid parameter","Error!",

      MB_OK|MB_ICONSTOP|MB_APPLMODAL);

    break;

  }

}

注意： MB_ICONSTOP 和 MB_ICONHAND 意义相同。


Custom function descriptions
自定义函数描述［Custom function descriptions］

概论

格式描述

预编译类型

概论［Introduction］

OllyDbg包含（做为内部资源）1900多种标准函数以及400多种标准C函数的名称和参数。分析器［Analyzer］ 用这些描述使被调试程序更加易懂。比较下面一个例子，分析器的函数CreateFont：

        PUSH OT.00469F2A               ; ASCII "Times New Roman"

        PUSH 12

        PUSH 2

        PUSH 0

        PUSH 0

        PUSH 0

        PUSH 0

        PUSH 0

        MOV EAX,DWORD PTR [49FA70]

        PUSH EAX

        PUSH 190

        PUSH 0

        PUSH 0

        PUSH 0

        PUSH 10

        CALL <JMP.&GDI32.CreateFontA>

这是分析后的：

        MOV EAX,DWORD PTR [49FA70]

        PUSH OT.00469F2A               ;  FaceName = "Times New Roman"

        PUSH 12                        ;  PitchAndFamily = VARIABLE_PITCH|FF_ROMAN

        PUSH 2                         ;  Quality = PROOF_QUALITY

        PUSH 0                         ;  ClipPrecision = CLIP_DEFAULT_PRECIS

        PUSH 0                         ;  OutputPrecision = OUT_DEFAULT_PRECIS

        PUSH 0                         ;  CharSet = ANSI_CHARSET

        PUSH 0                         ;  StrikeOut = FALSE

        PUSH 0                         ;  Underline = FALSE

        PUSH EAX                       ;  Italic => TRUE

        PUSH 190                       ;  Weight = FW_NORMAL

        PUSH 0                         ;  Orientation = 0

        PUSH 0                         ;  Escapement = 0

        PUSH 0                         ;  Width = 0

        PUSH 10                        ;  Height = 10 (16.)

        CALL <JMP.&GDI32.CreateFontA>  ;  CreateFontA

显然，后面的代码更容易理解。API函数CreateFont 有14个参数。分析器标记所有这些参数的名称并解码他们的值。如果寄存器跟踪开启，那么分析器同时会解码参数Italic 的值为地址49FA70处双字长的内容。解码使用参数的真实值，所以如果[49FA70]里的内容改变了，那么参数Italic的值也会随之改变。当EIP指向跳转或调用该函数的命令，或指向入口时，OllyDbg也会在栈中对已知函数的参数进行解码。

OllyDbg可以对像printf()这样参数个数可变的函数进行参数解码：

        PUSH EAX                       ;  <%.*s>

        PUSH E8                        ;  <*> = E8 (232.)

        PUSH EBX                       ;  <%08X>

        PUSH Mymodule.004801D2         ;  format = "Size %08X (%.*s) bytes"

        PUSH ESI                       ;  s

        CALL Mymodule.sprintf          ;  sprintf

您可以定义自己的函数。每次您打开某个应用程序时，OllyDbg都会重新设置函数参数表并用内嵌描述添充这个表。然后尝试打开文件“<OllyDbg目录>\common.arg”和“<OllyDbg目录>\<应用程序名>.arg”，这里<应用程序名>使用8.3格式（DOS）被调试程序文件名（不带路径和扩展名）。

下面看一个简单的.arg文件实例：

        INFO Simple .ARG file that decodes CreateHatchBrush

        TYPE HS_X

          IF 0 "HS_HORIZONTAL"

          IF 1 "HS_VERTICAL"

          IF 2 "HS_FDIAGONAL"

          IF 3 "HS_BDIAGONAL"

          IF 4 "HS_CROSS"

          IF 5 "HS_DIAGCROSS"

          ELSEINT

        END

        TYPE COLORREF

          IF 0 "<BLACK>"

          IF 00FFFFFF "<WHITE>"

          OTHERWISE

          TEXT "RGB("

          FIELD 000000FF

          UINT

          TEXT ","

          FIELD 0000FF00

          UINT

          TEXT ","

          FIELD 00FF0000

          UINT

          TEXT ")"

        END

        STDFUNC CreateHatchBrush

          "style" HS_X

          "colorref" COLORREF

        END

标准Windos API函数CreateHatchBrush(int style,int colorref) 有两个参数。第一个必须是阴影风格［hatch style］，第二个是常量由红色、绿色、蓝色组成，并用一个32位整数的低三字节表示。为了解码这些参数，文件定义了两个新的参数类型：HS_X 和 COLORREF。

阴影风格是一个简单的枚举类型，如0表示HS_HORIZONTAL（水平风格）、1表示HS_VERTICAL（垂直风格）。IF关键字比较参数与第一个操作数（注意：其总是十六进制的），如果相同则显示第二个操作数里的文本。但万一匹配失败会如何？关键字ELSEINT 会然OllyDbg会将参数解释为一个整数。

COLORREF 更复杂一些。首先尝试解码两个广泛使用的颜色值：黑（全0组成）与白（全0xFF组成）。如果匹配失败，COLORREF尝试解码颜色为一个结构包含红、绿、蓝的亮度。FIELD会用第一个操作数与参数进行逻辑与操作。然后转换结果为整数，并同时按位右移第一个操作及该整数，直到第一个操作数的二进制个位数字为1，这时整数按位右移的结果以无符号10进制显示出来。这个例子做了三次这样的操作，以分离出每个颜色成份。TEXT关键字用于无条件显示文本。如果参数为00030201，那么COLORREF将其解码为RGB(1.,2.,3.)。

大多断API函数都会从栈中移除参数并保护寄存器EBX, EBP, ESI 和 EDI。声明这样的函数为STDFUNC，以告诉分析器该函数做了这样的事情。否则请其描述为FUNCTION。

万一某个参数由多个域及比特值组成，比如上面提到的fdwPitchAndFamily ，我们该怎么办？请看下面这个例子：

        TYPE FF_PITCH

          MASK 03

          IF 00 "DEFAULT_PITCH"

          IF 01 "FIXED_PITCH"

          IF 02 "VARIABLE_PITCH"

          ELSEHEX

          TEXT "|"

          MASK 0C

          BIT 04 "4|"

          BIT 08 "8|"

          MASK FFFFFFF0

          IF 00 "FF_DONTCARE"

          IF 10 "FF_ROMAN"

          IF 20 "FF_SWISS"

          IF 30 "FF_MODERN"

          IF 40 "FF_SCRIPT"

          IF 50 "FF_DECORATIVE"

          ELSEHEX

        END

前两个比特位（第0和等1位）表示倾斜度，必须一起解码。我们使用 MASK 03 来提取这两个比特并通过IF序列来解码。增加了连接符“|”，分别提取第2和第3个比特位，并分别单独解码。最后提取剩余部分并进行解码。

OllyDbg 会移除生成串尾部的连接符“|”、空格、冒号、逗号、分号和等号。

目前版本的分析仅能够解码32位参数。如您不能解码双精度浮点或长双精度浮点的函数参数。

格式描述

自定义解码信息由函数描述和类型描述两部分组成。函数描述部分非常的简单：

FUNCTION|STDFUNC [模块名]函数名

  <第一个参数的名称> <第一个参数的类型>

  ……

  <最后一个参数的名称> <最后一个参数的类型>

END

如果函数从栈中移除参数并保护寄存器EBX, EBP, ESI 和 EDI，请使用关键字STDFUNC。大多少函数都遵循这样的规则。其他情况则声明为FUNCTION。模块（EXE 或 DLL）名是可选的。如果模块名被忽略，OllyDbg会对尝试匹配任何模块。模块名不区分大小写。

函数名称总是区分大小写的。有针对UNICODE的函数必须使用后缀 A 或 W 加以区分，比如SetWindowTextA.。

参数的顺序又C风格的参数使用惯例一致。而16位Windows和32位API函数也是按惯例使用。如果参数名由多个字组成，或者包含特殊字符，那么请将其用两个单引号引起来。与在C语言中一样，省略号（�）是一个特殊的记录用于表示参数数目可变。它必须在函数描述的最后。OllyDbg不会尝试解码这样的参数。如果函数的参数为空，则按functionname(void)对待

OllyDbg 仅支持32位的参数。某些参数已经预定义好了：

INT	以十六进制和带符号整数两种格式显示值
UINT	以十六进制和无符号整数两种格式显示值
HEX	以十六进制格式显示值
BOOL	TRUE 或 FALSE
CHAR	ASCII 字符
WCHAR	UNICODE 字符
FLOAT	32位浮点数
ERRCODE	系统错误代码（像由函数GetLastError()报告的）
ADDR, PTR	地址（特殊情况：NULL）
ASCII	ASCII 串指针
UNICODE	UNICODE 串指针
FORMAT	在类似函数printf()（不包括wscanfW()！）使用的 ASCII 格式串
WFORMAT	类似函数wsprintfW()（不包括scanf()！）使用的 UNICODE 格式串
RECT	RECT（矩形）结构指针
MESSAGE	MSG（ASCII 窗口消息）结构指针
WMESSAGE	MSG（UNICODE 窗口消息）结构指针
HANDLE	句柄（特殊情况：NULL, ERROR_INVALID_HANDLE）
HWND	窗口句柄
HMODULE	模块句柄
RSRC_STRING	带索引的资源串
NULL, DUMMY	有参数，但解码时跳过了

您不能重定义预定义类型。自定义类型允许您将参数分离成几个域并分别解码。类型描述有以下几种格式：

TYPE 类型名

  [TEXT "任何文本"]

  [<域选择器>]

  <域解码>

  <域解码>

  [TEXT "任何文本"]

  [PURGE]

  ...

  <域选择器>

  <域解码>

  <域解码>

  [TEXT "任何文本"]

END

类型名的程度限制在16个字符以内。 OllyDbg会无条件将"任何文本"作为生成的解码。域选择器提取一部分参数用于解码。以下域选择器，可以用于提取域：

MASK 十六进制掩码 - 域等于参数同十六进制掩码按位与（AND）的结果。

FIELD 十六进制掩码 - 参数同十六进制掩码按位与（AND）的数值，然后OllyDbg同时按位右移掩码和计算的数值直到掩码的二进制个位为1，这时数值按位右移的结果就是域的值。例如参数0xC250， FIELD F0，得到的结果是5。

SIGFIELD十六进制掩码 -参数同十六进制掩码按位与（AND）的数值，然后OllyDbg同时按位右移掩码和计算的数值直到掩码的二进制个位为1，这时数值按位右移的结果转成带符号32位数就是域的值。例如参数0xC250 ，SIGFIELD FF00，得到的结果是0xFFFFFFC2。

简单域的解码会一次显示整个域的内容：

HEX - 以十六进制形式显示域内容；

INT - 以带符号十进制形式显示域内容（带小数点）；

UINT -以无符号十进制形式显示域内容（带小数点）；

CHAR - 以 ASCII 字符形式显示域内容。

域若是一个枚举类型，则可以使用IF序列，如果必要的话还可以在IF序列后跟关键字 TRYxxx 与 ELSExxx：

IF 十六进制值 "文本" - 如果域等于十六进制值，则将文本作为输出字符串；

TRYASCII - 如果域是一个指向ASCII串的指针，则显示这个串；

TRYUNICODE - 如果域是一个指向UNICODE串的指针，则显示这个串；

TRYORDINAL - 如果域是一序号（有16位均为0），则会显示为序号（“#”后跟整数）；

OTHERWISE - 如果前面IF语句为真，则停止解码，否则继续解码；

ELSEINT - 如果前面所有的 IF 和 TRYxxx 语句均失败，则以带符号十进制数形式（带小数点）显示这个域；

ELSEHEX -如果前面所有的 IF 和 TRYxxx 语句均为失败，则以十六进制形式显示这个域；

ELSECHAR -如果前面所有的 IF 和 TRYxxx 语句均为失败，则以 ASCII 字符形式显示这个域；

ELSEWCHAR -如果前面所有的 IF 和 TRYxxx 语句均为失败，则以 UNICODE 字符形式显示这个域。

如果域是一个二进制位集，则可以使用BIT序列，如果必要的话可以后面跟关键字 BITZ 与 BITHEX ：

BIT 十六进制掩码 "文本" - 如果值与十六进制掩码按位与（AND）的结果不是0，则将文本做为输出串；

BITZ十六进制掩码 "文本" - 如果值与十六进制掩码按位与（AND）的结果是0，则将文本做为输出串；

BITHEX十六进制掩码 - 如果值与十六进制掩码按位与（AND）的结果不是0，则将结果以十六进制形式显示。

特殊关键字 PURGE 会从输出串尾部移除以下几种符号：

空格	' '
逗号	','
或	'|'
冒号	':'
等于	'='

这会让某些解码情况变的简单。关键字END是类型定义结尾标记并会自动运行PURGE命令。

预编译类型

OllyDbg在预编译资源时，已经包含150多种类型描述。以下列出了一部分。您可以在自定义文件中直接使用这些类型：

LANG_X - 操作系统语言ID（0 - 未知、 9 - 语言、 C - 法语，等等）

GENERIC_X - 访问类型（GENERIC_READ, GENERIC_WRITE...）

FILE_SHARE_X - 共享类型（FILE_SHARE_READ, FILE_SHARE_WRITE）

CREATEFILE_X - 文件创建模式（CREATE_NEW, OPEN_EXISTING...）

FILE_ATTRIBUTE_X - 文件属性（READONLY, SYSTEM, DELETE_ON_CLOSE...）

RT_AXX - 资源类型（RT_CURSOR, RT_GROUP_ICON, ASCII string...）

RT_WXX - 资源类型（RT_CURSOR, RT_GROUP_ICON, UNICODE string...）

COORD - 坐标结构 "(X=xxx,Y=yyy)"

STD_IO_X - 标准句柄（STD_INPUT_HANDLE, STD_ERROR_HANDLE...）

GMEM_X - 全局内存类型（GMEM_FIXED, GPTR...）

LMEM_X - 局部内存类型（LMEM_FIXED, LPTR...）

FSEEK_X - 文件查找类型（FILE_BEGIN, FILE_CURRENT...）

OF_X - 文件模式（fOF_READ, OF_SHARE_COMPAT, OF_VERIFY...）

O_X - 文件创建模式（O_RDONLY, O_BINARY, SH_COMPAT...）

SEMAPHORE_X - 信号量类型（SEMAPHORE_ALL_ACCESS, SYNCHRONIZE...）

SLEEP_TIMEOUT - 超时（INFINITE 或时间）

ROP - 一些标准柵格运算标志代码（ROP）(SRCCOPY, MERGEPAINT...)

COLORREF - RGB 颜色值（"<WHITE>", "RGB(rr.,gg.,bb.)"...）

WS_X - 窗口风格（WS_OVERLAPPED, WS_POPUP...）

WS_EX_X - 扩展窗口风格（WS_EX_DLGMODALFRAME, WS_EX_TOPMOST...）

MF_X - 菜单标志（MF_BYPOSITION, MF_ENABLED...）

WM_X - ASCII窗口消息类型（WM_CREATE, WM_KILLFOCUS, CB_SETCURSEL...）

WM_W - UNICODE窗口消息类型（WM_CREATE, WM_KILLFOCUS, CB_SETCURSEL...）

VK_X - 虚拟键盘代码（VK_LBUTTON, VK_TAB, VK_F10...）

MB_X - message box style (MB_OK, MB_ICONHAND...)

HKEY_X - 预定义注册表句柄（HKEY_CLASSES_ROOT, HKEY_LOCAL_MACHINE...）

还有更多的预编译类型。如果常量在它文件被定义为ABC_ xxxxxxxx，那么一般就有ABC_X预编译类型。


Search
搜索［Search］

OllyDbg 允许您使用以下的搜索方式：

符号名（标签）［Symbolic name (label)］

二进制串［binary string］

常量［constant］

命令［command］

命令序列［sequence of commands］

模块间调用［intermodular calls］

修改过的命令或数据［modified command or data］

自定义标签［user-defined label］

自定义注释［user-defined comment

文本字符串［text string］

Run跟踪的记录［record in run trace］

参考命令［referencing commands］


Names window
名称窗口［Names window］

名称窗口用户列出在某个模块中全部符号名称（标签［labels］）。这些名称包括输出函数（方便其他模块调用的公用符号）、引入函数（调用其他模块的函数符号名）、用户自定义标签以及从调试休息或目标文件中提取的标签。在反汇编窗口或可执行模块窗口中按 Ctrl+N，可以显示名称。

引入函数前面都有调用的模块名。某些模块的输出函数符号名只是一个序号。OllyDbg会将其显示为#nnn 的形式，这里nnn为十进制数字。

您可以在地址选项［Address options］.中设置名称的排列顺序（按地址或字母排序）。而按相对应的列标题栏或从快捷菜单中选择，可以改变排列顺序。如果您按名称字母顺序排序，请注意OllyDbg是忽略模块名和某些符号名前缀，如下划线（_）、问号（?）或和号（&）。

直接用键盘输入某个名称，可以迅速找这个名称。名称窗口的标题栏会显示您目前输入了哪些字母，而窗口会自动滚动到第一个匹配的名称上。比较时会忽略大小写与模块名及非字母的前缀。退格键会删除最后输入的字符。

名称窗口支持以下功能：

刷新［Actualize］ - 更新想模块相关联的名称列表。如果模块增加、删除或修改某个名称，OllyDbg都会自动更新列表，但不跟踪在不同模块中改变。

跟进到反汇编窗口［Follow in Disassembler］（回车） - 在反汇编窗口中跟进地址。如果地址指向当前模块的可执行代码，那么这个菜单项是可用的。

在反汇编窗口中跟进到引入函数［Follow import in Disassembler］ - 引入函数是一个指针，指向调用模块的名称地址。使用这个菜单项可以在反汇编窗口中跟进这个引入函数。

跟进到数据窗口［Follow in Dump］ - 跟进地址到CPU数据窗口中。F

查找参考［Find references］ - 搜索该模块中所有使用该参考名的命令。

查找参考到引入函数［Find references to import］（回车） - 搜索模块中所有使用该引入函数reference 地址的命令。某些编译器通过间接跳转实现调用引用函数。只要这样的跳转存在，OllyDbg会自己搜索这个跳转的参考。注意这个选项同“跟进到反汇编窗口［Follow in Disassembler］”是相互排斥的。

查看调用树［View call tree］ - 显示当前名称的调用树［Call tree］。

获得符号名的帮助［Help on symbolic name］（Ctrl+F1） - 如果API帮助文件已经选择，则搜索该符号名的解释说明。

切换断点［Toggle breakpoint］（F2） - 在所选命令地址处切换 INT3 断点 。

条件断点［Conditional breakpoint］（Shift+F2） - 在所选命令地址处设置条件断点。

条件记录断点［Conditional log breakpoint］（Shift+F4） - 设置记录断点。详细描述，请查看断点。

在引入函数上切换断点［Toggle breakpoint on import］ - 在引入函数上设置 INT3 断点

在引入函数上设置条件断点［Conditional breakpoint on import］ - 在引入函数上设置条件断点。

在引入函数上设置条件记录断点［Conditional log breakpoint on import］ - 在引入函数上设置记录断点。

在每个参考上设置断点［Set breakpoint on every reference］ - 搜索所有的参考，并在每个参考上设置无条件 INT3 断点。这个命令非常有用，如果您希望在基于Windows95的操作系统上中断对某个API函数的所有调用。而在Windows NT下您可以直接在API函数的入口设置断点。这个命令不会尝试搜索由 GetProcAddress 函数加载的函数参考。

在每个参考上设置记录断点［Set log breakpoint on every reference］ - 在每个搜索到的参考上使用相同的条件设置记录断点。

移除所有断点［Remove all breakpoints］ - 搜索参考并从全部找到的参考中移除所有类型的断点。

外观［Appearance］ - 查看这里.


SSE support
SSE支持［SSE support］

SSE （Streaming SIMD Extentions）指令集首先是在Intel的奔腾Ⅲ处理器中使用的。它们允许由时处理高达4个单精浮点操作数。OllyDbg 1.06 以上的版本就可以编译和反汇编SSE命令，并能够显示或修改128位SSE寄存器的内容。实现这个任务看起来并不容易。主要的问题是对于现在所有的操作系统版本，都缺乏对其调试的支持。因此，调试器不能够从操作系统中获得这些寄存器。为了克服这一限制，OllyDbg 在调试线程内部注入并执行了一小段代码，以读取并更新SSE寄存器。这个操作非常慢也非常危险，我建议您除非绝对需要，请关闭SSE寄存器解码。Run跟踪［Run trace］不保存SSE寄存器到记录中。

注意：OllyDbg不支持SSE2（奔4扩展指令集）。


Binary search
搜索二进制串［Search for binary strings］

其他搜索类型

OllyDbg 能够搜索个多达256字节长度的二进制。在大多数窗口中，这个功能一般使用快捷键Ctrl+B。

您可以使用ASCII和UNICODE或者十六进制三种搜索模式，如上图所示。出于方便的目的，编辑控件是同步的，三个控件的任意一个发生变化，都会在另外两个控件中同步更新。通过按 Ctrl＋↑ 或 Ctrl+↓，您可以迅速在不同控件的相同字节位置快速移动。

HEX 控件允许您从比较中排除半字节或一字节。在HEX控件中，输入疑问标记（?）来标记这半个字节被排除。如果您粘贴到 HEX 控件中，OllyDbg会在剪切板中扫描文本，并从中提取出十六进制数字（0..9, A..F, a..f）和疑问标记（?），而其他符号都会被忽略掉。另外，您能够在搜索时标记区分大小写。

有时您需要定位某个代码片断，在被调试程序的不同版本中的位置。如果代码没有变化，您可以选择它，然后复制到剪切版，打开另外一个版本，并粘贴它们到搜索窗口的 HEX 控件中。另外，若要搜索时不与加载地址相关，请使用选项“二进制复制时标记重定位”将重定位的字符用疑问标记（?）代替。


Search for a sequence of commands
搜索命令序列［Search for a sequence of commands］

其他搜索类型

编译器通常使用相同的命令序列来实现相同的任务。例如，许多函数过程都通过执行 PUSH EBP; MOV EBP,ESP 命令序列来创建栈框架。为了定位入口，可以尝试搜索十六进制 55, 8B, EC。但有两个问题，命令 MOV EBP,ESP 有另外一种译码方式 89, E5，并且某些针对奔腾处理器专门优化的编译器可能在这之前插入不影响 EBP 和 ESP寄存器的命令。

另外的例子是：为了访问一个100字节长度的结构数组，编译器可能生成如下代码：

LEA EAX,[4*EAX+EAX]	; EAX乘以5［Multiplies EAX by 5］

LEA EAX,[4*EAX+EAX]	; EAX乘以5［Multiplies EAX by 5］

MOV EBX,[4*EAX+base_of_array]	; EAX乘以5［Multiplies EAX by 4］

或者只有细微的不同，但结果相同：

LEA ECX,[4*EAX+EAX]

LEA ECX,[4*ECX+ECX]

MOV EBX,[4*ECX+base_of_array]

或者还有更多可能的替代方法。

为了帮助您解决类似的问题，OllyDbg实现了强大的命令序列搜索功能（在反汇编窗口中的快捷键为Ctrl+S）。您可以输入多达8条的汇编命令。对于每个列出的命令，OllyDbg 都会产生所有可能的译码形式，并在搜索时测试这些命令的每种可能的组合。您可以使用模糊的操作数和命令。然而，LEA R32,[4*R32+R32] 匹配到的 ESI,[EAX*4+EBX] ，不是您正想要寻找的。OllyDbg 允许您指定伪寄存器 RA 和 RB。像R32一样，它们可以替代任何32位通用寄存器，但他们在整个序列中含义的总是不变的。RA 和 RB 可能是一致的。这样，LEA RA,[4*RA+RA] 匹配到LEA EAX,[4*EAX+EAX] 和 LEA ESI,[4*ESI+ESI] ，但不会匹配到 LEA ESI,[EAX*4+EBX]。

通过建立ANY n，可以跳过 n 个任意命令。如果您希望在函数过程的头部可以有两条任意的命令。可以使用以下格式：

PUSH EBP

ANY 2

MOV EBP,ESP,

第二种可能的搜索模式，如下：

LEA RB,[4*RA+RA]

ANY

LEA R32,[4*RB+RB]

按 Ctrl+L 可以继续搜索其他符合的命令序列。您要可以一次找完所有符合的命令序列，然后使用键盘快捷键 Alt+F7 和 Alt+F8 来浏览这个列表。


Search for modified commands or data
搜索修改的命令或数据［Search for modified commands or data］

其他搜索类型

数据窗口支持备份［Backup］ 数据副本。如果您在反汇编窗口或修改代码或在CPU的数据窗口修改数据，OllyDbg会自动创建备份。只要真实代码或数据与备份的有不同，OllyDbg就会高亮显示不同之处。您可以从快捷菜单中选择“搜索［Search for］|修改的代码［Modified code］”或“ 搜索［Search for］|修改的数据［Modified data］，来查找下一个不同之处，按 Ctrl+L 键，也可以搜索下一个修改位置。


Profile
统计［Profile］

统计总是和Run跟踪［Run trace］一起工作的。统计会简单计算某个命令地址在Run跟踪记录中出现的次数。这个操作可能会花费大量的时间，因此统计窗口中是在得到您明确的要求时才会更新。如果某些连续的命令均有相同的计数，统计窗口会仅仅显示这个序列的第一条命令。

统计窗口执行以下操作：

刷新［Actualize］ - 程序计算选择模块的统计数字；

跟进到反汇编窗口［Follow in Disassembler］ （回车） - 跟进命令或具有相同计数的命令序列到反汇编窗口中。

在Run跟踪中查找［Find in Run trace］ - 查找最近在Run跟踪中出现的命令。如果同步CPU和Run跟踪［Synchronize CPU and Run trace］ i开启的话，CPU窗口会显示保留有原始寄存器的命令。


Call stack
调用栈［Call stack］

调用栈窗口（快捷键：Alt+K）根据选定线程的栈，尝试反向跟踪函数调用顺序并将其显示出来，同时包含被调用函数的已知的或隐含的参数。如果调用函数创建了标准的堆栈框架（PUSH EBP; MOV EBP,ESP），则这个任务非常容易完成。现代的优化编译器并不会为栈框架而操心，所以OllyDbg另辟蹊径，采用了一个变通的办法。例如，跟踪代码到下一个返回处，并计算其中全部的入栈、出栈，及 ESP 的修改。如果不成功，则尝试另外一种办法，这个办法风险更大，速度也更慢：移动栈，搜索所有可能的返回地址，并检查这个地址是否被先前的已分析的命令调用。如果还不行，则会采用启发式搜索。栈移动［Stack Walk］可能会非常慢。OllyDbg 仅在调用栈窗口打开时才会使用。

调用栈窗口包含5个栏目：地址［Address］、栈［Stack］、过程［Procedure］，调用来自［Called from］，框架［Frame］。地址［Adress］栏包含栈地址，栈［Stack］栏显示了相应的返回地址或参数值。

函数［Procedure］（或 函数/参数［Procedure / arguments］）显示了被调用函数的地址，在某些情况下，OllyDbg并不能保证该地址是正确的并会添加如下标记之一：

?	找到的入口点不可靠
可能［Maybe］	OllyDbg无法找到精确的入口点，报告的地址是用启发式算法猜测的。
包含［Includes］	OllyDbg无法找到入口点，仅知道该函数包含显示的地址

通过按例标题栏上的按钮或从菜单中选择“隐藏/显示参数［Hide/Show arguments］”，可以在显示或隐藏函数的参数之间切换。

调用来自［Called from］用于显示调用该函数的命令地址。最后一栏是框架［Frame］这一栏默认是隐藏的，如果框架指针的值（寄存器EBP）已知的话，则该栏用于显示这个值。

当调用函数经过分析［analyzed］.后，栈移动会更可靠并且迅速。

相关信息：调用树［Call tree］


Call tree
调用树［Call tree］

调用树（快捷键：在反汇编窗口中Ctrl+K）利用分析［Analysis］的结果来找出指定函数过程直接或间接调用的函数列表，同时列出指定函数过程被调用的地址。为了避免由此可能造成的副作用。调用树会判断选定函数是否明确地是递归的。“明确地”意味着它不会跟踪目标未知的调用，比如CALL EAX。如果函数过程中有未知调用，调用树将会添加标记“未知目标”。

某些函数调用将会添加如下注释之一：

叶子［Leaf］	不调用其他函数
纯函数［Pure］	不调用函数，不会产生副作用
单返回［RETN］	只有一个RETN 命令
系统［Sys］	系统动态链接库中的函数。系统动态链接库定义为保存在系统目录下的动态链接库。

如果想在调用树上移动，可以双击“被调用［Called from］”或“调用/直接调用［Calls/Calls directly］”两栏中的地址。调用树窗口保存了移动记录（快捷键“-”和“+”）。

如果被调试的程序包含几个模块，推荐您分析所有模块。Call tree 不会试图处理系统函数。

相关信息：分析［Analysis］, 调用栈［Call stack］


Windows
窗口［Windows］

窗口用于列出所有属于被调试程序窗口及其窗口相关的重要参数。

基于NT的操作系统隐藏了窗口过程（处理所有窗口消息的函数）的地址。这样可以有效的禁止属于不同进程窗口的子类化［subclassing］，但这也给调试器带来的麻烦。OllyDbg 向被调试程序代码注入，通过执行 GetWindowLong 函数来获得窗口过程的地址。这种方式非常耗时，有时（特别是多线程程序）还不安全。只有在被调试程序暂停，同时在选项允许代码注入以获得WinProc地址［Allow code injection to get address of WinProc］。

中设置为允许注入时，我才会使用这种方法。

由于空间有限，这个窗口中很多用于显示其他信息的列通常都被隐藏了。例如，窗口过程列［WinProc］标记子类窗口（窗口过程与类过程不同），ID 栏以十六进制的形式显示控件的 ID，而风格［Style］则显示由 WM_xxx 标志集解码后的窗口风格。通过改变相应列的宽度，可以看到这些附加信息。

为了能在消息上设置断点，OllyDbg 创建了一个名为“<WinProc>”的特殊条件记录断点。我们来看一下它是如何工作的，假设有一个句柄为00001234的按钮，需要接到任何按钮消息时暂停。在断点设置好后，以条件记录断点的方式打开它，那么您会看到如下的设置：

条件［Condition］:      [ESP+4]==00001234 && [ESP+8] IN (0F0..0F7,135)

描述［Explanation］:    <WinProc>

暂停［Pause program］:  On condition

在窗口过程的入口处，栈中包含以下内容：

[ESP+00]	返回地址［Return address］
[ESP+04]	窗口句柄［Window's handle］
[ESP+08]	消息［Message］
[ESP+0C]	W参数［wParam］
[ESP+10]	L参数［lParam］

现在我们明白了条件中的第一部分表示“窗口句柄必须是00001234”，而第二部分表示：“消息必须是 BM_GETCHECK……BM_SETIMAGE、WM_CTLCOLORBTN之一”。

特别注意：窗口句柄在每次创建时均不同，由此如果您设置的断点仅仅是作用于目前的窗口，断点仅在窗口的生命期［the life of this window］内有效。

消息组［Message groups］

组［Group］	组中消息［Messages in group］
任何消息［Any message］	所有消息
创建与销毁［Creation and destruction］	WM_CREATE, WM_DESTROY, WM_CLOSE, WM_QUERYENDSESSION, WM_QUIT,WM_ENDSESSION, WM_NCCREATE, WM_NCDESTROY, WM_INITDIALOG
Window activation［窗口活动］	WM_ACTIVATE, WM_SETFOCUS, WM_KILLFOCUS,WM_ENABLE, WM_SHOWWINDOW, WM_CHILDACTIVATE, WM_QUERYNEWPALETTE
Window position and size［窗口位置与大小］	WM_MOVE, WM_SIZE, WM_QUERYOPEN, WM_SHOWWINDOW, WM_GETMINMAXINFO, WM_WINDOWPOSCHANGING, WM_WINDOWPOSCHANGED, WM_NCCALCSIZE, WM_SIZING, WM_MOVING, WM_ENTERSIZEMOVE, WM_EXITSIZEMOVE
Commands and notifications［命令与通知］	WM_MEASUREITEM, WM_COMMNOTIFY, WM_NOTIFY,WM_NOTIFYFORMAT, WM_STYLECHANGING, WM_STYLECHANGED, WM_COMMAND, WM_SYSCOMMAND, WM_ENTERIDLE, WM_PARENTNOTIFY, WM_MDIRESTORE
System［系统］	WM_SYSCOLORCHANGE, WM_WININICHANGE, WM_DEVMODECHANGE, WM_ACTIVATEAPP, WM_FONTCHANGE, WM_TIMECHANGE, WM_COMPACTING, WM_POWER, WM_USERCHANGED, WM_DISPLAYCHANGE, WM_NCACTIVATE, WM_POWERBROADCAST, WM_DEVICECHANGE, WM_PALETTEISCHANGING, WM_PALETTECHANGED
Drawing［绘制］	WM_SETREDRAW, WM_PAINT, WM_ERASEBKGND, WM_PAINTICON, WM_ICONERASEBKGND, WM_DRAWITEM, WM_NCPAINT, WM_QUERYNEWPALETTE, WM_PRINT, WM_PRINTCLIENT
Scrolling ［滚动］	WM_HSCROLL, WM_VSCROLL, WM_CTLCOLORSCROLLBAR
Icon［图标］	WM_QUERYOPEN, WM_QUERYDRAGICON, WM_GETICON, WM_SETICON
MDI［多文档］	WM_MDICREATE, WM_MDIDESTROY, WM_MDIACTIVATE, WM_MDIRESTORE, WM_MDINEXT, WM_MDIMAXIMIZE, WM_MDITILE, WM_MDICASCADE, WM_MDIICONARRANGE, WM_MDIGETACTIVE, WM_MDISETMENU
Dialog［对话框］	WM_CANCELMODE, WM_NEXTDLGCTL, WM_MEASUREITEM, WM_DELETEITEM, WM_GETDLGCODE, WM_CTLCOLORMSGBOX, WM_CTLCOLORDLG
Menu［菜单］	WM_MEASUREITEM, WM_HELP, WM_CONTEXTMENU, WM_INITMENU, WM_INITMENUPOPUP, WM_MENUSELECT, WM_MENUCHAR, WM_ENTERMENULOOP, WM_EXITMENULOOP, WM_NEXTMENUWM_MDIREFRESHMENU
Text［文本］	WM_SETTEXT, WM_GETTEXT, WM_GETTEXTLENGTH, WM_SETFONT, WM_GETFONT
Mouse［鼠标］	WM_SETCURSOR, WM_MOUSEACTIVATE, WM_NCHITTEST, WM_NCMOUSEMOVE, WM_NCLBUTTONDOWN, WM_NCLBUTTONUP, WM_NCLBUTTONDBLCLK, WM_NCRBUTTONDOWN, WM_NCRBUTTONUP, WM_NCRBUTTONDBLCLK, WM_NCMBUTTONDOWN, WM_NCMBUTTONUP, WM_NCMBUTTONDBLCLK, WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBLCLK, WM_RBUTTONDOWN, WM_RBUTTONUP, WM_RBUTTONDBLCLK, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MBUTTONDBLCLK, WM_MOUSEWHEEL, WM_XBUTTONDOWN, WM_XBUTTONUP, WM_XBUTTONDBLCLK, WM_CAPTURECHANGED
Keyboard［键盘］	WM_VKEYTOITEM, WM_CHARTOITEM, WM_SETHOTKEY, WM_GETHOTKEY, WM_KEYDOWN, WM_KEYUP, WM_CHAR, WM_DEADCHAR, WM_SYSKEYDOWN, WM_SYSKEYUP, WM_SYSCHAR, WM_SYSDEADCHAR, WM_HOTKEY
Clipboard［剪切板］	WM_CUT, WM_COPY, WM_PASTE, WM_CLEAR, WM_UNDO, WM_RENDERFORMAT, WM_RENDERALLFORMATS, WM_DESTROYCLIPBOARD, WM_DRAWCLIPBOARD, WM_PAINTCLIPBOARD, WM_VSCROLLCLIPBOARD, WM_SIZECLIPBOARD, WM_ASKCBFORMATNAME, WM_CHANGECBCHAIN, WM_HSCROLLCLIPBOARD
Edit control［编辑控件］	All EM_xxx 消息
Static control［静态控件］	All STM_xxx 消息
Button［按钮］	All BM_xxx 消息, WM_CTLCOLORBTN
Combo box［组合框］	All CB_xxx 消息, WM_COMPAREITEM
List box［列表框］	All LB_xxx 消息, WM_COMPAREITEM, WM_CTLCOLORLISTBOX
IME［输入法］	All WM_IME_xxx 消息
User-defined［用户自定义］	所有大于或等于WM_USER的消息


Heap list
堆列表［Heap list］

堆列表非常类似于内存映射［Memory map］。用于显示被调试程序已经分配的内存块列表。

为了找到堆，OllyDbg利用了Kernel32.dll中的 Heap32ListFirst、Heap32First 等几个API函数。但这些函数在Windows NT系统下不能执行同时在 Windows 2000 中 OllyDbg 会被挂起。我不能解释这是什么原因，因此堆列表目前仅支持Win95系统。


Patch manager
补丁［Patches］

补丁窗口（快捷键 Ctrl+P）用于显示补丁列表。在这里您能够浏览、应用、移除补丁。

准确的说，补丁不同于全局备份［global backup］ 和真实代码。如果操作系统卸载某个模块，OllyDbg将会检查代码段的不同之处，并把它们保存到.udd文件中。在下一次调试时，您可以很快地恢复它们。一旦加入到补丁列表中，补丁会一直保持，除非补丁被重写或.udd文件被删除。

搜索补丁非常的耗时，因此您修改代码后，补丁窗口不会实时更新。您可以在快捷菜单中选择刷新［Actualize］或在工作栏上按补丁按钮，来刷新补丁列表。


Search for intermodular calls
搜索模块间调用［Search for intermodular calls］

其他搜索方式［Other types of search］

这种搜索方式会找到所有需要使用扩展模块（DLLs）的函数调用，并可以在这些API函数上设置断点。搜索范围包括所有的直接或间接调用，直接或间接跳转，Win95 thunks 以及thunks的组合。在很多的情况下，函数地址都可以通过 GetProcAddress 获得（当然是在 GetProcAddress 被调用之后）。

您可以按地址或字母顺序对搜索到的结果进行排序。如果您想查找某个特定的函数，最简单的办法就是直接输入函数名（注：模块名和前面的下划线均不用输入）。


SEH window
SEH 窗口［SEH window］

SEH 是结构异常处理［Structured Exception Handling］的缩写。如果应用程序做了非法的事情，比如除0或调用一个完全不存在的函数，系统将产生一个异常，同时查找准备处理这个异常的句柄。在C++的代码中，您可以使用try/catch语句来声明句柄。

异常处理必须和代码相关。比如，在某一个代码中除0操作是有意义的，您可以想设置除0的含义；而在另外的一段代码中发生除0操作时，最好的办法或许是重新处理或中止处理。为了处理这种情况，异常句柄就要连接成链。每一个链元素中都含有两个长度为双字的数据项：

地址+0  指向下一条SEH记录的指针［Pointer to next SEH record］

地址+4  异常处理函数地址［Address of SE handling function］

若指针值等于 0xFFFFFFFF，则表示链结尾。每个线程都有自己 SHE 链，链的开始地址为相关线程数据块的前四字节。通过表达式 [FS:0]，可以定位链开始地址。如果到达链尾部，系统将调用默认的异常句柄；在大多数情况下，这时会显示一个对话框，并结束应用程序。

SEH 窗口显示当前 CPU 窗口内线程的SEH链。从这个窗口里，您可以进入到SEH链记录或 SEH句柄处，您还可以在处理函数的入口处下断点。为了避免无限递归，链的最大长度限制为 500 项。


Plugins
插件［Plugins］

插件是一个DLL，存放在OllyDbg的目录中，用于增加 OllyDbg 的功能。您可以从 OllyDbg 的主页上（http://home.t-online.de/home/Ollydbg）免费下载插件开发工具包plug110.zip。

插件可以设置断点，增加标签和注释，修改寄存器和内存。插件可以添加到主菜单和很多的窗口（比如反汇编窗口、内存窗口）的快捷菜单中，也可以拦截快捷键。插件还可以创建MDI（多文档界面）窗口。插件还可以根据模块信息和OllyDbg.ini文件，将自己数据写到.udd文件中；并能读取描述被调试程序的各种数据结构。插件API包含了多达170个函数。

许多第三方插件都可以从Internet网上获得，比如由网友TBD创建并维护的OllyDbg的论坛（http://ollydbg.win32asmcommunity.net）。

安装插件的方法：将DLL复制到插件目录［plugin directory］中，然后重新启动Ollydbg。默认情况下，这个插件目录为ollydbg.exe文件所在的目录。

现在的版本中已经包含了两个“原始”插件： 书签［Bookmark］ and 命令行［Command line］. 他们的源代码都保存在plug110.zip.文件中。这些插件都是免费的，您可以任意修改或使用它们。


Bookmark plugin
书签插件［Bookmark plugin］

该插件允许通过在反汇编窗口中的使用键盘快捷键或快捷菜单，来设置高达10个代码书签。设置之后您可以通过快捷键、快捷菜单或书签窗口，迅速到达到任一个书签。书签是程序特定的。它们会保存到.udd文件中。

从主菜单中选择“插件［Plugin］|书签［Booknmarks］|书签［Bookmarks］，可以打开一个窗口列出所有的书签。

在反汇编窗口中使用书签子菜单，也可能对书签进行操作。

书签［Bookmarks］：

插入书签0［Insert bookmark 0］ (Alt+Shift+0)，

...

插入书签9［Insert bookmark 9］ (Alt+Shift+9) - 在选中行设置书签；

删除书签0［Delete bookmark 0］,

...

删除书签9［Delete bookmark 9］ - 删除书签；

跳到书签0处［Go to bookmark 0］ (Alt+0)，

...

跳到书签9处［Go to bookmark 9］ (Alt+9) - 跟入书签。


Command line plugin
命令行插件［Command line plugin］

命令行插件是OllyDbg的一个非常简单的命令接口。打开命令行窗口的方法：按快捷键Alt+F1，或从主菜单中选择插件［Plugins］|命令行［Command line］|命令行［Command line］。

命令行插件支持以下命令：

命令	描述	举例
计算［Expressions］
CALC 表达式	计算表达式的值	CALC EAX/2+1
? 表达式	同上
表达式 (第一个字符不能是字母)	同上	2*2
WATCH 表达式	增加需要监视的表达式	WATCH +[460030+ESI]
W 表达式	同上
分配［Assignments］
SET 寄存器=表达式	将表达式的值，写入8、16、32位寄存器中	SET AL=0 SET ESI=[DWORD EDI-10]
reg=表达式	同上	AX=0FFFF
SET 内存=表达式	将表达式的值，写入8、16、32位内存中	SET [410000]=80000001 SET [BYTE EAX+ESI*2]=0
反汇编窗口［Disassembler］
AT 表达式	在反汇编窗口中转到指定地址处	AT 410000
FOLLOW 表达式	同上	FOLLOW EAX
ORIG	跳到当前EIP处
*	同上
数据与栈
D 表达式	在数据窗口中跟进地址	D 460000
DUMP表达式	同上
DA [表达式]	以汇编格式显示数据
DB [表达式]	以十六进制字节格式显示数据
DC [表达式]	以ASCII文本显示数据	DC EAX
DD [表达式]	以地址（栈格式）显示数据
DU [表达式]	以UNICODE显示数据
DW [表达式]	以十六进制字格式显示数据
STK 表达式	在栈中跟进地址
编译
A 表达式 [,命令]	编辑指定地址处的命令	A 410000, XOR EAX,EAX
标签和注释
L 表达式, 标签	向指定地址设置符号名	L EAX, loopstart
C 表达式, 注释	在指定地址设置注释	C EAX, Here loop starts
断点和命令
BP 表达式 [,条件]	在指定地址设置 INT3 断点	BP EAX+10 BP 410010, EAX==WM_CLOSE BP Kernel32.GetProcAddress
BPX 标签	在当前模块每一个对外部标签的调用设置断点	BPX CreateFileA
BC 表达式	删除指定地址的断点	BC 410010
MR 表达式1 [,表达式2]	设置指定范围的内存访问断点
MW 表达式1 [,表达式2]	设置指定范围的内存写断点Set
MD	移除内存断点
HR 表达式	设置1字节的硬断点，当访问该地址时中断
HW 表达式	设置1字节的硬断点，当写该地址时中断
HE 表达式	设置硬断点，当执行该地址时中断
HD [表达式]	移除指定地址处的硬断点
跟踪命令
STOP	暂停执行
PAUSE	同上
RUN	运行程序
G [表达式]	运行直到地址
GE [表达式]	跳过异常句标，并运行直到地址
S	单步步人
SI	同上
SO	单步步过
T [表达式]	跟踪步入，直到地址
TI [表达式]	同上
TO [表达式]	跟踪步过，直到地址
TC 条件	跟踪步入，直到条件满足
TOC 条件	跟踪步过，直到条件满足
TR	执行，直到返回
TU	执行，直到用户代码段
OllyDbg窗口
LOG	显示记录窗口
MOD	显示执行模块窗口
MEM	显示内存窗口
CPU	显示CPU窗口
CS	显示调用栈
BRK	显示断点窗口
OPT	编辑选项
其他命令
EXIT	关闭OllyDbg
QUIT	同上
OPEN [文件名]	打开要调试的可执行文件
CLOSE	关闭调试程序
RST	重运行当前程序
HELP	显示该标签帮助
HELP OllyDbg	显示OllyDbg帮助
HELP APIfunction	显示API帮助	HELP CreateFile

命令不区分大小写，括号中的参数是可选的。表达式［Expressions］可以包含常量、寄存器和内存参考，并支持所有的标准算术运算和逻辑运算。默认情况下，所有的常量都是十六进制的。在数字的结尾加点，可又将其标识为十进制数。如果您没有指定内存大小，那么插件都会认为是32位的。

条件记录断点［Conditional logging breakpoint］ 允许您，在条件中断发生时，执行指定的插件命令。为了传递到命令行插件，请在命令之前加上点，例如：

.EAX=0

.RUN

举例说明：

•	CALC EAX/2+1 - 计算表达式的值，并显示十六进制格式结果。寄存器属于在CPU窗口中显示的线程；

•	2*2 - 计算表达式的值（4），并以十六进制格式显示；

•	WATCH +[460030+ESI] -增加监视，以十六进制和十进制两种方式显示在地址0x460030+ESI处，双字长内存的内容；

•	SET AL=0 - 改变当前线程寄存器AL的值为0；

•	SET ESI=[DWORD EDI-10] - 获得在地址EDI-10处的双字长内存的内容，并把它写到ESI中。ESI和EDI都属于CPU窗口选择的线程；

•	SET [410000]=80000001 - 改变在0x410000处双字长内存内容为0x80000001。注意：不像在反汇编窗口或CPU 数据窗口，命令行插件不能为修改的内存块创建备份［backup copy］ ！

•	A 410000, XOR EAX,EAX - 改变在0x410000处命令为XOR EAX,EAX；

•	L EAX, loopstart - 在地址EAX处，设置标签名称“loopstart”；

•	BP EAX+10 - 在EAX+10处，设置无条件断点；

•	BP 410010, EAX==WM_CLOSE - 在0x410010处设置条件断点。如果EAX等于符号常量WM_CLOSE 时中断；

•	BP Kernel32.GetProcAddress - 在KERNEL32中的GetProcAddress函数设置无条件断点；

•	BPX CreateFileA - 在反汇编窗口选择的模块中，对所有CreateFileA函数的调用设置断点。


AboutTransOD
关于 OllyDbg 汉化

汉化 OllyDbg 的想法早在去年就有了，可是面对这十余万的专业英文，做下来真的不容易。

最早的一份 OllyDbg 汉化帮助出现的今年年初，是由 babyfox 独自翻译完成的，但那份文档可读性有些差，于是准备重新翻译。

TT小组的成立使得此汉化工作完成实现成为可能。经过大家的努力，终于将此文档翻译完成。文档中保留了大量的中英文对照，以方便使用 OllyDbg 英文版的用户对照。虽然我们尽了最大努力避免翻译出错，但由于是水平有限，肯定有许多错误之处，希望大家发现了问题，请及时通知我们（邮件：TranslationTeam [AT] 126.Com，或论坛：http://bbs.pediy.com/index.php）我们会不断修正这份汉化文档的。

感谢 Oleh Yuschuk 为我们开发了一个如此好用的调试器。

感谢看雪为我们提供如此有技术含量的技术网站

希望 OllyDbg 能在中国有更多的用户！

祝中国软件越走越好！

                                                           TT小组［Translation Team］

                                                           二〇〇四年十二月

曾经参与 OllyDbg 文档翻译工作的人员（按字母顺序）：

babyfox （是他第一次尝试翻译完全部OllyDbg）

cyclotron[TT]

fly

kuangtudazuo[TT]

kvllz

onlyu[TT]

rigley[TT]

Roba[TT]

SwordLea[TT]

zdd[TT]

ZMWorm[TT]

相关信息：关于 TT 小组


Translation Team
关于 TT 小组

命令名称：TT小组［Translation Team］

成立时间：2004年08月12日

活动地点：http://bbs.pediy.com/index.php

当前的外文资料浩如烟海，而一个人面对如此多的外文资料只能望洋兴叹，由此萌发了这个想法：发挥集体的力量，有组织的翻译经典的计算机外文文档。希望能对国内整体技术水平的提高，做一点点的贡献。

成员的权利：

1、优先得到最先的翻译文档，获取最新的翻译进度。

2、提出需要翻译的项目。

2、对翻译错误的地方，有权修改。

3、交流翻译的心得经验。

4、翻译结束后，您的名字会写到翻译作者中。

成员的义务：

1、在英文材料没有完全翻译完时，不得将资料发向组外人员。

2、能及时地完成组织分配给组员的翻译任务。

3、成员发布翻译时应加上[TT]后缀，如某人的ID为 ABC，则发布翻译文档时应为ABC[TT]。

……

加入条件：（暂行）

1、对计算机有某一方面，有一定的了解，比如软件调试、网络安全。

2、至少能理解一门国外语言，具有一定的翻译能力，最好曾经翻译过计算机类外文文档。

如果您符合以上条件，并对TT小组感兴趣的话，欢迎将您的一个简单介绍（最好有包括您翻译过的文献）发送至 TranslationTeam [AT] 126.Com 申请加入，邮件中最好要有您的QQ号［用于加入TT群］以及 看雪论坛（www.pediy.com）的ID号［用于将您加入内部交流论坛］。

目前成员：

cnbragon

cyclotron

huangrui

kuangtudazuo

newsearch

nig

onlyu

rigley

Roba

SwordLea

springkang

wdasheng

zdd

zmworm

相关信息：关于 OllyDbg 汉化