Skip to content

Commit b26ced4

Browse files
committed
Add support for file format (document generation) exploits and local exploits
1 parent 3646f0a commit b26ced4

File tree

5 files changed

+248
-61
lines changed

5 files changed

+248
-61
lines changed

cli/commandline.go

Lines changed: 177 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/json"
66
"flag"
77
"fmt"
8+
"io"
89
"net"
910
"os"
1011
"strconv"
@@ -408,8 +409,25 @@ func dbFlags(conf *config.Config) {
408409
flag.IntVar(&db.GlobalHTTPRespCacheLimit, "cacheMax", 10*(1024*1024), "The maximum size of an HTTP response that can be cached")
409410
}
410411

411-
// handlue generic sounding c2 flags.
412-
func c2Flags(conf *config.Config) {
412+
// handle generic sounding c2 flags.
413+
func c2Flags(c2Selection *string, conf *config.Config) {
414+
c2Default, _ := c2.ImplToString(conf.SupportedC2[0])
415+
c2Available := "The C2 server implementation to use. Supported: "
416+
for _, value := range conf.SupportedC2 {
417+
c2Name, ok := c2.ImplToString(value)
418+
if ok {
419+
c2Available += "\n\t" + c2Name
420+
}
421+
422+
// add the supported c2 flags, allowing for command line config of the backend
423+
impl, success := c2.GetInstance(value)
424+
if success {
425+
impl.CreateFlags()
426+
}
427+
}
428+
c2Available += "\n"
429+
flag.StringVar(c2Selection, "c2", c2Default, c2Available)
430+
413431
// flags unique to remote code execution
414432
flag.IntVar(&conf.Bport, "bport", 0, "The port to attach the bind shell to")
415433

@@ -423,6 +441,31 @@ func c2Flags(conf *config.Config) {
423441
flag.BoolVar(&conf.ThirdPartyC2Server, "o", false, "Indicates if the reverse shell should be caught by an outside program (nc, openssl)")
424442
}
425443

444+
// loop through the c2 the exploit supports and find the one the user actually selected.
445+
func validateC2Selection(c2Selection string, conf *config.Config) bool {
446+
c2Selected, ok := c2.StringToImpl(c2Selection)
447+
if !ok {
448+
output.PrintFrameworkError("Provided an invalid c2 implementation")
449+
450+
return false
451+
}
452+
// is this a supported c2?
453+
foundSupported := false
454+
for _, value := range conf.SupportedC2 {
455+
if c2Selected == value {
456+
foundSupported = true
457+
}
458+
}
459+
if !foundSupported {
460+
output.PrintFrameworkError("The c2 you selected is not supported by this exploit.")
461+
462+
return false
463+
}
464+
conf.C2Type = c2Selected
465+
466+
return true
467+
}
468+
426469
// Parses the command line arguments used by RCE exploits.
427470
func CodeExecutionCmdLineParse(conf *config.Config) bool {
428471
var rhosts string
@@ -432,6 +475,7 @@ func CodeExecutionCmdLineParse(conf *config.Config) bool {
432475
var frameworkLogLevel string
433476
var exploitLogLevel string
434477
var proxy string
478+
var c2Selection string
435479

436480
dbFlags(conf)
437481
proxyFlags(&proxy)
@@ -440,26 +484,7 @@ func CodeExecutionCmdLineParse(conf *config.Config) bool {
440484
localHostFlags(conf)
441485
exploitFunctionality(conf)
442486
sslFlags(conf)
443-
c2Flags(conf)
444-
445-
// c2 selection. defaults to the implementations first supported value
446-
var c2Selection string
447-
c2Default, _ := c2.ImplToString(conf.SupportedC2[0])
448-
c2Available := "The C2 server implementation to use. Supported: "
449-
for _, value := range conf.SupportedC2 {
450-
c2Name, ok := c2.ImplToString(value)
451-
if ok {
452-
c2Available += "\n\t" + c2Name
453-
}
454-
455-
// add the supported c2 flags, allowing for command line config of the backend
456-
impl, success := c2.GetInstance(value)
457-
if success {
458-
impl.CreateFlags()
459-
}
460-
}
461-
c2Available += "\n"
462-
flag.StringVar(&c2Selection, "c2", c2Default, c2Available)
487+
c2Flags(&c2Selection, conf)
463488

464489
flag.Usage = func() {
465490
// banner explaining what the software is
@@ -478,23 +503,7 @@ func CodeExecutionCmdLineParse(conf *config.Config) bool {
478503

479504
// validate a reverse shell or bind shell params are correctly specified
480505
if conf.DoExploit {
481-
c2Selected, ok := c2.StringToImpl(c2Selection)
482-
if !ok {
483-
output.PrintFrameworkError("Provided an invalid c2 implementation")
484-
success = false
485-
}
486-
// is this a supported c2?
487-
foundSupported := false
488-
for _, value := range conf.SupportedC2 {
489-
if c2Selected == value {
490-
foundSupported = true
491-
}
492-
}
493-
if !foundSupported {
494-
output.PrintFrameworkError("The c2 you selected is not supported by this exploit.")
495-
success = false
496-
}
497-
conf.C2Type = c2Selected
506+
success = validateC2Selection(c2Selection, conf)
498507

499508
if rhostsFile == "-" {
500509
// this is a pretty dirty check but c2 that use stdin can't be used after piping targets in
@@ -589,3 +598,132 @@ func WebShellCmdLineParse(conf *config.Config) bool {
589598
return handleLogOptions(logFile, frameworkLogLevel, exploitLogLevel) &&
590599
commonValidate(conf, rhosts, rports, rhostsFile) && handleRhostsOptions(conf, rhosts, rports, rhostsFile)
591600
}
601+
602+
func loadFileFormatTemplate(templateFilePath string, conf *config.Config) bool {
603+
if len(templateFilePath) == 0 {
604+
// the user doesn't have to provide an -in. There are plenty of scenarios where I could imagine
605+
// the template would be embedded in the exploit. That seems fine to me.
606+
return true
607+
}
608+
609+
fileTemplate, err := os.Open(templateFilePath)
610+
if err != nil {
611+
output.PrintfFrameworkError("Failed to open the template file: %s", err.Error())
612+
613+
return false
614+
}
615+
defer fileTemplate.Close()
616+
617+
content, err := io.ReadAll(fileTemplate)
618+
if err != nil {
619+
output.PrintfFrameworkError("Failed to read the template file: %s", err.Error())
620+
621+
return false
622+
}
623+
624+
conf.FileTemplateData = string(content)
625+
if len(conf.FileTemplateData) == 0 {
626+
output.PrintfFrameworkError("The template file was empty")
627+
628+
return false
629+
}
630+
631+
return true
632+
}
633+
634+
// FileFormat doesn't handle any type of remote host configuration. FileFormat exploits just
635+
// take an -in and and -out, where "in" is expected to be some type of template and "out" is
636+
// the file to generate.
637+
func FormatFileCmdLineParse(conf *config.Config) bool {
638+
var logFile string
639+
var frameworkLogLevel string
640+
var exploitLogLevel string
641+
var templateFile string
642+
var c2Selection string
643+
644+
loggingFlags(&logFile, &frameworkLogLevel, &exploitLogLevel)
645+
localHostFlags(conf)
646+
exploitFunctionality(conf)
647+
c2Flags(&c2Selection, conf)
648+
flag.StringVar(&templateFile, "in", "", "The file format template to work with")
649+
flag.StringVar(&conf.FileFormatFilePath, "out", "", "The file to write the malicious file to")
650+
651+
flag.Usage = func() {
652+
// banner explaining what the software is
653+
fmt.Printf("An exploit for %s %s that crafts a malicious file\n\n", conf.Product, conf.CVE)
654+
655+
// print default usage information
656+
flag.PrintDefaults()
657+
658+
// usage examples
659+
fmt.Println("Usage example:")
660+
fmt.Println("\t./exploit -e -in <file> -out <file>")
661+
}
662+
flag.Parse()
663+
664+
if !loadFileFormatTemplate(templateFile, conf) {
665+
return false
666+
}
667+
if len(conf.FileFormatFilePath) == 0 {
668+
output.PrintFrameworkError("Must provide an -out parameter")
669+
670+
return false
671+
}
672+
if !conf.DoExploit {
673+
output.PrintFrameworkError("Exploitation must be invoked for file format exploits")
674+
675+
return false
676+
}
677+
if conf.DoVerify || conf.DoVersionCheck {
678+
output.PrintFrameworkError("Verification and version checking are disabled for file format exploits")
679+
680+
return false
681+
}
682+
if !validateC2Selection(c2Selection, conf) {
683+
return false
684+
}
685+
if !conf.ThirdPartyC2Server && (conf.Lport == 0 || len(conf.Lhost) == 0) {
686+
output.PrintFrameworkError("Missing exploitation options (-Lhost or -Lport)")
687+
688+
return false
689+
}
690+
691+
return handleLogOptions(logFile, frameworkLogLevel, exploitLogLevel)
692+
}
693+
694+
func LocalCmdLineParse(conf *config.Config) bool {
695+
var logFile string
696+
var frameworkLogLevel string
697+
var exploitLogLevel string
698+
var c2Selection string
699+
700+
loggingFlags(&logFile, &frameworkLogLevel, &exploitLogLevel)
701+
localHostFlags(conf)
702+
exploitFunctionality(conf)
703+
c2Flags(&c2Selection, conf)
704+
705+
flag.Usage = func() {
706+
// banner explaining what the software is
707+
fmt.Printf("An exploit for %s %s that exploits a local vulnerability\n\n", conf.Product, conf.CVE)
708+
709+
// print default usage information
710+
flag.PrintDefaults()
711+
712+
// usage examples
713+
fmt.Println("Usage example:")
714+
fmt.Println("\t./exploit -e")
715+
}
716+
flag.Parse()
717+
718+
if !validateC2Selection(c2Selection, conf) {
719+
return false
720+
}
721+
722+
if !conf.ThirdPartyC2Server && (conf.Lport == 0 || len(conf.Lhost) == 0) {
723+
output.PrintFrameworkError("Missing exploitation options (-Lhost or -Lport)")
724+
725+
return false
726+
}
727+
728+
return handleLogOptions(logFile, frameworkLogLevel, exploitLogLevel)
729+
}

cli/commandline_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cli
22

33
import (
4+
"strings"
45
"testing"
56

67
"github.com/vulncheck-oss/go-exploit/c2"
@@ -285,3 +286,16 @@ func TestParseIntelJSON(t *testing.T) {
285286
t.Fatal("Invalid triplet parsing")
286287
}
287288
}
289+
290+
func TestFileFormatParams(t *testing.T) {
291+
conf := config.NewLocal(config.FileFormat, []c2.Impl{}, "test product", "CVE-2023-1270")
292+
if !loadFileFormatTemplate("", conf) {
293+
t.Fatal("an empty file path should pass validation")
294+
}
295+
if !loadFileFormatTemplate("commandline_test.go", conf) {
296+
t.Fatal("failed to load the file format template")
297+
}
298+
if !strings.Contains(conf.FileTemplateData, "TestFileFormatParams") {
299+
t.Fatal("failed to load the file format template")
300+
}
301+
}

config/config.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ const (
1010
CodeExecution ExploitType = 0
1111
InformationDisclosure ExploitType = 1
1212
Webshell ExploitType = 2
13+
FileFormat ExploitType = 3
14+
Local ExploitType = 4
1315
)
1416

1517
type SSLSupport int
@@ -73,6 +75,10 @@ type Config struct {
7375
ThirdPartyC2Server bool
7476
// The database we are working with
7577
DBName string
78+
// File format template
79+
FileTemplateData string
80+
// File format exploit output
81+
FileFormatFilePath string
7682
}
7783

7884
func New(extype ExploitType, supportedC2 []c2.Impl, product string, cve string, defaultPort int) *Config {
@@ -85,3 +91,13 @@ func New(extype ExploitType, supportedC2 []c2.Impl, product string, cve string,
8591

8692
return returnVal
8793
}
94+
95+
func NewLocal(extype ExploitType, supportedC2 []c2.Impl, product string, cve string) *Config {
96+
returnVal := new(Config)
97+
returnVal.ExType = extype
98+
returnVal.SupportedC2 = supportedC2
99+
returnVal.Product = product
100+
returnVal.CVE = cve
101+
102+
return returnVal
103+
}

docs/exploit-types.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,25 @@
11
# `go-exploit` Exploit Types
22

3-
The `go-exploit` framework currently supports three exploit types. These types determine how the command-line interface accepts arguments and define the post-exploitation behavior. The three exploit types are defined in `config/config.go`:
3+
The `go-exploit` framework currently supports three exploit types. These types determine how the command-line interface accepts arguments and define the post-exploitation behavior. The fives exploit types are defined in `config/config.go`:
44

55
1. CodeExecution
66
2. InformationDisclosure
77
3. Webshell
8+
4. File Format
9+
5. Local
810

9-
To configure the exploit type in the exploit's `main` function, you can use the `config.New` function as follows:
11+
To configure the exploit type in the exploit's `main` function, you can use the `config.New` function for remote exploits as follows:
1012

1113
```go
1214
conf := config.New(config.CodeExecution, supportedC2, "My Target", "CVE-2023-1270", 80)
1315
```
1416

17+
Local exploits (including File Format) omits the default port:
18+
19+
```go
20+
conf := config.NewLocal(config.FileFormat,s upportedC2, "My Target", "CVE-2023-1270")
21+
```
22+
1523
## Examples
1624

1725
### Code Execution

0 commit comments

Comments
 (0)