Tuesday, May 25, 2010

Question du Jour

Trouve dans une DLL d'un systeme d'exploitation bien connu:

lea eax, [ebp+var_44]
push eax ; hMem
call ds:__imp__LocalFree@4 ; LocalFree(x)

Quelqu'un peut-il me dire:
  1. Pourquoi c'est "mal"?
  2. Quelle est l'erreur du programmeur qui a mene a ce code?
  3. Comment exploiter cela?
Par une operation du Saint Esprit, le code n'est pas atteignable dans la DLL en question. C'est moche.

Wednesday, May 19, 2010

Exception Culturelle

La derniere fois que je suis tombe sur du code promouvant l'exception culturelle Francaise, il s'agissait de cles DES specifiees en dur dans le Protected Storage. Cette fois-ci, on va regarder SChannel.

Un utilisateur averti pourra se demander pourquoi dans SChannel v5.1.2600.5834 (XP SP3 US plus ou moins a jour) on trouve la fonction IsSchEncryptionPermitted(), qui contient:

call ds:__imp__GetSystemDefaultLCID@0 ; GetSystemDefaultLCID()
cmp ax, 40Ch
jz short loc_767F41A7
push 0Ah ; cchData
lea ecx, [ebp+LCData]
push ecx ; lpLCData
push 5 ; LCType
push eax ; Locale
call ds:__imp__GetLocaleInfoA@16 ; GetLocaleInfoA(x,x,x,x)
test eax, eax
jz short loc_767F41A7
lea eax, [ebp+LCData]
push eax
call _MyStrToL@4 ; MyStrToL(x)
cmp eax, 21h
jnz short loc_767F41B8
loc_767F41A7: ; CODE XREF: IsSchEncryptionPermitted()+1Aj
; IsSchEncryptionPermitted()+2Dj 
and _g_ProtEnabled, 0FFFFFFFCh
mov _g_fFranceLocale, 1

Sauf que cette fois ci, le resultat n'est pas le meme. Si le Windows est francophone, on enleve les deux bits de poids faible de _g_ProtEnabled et on met a 1 une variable obscure.

Dans le code de SslReadRegOptions(), si _g_fFranceLocale est non 0, on ne prend pas en compte l'activation ou desactivation des protocoles specifies dans la base de registre, decrit dans la KB187498, si les bits de poids faible sont presents.

Les bits utilises pour l'activation des protocoles sont:
  • "Multi-Protocol Unified Hello\\Client": 80000000h
  • "Multi-Protocol Unified Hello\\Server": 40000000h
  • "PCT 1.0\\Client": 2
  • "PCT 1.0\\Server": 1
  • "SSL 2.0\\Client": 8
  • "SSL 2.0\\Server": 4
  • "SSL 3.0\\Client": 20h
  • "SSL 3.0\\Server": 10h
  • "TLS 1.0\\Client": 80h
  • "TLS 1.0\\Server": 40h

En conclusion, si je ne me suis pas plante, pas de drame - a part qu'un Windows francophone ne puisse pas faire de PCT du tout (client ou serveur). Ca m'aurait ete utile de savoir ca en 2004 pour l'exploit PCT Handshake...

Si quelqu'un veut confirmer, amusez-vous, je testerai sans doute dans la semaine pour verifier et mettrai a jour le post. Je n'ai pas d'explication au bannissement de PCT en France.

Et joyeux anniversaire a ma soeur!

Exploiter un double free() sous Windows

Un soir, une discussion avec Ronald et Sean nous a mene sur le sujet des doubles free() sous Unix, et je me suis rendu compte que je n'avais jamais exploite un double free() sous Windows. Bien que la problematique ne soit pas extremement complexe, il semblerait qu'il n'y ait pas des masses de documentation sur le sujet, a part une entree de sh0ck qui se retrouve massacree un peu partout.

Bien entendu, de nombreux elements entrent en compte:
  • Y a-t-il ecriture des donnees entrent les deux free()?
  • Le Heap en question a-t-il un Lookaside?
  • Est-ce que le Lookaside a atteint sa profondeur maximale avant le 1er free()? Apres?
  • Le Chunk libere est-il VirtualAllloc()'ed?
Quelques inexactitudes sur le sujet:

Tout d'abord: le free() d'un chunk deja marque comme libere (Chunk.Flag & 1 == 0) n'a aucun effet. Donc contrairement a ce qu'affirment des papiers comme Towards Automatically Generating Double-Free Vulnerability Signatures Using Petri Nets (1), meme s'il y a possibilite d'ecriture dans la partie data du chunk entre les deux free(), il ne se passera rien. S'il y a liberation, ecriture puis allocation, c'est une histoire differente (unlink sur un LIST_ENTRY maitrise qui donne un Write4) et ce n'est pas un double free().

Ensuite, si le chunk est VirtualAlloc'ed() - c'est usuellement le cas si la taille/8 est > 0xfe00 qui est le seuil par defaut - le 1er free() va retourner la page au gestionnaire de memoire de Windows qui va decommit la zone rapidement. Cela entrainera une violation d'acces lors du second free().

Nous sommes donc restreints aux cas ou le chunk est libere vers la Lookaside puisque dans ce cas la le chunk est toujours marque comme occupe. Donc:
  1. Le Heap en question doit avoir un Lookaside
  2. Le free() doit etre sur un chunk dont la taille est < 1024
  3. L'entree correspondante du Lookaside doit avoir au moins 1 place disponible (la profondeur par defaut est 4 la plupart du temps) sinon il sera libere vers la FreeList[]
Apres, il existe plusieurs possibilites, que l'on trouvera decrites dans une entree du blog de Symantec par Matt Connover.
  • Premier free() vers le Lookaside qui se retrouve plein entrainera un second free dans la FreeList[] (et potentiel coallesce) avec ecrasement du LIST_ENTRY apres premiere allocation, et une entree de Lookaside pointant vers le chunk libre (de la FreeList[]) suivant.
  • Premier et second free() vers le Lookaside, qui entrainera une primitive WriteN lors de la troisieme allocation d'un chunk de la taille en question.

Au final, un double free() ca s'exploite relativement bien dans XP et 2003, mais pas comme le decrivent certains.

Edit: petite correction dans le 1er cas.

(1): "After it has been freed, the programmer mistakenly uses temp and writes X in the first 4 bytes and Y in the second 4 bytes of temp. Then the programmer frees temp again. The system will then try to insert temp into the free list for a second time right before where it is already inserted."

Thursday, May 6, 2010

Supernaturel

Ce soir, Sam & Dean rencontrent le 3e Cavalier de l'Apocalypse: Mort. Cela faisait un moment que je n'avais pas autant accroche a une serie TV - mais Supernatural semble combler le manque. Voici le trailer de l'episode en attendant la diffusion dans une heure!