Skip to content

Commit

Permalink
Add code
Browse files Browse the repository at this point in the history
  • Loading branch information
Marco Lancini committed May 18, 2018
1 parent 660c434 commit e71e6e0
Show file tree
Hide file tree
Showing 14 changed files with 1,639 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

It can be used to perform host discovery, port scanning, and service enumeration in situations where being stealthy is not a priority, and time is limited (think at CTFs, OSCP, exams, etc.).

<a href="https://asciinema.org/a/4ebtOAiDKmM1X89yCIpFQjqSQ" target="_blank"><img src="https://asciinema.org/a/4ebtOAiDKmM1X89yCIpFQjqSQ.png"/></a>
[![asciicast](https://asciinema.org/a/4ebtOAiDKmM1X89yCIpFQjqSQ.png)](https://asciinema.org/a/4ebtOAiDKmM1X89yCIpFQjqSQ)



Expand Down
41 changes: 41 additions & 0 deletions goscan/Makefile
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}'
198 changes: 198 additions & 0 deletions goscan/core/cli/completer.go
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)
}
143 changes: 143 additions & 0 deletions goscan/core/cli/executor.go
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)
}
Loading

0 comments on commit e71e6e0

Please sign in to comment.