反汇编IDA WinDbg ╰+哭是因爲堅強的太久メ 2024-04-19 14:12 16阅读 0赞 **libdisasm** http://bastard.sourceforge.net/libdisasm.html http://code.google.com/p/libdasm/ ## 利用IDA Pro反汇编程序 ## [IDA Pro][]是一款强大的反汇编软件,特有的IDA视图和交叉引用,可以方便理解程序逻辑和快速定位代码片断,以方便修改。 [![ida-1][]][ida-1 1] IDA视图 ### 示例程序 ### 下面会通过修改示例程序的输出字符串,来讲解如何使用IDA Pro。 #include main() { int n; scanf ("%d",&n); if (n > 0) printf("a > 0"); //后面会用IDA Pro把'a'改成'n' else printf("n < 0"); } 编译后的程序下载:[demo][] ### 运行IDA Pro ### 运行IDA Pro,并使用PE文件的方式打开示例的test.exe文件。IDA Pro会新建一个工程,并开始反汇编程序。反汇编完成后,在\[IDA-View\]窗口中,可以看到程序逻辑的树形图,如下: [![ida-2][]][ida-2 1][![ida-3][]][ida-3 1] 树形图把条件分支清晰地显示出来了,**绿色线**连着的表示条件为true时执行的逻辑,而**红色线**表示条件为false时执行的逻辑。**右下角**有IDA视图的缩略图,在上面点击可以快速定位到视图的指定位置。 IDA的工具栏有几个按钮对定位代码很重要,如下图所示: [![ida-4][]][ida-4] 从左到右分别是: **Open exports window**:打开导出窗口 **Open import window**:打开导入窗口 \***Open names window**:函数和参数的命名列表 \***Open functions window**:程序调用的所有函数窗口 \***Open strings window**: 打开字符串显示窗口,会列出程序中的所有字符串,该窗口有助于你通过程序的运行输出逆向找出对应的代码片断。 ### 定位代码片断 ### 假设我们现在接到个任务,需修正程序,把输出“a > 0”修正为“n > 0”。示例程序比较简单,直接看IDA视图我们就能找到需修改的代码片断,但实际处理时,可能程序有几m大,通过一个个看IDA视图已没法有效找到相关的执行代码片断,这时怎么办? 使用字符串窗口和IDA强大的交叉引用! 点击工具栏的\[Open strings windows\]按钮,可以看到如下的程序字符串: [![ida-5][]][ida-5] 程序的字符串较少,可以很快地看到我们需要的字符串“a > 0”在数据段**00403003**位置。假如字符串多到已不能肉眼定位查找,因为字符串窗口是没有查找功能的,这时需要借助其他的文本编辑器,如notepad,editplus等。在字符串窗口内右键,选择菜单\[copy\]命令,会把字符串窗口的所有内容复制到剪贴板,再粘贴到记事本中查找就可以了。 **双击**字符串窗口的该行字符串,会跳转到IDA视图的**00403003位置,如下图所示:** [![ida-6][]][ida-6] 该位置的字符串后面会注释有DATA XREF的字样,这是程序中引用到该字符串的代码片断的地址!在该行上右键,选择\[Jump to cross reference...\]项,会立即跳转到引用该字符串的代码片断位置! [![ida-7][]][ida-7] [![ida-8][]][ida-8] 最后定位的代码片断 上图显示的汇编指令即是我们要找的代码片断,这时点击\[Hex View-A\]窗口,会切换到二进制浏览模式,并高亮了汇编代码的二进制格式指令,如下图所示: [![ida-9][]][ida-9] 已找到需修改的代码片断,剩下的只需把a改成n。 ### 修改程序文件 ### 在IDA中,可以在\[Hex View-A\]窗口右键选择\[Edit\]来修改二进制指令。修改后通过右键选择\[Commit Change\]可以看到修改后的IDA视图。但需要注意的是,这种方式的修改并不会更新原始程序文件,实际只是修改了IDA的项目文件!IDA中只适合做一些验证性的修改,确保正确后再使用其他工具修改原始程序文件。 在IDA中验证修改正确后,可以使用UltraEdit或Hex Workshop来修改原始程序文件。下面会以UltraEdit为例来说明如何修改。 [![ida-10][]][ida-10 1] 用UltraEdit直接打开程序文件,UltraEdit会以16进制模式显示程序文件。**UltraEdit显示的地址和IDA显示的地址是不同的**,为了找到对应代码片断在UltraEdit中的实际地址,需要使用到UltraEdit的查找功能。在IDA中复制需修改的16进制模式显示的指令,在UltraEdit中打开查找,粘贴并查找该16进制字符串,UltrEdit会很快定位到该指令处,如下图所示: [![ida-11][]][ida-11] 在IDA中使得右键来复制 [![ida-12][]][ida-12] 在UltraEdit打开查找功能 [![ida-13][]][ida-13] 找到了UltraEdit的对应位置 现在我们要把“a > 0”改成“n > 0”,a对应的ASCII码是61,而n对应的ASCII码是6E,只需把61改成6E就可以了,修改后保存。 [![ida-14][]][ida-14] 再次运行,可以看到结果已改变! [![ida-15][]][ida-15] 示例只是修改了字符串,只需更改数据段内容就可以了,不用更改指令。假如需要更改指令,需要参考[8086][]指令操作表写出对应指今的16进制形式,再修改。 ### 参考资料: [http://blog.csdn.net/liquanhai/article/details/5479141][http_blog.csdn.net_liquanhai_article_details_5479141] [http://www.youtube.com/watch?v=Gl2S0YPRb9s][http_www.youtube.com_watch_v_Gl2S0YPRb9s] [http://www.woodmann.com/crackz/Tutorials/Flores1.htm][http_www.woodmann.com_crackz_Tutorials_Flores1.htm] [http://courses.engr.illinois.edu/ece390/resources/opcodes.html\#Main][8086] ### [http://faydoc.tripod.com/cpu/conventions.htm][http_faydoc.tripod.com_cpu_conventions.htm] 边写变学IDA [http://hi.baidu.com/onepc/blog/item/bb217259aa539a212834f0f1.html][http_hi.baidu.com_onepc_blog_item_bb217259aa539a212834f0f1.html] 源码 <table> <tbody> <tr> <td> <div> <p><br><br><span style="color:#ff0000;">发觉若是没源码看着来还真的不知是啥意思。</span><br><br> PAGE:0001048E MyUnload proc near ; DATA XREF: DriverEntry+9 o<br> PAGE:0001048E ;<span style="color:#ff0000;">不过这个IDA怎么参数都没有显示?不是很明白。明明写有参数的。<br></span>PAGE:0001048E var_8 = dword ptr -8<br> PAGE:0001048E var_4 = dword ptr -4<br> PAGE:0001048E arg_0 = dword ptr 8<br> PAGE:0001048E<br> PAGE:0001048E push ebp<br> PAGE:0001048F mov ebp, esp<br> PAGE:00010491 sub esp, 8<br> PAGE:00010494 mov eax, [ebp+arg_0] ;<span style="color:#ff0000;">ebp+8刚好是在参数1的位置。</span>PAGE:00010497 mov ecx, [eax+4] ;<span style="color:#ff0000;">参数1偏移4的值传给ecx ;不能动态调试只能猜了。<br> lkd> dt _DRIVER_OBJECT<br> nt!_DRIVER_OBJECT<br> +0x000 Type : Int2B<br> +0x002 Size : Int2B<br> +0x004 DeviceObject : Ptr32 _DEVICE_OBJECT ;eax+4这里刚好是驱动对象里存放设备地址的地方<br></span>PAGE:0001049A mov [ebp+var_4], ecx <span style="color:#ff0000;">;传给变量1</span> <span style="color:#ff0000;">ebp-4<br></span><span style="color:#ff0000;">;这句 pDeviceObject=pDriverObject->DeviceObject; 变量1是设备对象指针。下面[变量1=pDeviceObject]表示</span><br> PAGE:0001049D<br> PAGE:0001049D loc_1049D: ; CODE XREF: MyUnload+40 j<br> PAGE:0001049D cmp [ebp+var_4], 0 ;<span style="color:#ff0000;">变量与0比较<br></span>PAGE:000104A1 jz short loc_104D0 ;<span style="color:#0000ff;">即是退出<br></span><span style="color:#0000ff;"><span style="color:#0000ff;">等于0时跳</span><br> push offset Format ; "Driver Exit!\n"<br> PAGE:000104D5 call _DbgPrint<br> PAGE:000104DA add esp, 4<br> PAGE:000104DD mov esp, ebp<br> PAGE:000104DF pop ebp<br> PAGE:000104E0 retn 4<br> PAGE:000104E0 MyUnload endp</span><br><br> PAGE:000104A3 mov edx, [ebp+var_4];<span style="color:#ff0000;">pDeviceObject的地址传给edx,</span>PAGE:000104A6 mov eax, [edx+28h];<span style="color:#ff0000;">地址偏移28h地方正是扩展设备存放地方的地方。</span><br><span style="color:#ff0000;">lkd> dt _DEVICE_OBJECT<br> nt!_DEVICE_OBJECT<br> +0x000 Type : Int2B<br> +0x002 Size : Uint2B<br> +0x004 ReferenceCount : Int4B<br> +0x008 DriverObject : Ptr32 _DRIVER_OBJECT<br> +0x00c NextDevice : Ptr32 _DEVICE_OBJECT<br> +0x010 AttachedDevice : Ptr32 _DEVICE_OBJECT<br> +0x014 CurrentIrp : Ptr32 _IRP<br> +0x018 Timer : Ptr32 _IO_TIMER<br> +0x01c Flags : Uint4B<br> +0x020 Characteristics : Uint4B<br> +0x024 Vpb : Ptr32 _VPB<br> +0x028 DeviceExtension : Ptr32 Void</span><br> PAGE:000104A9 mov [ebp+var_8], eax <br> ;<span style="color:#ff0000;">扩展设备地址传给变量8,即是pDeviceS=(PDevice_Save)pDeviceObject->DeviceExtension;这句代码<br> ;这里的(PDevice_Save)地址转换在汇编里直接透明。<br></span>PAGE:000104AC mov ecx, [ebp+var_8]<br> PAGE:000104AF add ecx, 0Ch<br><span style="color:#ff0000;">typedef struct _Device_Save <br> { <br> PDEVICE_OBJECT pDeviceSave; 4位<br> UNICODE_STRING uDeviceNameSave;8位<br> UNICODE_STRING uSysmbolicLinkNameSave;<br> }Device_Save,*PDevice_Save;<br></span><span style="color:#ff0000;">add ecx, 0Ch结构地址加上0ch这里正好是指向</span><span style="color:#ff0000;">uSysmbolicLinkNameSave地址</span><br> PAGE:000104B2 push ecx ; SymbolicLinkName <br> PAGE:000104B3 call ds:__imp__IoDeleteSymbolicLink@4 ; IoDeleteSymbolicLink(x)<br> PAGE:000104B9 mov edx, [ebp+var_4];<span style="color:#ff0000;">pDeviceObject地址<br></span>PAGE:000104BC mov eax, [edx+0Ch];<span style="color:#ff0000;"> +0x00c NextDevice : Ptr32 _DEVICE_OBJECT<br></span>PAGE:000104BF mov [ebp+var_4], eax;<span style="color:#ff0000;">就是说把下一个设备地址传给变量1<br></span>PAGE:000104C2 mov ecx, [ebp+var_8] ;<span style="color:#ff0000;">这个是扩展设备地址</span><br> PAGE:000104C5 mov edx, [ecx] ;<span style="color:#ff0000;">也是在扩展设备第一个结构成员的地址,即DeviceObject</span> <br> PAGE:000104C7 push edx ; DeviceObject <br> PAGE:000104C8 call ds:__imp__IoDeleteDevice@4 ; IoDeleteDevice(x)<br> PAGE:000104CE jmp short loc_1049D ;<br><span style="color:#ff0000;">无条件回跳GE:0001049D cmp [ebp+var_4], 0到这里。所以可以看出这是一个死循环,若是没有jz 这个语句的话,所以可以看出这是一个while(x){......} x为真是循环。</span><br> PAGE:000104D0 ; ---------------------------------------------------------------------------<br> PAGE:000104D0<br> PAGE:000104D0 loc_104D0: ; CODE XREF: MyUnload+13 j<br> PAGE:000104D0 push offset Format ; "Driver Exit!\n"<br> PAGE:000104D5 call _DbgPrint<br> PAGE:000104DA add esp, 4<br> PAGE:000104DD mov esp, ebp<br> PAGE:000104DF pop ebp<br> PAGE:000104E0 retn 4<br> PAGE:000104E0 MyUnload endp<br><br><span style="color:#274e13;">\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\</span><span style="color:#274e13;">偶的分割线</span><span style="color:#274e13;">\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\</span></p> <p><span style="color:#000000;">GE:000105D0 AllIrpComplete proc near ; DATA XREF: DriverEntry+2E o<br> PAGE:000105D0<br> PAGE:000105D0 var_4 = dword ptr -4 ;第一个变量<br> PAGE:000105D0 arg_4 = dword ptr 0Ch ;第二个参数<br> PAGE:000105D0<br> PAGE:000105D0 push ebp<br> PAGE:000105D1 mov ebp, esp<br> PAGE:000105D3 push ecx<br> PAGE:000105D4 mov [ebp+var_4], 0 ;第一个变量设值为0<br> PAGE:000105DB mov eax, [ebp+arg_4] ;第二个参数传的值传给eax [这里是pIrp的地址]<br> PAGE:000105DE mov ecx, [ebp+var_4]<br> PAGE:000105E1 mov [eax+18h], ecx<br><span style="color:#ff0000;">lkd> dt _IRP<br> nt!_IRP<br> +0x000 Type : Int2B<br> +0x002 Size : Uint2B<br> +0x004 MdlAddress : Ptr32 _MDL<br> +0x008 Flags : Uint4B<br> +0x00c AssociatedIrp : __unnamed<br> +0x010 ThreadListEntry : _LIST_ENTRY<br> +0x018 IoStatus : _IO_STATUS_BLOCK<br></span><span style="color:#ff00ff;">lkd> dt _IO_STATUS_BLOCK<br> nt!_IO_STATUS_BLOCK<br> +0x000 Status : Int4B<br> +0x000 Pointer : Ptr32 Void<br> +0x004 Information : Uint4B<br></span><span style="color:#ff0000;">把IRP的状态设为0即是成功的状态</span><br> PAGE:000105E4 mov edx, [ebp+arg_4]<br> PAGE:000105E7 mov dword ptr [edx+1Ch], 0<br><span style="color:#0000ff;">lkd> dt _IRP -r1<br> nt!_IRP<br> +0x000 Type : Int2B<br> +0x002 Size : Uint2B<br> +0x004 MdlAddress : Ptr32 _MDL<br> +0x000 Next : Ptr32 _MDL<br> +0x004 Size : Int2B<br> +0x006 MdlFlags : Int2B<br> +0x008 Process : Ptr32 _EPROCESS<br> +0x00c MappedSystemVa : Ptr32 Void<br> +0x010 StartVa : Ptr32 Void<br> +0x014 ByteCount : Uint4B<br> +0x018 ByteOffset : Uint4B<br> +0x008 Flags : Uint4B<br> +0x00c AssociatedIrp : __unnamed<br> +0x000 MasterIrp : Ptr32 _IRP<br> +0x000 IrpCount : Int4B<br> +0x000 SystemBuffer : Ptr32 Void<br> +0x010 ThreadListEntry : _LIST_ENTRY<br> +0x000 Flink : Ptr32 _LIST_ENTRY<br> +0x004 Blink : Ptr32 _LIST_ENTRY<br> +0x018 IoStatus : _IO_STATUS_BLOCK<br> +0x000 Status : Int4B<br> +0x000 Pointer : Ptr32 Void<br> +0x004 Information : Uint4B ;这里正是1ch的地方 18h+4h=1ch</span><br> PAGE:000105EE xor dl, dl<br> PAGE:000105F0 mov ecx, [ebp+arg_4]<br> PAGE:000105F3 call ds:__imp_@IofCompleteRequest<a href="http://my.oschina.net/u/147515" rel="nofollow">@8</a> ; IofCompleteRequest(x,x)<br> PAGE:000105F9 mov eax, [ebp+var_4] ;<span style="color:#ff0000;">return 0;<br></span>PAGE:000105FC mov esp, ebp<br> PAGE:000105FE pop ebp<br> PAGE:000105FF retn 8<br> PAGE:000105FF AllIrpComplete endp</span></p> </div> </td> </tr> </tbody> </table> PAGE:00010503 ; Attributes: bp-based frame PAGE:00010503 PAGE:00010503 ConExeToSys proc near ; DATA XREF: DriverEntry+3B o PAGE:00010503 PAGE:00010503 var\_28 = dword ptr -28h ;8 PAGE:00010503 var\_24 = dword ptr -24h ;7 PAGE:00010503 SourceString = dword ptr -20h ;6 PAGE:00010503 var\_1C = dword ptr -1Ch ;5 PAGE:00010503 UnicodeString = UNICODE\_STRING ptr -18h ;变量4=>这里可以看出占8字节变量 PAGE:00010503 DestinationString= STRING ptr -10h ;变量3=>同上 PAGE:00010503 var\_8 = dword ptr -8 ;变量2 PAGE:00010503 var\_4 = dword ptr -4 ;变量1 PAGE:00010503 arg\_4 = dword ptr 0Ch ;参数 PAGE:00010503 这个是主要的分发例程,看变量有N个。 PAGE:00010503 push ebp PAGE:00010504 mov ebp, esp PAGE:00010506 sub esp, 28h ;变量所需的空间 PAGE:00010509 mov \[ebp+var\_24\], 0 ;这个是NTSTATUS变量 PAGE:00010510 mov eax, \[ebp+arg\_4\] ;IRP地址 PAGE:00010513 mov ecx, \[eax+60h\] ; \+0x040 Tail : \_\_unnamed +0x000 Overlay : \_\_unnamed +0x000 DeviceQueueEntry : \_KDEVICE\_QUEUE\_ENTRY +0x000 DriverContext : \[4\] Ptr32 Void +0x010 Thread : Ptr32 \_ETHREAD +0x014 AuxiliaryBuffer : Ptr32 Char +0x018 ListEntry : \_LIST\_ENTRY +0x020 CurrentStackLocation : Ptr32 \_IO\_STACK\_LOCATION 上面是dt \_IRP -r得出的信息 60h偏移处是 \_IO\_STACK\_LOCATION结构的地址 PAGE:00010516 mov \[ebp+var\_8\], ecx var\_8这个变量就是pIoStackLocation=IoGetCurrentIrpStackLocation(pIrp); PAGE:00010519 mov edx, \[ebp+var\_8\] ;IO栈的地址传给edx PAGE:0001051C mov eax, \[edx+0Ch\] 这个结构太难看了,windbg及ddk定义的结构,太多共用体之类的了。 共用体的最大存储字节是其中的元素最大的那个为准。 PAGE:0001051F mov \[ebp+var\_1C\], eax var\_1C =>uControlCode PAGE:00010522 mov ecx, \[ebp+var\_8\] PAGE:00010525 mov edx, \[ecx+8\] PAGE:00010528 mov \[ebp+var\_4\], edx ebp+var\_4=>uInBufferLength; PAGE:0001052B mov eax, \[ebp+var\_1C\] var\_1C =>uControlCode PAGE:0001052E mov \[ebp+var\_28\], eax 控制码传给var\_28变量 PAGE:00010531 cmp \[ebp+var\_28\], 222000h 用这个变量与222000h比较 \[这个即是应用层传来的控制码\] PAGE:00010538 jz short loc\_1053C 相等跳到 PAGE:0001053A jmp short loc\_10594 不相等跳 PAGE:0001053C ; --------------------------------------------------------------------------- PAGE:0001053C 相等跳到这里 PAGE:0001053C loc\_1053C: ; CODE XREF: ConExeToSys+35 j PAGE:0001053C mov ecx, \[ebp+arg\_4\] ;IRP地址 PAGE:0001053F mov edx, \[ecx+0Ch\]; \+0x00c AssociatedIrp : \_\_unnamed PAGE:00010542 mov \[ebp+SourceString\], edx +0x00c AssociatedIrp : \_\_unnamed +0x000 MasterIrp : Ptr32 \_IRP +0x000 IrpCount : Int4B +0x000 SystemBuffer : Ptr32 Void 传给sourcestring pIrp->AssociatedIrp.SystemBuffer; PAGE:00010545 mov eax, \[ebp+SourceString\] PAGE:00010548 push eax ; SourceString PAGE:00010549 lea ecx, \[ebp+DestinationString\] PAGE:0001054C push ecx ; DestinationString PAGE:0001054D call ds:\_\_imp\_\_RtlInitAnsiString[@8][8] ; RtlInitAnsiString(x,x) PAGE:00010553 push 1 ; AllocateDestinationString PAGE:00010555 lea edx, \[ebp+DestinationString\] PAGE:00010558 push edx ; SourceString PAGE:00010559 lea eax, \[ebp+UnicodeString\] PAGE:0001055C push eax ; DestinationString PAGE:0001055D call ds:\_\_imp\_\_RtlAnsiStringToUnicodeString[@12][12] ; RtlAnsiStringToUnicodeString(x,x,x) RtlAnsiStringToUnicodeString转换状态在eax中 PAGE:00010563 mov \[ebp+var\_24\], eax PAGE:00010566 cmp \[ebp+var\_24\], 0 PAGE:0001056A jge short loc\_1057B ;若大于等于则跳 =>成功 PAGE:0001056C push offset aConverUnsucces ; "conver unsuccess!\\n" PAGE:00010571 call \_DbgPrint PAGE:00010576 add esp, 4 PAGE:00010579 jmp short loc\_1059B ;这里退出 break PAGE:0001057B ; --------------------------------------------------------------------------- PAGE:0001057B PAGE:0001057B loc\_1057B: ; CODE XREF: ConExeToSys+67 j PAGE:0001057B mov ecx, \[ebp+UnicodeString.Buffer\] PAGE:0001057E push ecx PAGE:0001057F mov edx, dword ptr \[ebp+UnicodeString.Length\] PAGE:00010582 push edx PAGE:00010583 call SetReg PAGE:00010588 lea eax, \[ebp+UnicodeString\] PAGE:0001058B push eax ; UnicodeString PAGE:0001058C call ds:\_\_imp\_\_RtlFreeUnicodeString@4 ; RtlFreeUnicodeString(x) PAGE:00010592 jmp short loc\_1059B ==>break PAGE:00010594 ; --------------------------------------------------------------------------- PAGE:00010594 不相等跳到这里 PAGE:00010594 loc\_10594: ; CODE XREF: ConExeToSys+37 j PAGE:00010594 mov \[ebp+var\_24\], 0C0000232h \#define STATUS\_INVALID\_VARIANT ((NTSTATUS)0xC0000232L) PAGE:0001059B 这里是流程语句结束。\[这个各种流程若是没优化编译的话都是有一定的特征的\] PAGE:0001059B loc\_1059B: ; CODE XREF: ConExeToSys+76 j PAGE:0001059B ; ConExeToSys+8F j PAGE:0001059B mov ecx, \[ebp+arg\_4\] PAGE:0001059E mov edx, \[ebp+var\_24\] PAGE:000105A1 mov \[ecx+18h\], edx PAGE:000105A4 mov eax, \[ebp+arg\_4\] PAGE:000105A7 mov dword ptr \[eax+1Ch\], 0 PAGE:000105AE xor dl, dl PAGE:000105B0 mov ecx, \[ebp+arg\_4\] PAGE:000105B3 call ds:\_\_imp\_@IofCompleteRequest[@8][8] ; IofCompleteRequest(x,x) PAGE:000105B9 mov eax, \[ebp+var\_24\] PAGE:000105BC mov esp, ebp PAGE:000105BE pop ebp PAGE:000105BF retn 8 PAGE:000105BF ConExeToSys endp PAGE:000105BF 总结:反汇编的主要是一些变量分配及堆栈平衡及一些结构成员的赋值。多看应会慢慢熟悉。还有各种流程控制语句要多练。 PAGE:0001057B mov ecx, \[ebp+UnicodeString.Buffer\] PAGE:0001057E push ecx PAGE:0001057F mov edx, dword ptr \[ebp+UnicodeString.Length\] PAGE:00010582 push edx PAGE:00010583 call SetReg ;这里设SetReg有一个UnicodeString参数 这里可以看到,当压入一个UnicodeString字符时,会把缓冲区及长度分别压入,所以这种字符串不用以0为标志作为结尾。 SetReg proc near ; CODE XREF: ConExeToSys+80 p INIT:00010938 INIT:00010938 var\_54 = dword ptr -54h INIT:00010938 var\_50 = dword ptr -50h INIT:00010938 var\_4C = dword ptr -4Ch INIT:00010938 var\_48 = dword ptr -48h INIT:00010938 var\_44 = dword ptr -44h INIT:00010938 var\_40 = dword ptr -40h INIT:00010938 var\_3C = dword ptr -3Ch INIT:00010938 DestinationString= UNICODE\_STRING ptr -38h INIT:00010938 KeyHandle = dword ptr -30h INIT:00010938 ObjectAttributes= OBJECT\_ATTRIBUTES ptr -2Ch INIT:00010938 ValueName = UNICODE\_STRING ptr -14h INIT:00010938 Handle = dword ptr -0Ch INIT:00010938 Disposition = dword ptr -8 INIT:00010938 Data = dword ptr -4 INIT:00010938 arg\_0 = byte ptr 8 INIT:00010938 INIT:00010938 push ebp INIT:00010939 mov ebp, esp INIT:0001093B sub esp, 54h INIT:0001093E push offset aRegistryMachin ; "\\\\Registry\\\\Machine\\\\SOFTWARE\\\\Microsoft\\\\Wi"... INIT:00010943 lea eax, \[ebp+DestinationString\] INIT:00010946 push eax ; DestinationString INIT:00010947 call ds:\_\_imp\_\_RtlInitUnicodeString[@8][8] ; RtlInitUnicodeString(x,x) INIT:0001094D mov \[ebp+ObjectAttributes.Length\], 18h INIT:00010954 mov \[ebp+ObjectAttributes.RootDirectory\], 0 INIT:0001095B mov \[ebp+ObjectAttributes.Attributes\], 40h INIT:00010962 lea ecx, \[ebp+DestinationString\] INIT:00010965 mov \[ebp+ObjectAttributes.ObjectName\], ecx INIT:00010968 mov \[ebp+ObjectAttributes.SecurityDescriptor\], 0 INIT:0001096F mov \[ebp+ObjectAttributes.SecurityQualityOfService\], 0 INIT:00010976 lea edx, \[ebp+ObjectAttributes\] INIT:00010979 push edx ; ObjectAttributes INIT:0001097A push 0F003Fh ; DesiredAccess INIT:0001097F lea eax, \[ebp+KeyHandle\] INIT:00010982 push eax ; KeyHandle INIT:00010983 call ds:\_\_imp\_\_ZwOpenKey[@12][12] ; ZwOpenKey(x,x,x) INIT:00010989 mov \[ebp+var\_3C\], eax INIT:0001098C cmp \[ebp+var\_3C\], 0 INIT:00010990 jge short loc\_109A4 INIT:00010992 push offset aOpenNotSuccess ; "Open Not Success\\n" INIT:00010997 call \_DbgPrint INIT:0001099C add esp, 4 INIT:0001099F jmp loc\_10A6C INIT:000109A4 ; --------------------------------------------------------------------------- INIT:000109A4 INIT:000109A4 loc\_109A4: ; CODE XREF: SetReg+58 j INIT:000109A4 mov \[ebp+var\_54\], 18h INIT:000109AB mov ecx, \[ebp+KeyHandle\] INIT:000109AE mov \[ebp+var\_50\], ecx INIT:000109B1 mov \[ebp+var\_48\], 40h INIT:000109B8 lea edx, \[ebp+arg\_0\] INIT:000109BB mov \[ebp+var\_4C\], edx INIT:000109BE mov \[ebp+var\_44\], 0 INIT:000109C5 mov \[ebp+var\_40\], 0 INIT:000109CC lea eax, \[ebp+Disposition\] INIT:000109CF push eax ; Disposition INIT:000109D0 push 0 ; CreateOptions INIT:000109D2 push 0 ; Class INIT:000109D4 push 0 ; TitleIndex INIT:000109D6 lea ecx, \[ebp+var\_54\] INIT:000109D9 push ecx ; ObjectAttributes INIT:000109DA push 0F003Fh ; DesiredAccess INIT:000109DF lea edx, \[ebp+Handle\] INIT:000109E2 push edx ; KeyHandle INIT:000109E3 call ds:\_\_imp\_\_ZwCreateKey@28 ; ZwCreateKey(x,x,x,x,x,x,x) INIT:000109E9 mov \[ebp+var\_3C\], eax INIT:000109EC cmp \[ebp+var\_3C\], 0 INIT:000109F0 jl short loc\_10A1A INIT:000109F2 cmp \[ebp+Disposition\], 1 INIT:000109F6 jnz short loc\_10A07 INIT:000109F8 push offset aCreate ; "create\\n" INIT:000109FD call \_DbgPrint INIT:00010A02 add esp, 4 INIT:00010A05 jmp short loc\_10A1A INIT:00010A07 ; --------------------------------------------------------------------------- INIT:00010A07 INIT:00010A07 loc\_10A07: ; CODE XREF: SetReg+BE j INIT:00010A07 cmp \[ebp+Disposition\], 2 INIT:00010A0B jnz short loc\_10A1A INIT:00010A0D push offset aOpen ; "Open\\n" INIT:00010A12 call \_DbgPrint INIT:00010A17 add esp, 4 INIT:00010A1A INIT:00010A1A loc\_10A1A: ; CODE XREF: SetReg+B8 j INIT:00010A1A ; SetReg+CD j ... INIT:00010A1A push offset aDebugger ; "Debugger" INIT:00010A1F lea eax, \[ebp+ValueName\] INIT:00010A22 push eax ; DestinationString INIT:00010A23 call ds:\_\_imp\_\_RtlInitUnicodeString[@8][8] ; RtlInitUnicodeString(x,x) INIT:00010A29 mov \[ebp+Data\], offset aCWindowsNtll\_e ; "C:\\\\WINDOWS\\\\ntll.exe" INIT:00010A30 mov ecx, \[ebp+Data\] INIT:00010A33 push ecx ; wchar\_t \* INIT:00010A34 call ds:\_\_imp\_\_wcslen INIT:00010A3A add esp, 4 INIT:00010A3D lea edx, \[eax+eax+2\] INIT:00010A41 push edx ; DataSize INIT:00010A42 mov eax, \[ebp+Data\] INIT:00010A45 push eax ; Data INIT:00010A46 push 1 ; Type INIT:00010A48 push 0 ; TitleIndex INIT:00010A4A lea ecx, \[ebp+ValueName\] INIT:00010A4D push ecx ; ValueName INIT:00010A4E mov edx, \[ebp+Handle\] INIT:00010A51 push edx ; KeyHandle INIT:00010A52 call ds:\_\_imp\_\_ZwSetValueKey@24 ; ZwSetValueKey(x,x,x,x,x,x) INIT:00010A58 mov eax, \[ebp+Handle\] INIT:00010A5B push eax ; Handle INIT:00010A5C call ds:\_\_imp\_\_ZwClose@4 ; ZwClose(x) INIT:00010A62 mov ecx, \[ebp+KeyHandle\] INIT:00010A65 push ecx ; Handle INIT:00010A66 call ds:\_\_imp\_\_ZwClose@4 ; ZwClose(x) INIT:00010A6C INIT:00010A6C loc\_10A6C: ; CODE XREF: SetReg+67 j INIT:00010A6C mov esp, ebp INIT:00010A6E pop ebp INIT:00010A6F retn 8 INIT:00010A6F SetReg endp IDA反汇编工具初探 对于程序员来说,增长自己编程功力的一个好方法是阅读其它人开发的程序的源码,从而把别人的技术来消化成为自己知识,这是不是很象吸星大法? 但开源的程序毕竟是在少数,大多数程序都只会分发可执行文件及相关文件,这时我们要想查看此程序的代码,就只有把它反汇编,当然这需要一定的汇编功底,但是一个好的反汇编工具能为你阅读反汇编出来的程序提供非常大的帮助。 了解反汇编的朋友也一定知道WINDASM这个有名的反汇编工具,比如我们用WINDASM反汇编一个程序,在其程序入口点反汇编得到如下代码: //\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* Program Entry Point \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* :00401000 6A00 push 00000000 :00401002 E8FF050000 call 00401606 :00401007 A316304000 mov \[00403016\], eax :00401007 E8EF050000 call 00401600 :00401011 A30E304000 mov \[0040300E\], eax :00401016 6A0A push 0000000A :00401018 FF350E304000 push dword ptr \[0040300E\] :0040101E 6A00 push 00000000 :00401020 EF3516304000 push dword ptr \[00403016\] :00401026 E806000000 call 00401031 :0040102B 50 push eax :0040102c E8C9050000 call 004015FA 如果不联系上下文及知道这是程序入口的话,很难看出来这一段代码到底是干什么的,但IDA就不一样了,它不但会反汇编程序,并会尽量分析程序,并加上相应的注释(正因为这样,IDA反汇编一个大的程序会花非常长的时间),请看下面一段IDA反汇编出来的代码,是不是明了多了? .text:00401000 push 0 ;lpModuleName .text:00401002 call GetModuleHandleA .text:00401007 mov hInstance, eax .text:0040100C call GetCommandLineA .text:00401011 mov dword\_0\_40300E, eax .text:00401016 push 0Ah .text:00401018 push dword\_0\_40300E .text:0040101E push 0 .text:00401020 push hInstance .text:00401026 call sub\_0\_401031 .text:0040102B push eax ;uExitCode .text:0040102C call ExitProcess IDA反汇编程序后,会生成一个 .idb文件,里面保存了反汇编出来的代码及注释及IDA的一些其它相关数据,我们可以直接在IDA中写自己的分析结果和注释并保存,下次直接打开.idb文件就可以了,例如上面 .text:00401000 push 0 ;lpModuleName .text:00401002 call GetModuleHandleA .text:00401007 mov hInstance, eax 我们可以看出来实际上就是hInstance = GetModuleHandleA(nil);我们可以在后面直接加上注释,在.text:00401007这一行最后面的空白处点右键,在弹出的菜单中选择"注释",然后在弹出的窗口中填上"取得当前模块实例句柄",这一行就会变为 .text:00401007 mov hInstance, eax ;取得当前模块实例句柄 这样就为我们的反汇编出的代码增加了可读性. IDA不但可以在当前代码中加注释,还可以更改其默认的符号名,比如 .text:00401011 mov dword\_0\_40300E, eax 其中的dwrd\_0\_40300E可以看出来是存放取得的命令行的缓冲区指针(可以双击符号名,函数名跳到其定义处),在dword\_0\_40300E上面点右键,选取"重命名",然后在弹出的窗口中填入lpCommandline,点确定,这样程序中所有使用到了dword\_0\_40300E这个变量的地方都会将dword\_0\_40300E替换为lpCommandline.如下所示: .text:00401011 mov lpCommandline, eax .text:00401016 push 0Ah .text:00401018 push lpCommandline 我们再来看.text:00401026 call sub\_0\_401031这一行 可以从上面的代码看出来,这是调用的WinMain函数,在sub\_0\_401031上面点右键,选取"重命名",然这个函数命名为WinMain,这时IDA就将所有sub\_0\_401031符号变为WinMain, 并且自动加上函数定义,并会在函数调用时入栈的参数后面加上其对应的变量注释,这时我们反汇编出来的这一段代码就成了下面这个样子的了: .text:00401000 start proc near .text:00401000 push 0 ;lpModuleName .text:00401002 call GetModuleHandleA .text:00401007 mov hInstance, eax ;取得当前模块实例句柄 .text:0040100C call GetCommandLineA .text:00401011 mov lpCommandline, eax .text:00401016 push 0Ah ;nShowCmd .text:00401018 push lpCommandline ;lpCmdLine .text:0040101E push 0 ;hPrevInstance .text:00401020 push hInstance ;hInstance .text:00401026 call WinMain .text:0040102B push eax ;uExitCode .text:0040102C call ExitProcess 是不是一目了解了呢? 当我们通过阅读源码,能确定某一个子函数的作用及传入的参数类型时,我们可以双击这个函数名,跳到函数定义处,在函数定义处点右键,使用"设置函数类型"功能来编辑函数定义(C++语法),这样所有调用到这个函数的地方都会在入栈的参数后面加上其对应的变量注释. 还可以通过在函数定义处后面空白处点右键加上"可重复注释",这样所有调用此函数的地方都会在后面加上这个重复的注释. 如果想查看某个变量或函数被调用的情况,可以通过在函数或变量名上点右键,点击"查看操作数交叉索引处"功能,就可以在打开的窗口中查看到所有调用其的代码,并可通过双击跳到这段代码处.这是一个很有用的功能,能帮助你快速的搞清函数及变量的调用关系. 按下F12还可以查看到程序的流程图,CTRL+12可以查看到函数的调用图. IDA还拥有符号调试技术,能识别常见编释器编释的程序,例如下面反汇编出的VC6.0的程序代码段: .text:00405427 push edx .text:00405428 call \_swscanf .text:0040542D lea eax, \[esp+38h+arg\_40\] .text:00405431 push offset unk\_0\_5DB1A4 ;const wchar\_t \* .text:00405436 push eax ;const wchar\_t \* .text:00405437 call \_wcscmp .text:0040543C add esp, 1Ch .text:0040543F test eax, eax .text:00405441 jz short loc\_0\_405459 .text:00405443 lea ecx, \[esp+24h+arg\_40\] .text:00405447 push offset unk\_0\_5DB18C ;const wchar\_t \* .text:0040544C push ecx ;const wchar\_t \* .text:0040544D call \_wcscmp 就检查到了其调用了MFC类库中的函数,并把它们替换成了相应的函数名. 还可以调用IDA导出.MAP文件,来配合其它动态调试工具如SOFT-ICE来进行代码分析. IDA是一个非常强大的反汇编工具,这里只是讨论了一下它的一些基本的应用,希望能起到抛砖引玉的作用 [汇编语言里 eax, ebx, ecx, edx, esi, edi, ebp, esp这些都是什么意思啊?][http_blog.csdn.net_liquanhai_article_details_5479141] eax, ebx, ecx, edx, esi, edi, ebp, esp等都是X86 汇编语言中CPU上的通用寄存器的名称,是32位的寄存器。如果用C语言来解释,可以把这些寄存器当作变量看待。 比方说: add eax,-2 ; //可以认为是给变量eax加上-2这样的一个值。 这些32位寄存器有多种用途,但每一个都有“专长”,有各自的特别之处。 EAX 是"累加器"(accumulator), 它是很多加法乘法指令的缺省寄存器。 EBX 是"基地址"(base)寄存器, 在内存寻址时存放基地址。 ECX 是计数器(counter), 是重复(REP)前缀指令和LOOP指令的内定计数器。 EDX 则总是被用来放整数除法产生的余数。 ESI/EDI 分别叫做"源/目标索引寄存器"(source/destination index),因为在很多字符串操作指令中, DS:ESI指向源串,而ES:EDI指向目标串. EBP 是"基址指针"(BASE POINTER), 它最经常被用作高级语言函数调用的"框架指针"(frame pointer). 在破解的时候,经常可以看见一个标准的函数起始代码: push ebp ; 保存当前ebp mov ebp,esp ; EBP设为当前堆栈指针 sub esp, xxx ; 预留xxx字节给函数临时变量. ... 这样一来,EBP 构成了该函数的一个框架, 在EBP上方分别是原来的EBP, 返回地址和参数. EBP下方则是临时变量. 函数返回时作 mov esp,ebp/pop ebp/ret 即可. ESP 专门用作堆栈指针,被形象地称为栈顶指针,堆栈的顶部是地址小的区域,压入堆栈的数据越多,ESP也就越来越小。在32位平台上,ESP每次减少4字节。 **[Win dbg入门][Win dbg](PPT)** View more [PowerPoint][] # [Intel Pentium Instruction Set Reference (Conventions)][http_faydoc.tripod.com_cpu_conventions.htm] # ## ## [80x86 Opcodes][] Instructions and opcodes **oo : Function ** * 00 : If mmm = 110, then a displacement follows the operation; otherwise, no displacement is used * 01 : An 8-bit signed displacement follows the opcode * 10 : A 16-bit signed displacement follows the opcode * 11 : mmm specifies a register, instead of an addressing mode **mmm : Function ** * 000 : DS:\[BX+SI\] * 001 : DS:\[BX+DI\] * 010 : SS:\[BP+SI\] * 011 : SS:\[BP+DI\] * 100 : DS:\[SI\] * 101 : DS:\[DI\] * 110 : SS:\[BP\] * 111 : DS:\[BX\] **rrr : W=0 : W=1 : reg32 ** * 000 : AL : AX : EAX * 001 : CL : CX : ECX * 010 : DL : DX : EDX * 011 : BL : BX : EBX * 100 : AH : SP : ESP * 101 : CH : BP : EBP * 110 : DH : SI : ESI * 111 : BH : DI : EDI **sss : Segment Register ** * 000 : ES * 001 : CS * 010 : SS * 011 : DS * 100 : FS (Only 386+) * 101 : GS (Only 386+) **rrr : Index Register** * 000 : EAX * 001 : ECX * 010 : EDX * 011 : EBX * 100 : No Index * 101 : EBP * 110 : ESI * 111 : EDI **32 bit addressing-mode ** <table> <tbody> <tr> <th>oo</th> <th>mmm</th> <th>rrr</th> <th>Description</th> </tr> <tr> <td>00</td> <td>000</td> <td> </td> <td>DS:[EAX]</td> </tr> <tr> <td>00</td> <td>001</td> <td> </td> <td>DS:[ECX]</td> </tr> <tr> <td>00</td> <td>010</td> <td> </td> <td>DS:[EDX]</td> </tr> <tr> <td>00</td> <td>011</td> <td> </td> <td>DS:[EBX]</td> </tr> <tr> <td>00</td> <td>100</td> <td>000</td> <td>DS:[EAX+scaled_index]</td> </tr> <tr> <td>00</td> <td>100</td> <td>001</td> <td>DS:[ECX+scaled_index]</td> </tr> <tr> <td>00</td> <td>100</td> <td>010</td> <td>DS:[EDX+scaled_index]</td> </tr> <tr> <td>00</td> <td>100</td> <td>011</td> <td>DS:[EBX+scaled_index]</td> </tr> <tr> <td>00</td> <td>100</td> <td>100</td> <td>SS:[ESP+scaled_index]</td> </tr> <tr> <td>00</td> <td>100</td> <td>101</td> <td>DS:[disp32+scaled_index]</td> </tr> <tr> <td>00</td> <td>100</td> <td>110</td> <td>DS:[ESI+scaled_index]</td> </tr> <tr> <td>00</td> <td>100</td> <td>111</td> <td>DS:[EDI+scaled_index]</td> </tr> <tr> <td>00</td> <td>101</td> <td> </td> <td>DS:disp32</td> </tr> <tr> <td>00</td> <td>110</td> <td> </td> <td>DS:[ESI]</td> </tr> <tr> <td>00</td> <td>111</td> <td> </td> <td>DS:[EDI]</td> </tr> <tr> <td>01</td> <td>000</td> <td> </td> <td>DS:[EAX+disp8]</td> </tr> <tr> <td>01</td> <td>001</td> <td> </td> <td>DS:[ECX+disp8]</td> </tr> <tr> <td>01</td> <td>010</td> <td> </td> <td>DS:[EDX+disp8]</td> </tr> <tr> <td>01</td> <td>011</td> <td> </td> <td>DS:[EBX+disp8]</td> </tr> <tr> <td>01</td> <td>100</td> <td>000</td> <td>DS:[EAX+scaled_index+disp8]</td> </tr> <tr> <td>01</td> <td>100</td> <td>001</td> <td>DS:[ECX+scaled_index+disp8]</td> </tr> <tr> <td>01</td> <td>100</td> <td>010</td> <td>DS:[EDX+scaled_index+disp8]</td> </tr> <tr> <td>01</td> <td>100</td> <td>011</td> <td>DS:[EBX+scaled_index+disp8]</td> </tr> <tr> <td>01</td> <td>100</td> <td>100</td> <td>SS:[ESP+scaled_index+disp8]</td> </tr> <tr> <td>01</td> <td>100</td> <td>101</td> <td>SS:[EBP+scaled_index+disp8]</td> </tr> <tr> <td>01</td> <td>100</td> <td>110</td> <td>DS:[ESI+scaled_index+disp8]</td> </tr> <tr> <td>01</td> <td>100</td> <td>111</td> <td>DS:[EDI+scaled_index+disp8]</td> </tr> <tr> <td>01</td> <td>101</td> <td> </td> <td>SS:[EBP+disp8]</td> </tr> <tr> <td>01</td> <td>110</td> <td> </td> <td>DS:[ESI+disp8]</td> </tr> <tr> <td>01</td> <td>111</td> <td> </td> <td>DS:[EDI+disp8]</td> </tr> <tr> <td>10</td> <td>000</td> <td> </td> <td>DS:[EAX+disp32]</td> </tr> <tr> <td>10</td> <td>001</td> <td> </td> <td>DS:[ECX+disp32]</td> </tr> <tr> <td>10</td> <td>010</td> <td> </td> <td>DS:[EDX+disp32]</td> </tr> <tr> <td>10</td> <td>011</td> <td> </td> <td>DS:[EBX+disp32]</td> </tr> <tr> <td>10</td> <td>100</td> <td>000</td> <td>DS:[EAX+scaled_index+disp32]</td> </tr> <tr> <td>10</td> <td>100</td> <td>001</td> <td>DS:[ECX+scaled_index+disp32]</td> </tr> <tr> <td>10</td> <td>100</td> <td>010</td> <td>DS:[EDX+scaled_index+disp32]</td> </tr> <tr> <td>10</td> <td>100</td> <td>011</td> <td>DS:[EBX+scaled_index+disp32]</td> </tr> <tr> <td>10</td> <td>100</td> <td>100</td> <td>SS:[ESP+scaled_index+disp32]</td> </tr> <tr> <td>10</td> <td>100</td> <td>101</td> <td>SS:[EBP+scaled_index+disp32]</td> </tr> <tr> <td>10</td> <td>100</td> <td>110</td> <td>DS:[ESI+scaled_index+disp32]</td> </tr> <tr> <td>10</td> <td>100</td> <td>111</td> <td>DS:[EDI+scaled_index+disp32]</td> </tr> <tr> <td>10</td> <td>101</td> <td> </td> <td>SS:[EBP+disp32]</td> </tr> <tr> <td>10</td> <td>110</td> <td> </td> <td>DS:[ESI+disp32]</td> </tr> <tr> <td>10</td> <td>111</td> <td> </td> <td>DS:[EDI+disp32]</td> </tr> </tbody> </table> 详解C++代码反汇编后的堆栈寄存器EBP和ESP 最近在分析一个进程崩溃的严重问题,其中有些过程分析需要对ebp, esp 有清晰的理解,对于ebp 和esp 相信大家都很熟悉了,但是为了使本文自成体系,我还是解释一下。 ebp--栈底指针 esp--栈顶指针 ![ebpesp.jpg][] 如图所示,简化后的代码调用过程如下: void Layer02() \{ int b = 2; \} void Layer01() \{ int a = 1; Layer02(); \} 那么函数执行过程中ebp和esp是如何变化的呢?如下是反汇编后的代码: void Layer02() \{ 00413700 push ebp 00413701 mov ebp,esp 00413703 sub esp,0CCh 00413709 push ebx 0041370A push esi 0041370B push edi 0041370C lea edi,\[ebp-0CCh\] 00413712 mov ecx,33h 00413717 mov eax,0CCCCCCCCh 0041371C rep stos dword ptr es:\[edi\] int b = 2; 0041371E mov dword ptr \[b\],2 \} 00413725 pop edi 00413726 pop esi 00413727 pop ebx 00413728 mov esp,ebp 0041372A pop ebp 0041372B ret 我们看到函数调用开始执行如下的两行代码: 00413700 push ebp 00413701 mov ebp,esp 返回前执行如下代码: 00413728 mov esp,ebp 0041372A pop ebp 0041372B ret 那么这几行代码到底是什么意思呢?首先,如图上所示: 开始两行代码的意思是先将ebp1压栈,然后将现在的栈顶esp1作为函数调用时的栈底,所以会执行如下语句: 00413701 mov ebp,esp 那么,返回前的几条语句又是什么意思呢? 我想大家已经猜到了,当函数调用执行结束,我们要执行相反的过程: 00413728 mov esp,ebp 还原栈顶指针 0041372A pop ebp 还原栈底指针 0041372B ret 返回到函数调用前的指令继续执行。待续… **IDA与OD的关系** R3级调试器。不是R0级调试器。R0级调试是gdb。 IDA称为静态调试器。属于R3级别。R0级是最核心。 反汇编工具的调试时中断cpu来进行的。对于R0级的是断不下来的,无法调试的。 IDA用来列出程序的汇编指令。注释。地址之类。而IDA静态反汇编工具。唯一不能做的就是动态调试。可能是这样。 OD是个比较不错的选择。动态调试。可以很形象很容易的就找到你要找的加密算。账户密码之类的关键数据。 相比较而言。各有各的优点。虽然OD分析动态分析很优秀。但是有时候还是不能缺少IDA结合运用。而有些人觉得IDA做的比OD还要出色。但是不是同一用处的。比好比较。相比较来说。IDA制作的可能复杂一点。高级一点。但是始终不能替代OD。 转载于:https://my.oschina.net/alphajay/blog/61791 [IDA Pro]: http://www.hex-rays.com/products/ida/index.shtml [ida-1]: http://blog.ksword.me/wp-content/uploads/2012/05/ida-1-300x252.png [ida-1 1]: http://blog.ksword.me/wp-content/uploads/2012/05/ida-1.png [demo]: http://blog.ksword.me/wp-content/uploads/2012/05/test.zip [ida-2]: http://blog.ksword.me/wp-content/uploads/2012/05/ida-2-300x288.png [ida-2 1]: http://blog.ksword.me/wp-content/uploads/2012/05/ida-2.png [ida-3]: http://blog.ksword.me/wp-content/uploads/2012/05/ida-3-300x275.png [ida-3 1]: http://blog.ksword.me/wp-content/uploads/2012/05/ida-3.png [ida-4]: http://blog.ksword.me/wp-content/uploads/2012/05/ida-4.png [ida-5]: http://blog.ksword.me/wp-content/uploads/2012/05/ida-5.png [ida-6]: http://blog.ksword.me/wp-content/uploads/2012/05/ida-6.png [ida-7]: http://blog.ksword.me/wp-content/uploads/2012/05/ida-7.png [ida-8]: http://blog.ksword.me/wp-content/uploads/2012/05/ida-8.png [ida-9]: http://blog.ksword.me/wp-content/uploads/2012/05/ida-9.png [ida-10]: http://blog.ksword.me/wp-content/uploads/2012/05/ida-10-300x139.png [ida-10 1]: http://blog.ksword.me/wp-content/uploads/2012/05/ida-10.png [ida-11]: http://blog.ksword.me/wp-content/uploads/2012/05/ida-11.png [ida-12]: http://blog.ksword.me/wp-content/uploads/2012/05/ida-12.png [ida-13]: http://blog.ksword.me/wp-content/uploads/2012/05/ida-13.png [ida-14]: http://blog.ksword.me/wp-content/uploads/2012/05/ida-14.png [ida-15]: http://blog.ksword.me/wp-content/uploads/2012/05/ida-15.png [8086]: http://courses.engr.illinois.edu/ece390/resources/opcodes.html#Main [http_blog.csdn.net_liquanhai_article_details_5479141]: http://blog.csdn.net/liquanhai/article/details/5479141 [http_www.youtube.com_watch_v_Gl2S0YPRb9s]: http://www.youtube.com/watch?v=Gl2S0YPRb9s [http_www.woodmann.com_crackz_Tutorials_Flores1.htm]: http://www.woodmann.com/crackz/Tutorials/Flores1.htm [http_faydoc.tripod.com_cpu_conventions.htm]: http://faydoc.tripod.com/cpu/conventions.htm [http_hi.baidu.com_onepc_blog_item_bb217259aa539a212834f0f1.html]: http://hi.baidu.com/onepc/blog/item/bb217259aa539a212834f0f1.html [8]: http://my.oschina.net/u/147515 [12]: http://my.oschina.net/mutou4 [Win dbg]: http://www.slideshare.net/ssuserd1b21c/win-dbg [PowerPoint]: http://www.slideshare.net/thecroaker/death-by-powerpoint [80x86 Opcodes]: http://courses.engr.illinois.edu/ece390/resources/opcodes.html#Technical [ebpesp.jpg]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/18/9db31d82ef7648218d4d43993fd3eed7.jpg
还没有评论,来说两句吧...