[401008]表示401008这个内存单元中存储的内容,这个时候我们得去数据窗口中查看它的值是多少。
在数据窗口中鼠标右键单击-Go to-Expression,输入401008,可以看到:
这四个字节是CA 20 40 00。按F7执行这条PUSH执行。
堆栈中我们可以看到在数据窗口中颠倒过来的值,即,它们被倒序放置。
读/写的内容在内存中倒序放置时处理器的特点之一。要怪你只能怪处理器的厂商了,嘿嘿。 通常情况下,没有用方框号括起来的只是一个数字。 现在我们知道,OD中“PUSH [401000]”的意思了。
6
PUSH DWORD PTR DS:[401008]
像这样的,除非有明确规定,否则OD都是认为你要操作的是4个字节的内存,也就是DWORD。其他格式会在其他指令中予以说明。 POP
POP指令是出栈:它会取出堆栈顶部的第一个字母或者第一个值,然后存放到指定的目标地址内存单元中。例如,POP EAX从栈顶中取出第一个值存放到EAX中,随后的一个值随即变成栈顶。
我们还是看到CrueHead'а的CrackMe的开始的语句:
将第一条指令替换成“POP EAX”,注意在第一行,按空格键:
以下是执行此操作,堆栈变化情况的说明:
7
ESP中存放的是12FFC4,它存放的是堆栈的顶部的内存地址。
我们可以看到EAX的值是0(我这里的情况)。 按F7键。
我们可以看到,原来堆栈顶部的值消失了,现在ESP为12FFC8。
原本在堆栈顶部的7C816D4F现在到了EAX中。
同样地,如果用户是“POP ECX”,那么上面的值将会到ECX寄存器中或者你指定其他寄存器中。
我们这里就研究了入栈和出栈指令。 PUSHAD
PUSHAD指令把所有通用寄存器的内容按一定顺序压入到堆栈中,PUSHAD也就相当
8
于’PUSH EAX,PUSH ECX,PUSH EDX,PUSH EBX,PUSH ESP,PUSH EBP,PUSH ESI, PUSH EDI’。 让我们来看看。
再次载入CrueHead'а的CrackMe,调用右键菜单来修改指令为PUSHAD。
这是我当前寄存器组的情况。
按下F7键,看看现在堆栈的情况:
9
看到所有寄存器的值都被压入堆栈了。12FFC4存放的是之前堆栈顶部的值,然后上面就是0(PUSH EAX),12FFBC存放的是ECX的内容,接下来是EDX寄存器的内容,以此类推。 POPAD
该指令与PUSHAD正好相反,它从堆栈中取值,并将它们放到相应的寄存器中。POPAD等价于“POP EDI,POP ESI,POP ESP,POP ESP,POP EBX,POP EDX,POP ECX,POP EAX”。 正如前面的例子,我们将第一条指令修改为POPAD:
由于堆栈中保存的是之前寄存器组的值,执行POPAD其返回原来的状态。
10