samedi 8 juin 2019

L'emblématique hash 0x6A4ABC5B


I.    Introduction

Vous trouverez plusieurs sites ou ce hash est utilisé dans différents shellcode ou Malware comme Zeus.

Rentrons dans le vif du sujet, il représente la chaîne unicode de "KERNEL.DLL".
Pour bien représenté celle-ci est pour nos explications, vous trouvez en en dessous une représentation en mémoire de la chaîne unicode.



L'algorithme utilisé est un Ror13 Additive Uppercase pour le calcule du hash. De plus l'algorithme à une particularité, il ce base pas sur un arrêt du calcule sur la fin de chaîne.
Mais reçoit le nombre d'octet à prendre en compte pour le calcule du hash.
Ce qui fait que l'on peut avoir différente valeur de hash fonction du nombre d'octet choisit
au lieu de prendre toute la chaîne on peut prendre X caractéres.

II.    Utilisation dans la pratique 


Pour notre description de ce hash, nous somme partie d'un fichier assembleur effectuant un simple WinExec("calc.exe"), mais utilisant ce hash pour effectuer la recherche de HMODULE de kernel32.dll qui est assez répandu comme utilisation de ce hash dans beaucoups de lien.

Nous mettons le listing de notre fichier "WinExecCalcV1.asm" utilisé pour notre étude.


[SECTION .text]

BITS 32

global _start

_start:

    jmp start_asm

GetKernel32Base:
        cld                                      ; // clear the direction flag for the loop
        xor edx, edx                       ; // zero edx
        mov edx, [fs:edx+0x30 ]   ; // get a pointer to the PEB
        mov edx, [ edx+0x0C ]     ; // get PEB->Ldr
        mov edx, [ edx+0x14 ]     ; // get the first module from the InMemoryOrder module list
    next_mod:
        mov esi, [ edx+0x28 ]       ; // get pointer to modules name (unicode string)
        mov ecx, 24                       ; // set ecx to this length for the loop
        xor edi, edi                         ; // clear edi which will store the hash of the module name
    loop_modname:
        xor eax, eax                        ; // clear eax
        lodsb                                   ; // read in the next byte of the name
        cmp al, 'a'                           ; // some versions of Windows use lower case module names
        jl not_lowercase
        sub al, 0x20                        ; // if so normalise to uppercase
    not_lowercase:
        ror edi, 13                           ; // rotate left our hash value
        add edi, eax                         ; // add the next byte of the name
        loop loop_modname           ; // loop untill we have read enough
        cmp edi, 0x6A4ABC5B      ; // compare the hash with that of KERNEL32.DLL
        mov ebx, [ edx+0x10 ]        ; // get this modules base address
        mov edx, [ edx ]                   ; // get the next module
        jne next_mod
    ret

find_function:
    pushad
    mov ebp, [esp + 0x24]
    mov eax, [ebp + 0x3c]
    mov edx, [ebp + eax + 0x78]
    add edx, ebp
    mov ecx, [edx + 0x18]
    mov ebx, [edx + 0x20]
    add ebx, ebp
find_function_loop:
    jecxz find_function_finished
    dec ecx
    mov esi, [ebx + ecx * 4]
    add esi, ebp ; esi now points to current function string
     ; start of compute hash function
compute_hash: ; put this into a function
    xor edi, edi ; edi will hold our hash result
    xor eax, eax ; eax holds our current char
    cld
compute_hash_again:
    lodsb ; puts current char into eax (except first time)
    test al, al ; checks for null - end of function string
    jz compute_hash_finished
    ror edi, 0xd ; rotate the current hash
    add edi, eax ; adds current char to current hash
    jmp compute_hash_again
compute_hash_finished: ; end of compute hash function
find_function_compare:
    ;this is where it compares the calculated hash to our hash
    cmp edi, [esp + 0x28]
    jnz find_function_loop
    mov ebx, [edx + 0x24]
    add ebx, ebp
    mov cx, [ebx + 2 * ecx]
    mov ebx, [edx + 0x1c]
    add ebx, ebp
    mov eax, [ebx + 4 * ecx]
    add eax, ebp
    ;this is the VMA of the function
    mov [esp + 0x1c], eax
