I've been working my way through The Art of Exploitation by Jon Erickson, but I've come to a sticking point regarding reading data from a file and his code.
There are two programs ./notetaker and ./notesearch, the former is used to create a note with the users id, the latter is used to retrieve notes by the current user.
However, after making a note and trying to access it through ./notesearch, the note isn't displayed as text as suggested in the book.
What I have deduced so far is that the file that is created in ./notetaker is a data file as opposed to a text file, so when it is printed out it is not readable.
So why is the author suggesting that his code works, when in reality it doesn't and what would be the simplest work around.
I have started looking at fopen, fgets() etc as the solution, but it seems to be far removed from the original code.
If I get ./notesearch to look at a random text file it will print out in human readable form, so the problem I believe lies in the creation of the original file and its type.
But unfortunately I am none the wiser as to how to overcome the problem
Snippet from ./notetaker
int main(int argc, char *argv[]) {
int userid;
int file_descriptor;
char *buffer, *datafile;
buffer = (char *) ec_malloc(100);
datafile = (char *) ec_malloc(20);
strcpy(datafile, "notes");
if (argc < 2)
usage(argv[0], datafile);
strcpy(buffer, argv[1]);
printf("[DEBUG] buffer @ %p: '%s'\n", buffer, buffer);
printf("[DEBUG] datafile @ %p: '%s'\n", datafile, datafile);
strncat(buffer, "\n", 1); //adds a newline to end
// opening file
file_descriptor = open(datafile, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR);
if (file_descriptor == -1)
fatal("in main() while opening file");
printf("[DEBUG] file descriptor is %d\n", file_descriptor);
userid = getuid();
// write data
if (write(file_descriptor, &userid, 4) == -1)
fatal("in main() while writing userid to file");
write(file_descriptor, "\n", 1);
if (write(file_descriptor, buffer, strlen(buffer)) == -1)
fatal("in main() while writing buffer to file");
write(file_descriptor, "\n", 1);
// closing file
if (close(file_descriptor) == -1)
fatal("in main() while closing file");
Snippet from ./notesearch
#define FILENAME "notes"
int print_notes(int, int, char *);
int find_user_note(int, int);
int search_note(char *, char *);
int main(int argc, char *argv[]) {
int userid, printing = 1, file_descriptor;
char search_string[100];
if (argc > 1)
strcpy(search_string, argv[1]);
else
search_string[0] = 0;
userid = getuid();
file_descriptor = open(FILENAME, O_RDONLY);
if (file_descriptor == -1)
fatal("in main() while opening file for reading");
while (printing)
printing = print_notes(file_descriptor, userid, search_string);
printf("------ [ end of note data ] ------\n");
close(file_descriptor);
}
// print notes for a given uid
// can match an optional search string
int print_notes(int file_descriptor, int uid, char *search_string) {
int note_length;
char byte = 0, note_buffer[100];
note_length = find_user_note(file_descriptor, uid);
// if EOF return 0
if (note_length == -1)
return 0;
read(file_descriptor, note_buffer, note_length); // read note data
note_buffer[note_length] = 0; // terminate string
// print note if search_string
if (search_note(note_buffer, search_string))
printf("------ [ note data ] ------\n");
printf(note_buffer);
printf("\n");
return 1;
}
// finds next note for given uid
int find_user_note(int file_descriptor, int user_uid) {
int note_uid = -1;
unsigned char byte;
int length;
while (note_uid != user_uid) {
if (read(file_descriptor, ¬e_uid, 4) != 4) // read uid data
return -1;
if (read(file_descriptor, &byte, 1) != 1) // read newline separator
return -1;
byte = length = 0;
while (byte != '\n') {
if (read(file_descriptor, &byte, 1) != 1) // read a single byte
return -1;
length++;
}
}
// rewind file by bytes length
lseek(file_descriptor, length * -1, SEEK_CUR);
printf("[DEBUG] found a %d byte note for user id %d\n", length, note_uid);
return length;
}
SOLVED: Tried the code on a 32 bit vm and all was well, although not entirely sure as to why this maybe, but has been my work around for the moment.
This is likely because the code makes assumptions about the size of integers and other types which it should not. For example...
int userid;
...
userid = getuid();
...
if (write(file_descriptor, &userid, 4) == -1)
fatal("in main() while writing userid to file");
There's two mistakes there. getuid
returns a uid_t
, not an int
. They might be the same size so it might work.
More important, they've hard coded the size of userid
as 4 bytes. userid
is an int
which is only guaranteed to be at least 2 bytes. On 32 bit machines it is typically 4 bytes (32 bits). On 64 bit machines it is 8 bytes (64 bits).
It works on a 32-bit VM because there int
is 4 bytes.
Instead, use the proper types and sizeof
to get the size.
uid_t userid;
...
userid = getuid();
...
if (write(file_descriptor, &userid, sizeof(userid)) == -1)
fatal("in main() while writing userid to file");
Overall the quality of this code is very poor. I'm hoping it's written this way for illustrative purposes.
strcpy(buffer, argv[1])
and strcpy(search_string, argv[1])
risk a buffer overflow. if
condition. if (search_note(note_buffer, search_string))
printf("------ [ note data ] ------\n");
printf(note_buffer);
printf("\n");
The indentation makes it look like it's all inside an if
, but the lack of braces means it's really this:
if (search_note(note_buffer, search_string)) {
printf("------ [ note data ] ------\n");
}
printf(note_buffer);
printf("\n");
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.