2016-09-26 2 views
1

Par exemple, supposons qu'au lieu de faire croître des tampons dans la direction opposée de la pile, ils poussent dans la même direction. Si j'ai un tampon de caractères contenant la chaîne "Bonjour tout le monde", au lieu que "H" soit placé à l'adresse la plus basse, il est placé à l'adresse la plus haute, et ainsi de suite.Quelles parties de l'espace d'adressage virtuel d'un processus sont écrasables?

Si une chaîne d'entrée copiée dans un buffer devait déborder, elle ne pouvait pas remplacer l'adresse de retour de la fonction, mais il y a certainement d'autres choses qu'elle pourrait écraser. Ma question est - si la chaîne d'entrée était assez longue, quelles choses pourraient être écrasées? Existe-t-il des fonctions de bibliothèque entre le tas et la pile qui pourraient être écrasées? Les variables de segment peuvent-elles être écrasées? Je suppose que les variables dans les sections de données et bss peuvent être écrasées, mais le segment de texte est-il protégé contre les écritures?

+3

Tout système d'exploitation particulier que vous demandez au sujet? Je ne Je pense que les normes C spécifient la disposition de la mémoire dans un processus, donc cela peut varier d'un système à l'autre – harmic

Répondre

1

La disposition des processus en mémoire varie d'un système à l'autre. Cette réponse couvre Linux sous les processeurs x86_64.

Il existe un bel article illustrant la disposition de la mémoire pour les processus Linux here.

Si le tampon est une variable locale, alors il sera sur la pile, avec d'autres variables locales.La première chose que vous risquez de toucher si vous débordez le tampon est d'autres variables locales dans la même fonction.

Lorsque vous atteignez la fin de la pile, il y a un décalage de taille aléatoire avant le segment de mémoire utilisé suivant. Si vous continuez à écrire dans cet espace d'adressage, vous déclenchez un segfault (puisque cet espace d'adressage n'est pas mappé sur une RAM physique).

En supposant que vous ayez réussi à ignorer le décalage aléatoire sans vous écraser et que vous ayez continué à écraser, la prochaine chose à laquelle il pourrait arriver est le segment de mappage de la mémoire. Ce segment contient des mappages de fichiers, y compris ceux utilisés pour mapper des bibliothèques partagées dynamiques dans l'espace adresse et des mappages anonymes. Les bibliothèques dynamiques vont être en lecture seule, mais si le processus avait des mappages RW en place, vous pourriez peut-être écraser des données à l'intérieur.

Après ce segment vient un autre décalage aléatoire avant d'atteindre le tas. Encore une fois, si vous essayez d'écrire dans l'espace d'adressage du décalage aléatoire, vous déclenchez un crash. En dessous du tas vient un autre décalage aléatoire, suivi par les segments BSS, Data et enfin text. Les variables statiques dans BSS et Data peuvent être écrasées. Le segment de texte ne doit pas être accessible en écriture.

Vous pouvez inspecter la carte mémoire d'un processus à l'aide de la commande pmap.

1

La réponse à votre question dépend entièrement du système d'exploitation utilisé, ainsi que de l'architecture matérielle. Le système d'exploitation définit la mémoire logique d'une certaine manière, et l'architecture réserve parfois (très peu) de la mémoire à des fins spécifiques. Une chose à comprendre est que les processus traditionnels peuvent accéder à tout leur espace mémoire logique, mais très peu de cette capacité est généralement utilisée. L'effet le plus probable de ce que vous décrivez est que vous allez essayer d'accéder à de la mémoire non allouée et que vous obtiendrez une erreur de segmentation en réponse, écrasant votre programme. Cela dit, vous pouvez certainement modifier ces autres segments de la mémoire, mais ce qui se passe lorsque vous le faites dépend de leurs autorisations de lecture/écriture. Par exemple, la mise en page typique de mémoire que vous apprenez à l'école est:

Low memory to high memory: 
.text - program code 
.data - initialized static variables 
.bss - uninitialized static variables 
.heap - grows up 
memory map segments - dynamic libraries 
.stack - grows down 

Le segment .text est marqué en lecture seule/exécutable par défaut, donc si vous essayez d'écrire dans un emplacement de mémoire .text vous obtiendrez une erreur de segmentation. Il est possible de changer .text en écriture, mais c'est en général une idée terrible. Les segments .data, .bss, .heap et .stack sont tous lisibles/inscriptibles par défaut, de sorte que vous pouvez remplacer ces sections sans aucune erreur de programme.

