assembly 如何使用缓冲区溢出“跳”到代码中的特定行?

brjng4g3  于 2022-11-24  发布在  其他
关注(0)|答案(1)|浏览(130)

我目前正在学习C语言,并试图找到更多关于堆栈中内存如何工作以及gdb如何帮助的信息。
下面是我的问题的代码片段:

bool thisEvaluatesToFalse(char* something) {
    return false;
}

void main() {
    char something[10];
    puts("My plan is to input a specific string over 10 characters than will achieve my goal:");
    gets(something);

    if (thisEvaluatesToFalse(something)) {
        puts("If this runs, its a success!");
    }
}

其思想是,我的成功消息将永远不会运行,除非我利用gets输入超过10个字符的something,导致溢出,覆盖成功消息所在的函数返回地址
我知道我应该用gdb查看汇编代码,并寻找地址,但我不知道如何做到这一点。
有人能给我一个例子吗?谢谢!

qgelzfjb

qgelzfjb1#

试试这个,希望它能帮你弄清楚这一点。祝你好运!
考虑将gets移到thisEvaluatesToFalse中,以覆盖main推送的返回地址,以便从thisEvaluatesToFalse返回的内容将返回到成功的puts
就像这样:

#include <stdio.h>

unsigned int thisEvaluatesToFalse() {
    char something[10];
    gets(something);
    return 0xdeadbeef;
}

int main() {
    puts("My plan is to input a specific string over 10 characters than will achieve my goal:");
    if (thisEvaluatesToFalse()) {
        puts("If this runs, its a success!");
    }
    return 0;
}

下面是使用w/ gdb的一些要点。

gcc main.c -fno-stack-protector -ggdb
gdb a.out
(gdb) disass main

   0x0000000100003eeb <+27>:    call   0x100003eb0 <thisEvaluatesToFalse>
   0x0000000100003ef0 <+32>:    cmp    $0x0,%eax
   0x0000000100003ef3 <+35>:    je     0x100003f05 <main+53>
   0x0000000100003ef9 <+41>:    lea    0x94(%rip),%rdi        # 0x100003f94
   0x0000000100003f00 <+48>:    call   0x100003f14

# ORIG RETURN ADDRESS IS 0x0000000100003ef0
# EXPLOIT RETURN ADDRESS FOR SUCCESS IS 0x0000000100003ef9

(gdb) break thisEvaluatesToFalse
(gdb) run

(gdb) x/16x $sp
0x7ff7bfeff930: 0x000c8060  0x00000001  0x00003ed0  0x00000001
0x7ff7bfeff940: 0xbfeff960  0x00007ff7  0x00003ef0  0x00000001
0x7ff7bfeff950: 0x00000013  0x00000000  0x000c8060  0x00000000
0x7ff7bfeff960: 0xbfeffa70  0x00007ff7  0x0001552e  0x00000001

# NOTICE THE VALUE AT 0x7ff7bfeff948 IS 0x00003ef0 (ORIG RETURN)
# NOTICE THE VALUE AT 0x7ff7bfeff94C IS 0x00000001 (ORIG RETURN)

(gdb) s
warning: this program uses gets(), which is unsafe.
1234567890AAAABBBBCCCCDDDD

(gdb) x/16x $sp
0x7ff7bfeff930: 0x000c8060  0x32310001  0x36353433  0x30393837
0x7ff7bfeff940: 0x41414141  0x42424242  0x43434343  0x44444444
0x7ff7bfeff950: 0x00000000  0x00000000  0x000c8060  0x00000000
0x7ff7bfeff960: 0xbfeffa70  0x00007ff7  0x0001552e  0x00000001

# NOTICE THE VALUE AT 0x7ff7bfeff948 IS 0x43434343 (LETTER C)
# NOTICE THE VALUE AT 0x7ff7bfeff94C IS 0x44444444 (LETTER D)

(gdb) set *0x7ff7bfeff948 = 0x00003ef9
(gdb) set *0x7ff7bfeff94C = 0x00000001
(gdb) x/16x $sp
0x7ff7bfeff930: 0x000c8060  0x32310001  0x36353433  0x30393837
0x7ff7bfeff940: 0x41414141  0x42424242  0x00003ef9  0x00000001

(gdb) s
main () at main.c:17
17          puts("If this runs, its a success!");
(gdb) s
If this runs, its a success!
19      return 0;

让您自己决定如何为gets输入值,以便执行将CD替换为所需值的操作。
如果你可以选择一种不同的方法,那么不要使用gets来处理溢出,而是尝试使用memcpy并复制超过10个字节。同样的影响,堆栈也会被修改。

相关问题