作 者:
driverox
时 间: 2008-05-19,16:45
链 接: http://bbs.pediy.com/showthread.php?t=65094
最近学习逆向,对OD本身做了个逆向,也算是一个小小的锻炼吧。呵呵,在这里以分析报告的形式贴出来,请大家批评指正。谢谢。
Ollydbg(以下均简称为OD)中的Int3断点的主要功能是:在需要下断点的执行代码处将原来的代码改成0xCC,程序执行到此处后会报一个Int3异常,由OD捕获并处理。当要执行该行代码时,将原来的代码改回来并执行,然后再恢复断点,这样就不会影响程序的正常运行了。
这里仅描述最常见的功能,其它的有兴趣的话可以分析一把。
先说明一下OD中的两个结构体,在IDA中,声明为如下格式:
t_bpoint用来保存Int断点的相关信息
00000000 t_bpoint struc ; (sizeof=0x11)
00000000 addr dd ? ; // Address of breakpoint
00000004 dummy dd ? ; // Always 1
00000008 type dd ? ; // Type of breakpoint, TY_xxx
0000000C cmd db ? ; // Old value of command
0000000D passcount dd ? ; // Actual pass count
00000011 t_bpoint ends
其中:addr为断点的地址,dummy始终为1,type为断点的类型,cmd为要用0xCC替换的指令码,passcount为需要断下的次数,0表示每次都断下。
t_sorted结构体保存了一种有序的数据:
00000000 ; Descriptor of sorted table
00000000 t_sorted struc ; (sizeof=0x138)
00000000 name[MAXPATH] db 260 dup(?) ; char Name of table, as appears in error messages
00000104 n dd ? ; int Actual number of entries
00000108 nmax dd ? ; int Maximal number of entries
0000010C selected dd ? ; int Index of selected entry or -1
00000110 seladdr dd ? ; ulong Base address of selected entry
00000114 itemsize dd ? ; int Size of single entry
00000118 version dd ? ; ulong Unique version of table
0000011C data dd ? ; void* Elements, sorted by address
00000120 sortfunc dd ? ; SORTFUNC Function which sorts data or NULL
00000124 destfunc dd ? ; DESTFUNC Destructor function or NULL
00000128 sort dd ? ; int Sorting criterium (column)
0000012C sorted dd ? ; int Whether indexes are sorted
00000130 index dd ? ; int Indexes, sorted by criterium
00000134 suppresserr dd ? ; int Suppress multiple overflow errors
00000138 t_sorted ends
name是结构体的名称,用来区别不同类型的结构体
n是数组元素的个数
itemsize是数组元素的大小
data 是指向各种数据结构数组的指针,这里使用的是int3断点,所以现在保存的是int3断点数据结构体数组的指针
---------------------------------------------------------------------------------------------------------------------------------
1)Int3断点的设置
int3断点的设置是通过消息来处理的,对应右键点击菜单中的切换,其对应的消息为1E;此外还有热键F2、双击反汇编窗口等也能切换int3断点,转入的函数虽然不同,但是调用设置int3断点的函数都是同一个,就不再举例了。传入相应参数调用函数00419974,改变int3断点,该函数的调用处如下:
004237C8 . 51 push ecx ; |Arg6
004237C9 . 50 push eax ; |Arg5 => 00000002
004237CA . 6A 00 push 0 ; |Arg4 = 00000000
004237CC . 6A 00 push 0 ; |Arg3 = 00000000
004237CE . 6A 71 push 71 ; |Arg2 = 00000071
004237D0 . 52 push edx ; |Arg1 => 0040100C
004237D1 . E8 9E61FFFF call 00419974 ; /OLLYDBG.00419974
下面主要来分析上述的00419974这个函数,经过分析可知大致主要流程为:
1. 判断是否配置了“Warn when break not in code”为1,若为1的话,程序会先判断所下断点是否在代码区,不在的话,会显示警告消息,若用户选择继续,则会断下,否则退出;
2. 若没有配置上面的项目,则首先获得断点的类型(即断点类型的高位是否为2,若为2则删除断点,不为2则设置断点),检查该地址的断点是否已经存在,若存在,则删除断点,并退出;
3. 若该地址处无Int3断点,则设置断点,使用的是Setbreakpointext函数,其流程如下:
a) 获得断点在调试进程中实际地址;
b) 判断指令码是否有效(判断规则是:指令码与1F做与运算之后为3或13的时候,说明是断在指令码中间;1D、1E、1F是正常指令码,除此之外,其它的都是无法执行的指令码),无效的话,重新设置CPU窗口,显示错误提示并退出;
c) 在t_sorted结构中查找断点数据;
d) 若t_sorted中不存在该断点,则添加;
e) 判断被调试进程是否在运行状态,若在运行,则把所有的线程都挂起;
f) 读取断点所在地址的内存,若读取成功的话,调用WriteMemory写入0xCC断点(跟入WriteMemory后,发现是调用WriteProcessMemory这个API函数来下Int3断点的);
g) 恢复线程运行;
h) 显示信息在窗口中;
4. 若设置断点成功,则插入name并做其它的一些判断与显示操作,进而退出;
保存现场,提升栈帧空间,用于存放局部变量:
00419974 /$ 55 push ebp
00419975 |. 8BEC mov ebp, esp
00419977 |. 81C4 F8FBF>add esp, -408
0041997D |. 53 push ebx
0041997E |. 56 push esi
0041997F |. 57 push edi
检查OD配置文件中的 “Warn when break not in code”是否为1,1为真,0为假,若上面的配置为0,则跳到下面的处理代码中:
00419980 |. 8B7D 14 mov edi, dword ptr [ebp+14]
00419983 |. 8B5D 08 mov ebx, dword ptr [ebp+8]
00419986 |. 833D C4574>cmp dword ptr [4D57C4], 0 ; 4D57C4--Warn when break not in code
0041998D |. 74 5E je short 004199ED ;为0则跳转到下面的处理代码
检查传入的参数是否正确:
0041998F |. 83
时 间: 2008-05-19,16:45
链 接: http://bbs.pediy.com/showthread.php?t=65094
最近学习逆向,对OD本身做了个逆向,也算是一个小小的锻炼吧。呵呵,在这里以分析报告的形式贴出来,请大家批评指正。谢谢。
Ollydbg(以下均简称为OD)中的Int3断点的主要功能是:在需要下断点的执行代码处将原来的代码改成0xCC,程序执行到此处后会报一个Int3异常,由OD捕获并处理。当要执行该行代码时,将原来的代码改回来并执行,然后再恢复断点,这样就不会影响程序的正常运行了。
这里仅描述最常见的功能,其它的有兴趣的话可以分析一把。
先说明一下OD中的两个结构体,在IDA中,声明为如下格式:
t_bpoint用来保存Int断点的相关信息
00000000 t_bpoint struc ; (sizeof=0x11)
00000000 addr dd ? ; // Address of breakpoint
00000004 dummy dd ? ; // Always 1
00000008 type dd ? ; // Type of breakpoint, TY_xxx
0000000C cmd db ? ; // Old value of command
0000000D passcount dd ? ; // Actual pass count
00000011 t_bpoint ends
其中:addr为断点的地址,dummy始终为1,type为断点的类型,cmd为要用0xCC替换的指令码,passcount为需要断下的次数,0表示每次都断下。
t_sorted结构体保存了一种有序的数据:
00000000 ; Descriptor of sorted table
00000000 t_sorted struc ; (sizeof=0x138)
00000000 name[MAXPATH] db 260 dup(?) ; char Name of table, as appears in error messages
00000104 n dd ? ; int Actual number of entries
00000108 nmax dd ? ; int Maximal number of entries
0000010C selected dd ? ; int Index of selected entry or -1
00000110 seladdr dd ? ; ulong Base address of selected entry
00000114 itemsize dd ? ; int Size of single entry
00000118 version dd ? ; ulong Unique version of table
0000011C data dd ? ; void* Elements, sorted by address
00000120 sortfunc dd ? ; SORTFUNC Function which sorts data or NULL
00000124 destfunc dd ? ; DESTFUNC Destructor function or NULL
00000128 sort dd ? ; int Sorting criterium (column)
0000012C sorted dd ? ; int Whether indexes are sorted
00000130 index dd ? ; int Indexes, sorted by criterium
00000134 suppresserr dd ? ; int Suppress multiple overflow errors
00000138 t_sorted ends
name是结构体的名称,用来区别不同类型的结构体
n是数组元素的个数
itemsize是数组元素的大小
data 是指向各种数据结构数组的指针,这里使用的是int3断点,所以现在保存的是int3断点数据结构体数组的指针
---------------------------------------------------------------------------------------------------------------------------------
1)Int3断点的设置
int3断点的设置是通过消息来处理的,对应右键点击菜单中的切换,其对应的消息为1E;此外还有热键F2、双击反汇编窗口等也能切换int3断点,转入的函数虽然不同,但是调用设置int3断点的函数都是同一个,就不再举例了。传入相应参数调用函数00419974,改变int3断点,该函数的调用处如下:
004237C8 . 51 push ecx ; |Arg6
004237C9 . 50 push eax ; |Arg5 => 00000002
004237CA . 6A 00 push 0 ; |Arg4 = 00000000
004237CC . 6A 00 push 0 ; |Arg3 = 00000000
004237CE . 6A 71 push 71 ; |Arg2 = 00000071
004237D0 . 52 push edx ; |Arg1 => 0040100C
004237D1 . E8 9E61FFFF call 00419974 ; /OLLYDBG.00419974
下面主要来分析上述的00419974这个函数,经过分析可知大致主要流程为:
1. 判断是否配置了“Warn when break not in code”为1,若为1的话,程序会先判断所下断点是否在代码区,不在的话,会显示警告消息,若用户选择继续,则会断下,否则退出;
2. 若没有配置上面的项目,则首先获得断点的类型(即断点类型的高位是否为2,若为2则删除断点,不为2则设置断点),检查该地址的断点是否已经存在,若存在,则删除断点,并退出;
3. 若该地址处无Int3断点,则设置断点,使用的是Setbreakpointext函数,其流程如下:
a) 获得断点在调试进程中实际地址;
b) 判断指令码是否有效(判断规则是:指令码与1F做与运算之后为3或13的时候,说明是断在指令码中间;1D、1E、1F是正常指令码,除此之外,其它的都是无法执行的指令码),无效的话,重新设置CPU窗口,显示错误提示并退出;
c) 在t_sorted结构中查找断点数据;
d) 若t_sorted中不存在该断点,则添加;
e) 判断被调试进程是否在运行状态,若在运行,则把所有的线程都挂起;
f) 读取断点所在地址的内存,若读取成功的话,调用WriteMemory写入0xCC断点(跟入WriteMemory后,发现是调用WriteProcessMemory这个API函数来下Int3断点的);
g) 恢复线程运行;
h) 显示信息在窗口中;
4. 若设置断点成功,则插入name并做其它的一些判断与显示操作,进而退出;
保存现场,提升栈帧空间,用于存放局部变量:
00419974 /$ 55 push ebp
00419975 |. 8BEC mov ebp, esp
00419977 |. 81C4 F8FBF>add esp, -408
0041997D |. 53 push ebx
0041997E |. 56 push esi
0041997F |. 57 push edi
检查OD配置文件中的 “Warn when break not in code”是否为1,1为真,0为假,若上面的配置为0,则跳到下面的处理代码中:
00419980 |. 8B7D 14 mov edi, dword ptr [ebp+14]
00419983 |. 8B5D 08 mov ebx, dword ptr [ebp+8]
00419986 |. 833D C4574>cmp dword ptr [4D57C4], 0 ; 4D57C4--Warn when break not in code
0041998D |. 74 5E je short 004199ED ;为0则跳转到下面的处理代码
检查传入的参数是否正确:
0041998F |. 83