网络安全|渗透测试入门学习,从零基础入门到精通—动态分析技术OllyDbg案例详情

目录

1、准备工作

 2、加载目标文件进行调试

 3、单步跟踪

4、设置断点

5、调试分析


 

1、准备工作


分析一个Windows程序要比分析一个DOS程序容易得多因为在Windows中只要API函数被使用了,再想对要寻找蛛丝马迹的人隐藏一些信息就比较困难了。因此,在分析一个程序时,以哪个API函数作为切人点就显得比较重要了。如果有一些编程经验,在这方面就更加得心应手了。

为了便于理解,先简单地看一下TraceMe 的序列号验证流程如图25所示。将用户名与序列号输人文本框程序调用GetDigltemTextA函数把字符读出然后进行计算,最后用lstremp函数进行比较。因此,这些调用的函数就是解密跟踪的目标,将这些函数作为断点,跟踪程序的序列号验证过程,就能找出正确的序列号。这种专门为练习解密技术制作的小程序,一般统称为“CrackMe”。

 2、加载目标文件进行调试

为了让OllyDbg中断在程序的入口点,在加载程序前必须进行相应的设置。运行OlyDbg,单击“Oplions”一“Debugging options”选项,打开调试选项配置对话框。单击“Event”标签,设置OllyDhg对中断人口点、模块加载/卸载、线程创建/结束等事件的处理方式,一般只需要将断点设置
在“WinMain”处。

设置完成后单击“File”一“Open”选项打开TraceMeexe此时0llyDbg会中断在TraceMe的第1条指令处调试器分析代码并等待用户的下一步操作。如下图所示光标停在004013AOh处004013A0h就是程序的人口点(EntryPoint)。大部分程序在启动时都会停在入口点。通过一些特殊的修改方式,有些程序可以在启动时不停在人口点,以达到反调试的目的。各部分代码的含义如下。

  • 虚拟地址:在一般情况下,同一程序的同一条指令在不同系统环境下此值相同。
  • 机器码:就是CPU执行的机器代码。
  • 汇编指令:与机器码对应的程序代码

 寄存器面板上显示了各个寄存器的当前值。寄存器有EAX、ECX、EDX、EBX、ESP、EBP、ESI、EDI和EIP等,它们统称为32位存器如下图所示。ESP为指针,指向顶在OllyDbg界面右下角的栈面板上显示了栈的值。另一个重要的寄存器是EIP,它指向当前将要执行的指令,按一下“F7”键将执行一条指令,然后 EIP将指向下一条将要执行的指令。

