Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

printf et %n.

15 réponses
Avatar
GurneyH
Bonjour,

Je me trouve en face d'un probl=E8me =E9trange.
Ce code compil=E9 avec MinGW :

#include <stdio.h>

int main(void)
{
int a;
char const *s =3D "Hello world";

printf("%s%n\n", s, &a);
printf("%d\n", a);

return 0;
}

M'affiche bien chez moi 11, qui est bien est le nombre de caract=E8res
d=E9j=E0 =E9crits.

Seulement une autre personne =E9galement sous MinGW compile ce code, et
il semble que le sp=E9cificateur %n est ignor=E9. : si on initialise la
variable a avec une valeur quelconque, on retrouve cette valeur apr=E8s
l'appel de printf.

Une id=E9e?...

Merci d'avance.

5 réponses

1 2
Avatar
espie
In article <hm90mk$a6i$,
Antoine Leca wrote:
D'après ISO/CÉI TR 24731-1, le problème ce serait des attaques contre
des printf qui ne contrôleraient pas leur chaîne de format ; cas type :
printf(argv);



C'est vraiment des blaireaux. C'est quand meme le Ba-ba de l'ecriture
de code correct. Ca fait meme partie des trucs que j'enseigne en cours
de C.

Le vrai souci, c'est la défense en profondeur : comme chacun sait, les
chaînes de format font partie des choses les plus faciles à repérer dans
un binaire C : donc un attaquant peut chercher à viser de telles
chaînes, changer le caractère qui suit un % par un n et le piège est
ouvert : par exemple, cela revient à modifier un code qui fait
printf("%x", &toto);
en
printf("%n", &toto);
soit
toto = 0;



Blaireau bis: dans tout systeme de compilation decent, les chaines de
caracteres constantes sont dans la zone read-only du code. C'est quelque
chose qui doit etre imposee dans le monde Unix depuis... environ 15 ans.
Et je crois que gcc a fini par virer l'option write-strings.

Apres, avoir un support pour ca dans les executables... ca existait DEJA
dans a.out, et me semble que le code auto-modifiant, meme chez crosoft,
c'est passe de mode depuis des annees.

Bref, je comprend leurs arguments, mais bof... quand ca s'allie a leur
fonctions ridicules de "traitements de chaines de caracteres safe" qu'ils
ont essaye (sont arrives ?) a imposer au comite C pour la prochaine
mouture de la norme, je me dis qu'on vit dans un monde de nuls, et qu'on
merite bien toutes les plaies du monde (dont fait evidemment partie
Windows 7...)
Avatar
Samuel DEVULDER
Marc Espie a écrit :


Blaireau bis: dans tout systeme de compilation decent, les chaines de
caracteres constantes sont dans la zone read-only du code.



Il me semble qu'Antoine parlait de modifier avec un éditeur binaire un
exe disk pour transformer les octets %x en %n dans le fichier. C'est
en tout cas comme ca que j'ai compris son texte.

En plus ca doit faire parti des petites modifs que des virus alakon font
comme ca pour faire chier le monde... et se marrer d'avoir planter un
systeme en modifiant un 'x' par un 'n' dans un .exe j'imagine.

sam.
Avatar
espie
In article <4b884041$0$22376$,
Samuel DEVULDER wrote:
Marc Espie a écrit :


Blaireau bis: dans tout systeme de compilation decent, les chaines de
caracteres constantes sont dans la zone read-only du code.



Il me semble qu'Antoine parlait de modifier avec un éditeur binaire un
exe disk pour transformer les octets %x en %n dans le fichier. C'est
en tout cas comme ca que j'ai compris son texte.



Euh, si t'as assez d'acces au systeme pour changer un exe sur le disque,
tu ne vas pas t'emmerder a faire ce genre de modifs, tu as bien d'autres
facons d'embeter le monde...
Avatar
Manuel Pégourié-Gonnard
Antoine Leca scripsit :

Manuel Pégourié-Gonnard écrivit :
Bon, alors les problèmes de scrcpy() et consorts, je vois, par contre,
celui de %n c'est quoi en fait ?



D'après ISO/CÉI TR 24731-1, le problème ce serait des attaques contre
des printf qui ne contrôleraient pas leur chaîne de format ; cas type :
printf(argv);



En même temps, comme l'a fait remarqué Marc, les gens bien élevés ne
sont pas censés faire ce genre de chose :-)

Une circonstance aggravante, en terme de sûreté, c'est que la fonction «
écrire » qui est sous-tendue par %n n'est pas naturellement associée à
printf() (cf. l'enfilade pour s'en rendre compte) : en conséquence de
nombreuses analyses de sûreté risquent de passer à côté du piège
potentiel (et là aussi, vu la virulence des propos, j'ai comme dans
l'idée que cela a dû se passer en pratique au sud de Vancouver ;
cf. aussi les vulnérabilités WMF à répétition, qui sont basées sur le
même défaut fonctionnel de sûreté).



Oui, effectivement, ça c'est un problème.

Merci pour ces explications.

--
Manuel Pégourié-Gonnard Institut de mathématiques de Jussieu
http://weblog.elzevir.fr/ http://people.math.jussieu.fr/~mpg/
Avatar
Antoine Leca
Samuel DEVULDER écrivit :
Marc Espie a écrit :

Blaireau bis: dans tout systeme de compilation decent, les chaines de
caracteres constantes sont dans la zone read-only du code.



Il me semble qu'Antoine parlait de modifier avec un éditeur binaire un
exe disk pour transformer les octets %x en %n dans le fichier.



Pas vraiment, je parlais bien d'aller modifier en mémoire les chaînes de
format, et Marc a totalement raison de rappeler que ceci est bloqué par
le simple fait d'avoir les chaînes de format en mémoire lecture-seule.
Et d'ailleurs je partage assez les commentaires de Marc sur le sujet
(mais cela reste des commentaires, et la question portait sur le fond).


Seulement, dans le monde merveilleux de la norme C, les chaînes de
caractères sont _potentiellement_ en mémoire inscriptible ;
et quoi qu'en pense Marc, je ne vois pas GCC /virer/ l'option
-fwrite-srings de sitôt, cela casserait vraiment beaucoup de code!
Par exemple, ce week end je suis tombé sur
char *template = "blablaXXXXXX";
/* ... */
tata = mktemp(ptr_issu_de_template);
et kaboum avec GCC.

Ce qui m'a fait le plus rire (nerveux) dans cette séquence, c'est que
l'aide en ligne de _mktemp/_wmktemp chez Microsoft continue à proposer
cette utilisation, avec un pointeur vers littéral de chaînes...
(plutôt qu'un tableau de caractères initialisé, comme indiqué par
exemple dans le texte de la norme Posix; le top est encore la page de
manuel *BSD, qui décrit le problème et sa solution ; dont acte.)


Antoine
1 2