-
-
Notifications
You must be signed in to change notification settings - Fork 146
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Marco Lancini
committed
May 18, 2018
1 parent
660c434
commit e71e6e0
Showing
14 changed files
with
1,639 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
NAME := goscan | ||
VERSION := 1.0 | ||
AUTHOR := Marco Lancini [@LanciniMarco] | ||
LDFLAGS := -X 'main.version=$(VERSION)' -X 'main.author=$(AUTHOR)' | ||
|
||
.DEFAULT_GOAL := help | ||
|
||
.PHONY: setup | ||
setup: ## Setup for required tools. | ||
go get github.com/golang/lint/golint | ||
go get golang.org/x/tools/cmd/goimports | ||
go get -u github.com/golang/dep/cmd/dep | ||
dep ensure | ||
|
||
.PHONY: fmt | ||
fmt: ## Formatting source codes. | ||
go fmt ./... | ||
|
||
.PHONY: lint | ||
lint: ## Run golint and go vet. | ||
@golint ./core/... | ||
@go vet ./core/... | ||
|
||
.PHONY: build | ||
build: main.go ## Build a binary. | ||
go build -ldflags "$(LDFLAGS)" | ||
|
||
.PHONY: cross | ||
cross: main.go ## Build binaries for cross platform. | ||
mkdir -p pkg | ||
@for os in "darwin" "linux"; do \ | ||
for arch in "amd64" "386"; do \ | ||
GOOS=$${os} GOARCH=$${arch} make build; \ | ||
zip pkg/goscan_$(VERSION)_$${os}_$${arch}.zip goscan; \ | ||
done; \ | ||
done | ||
|
||
.PHONY: help | ||
help: ## Show help text | ||
@echo "Commands:" | ||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-20s\033[0m %s\n", $$1, $$2}' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
package cli | ||
|
||
import ( | ||
"fmt" | ||
"github.com/c-bata/go-prompt" | ||
"goscan/core/utils" | ||
"io/ioutil" | ||
"path/filepath" | ||
"strings" | ||
) | ||
|
||
func excludeOptions(args []string) []string { | ||
ret := make([]string, 0, len(args)) | ||
for i := range args { | ||
if !strings.HasPrefix(args[i], "-") { | ||
ret = append(ret, args[i]) | ||
} | ||
} | ||
return ret | ||
} | ||
|
||
func Completer(d prompt.Document) []prompt.Suggest { | ||
if d.TextBeforeCursor() == "" { | ||
return []prompt.Suggest{} | ||
} | ||
args := strings.Split(d.TextBeforeCursor(), " ") | ||
|
||
// If PIPE is in text before the cursor, returns empty suggestions. | ||
for i := range args { | ||
if args[i] == "|" { | ||
return []prompt.Suggest{} | ||
} | ||
} | ||
return argumentsCompleter(d, excludeOptions(args)) | ||
} | ||
|
||
var commands = []prompt.Suggest{ | ||
{Text: "set_target", Description: "Set target CIDR."}, | ||
{Text: "set_output_folder", Description: "Set the output folder."}, | ||
{Text: "show", Description: "Show results."}, | ||
{Text: "sweep", Description: "Perform an ARP/ping sweep."}, | ||
{Text: "portscan", Description: "Perform a port scan."}, | ||
{Text: "enumerate", Description: "Perform enumeration of detected services."}, | ||
{Text: "help", Description: "Show help"}, | ||
{Text: "exit", Description: "Exit this program"}, | ||
} | ||
|
||
func argumentsCompleter(d prompt.Document, args []string) []prompt.Suggest { | ||
if len(args) <= 1 { | ||
return prompt.FilterHasPrefix(commands, args[0], true) | ||
} | ||
|
||
first := args[0] | ||
switch first { | ||
case "set_target": | ||
if len(args) == 2 { | ||
return prompt.FilterContains(getTargetSuggestions(), args[1], true) | ||
} | ||
case "set_output_folder": | ||
return fileCompleter(d) | ||
case "show": | ||
second := args[1] | ||
if len(args) == 2 { | ||
subcommands := []prompt.Suggest{ | ||
{Text: "hosts", Description: "Show live hosts"}, | ||
} | ||
return prompt.FilterHasPrefix(subcommands, second, true) | ||
} | ||
case "sweep": | ||
second := args[1] | ||
if len(args) == 2 { | ||
subcommands := []prompt.Suggest{ | ||
{Text: "ALL", Description: "Perform ARP scan and PING sweep"}, | ||
{Text: "ARP", Description: "Perform ARP scan"}, | ||
{Text: "PING", Description: "Perform PING sweep"}, | ||
} | ||
return prompt.FilterHasPrefix(subcommands, second, true) | ||
} | ||
if len(args) == 3 { | ||
return prompt.FilterContains(getTargetSuggestions(), args[2], true) | ||
} | ||
case "portscan": | ||
second := args[1] | ||
if len(args) == 2 { | ||
subcommands := []prompt.Suggest{ | ||
{Text: "TCP-FULL", Description: "Perform FULL TCP scan"}, | ||
{Text: "TCP-STANDARD", Description: "Perform TCP scan (top 200)"}, | ||
{Text: "TCP-VULN-SCAN", Description: "Perform TCP VULN scan (vulscan.nse)"}, | ||
{Text: "UDP-STANDARD", Description: "Perform UDP scan (common ports)"}, | ||
} | ||
return prompt.FilterHasPrefix(subcommands, second, true) | ||
} | ||
if len(args) == 3 { | ||
return prompt.FilterContains(getHostSuggestions(), args[2], true) | ||
} | ||
case "enumerate": | ||
if len(args) == 2 { | ||
second := args[1] | ||
subcommands := []prompt.Suggest{ | ||
{Text: "ALL", Description: "Automatically identify open services and enumerate them"}, | ||
{Text: "DNS", Description: "Enumerate DNS"}, | ||
{Text: "FINGER", Description: "Enumerate FINGER"}, | ||
{Text: "FTP", Description: "Enumerate FTP"}, | ||
{Text: "HTTP", Description: "Enumerate HTTP"}, | ||
{Text: "RDP", Description: "Enumerate RDP"}, | ||
{Text: "SMB", Description: "Enumerate SMB"}, | ||
{Text: "SMTP", Description: "Enumerate SMTP"}, | ||
{Text: "SNMP", Description: "Enumerate SNMP"}, | ||
{Text: "SQL", Description: "Enumerate SQL"}, | ||
{Text: "SSH", Description: "Enumerate SSH"}, | ||
} | ||
return prompt.FilterHasPrefix(subcommands, second, true) | ||
} | ||
if len(args) == 3 { | ||
third := args[2] | ||
subcommands := []prompt.Suggest{ | ||
{Text: "POLITE", Description: "Avoid bruteforcing"}, | ||
{Text: "BRUTEFORCE", Description: "Include bruteforce scripts"}, | ||
} | ||
return prompt.FilterHasPrefix(subcommands, third, true) | ||
} | ||
if len(args) == 4 { | ||
return prompt.FilterContains(getHostSuggestions(), args[3], true) | ||
} | ||
default: | ||
return []prompt.Suggest{} | ||
} | ||
|
||
return []prompt.Suggest{} | ||
} | ||
|
||
func getHostSuggestions() []prompt.Suggest { | ||
s := []prompt.Suggest{} | ||
s = append(s, prompt.Suggest{ | ||
Text: "ALL", | ||
Description: "Scan all live hosts", | ||
}) | ||
|
||
for _, h := range utils.Config.Hosts { | ||
s = append(s, prompt.Suggest{ | ||
Text: h.Address, | ||
Description: fmt.Sprintf("Scan only host: %s", h.Address), | ||
}) | ||
} | ||
|
||
return s | ||
} | ||
|
||
func getTargetSuggestions() []prompt.Suggest { | ||
// Default suggestions | ||
var target string = utils.Const_example_target_cidr | ||
var desc string = utils.Const_example_target_desc | ||
|
||
// Detect if a target has already been selected | ||
if utils.Config.Target != "" { | ||
target = fmt.Sprintf("%s", utils.Config.Target) | ||
desc = "Currently selected target" | ||
} | ||
|
||
// Build suggestion | ||
s := make([]prompt.Suggest, 1, 5) | ||
s[0] = prompt.Suggest{ | ||
Text: target, | ||
Description: desc, | ||
} | ||
|
||
// Parse address from network interface | ||
localInterfaces := utils.ParseLocalIP() | ||
for eth, ip := range localInterfaces { | ||
s = append(s, prompt.Suggest{ | ||
Text: utils.ParseCIDR(ip), | ||
Description: fmt.Sprintf("Subnet from interface: %s", eth), | ||
}) | ||
|
||
} | ||
|
||
return s | ||
} | ||
|
||
func fileCompleter(d prompt.Document) []prompt.Suggest { | ||
path := d.GetWordBeforeCursor() | ||
if strings.HasPrefix(path, "./") { | ||
path = path[2:] | ||
} | ||
dir := filepath.Dir(path) | ||
files, err := ioutil.ReadDir(dir) | ||
if err != nil { | ||
return []prompt.Suggest{} | ||
} | ||
suggests := make([]prompt.Suggest, 0, len(files)) | ||
for _, f := range files { | ||
if !f.IsDir() { | ||
continue | ||
} | ||
suggests = append(suggests, prompt.Suggest{Text: filepath.Join(dir, f.Name())}) | ||
} | ||
return prompt.FilterHasPrefix(suggests, path, false) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
package cli | ||
|
||
import ( | ||
"fmt" | ||
"github.com/olekukonko/tablewriter" | ||
"goscan/core/scan" | ||
"goscan/core/utils" | ||
"os" | ||
) | ||
|
||
func Executor(s string) { | ||
// Parse cmd | ||
cmd, args := utils.ParseCmd(s) | ||
|
||
// Execute commands | ||
switch cmd { | ||
|
||
case "set_target": | ||
cmdSetTarget(args) | ||
case "set_output_folder": | ||
cmdSetOutputFolder(args) | ||
case "show": | ||
cmdShow(args) | ||
case "sweep": | ||
cmdSweep(args) | ||
case "portscan": | ||
cmdPortscan(args) | ||
case "enumerate": | ||
cmdEnumerate(args) | ||
case "help": | ||
cmdHelp() | ||
case "exit", "quit": | ||
os.Exit(0) | ||
return | ||
|
||
case "": | ||
default: | ||
return | ||
} | ||
|
||
// Start checking for running scans | ||
go scan.ReportStatusNmap() | ||
go scan.ReportStatusEnum() | ||
} | ||
|
||
func cmdHelp() { | ||
utils.Config.Log.LogInfo("GoScan automates the scanning and enumeration steps of a penetration test") | ||
utils.Config.Log.LogInfo("Available commands:") | ||
|
||
data := [][]string{ | ||
[]string{"Set output folder", "set_output_folder <PATH>"}, | ||
[]string{"Ping Sweep", "sweep <TYPE> <TARGET>"}, | ||
[]string{"Port Scan", "portscan <TYPE> <TARGET>"}, | ||
[]string{"Service Enumeration", "enumerate <TYPE> <POLITE/AGGRESSIVE> <TARGET>"}, | ||
[]string{"Show live hosts", "show hosts"}, | ||
} | ||
table := tablewriter.NewWriter(os.Stdout) | ||
table.SetHeader([]string{"Command", "Syntax"}) | ||
table.SetAlignment(3) | ||
table.SetAutoWrapText(false) | ||
table.AppendBulk(data) | ||
table.Render() | ||
} | ||
|
||
func cmdShow(args []string) { | ||
what, _ := utils.ParseNextArg(args) | ||
switch what { | ||
case "hosts": | ||
utils.ShowHosts() | ||
} | ||
} | ||
|
||
func cmdSetTarget(args []string) bool { | ||
if len(args) != 1 { | ||
utils.Config.Log.LogError("Invalid command provided") | ||
return false | ||
} | ||
ip, _ := utils.ParseNextArg(args) | ||
cidr := utils.ParseCIDR(ip) | ||
if cidr == "" { | ||
utils.Config.Log.LogError("Invalid CIDR provided") | ||
return false | ||
} | ||
utils.Config.Log.LogInfo(fmt.Sprintf("Selected target: %s", cidr)) | ||
utils.Config.Target = cidr | ||
|
||
return true | ||
} | ||
|
||
func cmdSetOutputFolder(args []string) { | ||
if len(args) != 1 { | ||
utils.Config.Log.LogError("Invalid command provided") | ||
return | ||
} | ||
folder, _ := utils.ParseNextArg(args) | ||
utils.Config.Outfolder = folder | ||
utils.EnsureDir(utils.Config.Outfolder) | ||
} | ||
|
||
func cmdSweep(args []string) { | ||
if len(args) != 2 { | ||
utils.Config.Log.LogError("Invalid command provided") | ||
return | ||
} | ||
// Get type of scan | ||
kind, args := utils.ParseNextArg(args) | ||
// Get target and update global config | ||
target, _ := utils.ParseNextArg(args) | ||
check := cmdSetTarget(args) | ||
if check == false { | ||
return | ||
} | ||
// Perform ping sweep | ||
scan.ScanSweep(target, kind) | ||
} | ||
|
||
func cmdPortscan(args []string) { | ||
if len(args) != 2 { | ||
utils.Config.Log.LogError("Invalid command provided") | ||
return | ||
} | ||
// Get type of scan | ||
kind, args := utils.ParseNextArg(args) | ||
// Get target host | ||
target, _ := utils.ParseNextArg(args) | ||
// Perform port scan | ||
scan.ScanPort(target, kind) | ||
} | ||
|
||
func cmdEnumerate(args []string) { | ||
if len(args) != 3 { | ||
utils.Config.Log.LogError("Invalid command provided") | ||
return | ||
} | ||
// Get type of scan | ||
kind, args := utils.ParseNextArg(args) | ||
// Get politeness | ||
polite, args := utils.ParseNextArg(args) | ||
// Get target host | ||
target, _ := utils.ParseNextArg(args) | ||
// Perform port scan | ||
scan.ScanEnumerate(target, polite, kind) | ||
} |
Oops, something went wrong.