CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

C - buffer overflow

rangerprice
rangerprice
Niveau 10
11 juin 2016 à 22:22:05

Bonjour.

J'ai fais un petit programme qui me servira de programme de teste pour essayer des attaques par buffer overflow dans le cadre de mon apprentissage en reverse engineering.
http://pastebin.com/kTqHqWKL
Il demande un mot de passe, et ce mot de passe n'a juste aucune chance d'être correcte, puisqu'il n'existe pas de mot de passe correcte. Pour passer la sécurité il faut performer un buffer overflow et changé le contenu de la variable "r" dans checkPass().

J'ai réussis à le faire mais il y a quelque chose que je comprend pas.
Le "r" étant un entier sur 4 octets, et le buffer faisant 20 octets, checkPass doit avoir une stack frame de 24 octets.

Lorsque j'entre a x 22 en input, ça ne marche pas. (c'est ça que je comprend pas.)
mais lorsque j'entre 24 ou 23 x 'a' ça marche.

Normalement, si on entre a plus de 20 fois, ça devrait marcher car au delà de 20 il y a buffer overflow et les nouveaux octets iront sur "r".
alors si j'entre 21 fois "a" ça devrait marcher non ? :hap:
et pourtant ça marche pas à moins de mettre au minimum 23 fois "a" lorsqu'on demande un mot de passe. Pourquoi ? je me suis trompé dans mes calcules ? j'utilise gdb je peux fournir plus d'informations sur le programme si nécéssaire.

Message édité le 11 juin 2016 à 22:24:45 par rangerprice
drakenlorde
drakenlorde
Niveau 9
12 juin 2016 à 00:00:37

La raison pourquoi il n'y a pas d'overflow à 20 'a' est parce que le stack frame n'est pas de 24 octets et que l'espace utilisé par le tableau de 20 char n'est pas collé sur les 4 octets de r.

En compilant avec gcc, il me éserve un stack frame de 64 octets. Puis, il met le r sur les 4 premiers octets et le tableau de 20 char est alligné à partir de 32 octets en remontant vers le r.

Je soupçonne que pourquoi le nombre de 'a' ne semble pas juste est parce que la function strcpy copie plusieurs octets à la fois, donc si tu arrives sur un nombre injuste d'octets, eh bien les octets supplémentaires manquant seront simplement écrasés par la grosseur de l'opération de copie.

Message édité le 12 juin 2016 à 00:03:12 par drakenlorde
rangerprice
rangerprice
Niveau 10
12 juin 2016 à 05:01:54

drakenlorde :d) Après avoir desassemblé checkPass(), c'est un peu plus claire mais il y a certaines choses que je ne comprend pas. :hap:
http://pastebin.com/HZTq3WhE
On peut y voir "r" stocké tout de suite après rbp, et je crois que strcpy() fait passer ses paramètres dans les registres rsi et rdi(et peut etre aussi rax), après, je comprend plus rien.

Même le stockage de buffer me semble bizarre :hap: à cause de la ligne 6 qui stocke 'M' dans ce qui est censé être le premier element du buffer, hors c'est impossible sinon il n'y aurait pas assez de place pour stocker les 19 autres octets de buffer de façon contigu. :hap:

drakenlorde
drakenlorde
Niveau 9
12 juin 2016 à 06:51:19

La mémoire du stack fonctionne de bas en haut et non l'inverse.

Le 'm' est stocké à rbp-32 et la dernière case du tableau va être à rbp-12. (20 octets plus haut)

Pourquoi il réserve 48 octets alors qu'il en a besoin que 24? De un, le stack frame doit être alligné sur des blocs de 16 octets. Donc 16, 32, 48.... Pourquoi prend t-il 48 alors que 32 fonctionne? Tout simplement à cause du compilateur qui gère la mémoire de cette façon.

rangerprice
rangerprice
Niveau 10
12 juin 2016 à 09:13:03

Attends le haut c'est rbp ou rsp pour toi ? :hap:

rangerprice
rangerprice
Niveau 10
12 juin 2016 à 10:24:39

Bon, j'ai presque entièrement compris.

Mais j'ai une dernière question.
https://image.noelshack.com/fichiers/2016/23/1465719108-2016-06-12-051100-1366x768-scrot.png
Comme tu peux le voir sur ce screen ci dessus j'ai fais une modification, en mettant la valeur du dernier element de buffer à 'M'.

En examinant buffer avec gdb, je vois clairement tout le contenu du tableau, et l'adresse de fin également. Le buffer étant long de 20 octets, je devrais avoir un espacement de 14(20 en hexa) entre l'adresse de début du tableau, et l'adresse de fin du tableau. Hors ça n'est pas le cas.
En effet on peut voir que l'espacement est de 13. C'est ce petit détail qui me rend fou. :fou:

Pourtant on peut bien y voir 20 adresses différentes, 20 données différentes, alors pourquoi il y a seulement 13(19 en hexa) d'espace entre l'adresse de début et de fin du tableau ?! je dois rater un tout petit détail, le diable s'y cache, aide moi à le trouver. :hap:

Pseudo supprimé
Pseudo supprimé 12 juin 2016 à 11:33:21

Linux impose que la valeur de RSP soit un multiple de 16 avant l'appelle d'une procédure. Hors,

call <procedure address>

C'est équivalent de

push <return address>     ; 8 bytes
jmp  <procedure address>

Ca veut donc dire qu'a l’entrée de la procedure, RSP n'est plus aligné sur 16: il y a 8 de trops, il faut les prendre en compte pour aligner RSP avant l’appelle d'une autre procédure.

Ton code:


address de retour               8 octets
const char * pass;              8 octets
int r;                          4 octets
char buffer[20] ;              20 octets
----------------------------------------
                               40 octets

le prochain multiple de 16 c'est 48, 30 en base 16, d'où sub rsp, 0x30

drakenlorde
drakenlorde
Niveau 9
12 juin 2016 à 15:11:14

Pourtant on peut bien y voir 20 adresses différentes, 20 données différentes, alors pourquoi il y a seulement 13(19 en hexa) d'espace entre l'adresse de début et de fin du tableau ?! je dois rater un tout petit détail, le diable s'y cache, aide moi à le trouver. :hap:

On part de RBP-32 à RBP-13.
Soit les éléments d'index 0 à 19.
RBP-32, c'est buffer[0].
RBP-13, c'est buffer[19].
De 0 à 19, ça fait un total de 20 éléments. (tu oublies de compter le 0)

Message édité le 12 juin 2016 à 15:12:57 par drakenlorde
rangerprice
rangerprice
Niveau 10
12 juin 2016 à 21:47:08

Merci pour ton aide CodeArtisan et la tienne aussi drakenlorde. Je comprend tout à présent. :hap:

Sous forums
  • Aide à l'achat Mac
  • Création de Jeux
  • Linux
  • Création de sites web
  • Programmation
  • Internet
  • Steam Deck
  • Macintosh
  • Hardware
La vidéo du moment