Les segments de la carte mémoire ont tous leurs propres autorisations à gérer. Certains de ces segments sont accessibles en écriture, la plupart d'entre eux ne le sont pas (leur écriture crée donc des erreurs de segmentation). La dernière chose à noter est que la plupart des systèmes d'exploitation modernes vont randomiser les emplacements de ces segments pour rendre les choses plus difficiles pour les pirates. Cela peut introduire des écarts entre différents segments (ce qui entraînera à nouveau des erreurs de segmentation si vous essayez d'y accéder).

Sous Linux, vous pouvez imprimer une carte mémoire de processus à l'aide de la commande pmap. Ce qui suit est la sortie de ce programme sur une instance de vim:

10636: vim hello.text 
0000000000400000 2112K r-x-- vim 
000000000080f000  4K r---- vim 
0000000000810000  88K rw--- vim 
0000000000826000  56K rw--- [ anon ] 
0000000000851000 2228K rw--- [ anon ] 
00007f7df24c6000 8212K r--s- passwd 
00007f7df2ccb000  32K r-x-- libnss_sss.so.2 
00007f7df2cd3000 2044K ----- libnss_sss.so.2 
00007f7df2ed2000  4K r---- libnss_sss.so.2 
00007f7df2ed3000  4K rw--- libnss_sss.so.2 
00007f7df2ed4000  48K r-x-- libnss_files-2.17.so 
00007f7df2ee0000 2044K ----- libnss_files-2.17.so 
00007f7df30df000  4K r---- libnss_files-2.17.so 
00007f7df30e0000  4K rw--- libnss_files-2.17.so 
00007f7df30e1000  24K rw--- [ anon ] 
00007f7df30e7000 103580K r---- locale-archive 
00007f7df960e000  8K r-x-- libfreebl3.so 
00007f7df9610000 2044K ----- libfreebl3.so 
00007f7df980f000  4K r---- libfreebl3.so 
00007f7df9810000  4K rw--- libfreebl3.so 
00007f7df9811000  8K r-x-- libutil-2.17.so 
00007f7df9813000 2044K ----- libutil-2.17.so 
00007f7df9a12000  4K r---- libutil-2.17.so 
00007f7df9a13000  4K rw--- libutil-2.17.so 
00007f7df9a14000  32K r-x-- libcrypt-2.17.so 
00007f7df9a1c000 2044K ----- libcrypt-2.17.so 
00007f7df9c1b000  4K r---- libcrypt-2.17.so 
00007f7df9c1c000  4K rw--- libcrypt-2.17.so 
00007f7df9c1d000 184K rw--- [ anon ] 
00007f7df9c4b000  88K r-x-- libnsl-2.17.so 
00007f7df9c61000 2044K ----- libnsl-2.17.so 
00007f7df9e60000  4K r---- libnsl-2.17.so 
00007f7df9e61000  4K rw--- libnsl-2.17.so 
00007f7df9e62000  8K rw--- [ anon ] 
00007f7df9e64000  88K r-x-- libresolv-2.17.so 
00007f7df9e7a000 2048K ----- libresolv-2.17.so 
00007f7dfa07a000  4K r---- libresolv-2.17.so 
00007f7dfa07b000  4K rw--- libresolv-2.17.so 
00007f7dfa07c000  8K rw--- [ anon ] 
00007f7dfa07e000 152K r-x-- libncurses.so.5.9 
00007f7dfa0a4000 2044K ----- libncurses.so.5.9 
00007f7dfa2a3000  4K r---- libncurses.so.5.9 
00007f7dfa2a4000  4K rw--- libncurses.so.5.9 
00007f7dfa2a5000  16K r-x-- libattr.so.1.1.0 
00007f7dfa2a9000 2044K ----- libattr.so.1.1.0 
00007f7dfa4a8000  4K r---- libattr.so.1.1.0 
00007f7dfa4a9000  4K rw--- libattr.so.1.1.0 
00007f7dfa4aa000 144K r-x-- liblzma.so.5.0.99 
00007f7dfa4ce000 2044K ----- liblzma.so.5.0.99 
00007f7dfa6cd000  4K r---- liblzma.so.5.0.99 
00007f7dfa6ce000  4K rw--- liblzma.so.5.0.99 
00007f7dfa6cf000 384K r-x-- libpcre.so.1.2.0 
00007f7dfa72f000 2044K ----- libpcre.so.1.2.0 
00007f7dfa92e000  4K r---- libpcre.so.1.2.0 
00007f7dfa92f000  4K rw--- libpcre.so.1.2.0 
00007f7dfa930000 1756K r-x-- libc-2.17.so 
00007f7dfaae7000 2048K ----- libc-2.17.so 
00007f7dface7000  16K r---- libc-2.17.so 
00007f7dfaceb000  8K rw--- libc-2.17.so 
00007f7dfaced000  20K rw--- [ anon ] 
00007f7dfacf2000  88K r-x-- libpthread-2.17.so 
00007f7dfad08000 2048K ----- libpthread-2.17.so 
00007f7dfaf08000  4K r---- libpthread-2.17.so 
00007f7dfaf09000  4K rw--- libpthread-2.17.so 
00007f7dfaf0a000  16K rw--- [ anon ] 
00007f7dfaf0e000 1548K r-x-- libperl.so 
00007f7dfb091000 2044K ----- libperl.so 
00007f7dfb290000  16K r---- libperl.so 
00007f7dfb294000  24K rw--- libperl.so 
00007f7dfb29a000  4K rw--- [ anon ] 
00007f7dfb29b000  12K r-x-- libdl-2.17.so 
00007f7dfb29e000 2044K ----- libdl-2.17.so 
00007f7dfb49d000  4K r---- libdl-2.17.so 
00007f7dfb49e000  4K rw--- libdl-2.17.so 
00007f7dfb49f000  20K r-x-- libgpm.so.2.1.0 
00007f7dfb4a4000 2048K ----- libgpm.so.2.1.0 
00007f7dfb6a4000  4K r---- libgpm.so.2.1.0 
00007f7dfb6a5000  4K rw--- libgpm.so.2.1.0 
00007f7dfb6a6000  28K r-x-- libacl.so.1.1.0 
00007f7dfb6ad000 2048K ----- libacl.so.1.1.0 
00007f7dfb8ad000  4K r---- libacl.so.1.1.0 
00007f7dfb8ae000  4K rw--- libacl.so.1.1.0 
00007f7dfb8af000 148K r-x-- libtinfo.so.5.9 
00007f7dfb8d4000 2048K ----- libtinfo.so.5.9 
00007f7dfbad4000  16K r---- libtinfo.so.5.9 
00007f7dfbad8000  4K rw--- libtinfo.so.5.9 
00007f7dfbad9000 132K r-x-- libselinux.so.1 
00007f7dfbafa000 2048K ----- libselinux.so.1 
00007f7dfbcfa000  4K r---- libselinux.so.1 
00007f7dfbcfb000  4K rw--- libselinux.so.1 
00007f7dfbcfc000  8K rw--- [ anon ] 
00007f7dfbcfe000 1028K r-x-- libm-2.17.so 
00007f7dfbdff000 2044K ----- libm-2.17.so 
00007f7dfbffe000  4K r---- libm-2.17.so 
00007f7dfbfff000  4K rw--- libm-2.17.so 
00007f7dfc000000 132K r-x-- ld-2.17.so 
00007f7dfc1f8000  40K rw--- [ anon ] 
00007f7dfc220000  4K rw--- [ anon ] 
00007f7dfc221000  4K r---- ld-2.17.so 
00007f7dfc222000  4K rw--- ld-2.17.so 
00007f7dfc223000  4K rw--- [ anon ] 
00007ffcb46e7000 132K rw--- [ stack ] 
00007ffcb475f000  8K r-x-- [ anon ] 
ffffffffff600000  4K r-x-- [ anon ] 
total   163772K 

Le segment à partir de 0x851000 est en fait le début du tas (qui pmap vous dira avec les modes d'établissement de rapports plus verbeux, mais le mode plus bavard ne correspond pas).

+0

Merci pour votre réponse! – Connor

0

Je pense que votre question reflète une incompréhension fondamentale de la façon dont les choses fonctionnent dans un système d'exploitation. Des choses comme "buffers" et "stack" ont tendance à ne pas être définies par le système d'exploitation. Le système d'exploitation divise la mémoire en noyaux et en zones utilisateur (certains systèmes ont des zones protégées supplémentaires).

La disposition de la zone utilisateur est généralement définie par l'éditeur de liens. L'éditeur de liens crée des exécutables qui indiquent au chargeur comment configurer l'espace d'adressage. Divers lieurs ont différents niveaux de contrôle. En règle générale, les paramètres de l'éditeur de liens par défaut regrouper les sections de programme comme quelque chose comme:

-Lire/exécuter

-Lire/no execute

-Lire/écriture/initialisé

-Lire/écriture/demande zéro

Parmi les lieurs, vous pouvez créer plusieurs sections de programme avec ces attributs.

Vous demandez:

« Si j'ai un tampon de caractères contenant la chaîne « Bonjour tout le monde », au lieu de « H » étant placé à l'adresse la plus basse, il est placé à l'adresse la plus élevée, et ainsi de suite. "

Dans une machine neu neumann, la mémoire est indépendante de son utilisation. Le même bloc de mémoire peut être interprété simultanément comme une chaîne, un virgule flottante, un entier ou une instruction. Vous pouvez placer votre lettre dans l'ordre de votre choix, mais la plupart des bibliothèques de logiciels ne les reconnaissent pas dans l'ordre inverse. SI vos propres bibliothèques peuvent gérer les chaînes stockées à l'envers, faites-vous plaisir. "Ma question est - si la chaîne d'entrée était assez longue, quelles choses pourraient être remplacées?"

Cela pourrait être n'importe quoi."Y at-il des fonctions de bibliothèque qui existent entre le tas et la pile qui pourraient être remplacées?"

Cela dépend de ce que votre éditeur de liens a fait.

"Les variables de segment peuvent-elles être remplacées?"

Le tas peut être écrasé.

« Je suppose que les variables dans les données et les sections bss peuvent être remplacés, mais est le segment de texte protégé contre les écritures?

En général, oui.