Le développeur Guidobot, à l'origine du 138Menu que vous utilisez peut-être sur votre PS Vita, a posté avant-hier sur les forums de Wololo une explication relativement détaillée à propos du dernier exploit kernel PSP découvert par Qwikrazor87 sur les PS Vita en firmware 3.36 dont le code source a été révélé il y a 2 jours par l'auteur lui-même. Une petite traduction française s'impose...

Vous vous souvenez peut-être que nous évoquions une situation de compétition (ou race condition), cela semble être confirmé. Tout d'abord, sachez qu'une situation de compétition est une sorte de faille présente dans un système qui ne se manifeste que lorsque plusieurs "événements" causés par des acteurs (dont au moins un a la capacité de modifier l'état de la ressource impliquée) interviennent dans un ordre inattendu. Dans les codes multi-tâches (multithread), cela peut être assez commun si le verrouillage adéquat de chaque ressource partagée n'est pas fait correctement par les tâches (threads).
Dans un tel cas, la fonction exploitée vérifie que les paramètres sont valides avant de continuer, mais avant d'utiliser ces valeurs, un autre thread "malveillant" peut venir modifier le contenu de certains paramètres avec le fameux contenu exploité.

Ici, la fonction donnant l'accès au noyau (kernel) s'appelle sceMeVideo_driver_4D78330C (à comprendre comme étant le "do_some_stuff(data)" sur l'illustration ci-dessus), et la fonction avec la situation de compétition est le fameux scevideoCodecStop (le "myfonction" sur l'illustration). Vous avez une idée générale du fonctionnement de ce kernel exploit, si vous souhaitez connaître tout sur tout, nous vous invitons à voir les explications du code source plus bas. ;)
//sceVideocodecStop kxploit reverse by GUIDOBOT //u sont inconnus, p sont les pointeurs et v les valeurs typedef struct s_data { unsigned u0; //0 unsigned u4; //1 unsigned u8; //2 unsigned p12; //3 unsigned p16; //4 unsigned u20; //5 unsigned u24; //6 unsigned u28; //7 unsigned u32; //8 unsigned u36; //9 unsigned u40; //10 unsigned p44; //11, * unsigned p48; //12 unsigned u52; //13 unsigned p56; //14 unsigned v60; //15 } t_data; int sceVideocodecStop(t_data * data, int flag) { //on veut que cela retourne 0, on lui assigne donc les bonnes valeurs int check = sub_00000C38(data); if(!check) { //les deux lignes ci-dessous se chargent d'écrire certaines données depuis la structure vers la mémoire, mais on ne s'en soucie pas sub_00000D2C(data, flag); sub_00000B8C(data, flag); //c'est cet endroit qui nous intéresse, les valeurs de la structure doivent normalement déjà être échangées pour que tout fonctionne int val = sceMeVideo_driver_4D78330C(flag, data); //etc. //.. }; //etc. //.. }; //filtres des adresses du kernel int sub_00000C38(const t_data * data, int flag) { //ce morceau de code va simplement vérifier certaines données, à savoir les valeurs : data->p12, data->p16, data->p44 et data->p56 if((0x80000000 & ((data + 96) | data) >= 0) && (0x80000000 & data->p12 >= 0)) { int size = 256; if(flag == 0) size = 40; else if(flag >= 3) return 0x806201FE; if(0x80000000 & ((data->p16 + size) | data->p16) >= 0) { if(flag) return 0; //malheureusement, on ne l'obtient pas ici, mais continuez de lire if(0x80000000 & ((((data->p44 + (data->v60 * 44))) | data->p44) | (data->v60 * 44)) >= 0) { if(0x80000000 & ((data->p48 + 100) | data->p48) >= 0) { if(0x80000000 & (((data->p56 + data->v60 * 328) | data->p56) | (data->v60 * 328)) >= 0) return 0; //youpi }; }; }; }; //on ne veut pas arriver ici return 0x80000023; }; int sceMeWrapper_driver_4D78330C(int flag, t_data * data) { if(data->v0 > 0x05100601) // il est nécessaire de faire ce data->v0 = 0x05100601 pour s'amuser return -2; data->v8 = 0; if(flag == 0) { if(data->v60 - 1 >= 4) return -1; //Si data->v60 est égal à 1 alors le compteur sera à 0 int count = data->v60 - 1; if(data->p56) { //c'est affreux ici, mieux vaut voir du côté de la condition "else" (d'ailleurs, ou pourrait aussi faire un kernel exploit ici) void * address = count * 44 + data->p44; unsigned value = count * 328 + data->p56; for(int i = count; i > 0; i--) { *(address + 36) = value; *(address + 40) = value + 164; value -= 328; address -= 44; }; } else //cela signifie que si data->p56 est nul { //si le compteur est à 0 alors l'adresse sera data->p44 void * address = count * 44 + data->p44; for(int i = count; i > 0; i--) { *(address + 36) = 0; *(address + 40) = 0; address -= 44; }; //nous avons sauté 2 instructions ici, ce afin de ne pas "casser" le code et d'assigner 0 au compteur //le pointillage data->p44 à (ADDRESS - 36) va nous permettre de sauter ADDRESS et (ADDRESS + 4) }; int result2 = sceMeWrapper_driver_635397BB(3, data->p12, data->p16, data->p44); if(result2 >= 0) return 0; return sub_00001194(data, result2); } else if(flag != 1) return -1; int result = sceMeWrapper_driver_635397BB(33, data->v12); if(result) return sub_000011C4(data, result); return 0; };
Des questions que je me pose :
- SONY peut-il bloquer le chemin utilisé par les chercheurs de faille ?
- Si c'est pas SONY, les constructeurs de jeu peuvent-ils le faire ?
- Chaque faille trouver est chercher de la même manière ou est différent de chaque jeu utilisé ?
Merci !
Je ne saurai te répondre avec exactitude, mais en tout cas oui c'est clair que Sony peut boucher cette faille, et c'est d'ailleurs probablement ce qu'il fera pour les prochains firmwares. ^^