首先讲一下call:当你看到CALL语句,你只要明白CALL是子程序的入口,虽然在OD里目前看着是一条语句,如果你进入CALL的大门,里面有很多语句,我们可以把OD里看到的汇编语句看成是你的家,每个CALL就是你家里卧室、卫生间、厨房等小房间的大门,现在是关着的,你要想看卧室,你就必须打开门,进入CALL,怎么能进去呢,就是在OD里当指令执行到这个CALL的这一行语句时,用键盘上的F7就进去了。如果现在指令没有执行到CALL语句,你只是想看看CALL里面有什么?你可以把鼠标点到这一行,然后按回车键就可以进去浏览了。
红色箭头指的位置有一个EAX,上面有一个CALL,我们已经知道了CALL是一个子程序,里面有多行语句,子程序的作用就是实现一个功能,你可以这样理解,执行一个CALL就相当于执行一个任务,任务完成以后的结果就放在EAX里面,所以在CALL下面很近的EAX里面存放的就是CALL执行的结果。
那么这个结果对于破解有什么意义呢?
如果我们编程人员把某个CALL做为验证的子程序,这个CALL的作用就是进行真假码的比较,如果比较的结果是真,那么就返回数值1,如果结果是假,就返回数值0,那么返回值1或者0就放在EAX里面,然后下面的条件跳转命令JZ、JNZ就根据是1还是0这个结果来决定跳还是不跳,明白了吗?
EAX的意义就在于此,它里面存放的数值会决定程序以后的执行流程。
那我们知道了EAX的意义又有什么用呢?你可以修改EAX的值,比如把0改成1就行了,在哪改呢?在CALL里面的代码的开头改成MOV EAX,1 ,下一句改成RETN。这样改的好处是什么呢?因为很多程序在验证的时候会在程序执行过程中多次进行验证,每次验证后都会有条件跳转指令,与其你改多个条件跳转指令,不如改一个验证CALL的返回值更省事。