电子科技大学基于二进制代码混淆的软件保护研究 OS

admin 2019-8-31 198

译文:

置换条件

 ---------------------- 

这里我试图定义条件,当有可能改变

某些连续x86指令和指令块的顺序时,

即交换它们,但保持程序运行相同。

想象一下,我们有“ADD EAX,EBX”,其后是“MOV ECX,EDX”,

我们知道这两个指令都不是某些JMP,CALL 

或任何其他代码/数据/算法参考的目的地。

在这种情况下,它们可以相互交换。

现在让我们检查可以

对某些任意连续指令执行此类技巧的条件。

1.一条指令

  让它包括:

    操作代码,源对象集,目标对象集。

  对象集是属性的一组,指令处理:

      公共寄存器:EAX,ECX,EDX,EBX,ESI,EDI,ESP,EBP(8位)

    标志(1位)

    存储器引用(1位)

  我们将集合放入{}括号,

  因为全套是{EAX,EBX,ECX,EDX,ESI,EDI,ESP,EBP,flags,memory} 

  ,空集是{}。

  在二进制表示法中,它可能看起来就像一个10位数字。

  内存引用意味着

  我们的指令至少可以读取/写入内存中的任何字节。

  由于以下原因,我们不区分内存地址:

  如果有两条指令,

  首先在[eax]访问内存,

  第二个访问[ebx]的内存,

  我们不知道eax / ebx是否相等(或4字节范围相交); 

  那么,它只是我们的记忆参考,

  我们只知道它可能是同一个变量。

  其他属性,如EIP,segment-,FPU-,MMX-,SSE-寄存器,

  在此不予考虑,因为我们的理论应用有限。

  我们假设没有任何一条指令(NOP除外)可以与

  INT,RET,CALL,JMP,JXX或FPU / MMX指令混合使用。

  “源对象集”是要读取的一组对象。

  “目标对象集”是要写入/修改的一组对象。

  任何目标对象都将取代源对象。

  我的意思是在“ADD EAX,EBX”指令中,EBX是源对象,

  而EAX既是源对象,也是目标对象,

  但我们说EAX只是目标对象,

  我们从不说EAX是源; 

  但是,我们始终牢记任何目标对象

  也可以(间接)源对象。

  但是,如果我们有“ADD ECX,ECX”指令,我们必须将第二个(src)ECX包含

  在源对象集中。

  让我们考虑一些典型的指令:

  INSTRUCTION DESTINATION OBJECT SET SOURCE OBJECT SET 

  nop <none> <none> 

  mov R1,R2 R1 R2

  cmp R1,R2标志R1,R2 

  加R1,R1 R1,标志R1 

  adc R1,R2 R1,标志R2,标志

  mov R1,[R2 + R3] R1 R2,R3,存储器

  加R1,[R2 + R3] R1,标志R2,R3,存储器

  子[R1 + R2],R3标志,存储器R1,R2,R3 

  测试[R1 + R2],R3标志R1,R2,R3,存储器

  公司R1 R1,标志<无> 

  lea R1,[ R2 + R3] R1 R1,R2 

  xchg R1,[R2] R1,存储器R2 

  推送R1 ESP,存储器R1

  pop R1 ESP,R1 memory 

  cld flags <none> 

  lods ESI,EAX flags,memory 

  rep lods ESI,EAX,ECX,flags flags,memory 

  stos EDI,memory EAX,flags 

  rep stos EDI,ECX,memory,flags EAX,flags 

  rep cmps ESI,EDI,ECX,memory,flags memory 

2.1。

  两条指令

  使它们看起来像

CMD1 DST1,SRC1 

  CMD2 DST2,SRC2 

  ,其中DST1,SRC1,DST2,SRC2是源/目标对象集。

  任何这些集都可能是空的。

  我们还假设两个指令都已经过滤/检查,

  即它们中没有一个是JMP,CALL,RET等。

  因此,我们有4个集合,并且我们在

  这两个集合中有6个关系。{C(4,2)= 4!/ 2!*(4-2)!= 6} 

