首页
社区
课程
招聘
分析<这是什么加密算法>问题贴结果总结
发表于: 2016-1-4 15:01 7775

分析<这是什么加密算法>问题贴结果总结

2016-1-4 15:01
7775
原问题贴的地址

http://bbs.pediy.com/showthread.php?p=1409880#post1409880

首先上结论,这个加密算法是RC6,下边是分析的过程,过程都在代码中,望指正

这段程序对数据的处理比较非常规

下边就是分析了

//参数4和参数3的位置不一样,形参_4就是加密和解密的key(根据下边的函数头猜的)
int __fastcall sub_10B845F(int 形参_1, unsigned int 形参_2, char* 形参_3, signed int 形参_4)
{
  signed int v4; // edi@1
  unsigned int v5; // eax@1
  char* v6; // edx@6
  int v7; // ebx@6
  int v8; // esi@6
  unsigned int v9; // edi@7
  int v10; // eax@8
  int v11; // ecx@8
  int v12; // eax@8
  int v13; // ecx@11
  int v14; // eax@11
  int v15; // esi@11
  char* v16; // edx@11
  int v17; // edi@21
  signed int v18; // ecx@21
  int v19; // esi@21
  int v20; // eax@23
  int v21; // ecx@23
  int result; // eax@25
  int v23; // eax@26
  int v24; // [sp+Ch] [bp-11Ch]@1
  int v25; // [sp+18h] [bp-110h]@6
  int v26; // [sp+18h] [bp-110h]@25
  int v27; // [sp+1Ch] [bp-10Ch]@6
  int v28; // [sp+1Ch] [bp-10Ch]@25
  unsigned int v29; // [sp+20h] [bp-108h]@1
  int v30; // [sp+20h] [bp-108h]@23
  short* v31; // [sp+24h] [bp-104h]@8
  int v32[63]; // [sp+28h] [bp-100h]@8 //缓冲区
  unsigned int v33; // [sp+124h] [bp-4h]@1
  int v34; // [sp+128h] [bp+0h]@1

  v33 = (unsigned int)&v34 ^ __security_cookie;
  v4 = 形参_4;
  v5 = 形参_2;//可能是长度
  v29 = 形参_2;//可能是长度
  v24 = 形参_1;
  if ( 形参_4 != 16 && 形参_4 != 12 )
  {
    if ( 形参_4 != 8 )
      v4 = 16;
    形参_4 = v4;
  }
  v6 = 形参_3;//相当于char* temp = 形参_3;
  v7 = 0;
  *(_DWORD *)形参_1 = v4;
  v8 = 0; //index
  v25 = 0;
  v27 = 0;
  //如果v5(形参_2)大于等于8则进入下边的循环
  if ( ((v5 - 8) & 0x80000000u) == 0 )
  {
    v9 = v5 >> 3;//v9 = v5 div 8(是8的多少倍)
    v27 = 8 * (v5 >> 3);//v27是形参_2最接近8的整倍数的一个数
    do
    {
      /*
          temp[8];
          前4字节赋值给v31
          第5字节赋值给v10
      */
      char
      v10 = *(_BYTE *)(v6 + 5);
      //*(&v31+v8)=*((int*)v6) 相当于把char*里的数据解释成int,说明v31是一个short*类型
      //因为v8每次只+2,要想数据不被覆盖就得使指针+2等同于地址+4,所以是short*
      *(&v31 + v8) = (*(_BYTE *)(v6 + 3) << 24) | (*(_BYTE *)(v6 + 2) << 16) | (*(_BYTE *)(v6 + 1) << 8) | *(_BYTE *)v6;
      
      //下边3句加上v10的那一句就做了一件事情,把剩下的4字节赋值给v32[index]
      v11 = (*(_BYTE *)(v6 + 6) << 16) | (v10 << 8) | *(_BYTE *)(v6 + 4);
      v12 = *(_BYTE *)(v6 + 7) << 24;
      v6 += 8;
      v32[v8] = v12 | v11;
      v8 += 2; //index
      --v9;
    }
    while ( v9 );
    /*
        上边的循环就做了一件事,把传进的参数赋值给v31所指向的地址
        所以密文必须是8的倍数
    */

    v4 = 形参_4;
    v5 = v29;//这句好像是废话,长度没变
    v25 = v8;  //上一个循环的+2计数器(长度)
  }
   
   //如果v5不是8的整倍数就进入if
  if ( v5 != v27 )
  {
    v13 = 0;
    v14 = v29 & 7; //v14 = 长度 % 8(看下比8多了多少个字节)
    v15 = 0;
    v16 = v14 + v6;//指针到数据尾
    switch ( v14 )
    {
      case 8:
        --v16;
        v13 = *(_BYTE *)v16 << 24;
        goto LABEL_13;
      case 7:
LABEL_13:
        --v16;
        v13 |= *(_BYTE *)v16 << 16;
        goto LABEL_14;
      case 6:
LABEL_14:
        --v16;
        v13 |= *(_BYTE *)v16 << 8;
        goto LABEL_15;
      case 5:
LABEL_15:
        --v16;
        v13 |= *(_BYTE *)v16;
        goto LABEL_16;
      case 4:
LABEL_16:
        --v16;
        v15 = *(_BYTE *)v16 << 24;
        goto LABEL_17;
      case 3:
LABEL_17:
        --v16;
        v15 |= *(_BYTE *)v16 << 16;
        goto LABEL_18;
      case 2:
LABEL_18:
        --v16;
        v15 |= *(_BYTE *)v16 << 8;
        goto LABEL_19;
      case 1:
LABEL_19:
        v15 |= *(_BYTE *)(v16 - 1);
        break;
      default:
        break;
    }
    *(&v31 + v25) = v15;
    v32[v25] = v13;
  }
/*
上边的switch case 也是按顺序复制到v31这个地址中去
*/

  v17 = 2 * v4 + 2;
  v18 = 1;
  v19 = (signed int)(v29 + 3) / 4; //这句话相当于 v19 是4的多少倍(余数进1,比如说长度为7则结果为2)
  for ( *(_DWORD *)(v24 + 4) = 0xB7E15163u; v18 < v17; ++v18 )
    *(_DWORD *)(v24 + 4 * v18 + 4) = *(_DWORD *)(v24 + 4 * v18) - 0x61C88647;
  //参数_1为指针int *ptr,ptr[1]=0xB7E15163
  //                     ptr[2]=ptr[1]-0x61c88647(0x5618CB1C--RC6常数中出现)
  //                     ptr[3]=[ptr2]-0x61C88647(0xF45044D5--结果已经很明显了,两个常数都出现在RC6常数表中)
  //                     这段代码就是为了隐藏RC6加密算法的常数表
  //                     然后找了一段算法看了一下,这个函数是RC6的初始化函数
  //                     参考文章在这里
  //                     http://code1.okbase.net/codefile/rc6.c_2012122018645_202.htm
  //                     //setup参数4和参数3的位置和这个函数不一样
  //                     //int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)

  v30 = 0;
  v20 = v19;
  v21 = 0;
  if ( v17 > v19 )
    v20 = v17;
  v28 = 3 * v20;
  result = 0;
  v26 = 0;
  if ( v28 > 0 )
  {
    do
    {
      v21 = __ROL__(*(_DWORD *)(v24 + 4 * result + 4) + v30 + v21, 3);
      *(_DWORD *)(v24 + 4 * result + 4) = v21;
      v23 = __ROL__(v21 + v30 + *(&v31 + v7), (v30 + (_BYTE)v21) & 0x1F);
      *(&v31 + v7) = v23;
      v30 = v23;
      result = v26 + 1;
      if ( v26 + 1 >= v17 )
        result = 0;
      ++v7;
      v26 = result;
      if ( v7 >= v19 )
        v7 = 0;
      --v28;
    }
    while ( v28 );
  }
  return result;
}

