吾爱汇编

 找回密码
 立即注册

QQ登录

绑定QQ避免忘记帐号

查看: 3672|回复: 12

[转载技术] 第二十九章-P-CODE-Part1

[复制链接]
Shark恒 发表于 2015-1-20 16:43 | 显示全部楼层 |阅读模式

                        第二十九章-P-CODE-Part1
(本章的CrackMe需要支持库MSVBVM50.DLL)
前面章节我们已经介绍了Visual Basic逆向相关的基础知识,如果大家还想更加深入的研究VB应用程序逆向的话,可以继续学习高级篇中的关于VB逆向的相关内容。(PS:就是我打包上传到百度网盘的西班牙逆向文集系列)
COCO写的VB逆向教程就比较好,其中可能会涉及到比较复杂的处理技巧,拿来练习做好不过了。还有一些其他优秀教程可供我们更加深入的研究VB Cracking。接着下来我们将讨论下一个话题-P-CODE。
我们知道VB编写的应用程序有两种编译方式:一种是Native方式,我们前面章节已经讨论过了,两一种就是P-CODE方式-我们接下来将讨论的话题。
Native编译的代码和P-CODE的主要区别在于:Native是直接执行代码段中的代码的。而对于P-CODE,如果我们使用之前那个Patch过的OD加载它,并且给代码段设置内存访问断点的话(实际上是内存执行断点),除非是直接调用API函数,否则不会断下来。
说明,该区段没有直接可供CPU执行的代码。
P-code,实际上是一组自定义的指令集,必须通过基于堆栈的虚拟机翻译为80X86上的指令集才能执行,即通过msvbvm50.dll和msvbvm60.dll这两个动态库来解释执行。也可以理解为通过P-CODE告诉虚拟机将要进行什么操作。例如:
1e  表示 执行无条件跳转(JMP)
1e意味着执行无条件跳转,该无条件跳转是通过虚拟机(msvbvm50.dll,msvbvm60.dll)来执行的,也就是说P-CODE程序会读取代码段中的值,然后由这些值来告诉虚拟机需要执行什么操作。这也就是为什么我们说P-CODE程序的代码段中没有可执行代码的缘故。
现在就让我们一起拿起“手术刀”来跟踪,剖析一个CrackMe的P-CODE的奥秘吧。
我们实验的这个CrackMe名字叫做clave1,这个CrackMe是我朋友JB DUC写的,用来介绍P-CODE相关的内容正好合适,我们需要找到该CrackMe的正确序列号。
很多人调试P-CODE可能喜欢用WKT,如果大家想了解WKT怎么调试P-CODE的话,可以看JB DUC关于P-CODE的逆向教程,我们这里还是用OllyDbg来调试了,由于微软官方并没有提供操作码的清单,所以还会用到另外一个工具EXDEC-这个工具可以识别操作码的名称。
image002.jpg
我们使用原版的OD,配置好反反调试插件,加载该CrackMe。可以看到停在了入口点处。
说明一点,之前介绍的用于剔除Native程序的NAG窗口的4C法同样适用于P-CODE。
现在我们来看看跟Native的不同的地方:
我们从入口点往下看,会发现没有几行代码。
image004.jpg
我们只看到了大片的字节码,这里不要试图去分析这些字节码(毫无意义),我们应该还记得对于Native方式编译的VB应用程序,入口点往下还会有大量的代码吧。
image006.jpg
也有相似的字节码,我们继续往下。
image008.jpg
这里我们可以看到大段的代码,而P-CODE的程序的话OllyDbg可能也会显示处少量的代码,OD识别成了指令,但其实这些地方也是纯字节码。
我们继续来看刚刚那个P-CODE的CrackMe。
image010.jpg
另外一个特征就是MethCallEngine这个API函数,该函数我们在P-CODE方式编译的VB应用程序中都能看到,所以我们甄别一个VB应用程序是不是以P-CODE方式编译的,一般有两步:1:看代码段中入口点以下是不是大片的字节码 2:看有没有MethCallEngine这个函数。
好了,现在我们来看看字符串列表中有没有什么有价值的字符串。
image012.jpg
image014.jpg
貌似没看到什么有用的字符串。
好,那我们直接给JMPMethCallEngine这一行下一个断点吧。
image016.jpg
接下来我们选中JMP MethCallEngine这一行,单击鼠标右键选择-Follow,转入MethCallEngine内部,接着在MethCallEngine入口点处设置一个断点。
image018.jpg
image020.jpg
运行起来。
image022.jpg
弹出了注册窗口,等待我们输入序列号。对于Native的VB程序,我们可以断API函数,但是P-CODE就搞不定了,但4C法对P-CODE程序依然有用。
现在我们随便输入一个错误的序列号。
image024.jpg
我们单击Registrar(西班牙语:注册)按钮。
image026.jpg
断在了JMP MethCallEngine处,MethCallEngine函数对P-CODE进行初始化。
image028.jpg
我们继续运行,断在了MethCallEngine的入口处,我们来看看它做了些什么。
image030.jpg
我们可以看到跳转到了7413D243处。
现在我们用ExDec打开该CrackMe。ExDec是一款专门针对P-CODE的反编译器。我们来看看它显示了些什么。
image032.jpg
我们可以看到将被读取的第一个字节是04,位于401BD0地址处,应该在第一次读取代码段指令的附近,我们可以给该字节设置一个内存访问断点。
image034.jpg
我们单击Registrar按钮后就会断在了MethCallEngine处,我们给代码段设置内存访问断点。运行起来的话,将断在了读取代码段的指令处,读取401BD0内存单元中04的指令应该就在附近,所以我们接着给该字节设置内存访问断点,继续运行,就能马上定位到。
image036.jpg
我们按F9运行起来。
image038.jpg
断了下来,这个时候我们给刚刚那个04字节设置内存访问断点,运行起来,又断了下来,我们可以看到ESI指向的就是401BD0内存单元。(PS:这里下断点的顺序我换了次序,一次就可以定位到,作者10次才定位到)
image040.jpg
这里读取[ESI]的04字节值保存到AL中,这里是读取到的第一个P-CODE操作码。
接着我们来看看ExDec中显示的其他操作码。
image042.jpg
我们将ExDec跟OD的数据窗口显示的内容对应起来看,会发现这些操作码并不连续,这是因为中间夹杂着操作码需要的参数。
image044.jpg
正如你所看到的,这里正在读取第一个字节。
image046.jpg
我们可以看到当前ESI指向了401BD0,下一行,ESI值递增1,以便读取操作码的参数。
image048.jpg
接着我们就到了间接跳转JMP指令这里,这一行将去执行这个操作码(我们在ExDec中看到的04)。
image050.jpg
我们可以看到一个陌生的操作码。
image052.jpg
这里我们可以看到将执行操作码04(即FLdRfVar),就只有几行代码,也没实现什么很神奇的操作,嘿嘿。还可以看到XOREAX,EAX,然后就是读取后面操作码。
这里首先读取紧跟在04后面两个字节的参数。
image054.jpg
通过MOVSX指令将FF74(这是个负数,前面汇编章节介绍过)保存到EAX中,我们继续跟踪。
image056.jpg
EAX的值为-8C(十六进制),我们双击EAX值的话可以看到:
image058.jpg
我们可以看到FF74对应的十进制是-140也就是十六进制的-8C。我们可以看到ExDec中显示的是8C。
image060.jpg
接下来一行,操作码的参数值被加上EBP寄存器的值。
image062.jpg
接下来一行使用PUSH指令将刚刚运算的结果压入堆栈。
image064.jpg
这里相当于PUSH EBP - 8C (EBP - 8C:标识着堆栈中的局部变量),我的机器上,EBP的值为12F4E0,减去8C就得到了12F454。即当前EAX中的值。也就是使用PUSH指令压入堆栈中的值。
image066.jpg
好,我们继续往下跟。
image068.jpg
我们可以看到通过XOR EAX,EAX指令将EAX清零了,这就意味着操作码被清零了,该操作完成了,重置寄存器的值,然后接下来一行就可以读取下一个操作码了。
image070.jpg
第二个操作码是21,在接下来的一行读取它。
image072.jpg
image074.jpg
操作码跟之前一样依然被是保存在AL。
image076.jpg
现在ESI被加上3,指向当前操作码的参数,接着通过间接跳转JMP去执行操作码21。
我们来Google一下它的含义。
image078.jpg
image080.jpg
好,这里我们可以看到有些前辈做了注释,虽然我们不知道它具体是干什么用的,但是根据字面的意思来理解就是加载一个指针,并且指向一个数据项。
我们继续往下跟。
image082.jpg
这里是将EBP + 8指向内存单元的内容读取出来并保存到EBP - 4C指向的内存单元中。
这个值在我的机器上是15B000,我们在数据窗口中定位到这个地址。
image084.jpg
image086.jpg
该地址中保存的是4022E8,我们继续在数据窗口中定位到4022E8。
image088.jpg
这里我们可以推断出15B000其实是一个指针。该指针指向了一张表,虽然对我们的逆向起不到什么实质性的帮助,但起码我们还是看出一点门道了。
还有一点就是可以看出该操作码没有参数。
我们继续跟。
image090.jpg
这里EAX又被清零了,下一行读取第三个操作码。
image092.jpg
从ExDec中我们可以看出该操作码是0F。
image094.jpg
VcallAd
image096.jpg
以上是0F这个操作码具体的解释,我们可以看到它有一个占两个字节的参数。
image098.jpg
该参数我这里显示的0300,其表示句柄表中数据元素的偏移。接下来是一个间接跳转JMP,我们跟进去看看。
image100.jpg
又是读取EBP - 4C的内容,保存到EBX中。
image102.jpg
这里我们可以看到是15B000,并使用PUSH指令压入到堆栈中。
image104.jpg
接着是将参数值300保存到EAX中。
image106.jpg
这里EBX的值为15B000(我们已经知道了它指向了一张表),该表起始地址为4022E8,我们姑且将这张表称之为DescriptionItem Table。
image108.jpg
这里由该表的起始地址偏移300。
image110.jpg
表的起始地址偏移300就得到了4025E8,保存到EAX中。
image112.jpg
该值指向了表的这里。
image114.jpg
这里操作码0F就是根据参数值指明的偏移量来定位前一个操作码获取到的表中的数值。
image116.jpg
这里是使用CALL指令间接调用EAX内存单元中保存的值处。
image118.jpg
该值为7414C348,这里我们不跟进去,结果会被保存在堆栈中的。
我们直接按F8键单步步过这个CALL。
image120.jpg
我们可以看到堆栈中保存了结果,我们需要弄明白它表示什么意思。
image122.jpg
接下来的操作码是19,参数值是88,代表一个局部变量。
image124.jpg
这里我们直接跟进。
image126.jpg
我们看到这里。
image128.jpg
通过MOVSX指令读取出占两个字节的参数值,将其保存到EAX中。FF开头表明该参数值是一个负数。
image130.jpg
该值对应的十六进制为-88,跟ExDec中显示的刚好对应起来了。
image132.jpg
十进制的-139正好等于十六进制的-88。
image134.jpg
接着ESI 加2,然后刚刚计算出的-88加上EBP的值,即将EBP - 88保存到EAX中。
image136.jpg
这里我们可以看到到达了一个CALL处,根据堆栈的来看其有三个参数。
image138.jpg
第一个参数是前一个操作码执行的结果,第二个参数我这里是12F458,即EBP - 88-表示一个局部变量。第三个参数是-1。这里我们不跟进这个CALL,直接按F8键单步步过这个CALL,看看会发生什么。
image140.jpg
我们会发现堆栈发生了变化,ECX被清零了。
EBP-88内存单元保存了前一个操作码执行的结果。
image142.jpg
接下来一个操作码是08,它也将局部变量EBP -88作为参数。
image144.jpg
我们跟进这个JMP。
image146.jpg
这下面并不是我们之前看到的XOR EAX,EAX结束,而是OR EAX,EAX,接着使用条件跳转判断EAX是否为零。我们来看看它具体干了些什么。
首先将操作码的参数FF78保存到EAX中,注意这里使用的是MOVSX,FF开头表示是负数,十六进制值为-88。
image148.jpg
image150.jpg
这一行是将EAX + EBP指向内存单元的值保存到EAX中,即EBP - 88这个局部变量的值。
image152.jpg
这里判断EAX是否为零,如果为零就跳转到74145A15地址处。如果不为零就继续往下执行。
image154.jpg
这里将EAX的值保存到EBP -4C中。
我们应该还记得之前读取EBP + 8的内容,接着将其保存到EBP - 4C中。所以说EBP - 4C的值不为零。
所以我们将EBP - 4C称为指针数据元素。
image156.jpg
接下来是下一个操作码。
image158.jpg
这里我们来Google一下这个操作码0dVCallHresult。
表示获取文本框中输入的文本。
这里将读取我们输入的错误序列号,我们继续跟,看看是不是这样。
image160.jpg
我们可以看到该操作码跟之前一样还是以XOR EAX,EAX结束。
首先读取EBP - 4C的内容(指向数据项的指针)保存到EAX中。
image162.jpg
接下来将这个值压入堆栈。
image164.jpg
接着读取操作码的参数。
image166.jpg
这里将参数值保存到EDI中。
然后读取EAX指向的内存单元的内容,这是另一个表的起始内容。
image168.jpg
我们看到该表的00A0偏移处。
image170.jpg
这里依然是间接CALL表中内容,我们不跟进这个CALL,直接按F8键单步步过这个CALL,然后看堆栈的结果。
image172.jpg
我们按F8键执行这个CALL。
接着EBP - 44的内容保存到EDX中。
image174.jpg
这里判断某个值,接着读取下一个操作码。这里你可能会问读取的是什么,是我们输入的错误序列号吗?我们看看ExDec先。
image176.jpg
我们可以看到该操作码的参数是8C,也就是EBP - 8C,我们看看EBP - 8C的值是多少。
image178.jpg
这里我们可以看到是12F454。
image180.jpg
其保存的是15D3BC是我们输入的错误序列号的指针。
image182.jpg
嘿嘿,终于找到了我们输入的错误序列号。接下来一个操作码是6C ILdRf。
image184.jpg
image186.jpg
这里的解释是该操作码加载一个引用的值。我们跟进这个操作码看看。
image188.jpg
这里。
image190.jpg
这里通过MOVSX指令读取参数的值,是个负数。
image192.jpg
参数是FF74,所以保存到EAX中是:
image194.jpg
对应的十六进制是-8C。
image196.jpg
这里将EAX + EBP指向的内容压入堆栈,实际上是将EBP - 8C的内容压入堆栈。
image198.jpg
这里我们可以看到EBP - 8C指向了我们输入的错误序列号,堆栈中也保存了这个指针。
image200.jpg
我们在数据窗口中清楚地看到指向了我们输入的错误序列号。
下一个操作码是:
1b LitStr,根据字面上的意思来理解是”字符串”。
我们来看看它会干些什么。
image202.jpg
我们跟进该操作码。
image204.jpg
可以看到参数为0001,将被保存到EAX中,是个正数。
image206.jpg
image208.jpg
接下来一行我们可以看到4017E4被保存到了EDX中,这个值是什么,我们暂时还无从知晓。
image210.jpg
压入这个4016F8是干嘛的呢?
image212.jpg
ExDec中只显示了两个单引号,表明将一个空字符串压入堆栈。
image214.jpg
通过数据窗口我们也能看出是一个空字符串,即当我们单击注册按钮时,下一个操作码会检查我们输入的是否为空。
image216.jpg
ExDec中显示如下:
image218.jpg
这里Lead0是第一个操作,30EqStr是第二个操作。我们来Google一下它的意思。
Lead0/30 EqStr - 比较两个字符串。
也就是说这里将比较两个字符串。这是一个双操作码的操作。第一个操作码的操作数是FB,我们跟进这个操作码。
image220.jpg
这里直接以XOR EAX,EAX结束,什么也没做,接着读取第二个操作码。
image222.jpg
第二个操作码是30,接着读取参数。操作执行完后以XOREAX,EAX结束。我们跟进这个操作码。
image224.jpg
这第二个操作码PUSH 0。
image226.jpg
接下来是一个CALL,有三个参数。我们按F8键单步步过这个CALL,看看会发生什么。
堆栈移动了,里面值没有变,只是堆栈被抬高了。
下一行CMP AL,0,这里AL保存的是上一个CALL的结果,我这里的值是:
image228.jpg
AL = 01
表示两个字符串不相等。
image230.jpg
比较完以后首先将EAX置零。如果刚刚比较的结果不为零,就将零压入堆栈,如果比较的结果相等就将FFFFFFFF压入堆栈。说明在做检查,嘿嘿。
image232.jpg
我们接着看下一个操作码。
image234.jpg
我们Google一下它的意思会发现跟SysFreeString类似,就是释放字符串所占的内存空间。我们可以看到这里要释放的内存空间是EBP - 8C。
image236.jpg
这里首先将EDX赋值为1,接着通过MOVSX将参数值保存到EBX中,接着将EBX - FF74(十六进制的-8C)压入堆栈。
image238.jpg
这里EBX + EBP即EBP - 8C,所以压入堆栈的是错误的序列号。
image240.jpg
这里我们可以看到下面的CALL里面会调用一个API函数SysFreeString,然后返回。
image242.jpg
这个时候我们输入的错误序列号被清空了。
image244.jpg
这里我们输入的错误系列号其实还在15D3BC这个内存单元中,只不过它的指针EBP - 8C被清空了而已。
image246.jpg
接着看下一个操作码。
image248.jpg
这里将清除局部变量EBP - 88的内容。
EBP - 88的值是多少?
image250.jpg
这不是表中的数据项吗,将被清除,我们接着往下看。
image252.jpg
这里是获取操作码的参数。
image254.jpg
FF78对应十六进制的-88。
image256.jpg
这里又是将EBP - 88的内容保存到EAX中,接着判断它是否为零。这里不为零,我们继续。
image258.jpg
这里调用这个CALL释放EBP - 88局部变量的内存空间。
image260.jpg
这里EAX被清零了。
image262.jpg
下一个操作码是:
image264.jpg
该操作码是一个条件跳转,所有的Branch开头的都是跳转操作:
指令                   操作码                      跳转条件
Branch                 1e                          无条件跳转
BranchF                1c                          栈顶数据为false则跳转
BranchT                1d                          栈顶数据为True则跳转
这是一个条件跳转操作,如果栈顶数据为假就跳转,这里检查文本框中的序列号是否正确。
如果跳转了的话,下个操作码将是:
image266.jpg
这里的条件跳转直接越过了401BF3处的无条件跳转。
image268.jpg
这个操作就结束了,我们继续看下一个。
image270.jpg
这里到达了401BF6这个分支,条件跳转成立了,越过了401BF3处的无条件跳转,嘿嘿。
Lead3/c1 LitVarl4
这是个双操作码的操作,我们来看一看。
image272.jpg
这里第一个操作码结束了,继续读取第二个操作码。
image274.jpg
我们继续跟踪。
image276.jpg
这里读取操作码的参数。
image278.jpg
FF54以FF开头,所以是一个负数。
image280.jpg
这次参数占4个字节,被保存到EAX中。
image282.jpg
这是一个局部变量。
image284.jpg
EBP + FFFFFF54 + 8即第一个参数加上8,结果是12F43C,参数的值被保存到12F43C中。
image286.jpg
接着我们跳转到了这里。
image288.jpg
这里将12F434压入堆栈。
image290.jpg
12F434是一个结构体的指针。而这个结构体里面又保存了其他3个结构体。
image292.jpg
我们跟到了这里,嘿嘿。
如果该CrackMe采用的是硬编码的话,我们可以切换到小数形式,看看是不是正确的序列号。我们直接再打开一个这个CrackMe。
image294.jpg
我们在OD中看看十进制值为多少。
image296.jpg
我们可以看到十进制值为246810,我们在CrackMe中输入它。
image298.jpg
嘿嘿,提示输入的序列号正确。我们接着看比较的过程。
image300.jpg
下一个操作是双操作码。
第一个操作码是FC,我们跟进这个操作码,直接就结束了,接着读取第二个操作码。
image302.jpg
该操作码是F6,我们跟进去,ExDec中显示的是EBP - 9C,即local_009c。
image304.jpg
这里读取参数,是个负数。
image306.jpg
对应十六进制的-9C。
image308.jpg
这里EBP + EBX,即EBP - 9C,值为12F444,这里面是空的。
image310.jpg
这里判断[EBX]是否小于8,如果小于8则跳转。
image312.jpg
接着又跳转,这里我们就不深究了,直接看到该操作码的最后一行。
image314.jpg
这里将3保存到EBP - 9C中。
image316.jpg
执行后。
image318.jpg
下一行拷贝这里的内容到EBP - 9C中。
image320.jpg
EBP - 9C结构里保存了正确的序列号,还有这个数字3。
image322.jpg
接着看下一个操作码。
image324.jpg
这里跟前面的介绍基本上是一样的了。
image326.jpg
相同的地方我们直接略过,直接看到我们还没有跟过的操作码。
image328.jpg
这里我们跳过前面的,直接给401C17这个操作码设置一个内存访问断点,当读取到这个操作码的时候就会断下来。
image330.jpg
断在了这里,这里读取操作码0A,我们看看ExDec中显示的:
ImpAdCallFPR4,表示调用一个API函数。
例如:
4017F5: 0a  ImpAdCallFPR4:   _rtcMsgBox
这个例子是调用__rtcMsgBox这个API函数。
再来看
401C17: 0aImpAdCallFPR4: _rtcR8ValFromBstr
image332.jpg
这里读取该操作码的参数。
image334.jpg
参数被保存到ECX中。
image336.jpg
EAX被赋值为401000,接着判断EAX是否为零。
image338.jpg
接着读取第二个参数。
image340.jpg
image342.jpg
我们到了CALL EAX这里,此时EAX值为401000,我们看看这个地址是哪个API函数。
image344.jpg
传递给该函数的参数在堆栈中:
image346.jpg
可以看到是我们输入的错误序列号。
image348.jpg
这里该操作序列号被装载到了浮点寄存器ST0中去了,浮点寄存器我们还没有介绍过,下面还有一些寄存器。如果你看不到浮点寄存器的话,你可以在寄存器窗口中单击鼠标右键选择-View FPU registers。
image350.jpg
加载我们错误序列号的位置在这:
image352.jpg
我们看到下一个操作码。
401C1C:Lead2/6bCVarR8。
我们跟进这个操作码。
image354.jpg
这是一个双操作码的操作,先读取第一个操作码,接着读取第二个。
image356.jpg
接下来,是一些浮点指令,我们还没有介绍过。
但是我们可看到读取的参数。
image358.jpg
这里:
image360.jpg
EBP + EAX
image362.jpg
这里FSTP指令将ST0中的内容保存EAX+8指向的1内存单元中,即12F43C中。然后执行一次出栈操作。我们后面章节再详细讨论。
image364.jpg
执行以后:
image366.jpg
这里有可能是我们输入的错误序列号,我们将其转化为64位双精度小数看看,单击鼠标右键。
image368.jpg
可以看到正好是我们输入的错误序列号,但是这里占的是8个字节,即64位。从逻辑上来讲,一个占4个字节,32位,一个占8个字节,64位,看起来不一样。
image370.jpg
切换为正常模式显示。
image372.jpg
该指令将浮点寄存器的状态字保存到AX中,我们执行这一行。
image374.jpg
image376.jpg
这里该操作就结束了。
image378.jpg
这个操作码我们不知道是干什么用的,我们还是跟一跟吧。
image380.jpg
这一行是将ESP指向的内容保存到EAX中。
image382.jpg
这个内存单元位于转换后的错误序列号的上面。
image384.jpg
下一个操作码
image386.jpg
这里将EBP - 9C压入堆栈:
image388.jpg
接下来又是一个双操作码的操作。
image390.jpg
image392.jpg
这里读取第二个操作码。
image394.jpg
这里我们到了一个CALL处,堆栈中参数如下:
image396.jpg
其中一个指向了正确的序列号,一个指向了错误的序列号,将它们进行比较吗?
image398.jpg
image400.jpg
image402.jpg
这里我们下一个断点。
image404.jpg
我们可以看到这个CALL返回的结果EAX值为1。
image406.jpg
这里FFFFFFFF被压入堆栈,为了看到正确的序列号是多少,我们在比较这里设置一个断点。
image408.jpg
03C41A对应的十进制值为246810,我们在文本框中输入这个值。
image410.jpg
我们按下Registrar按钮,断了下来,我们看到比较处。
image412.jpg
246810对应的十六进制,可能会以不同格式存储,在不同的CALL中会被转化然后进行比较,我们看看结果是什么。
image414.jpg
我们可以看到EAX = 0。
image416.jpg
栈顶元素也被置零了。
接下来的BranchF操作码就会根据栈顶元素值来决定显示什么提示框了。
image418.jpg
你可能会说怎么这么长啊,因为这里是初次介绍P-CODE,所以我们给大家逐一介绍了每个操作码,后面章节我们就不会这么赘述了。我们可以根据ExDec反编译器得知每个操作码的名称,然后用OllyDbg来定位调试。
下一章节,我们将介绍clave2这个例子,大家可以先试试。

