简体   繁体   English

x86_64上的C中的溢出缓冲区以调用函数

[英]Overflow buffer in C on x86_64 to call function

Hello i have such code 你好我有这样的代码

#include <stdio.h>
#define SECRET "1234567890AZXCVBNFRT"
int checksecret(){
    char buf[32];
    gets(buf);
    if(strcmp(SECRET,buf)==0) return 1;
    else return 0;
}

void outsecret(){
    printf("%s\n",SECRET);
}
int main(int argc, char** argv){
    if (checksecret()){
        outsecret();
    };
}

disass of outsecret 绝望

(gdb) disassemble outsecret 
Dump of assembler code for function outsecret:
   0x00000000004005f4 <+0>: push   %rbp
   0x00000000004005f5 <+1>: mov    %rsp,%rbp
   0x00000000004005f8 <+4>: mov    $0x4006b4,%edi
   0x00000000004005fd <+9>: callq  0x400480 <puts@plt>
   0x0000000000400602 <+14>:    pop    %rbp
   0x0000000000400603 <+15>:    retq   

I have an assumption that i don't know SECRET , so i try to run my program with such string python -c 'print "A" * 32 + "\\x40\\x05\\xf4"[::-1]' . 我假设我不知道SECRET ,所以我尝试使用这样的字符串python -c 'print "A" * 32 + "\\x40\\x05\\xf4"[::-1]' But it fails with segmentation fault. 但是由于分割错误而失败。 What i am doing wrong? 我做错了什么? Thank you for any help. 感谢您的任何帮助。

PS 聚苯乙烯

I want to call function outsecret by overwriting return code in checksecret 我想通过覆盖checksecret返回代码来调用函数outsecret

You have to remember that all strings have an extra character that terminates the string, so if you input 32 characters then gets will write 33 characters to the buffer. 您必须记住,所有字符串都有一个终止字符串的额外字符,因此,如果输入32个字符,则gets将向缓冲区写入33个字符。 Writing beyond the limits of an array leads to undefined behavior which often leads to crashes. 超出数组限制的写入操作会导致未定义的行为 ,这通常会导致崩溃。

The gets function have no bounds-checking, and is very dangerous to use. gets函数没有边界检查,使用起来非常危险。 It has been deprecated since long, and in the latest C11 standard it has even been removed. 很久以来它已不推荐使用,在最新的C11标准中甚至已删除。

$ python -c 'print "A" * 32 + "\x40\x05\xf4"[::1]'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@

$ perl -le 'print length("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@")'
33

Your input string is too long for buffer size of 32 characters (extra one is needed for '\\0' terminating null character ). 您的输入字符串对于32个字符的缓冲区大小来说太长(对于'\\0'终止为null字符,需要加一个)。 You are victim to buffer or array overflow (sometimes also called as array overrun). 您是缓冲区或数组溢出的受害者(有时也称为数组溢出)。

Note that gets() is deprecated in C99 and eventually it has been dropped in C11 Standard for security reasons. 请注意,由于安全原因, gets()在C99中已弃用,最终在C11 Standard中已将其删除


I want to call function outsecret by overwriting return code in checksecret 我想通过覆盖checksecret中的返回代码来调用函数outsecret

Beware, you are about to leave relatively safe regions of C Standard. 当心,您将离开 相对 安全的C标准区域。 This means that behaviour is relative to compiler, compiler's versions, optimization settings, ABI and so on (maybe inclucing current phase of moon). 这意味着行为与编译器,编译器的版本,优化设置,ABI等有关(可能不包括当前的月相)。

