《Hacking:漏洞利用艺术》旧C代码编译write/close隐式声明报错咨询
告警原因分析与修复方案
告警原因
三个告警分别对应两类问题:
write、close隐式声明告警:这两个是Linux系统调用,声明在<unistd.h>头文件中,原书代码漏加了该头文件。早年C编译器对函数隐式声明的检查规则宽松,缺头文件也可以编译,但是新版编译器默认开启了严格检查,因此会抛出告警。strncat溢出告警:strncat的第三个参数指定的是最多从源字符串拷贝的字节数,函数执行完成后会自动在目标字符串末尾追加'\0'结束符。原代码指定拷贝1字节,刚好和源字符串"\n"的有效内容长度相等,此时strncat会额外写入1字节的结束符,如果buffer剩余空间不足就会发生越界。同时原代码没有对argv[1]的输入长度做校验,如果用户输入的内容超过98字节,100字节的buffer完全容不下输入内容+换行符+结束符,确实存在溢出风险,属于原书代码的已知疏漏。
修复方案
第一步:补全头文件
在代码的头文件引入区域新增一行:
#include <unistd.h>
即可解决write、close的隐式声明告警。
第二步:修复strncat问题
两种修复方式可选:
- 优先选择:新增输入长度校验,从根源避免溢出:
在strcpy(buffer, argv[1]);之前加校验逻辑:if(strlen(argv[1]) > 98) { fatal("input is too long, max 98 characters allowed"); } - 快速消除告警:将原
strncat(buffer, "\n", 1);修改为直接赋值的写法,避免编译器误判(也更高效):size_t buf_len = strlen(buffer); buffer[buf_len] = '\n'; buffer[buf_len + 1] = '\0';
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <sys/stat.h> #include <unistd.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 fatar errors void *ec_malloc(unsigned int); // An error-checked malloc() wrapper int main(int argc, char *argv[]) { int fd; // file descriptor char *buffer, *datafile; buffer = (char *) ec_malloc(100); datafile = (char *) ec_malloc(20); strcpy(datafile, "/tmp/notes"); if (argc < 2) // If there aren't command-line arguments, usage(argv[0], datafile); // display usage message and exit. // 新增输入长度校验 if(strlen(argv[1]) > 98) { fatal("input too long: max allowed length is 98 characters"); } strcpy(buffer, argv[1]); // Copy into buffer. printf("[DEBUG] buffer @ %p: '%s'\n", buffer, buffer); printf("[DEBUG] datafile @ %p: '%s'\n", datafile, datafile); // 替换原strncat写法 size_t buf_len = strlen(buffer); buffer[buf_len] = '\n'; buffer[buf_len + 1] = '\0'; // Opening 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); //Writing data if(write(fd, buffer, strlen(buffer)) == -1) fatal ("in main() while writing buffer to file"); //Closing file if(close(fd) == -1) fatal ("in main() while closing file"); printf("Note has been saved.\n"); free(buffer); free(datafile); } // A function to display and 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"); exit(-1); } return ptr; }
修复后直接用gcc编译即可无告警运行。
内容的提问来源于stack exchange,提问作者rctfx
相关产品推荐
相关产品推荐

