4.条件指令设置
条件指令的形式是SETcc r/m8,其中r/M8是表示8位寄存器或者单字节内存单元。
条件设置指令格局处理器定义的16种条件测试一些标志位。把结果记录到操作数当中。条件满足时,目标操作数为1,否则为0.
这里有一段代码。
如果运用条件设置指令
5.纯算法实现逻辑判断
在编译器优化的时候,会在不改变原来逻辑的情况下,使用数学技巧把源代码的一些逻辑分支转化成算术操作,来提高CPU的流水线性能。可见一个例子。
代码先用neg指令检验eax的值是否为0,并且把结果存放在CF标志位。当CF为1时取相反数为-1,否则为0。
循环语句
其他类型的语句都是低地址向高地址取值引用。这一点可以方便的辨认循环语句。一般以ecx寄存器当做计数器。如下有一段简单的代码。
用高级语言来讲。
数学运算符
1.整数的加法与减法
一般情况下,整数的加法和减法分别编译成add和sub指令。优化时,很多人喜欢用lea指令来代替。lea允许用户在1个时钟内完成c=a+b+78h的计算,abc都得有寄存器的情况下才能有效。
lea是一条纯算术指令,edx=ecx+eax+78h。
2.整数的乘法
一般被编译成mul,imul指令。只是一般这样的指令运行速度比较慢,提高效率,所以会使用其他指令来完成计算。例如一个数是2的幂,那么左移指令shl来实现乘法算法。
3.整数的除法
一般被编译成div,idiv指令。除法运算的代价相当高,大概需要比乘法运算多10倍的CPU时钟。
如果被除数是一个未知数,那么编译器会使用div。
除数/被除数是一个常量就会复杂很多。编译器会使用一些技巧来有效实现除法运算。例子如下
除法指令需要符号扩展指令cdq,作用是把eax寄存器的数视为有符号的数,来满足64位运算命令的需要。编译器在优化时常用乘法运算代替除法运算来提高数倍的效率。最常用的就是倒数相乘。
这段代码就是一个简单的除法运算,优化后比一个idiv长,但是运行速度快了三倍。
文本字符串
字符的识别和分析是软件逆向的一个重要步骤。
1.字符串存储格式
一般将字符串看做字符数组来处理,不过不同的编程语言字符存储格式不同。
①C字符串
也称为asciiz字符串,最后一个为空字符
②DOS字符串
$字符作为终止字符
③PASCAL字符串
没有终止符,但是在头部定义一个字节表示字符,因为用1个字节表示字符串的的长度,所以字符串不能超过255个字符。
④Delphi字符串
是为了克服PASCAL字符串的局限性。
双字节:表示字段扩展为2字节,长度为65535。
四字节:扩展为4字节,长度为4GB,很少使用。
2.字符寻址指令
80x86系统支持寄存器直接寻址与寄存器间接寻址等模式。与字符指针处理相关的指令有mov,lea等。mov指令将当前指令所在内存复制到目的寄存器中,其操作数可以是常量,也可以是指针
lea的意思是装入有效地址。
要明白带不带“【】”,是不同的。不带更像是值,带了就像是指针。而lea指令的效率远远高于add。
3.字母大小写转换
大小写字母之间转换方式就是将原来的码的值减20h。
另一种也就是进行位运算。
4.计算字符串的长度
高级语言有特定的函数来计算字符串的长度。例如C中的strlen。
指令修改技巧
为了优化原程序或者在一定空间里增添代码,有一些修改技巧。
另外很多指令对eax寄存器进行了优化,尽量使用eax。
64位软件逆向技术
寄存器
本节讨论的x64是AMD和INTEL64的合成,是指与现有x86兼容的64位CPU。在64位系统中,内存地址为64位。
x64系统通用寄存器的名称,第一个字母从E改为R“RAX”,大小扩展到64位,数量增加8个,扩充了8个128位XMM寄存器。
函数
1.栈平衡
RSP用来保存当前的栈顶指针,每8个字节的栈空间来保存一个数据。
栈中存储的数据主要包括局部变量,函数参数,函数返回地址等。每调用一个函数,函数都要申请相应的栈空间。当函数调用完成时需要对刚才申请的栈空间进行释放,这就是栈平衡。
如果不进行栈平衡,栈内存很快就会被消耗光。
2.启动函数
前面有讲,不再重复。
3.调用约定
与之前不同,x64程序只有一种寄存器快速调用约定。前四个参数使用寄存器传递,如果参数超过四个,多于的参数放在栈里,入栈顺序从右到左,由函数调用方平衡栈空间。
前四个参数虽然使用了寄存器来传递,但还是在栈中为4个参数预留了空间。为方便叙述,这里称之为预留栈空间。在x64中如果像之前那样前四个用寄存器传递那么在函数中相当于少了四个寄存器。当函数功能比较复杂可能导致寄存器不够用,为了避免这个问题,就可以使用预留栈空间。
4.参数传递
参数小于四个时,通过寄存器传递。
4个以上参数传递,后面的通过栈传递。
参数为结构体,且大小不超过8字节,这时应该直接把整个结构体的内容放在寄存器当中,通过访问寄存器的高32位和低32位来访问结构体成员。
大于8字节时
可以见得大于8个字节时,传递参数时会把结构内容复制到栈空间,再把结构体地址当做函数的参数来进行传递(引用传递),
thiscall传递,是C++类的成员函数调用约定。
由此可知类的成员函数调用,参数传递方式与普通函数没很大的区别,唯一的区别是成员函数调用会隐含地传递一个this指针参数。
5.函数返回值
在64位环境中,使用RAX寄存器来保存函数返回值。返回值类型由浮点类型使用MMX0寄存器返回。RAX寄存器可以保存8字节数据。当返回值大于8字节,可以将栈空间的地址作为参数间接访问达到目的。
标签:加密,字节,解密,指令,64,寄存器,字符串,第四章,函数 From: https://www.cnblogs.com/Corax0o0/p/17047803.html