c - 格式化字符串漏洞,意外结果

标签 c string security unix exploit

我正在尝试在 64 位 Linux 上用 C 实现格式字符串漏洞的简单示例。这是我的源代码:

void not_called() {
    printf("Exploited\n");
}

int main(int argc, char **argv) {

    // Buffer overflow vulnerability
    char buffer[256];
    gets(buffer);

    // User may input the format string
    printf(buffer);
}

我将以下字符串输入到程序中

AAAABBBB-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x

结果是

AAAABBBB-8608002c-f458fe00-fbad2288-78252d78-252d7825-5e5c51a8-0-41414141-2d78252d-78252d78-252d7825-2d78252d

我可以将 AAAA 识别为 41414141,但不能像我预期的那样识别后面的 BBBB,因为它是缓冲区中同一输入字符串的组成部分。

这是某种保护机制还是我误解了什么?我的目标是覆盖返回地址,并且我需要读取 8 个字节 (AAAABBBB),因为我在 64 位机器上工作。

利用字符串的伪代码看起来像这样

RETRNPTR%[decimal address of not_called - 8]u%[offset of RETRNPTR]$n

RETRNPTR是当前栈帧中存储返回地址的内存地址。

所以我最担心的是,8 个字节的 RETRNPTR 似乎并没有像我期望的那样连续存在于内存中。第二个问题是,%n 是 int 指针,意味着只写入 4 个字节。我也很困惑,AAAA 之前的那些值是从哪里来的。

最佳答案

首先,您询问的是具有未定义行为的代码;对于普通 C 程序员来说,代码的大部分行为确实应该被认为是未定义的。

现在,为什么你看不到BBBB。我猜这是因为你在 x86-64 系统上运行这个程序。那里的调用约定是对堆栈上的值进行 64 位压入;但是 %x 打印 32 位 int; 64 位堆栈值的 32 个最低有效位。要打印 64 位 long 值,请使用 %lx

(此外,在 x86-64 的 System-V API 上,前 6 个整数/指针参数根本不进入堆栈;它们位于 RDIRSIRDXRCXR8R9 寄存器)。

例如我输入:

AAAABBBB %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx

并得到输出

AAAABBBB 7f7c0a88f030 7f7c0a66b980 7f7c0a669980 7f7c0a88f031 786c2520786c2520 7ffc1456b6f8
100000000 4242424241414141 786c2520786c2520 786c2520786c2520

关于c - 格式化字符串漏洞,意外结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36428345/

相关文章:

security - 如何设置将所有环境变量从 root 用户复制到另一个特定用户

javascript - 如何在javascript中的两个分隔符之间拆分字符串?

C++:从字符串流到字符**

php - 变量两边的这些点是什么?

java - Glassfish 3 安全性 - 使用 JDBC 领域的基于表单的身份验证

c - curses 中的 halfdelay 函数有什么作用?

c - 如何在c中将一些long double转换为long int?

c - 具有优先级队列实现的 Prim 算法

C:在运行时输入文本,之前没有设置固定的数组大小

api - 使用 Spring Boot 和 OAuth2 获取此资源的范围不足