Skip to content

Commit dc1da1f

Browse files
committed
refactor old code
1 parent 3c2d204 commit dc1da1f

File tree

11 files changed

+626
-1800
lines changed

11 files changed

+626
-1800
lines changed

README.md

Lines changed: 35 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,133 +1,73 @@
11
# go-crypter
22

3-
A cryptographic payload loader and executor designed for advanced in-memory execution techniques. This project combines strong encryption, compression, and sophisticated evasion capabilities to execute both shellcode and PE files directly in memory.
3+
this is a loader that consists of two parts - the encrypter and the loader, both PEs and shellcode can be encrypted and embedded
4+
into a loader that offers multiple execution options for shellcode, pe's are just mapped and their entry point is executed with ntdll!rtlcreateuserthread. for shellcode, you can take a few different paths each with their own upsides and downsides evasion wise. this project is meant to be compiled on win10+ x64 only.
45

5-
## Features
6+
# enclave
7+
1. uses mscoree!GetProcessExecutableHeap, vdsutil!VdsHeapAlloc, and ntdll!LdrCallEnclave
8+
2. memory region of shellcode is RWX by default, as GetProcessExecutableHeap is usually used for JIT stuff
69

7-
### Encryption & Compression
10+
# indirect syscalls
11+
1. uses ntdll!NtAllocateVirtualMemory, ntdll!ProtectVirtualMemory to allocate memory and flip prots (takes PAGE_READWRITE -> PAGE_EXECUTE_READ path
12+
2. uses ntdll!RtlCreateUserThread to execute entry point
13+
14+
# run once
15+
1. uses ntdll!NtAllocateVirtualMemory, ntdll!ProtectVirtualMemory to allocate memory and flip prots (also takes PAGE_READWRITE -> PAGE_EXECUTE_READ path
16+
2. executes entry point with ntdll!RtlRunOnceExecuteOnce which does exactly what it says
17+
18+
## features
19+
20+
### encryption & compression
821
- **Multiple encryption algorithms**: ChaCha20-Poly1305, AES-GCM, Twofish-GCM
922
- **Argon2id key derivation** with configurable parameters for enhanced security
1023
- **Automatic compression** using zlib to reduce payload size
1124
- **CBOR serialization** for efficient binary encoding
1225

13-
### Execution Capabilities
14-
- **Dual payload support**: Handles both raw shellcode and PE executables
15-
- **In-memory PE execution**: Full RunPE implementation with proper relocation and import resolution
16-
- **Shellcode injection**: Direct shellcode execution using advanced injection techniques
17-
18-
### Evasion Features
19-
- **Self-deletion**: Automatic removal of the stub executable from disk (this being called prior to execution may seem weird, but as long as your payload is mapped into memory already (it is, it's embedded) execution will fire off, and the stub gets removed)
20-
- **Anti-monitoring patches**: Disables AMSI, ETW, debugging, and trace logging
21-
- **Direct syscalls**: Utilizes [go-direct-syscall](https://github.com/carved4/go-direct-syscall) for API evasion
22-
- **Memory-only execution**: No disk artifacts after initial execution
26+
### capabilities
27+
- **Dual payload support**: handles both raw shellcode and PE executables
28+
- **In-memory PE execution**: Full runpe implementation with proper relocation and import resolution
29+
- **Shellcode injection**: direct shellcode execution using some silly injection techniques
2330

24-
## Usage
2531

26-
### Encrypting Payloads
32+
### encrypting payloads
2733

2834
```bash
29-
# Encrypt shellcode (default)
30-
./crypt -type shellcode payload.bin
35+
# encrypt shellcode (default, used chacha20)
36+
go run crypt.go payload.bin
3137

32-
# Encrypt PE executable
33-
./crypt -type exe malware.exe
34-
35-
# Specify encryption algorithm
36-
./crypt -alg chacha20 -type exe payload.exe
38+
# encrypt PE executable with aesgcm
39+
go run crypt.go payload.exe -alg aesgcm
3740
```
3841

39-
### Available Options
42+
### available options
4043
- `-alg`: Encryption algorithm (chacha20, aesgcm, twofish)
41-
- `-type`: Payload type (shellcode, exe)
4244

43-
## Architecture
45+
## architecture
4446

4547
The project consists of two main components:
4648

47-
1. **Crypt**: Encrypts and packages payloads into CBOR format with embedded metadata
48-
2. **Stub**: Self-contained executable that decrypts and executes the embedded payload
49-
50-
## Execution Flow
51-
52-
```mermaid
53-
flowchart TD
54-
A["Stub Execution Starts"] --> B["Decrypt Embedded Payload"]
55-
B --> C["Extract Payload Metadata"]
56-
C --> D["Decompress if Compressed"]
57-
D --> E["Self-Delete Executable"]
58-
E --> F["Apply AMSI/ETW Patches"]
59-
F --> G{"Check Payload Type"}
60-
G -->|Shellcode| H["Execute via NtInjectSelfShellcode"]
61-
G -->|PE Executable| I["Execute via RunPE"]
62-
H --> J["Payload Running in Memory"]
63-
I --> J
64-
65-
style A fill:#e1f5fe,stroke:#000,stroke-width:2px,color:#000
66-
style B fill:#f5f5f5,stroke:#000,stroke-width:2px,color:#000
67-
style C fill:#f5f5f5,stroke:#000,stroke-width:2px,color:#000
68-
style D fill:#f5f5f5,stroke:#000,stroke-width:2px,color:#000
69-
style E fill:#f5f5f5,stroke:#000,stroke-width:2px,color:#000
70-
style F fill:#fff3e0,stroke:#000,stroke-width:2px,color:#000
71-
style G fill:#f5f5f5,stroke:#000,stroke-width:2px,color:#000
72-
style H fill:#f5f5f5,stroke:#000,stroke-width:2px,color:#000
73-
style I fill:#f5f5f5,stroke:#000,stroke-width:2px,color:#000
74-
style J fill:#c8e6c9,stroke:#000,stroke-width:2px,color:#000
75-
```
76-
77-
## Technical Details
78-
79-
### Cryptographic Implementation
80-
- **Key derivation**: Argon2id with configurable time, memory, and thread parameters
81-
- **Authentication**: All algorithms provide authenticated encryption (AEAD)
82-
- **Random generation**: Cryptographically secure random passwords, salts, and nonces
83-
84-
### Anti-Detection Mechanisms
85-
- **PatchAMSI**: Disable Anti-Malware Scan Interface
86-
- **PatchETW**: Disable Event Tracing for Windows
87-
- **PatchDbgUiRemoteBreakin**: Prevent remote debugger attachment
88-
- **PatchNtTraceEvent**: Prevent trace event logging
89-
- **PatchNtSystemDebugControl**: Prevent debug control operations
90-
91-
### Memory Execution
92-
- **Section mapping**: Uses NtCreateSection and NtMapViewOfSection for memory allocation
93-
- **Import resolution**: Dynamically resolves imported functions
94-
- **Relocation handling**: Properly handles address relocations for ASLR
95-
- **TLS callbacks**: Executes Thread Local Storage initialization routines
96-
97-
## Dependencies
98-
99-
- `github.com/carved4/go-direct-syscall` - Direct Windows syscall interface
100-
- `github.com/Binject/debug` - PE file parsing and manipulation
101-
- `github.com/fxamacker/cbor/v2` - CBOR encoding/decoding
102-
- `golang.org/x/crypto` - Cryptographic algorithms
49+
1. **crypt**: encrypts and packages payloads into CBOR format with embedded metadata
50+
2. **stub**: self-contained executable that decrypts and executes the embedded payload
10351

10452
## Building
10553

10654
```bash
107-
# Build the encryption tool
108-
go build -o crypt.exe ./crypt
109-
110-
# Build the stub (after encrypting a payload)
111-
go build -o stub.exe ./stub
55+
# build the stub (after encrypting a payload)
56+
cd ../stub && go build -o stub.exe
11257
```
11358

114-
## Running
59+
## running
11560
```bash
11661
# after running the crypter tool and building the stub, you can pass some flags to specify how you want to run
11762

118-
./stub.exe -sleepy # self inject with page no access delay to trip EDRs
63+
./stub.exe -enclave
11964

120-
./stub.exe -ghost # self inject standard
65+
./stub.exe -indirec
12166

122-
./stub.exe -phantom # inject with queueapc + page no access delay
67+
./stub.exe -once
12368

12469
# or
12570

12671
./stub.exe # with no flags to run an embedded EXE or shellcode with the default methods
12772

12873
```
129-
130-
131-
## Security Considerations
132-
133-
This tool is designed for security research, penetration testing, and red team exercises. Users are responsible for ensuring compliance with applicable laws and regulations in their jurisdiction.

crypt/crypt.go

Lines changed: 30 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -20,25 +20,23 @@ import (
2020
"golang.org/x/crypto/twofish"
2121
)
2222

23-
// Default Argon2 parameters
2423
const (
2524
argonTime uint32 = 1
2625
argonMemory uint32 = 64 * 1024
2726
argonThreads uint8 = 4
2827
argonKeyLen uint32 = chacha20poly1305.KeySize
2928
saltSize = 16
30-
passwordSize = 32 // Size of the random password
29+
passwordSize = 32
3130
)
3231

33-
// PayloadData represents the structure of our CBOR payload
3432
type PayloadData struct {
3533
EncryptedBytes []byte `cbor:"encrypted"`
3634
Password []byte `cbor:"password"`
3735
Salt []byte `cbor:"salt"`
3836
Nonce []byte `cbor:"nonce"`
3937
Alg string `cbor:"alg"`
40-
Compressed bool `cbor:"compressed,omitempty"` // Flag to indicate if data is compressed
41-
PayloadType string `cbor:"payload_type"` // "exe" or "shellcode"
38+
Compressed bool `cbor:"compressed,omitempty"`
39+
PayloadType string `cbor:"payload_type"`
4240
ArgonParams struct {
4341
Time uint32 `cbor:"time"`
4442
Memory uint32 `cbor:"memory"`
@@ -48,36 +46,34 @@ type PayloadData struct {
4846

4947
func main() {
5048
algFlag := flag.String("alg", "chacha20", "encryption algorithm: chacha20, aesgcm, twofish")
51-
typeFlag := flag.String("type", "shellcode", "payload type: exe or shellcode")
49+
typeFlag := flag.String("type", "shellcode", "type of file, you don't need to set this")
5250
flag.Parse()
5351

5452
if flag.NArg() < 1 {
55-
fmt.Printf("Run with %s <inputfile>\n", os.Args[0])
53+
fmt.Printf("[+] run with %s <inputfile>\n", os.Args[0])
5654
os.Exit(1)
5755
}
5856

5957
fname := flag.Arg(0)
58+
6059
plaintextBytes, err := os.ReadFile(fname)
6160
if err != nil {
62-
log.Fatalf("Failed to read file: %v", err)
61+
log.Fatalf("[-] failed to read file: %v", err)
6362
}
6463

6564
stubDir := filepath.Join("..", "stub")
6665
payloadPath := filepath.Join(stubDir, "payload.cbor")
6766

68-
// Generate a random password (instead of using the key directly)
6967
password := make([]byte, passwordSize)
7068
if _, err := io.ReadFull(rand.Reader, password); err != nil {
71-
log.Fatalf("Failed to generate random password: %v", err)
69+
log.Fatalf("[-] failed to generate random password: %v", err)
7270
}
7371

74-
// Generate a random salt for Argon2
7572
salt := make([]byte, saltSize)
7673
if _, err := io.ReadFull(rand.Reader, salt); err != nil {
77-
log.Fatalf("Failed to generate random salt: %v", err)
74+
log.Fatalf("[-] failed to generate random salt: %v", err)
7875
}
7976

80-
// Derive the encryption key using Argon2id
8177
key := argon2.IDKey(password, salt, argonTime, argonMemory, argonThreads, argonKeyLen)
8278

8379
var aead cipher.AEAD
@@ -86,84 +82,75 @@ func main() {
8682
case "aesgcm", "aes":
8783
block, err := aes.NewCipher(key)
8884
if err != nil {
89-
log.Fatalf("Failed to create AES cipher: %v", err)
85+
log.Fatalf("[-] failed to create AES cipher: %v", err)
9086
}
9187
aead, err = cipher.NewGCM(block)
9288
if err != nil {
93-
log.Fatalf("Failed to create AES-GCM AEAD: %v", err)
89+
log.Fatalf("[-] failed to create AES-GCM AEAD: %v", err)
9490
}
9591
case "twofish":
9692
block, err := twofish.NewCipher(key)
9793
if err != nil {
98-
log.Fatalf("Failed to create Twofish cipher: %v", err)
94+
log.Fatalf("[-] failed to create Twofish cipher: %v", err)
9995
}
10096
aead, err = cipher.NewGCM(block)
10197
if err != nil {
102-
log.Fatalf("Failed to create Twofish-GCM AEAD: %v", err)
98+
log.Fatalf("[-] failed to create Twofish-GCM AEAD: %v", err)
10399
}
104100
default:
105101
aead, err = chacha20poly1305.New(key)
106102
if err != nil {
107-
log.Fatalf("Failed to create AEAD: %v", err)
103+
log.Fatalf("[-] failed to create AEAD: %v", err)
108104
}
109105
alg = "chacha20"
110106
}
111107

112-
// Generate a random nonce appropriate for the algorithm
113108
nonce := make([]byte, aead.NonceSize())
114109
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
115-
log.Fatalf("Failed to generate random nonce: %v", err)
110+
log.Fatalf("[-] failed to generate random nonce: %v", err)
116111
}
117112

118-
// Compress the plaintext data before encryption
119113
var dataToEncrypt []byte
120-
compressed := true // Default to attempting compression
114+
compressed := true
121115

122-
// Try to compress the data using zlib
123116
var b bytes.Buffer
124117
zw, err := zlib.NewWriterLevel(&b, zlib.BestCompression)
125118
if err != nil {
126-
log.Printf("Warning: Failed to create zlib writer: %v", err)
119+
log.Printf("[!]: [-] failed to create zlib writer: %v", err)
127120
compressed = false
128121
dataToEncrypt = plaintextBytes
129122
} else {
130-
// Write data to the compressed buffer
131123
_, err = zw.Write(plaintextBytes)
132124
if err != nil {
133-
log.Printf("Warning: Failed to compress data: %v", err)
125+
log.Printf("[!]: [-] failed to compress data: %v", err)
134126
compressed = false
135127
dataToEncrypt = plaintextBytes
136128
} else {
137-
// Close to flush any pending data
138129
err = zw.Close()
139130
if err != nil {
140-
log.Printf("Warning: Failed to finalize compression: %v", err)
131+
log.Printf("[!]: [-] failed to finalize compression: %v", err)
141132
compressed = false
142133
dataToEncrypt = plaintextBytes
143134
} else {
144-
// Get the compressed data
145135
compressedData := b.Bytes()
146-
147-
// Only use compression if it actually reduces size
148136
if len(compressedData) < len(plaintextBytes) {
149137
dataToEncrypt = compressedData
150-
fmt.Printf("Compression reduced size from %d to %d bytes (%.2f%%)",
138+
fmt.Printf("[+] compression reduced size from %d to %d bytes (%.2f%%)",
151139
len(plaintextBytes), len(compressedData),
152140
float64(len(compressedData))/float64(len(plaintextBytes))*100)
153141
} else {
154-
// Compression didn't help, use original data
155142
compressed = false
156143
dataToEncrypt = plaintextBytes
157-
fmt.Println("Compression did not reduce size, using uncompressed data")
144+
fmt.Println("[+] compression did not reduce size, using uncompressed data")
158145
}
159146
}
160147
}
161148
}
162149

163-
// Encrypt the data with authentication
164150
encryptedBytes := aead.Seal(nil, nonce, dataToEncrypt, nil)
165-
166-
// Create the payload structure
151+
if strings.Contains(fname, ".exe") {
152+
flag.Set("type", "exe")
153+
}
167154
payload := PayloadData{
168155
EncryptedBytes: encryptedBytes,
169156
Password: password,
@@ -173,33 +160,26 @@ func main() {
173160
Compressed: compressed,
174161
PayloadType: strings.ToLower(*typeFlag),
175162
}
176-
177-
// Set the Argon2 parameters
178163
payload.ArgonParams.Time = argonTime
179164
payload.ArgonParams.Memory = argonMemory
180165
payload.ArgonParams.Threads = uint8(argonThreads)
181-
182-
// Create CBOR encoder with compression options
183166
encOpts := cbor.EncOptions{
184-
Sort: cbor.SortBytewiseLexical, // Sort map keys for deterministic output
167+
Sort: cbor.SortBytewiseLexical,
185168
}
186169

187-
// Create encoder with options
188170
encMode, err := encOpts.EncMode()
189171
if err != nil {
190-
log.Fatalf("Failed to create CBOR encoder: %v", err)
172+
log.Fatalf("[-] failed to create CBOR encoder: %v", err)
191173
}
192174

193-
// Marshal the payload to CBOR
194175
cborData, err := encMode.Marshal(payload)
195176
if err != nil {
196-
log.Fatalf("Failed to marshal CBOR data: %v", err)
177+
log.Fatalf("[-] failed to marshal CBOR data: %v", err)
197178
}
198179

199-
// Write the CBOR data to file
200180
if err := os.WriteFile(payloadPath, cborData, 0600); err != nil {
201-
log.Fatalf("Failed to write CBOR payload: %v", err)
181+
log.Fatalf("[-] failed to write CBOR payload: %v", err)
202182
}
203183

204-
fmt.Printf("Encryption completed successfully!\nCBOR payload saved to:\n- %s\n", payloadPath)
205-
}
184+
fmt.Printf("[+] encryption completed successfully!\nCBOR payload saved to:\n- %s\n", payloadPath)
185+
}

0 commit comments

Comments
 (0)