本系列文章汉化版转载看雪论坛

感谢原作者:RicardoNarvaja(西班牙人)
原作者个人主页:http://www.ricardonarvaja.info/

感谢热心翻译的朋友:
1~3章译者:BGCoder
4~58章译者:安于此生

全集配套程序下载地址:
链接: http://pan.baidu.com/s/1eQzTWfo 密码: vytv



评分

参与人数 14HB +12 THX +5 收起 理由
花盗睡鼠 + 2 + 1 [吾爱汇编论坛52HB.COM]-学破解防破解,知进攻懂防守!
Jawon + 1
一路走来不容易 + 1
Soul1999 + 1
极速菜 + 1
行行行行行行 + 1
冷亦飞 + 1
消逝的过去 + 1
zyyujq + 1
hackysh + 1
我是好人 + 1 [吾爱汇编论坛52HB.COM]-吃水不忘打井人,给个评分懂感恩!
jaunic + 1
hnymsh + 2
lies + 1

查看全部评分

吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
hackysh 发表于 2022-2-20 12:14 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
一道彩虹屁 发表于 2022-2-23 02:53 | 显示全部楼层

谢谢分享
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
不苦小和尚 发表于 2022-2-25 11:31 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
头像被屏蔽
别管我了行 发表于 2022-3-2 03:41 | 显示全部楼层

