第4章-汇编指令
之前的章节主要是理论知识,现在我们要在OllyDbg中实践一下,为后面打开基础。 OllyDbg中几乎所有的标志我都有考虑,如果你遇到了我没有给出的指令,你可以查阅更加全面的汇编指南。 NOP(无操作)
运行这条指令不会对寄存器,内存以及堆栈造成任何影响,英文单词的意思是”无操作”,也就是说,它没有特殊的用途。例如,你用一个短指令来替换一个长指令的话,如果处理器没有错误,多余的空间将会被NOP填充。
适当数目的nop指令可以将其他指令完全替换掉。
下面使用OllyDbg重新载入CrueHead'а(CrackMe的作者)的CrackMe。
我们可以看到反汇编的源代码,如上图第一条指令是PUSH 0,占两个字节,在这条指令上面单击鼠标右键选择Assemble.
或者直接使用快捷键-空格键,在弹出窗口的编辑框中输入NOP。
写入NOP指令后单击Assemble按钮。
1
这里我们可以看到OD设计的非常智能,考虑到PUSH指令占两个字节,OD会使用两条NOP指令进行替换,而不是使用一条NOP进行替换。
现在,在原来PUSH 0的地方显示的两条NOP指令,单击F7,指令一条NOP指令,可以看到,这里只改变了EIP(保存了下一条要执行指令的地址)寄存器的值,并没有影响到其他寄存器,堆栈或者标志位。
现在我们需要在数据窗口查看这两个字节,它们的内存地址分别是401000和401001。
在数据窗口中,鼠标右键选择-“Go to”-“Expression”,输入你需要转到的地址。
这里我们需要输入401000。
红色突出显示的是刚刚修改过的字节。前两个是90,然后E8,FF和04,00,00。这是一个Call指令的所有剩余字节。
OD可以撤销我们修改的指令吗?
2
呵呵,当然啦。
在数据窗口或者反汇编窗口中,鼠标拖选中两个字节。
然后单击鼠标右键,选择“UNDO SELECTION”。
这样就恢复了原来的PUSH指令。
在数据窗口中的话,你就可以看到它原始的字节了。
以上是关于NOP指令的所有内容。 堆栈相关指令的说明
我们之前说过,堆栈就像一个信箱一样,越顶部的信越先被取出来。 PUSH
PUSH指令-将操作数压入堆栈中。我们可以看到,CrueHead'а(CrackMe的作者)的CrackMe
3
的第一条指令就是PUSH指令。
“PUSH 0”指令将把0存入到堆栈的顶部,此时并没有压入堆栈,指令执行后,我们看看堆栈如何变化。堆栈的地址在你的机器上可能会有所不同,但效果是一样的。
堆栈地址在我的机器上是12FFC4,可能与你机器上的不同,因为堆栈每次可能放置在不同的位置,其初始内容也可能有所不同,即这里的7C816D4F和你的也可能不同。按F7,将0压入堆栈,堆栈顶部的就是0了。
按下F7,堆栈顶部我们可以看到加入了0。下面的12FFC4中仍然是7C816D4F,堆栈中的其他值并没有改变。
主要的变化就是堆栈的顶部变成了12FFC0(这是PUSH 0指令执行的结果),新压入的数据总是在堆栈的顶部,并不会改变下面的数据。 这里也可以看到,ESP的值变成了12FFC0。
4
当然PUSH指令不仅仅可以压入数值:
PUSH EAX的话,那么堆栈的顶部将保存EAX的值。
同样的适用于其他的寄存器,你也可以压入特定内存地址中的值。 PUSH [401008]
注意,这和下面这条指令的解释是不同的。 PUSH 401008 (没有方括号)
如果你使用的“PUSH 401008”,那么堆栈中将被放置401008。
执行以后,我们可以看到下面的结果:
如果换成是“PUSH [401008]”
5