病毒常用方法之加密

恶意软件为了躲避杀毒软件的扫描会将一些敏感的字符或数据进行加密,来改变原有的样子(特征).下面是一个解密的反汇编和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等,还可能对不同的数据段进行分别对待。

展开阅读全文

没有更多推荐了,返回首页