Buffer Overflow verhindern.



  • Ich beschäfte mich seit ca. 3 Wochen mit C und versuche mich gerade ein wenig an den Arrays. Ich habe eine Passwortabfrage erstellt, allerdings wenn man zu viele Zeichen als Passwort eingibt kommt es zum Bufferoverflow. Weiß jemand wie ich das verhindern kann?

    Compiler: Borland C++ 5.02
    Mein Programmierstil ist nochnicht sehr sauber, deswegen benutze ich Borland.

    #include <stdio.h>
    #include <conio.h>
    main()
    {
     char p[20]="fdgdhl";
     char adresse[20];
     int f;
     int z=0;
     gets(adresse);
     for(int x=0;adresse[x]!=0;x+=1)
     {
      if(p[0+x]+1==adresse[0+x])
      {
       z+=1;
      }
      else
      {
       f=1;
      }
     }
     if(f!=1 && adresse[z]==0)
     {
      printf("Passwort richtig.");
     }
     else
     {
      printf("Passwort falsch.");
     }
      getch();
    }
    

    Das ist der Code bis jetzt. Ich habe auch schon eine kleine verschlüsselung des Passwortes gemacht.



  • Daniel H. schrieb:

    allerdings wenn man zu viele Zeichen als Passwort eingibt kommt es zum Bufferoverflow. Weiß jemand wie ich das verhindern kann?

    Benutze fgets an Stelle von gets.



  • Daniel H. schrieb:

    Mein Programmierstil ist nochnicht sehr sauber, deswegen benutze ich Borland.

    😕


  • Mod

    Die Funktion gets ist gefährlich und sollte nicht benutzt werden. Einfaches Googles nach deinem eigenen Titel hätte dir zahlreiche Verweise (sogar aus diesem Forum) zu fgets (da kann man eine Maximallänge angeben) und scanf (da geht das ebenfalls, macht aber natürlich je nach Formatstring etwas anderes als fgets) gegeben.

    P.S.: Dein Programmierstil ist, wie du festgestellt hast, überhaupt nicht sauber:
    - conio.h ist unportabel, dabei machst du nichts sinnvolles damit
    - Default int zu nutzen (wie bei deiner main-Funktion) ist veraltet

    • char p[20]="fdgdhl"; Lass doch den Compiler die Länge feststellen
    • gets , schon genannt
      - Hmm, wieviel ist wohl 0 + x?
    • printf , wenn du bloß eine unformatierte Zeichenkette ausgeben möchtest. Wie wäre es mit puts oder fputs ?
      - Wenn ich wüsste, was f, p und z bedeuten sollen, könnte man dein Programm vielleicht verstehen
      - Es gibt bessere Möglichkeiten, ein Programm offen zu halten, siehe FAQ. Die beste ist, es gar nicht offen zu halten, sondern so zu benutzen, wie für ein Konsolenprogramm vorgesehen, d.h. von einer Konsole.


  • Falls ich mir das jetzt richtig erdenken kann, willst du einfach nur eine Benutzereingabe auf Gleichheit mit einem bestehenden String vergleichen:

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
         char userPassword[] = "Hallo123!";
         char userEingabe[20];
    
         printf("Bitte geben Sie Ihr Passwort ein: ");
         scanf("%s", userEingabe);
    
         printf("\n");
    
         //strcmp liefert den wert 0, 1 oder -1 zurück. 0 bedeutet, dass die    beiden verglichenen Zeichenketten identisch sind.
         if(strcmp(userPassword, userEingabe) == 0)
         {
             puts("Eingeloggt!");
         }
    
         else
         {
             puts("Passwort falsch.");
         }
    
         printf("\n");
         return 0;
    }
    

    Das ist eine einmalige Abfrage. Du hast deinen Code nicht kommentiert, ich weiß gar nicht genau was du vorhast, oder wofür du eine For-Schleife brauchst? 😕

    edit: achso, ich hab gelesen ich habe noch keine verschlüsselung gemacht. 😃 sorrü, ich schau noch mal x)
    edit: übrigens:

    if(g != 1 && adresse[z] == 0)
    

    z ist an dieser Stelle immer 0.
    Also wird die Dezimalzahl des ersten Buchstaben der vom Benutzer eingegeben wurde auf == 0 überprüft. also ist die bedingung immer falsch.
    adresse[z];



  • Ich hab mein Programm schonmal ein bisschen Optimiert und dazu noch Kommentare geschrieben. Ich versuche mich auch gleich mal an fgets.

    #include <stdio.h>
    #include <conio.h>
     main()
     {
      char p[20]="fdgdhl";
      char passwort[20];
      int f; // Wenn 1 Zeichen falsch ist, stimmt das Passwort nicht überein
      int z=0; // zählt die Länge des passwortes
      gets(passwort);
      for(int x=0;passwort[x]!=0;x+=1) // Bestimmt die größe des Passwortes und passt die Schleife dementsprechend an
      {
       if(p[x]+1==passwort[x])  // Buchstabe für Buchstabe wird das passwort mit der eingabe verglichen
       {
        z+=1;
       }
       else
       {
        f=1;
       }
      }
      if(f!=1 && passwort[z]==0) //Wenn f nicht 1 ist und an der Z. Stelle des Arrays eine 0 steht
      {                         //(gets schreibt am ende eine /0' in den Speicher) ist das Passwort richtig
       printf("Passwort richtig.");
      }
      else
      {
       printf("Passwort falsch.");
      }
       getch();
     }
    

    PS: Alle Sachen die ich verwende sind veraltet, aber mir wurde gesagt ich soll mich erstmal mit C vertraut machen, bevor ich an einem richtig sauberen Programmierstil arbeite. Mir geht es auch nicht darum, dass ich etwas brauche womit ich mich einloggen kann, ich möchte einfach nur Arrays üben, damit habe ich nämlich noch ein paar probleme. Aber danke für die ganze Ratschläge ich versuche sie so gut wie möglich umzusetzten.



  • marvNN schrieb:

    char userEingabe[20];
    ...
         scanf("%s", userEingabe);
    

    Das ist genauso schlecht wie gets -- keine Bereichsprüfung. Mindestmaß für Stringeingabe ist

    scanf("%19s", userEingabe);
    

    Aber für eine Passwortabfrage ist das insofern ungeeignet, als dass so Whitespaces vorne und hinten ignoriert und im Passwort nicht erlaubt werden.

    Ganz schlicht gestrickt wäre

    #include <stdio.h>
    #include <string.h>
    
    int request_passphrase(char const *pw_valid) {
      char buffer[256];
      size_t pwlen = strlen(pw_valid);
    
      return pwlen < sizeof(buffer)
          && fgets(buffer, sizeof(buffer), stdin) != NULL
          && memcmp(pw_valid, buffer, pwlen) == 0
          && buffer[pwlen] == '\n';
    }
    
    int main(void) {
      if(request_passphrase("fdgdhl")) {
        puts("Richtig.");
      } else {
        puts("Falsch.");
      }
    
      return 0;
    }
    

    Für Fortgeschrittene ist dann das Unterdrücken des Tastaturechos und das Sperren des Speichers, so dass keine Passwörter permanent in den Swapspace geschrieben werden (Stichwort mlock; ein Windows-Äquivalent müsste ich erst raussuchen).



  • @marvNN
    Der TO hat die Gefährlichkeit von Bufferoverflows erkannt.
    Das kann man auch bei scanf umgehen. Also bitte dann:

    scanf("%s19", userEingabe);
    

    🙄



  • Das Problem ist, dass scanf keine Leerzeichen unterstützt.
    Könnte mir jemand ein Beispielt geben, wie fgets zu benutzen ist? Ich werde von dem was ich im Internet gefunden habe nicht schlau. Ich bin im moment so weit:

    fgets(passwort,20);
    


  • Daniel H schrieb:

    PS: Alle Sachen die ich verwende sind veraltet, aber mir wurde gesagt ich soll mich erstmal mit C vertraut machen, bevor ich an einem richtig sauberen Programmierstil arbeite. Mir geht es auch nicht darum, dass ich etwas brauche womit ich mich einloggen kann, ich möchte einfach nur Arrays üben, damit habe ich nämlich noch ein paar probleme. Aber danke für die ganze Ratschläge ich versuche sie so gut wie möglich umzusetzten.

    Du magst den Eindruck haben C sei veraltet. Das ist es nicht. Kurz vor Weihnachten 2012 wurde ein neuer Standard (C11) verabschiedet.
    Das kann zwar noch kein Compiler, aber an den Standard von 1989 sollte man sich schon halten.

    Vielleicht hat man dir auch gesagt, dass du dann mit C++ weitermachen kannst.

    C und C++ sind zwei verschiedene Programmiersprachen die jeweils ihren eigenen Programmierstil erfordern.

    Und gerade C erfordert sauberes Arbeiten, wie du ja selber festgestellt hast.

    Das du mit der Sprache erstmal rumspielst, ist völlig in Ordnung.



  • Daniel H. schrieb:

    Das Problem ist, dass scanf keine Leerzeichen unterstützt.
    Könnte mir jemand ein Beispielt geben, wie fgets zu benutzen ist? Ich werde von dem was ich im Internet gefunden habe nicht schlau. Ich bin im moment so weit:

    fgets(passwort,20);
    

    fgets erwartet 3 Parameter: http://www.cplusplus.com/reference/clibrary/cstdio/fgets/
    Den Puffer, die Länge des Puffers und ein Dateistream.
    Der Stream von der Konsole heißt stdin
    ⚠ fgets liest das abschließende '\n' (die Entertaste) mit ein und speichert sie ab.



  • Daniel H. schrieb:

    Das Problem ist, dass scanf keine Leerzeichen unterstützt.

    Das ist natürlich totaler Quatsch und falsch.
    Wenn dieselben Leute, die dir dies gesagt haben auch gesagt haben, C ist veraltet, du sollst aber "erstmal" trotzdem mit C anfangen, kannst du die Kompetenz dieser Leute arg bezweifeln, überhaupt irgendwas fachkundig beurteilen zu können, nicht nur C.



  • Ich habe nie gesagt C ist veraltet, ich habe gesagt mein Compiler ist veraltet da er von 1997 ist.



  • Und der erste C-Standard (sog. ANSI-C oder C89) ist von 1989.
    Und das unterstützt auch dein Compiler.

    C ist aber noch älter. Damals gab es noch keinen offiziellen Standard sondern nur die Beschreibung der Sprche von Kernighan & Ritchie.
    Diese war noch etwas anders als ANSI-C, darum übersetzt der Compiler das auch noch.

    Gewöhn dir gleich den richtigen Stil an.


Anmelden zum Antworten