在调试时,可以双击这些寄存器,修改寄存器里的值。但是对EIP寄存器,不能直接修改,需要在反汇编窗口选择新的指令起始地址,例如004013AAh,在其上单击右键在弹出的快捷菜单中选择“Neworiginhere”(此处为新的EIP选项EIP的值将变成4013AAh,程序将从这条指令开始执行。寄存器下方显示的是标志寄存器,分别是C、P、A、ZS、T、D、0,它们的值只能是两个数字值-0和1,双击数字可以在0和1之间切换。

 3、单步跟踪

调试器的一个最基本的功能就是动态跟踪。0llyDbg在“Debug”菜单里控制运行的命令,各菜单项都有相应的快捷键。olyDhg的单步跟踪快捷键如下图所示。

快捷键 功能
F7 单步步进,遇到call 指令跟进
F8 单步步过,遇到call指令路过,不跟进
Ctrl+F9 直到出现rer指令时中断
Alt+F9 若进人系统领空,此命令可瞬间回到应用程序领空
F9 运行程序
F2 设置断点

“F8”键在调试中的使用很频繁,可以逐句单步执行汇编指令,遇到call 指令不会跟进,而是路过,示例如下。

 “F7”键和“F8”键的主要区别在于,若遇到callloop等指令,按“F8”键会路过,按“F7键会跟进,示例如下。

“ call00401DA0”表示调用00401DAOh处的子程序。一旦子程序调用完毕,就返回call指的下一条语句即004013FFh处。按“F7”键跟进00401DAOh处的子程序,观察的情况,会发现call指令的下一条指令的地址004013FFh作为返回地址被压人栈中如图28所示。子程序末尾是一个ret指令执行完00401DD7h处的指令,就能返回call指的下一条语004013FFh处。在进人子程序的过程中,若想回看之前单步跟踪的代码,可以按“-”(减号)键;若想让光标回到当前EIP所指向的语句,可以单击国按钮C或双击EIP寄存器。

 当要重复按“F7”键或“F8”键时OllyDbg提供了快捷键Ctl+F7”和“Ctrl+F8”直到用户按“Esc”键、“F12”键或遇到其他断点时停止。
当位于某个call指中,想返回调用这个cl 指的位置时可以按“Ctrl+F9”快捷键执行Executetillreum”(执行到返回)命令OllyDhg会停在遇到的第1个返回命处(retretf或iret).这样可以方便地略过一些没用的代码。

 例如上面的代码在00401DAO处如果按“Ctl+F9”快捷键就会返回 004013FFh 处。遇到et 指时是暂停还是路过可以在选项设置,方法是打开调试设置选项对话框,在“Trace”标签页中设置“After Execting tillRETstepover RET”(执行到ret指令后,单步路过ret指令)。
如果已经进人系统DLL提供的API函数,当要返回应用程序领空时可以按快捷键“Alt+F9”执行“Executetillusercode”(执行到用户代码)命令,示例如下。

 在004013C6h处按“F7”键就可跟进系统KERNEL32DLL了,示例如下。

“7C8114AB”等都是系统DLL所在的地址空间这时只要按快捷键“Alt+F9”就可以回到应用程序领空,代码如下。 

 注意:所谓“领空”,实际上是指在某一时刻CPU的CS:EIP 指向的某段代码的所有者。

如果不想单步跟踪,想让程序直接运行,可以按“F9”键或单击工具栏中的右进按钮。如果想重新调试目标程序,可以按“Ctrl+F2”快捷键,OllyDhg将结束被调试进程并重新加载它。如果程序进入死循环,可以按“F12”键暂停程序。

4、设置断点

断点(breakpoint)是调试器的一个重要功能可以让程序中断在指定的地方,从而方便地对其进行分析。如下图所示将光标移到004013A5h处按“F2”键即可设置一个断点再次按“F2”键可以取消断点。也可以双击“Hexdump”列中相应的行设置断点,再次双击可以取消断点。

 设置断点后,按“Alt+B”快捷键或单击B按钮,打开断点窗口,查看断点明细如下图所示。这里显示了除硬件断点外的其他断点,其中“Always”表示断点处于激活状态“Disable”表示断点停用。按空格键可切换其状态。也可以通过右键快捷菜单管理这些断点。删除断点的快捷是“Del”键。

00B2A5C8   .  E8 1BAA0000   call 路径修复.00B34FE8                       ; \路径修复.00B34FE8
00B2A5CD   .  59            pop ecx                                  ;  kernel32.777D0099
00B2A5CE   .  B8 4D5A0000   mov eax,0x5A4D
00B2A5D3   .  66:3905 0000B>cmp word ptr ds:[0xB20000],ax
00B2A5DA   .  74 04         je short 路径修复.00B2A5E0
00B2A5DC   >  33DB          xor ebx,ebx
00B2A5DE   .  EB 33         jmp short 路径修复.00B2A613
00B2A5E0   >  A1 3C00B200   mov eax,dword ptr ds:[0xB2003C]
00B2A5E5   .  81B8 0000B200>cmp dword ptr ds:[eax+0xB20000],0x4550
00B2A5EF   .^ 75 EB         jnz short 路径修复.00B2A5DC
00B2A5F1   .  B9 0B010000   mov ecx,0x10B
00B2A5F6   .  66:3988 1800B>cmp word ptr ds:[eax+0xB20018],cx
00B2A5FD   .^ 75 DD         jnz short 路径修复.00B2A5DC
00B2A5FF   .  33DB          xor ebx,ebx
00B2A601   .  83B8 7400B200>cmp dword ptr ds:[eax+0xB20074],0xE
00B2A608   .  76 09         jbe short 路径修复.00B2A613
00B2A60A   .  3998 E800B200 cmp dword ptr ds:[eax+0xB200E8],ebx
00B2A610   .  0f95c3        setne bl
00B2A613   >  895D E4       mov dword ptr ss:[ebp-0x1C],ebx
00B2A616   .  E8 067C0000   call 路径修复.00B32221
00B2A61B   .  85C0          test eax,eax
00B2A61D   .  75 08         jnz short 路径修复.00B2A627
00B2A61F   .  6A 1C         push 0x1C
00B2A621   .  E8 DC000000   call 路径修复.00B2A702
00B2A626   .  59            pop ecx                                  ;  kernel32.777D0099
00B2A627   >  E8 F4690000   call 路径修复.00B31020
00B2A62C   .  85C0          test eax,eax
00B2A62E   .  75 08         jnz short 路径修复.00B2A638
00B2A630   .  6A 10         push 0x10
00B2A632   .  E8 CB000000   call 路径修复.00B2A702
00B2A637   .  59            pop ecx                                  ;  kernel32.777D0099
00B2A638   >  E8 94AA0000   call 路径修复.00B350D1
00B2A63D   .  8365 FC 00    and dword ptr ss:[ebp-0x4],0x0
00B2A641   .  E8 EE7E0000   call 路径修复.00B32534
00B2A646   .  85C0          test eax,eax
00B2A648   .  79 08         jns short 路径修复.00B2A652
00B2A64A   .  6A 1B         push 0x1B
00B2A64C   .  E8 B1000000   call 路径修复.00B2A702
00B2A651   .  59            pop ecx                                  ;  kernel32.777D0099
00B2A652   >  FF15 3400B400 call dword ptr ds:[<&KERNEL32.GetCommand>; [GetCommandLineA
00B2A658   .  A3 C8DCB400   mov dword ptr ds:[0xB4DCC8],eax
00B2A65D   .  E8 AFAA0000   call 路径修复.00B35111
00B2A662   .  A3 4CBDB400   mov dword ptr ds:[0xB4BD4C],eax
00B2A667   .  E8 52A40000   call 路径修复.00B34ABE
00B2A66C   .  85C0          test eax,eax
00B2A66E   .  79 08         jns short 路径修复.00B2A678
00B2A670   .  6A 08         push 0x8
00B2A672   .  E8 6D820000   call 路径修复.00B328E4
00B2A677   .  59            pop ecx                                  ;  kernel32.777D0099
00B2A678   >  E8 70A60000   call 路径修复.00B34CED
00B2A67D   .  85C0          test eax,eax
00B2A67F   .  79 08         jns short 路径修复.00B2A689
00B2A681   .  6A 09         push 0x9
00B2A683   .  E8 5C820000   call 路径修复.00B328E4
00B2A688   .  59            pop ecx                                  ;  kernel32.777D0099
00B2A689   >  6A 01         push 0x1                                 ; /Arg1 = 00000001
00B2A68B   .  E8 8E820000   call 路径修复.00B3291E                       ; \路径修复.00B3291E
00B2A690   .  59            pop ecx                                  ;  kernel32.777D0099
00B2A691   .  85C0          test eax,eax
00B2A693   .  74 07         je short 路径修复.00B2A69C
00B2A695   .  50            push eax
00B2A696   .  E8 49820000   call 路径修复.00B328E4
00B2A69B   .  59            pop ecx                                  ;  kernel32.777D0099
00B2A69C   >  E8 FDAA0000   call 路径修复.00B3519E
00B2A6A1   .  56            push esi                                 ; /Arg4 = 00B2A5A8
00B2A6A2   .  50            push eax                                 ; |Arg3 = 010FFC98
00B2A6A3   .  6A 00         push 0x0                                 ; |Arg2 = 00000000
00B2A6A5   .  68 0000B200   push 路径修复.00B20000                       ; |Arg1 = 00B20000
00B2A6AA   .  E8 B1CBFFFF   call 路径修复.00B27260                       ; \路径修复.00B27260
00B2A6AF   .  8BF0          mov esi,eax
00B2A6B1   .  8975 DC       mov dword ptr ss:[ebp-0x24],esi          ;  路径修复.<ModuleEntryPoint>
00B2A6B4   .  85DB          test ebx,ebx
00B2A6B6   .  75 06         jnz short 路径修复.00B2A6BE
00B2A6B8   .  56            push esi                                 ;  路径修复.<ModuleEntryPoint>
00B2A6B9   .  E8 C9840000   call 路径修复.00B32B87
00B2A6BE   >  E8 4C820000   call 路径修复.00B3290F
00B2A6C3   .  EB 2E         jmp short 路径修复.00B2A6F3
00B2A6C5   .  8B4D EC       mov ecx,dword ptr ss:[ebp-0x14]
00B2A6C8   .  8B01          mov eax,dword ptr ds:[ecx]
00B2A6CA   .  8B00          mov eax,dword ptr ds:[eax]
00B2A6CC   .  8945 E0       mov dword ptr ss:[ebp-0x20],eax
00B2A6CF   .  51            push ecx                                 ;  路径修复.<ModuleEntryPoint>
00B2A6D0   .  50            push eax
00B2A6D1   .  E8 8DA20000   call 路径修复.00B34963
00B2A6D6   .  59            pop ecx                                  ;  kernel32.777D0099
00B2A6D7   .  59            pop ecx                                  ;  kernel32.777D0099
00B2A6D8   .  C3            retn
00B2A6D9   .  8B65 E8       mov esp,dword ptr ss:[ebp-0x18]
00B2A6DC   .  8B75 E0       mov esi,dword ptr ss:[ebp-0x20]
00B2A6DF   .  8975 DC       mov dword ptr ss:[ebp-0x24],esi          ;  路径修复.<ModuleEntryPoint>
00B2A6E2   .  837D E4 00    cmp dword ptr ss:[ebp-0x1C],0x0
00B2A6E6   .  75 06         jnz short 路径修复.00B2A6EE
00B2A6E8   .  56            push esi                                 ;  路径修复.<ModuleEntryPoint>
00B2A6E9   .  E8 B4820000   call 路径修复.00B329A2
00B2A6EE   >  E8 0D820000   call 路径修复.00B32900
00B2A6F3   >  C745 FC FEFFF>mov dword ptr ss:[ebp-0x4],-0x2
00B2A6FA   .  8BC6          mov eax,esi                              ;  路径修复.<ModuleEntryPoint>
00B2A6FC   .  E8 847C0000   call 路径修复.00B32385
00B2A701   .  C3            retn
00B2A702  /$  55            push ebp

5、调试分析

按“F8”键单步走出GetDlgllemTextA函数。当然也可以按“Alt+F9”快捷键回到调用函数的地方。OllyDbg非常强大,已经对各函数的调用参数及当前值进行了注释,相关代码如下。

 在阅读这些代码时,需要注意以下几点。

  • 要清楚各API函数的定义(查看相关API手册)
  • API函数大都采用sdcall调用约定即函数人口参数按从右到左的顺序人栈,由被调用者清理栈中的参数,返回值放在eax寄存器中。因此,对相关的API函数,要分析其前面的push 指令,这些指令将参数放人栈,以传送给API调用。在整个跟踪过程中要关注栈数据的变化。
  • C代码中的子程序采用的是C调用约定,函数人口参数按从右到左的顺序人栈,由调用者清理栈中的参数。
  • 调用约定、参数传递等知识,GetDlgItemText函数采用标准调用约定,参数按从右到左的顺序人栈。本例汇编代码如下:
00B2A728  \.  C3            retn
00B2A729      CC            int3
00B2A72A      CC            int3
00B2A72B      CC            int3
00B2A72C      CC            int3
00B2A72D      CC            int3
00B2A72E      CC            int3
00B2A72F      CC            int3
00B2A730   $  57            push edi                                 ;  路径修复.<ModuleEntryPoint>
00B2A731   .  56            push esi                                 ;  路径修复.<ModuleEntryPoint>
00B2A732   .  8B7424 10     mov esi,dword ptr ss:[esp+0x10]          ;  ntdll.77C67B6E
00B2A736   .  8B4C24 14     mov ecx,dword ptr ss:[esp+0x14]
00B2A73A   .  8B7C24 0C     mov edi,dword ptr ss:[esp+0xC]
00B2A73E   .  8BC1          mov eax,ecx                              ;  路径修复.<ModuleEntryPoint>
00B2A740   .  8BD1          mov edx,ecx                              ;  路径修复.<ModuleEntryPoint>
00B2A742   .  03C6          add eax,esi                              ;  路径修复.<ModuleEntryPoint>

猜你喜欢

转载自blog.csdn.net/qq_22903531/article/details/131390235