[英]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.