find_function_finished:
    popad
    ret
  
resolve_symbols_for_dll:
    ;about to load current hash into eax (pointed to by esi)
    lodsd
    push eax
    push edx
    call find_function
    mov [edi], eax
    add esp, 0x08
    add edi, 0x04
    cmp esi, ecx
    jne resolve_symbols_for_dll
resolve_symbols_for_dll_finished:
    ret

start_asm: ; start our main program

    sub esp, 0x08 ; allocate space on stack for function addresses
    mov ebp, esp ; set ebp as frame ptr for relative offset on stack

    call GetKernel32Base ;find address of Kernel32.dll
    mov edx, ebx

    ;resolve kernel32 symbols
    jmp short locate_hashes ;locate address of our hashes
locate_hashes_return: ;define return label to return to this code
    pop esi ;get constants address from stack
    lea edi, [ebp + 0x04] ;this is where we store our function addresses
    mov ecx, esi
    add ecx, 0x08 ;length of dns shellcode hash list
    call resolve_symbols_for_dll

    jmp short GetCommand
CommandReturn:
    pop ebx ;ebx now holds the handle to the string

    xor eax,eax ;empties out eax
    push eax ;push null onto stack as empty parameter value
    push ebx ;push the command onto the stack
    call [ebp+4] ;call WinExec(path,showcode)

    xor eax,eax ;zero the register again, clears winexec retval
    push eax ;push null onto stack as empty parameter value
    call [ebp+8] ;call ExitProcess(0);

locate_hashes:
    call locate_hashes_return

    ;WinExec ;result hash = 0x98FE8A0E
    db 0x98
    db 0xFE
    db 0x8A
    db 0x0E

    ;ExitProcess ;result hash = 0x7ED8E273
    db 0x7E
    db 0xD8
    db 0xE2
    db 0x73

GetCommand:
    call CommandReturn
    db "calc.exe"
    db 0x00

Pour le compiler, vous pouvez utiliser "NASM", vous trouvez cette assembleur à l'url suivant: https://www.nasm.us/

En suite vous avez plus qu'a compiler le fichier .asm avec une ligne de commande suivant:

C:\NASM\nasm.exe -f bin C:\Asm\WinExecCalcV1.asm -o C:\Asm\WinExecCalcV1.bin

Dans notre cas, nous allons utilisé un de nos anciens programme de notre tools permettant de faire cela via un interface graphique windows et il nous suffit de cliquer sur "Compile(bin)" pour obtenir la compilation. Cela est assez pratique quand on veut modifier rapidement quelques ligne du fichier et pas avoir à taper n commande pour générer des exécutables



Suite à cela nous n'avons plus qu'a cliquer sur le button "Obj/Bin", pour avoir les opcodes générés

 
 
Nous remontons en dessous le listing obtenu

