比较全面的OD指令
最近在学习脱壳破解,看了下论坛对于OD指令的解释不是太全面,下面把我搜集的一些相对来说比较全面的指令分享给大家共勉,虽然我也没全搞懂{:301_1008:}附上文档下载链接:http://pan.baidu.com/s/1bnDKO1p 密码:amsy
OD汇编指令
NOP无操作
PUSH将数据压如堆栈中
POP出栈(与PUSH相反)
PUSHAD所有通用寄存器的内容按一定顺序压入到堆栈中,相当于’PUSHEAX,PUSH ECX,PUSH EDX,PUSH EBX,PUSH ESP,PUSH EBP,PUSH ESI, PUSH EDI’
POPAD该指令与PUSHAD正好相反,它从堆栈中取值,并将它们放到相应的寄存器中,等价于“POPEDI,POP ESI,POP ESP,POP ESP,POP EBX,POP EDX,POP ECX,POP EAX”
MOV该指令将第二个操作数赋值给第一个操作数
MOV EAX, EBX 释:EBX值赋值给EAX
MOVSX
(带符号扩展的传送指令)第二个操作数可能是一个寄存器也可能是一个内存单元,第一个操作数的位数比第二个操作数多,第二个操作数的符号位填充第一个操作数剩余部分
MOVZX
(带0扩展的传送指令)类似于MOVSX,但是这种情况下剩余的部分不根据操作数的正负来进行填充,剩余的部分总是被填充为0
LEA
(取地址指令)类似于MOV指令,但是第一个操作数是一个通用寄存器,并且第二个操作数是一个内存单元。当计算的时候要依赖于之前的结果的话,那么这个指令就非常有用
XCHG交换寄存器/内存单元 和 寄存器
OD数学指令
INC执行增加,如果是INC指令的话,就加1
DEC执行减少,如果是DEC指令的话,就减1
ADDADD指令有两个操作数,相加后的结果存放到第一个操作数中,ADD EAX,1等价于INC EAX
ADC
(带进位的加法)两个操作数的和加上进位标志的值,结果存放到第一个操作数中
SUB这个指令与ADD刚好相反,它将第一个操作数减去第二个操作数的值存放到第一个操作数中
SBB该指令跟ADC正好相反,它计算两个操作数的差值,并且还要减去进位标志,结果存放到第一个操作数中
MUL
(无符号数的乘法)有两种乘法:
第一种只有一个操作数,另一个操作数是EAX,结果存放到EDX:EAX中,比如:MUL ECX
第二种有两个操作数,两个操作数相乘,结果存放于EDX:EAX中,比如:MUL DWORD PTR DS:
IMUL
(有符号数的乘法)IMUL指令用法类似于MUL,例如:IMULECX 该指令将有有符号数ECX乘以EAX,结果存放到EDX:EAX中
注:
1.除了上面一条指令外,IMUL还允许使用多个操作数,这是与MUL不同的地方
2.尽管在默认情况下是使用EAX和EDX寄存器,但是我们还可以指定其他的数据源以及目标多达三个操作数;例:
0FAF55E8 IMUL EDX, DWORDPTR EDX x -> EDX
DIV
&&
IDIV无符号除法/有符号除法;这两个指令反别与MUL和IMUL相反
DIV只有一个操作数,该操作数必须是无符号数,结果存放到EDX:EAX中
如果是一个操作数的话,那么它和DIV类似,只不过操作数是有符号的,结果依然保存在EDX:EAX中。IDIV两个操作数的情况,第一个操作数除以第二个操作数,结果存放到第一个操作数中。三个操作数的情况,第二个操作数除以第三个操作数,结果存放到第一个操作数中
XADD
(交换并相加)这个指令其实就是XCHG和ADD两个简单指令的组合
NEG该指令的目的是将操作数的符号取反,即如果我们有一个32位的16进制数,用NEG操作以后,结果就会取反
逻辑指令逻辑指令有两个操作数,两操作数按位运算,并将结果存放到第一个操作数中
AND只有两个二进制位都为1的时候结果才为1,其他情况,结果都为0;例:
AND ECX,EAX 将ECX设置为0001200,EAX设置为3500
1200二进制为01001000000000
3500二进制为11010100000000
两个0取0。对每一位重复此过程,当两位都为1的时候才取1,这两个数中只有一次,两位都是1的情况
按下F7键,我们将看到ECX的值为1000。相当于二进制的01000000000000
OR该指令与AND的不同之处在于,两位中只要有一位为1,结果就取1;
XOR该指令运算,当两位不同时取1,相同时取0
NOT该指令是简单的按位取反
比较和条件跳转
CMPCMPEAX, ECX
该指令是比较两个操作数,实际上,它相当于SUB指令,但是相减的结构并不保存到第一个操作数中。只是根据相减的结果来改变零标志位的,当两个操作数相等的时候,零标志位置1
根据标志的值来决定跳转还是不跳转。最简单的例子就是配合JZ指令,如果Z标志被置为1,就跳转,否则,就不跳转
TEST
(逻辑比较)TESTEAX,EAX
该指令在一定程序上和CMP指令时类似的,两个数值进行与操作,结果不保存,但是会改变相应标志位(比如说,SF,ZF,PF标志位),程序可以根据结果来决定是否跳转到相应的分支
JUMPS所有的跳转指令都会指向程序将会跳转到的地址。
具体如下:
JMP – 跳转
JE, JZ – 结果为零则跳转
JNE, JNZ – 结果不为零则跳转
JS – 结果为负则跳转
JNS – 结果不为负则跳转
JP, JPE – 结果中1的个数为偶数则跳转
JNP, JNPE – 结果为1的个数为奇数则跳转
JO – 结果溢出了则跳转
JNO – 结果没有溢出则跳转
JB, JNAE – 小于则跳转 (无符号数)
JNB, JAE – 大于等于则跳转 (无符号数)
JBE, JNA – 小于等于则跳转 (无符号数)
JNBE, JA – 大于则跳转(无符号数)
JL, JNGE –小于则跳转 (有符号数)
JNL, JGE – 大于等于则跳转 (有符号数)
JLE, JNG – 小于等于则跳转 (有符号数)
JNLE, JG – 大于则跳转(有符号数)
JMP这是一个无条件跳转指令,即总是跳转到指定的地址
JE或者JZ若相等则跳;如果零标志位Z不为0则跳转,即,要求操作的结果为零
JNE或JNZ若不等则跳转;如果零标志位Z为0则跳转,即,要求操作的结果非零
JSJSEAX,ECX
当比较的结果为负时将跳转,即,就是EAX小于ECX则跳转
JNSJNSEAX,ECX
这个跳转指令与JS刚好相反。当零标志位S为0的时候跳转,也就是说EAX大于ECX的时候跳转
JP或JPE 这个跳转指令是当奇偶标志位P置1的时候才会发生,也就是比较的结果中1的个数要是偶数才会跳转
JNP 或JNPE这条指令刚好与上一条指令刚好相反,当奇偶标志位P为0的时候跳转。即结果中1的个数为奇数的时候
JO当发生溢出时,即溢出标志位O置1的时候跳转
JNO跟上一条指令相反,这里是当溢出标志位O为0时跳转,即溢出没有发生时
JB第一个操作数小于第二个操作数的时候跳转
JNB和JB指令相反,这个指令是当进位/借位标志位为0的时候跳转,也就是说,结果为正的时候跳转也就是说第二个第一个操作数大于第二个操作数的时候跳转
JBEJBEEXA,ECX
这个指令是小于或者等于的时候跳转,这是判断两个标志位的,当进位/借位标志位置1或者零标志位Z置1的时候将发生跳转,也就是说,EAX要小于或者等于ECX才会发生跳转
JNBE这个指令跟JBE刚好相反,当进位/借位标志位C与零标志位Z都为0时候才会发生跳转,
JL这个指令当小于的时候跳转,但是与前面的JB稍微有点不同。这个指令时根据符号标志位S来决定是否跳转
JB比较两个数的时候,将它们两个都看做是正数,即认为它们是无符号数,但是JL指令要考虑符号,这就是这两条指令的主要区别
CALL是指将转移到指定的子程序处,它的操作数就是给定的地址;例:
Call401362表示将转移到地址401362处,将调用401362处的子程序,一旦子程序调用完毕就返回到Call指令的下一条语句处,在这种情况下,完成401362的子程序调用以后,则会返回到40124A地址处
RET(RETN)返回到指定位置,当我们执行到ret指令的时候,栈顶存放的一般是子程序的返回地址;也就是说ret指令是子程序的结束,也就是说,如果我们call跟进的话,那么ret就能返回到call指令的下一条语句处。当然RET指令不止适用于子程序返回,例如:
PUSH 401256
RET
这里将401256压入堆栈。下面的ret指令会将401256当做子程序的返回地址,其实它并不是返回地址,但是执行ret指令后我们依然可以转移到401256地址处。这段代码和JMP401256指令的功能是一样的
循环指令为了实现循环可以使用前面介绍过一些指令。例如,你可以将任意通用寄存器指定为计数器(通常ECX作为计数器使用),你可以将其初始化为需要循环的次数,然后执行循环体,接着计数器递减1,判断计数器是否为0,如果计数器不为0继续重复前面的过程,如果计数器为0,就不继续循环了,而直接执行下面的代码。代码如下:
XOR ECX,ECX
MOV ECX,15h
将计数器初始化为循环次数15h。接下来就是循环体了:
Label:
DEC ECX
该计数器每次递减1。
其实就是循环体了,循环体里面可以是任意指令。
最后,你需要添加一个判断计数器是否为0的指令以及条件跳转指令。
CMP ECX,0
JNE Label
LOOPLOOP指令可以帮我们完成前面例子中的事情-将计数器ECX的值减1,判断ECX的值是否为0,如果为0就跳转到指定的地址-将像前面的例子一样。(可惜的是,大多数现代的处理器中该指令的效率不如前面模拟的例子。)
在DEC ECX指令上单击鼠标右键选择-Binary-Fill with NOPS。对TEST ECX,ECX和JNZ401007两条指令也进行同样的操作。这三条指令用一条LOOP 401007指令就可以替代
LOOPZ
LOOPE重复循环,直到零标志位Z置1
LOOPNZ
LOOPNE重复循环,直到零标志位Z清0
此外,LOOPZ,LOOPNZ指令还将检查零标志位Z是否为0。只有计数器的值和零标志Z同时满足条件时才循环。
你的热心是我持续分享的动力!!
谢谢分享! 新手刚学破解,每次啥步进单步啥的都不太懂,楼主这贴很给力啊666{:301_1003:},感谢 很好很给力很详细 感谢分享
感谢分享 好东西,谢谢分享。 你们这些人
都不给热心{:301_972:} 我来看看啊
谢谢楼主 不错,不过好难记住啊 这个贴非常好!赞!!!