README.md
Rendering markdown...
package main
import (
"flag"
"fmt"
"log"
"os"
"strings"
"sync"
"time"
)
func processHostExt(host string) {
var pResult fResult
for vuln, runner := range vulnToModule {
if isItemIn(vuln, &allvulns) {
runner.(func(string, *fResult))(host, &pResult)
}
}
pResult.Host = strings.Split(strings.Split(host, "@")[1], ":")[0]
finalResults = append(finalResults, pResult)
}
func initScan(allhosts, allexts *[]string) {
log.Println("Checking if hosts are alive and responding to SIP...")
var alivehosts []string
xmap := checkAlive(allhosts)
for target, alive := range xmap {
if alive {
alivehosts = append(alivehosts, target)
} else {
log.Fatalf("Looks like '%s' is down / not responding to SIP.", target)
}
}
hosts := make(chan string, maxConcurrent)
maxProcs := new(sync.WaitGroup)
maxProcs.Add(maxConcurrent)
cwd, _ := os.Getwd()
log.Printf("Using output directory %s under %s...", outdir, cwd)
_, err := os.Stat(outdir)
if err != nil {
if os.IsNotExist(err) {
log.Println("Output directory doesn't exist. Creating one...")
if err = os.Mkdir(outdir, 0777); err != nil {
log.Fatalln(err.Error())
}
}
}
startTime := time.Now()
log.Println("Starting scan at:", startTime.String())
for i := 0; i < maxConcurrent; i++ {
go func() {
for {
host := <-hosts
if host == "" {
break
}
processHostExt(host)
}
maxProcs.Done()
}()
}
if len(extFile) < 1 {
for _, xhost := range alivehosts {
for _, ext := range *allexts {
hosts <- fmt.Sprintf("%s@%s", ext, xhost)
}
}
} else {
for _, host := range *readExtensionsFromFile(extFile) {
*allhosts = append(*allhosts, host)
if !strings.Contains(host, ":") {
host = fmt.Sprintf("%s:5060", host)
}
hosts <- host
}
}
close(hosts)
maxProcs.Wait()
if outFormat == "json" {
log.Println("Writing results to destination directory as JSON...")
if err = writeToJSON(&finalResults); err != nil {
log.Panicln(err)
}
} else if outFormat == "csv" {
log.Println("Writing results to destination directory as CSV...")
if err = writeToCSV(&finalResults); err != nil {
log.Panicln(err)
}
}
log.Println("Scan finished at:", time.Now().String())
log.Printf("Total %d hosts scanned in %s.", len(*allhosts), time.Since(startTime).String())
}
func main() {
flag.IntVar(&delay, "delay", 0, "Delay in seconds between subsequent requests.")
flag.IntVar(&maxConcurrent, "threads", 2, "Number of threads to use while scanning.")
flag.IntVar(&maxExpires, "expires", 60, "Maximum value of the 'Expires' header for SUBSCRIBE requests.")
flag.StringVar(&monEvents, "events", "", "Comma-separated list of events to be subscribed to. All events are monitored by default.")
flag.StringVar(&userAgent, "user-agent", fmt.Sprintf("pewswitch/%s", version), "Custom user-agent string to use.")
flag.StringVar(&cveToScan, "cve", "", "Specify a specific CVE to scan. Both vulns are tested by default.")
flag.StringVar(&extensions, "exts", "", "Comma separated list of extensions to scan.")
flag.StringVar(&extFile, "ext-file", "", "Specify a file containing extensions instead of '-exts'.")
flag.StringVar(&sendmsgs, "msg-file", "", "Specify a CSV file containing messages to be sent (if found vulnerable to CVE-2021-37624).")
flag.StringVar(&outdir, "out-dir", "./pewswitch-results/", "Output directory to write the results to.")
flag.StringVar(&outFormat, "out-format", "json", "Output format type of the results. Can be either 'json' or 'csv'.")
mainUsage := func() {
fmt.Fprint(os.Stdout, lackofart, "\n\n")
fmt.Fprintf(os.Stdout, "Usage of %s:\n", os.Args[0])
flag.PrintDefaults()
}
flag.Usage = mainUsage
flag.Parse()
fmt.Print(lackofart, "\n\n")
targets := flag.Args()
if (len(targets) < 1 || len(extensions) < 1) && len(extFile) < 1 {
log.Println("You need to supply at least a valid target & extension to scan!\n\nUsage:")
flag.PrintDefaults()
os.Exit(1)
}
if outFormat != "json" && outFormat != "csv" {
log.Println("The only output formats allowed are json and csv.")
flag.PrintDefaults()
os.Exit(1)
}
if len(cveToScan) != 0 {
allvulns = []string{strings.ToLower(cveToScan)}
}
xflag := false
for x := range targets {
if !strings.Contains(targets[x], ":") {
xflag = true
targets[x] = fmt.Sprintf("%s:5060", targets[x])
}
}
// just letting the user know we're defaulting to 5060.
if xflag {
log.Println("No port supplied, using default port 5060 for targets...")
}
for _, ext := range strings.Split(extensions, ",") {
allexts = append(allexts, strings.TrimSpace(ext))
}
if len(sendmsgs) > 0 {
msgstosend = append(msgstosend, readCsvFile(sendmsgs)...)
} else {
msgstosend = append(msgstosend, defaultMsgText)
}
if len(monEvents) > 0 {
for _, x := range strings.Split(monEvents, ",") {
allEvents = append(allEvents, strings.TrimSpace(x))
}
} else {
allEvents = events
}
initScan(&targets, &allexts)
}