\xE9\x98\x00\x00\x00\xFC\x31\xD2\x64\x8B\x52\x30\x8B\x52\x0C\x8B
\x52\x14\x8B\x72\x28\xB9\x18\x00\x00\x00\x31\xFF\x31\xC0\xAC\x3C
\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2\xF0\x81\xFF\x5B\xBC
\x4A\x6A\x8B\x5A\x10\x8B\x12\x75\xD9\xC3\x60\x8B\x6C\x24\x24\x8B
\x45\x3C\x8B\x54\x05\x78\x01\xEA\x8B\x4A\x18\x8B\x5A\x20\x01\xEB
\xE3\x34\x49\x8B\x34\x8B\x01\xEE\x31\xFF\x31\xC0\xFC\xAC\x84\xC0
\x74\x07\xC1\xCF\x0D\x01\xC7\xEB\xF4\x3B\x7C\x24\x28\x75\xE1\x8B
\x5A\x24\x01\xEB\x66\x8B\x0C\x4B\x8B\x5A\x1C\x01\xEB\x8B\x04\x8B
\x01\xE8\x89\x44\x24\x1C\x61\xC3\xAD\x50\x52\xE8\xAA\xFF\xFF\xFF
\x89\x07\x83\xC4\x08\x83\xC7\x04\x39\xCE\x75\xEC\xC3\x83\xEC\x08
\x89\xE5\xE8\x5E\xFF\xFF\xFF\x89\xDA\xEB\x1E\x5E\x8D\x7D\x04\x89
\xF1\x83\xC1\x08\xE8\xCF\xFF\xFF\xFF\xEB\x1B\x5B\x31\xC0\x50\x53
\xFF\x55\x04\x31\xC0\x50\xFF\x55\x08\xE8\xDD\xFF\xFF\xFF\x98\xFE
\x8A\x0E\x7E\xD8\xE2\x73\xE8\xE0\xFF\xFF\xFF\x63\x61\x6C\x63\x2E
\x65\x78\x65\x00

Nous gardons cela de côté pour la suite, revenons à la partie qui nous intéresse le calcul du hash. Nous avons mis en rouge la fonction GetKernel32Base qui exploite ce hash.

Regardons la partie qui correspond au calcule du hash en dessous extrait de la fonction GetKernel32Base

        mov ecx, 24                       ; // set ecx to this length for the loop
        xor edi, edi                         ; // clear edi which will store the hash of the module name
    loop_modname:
        xor eax, eax                        ; // clear eax
        lodsb                                   ; // read in the next byte of the name
        cmp al, 'a'                           ; // some versions of Windows use lower case module names
        jl not_lowercase
        sub al, 0x20                        ; // if so normalise to uppercase
    not_lowercase:
        ror edi, 13                           ; // rotate left our hash value
        add edi, eax                         ; // add the next byte of the name
        loop loop_modname           ; // loop untill we have read enough
        cmp edi, 0x6A4ABC5B      ; // compare the hash with that of KERNEL32.DLL

Il y a utilisation du registre ECX pour fixer le nombre d'octet à prendre pour le calcule du hash.

On peut à partir de la écrire une fonction C , effectuant le même traitement

DWORD CalculatehashRor13AdditiveUppercaseAndFixedLength(char*pData,DWORD dwLength)
{
    DWORD dwHash =0x0;

    for(int i=0;i<dwLength;i++)
            {
        dwHash = (dwHash >> 13) | (dwHash << (32 - 13));   // ROR dwHash , 13
        dwHash += *pData >= 'a' ? *pData - 32 : *pData;    // Convert the character to uppercase
        pData++;
    }

    return dwHash;
}

On avait implémenté cela dans un petit programme pour valider notre calculateur de se hash
Il y a quelque années






















 
Nous avons bien le mode Uppercase, comme vous pouvez le constater, nous avons écrit "KeRnel32.dLL" et fixer la taille à 24 octets pour le calcule du hash de la chaîne Unicode.

Revenons à notre exemple au dessus, nous avons référencé cette fonction "GetKernel32Base" dans notre outils " GetProcessTEBorPEB.exe", listant les références de la fonction GetKernel32 par PEB, trouvez lors de nos différentes étude de shellcode

Cette Fonction est référencé sous le numéro 38 



 
Ce qui correspond en assembleur à cela avec les opcodes

