Adresse de retour d'un fonction (C/ASM)

Résolu
cs_bouba Messages postés 518 Date d'inscription dimanche 2 décembre 2001 Statut Membre Dernière intervention 10 novembre 2007 - 29 mai 2006 à 22:57
cs_bouba Messages postés 518 Date d'inscription dimanche 2 décembre 2001 Statut Membre Dernière intervention 10 novembre 2007 - 31 mai 2006 à 19:27
Bonjour, je suis en train de suivre un tutorial sur les Buffers Overflow (http://www.cgsecurity.org/exploit/p49-14.txt), mais je ne comprends pas un truc sur les adresses de retours dans la pile.
J'ai le code C suivant que je désassemble .

#include <stdio.h>

void function(int a, int b, int c) {
  char buffer1[5];
  char buffer2[10];
  int * ret;

  /* Je modifie l'adresse de retour de function pour sauter une instruction dans le main */
  ret = (int)buffer1 + 13; // Dans le turorial +12
  *ret = *ret + 7;  // Dans le tutorial +8

  printf("ret %x\n", *ret);
}

int main(void) {
  int x;

  x = 0;
  function(1,2,3);
  x = 1;  // Je souhaite sauter cette instruction en modifiant l'adresse de retour dans function
  printf("%d\n", x); // Ici le printf affiche bien 0 comme il se doit

  return 0;
}

Le désassemblage du code me donne un truc comme ça:
...
0x080483c1 <main+58>:   call   0x8048354 <function>
0x080483c6 <main+63>:   movl   $0x1,0xfffffffc(%ebp)
0x080483cd <main+70>:   mov    0xfffffffc(%ebp),%eax
...
Je saute passe donc directement de 0x080483c1 à 0x080483cd en ajoutant 0x080483cd-0x080483c6=7 à l'adresse de retour de function.
Pour accéder à la valeur de retour je fais ret = (int)buffer1 + 13 ; car on a le schéma suivant en mémoire
bottom of top of
memory memory
buffer2 buffer1 sfp ret a b c
<------ [ ][ ][ ][ ][ ][ ][ ]

top of bottom of
stack stack

C'est ici que je ne pige pas, en ajoutant 13 j'arrive à accéder à ret, mais pourtant en comptant bien, on s'aperçoit que buffer1 fait 8 octets, sfp 4, donc 8+4 =12 ! Alors pourquoi en ajoutant 13 j'arrive à accéder à ret, mais avec 12 je ne tappe pas ou il faut !! C'est sans doute une erreur de ma part, ou alors la gars a du se planter dans le turorial puisqu'il utilise 
ret = (int)buffer1 + 12;
*ret = *ret + 8;
Pouvez-vous m'expliquer ce qui n'est pas correct dans mon raisonnement SVP ?

Merci.

Bouba

4 réponses

BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
30 mai 2006 à 22:10
Au moment où tu entres dans la fonction, l'adresse retour est en [esp] et pas ailleurs.
Pour autant c'est assez aléatoire d'y accéder avec seulement du C, dépendra déjà si le compilo aura fait ou non une stackframe (meme en désactivant l'option il en met parfois s'il juge utile...).

ciao...
BruNews, MVP VC++
3
Guilou34 Messages postés 142 Date d'inscription mercredi 5 avril 2006 Statut Membre Dernière intervention 29 janvier 2016 1
31 mai 2006 à 02:17
C'est le cas avec visual  studio.net, buffer1 prend 10 octets et buffer2 en prend 20
Pour m'en rendre compte ,j'ai rajouté les lignes initialisant buffer1 et buffer2[0]:
 char buffer1[5];
  char buffer2[10];
buffer1[0]='A';
buffer1[1]='B';
buffer1[2]='C';
buffer1[3]='D';
buffer1[4]='E';
buffer2[0]='0';
  int * ret;
 Comme le signale BruNews, quelque soit le compilateur, à l'entrée de la fonction esp pointe sur l'adresse de retour et, si on veut modifier cette  valeur,  il est quand même plus simple de  coder en asm:  add [esp], valeur. Non ?  .
Salut.
3
cs_bouba Messages postés 518 Date d'inscription dimanche 2 décembre 2001 Statut Membre Dernière intervention 10 novembre 2007 3
31 mai 2006 à 18:46
Ok, je viens d'essayer de faire quelques tests avec esp en insérant du code ASM inline. Mais je ne pige pas, il semble que l'adresse de retour dans
ESP ne corresponde pas à l'adresse de retour que mon debugger m'affiche.

void function(int a, int b, int c) {

  char buffer1[5];

  char buffer2[10];

}

main() {
    int x;

    /* On met l'adresse de ebp dans x */

  asm("movl (%%ebp), %0;"

         :"=r"(x));


  /* Affichage de x, donc de [ebp] */

  printf("x %x\n", x);

    function(1,2,3);
    return 0;
}

L'affichage me donne ceci:
x bf8320f8


Alors que le debugger me donne
0x080483a8 <main+76>:   call   0x8048354 <function>
0x080483ad <main+81>:   mov    $0x0,%eax

L'adresse de ebp avant de rentrer dans la fonction est bf8320f8 celle que m'affiche le debugger est 0x080483ad, pourquoi sont-elles différentes ?

Merci.

Bouba
0
cs_bouba Messages postés 518 Date d'inscription dimanche 2 décembre 2001 Statut Membre Dernière intervention 10 novembre 2007 3
31 mai 2006 à 19:27
Oups, autant pour moi, ça marche, merci pour vos indices, le code avec ESP pour sauter l'instruction x=1 est le suivant:
#include <stdio.h>

void function(int a, int b, int c) {
  char buffer1[5];
  char buffer2[10];
  int x;

  asm("addl $7,4(%ebp)"); // EIP se voit ajouter de 7 pour sauter l'instruction
}

int main(void) {
  int x;
  x = 0;
  function(1,2,3);
  x = 1;
  printf("x %d\n",x);
  return 0;
}

Merci.

Bouba.
0
Rejoignez-nous