首页 > 代码库 > 花指令

花指令

本文作者:sodme
本文出处:http://blog.csdn.net/sodme
声明:本文能够不经作者允许随意转载、复制、引用。但不论什么对本文的引用,均须注明本文的作者、出处以及本行声明信息。

可能非常多人都听说过花指令,但限于平时的开发所限,可能较少接触到。日前,跟同事讨论了一些有关花指令的问题,现将自己的体会总结一下。

这篇文章将讨论以下问题:

一、什么是花指令?它的原理是什么?
二、在什么地方使用花指令?怎样使用花指令?
三、怎样识别花指令?怎样去除花指令?
四、一些典型的花指令实例

什么是花指令?当然不是"flower code",呵呵,实际上,把它依照“乱指令”来理解可能更贴切一些,它的真正英文名应该叫"thunkcode"吧(不确定,呵呵)。我们知道,汇编语言事实上就是机器指令的符号化,从某种程度上看,它仅仅是更easy理解一点的机器指令而已。每一条汇编语句,在汇编时,都会依据cpu特定的指令符号表将汇编指令翻译成二进制代码。而日常应用中,我们通过VC的IDE或其他如OD等反汇编、反编译软件也能够将一个二进制程序反汇编成汇编代码。机器的一般格式为:指令+数据。而反汇编的大致过程是:首先会确定指令開始的首地址,然后依据这个指令字推断是哪个汇编语句,然后再将后面的数据反汇编出来。由此,我们能够看到,在这一步的反汇编过程中存在漏洞:如果有人有益将错误的机器指令放在了错误的位置,那反汇编时,就有可能连同后面的数据一起错误地反汇编出来,这样,我们看到的就可能是一个错误的反汇编代码。这就是“花指令”,简而言之,花指令是利用了反汇编时单纯依据机器指令字来决定反汇编结果的漏洞

先举个样例(记为A代码段):
   jz    label
   jnz  label
   db thunkcode
label:

以上是一个相当简单的花指令块,当中thunkcode是由应用者自己随便写的机器指令字,当然,你写的这个机器指令字不能是单字节指令(比方nop, clr,等),否则,你的花指字就相当于白加了。那么,你要怎样来使用这段代码呢?

如果我们待加密的代码块例如以下(记为B代码段):
   mov ax, 8
   xor ax, 77
   ...

我们如果这B代码段是我们的加密算法所在的代码段,如今我们想要对B代码段进行保护,能够直接将A花指令块加到mov指令之前,形如:
   jz    label
   jnz  label
   db thunkcode
label:
   mov ax, 8
   xor ax, 77
   ...

当中,对于thunkcode,在实际使用时,能够使用不论什么一个多字节指令的机器指令字来取代,这样就会欺骗反汇编软件将它连同后面的mov指令的前边某一部分反汇编成一个多字节指令。这样,我们的目的也就达到了。

由上能够看到,使用了花指令的地方,一般都会出现这样的现象:一个跳转指令,跳转到了某条语句的中间位置,而不是这条语句的開始位置。每当出现这样的情况时,我们就能够断定,这里出现了花指令。

显然地,破解它的办法,就是在那个跳转到的目的地址之前将中间的代码所有nop掉。

当然,为了加强难度,我们能够将若干个花指令结合起来使用。比方:
   jz    label
   jnz  label
   db thunkcode
label:
   jz    label2
   jnz  label2
   db thunkcode
lable2
   mov ax, 8
   xor ax, 77
   ...

也当然,针对这样的情况的破解仅仅要一层层解开它就可以:我们能够先破解到以label为首字节的指令出现为止,然后再依据新的结果,破解到以label2为首字节的指令出现为止,尽管这样麻烦点,但还是不难的。

可是,如果把以下的这段代码再同其他花指令结合起来使用,可能就更复杂了:
   call    label_1 
   db        thunkcode 
   jmp        label_2 
   db        thunkcode
label_1:   
   pop        eax 
   jmp        label_3 
   db        thunkcode,thunkcode,thunkcode
label_3:   
   inc        eax 
   jmp      label_4 
   db        thunkcode,thunkcode,thunkcode
label_4:   
   jmp        eax 
   db        thunkcode
label_2:   
   ....


这里另一段:
   call label_1
   db  thunkcode,thunkcode
   jmp  label_4
label_1: 
   pop  eax
   jmp  label_2
   db  thunkcode,thunkcode
label_2: 
   add  eax,2
   jmp  label_3
   db  thunkcode
label_3: 
   push eax
   ret
   db  thunkcode
label_4: ....
 
为了加强难度,尽可能地用call和push实现间接跳转,当然,矛矛盾盾,仅仅是时间长点而已,世上没有绝对安全的系统。
<以上代码来源于看雪的"软件加密技术内幕"一书>