00000000:   53                                       PUSH EBX
00000001:   56                                       PUSH ESI
00000002:   57                                       PUSH EDI
00000003:   FC                                      CLD        // Clear Direction Flag
00000004:   31 D2                                 XOR EDX,EDX
00000006:   64 8B 52 30                       MOV EDX,DWORD PTR FS:[EDX+0x30]
0000000A:   8B 52 0C                           MOV EDX,DWORD PTR[EDX+0x0C]
0000000D:   8B 52 14                            MOV EDX,DWORD PTR[EDX+0x14]
00000010:   8B 72 28                            MOV ESI,DWORD PTR[EDX+0x28]
00000013:   B9 18 00 00 00                  MOV ECX, 00000018h ""
00000018:   31 FF                                  XOR EDI,EDI
0000001A:   31 C0                                 XOR EAX,EAX
0000001C:   AC                                     LODS BYTE PTR DS:[ESI]
0000001D:   3C 61                                 CMP AL,0x61 ('a')
0000001F:   7C 02                                 JL 02h (rel8)(+02h ->:00000023)
00000021:   2C 20                                 SUB AL,20h
00000023:   C1 CF 0D                           ROR EDI,0Dh (13)
00000026:   01 C7                                 ADD EDI,EAX
00000028:   E2 F0                                 LOOP F0h (-FFFFFFF0h=>:0000001A) Dec ECX or CX jump if !=0
0000002A:   81 FF 5B BC 4A 6A           CMP EDI,6A4ABC5Bh
                                                               (6A4ABC5B=Hash[ROR13(Additive)/FixedLenght](Unicode >'KERNEL32.DLL',24))
00000030:   8B 5A 10                            MOV EBX,DWORD PTR [EDX+10h]
00000033:   8B 12                                 MOV EDX,DWORD PTR [EDX]
00000035:   75 D9                                 JNZ D9h (rel8)(-27h ->:00000010)
00000037:   8B C3                                 MOV EAX,EBX
00000039:   5F                                       POP EDI
0000003A:   5E                                      POP ESI
0000003B:   5B                                      POP EBX
0000003C:   C3                                      RET


Il ne nous reste plus qu' à vérifier si notre shellcode générer via NASM est bien transcrit pas notre outil d'analyse de shellcode X32. Pour cela nous avons juste à positionner le shellcode et basculer en mode "Diagram".



 
Nous mettons le listing correspondant en dessous:

00000000:   E9 98 00 00 00            JMP 00000098h (+98h ->:0000009D)
00000005 -> 00000038:  =>{BLOC}[AsmGetKernel32_V38 -> EBX]
00000039:   C3                                   RET
0000003A -> 00000087:  => DWORD __declspec(naked) GetProcAddressByHashRor13AdditiveV3(HMODULE hMod,DWORD dwHash)
00000088:   AD                                   LODSD (Loads DS:[SI](ESI for LODSD) val into AL,AX,EAX and inc SI)
00000089:   50                                   PUSH EAX
0000008A:   52                                   PUSH EDX
0000008B:   E8 AA FF FF FF            CALL FFFFFFAAh (-56h ->:0000003A)
00000090:   89 07                              MOV DWORD PTR[EDI],EAX
00000092:   83 C4 08                       ADD ESP,08h
00000095:   83 C7 04                       ADD EDI,04h
00000098:   39 CE                             CMP ESI,ECX
0000009A:   75 EC                             JNZ ECh (rel8)(-14h ->:00000088)
0000009C:   C3                                  RET
0000009D:   83 EC 08                      SUB ESP,08h (On alloue l'espace de 8 octets sur la stack)
000000A0:   89 E5                             MOV EBP,ESP
000000A2:   E8 5E FF FF FF            CALL FFFFFF5Eh (-A2h ->:00000005)
000000A7:   89 DA                             MOV EDX,EBX
000000A9:   EB 1E                             JMP 1Eh +1Eh ->:000000C9)
000000AB:   5E                                   POP ESI
000000AC:   8D 7D 04                      LEA EDI,[EBP+04h]
000000AF:   89 F1                              MOV ECX,ESI
000000B1:   83 C1 08                       ADD ECX,08h
000000B4:   E8 CF FF FF FF           CALL FFFFFFCFh (-31h ->:00000088)
000000B9:   EB 1B                            JMP 1Bh +1Bh ->:000000D6)
000000BB:   5B                                  POP EBX
000000BC:   31 C0                            XOR EAX,EAX
000000BE:   50                                   PUSH EAX
000000BF:   53                                   PUSH EBX
000000C0:   FF 55 04                       CALL DWORD PTR [EBP+04h]
000000C3:   31 C0                            XOR EAX,EAX
000000C5:   50                                   PUSH EAX
000000C6:   FF 55 08                       CALL DWORD PTR [EBP+08h]
000000C9:   E8 DD FF FF FF          CALL FFFFFFDDh (-23h ->:000000AB)
                                                               db (0E8AFE98=Hash[ROR13(Additive)]('WinExec'))
