如何绕过长度检查执行特定的缓冲区溢出

时间:2019-06-30 13:08:16

标签: c gdb buffer-overflow strlen

我正在尝试执行bufferoverflow,以便变量(类型)中具有特定值。我为不满意而苦恼并检查我的输入。

我尝试使用诸如“ AAAAA \ x00AAA ... A \ x00 \ xbc \ xd4 \ xb9”之类的技巧来欺骗我的输入仅5 A长的检查。但是某些东西总是剥夺我的\ x00信息:

-bash:警告:命令替换:忽略输入中的空字节

所以我去增加了一个输入,并且有一个Integer溢出,所以保存长度的short太大了,并低于32700 ...但这似乎也没有用。

我的输入的结构如下:

./challenge `python programm.py`

(对于\ xXX我想要的输入)

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

int main(int argc, char *argv[])
{
    int type = 0xdeadbeef;
    char buf[32700];
    short len;

    if (argc < 2)
        return -1;

    len = strlen(argv[1]);
    if (len > 32700) {
        printf("Too long\n");
        return -1;
    }

    strcpy(buf, argv[1]);

    if (type == 0x00b1c2d3) {
        printf("Success\n");
    } else {
        printf("Try again\n");
    }

    exit(0);
}

我还在使用gdb进行内存分析。但我找不到正确的使用方式...

我的任务的代码是:

const configureStore = () => {
    return createStore(
        rootReducer,
        composeWithDevTools(
            applyMiddleware(thunk)
        )
    );
}

关于此问题还有其他想法(或“解决方案”)吗?从现在开始,我现在很努力。另外,多年来我与C无关(尤其是内存分析,gdb等),因此对我来说有些事情变得很难理解。

1 个答案:

答案 0 :(得分:2)

代码中的问题是使用len计算的长度strlen()short。这意味着它是一个16位的值。由于strlen()返回了size_t(这是我的x86_64系统上的64位值),因此仅低16位将存储在len变量中。

因此,乍一看,您可以提交长度超过65,535字节的任何内容,使short int溢出,并仅存储较低的16位。但是还有另一个问题要注意。 len变量是一个 signed 短整数。这意味着它存储来自[-32768,32767]的值,而size_t是无符号值。因此,当strlen()返回其值时,设置了最高位的长度(超过32,767字节的任何长度)将变为负数。

这是一个示例gdb会话,说明了这一点:

(gdb) break 22
Breakpoint 1 at 0x829: file challenge.c, line 22.
(gdb) run `ruby -e 'print("A"*32768)'`
Starting program: /home/josh/foo/challenge `ruby -e 'print("A"*32768)'`

Breakpoint 1, main (argc=2, argv=0x7fffffff6338) at challenge.c:22
22          if (type == 0x00b1c2d3) {
(gdb) p len
$1 = -32768
(gdb) x/64bx $rsp
0x7ffffffee260: 0x38    0x63    0xff    0xff    0xff    0x7f    0x00    0x00
0x7ffffffee268: 0x00    0x00    0x00    0x00    0x02    0x00    0x00    0x00
0x7ffffffee270: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x7ffffffee278: 0x00    0x00    0x00    0x80    0xef    0xbe    0xad    0xde
0x7ffffffee280: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7ffffffee288: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7ffffffee290: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7ffffffee298: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
(gdb) 

看看0x7ffffffee27a处的字节是0x00 0x80吗?这是-32768到short int,因此长度被认为是负数(远低于32,700!)。

我还在内存转储中添加了一些额外的信息,因此您可以看到type字段紧随内存中的len字段之后,最后是buf数组(其中包含我的32768个A!)。请注意,只有某些长度的输入才有效-出现负数或截断为16位时溢出到小于32,700的值。

这不能解决所有挑战,但至少应该给您一个很好的开始,让您了解可以控制的内容。还要注意,在buf数组上方有数据,例如rbp指向的位置,保存的返回指针等。取决于您对此的编译方式(例如,是否带有堆栈金丝雀等)。 ),在此过程中还有很多事情需要您解决。