You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

《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问题

两种修复方式可选:

  1. 优先选择:新增输入长度校验,从根源避免溢出:
    在strcpy(buffer, argv[1]);之前加校验逻辑:
    if(strlen(argv[1]) > 98) {
        fatal("input is too long, max 98 characters allowed");
    }
    
  2. 快速消除告警:将原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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 03:36:04