000000CE:  98 FE 8A 0E
                                                               db (73E2D87E=Hash[ROR13(Additive)]('ExitProcess'))
000000D2:  7E D8 E2 73
000000D6:   E8 E0 FF FF FF           CALL FFFFFFE0h (-20h ->:000000BB)
000000DB -> 000000E3:  db    'calc.exe',00h

Maintenant, nous allons chercher quelques autres exemples via internet au travers de la séquence suivant "\x81\xFF\x5B\xBC\x4A\x6A\x"

Nous arrivons sur plusieurs référence de shellcode, dont celui-ci:

http://ddecode.com/hexdecoder/?results=b22a5424479b1d0bf59c5cc59a056e61

Nous vous remettons en dessous le shellcode correspondant

"\xFC\x33\xD2\xB2\x30\x64\xFF\x32\x5A\x8B\x52\x0C\x8B\x52\x14\x8B\x72\x28\x33\xC9"
"\xB1\x18\x33\xFF\x33\xC0\xAC\x3C\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x03\xF8\xE2\xF0"
"\x81\xFF\x5B\xBC\x4A\x6A\x8B\x5A\x10\x8B\x12\x75\xDA\x8B\x53\x3C\x03\xD3\xFF\x72"
"\x34\x8B\x52\x78\x03\xD3\x8B\x72\x20\x03\xF3\x33\xC9\x41\xAD\x03\xC3\x81\x38\x47"
"\x65\x74\x50\x75\xF4\x81\x78\x04\x72\x6F\x63\x41\x75\xEB\x81\x78\x08\x64\x64\x72"
"\x65\x75\xE2\x49\x8B\x72\x24\x03\xF3\x66\x8B\x0C\x4E\x8B\x72\x1C\x03\xF3\x8B\x14"
"\x8E\x03\xD3\x52\x68\x78\x65\x63\x01\xFE\x4C\x24\x03\x68\x57\x69\x6E\x45\x54\x53"
"\xFF\xD2\x68\x63\x6D\x64\x01\xFE\x4C\x24\x03\x6A\x05\x33\xC9\x8D\x4C\x24\x04\x51"
"\xFF\xD0\x68\x65\x73\x73\x01\x8B\xDF\xFE\x4C\x24\x03\x68\x50\x72\x6F\x63\x68\x45"
"\x78\x69\x74\x54\xFF\x74\x24\x20\xFF\x54\x24\x20\x57\xFF\xD0"

Si nous passons ce shellcode dans notre outils, nous obtiendrons le code assembleur.
Comme vous pouvez le voir dans la capture en dessous:




 
Nous retrouvons bien le partie de recherche du hModule de Kernel32.dll. Mais il y a plus intéressant, nous avons mis en rouge une partie correspondant à une fonction que vous trouverez dans plusieurs shellcode lors de vos recherche sur le hash 0x6A4ABC5B

Nous remettons le listing obtenu avec notre outils.


