-
-
分析<这是什么加密算法>问题贴结果总结
-
发表于: 2016-1-4 15:01 7776
-
原问题贴的地址
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对数据解密了就可以了
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对数据解密了就可以了
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
赞赏
他的文章
- [翻译]一个简单虚拟机的逆向 9635
- [翻译]使用 IDAPython 写一个简单的x86模拟器 14426
- [翻译]通过x64分页机制的PTE Space实现内核漏洞利用 15280
- [翻译]Unicorn引擎教程 44589
- [翻译]首款反射式PE壳<琥珀>简介 18749
看原图
赞赏
雪币:
留言: