




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
OllyDbgCracking第一章-OD第七章- ret第十三章-硬编码序列号寻踪-第十四章-硬编码序列号寻踪-第十五章-硬编码序列号寻踪-第十六章-序列号生成算法分析-第十七章-序列号生成算法分析-第十八章-序列号生成算法分析-第十九章-OllyDbgIsDebuggerPresent20.第二十章-OllyDbg反调试之检测OD进程名第二十一章-OllyDbgOD第二十二章-OllyDbgUnhandledExceptionFilterZwQueryInformationProcess23.第二十三章-OllyDbg反调试之ProcessHeapNTGlobalFlagOutputDebugStringA第二十四章-OllyDbgIAT第三十六章-IATIATYoda'sCrypterv1.339.第三十九章-何谓stolenbytes第四十章-OllyDbg的编第四十二章-ACProtectV1.09OEPStolen第四十三章-ACProtectV1.09脱壳(编写修复IAT)44.第四十四章-ACProtectV1.09脱壳(修复AntiDump)45.第四十五章-ReCryptv0.80脱壳45.第四十五章补充章节-ReCryptv0.8046.第四十六章-PatrickCrackMe-Part147.第四十七章-PatrickCrackMe-Part250.第五十章-再谈ReCryptv.0.80脱壳(OutputDebugString)51.第五十一章-ASProtectv2.3.04.26脱壳-Part153.第五十三章-TPPpack 脱壳54.第五十四章-EXECryptorv2.2.50.a脱壳-Part156.第五十六章-EXECryptorv2.2.50.b脱壳57.第五十七章-EXECryptorv2.2.50.c.d.e.f.g58.第五十八章-EXECryptorv2.2.50第⼀章-OD(《使用OllyDbg从零开始Cracking》 的目的是为那些想精通Cracking(译注1)艺术的人提供必要的基础知识。有了这些基础 写这个想法的产生,是由于了《INTRODUCCIÓNALCRACKING中的很多对于新手来说太过于复杂。而新手们还未《INTRODUCCIÓNALCRACKING中的(它里面的数量已逾500),而是为学完这个课程后的读者打下一个良好的基础,以便去学习阅读日益复杂的资料。它的主要目的是减少课程数量,提供必要的基础知识,从而使新的Cracker对更复章资为什么使⽤SoGICE和OllyDbgSoGICEOllyDbg。而OllyDbg拥有的资料且更容易学习。我们需要从OllyDbg这扇大门进入Cracking的世界。以后可能会在必要的时候换成其它调试器,但变化的只是它们的使用方法,不变的是它们的本质。首先,需要装备我们以后将主要使用的工具(OllyDbg),点此(译注3)成功后,将其解压到你容易的硬盘文件夹内,一个好的办法是在C盘创建一个 尽管它在哪里都可以运行,在这里我选择了C:/。它的可执行文件是OLLYDBG.exe好的,启动软件,点击OllyDbg上图的消息框显示,PSAPI.DLL,一个库文件旧于我们系统上的同名DLL文件。如果你点击Yes,那么这个旧文件就会从你的文件夹内,然后使用系统自身的。尽管我看不出两个文件有什么不同,但是最好选择随软件包自带的,所以要点击No(译注这是纯净的OllyDbg(译注:未加载插件非修),为了逐渐熟悉OllyDbg,我们打开的第一个程序来自著名的CrueHead'aCrackMeOllyDbgFileOpen随后打开一个窗口,找到CrackMeCrackMeOllyDbg心的只是是如何将它打开。之后,当学习下一节课程时,当说到Dump,至少你应该知道到哪里去找这个选项。这里,我们看一下OllyDbgOllyDbg在这里显示反汇编代码,要以OllyDbg的默认配置调试分析你打开的程序。调试选项可以在Options->Debuggingoptions里更改。如果勾选了自动对主模块进行分析(译注5),OllyDbg这是CrackMe在分析结果中,出现了大量的信息,尽管我们现在还不清楚这些信息是什么,但看起来很有趣。同时,最好要知道,如果分析的不够正确或有错误,这些消息可以在任何时候去除。lyDbg显示程序的某些部分时是不正确的,错误的将可执行代码解释为数据。然后,它会显示类似于下图中的内容。 ysis->Removeysisfrommodule手动删除分析结果umps和calls,你使用它可能会更为方便但我个人不喜欢(这会有不同的体验),择pearane>Highligting->Jps’nCalls。这里,我们看到Call句变为绿色,跳转变为黄色。现在,反汇编窗口更加容易阅读。虽然到现在为止,我们头脑里对这些是什么意思还没有概看一下这个在OllyDbg还有一些重要的信息我们没有看到。但是你可以设置显示模式的不同类型。,ViewFPUregisters显示FPU寄存器,View3DNow!registers显示3DNow!寄存器。Viewdebugregisters显示调试寄存器。默认是第一个。ESPEBP寄存器指向地址的信ESP寄存器指向的信息(也是最重要的),但是你可以改变它的显示模式来显示来自涉及EBP的信息。这需要在这个窗口上点击右键,选择GOtoEBP。再次点击右键选择GotoESP,回到先前窗口。在后续课程中,我将更加详细的解释堆栈的功能。但目前,我们还只能通过修改配置选项看数据窗⼝这个窗口有很多显示模式,可以在该出口选择你需要的,默认模式为8-byteHex/ASCII默认的模式是最常用的,我们还可以改变它以显示反汇编代码(Disassemble),文本(Text)和其它格式(Short,Long,Float)另外,选择Special->PEHeader,会在下节课程中看到,非常有用现在我们了解了OllyDbg的最主要的四个窗口。还有一些窗口没有直接显示,可以通过菜单或控制面板上的图标按钮。(CrackMe)的信息和它加载的库文件。LogtofileEView>Executables显示程序运行使用的模块:exe,,dll,,ocxM按钮或View->Memory显示我们的程序映射到内存的信息,一个内存块可能被分为几个部分。可以搜索不同种类的字符串,可以在上设置中断T按钮或View->ThreadsW按钮或View->WindowsH按钮或View->HandlesCView->CPUOllyDbg的主窗口,CPU/View->Patches,如果程序经过了修改,这里显示修改的信息,现在我们的程序还没K按钮或View->Callstack显示调用堆栈的窗口信息,可以尝试反向函数的调用顺序B按钮或View->BreakpointsRView->ReferenceOllyDbg“...”按钮或View->Runtrace显示RUNTRACE(RUN)命令的结果。这里我们也可以通过Logtofile保存输出结果到文件JITJUSTINTIME当然,我们不一定会用的实时调试,除非特殊情况。因为如果我们运行的程序出现时,我们不需要使用OllyDbg(默认为Dr.Watson)。OllyDbgOptionsJust-in-timedebuggingMakeOllyDbgjust-in-timedebuggerdoneRestoreoldjust-in-timedebuggerDone在OllyDbgOllyDbgCommandBar点击这里(译注:随文附带)插件。首先,你需要为插件建立文件夹,我将把它建立在C:\,名为PLUGINS当然,此文件夹可以放在任何位置,但我喜欢将它放在C盘,我们现在马上配置OllyDbg,使OllyDbg将此文件夹认可为所有插 要这样做,选择Options->Appearance然后在窗口中选择Directories我们看到作为插件路径 已被指定,即OllyDbg.exe所在 ,可以把插件放在那里,但是我喜欢将它们分开,点Pluginpath->BrowsePLUGINS出现上图,说明你需要重启OllyDbg,它会认可新的插件文件 ,但是首先你需要拷贝刚的插件所有文档到PLUGINS现在CommandBar插件包里的所有文件都被到PLUGINS文件夹内(通常不需要所有文件,只需DLL文件即可)OllyDbgPluginsCommandBar和它CommandBarOllyDbg这是一个供输入命令的文本框,在很多情况下对我们很有用。以后,我们会看到它的用法。学习怎样关联插件这一部很重要。PLUGINSdllOllyDbg。然而,最好总是保持CommandBar被启用。OllyDbgCrackMeOllyDbgF7执行一行代码,遇到CALL等子程序时会进入其中,进入后首先会停留在子程序的第一条F8CALL等子程序不进入其代码。F2F2我们想在确定位置40101A用鼠标单击此行,就会像图中所示,此行被标记为灰色,然后按F2F2则删除断点。F9运行调试程序,直到遇到断点停止运行。当程序运行时,在OllyDbg的右下角(译注6)会显示单词Running通过运行CrackMeF12DebugPauseOllyDbgPausedF9Debug->Run。选择DEBUG->CLOSE就可以关闭调试程序。以上就是lyDbg总的概貌,其它深入的设置,在探讨后续章节时会有所涉及。译注1крэкнингаCracking代替。:西班牙文,强大的Cracking,这个系列程目前已有1200请从,:译者注4在这里,本人建议使用系统自带的文件。译注5:该选项在Debuggingoptions的ysis1中,AutoStartysisofmainmodule这个位置显示当前状态,通常我们习惯将其设置在左上角,可以在Options->Appearance,General下勾选Showstatusintoolbar。1.OllyDbg1.10,本文使用原版,请从官网,:CrackMe:ollydbg01-插件该系列目前已更新到第47章。本文原文为俄语,译者不才,斗胆翻译,采用了能用的所有。虽经本人严加审校,但难免讹误。有些词句加入了译者的理解,所以可能部分内容与原文有所出入。翻译本文也是译者学习的过程,所以错误在所难免。如发现错误,敬请指正,以免误人。该系列 :[C]РикардоНарваха,пер.Aquila译 (OllyDbg0110个字符(从0到9),0到F(0-9,A,B,C,D,EF16个字符)通常,除非另有说明,当我们提及某一具体数字时都将其认作十六进制。我们不使用将数值从一种数制转换为其它数制的令人不太愉快的数学。当前,Cracker们一般使用Windows自带的计算器,它将更加快捷和容易使用,以避免繁冗的工作。ViewHex,八进制Oct,二进制Bin。8Cracking中不太常用,但如果需要,也可在计算器中选择使用。55555537ABC,D,E,,F时,我们可以从键盘输入这些信息。我认为这种方法在实践中更有用途,允许我们不费力的将数字从一种数制转换到另一种数制。考虑到这个问题后,我希望所有的问题将会逐渐变的如果到FFFFFFFF所有可能的十六进制数都写出来,我们怎样表示负数?正数 到7FFFFFFF,负数 到正0仍然是十进制中的7FFFFFFF为十进制 负FFFFFFFF和十进制-1等同于十进制的 (也是最小负数CommandBar7FFFFFFF在右边,我们看到它返回了十进制 现在,我们想看 的值是否为负,我们看到它不能显示(译注1)7FFFFFFF之后的值(这是CommandBar的一bug),OllyDbgEAX选择EAX的值,这个窗口也可以完成不同的转换功能。第一栏填入我们这里,我们看到十六进 转换为了十进制 FFFFFFFF为十进制-1CancelASCII在以下截图中,看到的这种数据将是我们学习的内容之一。每个字符都被赋予了十六进制值。这允许它们视为字符组合,这张表拷贝自(嘿嘿)«Теорииассемблера»(CaosReptante),你可以看到十进制值,相应的十六OllyDbg20Hex32Dec)。CommandBar45E45,会发现它确实就是大写字母E的十六进制值。ASCIIASCII它是内存的一块区域,用于短暂数据,这些数据稍后不久就要恢复取出。就像在桌上放一叠信件或纸牌,的信件或纸牌这是堆栈的主要性质,放在顶部的信件总会被最先取走。以后学习OllyDbg的堆栈怎样工作。好的,我认为这次的课程应该结束了。在第三章,学习寄存器,标志以及它们的意义。译注2CrackMe1.CrackMe:ollydbg01-该系列目前已更新到第47章。本文原文为俄语,译者不才,斗胆翻译,采用了能用的所有。虽经本人严加审校,但难免讹误。有些词句加入了译者的理解,所以部分内容可能与原文有所出入。翻译本文也是译者学习的过程,所以错误在所难该系列本文原文本文原 :[C]РикардоНарваха,пер.译
存器的一个例子(1)ESPCrueHead'aCrackMe(2)ESP12FFC4OllyDbg–CrackMe401000如果你按下F7现在为住OllyDbg在哪里显示这些寄存器。它们都被称为32位寄存器。在OllyDbg中,它们的内容以十六进制显示。例如,EAX的最小值为 ,最大值为FFFFFFFF,用二进制表示将是320132位的。你可以在汇编语言中查阅参考这些32位寄存器。现在,在OllyDbgOllyDbgCrackMe(也可以加载其它的程序)EAX在打开的窗口的Hexdecimal处填 OK现在EAX变为了我们的期望值,OllyDbg将变化的值用红色显示EAX寄存器的一部分,在这个例子中,AXEAX16,我们在?AX(问号也可用于查询寄存器的值5678,AXEAX4ALAH(译注:16AX的低八位和高八位),它们的值在OllyDbg中同样能够观察到。或者这样更直观,如果EAX ,那么AX就是它的后四位数字AH56的组合,AL同样的,EBXBX,BLBH。几乎所有其它寄存器都可以如此分割(3)我们已经看到了,OllyDbgEAX你想要更改的,然后它选择Modify。但EIP是唯一一个例外的,它指向下一条将要执行的指令。EIP40101ANeworiginhere(汉化版翻译为:此处为新的EIP),EIP就会改变为40101A,这样,程序就将会从这条指令执行。在这里你会看到,EIP40101A就像我们在第一章看到的,在OllyDbgC,P,A,Z,S,T,DO01。某一具体指令的执行可以O标志(溢出标志溢出标志在当操作改变了符号位,返回错误值时被设置(4)OllyDbgCrueHead'aEAX7FFFFFFF现在使其加1,其和将超过最大正数,我们还知道, 对应的是一个负数。这需要打开一个能够写入指令的框(译注: 指令上按空格键,或在反汇编代码那一列的指令上双击)。 ADDEAX,1EAX1EAXF7将完成这条指令,O在F7后,看看发生了什么,EAX变 O标志被设置为1。A标志(辅助进位标志P标志(奇偶标志如果指令的结果用二进制表示,该二进制数中的的1的总个数为偶数时,P标志被设置。例如 为做个试验,我们已经在OllyDbg中设置了指令:ADDEAX,1(译注5),再一次执行该操作。选择401000行,选NeworginhereF7现在,EAX中包含的值为 ,P标志等于1,(这里是先前指令的结果),让我们看一下,当向EAX中加入1时发生了我们看到,P0,EAX11再次返回,选择ADDEAX,1这行,该行,选择Neworiginhere,按F7,再次加1。我们看到,EAX1210,1的个数为奇数,P于以下事实:当指令结果的二进制格式含有偶数个1时,被设置。Z标志(零标志Cracking0下F7运行指令ADDEAX,1使,结果为-1+1,等于0,零F7后,EAX00,Z1现在应该清楚了,当指令的结果为0S标志(符号标志1EAXFFFFFFF8-F7执行指令,S1SC(无符号运算的结果)在超过最大数值时设置,可能是寄存器的值,例如,将EAXFFFFFFFF1T,D我现在还不打算解释它们的用途,这是一个相对复杂的话题。我们对它们也不太感。所以目前可以先着手相对更简单问题,此如果看完本文后,你还存有疑惑,请用指令ADDEAX,1跟随本文的操作(以改变标志位的值)译注1寄存器是CPU内部的高速单元,速度比常规内存快很多。译注2此CrackMe译注3EAX,EBX,ECX,EDX16位寄存器,但不能进一步再分。译注4标志被设置,意思是说使其等于1,被清除,则使其等于0。译注5更改寄存器EAX 处改为ADDEAX,1CrackMe:ollydbg01-该系列目前已更新到第47章。本文原文为俄语,译者不才,斗胆翻译,采用了能用的所有。虽经本人严加审校, 如发现错误,敬请指正,以免误人。该系列:http本文原文: :[C]РикардоНарваха,пер.Aquila译 运行这条指令不会对寄存器,内存以及堆栈造成任何影响,英文单词的意思是”无操作”,也就是说,它没有特殊的用途。例如,你用一个短指令来替换一个长指令的话,如果处理器没有错误多余的空间将会被NOP填充。我们可以看到反汇编的源代码,如上图第一条指令是 0,占两个字节,在这条指令上面单击鼠标右键选择.或者直接使用快捷键-空格键,在弹出窗口的编辑框中输入NOP写入NOP指令后单击Assembe现在,在原来PUSH0的地方显示的两条NOP指令,单击F7,指令一条NOP指令,可以看到,这里只改变了E保存了下一条要执行指令的地址)寄存器的值,并没有影响到其他寄存器,堆栈或者标志位。在数据窗口中,鼠标右键选择-“Goto”-“”,,在数据窗口或者反汇编窗口中, 在数据窗口中的话,我们之前,堆栈就像一个信箱一样,越顶部的信越先被取出来H按下F7,堆栈顶部我们可以看到加入了0。下面的12FFC4中仍然是7C816D4F,PUSHEAX的话,那么堆栈的顶部将保存EAXPUSH]注意,PUSH(没有方括号如果你使用的“PUSH8”那么堆栈中将被放置401008执行以后,我们可以看到下面的结果如果换成是“PUSH”存元中的个候们去据窗中看的是少。o:这节是CA204000。按F7执行这条PUSH执行堆栈中我们可以看到在数据窗口中颠倒过来的值,即,现在我们知道,O中 [410]”的意思了]像这样的,除非有明确规定,否则OD都是认为你要操作的是4个字节的内存,也就是DWORDP以下是执行此操作,堆栈变化情况的说明ESP中存放的是F我们可以看到,原来堆栈顶部的值了,现在ESP为12FFC8同样地,如果用户是“POPECX”,那么上面的值将会到ECX我们这里就研究了入栈和出栈指令。PUSHAD指令把所有通用寄存器的内容按一定顺序压入到堆栈中PSHA也就相当于H,HH DPUSHBPSHSUSHEPUSH,PUSHE按下F7键,看看现在堆栈的情况看到所有寄存器的值都被压入堆栈了。12FFC4存放的是之前堆栈顶部的值,然后上面就是PSHAXC存放的是ECX的内容,接下来是EDX寄存器的内容,该指令与PUSHAD正好相反,它从堆栈中取值,并将它们放到相应的寄存器中。POPAD等价于“POPEPOPPOPEPOP PPPP:因为之前执行了PUSA,:PUSHA等价于H,,,,,, ,D'。POPA等价于'p,,,,,,, US,PP和PSHAPPD就像姐妹一样,只不过它们在16位程序中使用,所以我们不感,OyD是一个32位程序的调试器MOVEA两个寄存器的值是不一样的,我们只是看寄存器在我的机器上EX为B为7FFD7000。这些初始值有可能与你机器上的不一样,我们只是看赋值的过程,按F7键B的值就赋值给了EAX明白了吗MOVAL,寄存器赋值给和的其他内容即的最后两位数字。也o. ,按下F7键,看看会发生什么这里是1000,是从内存中出来的。现在,如果我们想写一个值到这个地址X:然后,按F7键发生异常注意异的描述是由我们要入这内存地导致内存异常。如果移动的是4个字节使用DWORD,移动两个字节的话使用WORD。例如D].按F7赋值给AX的只有两个字节。如下,]这种情况下,只有最后一个字节赋值给AL了,即08MOVSX带符号扩展的传送指令第二个操作数可能一个寄存器也可能是内存单元,第一个操作数的位数比第二个操作数多,同时可以看到,EAX的值为0,所以这些东西总是可以帮助我们理解OD要执行的指令(我希望你已经掌握了其中的概念和寻址方式,嘿嘿)。按键。看到B中存放的是F000,并且EAX剩余部分填充为了FF因为F000是一个负的16位数字。如果BX存放1234,EAX将等 AX被赋值为了,其余部分被填充为0了-因为7FFF是正数。我们还可以把BX修改为8000(负)MOVZX带0扩展的传送指令MOVZX类似于前面的语句,但是这种情况下,剩余的部分不根据第二个操作数的正负来进行填充。我们这里不提供范例,因为和上面是相似的,剩余的部分总是被填充为0LEA取地址指令类似于MOV指令,,OD中写入以下指令:在这种情况下,有括号,但不需要获取ECX+38指向内存的值,只需要计算ECX+38的值即可。我这里EX在这个例子中LE指令就计算ECX+38的值,然后将计算的结果赋值给EAX。它表示,该操作数是12FFE8,也就是ECX+38的值,并且EAX的值为0。按键。,XCHG/该指令交换两个操作数的值,例如XCHG在我的机器上EX的值为X的值为12FFB0按F7键,你也可以使用这个指令来交换寄存器和内存单元的值,按下F7键这个例子我们在MOV指令使用过,oydbg01-按F7键,执行指令DECEAX,EAX将会由1变成0反过来,就会 ADD指令有两个操作数,相加后的结果存放到第一个操作数中。ADDEAX,1等价于INCEAXADD也将两个寄存器相加,我们可以执行该语句之前 变。因为并不会异常。在这种情况下,结果存放到405000内存单元中,按下F7键,由于我们对该内存单元没有写权限,当尝试修改该内存单元的值时候,发异在这种情况下,两个操作数的和加上进位标志的值,我们通过修改进位标志,我们可以看到十进制为-2另外也可以使用该指令来计算寄存器的值来寄存器的值,SUBEAX,SUBEAX,DWORDPTRSUBDWORDPTR这种情况下,由于我们对405000这个内存单元没有写权限,将结果存放到其中的话,会一个异常MUL结果为下面的情况MULDWORDPTR IMULECX两个数,并且保存相乘的结果,结果必须保存在寄存器中。下面看到两个和三个操作数的例子。F7EB EAXxEBX-> FFIMULEBP,DWORDPTR[ESI+74],FF800002[ESI+74]xFF800002->这是第二个例子,其中有三个操作数:ESI+74内存单元的值乘以FF800002,并且将结果到EBP中。我们可以在OD中执行看看。把IMULEBP,DWORDPTR[ESI+74],FF800002拷贝到OD中。为了确保能够ESI+74这个地址的值,ESI的值修改为401000见注释这里表示 的值 这里 是指 IMULEBP,DWORDPTR[ESI+74],在计算器中我们计算 IMULEDX,DWORDPTR[EBP- EDXx[EBP-18]->指令经常被使用。如果是一个操作数的话那么它和类似只不过操作数是有符号的结果依然保存在EDX:EX中。两个操作数的情况第一个操作数除以第二个操作数,结果存放到第一个操作数中。三个操作数的情况第二个操作数除以第三个操作数结果存放到第一个操作数中。XADD在OD中写入NEGEAX指令,并将EAX的值改为32逻辑指令有两个操作数,两操作数按位运算, 按下F7键,看到ECX的值 1or1=1or0=0or1=0or0=1xor1=0xor0=例如:not0110例如:EAX=1200,其二进制位1001000000000,其填充为32位,不足的时候补0NOT这里我们第5章就结束了,下一章介绍比较,跳转,函数调用,以及函数返回指令。附件接下来,详细介绍比较和跳转指令我们知道,某些指令的指令会影响到标志位,最常见的就是零标志位Z的例子写入CMPEAX,ECX指令并修改EAX和ECX虽然我们还没有介绍条件跳转,这里简单提一下,有两种可能性:根据标志的值来决定跳转还是不跳转。最简单的例子就是配合JZ如果有两个序列号做比较,例如EAXEC存放的是正确的序列号,该程序使用CM指令来比较,如果相零1,后面指就会跳转到成功的部分。如果不等于EC的话,那么零标志位就会置0,那么就不会跳转到成功的部分。重新写入CMPEAX,ECX指令,但是现在要求是EAX的值要大于ECX依然是CMPEAX,ECX指令,但这次是EAX小于ECX CMPAX,WORDPTR和CMPAL,BYTEPTR下面有几个例子TEST与操作的表如下1and1=1and0=我们看到,零标志位被置1了,两个0做与操作,结果为0,所以零标志位被置1如果EAX改为非零值,然后重复上面的操作呢零标志位没有被置1的话,就说明结果不等于0如果你使用计算器的话,可以计算出390AND390结果依然是390,二进制 JMPJNSJP,JPE–结果中1的个数为偶数则跳转JO–结果溢出了则跳转JNOJBJNAE–小于则跳转(无符号数)JNBE,JA–大于则跳转(无符号数)JL,JNGE–小于则跳转(有符号数)JNLE,JG–大于则跳转(有符号数)进入OPTIONS-DEBUGGING切换到CPU将3这两个条件跳转指令是等价的,只是书写的形式不同而已。我们可以看到零标志位Z被置1我们来这个条件跳转JNP或进位/借位标志位置1,当两个操作数的差值为负的时候,该标志位将被置1,这里可以得出EAX小于ECX在这种情况下进位/借位标志位置1,因为结果是负的,也就是说EAX小于ECX。(此表由于是,就不翻译了在任意一行点击鼠标右键选择-“Goto”-“Expression在弹出的框中输入401245 针对于指令D提供了一些有用的机制。如果想继续跟进子程序内部你可以按7键跟进。如果只是想先看看子程序里面的内容再决定要不要跟进的话,可以单击鼠标右键”。最后,如果我们不想继续该子程序了我们可以按下8键继续执行OD允许我们看我们感的子程序里面的内容,但是不执行,只需要在call指令上面单击鼠标右键选择“Follow”我们继续按F7键,执行push0指令,看看这个0是不是压入堆栈中并且存放到返回地址的上面了。顶存放的一般是子程序的返回地址。按F8不跟进call指令里面,直到遇到了ret指令停止PUSH401256以转移到401256地址处。这段代码和JMP401256指令的功能是一样的。出现了下面的窗口,随便填我们处于程序的代码中间,这里我们看到几个RETURNTO指令。显然,这些是我们在程序中保存的返回地址。我们现在在40124A这行按下回车键。现在来看看另外一个例子。重新载入CrackMe,按下空格键,输入一条指令:Call401245这个子程序起始于401245,到401288地址处结束(其中retn10指令跟我们熟悉ret指令略有不同,稍后详细说明)。注意嵌套调用(这个子这确实是一个返回地址,但是OD没有以红色显示RETURNTO401005。要弄明白为什么这一次OD没有以红色显示返回信息,我们回因为我们已经让OD了 ysis”- ysecode” 点+5=401000+5=401005一般情况下,在改变程序代码后了重新分析代码。有的时候,代码分析可能是错的,这个时候应该选择“ ysisfrommodule”。查看一下堆栈DEC该计数器每次递减1其实就是循环体了,最后,你需要添加一个判断计数器是否为0CMPJNEADDECX,15hTESTJNE然后继续按F7键,直到DECECX,这个时候我们的计数器的值将减少至14h继续F7单步直到TESTECX,ECX。该指令判断ECX是否为0,为0零标志位Z就置1,这样就停止循环, 地址处。下一步计数器继续递减,这一次减少见到灰色箭头,意味着什么?-这里意味着跳转不会发生。按F7键跳出循环继续执行下面的代码LOOP指令可以帮我们完成前面例子中的事情将计数器ECX的值减1,判断ECX的值是否为0,如果为0就跳转到指定的地址-将像前面指令用一条LOOP401007指令替代。第一行突出显示(401000)-单击鼠标右键选择-Neworiginhere。现在我们来执行新的LOOP按F7键,再次看到计数器ECX首先被初始化为0了,然后又被设置为15h了。我们继续单步,直到LOOP指令继续单步。当计数器为0时,循环将结束LOOPZ,LOOPE重复循环,直到零标志位Z置1LOOPNZ,LOOPNE重复循环,直到零标志位Z清0下面,数。现在我们在OD中写入MOVSDWORDPTRES:[EDI],DWORDPTRDS:[ESI]指令,样子如下:在拷贝内容之前,你可以在数据窗口中,单击鼠标右键选择-Goto-Expression,然后输入地址40366C。还有一个更加简单的方法:鼠标右键选择-FollowinDump-Immediateconstant,如下图所示 源地址现在是40365C(说明),目的地址和之前的一样,是40369C。我们来到第一条指令处,单步到REPMOVS指令处请记住,MOVS指令不能将数据拷贝到没有写入权限的内存单元中,强制写入的话会异常当循环执行REPLODS指令时,解释窗口中会提示ECX的值,以及ESI指向的内存单元中下一次将被拷贝到EAX我们单步直到执行完STOS指令,在解释窗口我们可以看到当前EAX的值以及当前EDI指向内存单元中的值我们在OD中输入CMPSDWORDPTRESI],DWORDPTREDI],OD中将显示为CMPSDWORDPTRDS:[ESI],DWORDPTR解释窗口中会提示要比较的值我们已经介绍了很多有用的指令,但是浮点运算指令我们还没有介绍,在后面讨论。大家需要重复练习前面介绍的内容,直到大家MOVDWORDPTR[ MOVAX,WORDPTR[00510A25]MOVAL,BYTEPTR[ CALL452200JMPCALLEAXJMP[EBX+要想在指令执行之前看到址,需要在该指令上下断点,断下来以后查看寄存器的值或者查看解释窗口中的提示信息这里我们来看一看间接寻址的例子:PUSHEBP 点,在执行PUSH[EBP+8]指令之前我们并不能预先直到EBP寄存器的值,我们在该指令处(4010E9)按现在让我们在数据窗口中看看EBP+8指向内存单元的值,在数据窗口中单击鼠标右键选择-Goto-Expression,输入第九章我们会将基础知识运用到中去。本章开始。我们先从基本的概念开始一步步的来介绍所需要的步骤让我们用调试器开始之旅吧通过这个CrackMe点:程序刚刚被加载第一条指令的地址。为了不和OEP(原始点)相,我们稍后再来介绍OEP的概念。当用OD加载应用程序后,调试器就会停在点处,分析代码并且等待用户的进一步提示。接下来,让我们来了解一下DLL(动态库)的概念以及DLL导出函数的功能注意一下突出显示的部分,举个例子,比如我们要调用401020或者要跳转到421367,CALL在最右边的列中显示了一些额外的信息,调用的是LoadIconA作系谓态(文正文同态出函DDLL中。如果一个功能的代码量很大,那么这样就可以缩减可执行文件的大小,更重要的是可以节省内存。Windows的基本功能:文件,内存,进程,线程,图形,声是态现。oA.l个应。口也称之为API。让我们来看看另一个APIMessageBoxA的例子。在命令栏中输入:?MessageBoxA有个简单的提示,该函数的地址是77D504EA。我们单击鼠标右键选择-Goto-Expression如果你是windows9x可以看到该函数属于USER32.DLL,通常在调试器中显示的函数名称前面会有DLL的名称(例如CallUSER32.MessageBoxA)。从当前地址开始到函数返回实现了MessageBoxA的功能。MessageBoxA便于我们的识别,但并不是机器码,给者提供了一定的帮助。按减号-回到点。单击鼠标右键:选择Searchfor-Name(label)incurrentmoduleCtrl+N菜单项。获取该CakM的PI查找我们关注的API函数的话,不需要一个个去看,只需要输入API函数的名称即可。这里我们按M光标定位到第一个函数名称以M开始的API选择FollowimportinDisassembler选项,我们就可以转到API函数的实现处。这也是另一种转到API在这里新手普遍会犯一个错误,现在单击鼠标右键选择-Sarchfor-Name(label)incurrentmodule称是RLL库中的函数名称,并不是我们的Me主程序的导入表中的函数名。菜单项中明确是搜索当前模块,我们现在这种情况,当前模块是USR3Mssgeo是位于该模块当中的。WindowsNT:2000,XP或者这里我们的讨论的是windowsNT/2000和XP,2003。对于NT系列的操作系统来说,OD是非常好用的。如果你是95/98系统的话,你也可以参考附录部分(windows9x的说明).我们在CrackMe的API列表中单击鼠标右键选择-Togglebreakpointonimport菜单项来给当前选中的函数设置断点。bpBP是在指定的函数的第一条指令处设置断点。而不是在函数的调用处。我们可以来到MessageBoxA现在我们按下F9运行CrackMe出现了CrackMe的主窗口。在菜单中选择help-随便输入一个名词和序列号,然后单击确定。这个时候MessageBoxA提示说:”中断在USER32.MessageBoxA处”,这意味着USER32.MessageBoxA消息文本是:“Noluckthere,mate!”。由于我们输入的用户名和序列号不正确。所以即将弹出失败的消息框为了证明会弹出消息框,我们在下方的RETN10处设置断点。我们对应的地址可能不一样。但是无论如何,第一个RET处就按F9消息框弹了出来。标题文本为Noluck!,文本内容为Noluckthere,mate!。表明输入的用户名或者序列号不正确。单击”是”-触发RETN10处的断点。这里RETN10跟通常的RETN有点差别。通常的RET只是返回到4013C1返回以后,返回地址从堆栈中删除。堆栈指针向下移动4字节(更确切的说是向高地址一侧)。对于RET10H来说,除了完成RET的操作之外,ESP还要增加10h。所以,ESP的增量为10h+4h=14h=20,让我们按F7键看看。单的返回,并且还会清理按照stdcall现在CrackMe已经知道了序列号不正确,我们按F9断点再次触发。CrackMe返回地址是40137D。让我们来看看该地址处的代码。单击鼠标右键选择-FollowinDisassembler或者Goto-Expression输来到了40137D处,上面是一个CALL指令,调用MessageBox(401378可以看到上面还有一个MessageBox,但是提示的是”Greatwork,mate!Nowtrythenext初步分析调试器显示的代码是函数的一部分,一个功能开始于401362弹出Noluck的消息框。另一个功能开始于40134D弹出Good如果突出显示该函数的第一行(地址401362)调试器提示调用来至于401245,单击鼠标右键选择-Goto-CALLfrom401245这里是典型的比较代码:一个分支是Noluck!,另一个分支是Greatwork同时取消MessageBox处的断点。这里我们可以单击调试器窗口中的B按钮,即显示断点窗口单击鼠标右键选择-Remove。删除两个调用MessageBox的断点,只留下401243我们F9运行起来,弹出Noluck消息框,刚才我们已经过一次了。单击确定关闭消息框,然后继续打开窗口,输入名称和序列单击OK跳转不会发生,因为EAX和EBX的值不相等。因此CALL401362弹出Noluck消息框,如果你忘记了。可以单击鼠标右键-Expression来到401362但是如果我们修改零标志位Z的值呢?将ZZ标志位为1表示EAX=EBX。即EAX与EBX按F9因此,比较是验证序列号的一个关键点。如果EAX和EBX的值相等则弹出Greatwork消息框,否则弹出Noluck消息框。我们注意到代码中有两处Noluck的消息框提示,只有一个是最后一次的提示。CrackMe当名称中包含数字的时候会提示Noluck消息框,当序列号错误的时候还会提示Noluck消息框。输入包含数字的名称。单击OKF9返回地址为4013C1OD的分析显示该子过程开始于40137E,结束于4013C1。调用MessageBox请注意,4013AC的箭头(’现在我们面对的是的比较和条件跳转指令,可以导致弹出Noluck消息框。我们在这里设置断点这里的代码会循环检测用户名的所有字母。一旦用户名中包含数字的话,就会跳转到Noluck消息框处。每检测一个字母,就会中断 JB条件跳转是根据进位标志位C来决定是否跳转的,我们通过双击C接下来我依然要来比较EAX和EBX的值,向之前一样通过修改零标志位Z按F9这次我们不改变进位标志位C,而是直接简单的把该指令填NOP。在该指令上单击鼠标右键选择-Assemble输入NOP可以将断点去掉了,只需要按下F2这里我们需要跳转始终成立,所以JE改成JMP然后还是按F2删除断点。然后按F9在反汇编窗口的任意位置单击鼠标右键选择-Copytoexecutable-Allmodifications选择Copyall弹出一个新窗口,再次单击鼠标右键选择-SaveFile这时候,我们可以关闭OD我们双击打开我们CRACKME2选择-help-Register单击OK(下面的一个点点内容是针对于windows9x系列系统的,考虑到windows9x已经淘汰很久了。连XP系统前不久都已经退役了。这里就 我们来看看断点列表刚刚设置的断点,Editcondition:给断点设置触发条件,我们后面再来讨论。Followindisassembler:Disableallorenableall:禁用/启用列表中的全部断点。这里没有启用的选项,因为列表中唯一的断点没有被禁用。CopytoClipboard:把选中断点的信息到剪贴板。我们来实验一下。Breakpoints,item0Disassembly=OREAX,EAX暂停的原因如下单击鼠标右键选择-FollowinDump-Selection我们初看一下数据窗口中的内容和反汇编代码中代码是一样的数据窗口和反汇编代码中我们看到的都是0BC0,对应的是OREAX,EAX。似乎代码没有什么变化,但是真的没有变化吗OREAX,EAX对应的机器代码出来然后写到别处在数据窗口中和提示框中显示的都是相同的内容:0BC0。但是,我们按下F7键看看EAX读出来的401018处的内容不是OD刚刚示的0BC07401(小端按双字取出来是0174C0B而现在显示的是0174CCC因此401018处字节值是CC。当我们设置断点后D会将对应指令处第一个字节指令替换成CC。但是为了不影响界面显示效果会我存中出容反方点我们设置的断点有时候莫名其妙的了不要感到奇怪,或许说这是调试器的本身的弱点吧。除BP 还有一个比BP更加强大令BPX可以给或者调用了指定API函数的指令都下断点还有一种设置断点的方法:在反汇编窗口中你想设置断点的那一行双击机器码即可。如果想删除的话,内存断点有时候也称之为BPM,但是不要与SoftIce中的BPM弄了,这二者是完全不同的 我们在4020CA处设置4个字节的内存断点。当前有指令尝试这几个字节的时候,就会中断下来 下面状态栏清楚了描述了暂停的原因异常,OD会到这个异常,并中断下来,我们看到断下来的时候,OD已经将内存页的属性设置正常了。400000h的值成功写入。我们运行起来,由于内存断点仍然存在,如果程序尝试4020CA内存单元的话,会再次触发异常正如你看到的,该指令尝试4020CA内存单元的内容,证明内存断点又触发了 “Memory,onaccess”是内存断点(读或者写),“Memory,onwrite”是内存写断点OD也可以对区段设置内存断点,我们选择菜单项View-Memory,也可以按中的[M]按钮打开内存窗口在选中部分上单击鼠标右键选择-SetMemorybreakpointonaccess下面还有Setmemorybreakpointonwrite的选项,但是这里我们选择Setmemorybreakpointonaccess因为试图执行401002处的代码,而当前代码段设置了内存断点,尝试执行当前代码段的任何一条指令都会触发内存断点我们对kernel32的代码段设置内存断点,列表的下面可以找到我们选择-Setmemorybreakpointonaccess,当试图/写入/执行Kernel32代码段的时候就会中断下来,我们运行起来在返回地址上单击鼠标右键选择-FollowinDisassembler 这里Executetillusercode起作用了,此外,如果程序会检测函数首字节是否为0xCC的话,这个时候我们使用bpMessageBoxA命令下断点就无效了,这个时候我们可以尝试第一条指令被显示下一章,介绍硬件断点和消息断点,条件断点我们会在后面介绍面把剩下的类型的断点介绍完,本章先介绍硬件断点和条件断点。硬件断点分为:硬件执行断点(ONEXECUTION),硬件写入断点(ONWRITE),硬件断点(ONACCESS)3种也可以在命令栏中输入OD中有个特殊的窗口,通过它我们可以查看和管理硬件断点。我们选择菜单栏中的Debug- breakpoints就可以打开这个窗口在401000这一行单击鼠标右键选择-Neworiginhere将EIP修改为401000,接着按F7单击Delete按钮将其删除,然后给MessageBoxAAPI注意前4接下来我们选择后面的1个字节,单击鼠标右键选择-Hardware,onaccess,可以看到只有1回到4020CA处,单击鼠标右键选择-Hardware,onaccess-Byte。我们可以看到硬件断点窗口中显示的硬件断点长度为1个字节我们来看一个例子举个例子,如果你想当前EAX等于400000的时候,程序中断下来,那么条件应该写成:“EAX400000选择超Breakpoints,紧接着选择超expression条件记录断点跟刚刚介绍的条件断点差不多区别在于我们可以通过设置该断点来记录下设置的条件的精确值。我们举个例子我们给一个函数设置条件记录断点程序中有很多地方调用了这个函数通过该条件记录断点我们可以精确的记录程序中每处调用该函数传递给它的内容。在反汇编窗口中单击鼠标右键选择-Goto-Expression转到MessageBoxA函数的这里我们只是记录下我们关心的数据,我们单击中【L】按钮打开日志窗口。我们单击鼠标右键选择-Clearwindow如果需要想将日志保存到文件的话,我们选择Logtofile 如果程序中有大约100处调用了该API函数,你可以指定相应的条件,比如说返回地址。设置条件为[ESP]40137D,那么这100个函行程序打开窗口输入用户名 好了,UnderstandingtheMessageunderstandwhythingshappenthewaytheydo.eGe
GettingASimpleGettingASimpleTheMessageUsingsandModelessStandardCreatingasimpleToolandStatusGraphicsDeviceBitmapsandDeviceContextsText,FontsandTools Appendices.SolutionstoCAPIvs..ResourcefiletheForger'sWin32APIProgramming...andsoon.Messagesareusedtocommunicateprettymucheverythinginwindowsatleastonbasiclevels. Eachwindowsmessagemayhaveuptotwoparameters, mandm.Originally mwas16bitmeachmessageusesthemdifferently.ForexampletheWM_CLOSEmessagedoesn'tuseeither,andyoushouldignorethemboth.The mcontainstwovalues,IO( )isthenotificationmessage(ifapplicable)andO( )isthecontrolor mistheHWND(windowhandle)tothecontrolwhichsentthemessageorNULLifthemessagesisn'tfromacontrol.IO)andO)aremacrosdefinedbywindowsthatsingleoutthetwohighbytes(HighWord)ofamakingDWORD(orDoubleWord)a32bitvalue.).)theMessageQueueandreturnsimmediatly.ThatmeansoncethecalltostMs)isdonethemessagemayormaynothavebeenprocessedyet.Ms)sendsthemessagedirectlytothewindowanddoesnotreturnuntillthewindowhasfinishedprocessingit.Ifwewantedtocloseawindowwecouldsendit,,,;clickingonthe mandmarebothThisisbecause,asmentioned,theyaren'tusedfor)andthenuseM,ORyoucanusetmMs)whichcombinesthesteps.Yougive))LetssayyouwerebusyhandlingtheWMITmessageandsuddenlytheusertypesabunchofstuffonmessagequeue,whenmessagesarepostedtheyareaddedtothemessagequeueandwhenyouhandle,,,{;t ;}ThemessageloopcallstMs,whichlooksinyourmessagequeue.Ifthemessagequeueisemptyyourprogrambasicallystopsandwaitsforone(itBlocks).)processed,andthatithasfilledinthemembersoftheMSGstructurewepassedit.Itreturns0ifithits,,additionalprocessing,translatingvirtualkeymessagesintocharactermessages.Thisstepisactuallyoptional,butcertainthingswon'tworkifit'snotthere.Oncethat'sdonewepassthemessagetost essage().Whatst essage()doesiswindow.Itthencallsthatprocedure,sendingasparametersthehandleofthewindow,themessage, mand.them!Ifyouaren'thandlingthespecificmessage,youalmostalwayscallfc)whichwillOnceyouhavefinishedprocessingthemessage,yourwindowsprocedurereturns,t system,ineffectyoucallityourselfindirectlybycallingst essage().Ifyouwanted,youcoulduset)onthewindowhandlethatthemessageisdestinedfortolookupthewindow'sprocedureandcallitdirectly!,,,{Wcs.,s.ms,. ,sm;}Unicode/ANSItranslation,callingtimercallbacksandsoforththatthismethodwillnotaccountfor,andveryNoticethatweuseW)toretreivethewindowprocedureassociatedwiththewindow.Whydon'twejustcallourWc)directly?WellourmessageloopisresponsibleforALLofthewindowsinoursamewindowprocedure,thefirstparameter(thehandletothewindow)isusedto whichwindowthemessageisintendedfor.))FALSE(aka0),theloopwouldendandwewouldreachtheendofourM)thusexitingtheprogram.ThisisexactlywhatsQtMs) plishes.It cesaWMQTmessageintothequeue,andinsteadofreturningapositivevalue,tMs)fillsintheMsgstructureandreturns0.Atthispoint, ignoreit,orreturnitfromM)whichwillthenbeusedastheexitcodewhentheprocessterminates.)catchyououtatsomepoint...eventhoughGMs)isdefinedasreturningaBOOL,itcanreturnT(d).ofcodethatmayseemtowork,butwillnotprocesscertianconditionscorrectly:,,,GtMsM,,,0)==sinceasIjustmentioned,itworksfineaslongasGtMs)neverfails,whichwhenyourcodeiscorrectitwon't.HoweverIfailedtotakeintoconsiderationthatifyou'rereadingthis,yourcodeprobablywon'tbecorrectalotofthetime,andGtMs)willfailatsomepoint:)I'vegonethroughand,,,Ihopeyounowhaveabetterunderstandingofthewindowsmessageloop,ifnot,donotfear,thingswillCopyright©1998-2013,Brook(tut...@).Allrights循环也会用到其他的API函数。想要深入了解Windows的消息的话,可以参考下面的中的”理解消息循环”(该的中文版见让我们来看一个简单的例子:用OD加载CrueHead`s的CrackMe在反汇编窗口中单击鼠标右键选择-Search-Name(labelincurrentmodule我们在命令栏中使用BPGetDlgItemTextA设置断点可以看到该函数有一个参数是缓冲区,所以,我们在数据窗口中定位到该缓冲区,堆栈窗口中选中该缓冲区参数,单击鼠标右键选择-FollowinDump。或者在数据窗口中单击现在缓冲区还是空的,我们通过选择主菜单项Debug-Executetillreturn现在缓冲区中保存了我们在窗口中输入的用户名我们依然选择主菜单项Debug-Executetillreturn,整个过程想必很清楚了吧为了找到正确的序列号在程序获取我们输入数据(这里是用户名和序列号的时候应该让其中断下来。更进一步的分析我们后面再讨论。我们现在再通过消息断点来提取序列号。很多有经验的程序员不使用I函数来获取编辑框中文本而是直接通过发送消息来获取编辑框中的文本。我们单击中【B】按钮删除所有的普通CC断点F9键将程序运行起来,打开窗口输入用户名和序列号,但是不要点确定单击中的【W】按钮打开Windows窗口(并不会暂停程序,依然显示的是运行)我们在找到的窗口这一行单击鼠标右键选择-MessagebreakpointonClassProc在打开的窗口中,我们展开下拉列表选择我们感的消息类型如下及Pauseprogram(中断程序),还要选中下面的LogWinProcarguments(记录消息过程函数的参数值)。我们知道主程序的代码是401000开头的这个区段,我们选中这个区段,单击鼠标右键选择-Setmemorybreakpointonaccess不要清除内存断点,我们按F9键运行,我们发现单步执行了一行,我们继续F9单步 序列号代码的附近。对不对,我们再一次定位到了我们感的代码,这一次我们并没有直接给API下断点。为了让我们确定的时候,程序能断下来,我们单击鼠标右键选择-Breakpoint-Removememorybreakpoint来删除内存断点我们单击中【B】按钮打开断点列表窗口,单击鼠标右键选择-Remove删除所有消息断点我们再次运行程序,打开窗口,但是这次我们不输入任何东西单击中的[W]按钮打开窗口列表我们选择中的【B】按钮打开断点窗口,删除所有断点。然后设置一个针对于值为0x202的WM_LBUTTONUP的消息断点接着我们窗口中的OK按钮我们单击中的[B]按钮打开断点列表。在我们设置的消息断点这一行上单击鼠标右键选择-Editcondition我们可以看到消息断点实际上也是一个条件断点,当前条件为[ESP8]0x202,即WM_LBUTTONUP。我们看看堆栈的情况我们看看栈顶择Always(总是记录),Logfunctionarguments(记录函数参数)也选择Always。单击OK,然后打开窗口输入用户名和序列号,单击OK,接着来看看日志中的消息在日志窗口中,我们可以看到首先是值为0x201的WM_LBUTTONDOWN消息,然后又是值为0x202的WM_LBUTTONUP消息。没 和窗口,然后在第一个断点上单击鼠标右键选择-Followindisassembler。然后断点这一行上单击鼠标右键选择-Conditionallog然后Pauseprogram选择Never,Logvalueofexpression选择Always,Logfunctionarguments选择Always这样,因为记录的结果可能会很多,在日志窗口中单击鼠标右键选择-Logtofile本章附件Win32API编程首先第一个最简单的CrackMe名为Leccion_13_HARDCODED_1(原名称西班牙文,英文名称译为:Lesson_13_Hardcoded_1),我们OD结果如下(MalMuyMAL:西班牙文译为:错误首先通过在反汇编窗口中单击鼠标右键选择-Searchfor-Name(labelincurrentmodule来查看API单击鼠标右键选择-Togglebreakpointonimport或者在命令栏中输入bpGetDlgItemTextA,bpMessageBoxA我们在该参数上单击鼠标右键选择-FollowinDump我们选择主菜单中项Debug-Executetillreturn这里我们可以看到比较和条件跳转指令,两个分支分别为提示MalMuyMAL(错误)的消息框和提示MuyBIEN(正确)401066地址处的指令将403010地址处的DWORD内容保存到EBX中,我们在该语句上单击鼠标右键选择-FollowinDump-Memory E,在403010开始的内存单元中是倒序存放的,(小端我们前面章节已经介绍过),这4个字节是错跳转到提示”MuyBIEN”(正确)的消息框处,如果不相等的话,就提示”MalMuyMAL”(错误)的消息框。很明显它们不相等,所以会直接提示”MalMuyMAL”(错误)的消息框。我们按F9从参数我们可以看出是提示”MalMuyMAL”(错误)。我们按F9跳转到了”MuyBIEN”(正确)的消息框处。我们按F9虽然作者忘了修改窗口的标题,但是我们还是找到了正确的序列号,我们用OD打开”Leccon13HARDCODED2”。这个例子和刚才那个例子非常的相似, ,对应字符串”9898”,所以会跳转到提示”MuyBIEN”(正确)的消息框处接下来的章节,增加难度-两个相对难一点的硬编码序列号的CrackMe。 第十四章-硬编码序列号寻踪- 函数比较重要BoxA用于显示一条消息提示是正确或者错误的序列号。我们通过在反汇编窗口中单击鼠标右键选择-Searchfor-Allreferencedtextstrings码附近。现在我们在”Youenteredtherightpassword!”字符串上面双击鼠标左键。 ”。我 我们直接运行程序, 这个CrackMe并不是序列号直接进行比较。用OD加载这个名为”crakmeeasy”的CrackMe我们在命令栏窗口中输入bpGetDlgItemTextA这里我们可以注意到Buffer参数:用于保存用户输入的序列号,我们在这个参数上单击鼠标右键选择-FollowinDump这里缓冲区是空的,因为该函数还没有执行,我们选择主菜单项-Debug-Executetillreturn我们可以看到,这里我们看到了一长串数字字符串。有些人可能会问这是正确的序列号吗?呵呵,单步一行,EAX就等于401222MOVEDX,DWORDPTRMOVEDX,DWORDPTR我们按F键 实际上就是将4现在是最后的4堆栈中的内容如下 下一条指令,EDXEAX保存了我们输入的错误序列号的首地址,EDX的初始值为零,现在创建一个循环,EAXEDX,然后EDX依次递增来获取我们输入我们知道MOVSX指令将指定字节保存到EDX中,如果该字节是正数,补零,如果该字节为负数补下一条指令是这里我们看到ECX已经被赋值为了零,然后EDXECX就指向了常量数字字符串的第一个字节,我们来看看ODCMPCMP错误的序列号的第一个字节-14常量数字字符串的第一个字节CMP25,31我们输入的是一个错误的序列号,如果输入的是一个正确的序列号的话,CMP正确序列号的第一个字节值-判断两者相等的条件为正确序列号的第一个字节值-14常量数字字符串的第一个字节正确的序列号的第一个字节值=常量数字字符串第一个字节值+正确的序列号的第一个字节值=31+第一个字节值=常量数字字符串第一个字节值+14常量数字字符串第二个字节值+14常量数字字符串第三个字节值+14我们用这个来计算序列号(正确序列号字节值=常量数字字符串对应字节值+14)的每个字符+=对应字符+=对应字符+=对应字符+=对应字符+=对应字符+=对应字符+=对应字符+=对应字符+=对应字符+=对应字符+=对应字符本章附件:第十五章-硬编码序列号寻踪- 点处我们通过在反汇编窗口中点击鼠标右键选择-Searchfor-Name(label)incurrentmodule查看API 单击鼠标右键选择-Searchfor-Allreferencedtextstrings双击鼠标左键,就可以来到了该字符串的代码处。为了找到上面的硬编码序列号,我们随便输入一个错误的序列号,然后单击CheckHardcoded是401353)。我们通过在该指令上面单击鼠标右键选择-FollowinDump-Memoryaddress来在数据窗口中定位到401353 跳转到4013D2地址处,弹出消息框提示”Sorrypleasetryagain.”。这里都为零,检列号结束删除之前设置的所有断点,然后按下CheckHardcoded弹出Congratulations,yougotthehardcodedserial 点处 让我们来看看该程序的区段的情况,我们可以选择菜单项中的View-Memory或者单击中M按钮 我们可以看到程序正在内存中各种区段,我们来分析一下代码。单击鼠标右键选择 ysecode我们可以看到”Youdidit!”-memorybreakpoint来删除之前设置的内存断点。然后弹出一个提示成功的窗口,我们修改影响跳转标志位,弹出提示序列号正确的消息框,这里的TESTCL,CL指令判断CL是否等于零,在判断之前还一个CALL指令,我们在这个CALL堆栈中我们可以看到我们刚刚输入的错误序列号,我们通过单击鼠标右键选择-FollowinDump我们可以看到一个字符串 处,我们在断在这一行上面单击鼠标选择-Breakpoint-Conditional我们设置条件为MSG202WM_LBUTTONUP并且设置中断程序方式为条件中断,我们来到主窗口,由于之前的序列号还在内存中,为了不和之前的,我们输入一个不同的序列号我们通过选择菜单项中Debug-Executetillreturn较的,我们可以看到,代码量有点大。第二种选择-就是在内存搜索一下我们输入的序列号,我们单击中的M按钮打开内存窗口我们勾选上Entireblock(这个内存块),然后按下OK我们还可以使用CTRLL来看看有没有其他内存区域有该错误序列号,我们发现当前区段中没有,其他区段中也没有找到错误序列号择-FollowinDump在数据窗口中定位到EDI指向的内存单元。当F8单步执行到下面的CALL指令处时,错误序列号拷贝完毕,我们继续在该错误序列号上面设置内存断点 本章附件:本章,我们分析的CrackMe与之前的不同之处在于序列号是基于名称
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 过河拆桥活动作文指导(场面描写和细节描写)
- 上消化道出血护理查房
- 法学专业知识题库民商法案例分析与解答参考
- 跨部门合作事务处理文书模板
- 2025年呼和浩特货运从业资格证考试试题和答案
- 食品安全及其相关法律法规标准体系s
- 三农村领导干部教育培训方案与实施细则
- 工程劳务外包协议书
- 传统制造业转型框架智能制造实践
- 化妆品生产中的膏体稳定
- 中央2025年交通运输部所属事业单位招聘261人笔试历年参考题库附带答案详解
- 中智集团所属中智国际商务发展限公司招聘高频重点提升(共500题)附带答案详解
- 2024年广东省《辅警招聘考试必刷500题》考试题库含答案
- 【9语一模】2024年蚌埠市怀远县中考一模语文试题
- 《智能制造技术基础》课件-第1章 智能制造技术概述
- 国网基建安全管理课件
- 10.1.2事件的关系和运算(教学课件)高一数学(人教A版2019必修第二册)
- 传统与现代滋补品的营销变革
- DB37T 5123-2018 预拌混凝土及砂浆企业试验室管理规范
- 陈元方年十一时课件
- 2024解析:第九章固体压强-讲核心(解析版)
评论
0/150
提交评论