[Hacking - Die Kunst des Exploits] C - Lesen aus einer Datei funktioniert nicht

Hallo da draußen,
ich bin seit einigen Jahren schon am programmieren mit C++ und SDL, sowie SFML.
Nun habe ich mir das Buch "Hacking - Die Kunst des Exploits" von Jon Erickson besorgt, in dem mit C unter Linux programmiert wird, und auch schon fleißig angefangen. Ich benutze Ubuntu 14.04.
Allerdings brüte ich jetzt schon länger über einem Problem, das sich nicht lösen lässt und dachte, ich schreib mal hier, vielleicht kann mir jemand helfen.
Ich habe zwei kleine Programme.
Das erste, "notetaker", nimmt als Argument einen string entgegen und schreibt diesen, zusammen mit der Benutzer-ID in eine Datei.

notetaker.c

Code:
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <fcntl.h> 
#include <sys/stat.h> 
#include "hacking.h" 
 
void usage(char *prog_name, char *filename) { 
   printf("Usage: %s <data to add to %s>\n", prog_name, filename); 
   exit(0); 
} 
 
void fatal(char *);            // a function for fatal errors 
void *ec_malloc(unsigned int); // an errorchecked malloc() wrapper 
 
int main(int argc, char *argv[]) { 
   int userid, fd; // file descriptor 
   char *buffer, *datafile; 
 
   buffer = (char *) ec_malloc(100); 
   datafile = (char *) ec_malloc(20); 
   strcpy(datafile, "/var/note"); 
 
   if(argc < 2)                // If there aren't commandline arguments 
      usage(argv[0], datafile); // display usage message and exit 
 
   strcpy(buffer, argv[1]);  // copy into buffer 
 
   printf("[DEBUG] buffer   @ %p: \'%s\'\n", buffer, buffer); 
   printf("[DEBUG] datafile @ %p: \'%s\'\n", datafile, datafile); 
 
 // Opening the file 
   fd = open(datafile, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR); 
   if(fd == -1) 
      fatal("in main() while opening file"); 
   printf("[DEBUG] file descriptor is %d\n", fd); 
 
   userid = getuid(); // get the real user ID 
 
   if(write(fd, &userid, 4) == -1) 
      fatal("in main() while writing userid to file"); 
   write(fd, "\n", 1); 
 
   if(write(fd, buffer, strlen(buffer)) == -1) // write note 
      fatal("in main() while writing buffer to file"); 
   write(fd, "\n", 1); // terminate line 
 
// Closing file 
   if(close(fd) == -1) 
      fatal("in main() while closing file"); 
 
   printf("Note has been saved.\n"); 
   free(buffer); 
   free(datafile); 
}
hacking.h

Code:
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
 
// A function to display an error message and then exit 
void fatal(char *message) { 
   char error_message[100]; 
 
   strcpy(error_message, "[!!] Fatal Error "); 
   strncat(error_message, message, 83); 
   perror(error_message); 
   exit(-1); 
} 
 
// An error checked malloc() wrapper function 
void *ec_malloc(unsigned int size) { 
   void *ptr; 
   ptr = malloc(size); 
   if(ptr == NULL) 
      fatal("in ec_malloc() on memory allocation"); 
   return ptr; 
}
Das zweite, "notesearch", gibt alle Notizen aus, die der Benutzer, der dieses Programm aufruft, mithilfe des notetakers in die Datei geschrieben hat. (Zusätzlich kann man noch einen Suchbegriff hinzufügen).

notesearch.c

Code:
#include <stdio.h> 
#include <string.h> 
#include <fcntl.h> 
#include <sys/stat.h> 
#include "hacking.h" 
 
#define FILENAME "/var/note" 
 
int print_notes(int, int, char *);   // note printing function 
int find_user_note(int, int);        // seek in file for a note for user 
int search_note(char *, char *);     // search for keyword function 
void fatal(char *);                  // fatal error handler 
 
int main(int argc, char *argv[]) { 
    int userid, printing=1, fd; // file descriptor 
    char searchstring[100]; 
 
    if(argc > 1)                        // If there is an arg 
        strcpy(searchstring, argv[1]);   //   that is the search string 
    else                                // otherwise 
        searchstring[0] = 0;             //   search string is empty 
 
    userid = getuid(); 
    fd = open(FILENAME, O_RDONLY);   // open the file for read-only access 
    if(fd == -1) 
        fatal("in main() while opening file for reading"); 
 
    while(printing) 
        printing = print_notes(fd, userid, searchstring); 
    printf("-------[ end of note data ]-------\n"); 
    close(fd); 
} 
 