提示: 作者被禁止或删除 内容自动屏蔽
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
zg2600 发表于 2022-7-10 11:18 | 显示全部楼层

[吾爱汇编论坛52HB.COM]-楼主,你是一个大好人!!nice,谢谢,给力非常感谢破解思路
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
天使替我爱你 发表于 2022-7-10 22:14 | 显示全部楼层

大佬腻害多谢大佬
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
zg2600 发表于 2022-7-26 11:23 | 显示全部楼层

[吾爱汇编论坛52HB.COM]-做的不错哦,楼主加油,期待更好的作品!
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
冷亦飞 发表于 2022-11-5 09:16 | 显示全部楼层

谢谢分享
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
曾经沧海 发表于 2022-11-19 17:38 | 显示全部楼层

感谢分享。正在试用。
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

警告:本站严惩灌水回复,尊重自己从尊重他人开始!

1层
2层
3层
4层
5层
6层
7层
8层
9层
10层

免责声明

吾爱汇编(www.52hb.com)所讨论的技术及相关工具仅限用于研究学习,皆在提高软件产品的安全性,严禁用于不良动机。任何个人、团体、组织不得将其用于非法目的,否则,一切后果自行承担。吾爱汇编不承担任何因为技术滥用所产生的连带责任。吾爱汇编内容源于网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除。如有侵权请邮件或微信与我们联系处理。

站长邮箱:SharkHeng@sina.com
站长QQ:1140549900


QQ|RSS|手机版|小黑屋|帮助|吾爱汇编 ( 京公网安备11011502005403号 , 京ICP备20003498号-6 )|网站地图

Powered by Discuz!

吾爱汇编 www.52hb.com

快速回复 返回顶部 返回列表