Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ $ ./Talon -h
Usage of ./Talon:
-A float
Authentication attempts per lockout period (default 3)
-Combofile string
File containing list of user:pass combinations to try
-D string
Fully qualified domain to use
-E Enumerates which users are valid
Expand Down Expand Up @@ -212,4 +214,4 @@ Will resume at 03-10-2022 16:43:35
* Version 1.3 released 05/03/2019
* Version 1.4 released 03/17/2020
* Version 2.0 public relase 06/18/2020
* Version 3.0 relase 03/10/2022
* Version 3.0 relase 03/10/2022
94 changes: 87 additions & 7 deletions Talon.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ type FlagOptions struct {
user string
userfile string
passfile string
combofile string
lockout float64
attempts float64
domain string
Expand Down Expand Up @@ -81,6 +82,7 @@ func options() *FlagOptions {
user := flag.String("U", "", "Username to authenticate as")
userfile := flag.String("Userfile", "", "File containing the list of usernames")
passfile := flag.String("Passfile", "", "File containing the list of passwords")
combofile := flag.String("Combofile", "", "File containing list of user:pass combinations to try")
lockout := flag.Float64("Lockout", 60, "Account lockout period in minutes")
attempts := flag.Float64("A", 3, "Authentication attempts per lockout period")
pass := flag.String("P", "", "Password to use")
Expand All @@ -94,15 +96,17 @@ func options() *FlagOptions {
flag.Parse()
debugging = *debug
debugWriter = os.Stdout
return &FlagOptions{host: *host, domain: *domain, user: *user, userfile: *userfile, hostfile: *hostfile, pass: *pass, outFile: *outFile, sleep: *sleep, enum: *enum, ldap: *ldap, kerb: *kerb, passfile: *passfile, lockout: *lockout, attempts: *attempts, lockerr: *lockerr}
return &FlagOptions{host: *host, domain: *domain, user: *user, userfile: *userfile, combofile: *combofile, hostfile: *hostfile, pass: *pass, outFile: *outFile, sleep: *sleep, enum: *enum, ldap: *ldap, kerb: *kerb, passfile: *passfile, lockout: *lockout, attempts: *attempts, lockerr: *lockerr}
}

func readfile(inputFile string) []string {
output, err := ioutil.ReadFile(inputFile)
if err != nil {
log.Fatal(err)
}
return strings.Split(string(output), "\n")
return strings.FieldsFunc(string(output), func(r rune) bool {
return r == '\n' || r == '\r'
})
}

func check(e error) {
Expand All @@ -126,6 +130,7 @@ func main() {
var usernames []string
var services []string
var passwords []string
var combos []string
services = []string{"KERB", "LDAP"}
fmt.Println(`
__________ ________ ___ ________ ________
Expand All @@ -137,7 +142,7 @@ func main() {
\|__| \|__|\|__|\|_______|\|_______|\|__| \|__|
(@Tyl0us)

Version: 3.2 `)
Version: 3.2-mod1 `)

if opt.enum {
services = []string{"KERB"}
Expand Down Expand Up @@ -190,12 +195,20 @@ func main() {
}
}

if opt.user == "" && opt.userfile == "" {
log.Fatal("Error: Please provide an username or list of usernames")
if opt.user == "" && opt.userfile == "" && opt.combofile == "" {
log.Fatal("Error: Please provide a username, username file or a combofile")
}

if (opt.pass == "" && opt.passfile == "") && opt.enum == false {
log.Fatal("Error: Please provide a password or select the enumeration option")
if (opt.pass == "" && opt.passfile == "") && opt.enum == false && opt.combofile == "" {
log.Fatal("Error: Please provide a password, select the enumeration option or provide a combofile")
}

if (opt.user != "" || opt.userfile != "") && opt.combofile != "" {
log.Fatal("Error: Don't specify username or username file with Combofile")
}

if (opt.pass != "" || opt.passfile != "") && opt.combofile != "" {
log.Fatal("Error: Don't specify password or password file with Combofile")
}

if opt.pass != "" {
Expand All @@ -214,6 +227,17 @@ func main() {
}
}

if opt.combofile != "" {
printDebug("Reading combo file %s\n", opt.userfile)
fileCombos := readfile(opt.combofile)
printDebug("Appending combos %v\n", fileCombos)
for _, combo := range fileCombos {
if combo != "" {
combos = append(combos, combo)
}
}
}

if opt.user != "" {
printDebug("Appending user %s\n", opt.user)
usernames = append(usernames, opt.user)
Expand All @@ -234,6 +258,62 @@ func main() {
fmt.Print("\n")
}

// Combo execution logic
if (opt.combofile != "") {
sleep := opt.sleep
domain := strings.ToUpper(opt.domain)
printDebug("Domain %v\tCombos %v\tHosts %v\tServices %v\n", domain, combos, hosts, services)
x := 0
err := 0
rand.Seed(time.Now().Unix())
lenServices := len(services) - 1
for _, combo := range combos {
n := 0
if opt.hostfile != "" {
n = rand.Int() % (len(hosts) - 1)
}
if hosts[n] == "" {
return
}

parts := strings.SplitN(combo, ":", 2)
if len(parts) != 2 {
fmt.Printf("[W] Ignoring combo with too many colons: %s", combo)
continue
}
username := parts[0]
password := parts[1]

time.Sleep(time.Duration(sleep) * time.Second)
auth := setup(services[x], hosts[n], domain, username, password, opt.enum)
result, forfile, _ := auth.Login()
fmt.Println(result)
if strings.Contains(result, "User's Account Locked") && opt.enum != true {
err++
if err == int(opt.lockerr) {
reader := bufio.NewReader(os.Stdin)
fmt.Printf("[*] %d Consecutive account lock out(s) detected - Do you want to continue.[y/n]: ", err)
text, _ := reader.ReadString('\n')
if strings.Contains(text, "y") {
err = 0
continue
}
log.Fatal("Shutting down")
}
}
if opt.outFile != "" {
forfile = forfile + "\n"
writefile(opt.outFile, forfile)
}
if lenServices == x {
x = 0
} else {
x++
err = 0
}
}
}

// Normal execution logic
if (opt.pass != "" && opt.passfile == "") || opt.enum {
sleep := opt.sleep
Expand Down