恶意软件为了躲避杀毒软件的扫描会将一些敏感的字符或数据进行加密,来改变原有的样子(特征).下面是一个解密的反汇编和C代码:
...
;这个函数调用时有一个参数压入栈,另外还有两个寄存器的值被使用
;lea eax,[ebx-4] ebx 长度,从第五个字节开始处理
;lea edi,[esi+4] esi 数据起始地址,和上面对应
test al,3
jz short loc_40292c
xor eax,eax
jmp short loc_4029a1
loc_40292c:
lea eax,[edi+eax-4]
push 0fffffffch
pop esi
mov [ebp+var_C],eax
mov eax,edi
sub esi,edi
loc_40293a:
mov ebx,[eax]
lea ecx,[esi+eax+4]
and ecx,1fh
mov [ebp+var_8],ecx
and cl,4
mov [ebp+var_4],ebx
cmp cl,1
jnb short loc_40295b
push ecx
mov ecx,[ebp+var_8]
rol [ebp+var_4],cl ;循环左移 cl位
pop ecx
jmp short loc_402963
loc_40259b:
push ecx
mov ecx,[ebp+var_8]
ror [ebp+var_8],cl ;循环右移 cl位
pop ecx
loc_402963:
mov ebx,[ebp+arg_0]
mov ecx,[ebp+var_4]
xor ecx,ebx ;异或运算
not ecx ;非运算
add ecx,ebx
add ecx,[eax+4]
mov [eax],ecx
add eax,4
cmp eax,[ebp+var_c]
jb short loc_40293a
mov ecx,[eax]
add ecx,ebx
mov [ebp+arg_0],ecx
mov ecx,eax
sub ecx,edi
and ecx,1fh
mov [ebp+var_8],ecx
push ecx
mov ecx,[ebp+var_8]
rol [ebp_arg_0],cl
pop ecx
mov ecx,[ebp+arg_0]
not ecx
xor ecx,ebx
mov [eax],ecx
xor eax,eax
inc eax ;操作完毕,eax=1,成功
经过IDA F5 得到的伪代码,在家一下功的到的C代码(可能有一些出入:):
void Decryption(HGLOBAL a2,int a1,DWORD a3)
//a1是处理的数据长度,a3是后面运算的种子
{
DWORD v4; // eax@3
DWORD v5,v11; // esi@3
DWORD v8; // et0@8
DWORD v9; // [sp+8h] [bp-Ch]@3
int v10; // [sp+Ch] [bp-8h]@4
if ( a1 & 3 )
{
printf("数据长度不够!\n");
}
else
{
v9 =(DWORD)a2 + a1 - 4; //a9 最后4字节的起始地址
v4 =(DWORD)a2;
v5 = -4 -(DWORD)a2;
do //一个do-while结构来处理数据
{
v10 = (v5 + v4 + 4) & 0x1F;
//printf("%d ",v10);
v11 = *(DWORD *)v4;
if ((v10& 4u) >= 1 )
{
v11=(v11<<(32-v10))|(v11>>v10);
}
else
{
v11=(v11>>(32-v10))|(v11<<v10);
}
*(DWORD *)v4 = *(DWORD *)(v4 + 4) + a3 + ~(a3 ^ v11);
//printf("%x ",*(DWORD *)v4);
v4 += 4;
}while ( v4 < v9 );
v8 =a3 + *(DWORD *)v4;
//printf("%x ",v8);
v8=v8>>(32-((v4-(DWORD)a2)&0X1F))|(v8<<(v4-(DWORD)a2));
//printf("%x ",v8);
*(DWORD *)v4 = a3 ^ ~v8; //最后4个字节的数据单独处理
//printf("%x finished!n",*(DWORD *)v4);
}
总结:一般的加密就是对数据进行一些位运算,例如and (与),or(或),xor (异或),not(非),add/sub/mul等,还可能对不同的数据段进行分别对待。