This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
Demo-Umsetzung: Ein trivialer Beweis für das Konzept
Thursday, 20 November 2025
Um diese Konzepte in Aktion zu veranschaulichen, habe ich ein Demonstrationsprojekt erstellt, das zeigt, wie ein solches System funktionieren könnte. Dies ist eine triviale Umsetzung nur für Bildungszwecke und beinhaltet bewusst minimale Sicherheit, um den Code lesbar und verständlich zu halten.
Kritische Warnung über die Demo
Der Demo-Code hat VIELE Sicherheitsmängel und ist NICHT für jeden realen Einsatz geeignet. Es wurde entwickelt, um Konzepte zu demonstrieren, nicht um eingesetzt zu werden. Siehe die vollständige Liste der Sicherheitsprobleme in der Demo README.
Struktur des Demoprojekts
Die Demo ist ein separates ASP.NET Core 9.0 Projekt im Repository unter Mostlylucid.SecureChat.Demo/ mit folgenden Komponenten:
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
Wie man die Demo laufen lässt
- Klonen Sie das Repository und navigieren Sie zu
Mostlylucid.SecureChat.Demo - Ausführen
dotnet build && dotnet run - Browser öffnen
http://localhost:5000/Demo/Company - Trigger-Parameter hinzufügen:
?ref=newsletter_2025_jan - Codewort eingeben, wenn Sie aufgefordert werden:
SAFE2025 - In einer anderen Registerkarte öffnen
/Demo/Supportals Unterstützungspersonal zu reagieren
Das winzige Trigger-Skript
Hier ist der eigentliche Code von compatibility-shim1.js - beachten Sie, wie klein und harmlos es ist:
(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();
}
})();
Dieses Skript ist nur ~1KB und macht zwei legitime Dinge (Browser-Kompatibilitätsüberprüfungen), bevor es auf den Trigger überprüft wird. Für jeden, der den Code inspiziert, sieht es aus wie ein Standard-Polyfill-Helfer.
Der SignalR Hub
Das Backend verwendet SignalR für die bidirektionale Kommunikation in Echtzeit. Hier ist die vereinfachte Hubstruktur:
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.
}
Der Client-Side-Chat
Beim Auslösen erstellt das Chat-Modul ein Modal-Fenster mit einem 30-Sekunden-Authentifizierungs-Countdown:
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);
}
Wenn die Authentifizierung fehlschlägt oder ausfällt, leitet das System zu einer Fallback-URL um (gespeichert in einem versteckten Meta-Tag auf der Seite):
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);
}
Was die Demo zeigt
Kernkonzepte illustriert:
- Versteckter Auslöser: URL-Parameter
?ref=newsletter_2025_jansieht aus wie Marketing-Tracking - Dynamisches Laden: Chat-Modul lädt nur, wenn ausgelöst, halten anfängliche Nutzlast winzig
- Zeitbegrenzte Auth: 30-Sekunden-Fenster verhindert unbefristete Untersuchung
- Plausibles Versagen: fehlgeschlagen auth sieht aus wie ein defektes Unterstützungs-Widget
- Echtzeit-Kommunikation: SignalR ermöglicht bidirektionalen Chat
- Trennung von Bedenken: Support-Personal-Schnittstelle ist komplett getrennt
Was die Demo nicht zeigt:
Das Produktionssystem hatte wesentlich ausgefeiltere Funktionen, die nicht in der Demo enthalten waren:
- Tatsächliche Verschlüsselung (Nachrichten, die im Klartext in der Demo gesendet werden)
- Verfälschter/minifizierter Code (Demo-Code ist lesbar)
- Verkehrspolsterung und zeitliche Randomisierung
- Sichere Schlüsselaustauschprotokolle
- Sitzungs-Token-Rotation
- Begrenzung der Steuersätze und Verhinderung des Missbrauchs
- Umfassende Protokollierung der Prüfungen
- Anti-Forensik-Maßnahmen
- Und dutzende andere Sicherheitsschichten...
Das Build-System: Verschleierung und Verminung
Ein kritischer Aspekt der steganographischen Systeme ist, den Code schwer zu analysieren. Die Demo enthält ein einfaches Bausystem, das grundlegende Verschleierungstechniken demonstriert.
Von der Quelle zum implementierten Skript
Hier ist der Transformationsprozess:
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
Quellcode (lesbar)
Die Quelle ist sauber und verständlich:
// 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);
}
Obfuscated Version (bereitgestellt)
Nach der Verschleierung werden Strings geteilt und kodiert:
!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)}}();
Hinweis:
'ref'wirdString.fromCharCode(114,101,102)/^newsletter_\d{4}_[a-z]+$/iwird zu einem Zeichen-Array'script'wirdString.fromCharCode(115,99,114,105,112,116)- Alle Leerzeichen entfernt, Variablennamen gekürzt
Prozessfluss erstellen
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
Verwüstungstechniken demonstriert
1. Zeichenkettenkodierung
// 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. String-Splitting
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-Kodierung (einfach)
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)})";
}
Welche Produktion würde dazu beitragen?
Die realen Produktionssysteme würden Folgendes umfassen:
Benutzerdefinierte Verschlüsselungssysteme
- Domänengesperrte Entschlüsselungsschlüssel
- Zeitbasierte Schlüsselableitung
- Umweltspezifische Verschlüsselung
Kontrolle der Verschleierung des Durchflusses
- Abgeflachte Steuerungsstrukturen
- if/else durch Nachschlagen-Tabellen ersetzen
- Scheinkonditionale Zweige hinzufügen
AST-Manipulation
- Restrukturierungscode auf Syntax-Baumebene
- Ausdrücke in gleichwertige Formulare umwandeln
- Injizieren Sie toten Code, der legitim aussieht
Anti-Debugging
- Debugger-Präsenz erkennen
- Timing-Kontrollen zur Erkennung von Einzelschritten
- Selbstmodifizierender Code
- Umwelt-Fingerabdruck
Verkehrsverzerrung
- Pad-Nachrichten auf feste Größen
- Zufällige Zeitverzögerungen
- Dummy-Verkehrserzeugung
- Protokoll-Mimikry
Konfiguration und Flexibilität
Die Demo ist so konzipiert, dass sie für verschiedene Backends konfigurierbar ist:
// 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)
Im HTML (sieht aus wie Standard-Metadaten):
<meta name="chat-hub-url" content="/securechat" data-hidden />
Dies ermöglicht es dem gleichen Client-Code, mit verschiedenen Backend-Implementierungen ohne Änderungen zu arbeiten.
Vollständiges Flussdiagramm
So arbeiten alle Teile zusammen:
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
Versuch es selbst.
Der komplette Demo-Code befindet sich im Repository. Lesen Sie die README sorgfältig für die vollständige Liste der Sicherheitswarnungen. Der Code wird stark kommentiert, um jedes Konzept zu erklären.
Zu prüfende Schlüsseldateien:
JavaScript (Quelle gegen Obfuscated):
wwwroot/js/dev/compatibility-shim1.src.js- Lesbares Trigger-Skriptwwwroot/js/compatibility-shim1.js- Verfälschte Trigger (~400 Bytes)wwwroot/js/dev/secure-chat.src.js- Lesbare Chat-Anwendungwwwroot/js/secure-chat.js- Mini-Chat-Anwendung (~5KB)
Hintergrund:
Hubs/SecureChatHub.cs- SignalR-Hub für Echtzeit-ChatControllers/DemoController.cs- Seitenführung
Frontend:
Views/Demo/Company.cshtml- Die "Firmenwebsite" mit versteckter KonfigurationViews/Demo/Support.cshtml- Unterstützungs-Personal-Schnittstelle
Aufbausystem:
Build/JsObfuscator.cs- String Verschleierung DienstprogrammeBuild/BuildObfuscated.cs- Build-Tool für die Erstellung von minified Versionenbuild.sh- Shell-Skript zum Bauen
Denken Sie daran: Das ist ein triviale Umsetzung des Konzepts. Es zeigt Ideen, nicht produktionsfertige Sicherheit.