Oops-re's Blog.

OD学习笔记

字数统计: 1.7k阅读时长: 6 min
2021/11/27

OD的使用学习笔记

学逆向必备工具,但是,由于之前知识储备不足,使用的时候总是看不懂,但这个假期又学了新知识,再来尝试尝试这个工具。

这篇文章可能大致会分会两个部分,一部分为使用OD要用的汇编知识,一部分就是使用OD来分析一个个程序。

需要在意的是OD只能分析32位的程序。

汇编知识

1.标志位

image-20220114223402836

在逆向中,需要在意的标志位只有3个,即cmp指令能修改的那三个:Z/O/C

1
2
3
4
首先要知道cmp指令的作用:
cmp ax,bx
cmp---比较语句,相当于执行减法,但结果不对ax,bx造成影响,但会对标志寄存器中的值造成影响,
从而实现JCC跳转
1
2
3
4
5
6
Z标志位(0标志位)---
这个标志位是最常用的,运算结果为0的时候,Z标志位为1,否则为0
O标志位(溢出标志位)---
在运算的过程中,如操作数超出了机器能表示的范围则称为溢出,此时O标志位为1,否则置0
C标志位(进位标志位)---
记录运算时从最高有效位产生的进位值。例如。执行加法指令时,最高有效位进位时置1,否则置0.

2.test指令

这个指令和and指令类似,对两个操作进行按位 与 操作,但是并不会对操作数造成影响。

这个指令通常用来 test ax,ax,如果eax的值为0,则Z标志位 置1.

3.跳转指令

image-20220120162337494

4.ADC指令

带进位的加法

就是两个操作数在进行加法的时候,还要再加上CF

1
2
3
4
5
CF = 1
mov al,1
mov cl,2
adc al,cl
最后的al值为4,同时由于运算结果最高位没有进位,CF位置0

5. SBB指令

带借位的减法

就是两个操作数在进行减法的时候,还要再减去CF

1
2
3
4
5
CF = 1
mov al,4
mov cl,2
sbb al,cl
最后的al值为1,同时由于运算结果最高位没有借位,CF位置0

6. XCHG指令

数据交换指令

将两个操作数中的值进行交换,操作对象要保证宽度一致,且不能为立即数

1
2
3
4
    MOV AX,1
MOV CX,3
XCHG AX,CX
最后AX,CX中的值分别为3,1

7. MOVS指令

将数据 从 内存-内存 转移

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
常见用法:
MOVSB
MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
MOVSW
MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI]
MOVSD
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
这几个命令都是将内存DS:[ESI]指向的数据,转移到另一个内存ES:[EDI]
在执行完指令后 EDI和ESI中的值将更根据 DF位 所移动数据的宽度 进行加减
比如:
当前 DF 为 0 ,在执行了 MOVSD 后
ESI指向数据移动到了EDI
ESI+4 , EDI+4
当前 DF 为 1 ,在执行了 MOVSW 后
ESI指向数据移动到了EDI
ESI-2 , EDI-2

8. STOS指令

将 AL\AX\EAX 的值保存到 [EDI] 指定的内存单元

1
2
3
4
5
6
7
8
常见用法:
STOSB
STOS BYTE PTR ES:[EDI]
STOSW
STOS WORD PTR ES:[EDI]
STOSD
STOS DWORD PTR ES:[EDI]
在执行结束后,同MOVS指令一样,EDI会根据 DF位 和 移动数据的宽度 进行加减

9. REP指令

按计数器寄存器(EAX)中的值重复执行后面的指令

1
2
3
4
5
	MOV ECX,0X11
REP MOVSW
该段代码将执行17次MOVSW指令
每次执行ECX-1
知道ECX值为0

10.MOVZX、MOVSX

容器扩展

当需要将变量转移到更大的容器时,如:将char型数据保存到int型中,汇编层面就通过这两个指令实现

1
2
当转移的是有符号的就使用 MOVSX
当转移的是无符号的就使用 MOVZX