As of x86 calling conventions integer return value is stored directly in %eax register (that's assuming that you have x86 or x86-64 CPU). x86调用约定开始,整数返回值直接存储在%eax寄存器中(假定您具有x86x86-64 CPU)。 Stack-likely-located array buf is handled by %rbp offsets within current stack frame . 通过当前堆栈frame内的%rbp偏移量来处理可能位于堆栈中的数组buf Let's consult with gdb disassemble command: 让我们咨询一下gdb disassemble命令:

$ gcc -O0 test.c

$ gdb -q a.out
(gdb) b checksecret
(gdb) r
Breakpoint 1, 0x0000000000400631 in checksecret ()
(gdb) disas
Dump of assembler code for function checksecret:
   0x000000000040062d <+0>: push   %rbp
   0x000000000040062e <+1>: mov    %rsp,%rbp
=> 0x0000000000400631 <+4>: sub    $0x30,%rsp
   0x0000000000400635 <+8>: mov    %fs:0x28,%rax
   0x000000000040063e <+17>:    mov    %rax,-0x8(%rbp)
   0x0000000000400642 <+21>:    xor    %eax,%eax
   0x0000000000400644 <+23>:    lea    -0x30(%rbp),%rax
   0x0000000000400648 <+27>:    mov    %rax,%rdi
   0x000000000040064b <+30>:    callq  0x400530 <gets@plt>
   0x0000000000400650 <+35>:    lea    -0x30(%rbp),%rax
   0x0000000000400654 <+39>:    mov    %rax,%rsi
   0x0000000000400657 <+42>:    mov    $0x400744,%edi
   0x000000000040065c <+47>:    callq  0x400510 <strcmp@plt>
   0x0000000000400661 <+52>:    test   %eax,%eax
   0x0000000000400663 <+54>:    jne    0x40066c <checksecret+63>
   0x0000000000400665 <+56>:    mov    $0x1,%eax
   0x000000000040066a <+61>:    jmp    0x400671 <checksecret+68>
   0x000000000040066c <+63>:    mov    $0x0,%eax
   0x0000000000400671 <+68>:    mov    -0x8(%rbp),%rdx
   0x0000000000400675 <+72>:    xor    %fs:0x28,%rdx
   0x000000000040067e <+81>:    je     0x400685 <checksecret+88>
   0x0000000000400680 <+83>:    callq  0x4004f0 <__stack_chk_fail@plt>
   0x0000000000400685 <+88>:    leaveq 
   0x0000000000400686 <+89>:    retq  

There is no way overwrite %eax directly from C code, but what you could do is to overwrite selective fragment of code section. 无法直接从C代码覆盖%eax ,但是您可以做的是覆盖代码段的选择性片段。 In your case what you want is to replace: 在您的情况下,您要替换的是:

0x000000000040066c <+63>:   mov    $0x0,%eax

with

0x000000000040066c <+63>:   mov    $0x1,%eax

It's easy to accomplish by gdb itself: 通过gdb本身很容易完成:

(gdb) x/2bx 0x40066c
0x40066c <checksecret+63>:  0xb8    0x00

set {unsigned char}0x40066d = 1

Now let's confirm it: 现在让我们确认一下:

(gdb) x/i 0x40066c
   0x40066c <checksecret+63>:   mov    $0x1,%eax

From that point checksecret() is returning 1 even if SECRET does not match. 从那时起,即使SECRET不匹配, checksecret()也会返回1 However It wouldn't be so easy to do it by buf itself, as you need to know (guess somehow?) correct offset of particular code section instruction. 但是,通过buf本身来完成它并不是那么容易,因为您需要知道(以某种方式猜测)特定代码段指令的正确偏移量。

Above answers are pretty clear and corret way to exploit buffer overflow vulnerability. 以上答案是利用缓冲区溢出漏洞的非常清晰和正确的方法。 But there is a different way to do same thing without exploit vulnerability. 但是,可以利用另一种方法来利用漏洞而做同样的事情。

mince@rootlab tmp $ gcc test.c -o test
mince@rootlab tmp $ strings test
/lib64/ld-linux-x86-64.so.2
libc.so.6
gets
puts
__stack_chk_fail
strcmp
__libc_start_main
__gmon_start__
GLIBC_2.4
GLIBC_2.2.5
UH-X
UH-X
[]A\A]A^A_
1234567890AZXCVBNFRT
;*3$

Please look at last 2 row. 请看最后2行。 You will see your secret key in there. 您将在其中看到您的秘密密钥。

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

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