2.2。简单条件

  六个关系中的每一个都是对两个位集的按位AND运算,返回

  逻辑ZERO或NON-ZERO。换句话说,每两组可以相交或不相交。

  #define INTERSECT(bitset_X,bitset_Y)((bitset_X&bitset_Y)!= 0)

  这里有3个条件,当可以交换两条指令时:

   (DST1&DST2)== 0 [1] 

   (DST1&SRC2)== 0 [2]

   (DST2和SRC1)== 0 [3] 

  其他3(未使用)关系如下所示:

   (DST1&SRC1)==无论[4] 

   (DST2和SRC2)==无论[5] 

   (SRC1&SRC2)==无论[6] 

  示例:

  添加eax,ebx#cmd1 = ADD dst1 = {EAX,flags} src1 = {EBX} 

  sub ebx,ecx#cmd2 = SUB dst2 = {EBX,flags} src2 = {ECX} 

  [1] = = FALSE {EAX,flags}相交{EBX,flags} 

  [2] == TRUE {EAX,flags}不与{ECX} 

  [3] == FALSE {EBX,flags}相交{EBX} 

  本身,这两条指令不能交换。

2.3。高级条件

  存在一些先进条件,需要更多分析。

  在这种情况下,可以忽略[1],[2],[3]条件中的一些条件。

  例如:

   (CMD1 == CMD2)&&(DST1 == DST2)&& [2] && [3] [7] 

  或

   #define GROUP_1(cmd)((cmd == ADD)||(cmd == SUB))

   GROUP_1(CMD1)&& GROUP_2(CMD2)&&(DST1 == DST2)&& [2] && [3] [8] 

  例如(下图),[1]为FALSE,但从[8]开始,以下

  说明可以是swapped:

  添加eax,ecx 

  sub eax,edx 

  现在,想象一下,我们有以下命令:

  mov [ebp + 4],eax 

  mov [ebp + 8],ecx

  这种情况应该以特殊的方式处理; 

  否则我们的理论将增长到包含

  对象集中的变量列表; 这也需要检查

  内存范围等的交集。

  除了全部之外,我们可以忽略条件[1],如果指令

  后面跟着没有使用DST1和DST2对象集的代码。

  但这需要更多的分析,我认为这不是最佳的。

3.从单指令到指令块

  想象一下我们有这些指令(彼此跟随):

  [a]添加eax,ecx 

  [b] adc eax,edx 

  [c] add ebx,ecx 

  [d] adc ebx,edx 

  [ e] sub esi,edi

  我们不能交换[a]和[b],我们不能交换[c]和[d]。

  但我们可以交换[ab]和[cd]。

  因此,我们需要一些实体来替换连续的指令。

4. N个指令的一个块

  CMD1 DST1,SRC1 

  CMDi DSTi,SRCi 

  CMDN DSTN,SRCN 

  如果我们将该块视为单个指令,

  如何计算摘要SUM_DST和SUM_SRC对象集?

  即由该代码块读取和写入的对象集。

  最简单的方法是对所有SRC / DST [i]进行BITWISE OR; 它是正确的,

  但随后我们将失去一些可能性,

  如下例所示:

   mov eax,ebx 

   add eax,ecx

   adc edx,eax 

  here,SUM_SRC,如果计算为SRC1 | SRC2 | SRC3,则等于

  EBX | ECX | EAX,但是没有必要将EAX包含到该集合中,

  因为它在此块内部初始化,但未通过成。

  因此,计算SUM_SRC和SUM_DST的算法如下:

  SUM_SRC = 0 

  SUM_DST = 0 

  for(i = 0; i <N; i ++)#在上面的例子中显示(N = 3):

  {#i = 0 1 2 

    SUM_SRC | = SRC [i]&(~SUM_DST)#SUM_SRC = {EBX} {EBX,ECX} {EBX,ECX} 

    SUM_DST | = DST [i] #SUM_DST = {EAX} {EAX} {EAX,EDX} 

  } 

5两个街区

  使用块与使用单个指令相同,

  除了应该计算SUM_SRC和SUM_DST,如上

  所示。

  你可以交换两个块,或者块和单个指令,这没关系。

6.如何查找某些给定指令的对象集?

  可能使用ADE32之类的东西和一些额外的分析。

原文:

                           Permutation conditions

                           ----------------------

Here i'm trying to define conditions, when it is possible to change order

of some consecutive x86 instructions and instruction blocks,

i.e. swap them, but keep program working the same.

Imagine that we have "ADD EAX, EBX" which is followed by "MOV ECX, EDX",

and we know that both instructions are not the destination of some JMP, CALL,

