«Xor eax, ebp» utilisé dans la sortie du compilateur C ++

J’ai juste essayé de comstackr quelques fragments C ++ sur VS2010 et analysé les exécutables sur IDA Pro. Quelque chose que j’ai remarqué, c’est que la plupart d’entre eux ont quelque chose comme ce qui suit au début (peu après un appel à __security_check_cookie)

xor eax, ebp

et quelque chose comme

xor ecx, ebp

au fond. Pourquoi cela arrive-t-il? L’optimisation du compilateur a été désactivée.

Ce sont des méthodes de protection contre le dépassement de la mémoire tampon et n’ont rien à voir avec l’optimisation du compilateur. MSVC (si vous spécifiez le commutateur /GS ) poussera un cookie de sécurité sur la stack près de l’adresse de retour afin qu’il puisse détecter un cas courant de corruption de stack.

La corruption de la stack peut être causée par un code incorrect, comme suit:

 char buff[5]; strcpy (buff, "Man, this ssortingng is waaay too long!!"); 

ou par des utilisateurs malveillants tirant parti des mauvaises pratiques de codage, comme l’utilisation de scanf ("%s", myBuff) pour la saisie par l’utilisateur. Des attaques soigneusement conçues comme celle-là peuvent suborner votre programme pour faire des choses que vous ne voulez probablement pas.

En plaçant un cookie près de l’adresse de retour, un grand nombre de bogues (et de vecteurs d’attaque) peuvent être évités, simplement parce que les corruptions de mémoire ont tendance à être séquentielles. En d’autres termes, si vous avez écrasé l’adresse de retour, c’est probablement parce que vous avez commencé à écrire sur une face du cookie et à la mémoire corrompue jusqu’à l’adresse de retour de l’autre côté du cookie (le cookie sera donc écrasé). ainsi que).

Il ne détecte pas tous les bogues, car vous pouvez avoir du code comme:

 char buff[5]; buff[87] = 'x'; 

qui pourrait potentiellement corrompre l’adresse de retour sans toucher le cookie. Mais il va attraper tous ceux malveillants qui comptent sur la saisie d’une chaîne plus longue que prévu, ce qui corrompt jusqu’à l’adresse de retour (y compris les cookies).

La séquence que vous voyez probablement dans le code est quelque chose comme:

 mov eax, dword ptr ds:___sec_cookie ; fixed value. xor eax, ebp ; adjust based on base pointer. mov [ebp+SOMETHING], eax ; store adjusted value. 

qui personnalise le cookie, en fonction du pointeur de base actuel.

Cela changera ce qui est réellement placé sur la stack au niveau de chaque stack (et également en fonction du nombre et de la taille des parameters) et est probablement une tentative de sécuriser davantage le code contre une intention malveillante en s’assurant qu’une signature de variable est écrite dans la stack. plutôt qu’une valeur fixe (sinon l’attaquant pourrait entrer des caractères, y compris un cookie valide).

Et la séquence à la fin exécutera quelque chose comme ceci:

 mov ecx, [ebp+SOMETHING] ; get the adjusted cookie. xor ecx, ebp ; un-adjust it, since ; ((N xor X) xor X) == N. call @__sec_check_cookie ; check the cookie. 

C’est simplement le processus inverse de celui décrit ci-dessus. L’appel @__sec_check_cookie ne retournera que si ecx est défini sur la valeur de cookie correcte. Sinon, cela provoquera une erreur, comme confirmé ici :

La routine __security_check_cookie() est simple: si le cookie n’a pas été modifié, il exécute l’instruction RET et met fin à l’appel de fonction. Si le cookie ne correspond pas, la routine appelle report_failure() .

La fonction report_failure() appelle alors __security_error_handler() . Les deux fonctions sont définies dans le fichier seccook.c fichiers source CRT.

Le support CRT est nécessaire pour que ces contrôles de sécurité fonctionnent. Lorsqu’un échec de contrôle de sécurité se produit, le contrôle du programme est transmis à __security_error_handler() , qui est résumé ici:

 void __cdecl __security_error_handler(int code, void *data) { if (user_handler != NULL) { __try { user_handler(code, data); } __except (EXCEPTION_EXECUTE_HANDLER) {} } else { //...prepare outmsg... __crtMessageBoxA( outmsg, "Microsoft Visual C++ Runtime Library", MB_OK|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL); } _exit(3); } 

Par défaut, une application qui échoue à un contrôle de sécurité affiche une boîte de dialog indiquant “Dépassement du tampon détecté!”. Lorsque la boîte de dialog est rejetée, l’application se termine.