无法覆盖返回地址以创建堆栈溢出

时间:2018-03-07 16:03:37

标签: c assembly gdb stack-overflow x86-64

我正在尝试书籍The Shellcoder's Handbook: Discovering and Exploiting Security Holes, 2nd Edition第23页的一个例子。下面是我所指的C程序,它需要用户输入并测试条件User Input % 853 == 83。我在64位Linux机器上试用这个例子。

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

int valid_serial(char *psz){

    size_t len = strlen(psz);
    unsigned total = 0;

    if (len<0){
        return 0;
    }

    for (size_t i = 0; i < len; i++){

        if(psz[i] < '0' || psz[i] > 'z'){
            return 0;
        }
        total += psz[i];
    }
    if (total % 853 == 83){
        return 1;
    }

    return 0;
}
int validate_serial(){

    char serial[24];
    fscanf(stdin, "%s", serial);

    if(valid_serial(serial)){
        return 1;
    }
    else{
        return 0;
    }
}

int do_valid_stuff(){
    printf("The entered serial number is valid\n");
    exit(0);
}

int do_invalid_stuff(){
    printf("The entered serial number is Invalid\n");
    exit(1);
}
int main(void){

    if (validate_serial()){
        do_valid_stuff();
    }
    else{
        do_invalid_stuff();
    }
    return 0;
}

我编译了上面的程序,并使用gcc -g -fno-stack-protector serial.c -o serial关闭了堆栈保护程序,正如预期的那样程序运行正常

$ printf "HHHHHHHHHHHHH" | ./serial
The entered serial number is valid
$ printf "1234" | ./serial
The entered serial number is Invalid

Q1)如何在GDB中输入十六进制值?

在GDB中,我在以下行创建断点

line 31          fscanf(stdin, "%s", serial);
line 33          if (valid_serial(serial));

在第一个断点第31行,这就是我所拥有的

(gdb) disassemble main
Dump of assembler code for function main:
   0x0000555555554912 <+0>: push   rbp
   0x0000555555554913 <+1>: mov    rbp,rsp
   0x0000555555554916 <+4>: mov    eax,0x0
   0x000055555555491b <+9>: call   0x555555554899 <validate_serial>
   0x0000555555554920 <+14>:    test   eax,eax
   0x0000555555554922 <+16>:    je     0x555555554930 <main+30>
   0x0000555555554924 <+18>:    mov    eax,0x0
   0x0000555555554929 <+23>:    call   0x5555555548de <do_valid_stuff>
   0x000055555555492e <+28>:    jmp    0x55555555493a <main+40>
   0x0000555555554930 <+30>:    mov    eax,0x0
   0x0000555555554935 <+35>:    call   0x5555555548f8 <do_invalid_stuff>
   0x000055555555493a <+40>:    mov    eax,0x0
   0x000055555555493f <+45>:    pop    rbp
   0x0000555555554940 <+46>:    ret
End of assembler dump.
(gdb) x/20xg $rsp
0x7fffffffe4f0: 0x0000000000000000  0x0000000000000000
0x7fffffffe500: 0x0000555555554950  0x00005555555546c0
0x7fffffffe510: 0x00007fffffffe520  0x0000555555554920
0x7fffffffe520: 0x0000555555554950  0x00007ffff7a5a2b1
0x7fffffffe530: 0x0000000000040000  0x00007fffffffe608
0x7fffffffe540: 0x00000001f7b9b2e8  0x0000555555554912
0x7fffffffe550: 0x0000000000000000  0x9eeb30dff32f3990
0x7fffffffe560: 0x00005555555546c0  0x00007fffffffe600
0x7fffffffe570: 0x0000000000000000  0x0000000000000000
0x7fffffffe580: 0xcbbe658aabef3990  0xcbbe753e255d3990
(gdb)

因此,在下一步中,我必须使用validate_serial指令0x0000555555554920的地址覆盖call do_valid_stuff的返回地址0x0000555555554929 }} 继续gdb

(gdb) c
Continuing.
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)IUUUU

Breakpoint 2, validate_serial () at serial.c:33
33      if(valid_serial(serial)){

成功覆盖了返回地址

(gdb) x/20xg $rsp
0x7fffffffe4f0: 0x4141414141414141  0x4141414141414141
0x7fffffffe500: 0x4141414141414141  0x4141414141414141
0x7fffffffe510: 0x4141414141414141  0x0000555555554929
0x7fffffffe520: 0x0000555555554950  0x00007ffff7a5a2b1
0x7fffffffe530: 0x0000000000040000  0x00007fffffffe608
0x7fffffffe540: 0x00000001f7b9b2e8  0x0000555555554912
0x7fffffffe550: 0x0000000000000000  0x9eeb30dff32f3990
0x7fffffffe560: 0x00005555555546c0  0x00007fffffffe600
0x7fffffffe570: 0x0000000000000000  0x0000000000000000
0x7fffffffe580: 0xcbbe658aabef3990  0xcbbe753e255d3990
(gdb) c
Continuing.
The entered serial number is valid
[Inferior 1 (process 9851) exited normally]
(gdb)

我无法使用以下方法将地址覆盖为0x0000555555554929。

(gdb) c
Continuing.
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x29\x49\x55\x55\x55\x55\x00\x00
(gdb) x/20xg $rsp
0x7fffffffe4f0: 0x4141414141414141  0x4141414141414141
0x7fffffffe500: 0x4141414141414141  0x4141414141414141
0x7fffffffe510: 0x4141414141414141  0x3934785c3932785c
0x7fffffffe520: 0x3535785c3535785c  0x3535785c3535785c
0x7fffffffe530: 0x3030785c3030785c  0x00007fffffffe600
0x7fffffffe540: 0x00000001f7b9b2e8  0x0000555555554912
0x7fffffffe550: 0x0000000000000000  0xb17102b2c99239fc
0x7fffffffe560: 0x00005555555546c0  0x00007fffffffe600
0x7fffffffe570: 0x0000000000000000  0x0000000000000000
0x7fffffffe580: 0xe42457e7915239fc  0xe42447531fe039fc
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.

Q2)即使使用以下方法,我也无法覆盖返回地址。是因为ASLR?

$ printf "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x29\x49\x55\x55\x55\x55\x00\x00" | ./serial
Segmentation fault

0 个答案:

没有答案