web-dev-qa-db-fra.com

Compiler un exemple de débordement de tampon dans le Linux moderne?

J'essaie de compiler un exemple de débordement de tampon simple sur une VM debian i386 VM. L'exécutable est correcte, mais l'EIP n'est pas écrasée correctement malgré son entrée suffisamment grande pour déborder le tampon et écraser l'EIP poussée sur la pile. Voici mes commandes en tant que root:

sysctl -w kernel.randomize_va_space=0
gcc test.c -z execstack -z norelro -fno-stack-protector -D_FORTIFY_SOURCE=0 -ggdb -o test

Comme vous pouvez le voir, j'ai:

  • Fait l'exécutable de la pile
  • Pile enlevé Canaries
  • Système ASLR handicapé large
  • Suppression des protections relatives à relever
  • Protections FORTIFY_SOURCE de GCC handicapées

Voici Test.c:

#include <stdio.h>
#include <string.h>

int main(int argc, char **argv) {
  char buf[128];
  if(argc < 2) return 1;
  strcpy(buf, argv[1]);
  printf("%s\n", buf);
  return 0;
}

J'ai expérimenté des cordes de collision (tout aussi) de 128 à 256. Dans GDB, l'EIP poussée n'est jamais écrasée. De manière réaliste, il ne devrait pas simplement être une chaîne de 132 octets pour écraser EIP car il n'y a pas d'autres variables de pile locales.

Y a-t-il une autre protection que je dois désactiver lors de la compilation? Ou y a-t-il quelque chose d'autre pour désactiver avec SYSCTL?

12
B-MO

Votre exemple segfault ici (ou provoque la résiliation du programme si le protège-pile est actif).

Peut-être devriez-vous essayer de déplacer le débordement du tampon dans une autre fonction. Peut-être que votre version GCC convertit return 0; De Main dans exit(0);.

4
Ángel

Alors que la réponse acceptée est correcte pour suggérer de tout déplacer à une fonction différente n'explique pas pourquoi.


Comme vous pouvez le voir dans cette question et réponsemain() Les fonctions effectuent souvent un alignement de la pile pour vous assurer que la pile est configurée correctement. Les instructions suivantes sont effectuées:

83 e4 f0 and esp, 0xfffffff0

Cela alignera la pile à 8 octets. Cela signifie que une opération de soustraction a été effectuée sur esp. Donc, afin de déborder l'adresse de retour, vous avez besoin de 128 bytes + <variable stack alignment> + <optional saved ebp> + <new_return_address>.

J'ai compilé et dirigé votre programme (je devais ajouter un -m32).

Starting program: /home/user/Private/misc/overflow_test  
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCDDDDEEEEFFFFaaaabbbbcccc
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCDDDDEEEEFFFFaaaabbbbcccc

Program received signal SIGSEGV, Segmentation fault.
0x63636363 in ?? ()

J'ai utilisé 128 comme, puis 4 de chaque nouvelle lettre.

Décompresser le programme Nous voyons les lignes suivantes:

;      .//overflow_test.c:4
;-- main: 
;-- sym.main: 
0x0804842d    55             Push ebp  
0x0804842e    89e5           mov ebp, esp  
0x08048430    83e4f0         and esp, 0xfffffff0 
0x08048433    81ec90000000   sub esp, 0x90 

Nous voyons ici que 0x90 (144) est soustrait de la pile. Ce qui signifie que plus de 128 octets d'espace sont alloués pour les variables locales. ceci SO Réponse Donne des raisons pour lesquelles cela pourrait se produire. Donc, si vous comptez pour les 128 octets, les 16 octets supplémentaires ont ajouté pour les variables locales et assumez 8 octets d'alignement de la pile: alors vous avez écrasé par EBP avec 0x62626262 et l'adresse de retour avec 0x63636363.


Les fonctions normales n'effectuent généralement pas cette étape d'alignement de la pile. C'est pourquoi quand vous l'avez déplacé dans une fonction distincte, tout fonctionnait comme prévu. En véritable exploitation, les chances que vous exploitiez les paramètres dans une main() est hautement improbable. Il est plus réaliste d'être exécuté dans la portée d'une fonction différente.

13
RoraΖ