Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
工具/GitHubGitHub/yousif-iq/cve-2026-39259
嵌入式系统安全静态代码分析 (SAST)漏洞分析漏洞利用二进制分析学习与教育
GitHubyousif-iq/cve-2026-39259

CVE-2026-39259

CVE-2026-39259

查看仓库
22个月前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

SmallerC scanf s Stack.md

SmallerC - scanf %s 栈缓冲区溢出

项目: https://github.com/alexfru/SmallerC

SmallerC 的 scanf 实现在格式字符串中 %s 或 %[ 未指定显式字段宽度时,不会对字符串读取实施上限。运行时将持续向目标缓冲区写入,直到遇到空白字符或 EOF,而不管缓冲区实际分配的大小如何。任何超出边界的字节都会直接落入栈中,覆盖编译器放置在缓冲区上方的所有内容——局部变量、保存的寄存器、返回地址。

这并不是一类新颖的漏洞。自 C 语言早期以来,无界 scanf 字符串读取就已有记载,任何合格的静态分析工具都会将其标记出来。在 SmallerC 的背景下,这件事之所以值得报告,关键在于其目标环境。SmallerC 面向 DOS 和裸机嵌入式目标设计——这些平台按定义不提供栈金丝雀(stack canary)、ASLR、NX 位或任何那些让现代系统上漏洞利用变得困难的安全缓解措施。同一个原语,在加固的 Linux 二进制程序上要转化为可用的漏洞利用需要大量研究工作,而在运行于平坦、可预测栈上的 DOS 程序中则要容易处理得多。

缓冲区为 16 字节,输入为 20 个非空白字节。%s 转换没有宽度说明符,因此 sscanf 会将全部 20 个字节加上一个空终止符(共 21 字节)读入一个 16 字节的分配中。超出边界的 5 个字节破坏了相邻的栈内存。具体破坏哪些内容取决于编译器对该特定函数的栈布局决策,但覆盖本身是确定性的、无条件的——每当此代码路径以该输入运行时都会发生。

概念验证

root@kitploit:~
#include <stdioh>
#include <stringh>

/*
 * Build with SmallerC targeting DOS or bare-metal
 * Demonstrates unbounded %s write past a fixed stack buffer
 *
 * buffer is 16 bytes payload is 20 non-whitespace bytes
 * sscanf writes 21 bytes (20 + null terminator) into buffer
 * corrupting 5 bytes of adjacent stack memory
 *
 * To observe the corruption inspect stack memory after the call:
 * the 5 bytes immediately above buffer will contain 'A' (0x41)
 */

int main() {
    char buffer[16];
    char canary[8];

    memset(buffer 0x00 sizeof(buffer));
    memset(canary 0xCC sizeof(canary));  /* marker to detect overwrite */

    printf("[*] canary before: ");
    for (int i = 0; i < 8; i++) printf("%02x " (unsigned char)canary[i]);
    printf("\n");

    sscanf("AAAAAAAAAAAAAAAAAAAA" "%s" buffer);  /* 20 bytes into 16-byte buffer */

    printf("[*] canary after:  ");
    for (int i = 0; i < 8; i++) printf("%02x " (unsigned char)canary[i]);
    printf("\n");

    if (memcmp(canary "\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC" 8) != 0)
        printf("[!] stack corruption confirmed  canary overwritten\n");
    else
        printf("[-] canary intact (stack layout placed it elsewhere)\n");

    return 0;
}

受影响构建上的预期输出:

root@kitploit:~
[*] canary before: cc cc cc cc cc cc cc cc
[*] canary after:  41 41 41 41 41 cc cc cc
[!] stack corruption confirmed  canary overwritten

金丝雀相对于缓冲区的位置取决于编译器的栈布局。如果输出显示金丝雀完好,覆盖仍在发生——只是落在了缓冲区上方的其他内容上。请调整复现程序,用调试器检查实际的栈帧,以定位那 5 个被破坏字节的落点。

有一个值得明确指出的纠正:此类漏洞的一些报告中,尝试通过在载荷中的空字节后附加目标地址来演示返回地址控制,例如 "AAAAAAAAAAAAAAAAAAA\x00\x90\x04\x08"。这行不通。sscanf 中的 %s 转换将 \x00 视为字符串终止符,一遇到它就会立即停止读取。空字节之后的字节永远不会被处理。要真正演示返回地址控制,需要在载荷的关键部分中不含空字节的情况下完成覆盖,这又要求了解目标二进制程序的确切栈布局——从缓冲区到保存的返回地址的距离、编译器是否插入了任何填充,以及适用的对齐约束。这些都不是这个复现程序能自动得出的。

这个复现程序确实清楚确立的是破坏原语本身。越界写入是真实、可复现的,并且不依赖任何竞态条件或时序。在 DOS 或嵌入式目标上,栈布局在各次构建之间是静态且可预测的,从该原语通向可用漏洞利用是一项现实的研究工作,而非理论练习。

受影响场景虽然狭窄,但并非人为构造。程序必须同时满足:使用 SmallerC 构建、在 scanf 系列解析中使用无界 %s 或 %[ 说明符写入固定大小的栈缓冲区,以及接受来自攻击者可影响来源的输入。这四个条件必须同时成立。使用了正确字段宽度(例如 char[16] 用 %15s)的程序不受影响。不解析攻击者控制输入的程序不受影响。该问题本质上是 SmallerC 运行时在缺失宽度约束时处理不当的缺陷,但只有当应用程序代码将该缺陷暴露给不可信输入时,它才成为安全问题。

在应用程序方面,修复方法很直接:指定一个为空终止符留出空间的字段宽度——16 字节缓冲区用 %15s,64 字节缓冲区用 %63s。这是标准的 C 实践,格式字符串语法完全支持。在 SmallerC 项目方面,更持久的工作是添加回归测试,覆盖 scanf、sscanf 和 fscanf 中有界和无界的 %s 与 %[ 行为,验证实现确实遵守显式字段宽度,并醒目地记录这种不安全模式。当格式字符串字面量中的 %s 或 %[ 不带字段宽度出现时,编译器级诊断能够发出警告,从而主动防止此类错误,这将是工具链一个有意义的增强。

当外部输入到达易受攻击的代码路径时,严重性为中等(Medium);当输入为本地或非特权时,则降为低(Low)。目标环境——特别是 SmallerC 预期平台上缺乏现代漏洞利用缓解措施——是使其区别于泛泛的"不要使用无界 scanf"建议、并值得在项目层面报告而非纯粹视为应用层误用的原因。

致谢:Yousif Wazni

下载工具