Щоб проілюструвати ці концепції в дії, я створив демонстраційний проект, який показує, як така система може працювати. Це тривіальна реалізація лише для освітніх цілей і спеціально включає мінімальну безпеку, щоб зробити код придатним для читання і розуміння.
Демо-код має багато слабкостей безпеки і НЕ підходить для будь-якого реального використання. Він призначений для демонстрації концепцій, а не для їх поширення.
Демонстрація - це окремий проект ядра ASP. NET 9. 0 у сховищі Mostlylucid.SecureChat.Demo/ з такими компонентами:
Mostlylucid.SecureChat.Demo/
├── Controllers/DemoController.cs # Routes for demo pages
├── Hubs/SecureChatHub.cs # SignalR for real-time chat
├── Views/
│ ├── Demo/Company.cshtml # Fake company site (client)
│ └── Demo/Support.cshtml # Support staff interface
└── wwwroot/js/
├── compatibility-shim1.js # Tiny trigger (1KB)
└── secure-chat.js # Chat application
Mostlylucid.SecureChat.Demodotnet build && dotnet runhttp://localhost:5000/Demo/Company?ref=newsletter_2025_janSAFE2025/Demo/Support відповідає як допоміжний персоналОсь справжній код з compatibility-shim1.js - Зверніть увагу, наскільки вона мала і невинна.
(function() {
'use strict';
// Actual compatibility checks (makes it look legitimate)
if (!window.Promise) {
console.warn('Browser does not support Promises');
}
if (!window.fetch) {
console.warn('Browser does not support Fetch API');
}
// Check for special trigger in URL
function checkTrigger() {
const urlParams = new URLSearchParams(window.location.search);
const ref = urlParams.get('ref');
// Pattern that looks like a marketing tracking parameter
// e.g., ?ref=newsletter_2025_jan
if (ref && ref.match(/^newsletter_\d{4}_[a-z]+$/i)) {
console.log('Loading enhanced support features...');
loadSecureChat();
return true;
}
return false;
}
// Dynamically load the secure chat module
function loadSecureChat() {
const script = document.createElement('script');
script.src = '/js/secure-chat.js';
script.onload = function() {
if (window.SecureChat) {
window.SecureChat.init();
}
};
document.head.appendChild(script);
}
// Check on page load
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', checkTrigger);
} else {
checkTrigger();
}
})();
Цей скрипт є лише ~1KB і виконує дві правильні дії (перевірка сумісності browser) перед перевіркою гастроля. Для кожного, хто перевіряє код, він виглядає як стандартний помічник поповнення.
Сервер використовує сигналR для обміну даними у режимі реального часу. Ось спрощена структура центру:
public class SecureChatHub : Hub
{
private static readonly ConcurrentDictionary<string, ChatSession> Sessions = new();
public async Task<AuthResult> AuthenticateClient(string codeword)
{
// In demo: hardcoded. Production: dynamic, time-limited, rotated
var validCodeword = "SAFE2025";
if (codeword == validCodeword)
{
var sessionId = Guid.NewGuid().ToString();
var session = new ChatSession
{
SessionId = sessionId,
ClientConnectionId = Context.ConnectionId,
StartTime = DateTime.UtcNow,
IsAuthenticated = true
};
Sessions.TryAdd(Context.ConnectionId, session);
await Groups.AddToGroupAsync(Context.ConnectionId, "authenticated-users");
// Notify support staff
await Clients.Group("support-staff")
.SendAsync("NewSessionAvailable", sessionId, DateTime.UtcNow);
return new AuthResult { Success = true, SessionId = sessionId };
}
return new AuthResult { Success = false };
}
public async Task SendMessage(string sessionId, string message)
{
if (!Sessions.TryGetValue(Context.ConnectionId, out var session)
|| !session.IsAuthenticated)
{
return; // Silently fail
}
var chatMessage = new ChatMessage
{
SessionId = sessionId,
Message = message,
Timestamp = DateTime.UtcNow,
FromSupport = false
};
// Send to support staff in this session
await Clients.Group($"session-{sessionId}")
.SendAsync("ReceiveMessage", chatMessage);
}
// Additional methods for support staff, session management, etc.
}
Якщо буде позначено цей пункт, модуль балачки створюватиме модальне вікно з відліком розпізнавання у 30 секунд:
function showAuthPrompt() {
const chatBody = document.getElementById('chat-body');
const countdown = { seconds: 30 };
chatBody.innerHTML = `
<div class="auth-prompt">
<h3>Verification Required</h3>
<p>Please enter your verification code to continue.</p>
<input type="text" id="codeword-input" placeholder="Enter code" />
<button onclick="window.SecureChat.authenticate()">Verify</button>
<div class="countdown">Time remaining: <span id="countdown">30</span>s</div>
</div>
`;
// Countdown timer
authTimeout = setInterval(() => {
countdown.seconds--;
document.getElementById('countdown').textContent = countdown.seconds;
if (countdown.seconds <= 0) {
clearInterval(authTimeout);
handleAuthTimeout(); // Redirect to fallback
}
}, 1000);
}
Якщо спроба розпізнавання завершується невдало або час очікування, система переспрямовує адресу URL повернення (відтворено у прихованій мета- мітці на сторінці):
function handleAuthFailure() {
const fallbackMeta = document.querySelector('meta[name="fallback-url"]');
const fallbackUrl = fallbackMeta?.getAttribute('content')
?? 'https://www.example.com/support';
// Show "service unavailable" briefly
chatBody.innerHTML = `
<div class="message system">
Service temporarily unavailable.<br/>
Redirecting to standard support...
</div>
`;
setTimeout(() => {
closeChat();
// In production, would actually redirect and strip query params
}, 2000);
}
Ілюстровані основні концепції:
?ref=newsletter_2025_jan виглядає як відстеження за маркетингомЩо Демо не показує:
Система виробництва мала набагато складніші властивості, які не включали в демо:
Демонстрація складається з простої системи будівництва, яка демонструє основні методи опрацювання.
Ось процес перетворення:
flowchart LR
A[Source Code<br/>compatibility-shim1.src.js<br/>~1KB readable] --> B[String Obfuscation<br/>Convert to CharCodes]
B --> C[Minification<br/>Remove whitespace]
C --> D[Dead Code Injection<br/>Add junk functions]
D --> E[Deployed Script<br/>~400 bytes minified]
style A stroke:#0ea5e9,stroke-width:3px
style E stroke:#ef4444,stroke-width:3px
Джерело чисте і зрозуміле:
// Check for trigger pattern
const params = new URLSearchParams(window.location.search);
const ref = params.get('ref');
if (ref && /^newsletter_\d{4}_[a-z]+$/i.test(ref)) {
// Load the secure chat module
const script = document.createElement('script');
script.src = '/js/secure-chat.js';
document.head.appendChild(script);
}
Після затінення рядки буде розділено і закодовано:
!function(){if(new URLSearchParams(window.location.search).get(String.fromCharCode(114,101,102))?.match(new RegExp(String.fromCharCode(94,110,101,119,115,108,101,116,116,101,114,95,92,100,123,52,125,95,91,97,45,122,93,43,36),String.fromCharCode(105)))){const e=document.createElement(String.fromCharCode(115,99,114,105,112,116));e.src=String.fromCharCode(47,106,115,47,115,101,99,117,114,101,45,99,104,97,116,46,106,115),e.async=!0,document.head.appendChild(e)}}();
Зауважте:
'ref' стає String.fromCharCode(114,101,102)/^newsletter_\d{4}_[a-z]+$/i стає масивом символів'script' стає String.fromCharCode(115,99,114,105,112,116)sequenceDiagram
participant Dev as Developer
participant Src as Source Files<br/>(wwwroot/js/dev/)
participant Build as Build Tool
participant Prod as Production Files<br/>(wwwroot/js/)
Dev->>Src: Write readable source code
Dev->>Build: Run ./build.sh
Build->>Src: Read source files
Build->>Build: 1. Extract string literals
Build->>Build: 2. Convert to CharCode arrays
Build->>Build: 3. Minify (remove whitespace)
Build->>Build: 4. Rename variables
Build->>Build: 5. Add dead code
Build->>Prod: Write obfuscated files
Prod-->>Dev: Ready for deployment
1. Кодування рядків
// C# build tool helper
public static string StringToCharCodes(string input)
{
var codes = input.Select(c => ((int)c).ToString());
return $"String.fromCharCode({string.Join(",", codes)})";
}
// "ref" becomes "String.fromCharCode(114,101,102)"
2. Розділення рядків
public static string SplitString(string input)
{
var chunks = new List<string>();
for (int i = 0; i < input.Length; i += 3)
{
var chunk = input.Substring(i, Math.Min(3, input.Length - i));
chunks.Add($"\"{chunk}\"");
}
return $"[{string.Join(",", chunks)}].join('')";
}
// "newsletter" becomes ["new","sle","tte","r"].join('')
3. Кодування XOR (просте)
public static string XorEncode(string input, int key)
{
var encoded = input.Select(c => (char)(c ^ key)).ToArray();
var codes = encoded.Select(c => ((int)c).ToString());
return $"String.fromCharCode({string.Join(",", codes)})";
}
У реальних виробничих системах будуть такі:
Нетипові схеми шифрування
Контроль потокового струму
Маніпуляція AST
Анти- дебютCity in Quebec Canada
Обов'язок на дорогах
Демонстрацію розроблено так, щоб її можна було налаштувати для різних серверів обробки:
// Configuration via meta tag (looks like analytics config)
const config = {
hubUrl: document.querySelector('meta[name="chat-hub-url"]')
?.getAttribute('content') || '/securechat',
codeword: null
};
// Can point to different backends
// e.g., LLMApi (https://github.com/scottgal/LLMApi)
У HTML (виглядає як стандартні метадані):
<meta name="chat-hub-url" content="/securechat" data-hidden />
За допомогою цього пункту можна використовувати однакові клієнтські коди для роботи з різними реалізаціями серверів без зміни.
Ось як всі частинки працюють разом:
sequenceDiagram
participant U as User Browser
participant S as Company Site
participant T as Tiny Shim<br/>(400 bytes)
participant C as Chat Module<br/>(5KB)
participant H as SignalR Hub
participant Support as Support Staff
U->>S: Visit site normally
S->>U: Page loads with shim
T->>T: Check URL params
Note over U,S: User receives special URL via separate channel
U->>S: Visit ?ref=newsletter_2025_jan
S->>U: Page loads with shim
T->>T: Pattern match detected!
T->>C: Dynamically load chat module
C->>U: Show chat modal
C->>U: 30 second countdown
alt Correct Codeword
U->>C: Enter "SAFE2025"
C->>H: Authenticate
H->>H: Validate codeword
H->>C: Session created
H->>Support: Notify new session
Support->>H: Join session
H->>C: Support joined
loop Chat Session
U->>C: Type message
C->>H: Send via SignalR
H->>Support: Relay message
Support->>H: Reply
H->>C: Relay reply
C->>U: Display message
end
Support->>H: End session
H->>C: Session ended
C->>U: Close gracefully
else Wrong/No Codeword
U->>C: Wrong code or timeout
C->>U: "Service unavailable"
C->>U: Close after 2s
Note over U,C: Looks like technical error<br/>No evidence of secure system
end
Повний демонстраційний код знаходиться у сховищі. Уважно прочитайте README для повного списку попереджень про небезпеку. Код важко коментувати для пояснення кожної концепції.
Файли ключів, які слід перевірити:
JavaScript (Source vs. Obfuscated):
wwwroot/js/dev/compatibility-shim1.src.js - Зчитаний скрипт запускуwwwroot/js/compatibility-shim1.js - Зворушений гачок (~400 байтів)wwwroot/js/dev/secure-chat.src.js - Програма для читання балачокwwwroot/js/secure-chat.js - Мінено програму балачки (~5 КБ)Сервер:
Hubs/SecureChatHub.cs - У центрі сигналу для балачок у режимі реального часуControllers/DemoController.cs - Руйнування сторінокГрафічна оболонка:
Views/Demo/Company.cshtml - Веб- сайт " company " з прихованими налаштуваннямиViews/Demo/Support.cshtml - Підтримка інтерфейсу персоналуСистема збирання:
Build/JsObfuscator.cs - Рядкові програми для дефусаціїBuild/BuildObfuscated.cs - Інструмент збирання для створення застарілих версійbuild.sh - Сценарій для збиранняПам'ятайте, що це - незначна реалізація концепціїЦе демонструє ідеї, а не забезпечення виробництва.
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.