拓展知识:

1
2
3
4
5
6
7
当数据从大的类型容器,转移到小的类型容器时,如:int型 到 char
数据将从低位截取
int a = 12345678H;
mov dword ptr ds:[ebp-4],12345678H
char c = a;
mov ax,dword ptr ds:[ebp-4]
//执行后,ax等于00005678h

OD知识

1.显示系统异常

1.1Windows系统异常

​ SEH系统异常–在windows程序中,异常可以看作是一种消息,应用程序发生异常时就触发了该消息并告知系统,系统接收后就找到他的“回调函数”,从而进行异常事件的处理。

​ 当程序运行时,触发系统异常时,OD界面会显示

可直接使用shift+F9,继续走下一步

2.保存修改后的程序

第一步:修改

image-20220228162643539

第二步:找到地址

这里我将call命令修改成jmp命令,然后记住偏移地址0x0044426F,在内存框中找到地址,通过右键–转到–表达式,输入地址image-20220228163117661

第三步:保存

选中修改内容,右键–复制到可执行文件,OD弹出新的文本框,再右键–保存文件

这样就保存一个修改过后的文件。

3.调试VB程序

image-20220303135154372

4.OD的两种断点—硬件断点和软件断点

说是有这些个寄存器—Dr0~Dr7,他们只用于调试,我们称为调试寄存器。

其中Dr0Dr3四个寄存器用来存放中断地址,Dr4、Dr5保留不用,Dr6、Dr7用来记录Dr0Dr3的属性(如:读、写还是执行,单位是字节、字啊还是双字)。

软件断点就是在程序的在OD本程序内的断点,设置断点后并不会因为重加载而断点消失。(F12下断点)

硬件断点就是在动态链接库也就是那些**.dll**文件中下断点,因为要是通过F12在dll下断点的话,程序重加载的时候,这个断点会消失,只能通过“硬件执行”功能下断点。

4.Delphi调试特点

5.内嵌补丁

6.找到程序的入口

6.1windows控制台程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
在编写程序时,我们的程序入口就是自己编写的main函数,
然后在程序运行的时候并不是直接运行这部分main函数
main函数被调用前还要先调用一些系统函数包括:
GetVersion()--获取操作系统版本号
heap_init()--堆栈空间初始化
GetCommandLineA()--获取命令行指令
_crtGetEnvironmentStringsA()--获取环境变量
_setargv()
_setenvp()
_cinit()
这些函数都是控制台程序需要用到,在调用完这些函数后就开始调用main函数
然后由于main函数需要传入3个参数,所以就可以根据这几个特点来找到程序的入口
1.在OD的批注区看到使用到GetVersion这些系统函数后
2.注意传入3个参数的call指令
3.进入call,这就是main函数的入口
CATALOG
  1. 1. OD的使用学习笔记
    1. 1.1. 汇编知识
      1. 1.1.1. 1.标志位
      2. 1.1.2. 2.test指令
      3. 1.1.3. 3.跳转指令
      4. 1.1.4. 4.ADC指令
      5. 1.1.5. 5. SBB指令
      6. 1.1.6. 6. XCHG指令
      7. 1.1.7. 7. MOVS指令
      8. 1.1.8. 8. STOS指令
      9. 1.1.9. 9. REP指令
      10. 1.1.10. 10.MOVZX、MOVSX
    2. 1.2. OD知识
      1. 1.2.1. 1.显示系统异常
        1. 1.2.1.1. 1.1Windows系统异常
      2. 1.2.2. 2.保存修改后的程序
      3. 1.2.3. 3.调试VB程序
      4. 1.2.4. 4.OD的两种断点—硬件断点和软件断点
      5. 1.2.5. 4.Delphi调试特点
      6. 1.2.6. 5.内嵌补丁
      7. 1.2.7. 6.找到程序的入口
        1. 1.2.7.1. 6.1windows控制台程序