00000000:   FC                                   CLD       // Clear Direction Flag
00000001:   33 D2                             XOR EDX,EDX
00000003:   B2 30                             MOV DL,30h
00000005:   64 FF 32                        PUSH DWORD PTR FS:[EDX]
00000008:   5A                                   POP EDX
00000009:   8B 52 0C                       MOV EDX,DWORD PTR[EDX+0x0C]
0000000C:   8B 52 14                       MOV EDX,DWORD PTR[EDX+0x14]
0000000F:   8B 72 28                        MOV ESI,DWORD PTR[EDX+0x28]
00000012:   33 C9                             XOR ECX,ECX
00000014:   B1 18                             MOV CL,0x18
00000016:   33 FF                              XOR EDI,EDI
00000018:   33 C0                             XOR EAX,EAX
0000001A:   AC                                   LODS BYTE PTR DS:[ESI]
0000001B:   3C 61                             CMP AL,0x61 ('a')
0000001D:   7C 02                            JL 02h (rel8)(+02h ->:00000021)
0000001F:   2C 20                             SUB AL,20h
00000021:   C1 CF 0D                      ROR EDI,0Dh (13)
00000024:   03 F8                              ADD EDI,EAX
00000026:   E2 F0                             LOOP F0h (-FFFFFFF0h=>:00000018) Dec ECX or CX jump if !=0
00000028:   81 FF 5B BC 4A 6A      CMP EDI,6A4ABC5Bh (6A4ABC5B=Hash[ROR13(Additive)/FixedLenght](Unicode >'KERNEL32.DLL',24))
0000002E:   8B 5A 10                       MOV EBX,DWORD PTR [EDX+10h]
00000031:   8B 12                             MOV EDX,DWORD PTR [EDX]
00000033:   75 DA                             JNZ DAh (rel8)(-26h ->:0000000F)
00000035:   8B 53 3C                       MOV EDX,DWORD PTR[EBX+0x3C]
00000038:   03 D3                             ADD EDX,EBX
0000003A:   FF 72 34                        PUSH DWORD PTR[EDX+0x34]
0000003D:   8B 52 78                       MOV EDX,DWORD PTR[EDX+0x78]
00000040:   03 D3                             ADD EDX,EBX
00000042:   8B 72 20                        MOV ESI,DWORD PTR[EDX+0x20]
00000045:   03 F3                              ADD ESI,EBX
00000047:   33 C9                             XOR ECX,ECX
00000049:   41                                   INC ECX
0000004A:   AD                                   LODSD (Loads DS:[SI](ESI for LODSD) val into AL,AX,EAX and inc SI)
0000004B:   03 C3                             ADD EAX,EBX
0000004D:   81 38 47 65 74 50      CMP DWORD PTR[EAX],50746547h ('PteG' => GetP)
00000053:   75 F4                              JNZ F4h (rel8)(-0Ch ->:00000049)
00000055:   81 78 04 72 6F 63 41 CMP DWORD PTR[EAX+0x04],0x41636F72 "rocA"
0000005C:   75 EB                            JNZ EBh (rel8)(-15h ->:00000049)
0000005E:   81 78 08 64 64 72 65 CMP DWORD PTR[EAX+0x08],0x65726464 "ddre"
00000065:   75 E2                             JNZ E2h (rel8)(-1Eh ->:00000049)
00000067:   49                                   DEC ECX
00000068:   8B 72 24                        MOV ESI,DWORD PTR[EDX+0x24]
0000006B:   03 F3                             ADD ESI,EBX
0000006D:   66 8B 0C 4E                MOV CX,WORD PTR[ESI+ECX*2]
00000071:   8B 72 1C                       MOV ESI,DWORD PTR[EDX+0x1C]
00000074:   03 F3                              ADD ESI,EBX
00000076:   8B 14 8E                       MOV EDX,DWORD PTR [ESI+ECX*4]
00000079:   03 D3                             ADD EDX,EBX
0000007B:   52                                   PUSH EDX
0000007C:   68 78 65 63 01            PUSH 01636578h "xec" dw:23291256 / {120 101 99 1} / < w:25345 | w:30821 >
00000081:   FE 4C 24 03                 DEC BYTE PTR [ESP+0x03h]
00000085:   68 57 69 6E 45            PUSH 456E6957h "WinE" dw:1164863831 / {87 105 110 69} / < w:28229 | w:22377 >
0000008A:   54                                   PUSH ESP
0000008B:   53                                   PUSH EBX
0000008C:   FF D2                            CALL EDX
0000008E:   68 63 6D 64 01            PUSH 01646D63h "cmd" dw:23358819 / {99 109 100 1} / < w:25601 | w:25453 >
00000093:   FE 4C 24 03                 DEC BYTE PTR [ESP+0x03h]
00000097:   6A 05                              PUSH 05h (5) ''
00000099:   33 C9                             XOR ECX,ECX
0000009B:   8D 4C 24 04                 LEA ECX,[ESP+0x04]
0000009F:   51                                   PUSH ECX
000000A0:   FF D0                             CALL EAX
000000A2:   68 65 73 73 01             PUSH 01737365h "ess" dw:24343397 / {101 115 115 1} / < w:29441 | w:25971 >
000000A7:   8B DF                             MOV EBX,EDI
000000A9:   FE 4C 24 03                 DEC BYTE PTR [ESP+0x03h]
000000AD:   68 50 72 6F 63            PUSH 636F7250h "Proc" ( 636F7250 = ('corP') => PILE:Proc )
000000B2:   68 45 78 69 74            PUSH 74697845h "Exit" ( 74697845 = ('tixE') => PILE:Exit )
000000B7:   54                                   PUSH ESP
000000B8:   FF 74 24 20                  PUSH DWORD PTR [ESP+20h]
000000BC:   FF 54 24 20                 CALL DWORD [ESP+20h]
000000C0:   57                                   PUSH EDI
000000C1:   FF D0                            CALL EAX