or any other code/data/algorithmic reference.

In such a case they can be swapped with each other.

Now lets examine conditions under which such a trick can be performed

for some arbitrary consecutive instructions.

1. ONE instruction

  Let it consists of:

    operation code, source object set, destination object set.

  Object set is a bitset of properties, instruction deal with:

      common registers: EAX,ECX,EDX,EBX,ESI,EDI,ESP,EBP (8 bits)

    flags (1 bit)

    memory reference (1 bit)

  We will enclose sets into { } brackets,

  as such full set is {EAX,EBX,ECX,EDX,ESI,EDI,ESP,EBP,flags,memory}

  and empty set is {}.

  In binary notation it may look just like a 10-bit number.

  Memory reference means that at least any byte in memory can be read/written

  by our instruction.

  We dont distinguish memory addresses, because of the following:

  if there are two instructions,

  first one accessing memory at [eax],

  second one accessing memory at [ebx],

  and we dont know if eax/ebx are equal or not (or 4-byte ranges intersects);

  then, it is just a memory reference for us,

  and we only know that it could be the same variable.

  Other properties, such as EIP, segment-, FPU-, MMX-, SSE-registers,

  are not considered here, since limited application of our theory.

  We just assume, that no one instruction (except maybe NOP) can be mixed with

  INT, RET, CALL, JMP, JXX, or FPU/MMX instructions.

  "Source object set" is a set of objects to be read.

  "Destination object set" is a set of objects to be written/modified.

  Any destination object supersedes source object.

  I mean that in "ADD EAX, EBX" instruction, EBX is source object,

  and EAX is both source and destination object,

  but we say that EAX is destination object only,

  and we never say that EAX is source;

  however, we always keep in mind that any destination object

  can be also (indirectly) source object.

  But, if we have "ADD ECX, ECX" instruction, we MUST include 2nd (src) ECX

  into source object set.

  Lets consider some typical instructions:

  INSTRUCTION             DESTINATION OBJECT SET        SOURCE OBJECT SET

  nop                     <none>                        <none>

  mov R1, R2              R1                            R2

  cmp R1, R2              flags                         R1, R2

  add R1, R1              R1, flags                     R1

  adc R1, R2              R1, flags                     R2, flags

  mov R1, [R2+R3]         R1                            R2, R3, memory

  add R1, [R2+R3]         R1, flags                     R2, R3, memory

  sub [R1+R2], R3         flags, memory                 R1, R2, R3

  test [R1+R2], R3        flags                         R1, R2, R3, memory

  inc R1                  R1, flags                     <none>

  lea R1, [R2+R3]         R1                            R1, R2

  xchg R1, [R2]           R1, memory                    R2

  push R1                 ESP, memory                   R1

  pop R1                  ESP, R1                       memory

  cld                     flags                         <none>

  lods                    ESI, EAX                      flags, memory

  rep lods                ESI, EAX, ECX, flags          flags, memory

  stos                    EDI, memory                   EAX, flags

  rep stos                EDI, ECX, memory, flags       EAX, flags

  rep cmps                ESI, EDI, ECX, memory, flags  memory

2.1. TWO instructions

  let they look as

  CMD1 DST1, SRC1

  CMD2 DST2, SRC2

  where DST1, SRC1, DST2, SRC2 are source/destination object sets.

  Any of these sets could be empty.

  We also assume that both instructions are already filtered/checked,

  i.e. no one of them is JMP, CALL, RET, etc.

  So, we have 4 sets, and we have 6 relations between

  each 2 of these sets. {C(4,2) = 4!/2!*(4-2)! = 6}

2.2. Simple conditions

  Each of six relations is bitwise AND operation on the two bitsets, returning

  logical ZERO or NON-ZERO. In other words, each two sets can intersect or not.

  #define INTERSECT(bitset_X, bitset_Y)  ((bitset_X & bitset_Y) != 0)

  Here is 3 conditions, when it is possible to swap two instructions:

   (DST1 & DST2) == 0                                                [1]

   (DST1 & SRC2) == 0                                                [2]

   (DST2 & SRC1) == 0                                                [3]

  Other 3 (unused) relations looks as following:

   (DST1 & SRC1) == whatever                                         [4]

   (DST2 & SRC2) == whatever                                         [5]

   (SRC1 & SRC2) == whatever                                         [6]

  Example:

  add eax, ebx          # cmd1=ADD  dst1={EAX,flags}  src1={EBX}

  sub ebx, ecx          # cmd2=SUB  dst2={EBX,flags}  src2={ECX}

  [1] == FALSE      {EAX,flags} intersects {EBX,flags}

  [2] == TRUE       {EAX,flags} doesnt intersects {ECX}

  [3] == FALSE      {EBX,flags} intersects {EBX}

  as such, these two instructions can not be swapped.

