49 votes

Explication d'un pointeur dans le code d'exploitation

Dans quelques exploits pour obtenir le shell root, je vois souvent un pointeur :

Quelqu'un peut-il expliquer ce pointeur un peu ? Je pense que 8191 est la taille de la pile du noyau. pointe vers le bas de la **pile du noyau**? Voici comment pointeur est utilisé :

54voto

Mormegil Points 4263

Le code prend l'adresse de la variable locale i pour obtenir un pointeur dans le cadre de la pile. Ensuite, il s'aligne l'adresse à 8K page (c'est ce que vous faites avec x & ~8191: 8191 est de 2^13 - 1, ce qui signifie ~8191 est tout sauf une faible 13 bits, ANDing avec un certain nombre de dégager le bas de 13 bits, c'est à dire d'adapter le nombre le plus proche inférieur multiple de 2^13, en d'autres termes, l'aligner à 8K limite).

Il prend alors cette adresse, et l'interprète comme un pointeur vers un pointeur et les charges de la pointe de l'adresse. Voir la Compréhension de l'obtention de task_struct pointeur de processus de la pile du noyau pour plus d'informations.

Après cela, il tente de trouver une structure spécifique stockée quelque part après cette adresse: Il regarde à travers la suivante 1024-13 unsigneds, en essayant de trouver un endroit de la mémoire où le processus actuel de l'information (probablement) est stockée: Quand il trouve un morceau de la mémoire de la tenue de multiples copies de l'actuel UID et GID, il suppose qu'il a trouvé. Dans ce cas, il le modifie de sorte que le processus actuel obtient un UID et un GID 0, ce qui rend le processus de l'exécution sous la racine (de plus, il stocke tout dans la capacité de suivi des drapeaux).

Cf. struct cred.

8voto

Joshua Points 13231

Je vais poster encore une autre réponse, car il n'y a vraiment quelque chose à ajouter ici.

unsigned *p = *(unsigned**)(((unsigned long)&i) & ~8191); 

résultats dans les p étant le pointeur au début de la 8192 octets la taille du bloc de mémoire. Toutefois, le code est erroné. Si p est au-dessus de INT_MAX (qui peut être ou il serait en fonte non signé, pas unsigned long), le haut-bits obtenir cisaillée par le masque. Bon code est comme suit:

unsigned *p = *(unsigned**)(((ptrdiff_t)&i) & ~(ptrdiff_t)8191);

ou à l'aide de uintptr_t:

unsigned *p = *(unsigned**)(((uintptr_t)&i) & ~(uintptr_t)8191U);

Il est nécessaire de jeter en entier et à l'arrière de pointeur pour que le code du travail; toutefois, pour garantir un int-pointeur de la taille nécessite l'utilisation de ptrdiff_t (nous rappelons que les entiers signés et non signés se comportent exactement de la même pour les opérations bit à bit). Quant à savoir pourquoi ils n'ont pas les écrire avec hex constantes, qui s'en soucie. Les gars qui font ce genre de choses connaître leurs puissances de 2 par cœur. Il peut être plus rapide à lire 8191 puis 0x1FFF.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X