//在 x 中查找 y, 查找成功索引,否则返回 -1
static DWORD _2find(DWORD x[], DWORD l, DWORD y)
{
  DWORD low, high, mid;

  low = 0;
  high = l - 1;
  while ( low <= high )
  {
    mid = (high + low) >> 1;
    if ( x[mid] == y )
      return mid;

    if ( y > x[mid] )
      low = mid + 1;
    else
      high = mid - 1;
  }

  return -1;
}


/*
CONTS PBYTE psrc 要抽代码的地方
PBYTE pdst 代码经过处理后存放的地方
DWORD Offset 被抽代码和存放代码之间偏移,注:不一定是 pdst - psrc, 有些难表达
int line 要抽的代码行数
返回第一条指令的位置
*/
//打乱原始指令序列
/*
DWORD StolenCode(CONST PBYTE psrc, PBYTE pdst, DWORD offset, DWORD line, PDWORD size)
{
  DWORD a[100], b[100], l[100];

  PBYTE p1, p2;
  DWORD i, j;

  j = 0;
  for ( i = 0; i < line; ++i )
  {
    a[i] = j;  //原始指令的原始偏移位置
    b[i] = (DWORD)-1;
    
    xde_instr instr;
    l[i] = xde_disasm(psrc + j, &instr); //获取指令长度
    if ( l[i] == 0 )
      break;

    j += l[i];
  }

  p2 = pdst;
  for ( j = 0; j < i; ++j ) //打乱指令顺序,然后用 jmp 指令串连起来
  {
    int k;
    do {
      k = rand() % i;
    } while ( b[k] != (DWORD)-1 );
    
    p1 = psrc + a[k];
    b[k] = p2 - pdst + 1;

    if ( *p1 == 0xEB ) { //把短跳转指令修改为长跳转指令
      p2 += 3; // 3 = 5 - l[k]
    }
    else if ( *p1 >= 0x70 && *p1 <= 0x7F ) {
      p2 += 4; // 4 = 6 - l[k]
    }
    else if ( *p1 == 0xE2 ) {
      p2 += 5; //5 = 7 - l[k]
    }
    else if ( *p1 == 0xE3 ) { //jcxz
      p2 += 6; //6 = 8 - l[k]
    }
    else if ( *p1 == 0xE0 || *p1 == 0xE1 ) {
      p2 += 7; //7 = 9 - l[k]
    }
    else {
      *p2++ = (BYTE)rand(); //junk
      memcpy(p2, p1, l[k]);
    }
    
    p2 += l[k] + 5;
  }
  *size = p2 - pdst; //变化后数据实际大小

  for ( j = 0; j < i; ++j ) //修正跳转
  {
    DWORD  w1 = l[j];
    DWORD  w2 = l[j];

    p1 = psrc + a[j];
    p2 = pdst + b[j];
    if ( *p1 == 0xEB || (*p1 >= 0x70 && *p1 <= 0x7F) || (*p1 >= 0xE0 && *p1 <= 0xE3) ) //8 位相对跳转
    {
      if ( *p1 == 0xEB )
      {
        w2 = 5; //修改模式后, 这条指令的长度
        *p2++ = 0xE9;
      }
      else if ( *p1 >= 0x70 && *p1 <= 0x7F )
      {
        w2 = 6;
        *p2++ = 0x0F;
        switch ( *p1 )
        {
        case 0x70: *p2 = 0x80; break;  //jo rel8    --> jo rel32
        case 0x71: *p2 = 0x81; break;  //jno rel8    --> jno rel32
        case 0x72: *p2 = 0x82; break;  //jnae rel8    --> jnae rel32
        case 0x73: *p2 = 0x83; break;  //jnb rel8    --> jnb rel32
        case 0x74: *p2 = 0x84; break;  //jz rel8    --> jz rel32
        case 0x75: *p2 = 0x85; break;  //jnz rel8    --> jnz rel32
        case 0x76: *p2 = 0x86; break;  //jna rel8    --> jna rel32
        case 0x77: *p2 = 0x87; break;  //jnbe rel8    --> jnbe rel32
        case 0x78: *p2 = 0x88; break;  //js rel8    --> js rel32
        case 0x79: *p2 = 0x89; break;  //jns rel8    --> jns rel32
        case 0x7A: *p2 = 0x8A; break;  //jp rel8    --> jp rel32
        case 0x7B: *p2 = 0x8B; break;  //jpo rel8    --> jpo rel32
        case 0x7C: *p2 = 0x8C; break;  //jnge rel8    --> jnge rel32
        case 0x7D: *p2 = 0x8D; break;  //jnl rel8    --> jnl rel32
        case 0x7E: *p2 = 0x8E; break;  //jng rel8    --> jng rel32
        case 0x7F: *p2 = 0x8F; break;  //jnle rel8    --> jnle rel32
        }

        ++p2;
      }
      else 
      {
        switch ( *p1 )
        {
        case 0xE0:
          //loopne --> 
          //$      jz    $ + 8
          //$ + 2    dec    ecx
          //$ + 3    jnz    xxxxxxxx
          //$ + 8    ????????????????
          *p2++ = 0x74; *p2++ = 0x07; *p2++ = 0x49; *p2++ = 0x0F; *p2++ = 0x85;
          w2 = 9;
          break;

        case 0xE1:
          //loope  -->
          //$      jnz    $ + 8
          //$ + 2    dec    ecx
          //$ + 3    jnz    xxxxxxxx
          //$ + 8    ????????????????
          *p2++ = 0x75; *p2++ = 0x07; *p2++ = 0x49; *p2++ = 0x0F; *p2++ = 0x85;
          w2 = 9;
          break;

        case 0xE2:
          //loop    -->
          //$      dec    ecx
          //$ + 1    jnz    xxxxxxxx
          *p2++ = 0x49; *p2++ = 0xF; *p2++ = 0x85;
          w2 = 7;
          break;

        case 0xE3:
          //jcxz    -->
          //$      test  ecx, ecx
          //$ + 2    jz    xxxxxxxx
          *p2++ = 0x85; *p2++ = 0xC9; *p2++ = 0x0F; *p2++ = 0x84;
          w2 = 8;
        }
      }

      DWORD k = _2find(a, i, a[j] + (char)p1[1] + l[j]);
      if ( (DWORD)-1 == k )
      {  //目标指令没有抽到
        DWORD z = offset + b[j] - a[j] + w2 - w1 - (char)p1[1];
        *(PDWORD &)p2 = 0 - z;
      }
      else {
        *(PDWORD &)p2 = b[k] - b[j] - w2;
      }
      p2 += sizeof (DWORD);
    }
    else if ( *p1 == 0xE9 || *p1 == 0xE8 || (*(PDWORD)p1 >= 0x800F && *(PDWORD)p1 <= 0x8F0F) ) //32 位相对跳转
    {
      DWORD k = _2find(a, i, a[j] + *(PDWORD)(p1 + 1) + l[j]);

      p2 += l[j] == 5 ? 1 : 2;
      if ( (DWORD)-1 == k ) 
      {
        DWORD z = offset + b[j] - a[j] - *(int*)(p1 + 1);
        *(PDWORD &)p2 = 0 - z;
      }
      else {
        *(PDWORD &)p2 = b[k] - b[j] - w1;
      }
      p2 += sizeof (DWORD);
    }
    else {
      p2 += l[j];
    }
    
    DWORD z = offset + b[j] - a[j] + 5 + w2 - w1;

    *p2++ = 0xE9;
    *((PDWORD &)p2)++ = j == i - 1 ? 0 - z : b[j + 1] - b[j] - w2 - 5; //修改 jmp 跳转
  }

  return b[0];
}