2.3. Advanced conditions

  There exists some advanced conditions, which requires more analysis.

  In such a cases, some of [1], [2], [3] conditions can be ignored.

  For example:

   (CMD1 == CMD2) && (DST1 == DST2) && [2] && [3]                    [7]

  or

   #define GROUP_1(cmd)  ((cmd == ADD) || (cmd == SUB))

   GROUP_1(CMD1) && GROUP_2(CMD2) && (DST1 == DST2) && [2] && [3]    [8]

  For example (below), [1] is FALSE, but since [8], the following

  instructions can be swapped:

  add eax, ecx

  sub eax, edx

  Now, imagine, that we have the following commands:

  mov [ebp+4], eax

  mov [ebp+8], ecx

  Such a situation should be handled in a special way;

  otherwise our theory will grow to contain lists of variables in the

  object sets; also this will require checking for intersection

  of memory ranges & etc.

  Except that all, we can ignore condition [1], in cases when instructions

  are followed by code which doesn't uses DST1 and DST2 object sets.

  But this will require much more analysis, and i think it is not optimal.

3. From single instruction to block of instructions

  Imagine that we have these instructions (following each other):

  [a] add eax, ecx

  [b] adc eax, edx

  [c] add ebx, ecx

  [d] adc ebx, edx

  [e] sub esi, edi

  We can not swap [a] and [b], and we can not swap [c] and [d].

  But we can swap [ab] and [cd].

  As such, we need some entity to replace consecutive instructions with.

4. ONE block of N instructions

  CMD1 DST1, SRC1

  CMDi DSTi, SRCi

  CMDN DSTN, SRCN

  If we will consider this block as a single instruction,

  how to calculate summary SUM_DST and SUM_SRC object sets?

  I.e. sets of objects which are read and written by that code block.

  Simplest way is to do BITWISE OR for all SRC/DST[i]; it is correct,

  but then the we will lose some possibilities in the future,

  as shown in the following example:

   mov eax, ebx

   add eax, ecx

   adc edx, eax

  here, SUM_SRC, if calculated as SRC1|SRC2|SRC3, is equal to

  EBX|ECX|EAX, however it is not necessary to include EAX into that set,

  since it is initialized inside of this block, but not passed into.

  So, algorithm of calculating SUM_SRC and SUM_DST is the following:

  SUM_SRC = 0

  SUM_DST = 0

  for(i = 0; i < N; i++)           # in the example shown above (N=3):

  {                                #       i =    0      1          2

    SUM_SRC |= SRC[i] & (~SUM_DST) # SUM_SRC =  {EBX}  {EBX,ECX}  {EBX,ECX}

    SUM_DST |= DST[i]              # SUM_DST =  {EAX}  {EAX}      {EAX,EDX}

  }

5. TWO BLOCKS

  Working with blocks is the same as working with single instructions,

  except that SUM_SRC and SUM_DST should be calculated, as it were

  shown above.

  You can swap two blocks, or block and single instruction, it doesn't matter.

6. How to find out object sets for some given instruction?

  Probably, using something like ADE32 and some additional analysis.

<eof>


少客联盟- 版权声明 1、本主题所有言论和图片纯属会员个人意见,与少客联盟立场无关。
2、本站所有主题由该帖子作者发表,该帖子作者admin少客联盟享有帖子相关版权。
3、少客联盟管理员和版主有权不事先通知发贴者而删除本文。
4、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者admin少客联盟的同意。
5、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任。
6、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责。
7、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意。
8、官方反馈邮箱:chinasuc@chinasuc.cn


上一篇:二进制代码的混淆策略研究
下一篇:Windows 10特定注册表项
Whatever is worth doing is worth doing well. juvenile hacker league
最新回复 (0)
    • 少客联盟
      2
        登录 注册 QQ登录(停用)
返回