CISCO IOS (Partie 4)
Par Mathieu le dimanche 6 janvier 2008, 16:58 - Lien permanent
Tout Operating System possède un système de gestion mémoire. Les Operating
Systems récents travaillent avec de la mémoire protégée. Un processus x ne peut
pas accéder à la mémoire d’un processus y. Pour que le processus x dialogue
avec le processus y, ils vont devoir employer d’autres méthodes (Shared Memory,
Message Queues, Pipes, Network Connections, …). Ces méthodes sécurisent les
processus entre-euxs mais ralentissent néanmoins leurs fonctionnements. L’IOS
ne gère pas la mémoire partagée, tous les processus ont accès à la mémoire sans
restrictions. Un processus est donc libre de dialoguer avec un autre en
écrivant dans la mémoire de ce dernier (Buffer Overflow = Crash, j’y reviendrai
avec la notion de bloc). Il existe néanmoins une notion de mémoire R/O et R/W.
L’IOS travaille avec des pools de mémoire, c’est le Pool Manager qui en est
responsable :
Le post suivant
parlera du « chunk manager » de l’IOS.
#show memory Head Total(b) Used(b) Free(b) Lowest(b) Largest(b) Processor 653B8C20 155481056 86243592 69237464 68168948 67670028 I/O EE800000 25165824 5269012 19896812 19819968 19871932Ici, un pool réservé au processor et un pool réservé aux I/O:
- Head : début du pool
- Total : taille du pool en bytes
- Used : utilisation actuelle du pool en bytes
- Free : mémoire libre actuelle du pool en bytes
- Lowest : mémoire libre historiquement la plus basse en bytes
- Largest : le plus grand bloc de mémoire libre contigüe
#show region Region Manager: Start End Size(b) Class Media Name 0x0E800000 0x0FFFFFFF 25165824 Iomem R/W iomem:(iomem) 0x60000000 0x6E7FFFFF 243269632 Local R/W main 0x6000F000 0x632FFFFF 53415936 IText R/O main:text 0x63300000 0x64DFFCFF 28310784 IData R/W main:data 0x64DFFD00 0x653B8C1F 6000416 IBss R/W main:bss 0x653B8C20 0x6E7FFFFF 155481056 Local R/W main:heap 0x80000000 0x8E7FFFFF 243269632 Local R/W main:(main_k0) 0xA0000000 0xAE7FFFFF 243269632 Local R/W main:(main_k1) 0xEE800000 0xEFFFFFFF 25165824 Iomem R/W iomemLe pool de mémoire Processor est donc compris dans la région main:heap. Cette région fait partie de la région main qui commence en 0x60000000 et finit en 0x6E7FFFFF. Le pool de mémoire I/O représente la région iomem de 0xEE800000 à 0xEFFFFFFF. Dans la région main, on trouve :
- main:text : contient le code de l’IOS en R/O (IText)
- main:data : contient les variables initialisées R/W (IData)
- main:bss : contient les variables non initialisées R/W (IBss)
- main:heap : contient les structures de mémoire standard locales R/W
- iomem : contient la mémoire des périphériques (mémoire pour le bus I/O)
#show memory processor Processor memory Address Bytes Prev Next Ref PrevF NextF Alloc PC what 65A817E0 0000000084 65A8175C 65A81864 001 -------- -------- 628215E8 Init 65A81864 0000001372 65A817E0 65A81DF0 001 -------- -------- 608E3218 Skinny Socket Server 65A81DF0 0000001156 65A81864 65A822A4 001 -------- -------- 608E3218 Skinny Socket Server
- Address : début du bloc
- Bytes : taille du bloc
- Prev : adresse du bloc précédent (chaînage)
- Next : adresse du bloc suivant (chaînage)
- Ref : par combien de processus ce bloc est-il utilisé ?
- PrevF : bloc libre précédent
- NextF : bloc libre suivant
- Alloc PC : processus ayant alloué ce bloc
- What : nom du processus détenant le bloc
#show memory 0x65A81864 65A81860: AB1234CD 010B0000 66B4EBEC +.4M....f4kl 65A81870: 6395634C 608E3218 65A81DF0 65A817F4 c.cL`.2.e(.pe(.t 65A81880: 800002AE 00000001 605C3DD4 00000112 ........`=T.... ... 65A81DE0: FD0110DF }.._Après quelques recherches on devine déjà les champs du header de bloc :
65A81860: [MAGIC ] [PID ] [? ] 65A81870: [PTR_NAME] [ALLOCPC] [NEXT ] [PREV+20d] 65A81880: [SIZE*] [REF ] [? ] [ DATA ->] ... 65A81DE0: [<- DATA] [MAGIC ]
- MAGIC_START est toujours 0xAB1234CD
- PID : l’id du processus
- [ PLACEHOLDER ]
- PTR PS_ NAME : pointeur vers le nom du processus détenant le bloc
- ALLOC_PC : même valeur que dans la commande « show memory processor »
- NEXT : pointeur vers le prochain bloc
- PREV : pointeur vers le précédent bloc + 20d (directement sur le champ next du précédent)
- SIZE : renferme une petite subtilité, le MSB (Most Significant Bit) de ce champ est un flag qui positionné à 1 indique que ce bloc est utilisé. De plus la valeur lue dans ce champ diffère de la valeur affichée avec la commande « show memory processor ». Pour obtenir la valeur correcte je dois faire : (valeur lue)*2+4 ????
- REF : combien de processus utilisent ce bloc
- [ PLACEHOLDER ]
- DATA : les données …
- MAGIC_END est toujours 0xFD0110DF (palindrome en hexa)
#show process 0x0000010B [010B <> 0000] Process ID 267 [Skinny Socket Server], TTY 0 Memory usage [in bytes] Holding: 89644, Maximum: 109468, Allocated: 6601380, Freed: 6514500 Getbufs: 0, Retbufs: 0, Stack: 8908/12000 CPU usage PC: 60846DE4, Invoked: 26, Giveups: 1, uSec: 9384 5Sec: 0.00%, 1Min: 0.00%, 5Min: 0.00%, Average: 0.00% Age: 5007208 msec, Runtime: 244 msec State: Waiting for Event, Priority: NormalVérification du contenu du champ PTR PS_NAME:
#show memory 0x6395634C 63956340: 536B696E Skin 63956350: 6E792053 6F636B65 74205365 72766572 ny Socket Server 63956360: 00000000 0A496E76 616C6964 20736B69 .....Invalid ski ->Skinny Socket ServerVérification que nous arrivons bien à la fin du bloc (présence d’un magic number FD0110DF) :
0x65A81864 + 2*[SIZE]+4 + SIZEOF(MAGICSTART) + [HEADERSIZE] = 0x65A81864 + 0X560 + 0x4 + 0x24 #show memory 0x65A81DEC 65A81DE0: FD0110DF }.._S'il nous venait à l’idée de réaliser un buffer overflow dans une zone mémoire, donc écrire plus de bytes prévu que ceux alloués pour cette zone mémoire, on finirait par écraser le header de la prochaine zone mémoire et donc rompre le chaînage mémoire IOS. Hélas, ou pas, l’IOS vérifie en permanence la structure de sa mémoire et à la moindre incohérence, force un crash. Donc pour réussir un buffer overflow sans crash, il faut s’arranger pour réécrire un header cohérant sur la prochaine zone mémoire. Ne pas oublier non plus de faire un « jmp » pour sauter à la suite de son code juste après le header !
Le post suivant
parlera du « chunk manager » de l’IOS.