格式化字符串利用长度

Format string exploit length

我是软件安全方面的新手,现在正在大学学习。我对格式字符串漏洞利用有一些疑问,特别是如何计算格式字符串漏洞利用的长度(字节数)。

假设我有以下易受攻击的代码:

 int guess(char *user) {
     struct {
          int n;
          char usr[16];
          char buf[16];
      } s;

      snprintf (s.usr, 16, "%s", user);

      do {
          scanf ("%s", s.buf);
          if ( strncmp (s.buf, "DEBUG", 5) == 0) {
              scanf ("%d", &s.n);
              for ( int i = 0; i < s.n; i++) {
                  printf ("%x", s.buf[i]);
              }
          } else {
              if ( strncmp (s.buf, "pass", 4) == 0 && s.usr[0] == '_') {
                  return 1;
          } else {
              printf ("Sorry User: ");
              printf (s.usr); //#line 26 vulnerable line
              printf ("\nThe secret is wrong! \n");
              abort ();
          }
          }
      } while ( strncmp (s.buf, "DEBUG", 5) == 0);
  }

 int main(int argc, char** argv) {
      guess(argv[1]);
 }

并且代码是在 IA-32 架构(32 位)中编译的,具有 cdecl 调用约定,并且没有实施攻击缓解(没有堆栈金丝雀,没有 ALSR 等......,我在一个完全易受攻击的机器中)

第 26 行存在格式字符串漏洞,因为缺少占位符 (printf (s.usr);)。

我想用包含我的 shellcode 的环境变量地址覆盖 EIP。

我假设(这是一个理论练习,我知道在实践中还有许多其他含义)我的环境变量的地址是 0x44674234,EIP 的地址是 0x42414515 并且我的格式字符串在堆栈上的位移是 7.

所以我的格式字符串利用将是 \x15\x45\x41\x42\x17\x45\x41\x42%16940c%7$hn%563c%8$hn,我将把它放入 user 然后它会被复制到 s.usr 并由 printf (s.usr);

现在我注意到只有 15 个字符从 user 复制到 s.usr

我的格式字符串不可利用吗?我在我的 exploit 中计算了 30 个字符,因此 strcpy 将只复制我的 exploit 的一半。

我算的字数对吗?我应该如何计算它们?

\x15\x45\x41\x42\x17\x45\x41\x42%16940c%7$hn%563c%8$hn 确实指的是 30 chars/bytes 的序列。因此需要 snprintf (s.usr, 31, "%s", user); 来复制它。[1] 额外的计数是因为 snprintf 为 NUL 保留了 space。

由于您需要 s.usr 作为 30 个字符序列的开始,并且您只能在其中放置 15 个必要的字符,因此您的 exploit 无法按原样工作。

这并不意味着该漏洞无法被利用。可以编写一个更短的漏洞利用程序,跳转到位于其他地方的剩余漏洞利用程序,例如在 user.[2] 但是我没有必要的知识来评估这个的可行性。


  1. 当然,你在s.usr中也需要更大的面积,至少在正常情况下是这样。
  2. user 将包含 <15-byte exploit><remainder of exploit>。 15 字节的漏洞将跳转到漏洞的其余部分。