[英]Reading from a data file in c
我一直在研究 Jon Erickson 的 The Art of Exploitation,但在從文件和他的代碼中讀取數據時,我遇到了一個症結。
有./notetaker 和./notesearch 兩個程序,前者用於創建帶有用戶id 的筆記,后者用於檢索當前用戶的筆記。
但是,在做筆記並嘗試通過 ./notesearch 訪問它之后,筆記不會像書中建議的那樣顯示為文本。
到目前為止,我已經推斷出在 ./notetaker 中創建的文件是一個數據文件,而不是文本文件,因此當它打印出來時是不可讀的。
那么為什么作者建議他的代碼有效,而實際上卻沒有,最簡單的解決方法是什么。
我已經開始將 fopen、fgets() 等視為解決方案,但它似乎與原始代碼相去甚遠。
如果我讓 ./notesearch 查看一個隨機文本文件,它將以人類可讀的形式打印出來,所以我認為問題在於原始文件的創建及其類型。
但不幸的是,我不知道如何克服這個問題
來自 ./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");
來自 ./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;
}
已解決:在 32 位 vm 上嘗試了代碼,一切都很好,雖然不完全確定為什么會這樣,但目前是我的工作。
這可能是因為代碼對整數和其他類型的大小做出了假設,而這些假設不應該。 例如...
int userid;
...
userid = getuid();
...
if (write(file_descriptor, &userid, 4) == -1)
fatal("in main() while writing userid to file");
那里有兩個錯誤。 getuid
返回一個uid_t
,而不是一個int
。 它們可能大小相同,因此可能會起作用。
更重要的是,他們將userid
的大小硬編碼為 4 個字節。 userid
是一個int
,它只能保證至少為 2 個字節。 在 32 位機器上,它通常是 4 個字節(32 位)。 在 64 位機器上,它是 8 個字節(64 位)。
它適用於 32 位 VM,因為int
有 4 個字節。
相反,使用正確的類型和sizeof
來獲取大小。
uid_t userid;
...
userid = getuid();
...
if (write(file_descriptor, &userid, sizeof(userid)) == -1)
fatal("in main() while writing userid to file");
總的來說,這段代碼的質量很差。 我希望這樣寫是為了說明目的。
strcpy(buffer, argv[1])
和strcpy(search_string, argv[1])
存在緩沖區溢出的風險。if
條件。 if (search_note(note_buffer, search_string))
printf("------ [ note data ] ------\n");
printf(note_buffer);
printf("\n");
縮進使它看起來像是在if
,但缺少大括號意味着它真的是這樣的:
if (search_note(note_buffer, search_string)) {
printf("------ [ note data ] ------\n");
}
printf(note_buffer);
printf("\n");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.