//下边就进入RC6加密了
unsigned int __fastcall sub_10B7C16(char* 形参_1, char* 形参_2, unsigned int 形参_3, int 形参_4, char* 形参_5, int a6)
{
  char* v6; // edi@1
  char* v7; // edx@1
  char* v8; // esi@2
  int v9; // ebx@2
  int v10; // ecx@2
  unsigned int v11; // eax@2
  int v12; // esi@3
  int v13; // ecx@4
  int v14; // ecx@4
  int v15; // eax@4
  unsigned int v16; // eax@4
  bool v17; // zf@4
  int v18; // ecx@7
  int v19; // edx@7
  int v20; // eax@7
  unsigned int v21; // eax@16
  unsigned int result; // eax@17
  int v23; // ebx@18
  int v24; // ecx@18
  int v25; // esi@18
  bool v26; // sf@18
  unsigned int v27; // eax@18
  int v28; // ebx@19
  int v29; // edi@20
  int v30; // esi@20
  int v31; // ecx@20
  int v32; // edx@20
  int v33; // eax@23
  int v34; // ecx@23
  int v35; // eax@23
  int v36; // eax@23
  int v37; // edx@23
  int v38; // ecx@23
  unsigned int v39; // edx@32
  unsigned int v40; // [sp+Ch] [bp-1Ch]@4
  int v41; // [sp+10h] [bp-18h]@4
  int v42; // [sp+14h] [bp-14h]@18
  unsigned int v43; // [sp+18h] [bp-10h]@7
  int v44; // [sp+1Ch] [bp-Ch]@2
  int v45; // [sp+20h] [bp-8h]@2
  int v46; // [sp+24h] [bp-4h]@5
  unsigned int v47; // [sp+30h] [bp+8h]@3
  int v48; // [sp+30h] [bp+8h]@7
  unsigned int v49; // [sp+30h] [bp+8h]@18
  int v50; // [sp+3Ch] [bp+14h]@18
  int v51; // [sp+3Ch] [bp+14h]@23

  v6 = 形参_2;//相当于char * temp1 = 形参_2
  v7 = 形参_1;//想当于char * temp2 = 形参_1
  if ( a6 )
  {
    v8 = 形参_5;

    //汗!! 又是这招,手工复制数据,作者的精力好旺盛啊
    //形参5好像是被加密数据
    v9 = (*(_BYTE *)(形参_5 + 3) << 24) | (*(_BYTE *)(形参_5 + 2) << 16) | (*(_BYTE *)(形参_5 + 1) << 8) | *(_BYTE *)形参_5;
    v10 = (*(_BYTE *)(形参_5 + 7) << 24) | (*(_BYTE *)(形参_5 + 6) << 16) | (*(_BYTE *)(形参_5 + 5) << 8) | *(_BYTE *)(形参_5 + 4);
    v11 = 形参_3 - 8;
    v44 = (*(_BYTE *)(形参_5 + 7) << 24) | (*(_BYTE *)(形参_5 + 6) << 16) | (*(_BYTE *)(形参_5 + 5) << 8) | *(_BYTE *)(形参_5 + 4);
    v45 = 形参_3 - 8;
   
    //形参_3大于等于8
    if ( ((形参_3 - 8) & 0x80000000u) == 0 )
    {
      v12 = v7;//保存指针
      v47 = 形参_3 >> 3;//长度 div 8
      v45 += -8 * v47;
      do
      {
        v13 = (*(_BYTE *)(v12 + 5) << 8) | *(_BYTE *)(v12 + 4);
        
        //注意看上边,v7=形参_1,v12=v7,如果没看错的话,这句相当于 v40=参数_1对应位置 ^ 参数_2对应位置
        v40 = v9 ^ ((*(_BYTE *)(v12 + 3) << 24) | (*(_BYTE *)(v12 + 2) << 16) | (*(_BYTE *)(v12 + 1) << 8) | *(_BYTE *)v12);
        v14 = (*(_BYTE *)(v12 + 6) << 16) | v13;
        v15 = *(_BYTE *)(v12 + 7) << 24;
        v12 += 8;
        //v41 = 参数_1对应位置 ^ 参数_2对应位置
        v41 = v44 ^ (v15 | v14);
        sub_10B809E(&v40, 形参_4);//这个子函数应该可能是解密子函数(猜得,可惜没代码,看不到)
        v9 = v40;
        v10 = v41;
        v16 = v40 >> 8;
        *(_BYTE *)v6 = v40;
        *(_BYTE *)(v6 + 1) = v16;
        *(_BYTE *)(v6 + 2) = (unsigned int)v9 >> 16;
        *(_BYTE *)(v6 + 3) = BYTE3(v9);
        *(_BYTE *)(v6 + 4) = v10;
        *(_BYTE *)(v6 + 5) = BYTE1(v10);
        *(_BYTE *)(v6 + 6) = (unsigned int)v10 >> 16;
        *(_BYTE *)(v6 + 7) = BYTE3(v10);
        v6 += 8;
        v17 = v47-- == 1;
        v44 = v10;
      }
      while ( !v17 );
      v11 = v45;

      v7 = v46;
      v46 = v12;
      v8 = 形参_5;
      
    }

    //不多说了,和上边的一样,补齐剩余数据,(这可能是个库......)
    //因为下边的处理手法和上边的一样的,所以就没有继续写了
    if ( v11 != -8 )
    {
      v18 = v7 + v11 + 8;
      v19 = 0;
      v43 = v45 + 7;
      v20 = 0;
      v48 = 0;
      switch ( v45 + 7 )
      {
        case 7:
          --v18;
          v19 = *(_BYTE *)v18 << 24;
          goto LABEL_9;
        case 6:
LABEL_9:
          --v18;
          v19 |= *(_BYTE *)v18 << 16;
          goto LABEL_10;
        case 5:
LABEL_10:
          --v18;
          v19 |= *(_BYTE *)v18 << 8;
          goto LABEL_11;
        case 4:
LABEL_11:
          --v18;
          v19 |= *(_BYTE *)v18;
          goto LABEL_12;
        case 3:
LABEL_12:
          --v18;
          v48 = *(_BYTE *)v18 << 24;
          goto LABEL_13;
        case 2:
LABEL_13:
          --v18;
          v48 |= *(_BYTE *)v18 << 16;
          goto LABEL_14;
        case 1:
LABEL_14:
          --v18;
          v48 |= *(_BYTE *)v18 << 8;
          goto LABEL_15;
        case 0:
LABEL_15:
          v20 = *(_BYTE *)(v18 - 1) | v48;
          break;
        default:
          break;
      }
      v41 = v44 ^ v19;
      v40 = v9 ^ v20;
      sub_10B809E(&v40, 形参_4);
      v9 = v40;
      v10 = v41;
      v21 = v40 >> 8;
      *(_BYTE *)v6 = v40;
      *(_BYTE *)(v6 + 1) = v21;
      v8 = 形参_5;
      *(_BYTE *)(v6 + 2) = (unsigned int)v9 >> 16;
      *(_BYTE *)(v6 + 3) = BYTE3(v9);
      *(_BYTE *)(v6 + 4) = v10;
      *(_BYTE *)(v6 + 5) = BYTE1(v10);
      *(_BYTE *)(v6 + 6) = (unsigned int)v10 >> 16;
      *(_BYTE *)(v6 + 7) = BYTE3(v10);
    }
    *(_BYTE *)v8 = v9;
    *(_BYTE *)(v8 + 1) = BYTE1(v9);
    *(_BYTE *)(v8 + 2) = (unsigned int)v9 >> 16;
    *(_BYTE *)(v8 + 3) = BYTE3(v9);
    *(_BYTE *)(v8 + 4) = v10;
    *(_BYTE *)(v8 + 5) = BYTE1(v10);
    result = (unsigned int)v10 >> 16;
    *(_BYTE *)(v8 + 6) = (unsigned int)v10 >> 16;
    *(_BYTE *)(v8 + 7) = BYTE3(v10);
  }
  else
  {
    v23 = 形参_5;
    v42 = 形参_5;
    v24 = (*(_BYTE *)(形参_5 + 3) << 24) | (*(_BYTE *)(形参_5 + 2) << 16) | (*(_BYTE *)(形参_5 + 1) << 8) | *(_BYTE *)形参_5;
    v50 = (*(_BYTE *)(形参_5 + 3) << 24) | (*(_BYTE *)(形参_5 + 2) << 16) | (*(_BYTE *)(形参_5 + 1) << 8) | *(_BYTE *)形参_5;
    v25 = (*(_BYTE *)(形参_5 + 7) << 24) | (*(_BYTE *)(形参_5 + 6) << 16) | (*(_BYTE *)(形参_5 + 5) << 8) | *(_BYTE *)(形参_5 + 4);
    v26 = ((形参_3 - 8) & 0x80000000u) != 0;
    v27 = 形参_3 - 8;
    v45 = (*(_BYTE *)(形参_5 + 7) << 24) | (*(_BYTE *)(形参_5 + 6) << 16) | (*(_BYTE *)(形参_5 + 5) << 8) | *(_BYTE *)(形参_5 + 4);
    v49 = 形参_3 - 8;
    if ( !v26 )
    {
      v28 = v6;
      v43 = (v27 + 8) >> 3;
      v49 += -8 * v43;
      do
      {
        v30 = (*(_BYTE *)(v7 + 5) << 8) | *(_BYTE *)(v7 + 4);
        v40 = (*(_BYTE *)(v7 + 3) << 24) | (*(_BYTE *)(v7 + 2) << 16) | (*(_BYTE *)(v7 + 1) << 8) | *(_BYTE *)v7;
        v29 = v40;
        v25 = (*(_BYTE *)(v7 + 7) << 24) | (*(_BYTE *)(v7 + 6) << 16) | v30;
        v46 = v7 + 8;
        v41 = v25;
        sub_10B82CE(&v40, 形参_4);//移位子函数,在原帖可以看到,
        v31 = v50 ^ v40;
        v32 = v45 ^ v41;
        *(_BYTE *)v28 = v50 ^ v40;
        *(_BYTE *)(v28 + 1) = BYTE1(v31);
        *(_BYTE *)(v28 + 2) = (unsigned int)v31 >> 16;
        *(_BYTE *)(v28 + 3) = BYTE3(v31);
        v24 = v29;
        *(_BYTE *)(v28 + 4) = v32;
        *(_BYTE *)(v28 + 5) = BYTE1(v32);
        *(_BYTE *)(v28 + 6) = (unsigned int)v32 >> 16;
        *(_BYTE *)(v28 + 7) = BYTE3(v32);
        v28 += 8;
        v17 = v43-- == 1;
        v7 = v46;
        v50 = v29;
        v45 = v25;
      }
      while ( !v17 );
      v27 = v49;
      v44 = v28;
      v23 = v42;
      v6 = v44;
    }
    if ( v27 == -8 )
    {
      v39 = v45;
    }
    else
    {
      v33 = *(_BYTE *)(v7 + 5);
      v42 = (*(_BYTE *)(v7 + 3) << 24) | (*(_BYTE *)(v7 + 2) << 16) | (*(_BYTE *)(v7 + 1) << 8) | *(_BYTE *)v7;
      v40 = v42;
      v34 = (v33 << 8) | *(_BYTE *)(v7 + 4);
      v35 = *(_BYTE *)(v7 + 6);
      v44 = v34;
      v44 = ((v35 | (*(_BYTE *)(v7 + 7) << 8)) << 16) | v34;
      v41 = v44;
      sub_10B82CE(&v40, 形参_4); //这是一个移位字函数
      v36 = v25 ^ v41;
      v37 = v50 ^ v40;
      v51 = v25 ^ v41;
      v38 = v6 + v49 + 8;
      switch ( v49 + 7 )
      {
        case 7u:
          --v38;
          *(_BYTE *)v38 = BYTE3(v36);
          v36 = v51;
          goto LABEL_25;
        case 6u:
LABEL_25:
          --v38;
          *(_BYTE *)v38 = (unsigned int)v36 >> 16;
          BYTE1(v36) = BYTE1(v51);
          goto LABEL_26;
        case 5u:
LABEL_26:
          --v38;
          *(_BYTE *)v38 = BYTE1(v36);
          LOBYTE(v36) = v51;
          goto LABEL_27;
        case 4u:
LABEL_27:
          --v38;
          *(_BYTE *)v38 = v36;
          goto LABEL_28;
        case 3u:
LABEL_28:
          --v38;
          *(_BYTE *)v38 = BYTE3(v37);
          goto LABEL_29;
        case 2u:
LABEL_29:
          --v38;
          *(_BYTE *)v38 = (unsigned int)v37 >> 16;
          goto LABEL_30;
        case 1u:
LABEL_30:
          --v38;
          *(_BYTE *)v38 = BYTE1(v37);
          goto LABEL_31;
        case 0u:
LABEL_31:
          *(_BYTE *)(v38 - 1) = v37;
          break;
        default:
          break;
      }
      v24 = v42;
      v39 = v44;
    }
    *(_BYTE *)v23 = v24;
    *(_BYTE *)(v23 + 1) = BYTE1(v24);
    *(_BYTE *)(v23 + 2) = (unsigned int)v24 >> 16;
    *(_BYTE *)(v23 + 3) = BYTE3(v24);
    *(_BYTE *)(v23 + 4) = v39;
    *(_BYTE *)(v23 + 5) = BYTE1(v39);
    result = v39 >> 16;
    *(_BYTE *)(v23 + 6) = v39 >> 16;
    *(_BYTE *)(v23 + 7) = BYTE3(v39);
  }
  return result;
}

这是问题贴,我分析的过程都在注释中,如果要解密的话,就要在sub_10B845F这里下断得到key然后使用RC6对数据解密了就可以了

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 3366
活跃值: (1353)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
2
楼主的耐心真是值得敬佩啊 表示没看完直接翻到底部了233
2016-2-21 23:19
0
游客
登录 | 注册 方可回帖
返回
//