Ce bloc représente une fonction qui permet d'avoir deux adresses lors de son appel qui sont l'adresse du module kernel32 et l'adresse de l'api GetProcAddress.

Nous avions écrit une fonction C pour tester cela il y a un certain temps. Nous remettons en dessous la fonction.

void GetAddressOfKernel32AndApiGetProcAddressV1(DWORD* pKernel32,DWORD* pApiGetProcAddress)
{
                __asm
                {
                               CLD
                               XOR EDX,EDX
                               MOV DL,0x30
                               PUSH DWORD PTR FS:[EDX]
                               POP EDX
                               MOV EDX,DWORD PTR[EDX+0x0C]
                               MOV EDX,DWORD PTR[EDX+0x14]
saut3:
                               MOV ESI,DWORD PTR[EDX+0x28]
                               XOR ECX,ECX
                               MOV CL,0x18
                               XOR EDI,EDI
saut2:
                               XOR EAX,EAX
                               LODS BYTE PTR DS:[ESI]
                               CMP AL,0x61
                              JL saut1
                               SUB AL,0x20
saut1:
                               ROR EDI,0x0D
                               ADD EDI,EAX
                               LOOP saut2
                               CMP EDI,0x6A4ABC5B
                               MOV EBX,DWORD PTR [EDX+0x10]
                               MOV EDX,DWORD PTR [EDX]
                               JNZ saut3
                               MOV EDX,DWORD PTR[EBX+0x3C]
                               ADD EDX,EBX
                                               PUSH DWORD PTR[EDX+0x34]
                               MOV EDX,DWORD PTR[EDX+0x78]
                               ADD EDX,EBX
                               MOV ESI,DWORD PTR[EDX+0x20]
                               ADD ESI,EBX
                               XOR ECX,ECX                    
saut4:
                               INC ECX
                               LODSD
                               ADD EAX,EBX
                               CMP DWORD PTR[EAX],0x50746547
                               JNZ saut4
                               CMP DWORD PTR[EAX+0x04],0x41636F72
                               JNZ saut4
                               CMP DWORD PTR[EAX+0x08],0x65726464
                               JNZ saut4            
                               DEC ECX
                               MOV ESI,DWORD PTR[EDX+0x24]
                               ADD ESI,EBX
                               MOV CX,WORD PTR[ESI+ECX*2]
                               MOV ESI,DWORD PTR[EDX+0x1C]
                               ADD ESI,EBX
                               MOV EDX,DWORD PTR [ESI+ECX*4]
                               ADD EDX,EBX

                               POP EAX     // équilibrage de la pile lié

                               MOV         EAX,DWORD PTR[pKernel32]
                               MOV         DWORD PTR[EAX],EBX

                               MOV         EAX,DWORD PTR[pApiGetProcAddress]
                               MOV         DWORD PTR[EAX],EDX
                }
}