// A function to print the notes for a given uid that match 
// an optional search string 
// returns 0 at end of file, 1 if there are still more notes 
int print_notes(int fd, int uid, char *searchstring) { 
    int note_length; 
    char byte=0, note_buffer[100]; 
     
    note_length = find_user_note(fd, uid); 
    if(note_length == -1)  // if end of file reached 
        return 0;           //   return 0 
 
    read(fd, note_buffer, note_length); // read note data 
    note_buffer[note_length] = 0;       // terminate the string 
     
    if(search_note(note_buffer, searchstring)) // if searchstring found 
        printf(note_buffer);                    //   print the note 
    return 1; 
} 
 
// A function to find the next note for a given userID 
// returns -1 if the end of the file is reached 
// otherwise it returns the length of the found note 
int find_user_note(int fd, int user_uid) { 
    int note_uid=-1; 
    unsigned char byte; 
    int length; 
 
    while(note_uid != user_uid) {  // loop until a note for user_uid is found 
        if(read(fd, &note_uid, 4) != 4) // read the uid data 
            return -1; // if 4 bytes aren't read, return end of file code 
        if(read(fd, &byte, 1) != 1) // read the newline separator 
         return -1; 
 
        byte = length = 0; 
        while(byte != '\n') {  // figure out how many bytes to the end of line 
            if(read(fd, &byte, 1) != 1) // read a single byte 
                return -1;     // if byte isn't read, return end of file code 
            length++;   
        } 
    } 
    lseek(fd, length * -1, SEEK_CUR); // rewind file reading by length bytes 
 
    printf("[DEBUG] found a %d byte note for user id %d\n", length, note_uid); 
    return length; 
} 
 
// A function to search a note for a given keyword 
// returns 1 if a match is found, 0 if there is no match 
int search_note(char *note, char *keyword) { 
    int i, keyword_length, match=0; 
 
    keyword_length = strlen(keyword); 
    if(keyword_length == 0)  // if there is no search string 
        return 1;              // always "match" 
     
    for(i=0; i < strlen(note); i++) { // iterate over bytes in note 
        if(note[i] == keyword[match])  // if byte matches keyword 
            match++;   // get ready to check the next byte 
        else {        //   otherwise 
            if(note[i] == keyword[0]) // if that byte matches first keyword byte 
                match = 1;  // start the match count at 1 
            else 
                match = 0;  // otherwise it is zero 
        } 
        if(match == keyword_length) // if there is a full match 
            return 1;   // return matched 
    } 
    return 0;  // return not matched 
}
Das Schreiben der Notizen funktioniert soweit, aber wenn ich versuche mit notesearch die Notizen wieder auszugeben, gibt er mir anstelle der Notiz nur unlesbare Zeichen aus. (vgl. Screenshot vorletzte Zeile)

Anhang anzeigen 4016


Könnt ihr mir helfen? Ich habe alles so gemacht, wie es auch im Buch steht, bzw. auf der Seite hacking - Die Kust des Exploits - the art of Exploits (eine Aktualisierung zum Buch). Warum werden nur komische Zeichen ausgegeben?
Danke schon mal im Voraus.
 
1. Rückgabewerte überprüfen ist äußerst hilfreich
2. Das Zurückspringen mit lseek war der Fehler, da wird es schon um ein Byte +/- nicht gepasst haben. Einfacher ist es an der Stelle, wenn man zu Beginn die aktuelle Position ermittelt und danach zu dieser wieder zurückspringt. Dann muss man nicht relativ in der Datei herum springen.

mfg benediktibk
 
Danke für die Antwort :)
Komisch nur, dass es im Buch dann offensichtlich geklappt hat...
Aber ich werde deine Lösung gleich mal ausprobieren.
 
Ich bin mir inzwischen auch gar nicht mehr sicher ob es da wirklich einfach nur um ein Byte gehapert hat, vielleicht ist off_t auch ein unsigned Datentyp. Das könnte ebenfalls das Problem sein, aber da bin ich jetzt mal zu faul zum googlen. Kannst du aber gerne selber machen ;-).

mfg benediktibk
 
Ich habs ausprobiert und es hat mit deiner Lösung geklappt.
Weiß auch nicht, warum es im Buch auch anders funktioniert hat.
Wie auch immer, dankeschön :)
 
Danke!

Ich war schon am verzweifeln, da ich das selbe problem hatte und habe nebenbei auch noch ein interessantes Forum gefunden.
 
Hallo hier der L3nny,
Ich arbeite mich auch gerade durch das Buch und bin durch Herumexperimentieren auf eine andere Lösung gekommen. Mir ist nebenbei bei vielen Beispielen aufgefallen das die Speicher heutzutage alle etwas größer sind und bin daher gut damit gefahren einfach mal vor ein int ein long oder long long zu setzten.

Deklariere einfach: long int length; und schon wirds funzen.:wink:
Promis ;-)
 
Zuletzt bearbeitet:
Zurück
Oben