Nous avons un testeur de cette fonction , nous mettons une capture écran associer























 

Comme cette signature de bloc est incluse dans notre outil d'analyse de shellcode X32



 
Nous mettons en dessous le listing obtenu

00000000 -> 0000007A:  =>{BLOC}[GetAddressOfKernel32AndApiGetProcAddressV1-> EBX:Kernel32 / EDX:Addr Api GetProcAddress]
0000007B:   52                                   PUSH EDX
0000007C:   68 78 65 63 01            PUSH 01636578h "xec"
00000081:   FE 4C 24 03                 DEC BYTE PTR [ESP+0x03h]
00000085:   68 57 69 6E 45            PUSH 456E6957h "WinE"
0000008A:   54                                   PUSH ESP
0000008B:   53                                   PUSH EBX
0000008C:   FF D2                            CALL EDX
0000008E:   68 63 6D 64 01            PUSH 01646D63h "cmd
00000093:   FE 4C 24 03                 DEC BYTE PTR [ESP+0x03h]
00000097:   6A 05                              PUSH 05h (5) ''
00000099:   33 C9                             XOR ECX,ECX
0000009B:   8D 4C 24 04                 LEA ECX,[ESP+0x04]
0000009F:   51                                   PUSH ECX
000000A0:   FF D0                             CALL EAX
000000A2:   68 65 73 73 01             PUSH 01737365h "ess"
000000A7:   8B DF                             MOV EBX,EDI
000000A9:   FE 4C 24 03                 DEC BYTE PTR [ESP+0x03h]
000000AD:   68 50 72 6F 63            PUSH 636F7250h "Proc" ( 636F7250 = ('corP') => PILE:Proc )
000000B2:   68 45 78 69 74            PUSH 74697845h "Exit" ( 74697845 = ('tixE') => PILE:Exit )
000000B7:   54                                   PUSH ESP
000000B8:   FF 74 24 20                  PUSH DWORD PTR [ESP+20h]
000000BC:   FF 54 24 20                 CALL DWORD [ESP+20h]
000000C0:   57                                   PUSH EDI
000000C1:   FF D0                            CALL EAX

Rien que à la lecture, il est simple de voir que ce shellcode ne fait que un WinExec('cmd')

III.    Test du shellcode WinExec("cmd")


Nous avons testé cela au travers d'un générateur de shellcode perso dédier à la création de shellcode de type WinExec


























 
Après avoir mis le shellcode dans la zone de saisi, nous avons lancé le shellcode via le bouton "Run". 
Et suite à cela nous avons eu bien le lancement d'un "cmd" et la fermeture de notre programme exécutant le shellcode lié à l'appel ExistProcess en fin du shellcode.




 

 IV.Conclusions


L'intérêt de connaître les hash current permet de identifier plus rapidement des shellcode nouveau. Et il permet également de pas perdre son temps sur des copie de shellcode.

Comprendre lle processus de reconnaissance par signature est importante. Car la technique étant lié à une identification d'un bloc d'opcode , elle permet de rapidement connaitre les appels et la typologie du shellcode.
L'intérêt ici était de mettre en avant un type de calcule de hash basé sur la fixation de la taille.
Il est est problabe que d'autre changerons le calcule ROR 13 par des ROL 7 , ROR 3 ... etc
Mais démarche pour retrouver les fonctions sera toujours identique. 





1 commentaire: