BLOG
Bestätigter Supply-Chain-Angriff im „Anti-KI-Tool“ mit 729★: In main.py verbirgt sich eine C2-Adresse
Zuerst eine Abgrenzung der Sicherheitsgrenzen: Das in diesem Artikel zerlegte Repository korcarc/text-humanizer ist eine bösartige Probe. Kein Leser sollte es klonen, installieren oder ausführen. Leser, die es bereits installiert haben, sollten es so schnell wie möglich deinstallieren und auf Windows-Maschinen nach verdächtigen Netzwerkverbindungen suchen. Alle Schlussfolgerungen in diesem Artikel stammen aus dem statischen Lesen des Quellcodes und der mathematischen Dekodierung der verschlüsselten Payload; es wurde kein Code aus dem Repository ausgeführt.
Das am 16. September 2026 erstellte GitHub-Repository korcarc/text-humanizer erhielt bis zum 20. September 729 Stars und 83 Forks, ist in Python geschrieben und unter der MIT-Lizenz lizenziert. Das Verkaufsargument im README ist sehr direkt: Eine vierstufige Übersetzungs- und Umschreibepipeline – DeepSeek-Umschreibung, Google-Übersetzung Englisch-Türkisch, optionale DeepL-Übersetzung Türkisch-Japanisch, DeepSeek-Rückübersetzung in den Originaltext – mit dem Anspruch, „die meisten KI-Detektoren wie Turnitin/GPTZero zu umgehen“, und empfiehlt, die Temperatur auf 1,3 einzustellen. Mit anderen Worten: Es zielt auf die Zielgruppe ab, die „KI-Muster entfernen“ muss. Dieser Artikel zerlegt es in sechs Punkte: Was ist es, die Logik des Köders, wie der Mechanismus funktioniert, drei Stellen im Quellcode, die einen Blick wert sind, Grenzen und Schutz sowie ob es sich lohnt und die richtige Vorgehensweise.
1. Was ist das
text-humanizer ist nominell ein Text-Umschreibewerkzeug: Man gibt ihm einen KI-generierten Text, er lässt ihn durch eine vierstufige Übersetzungskette laufen, damit der Text „nicht wie von einer Maschine geschrieben“ klingt, und behauptet, gängige KI-Detektoren zu bestehen. Das README sieht aus wie ein seriöses Projekt, mit Verwendungsbeispielen, Parameterbeschreibungen und einer Liste der unterstützten Sprachen – allerdings stimmt die Sprachliste selbst nicht: Es werden 8 Sprachen behauptet, aber tatsächlich sind nur en/ja/zh/ko/de/fr/es aufgeführt, also 7.
Bei der statischen Lektüre des Repositories passen drei Dinge nicht mit dem README überein. Erstens: Die im README versprochene Kernfunktion läuft überhaupt nicht: In src/standard/llm_rewriter.py steht from .llm_client import chat_completions, aber die Datei llm_client.py existiert nicht, sodass die gesamte DeepSeek-Pipeline bereits in der Import-Phase abbricht. Zweitens: Die Datei src/conversion/translation_chain.py, die angeblich das Übersetzungsmodul ist, umfasst 1403 Zeilen, enthält aber eine vollständige Bitcoin-Schlüsselbibliothek – ECDSA, secp256k1, Taproot, WIF-Signaturen –, hat mit Übersetzung nichts zu tun, wird von keiner Datei im Repository importiert und hat auch keine in requirements.txt gelisteten Abhängigkeiten; es ist sorgfältig platzierter toter Code. Drittens: Der einzige lebendige Code in main.py ist Zeile 12 humanizer.run_sync() – vom Import bis zur netzwerkgestützten Ausführung ist es nur ein Schritt, und humanizer.py trägt seinen Namen zu Unrecht: Es ist eine zweifach verschlüsselte Payload. Drei Unstimmigkeiten: Versprechen passt nicht zur Datei, Dateiname passt nicht zum Inhalt, Projektname passt nicht zum Verhalten.
2. Die Köderlogik: Warum gerade dieses?
Um diese Probe zu verstehen, muss man ihre Zielgruppe verstehen. Das Umgehen von KI-Detektoren bewegt sich in einer grauen Zone der akademischen Integrität – auf der einen Seite Studenten, die Hausarbeiten abgeben wollen, auf der anderen Seite Marketing-Accounts, die Beiträge massenhaft veröffentlichen wollen. Beide haben einen starken Bedarf, „Texte durch den Detektor zu bekommen“, können aber nicht laut darüber werden. Dieser Bedarf drängt die Menschen natürlich in die grauen Ecken von Suchmaschinen und GitHub: Normale Kanäle verkaufen solche Tools nicht, also werden zweifelhafte Repositories zur einzigen Anlaufstelle.
Die Angreifer haben ihre Ware sehr genau ausgewählt. Diese Zielgruppe hat drei Merkmale, von denen jedes das Risiko der Entdeckung der Probe verringert: Sie können keinen Quellcode lesen – „Installieren und Fertig“ ist die Erwartung. Sie trauen sich nicht, laut zu werden – wenn sie Opfer werden, geben sie die Schuld sich selbst. Ihnen fehlt die Erfahrung zur Fehlersuche – selbst mehrere fremde Prozesse auf dem Computer bemerken sie nicht. Selbst wenn unter den 729 Stars nur ein Zehntel echte Benutzer sind, die main.py ausgeführt haben, ist die Effizienz der Verbreitung bereits beträchtlich.
Kurz erwähnt: Auch auf Kontoebene stimmen die Dinge nicht. Der Autor korcarc registrierte sich im April 2020, hat in über vier Jahren nur dieses eine öffentliche Repository und nur 6 Follower. Ein vier Jahre ruhendes Konto, das innerhalb von drei Tagen 729 Stars erhält – diese Kombination beweist für sich genommen nichts, aber in Kombination mit den drei Unstimmigkeiten im Code ist die Richtung klar: Die Zusammensetzung der Aufmerksamkeit für dieses Repository passt nicht zur Kontohistorie. Leser, die die Anzahl der Stars als Qualitätssiegel nehmen, werden Nachteile erleiden.
3. Der Mechanismus: Die Kette vom Import zum C2
3.1 Der erste Schritt: Import führt zur Ausführung
Der effektive Code in main.py umfasst nur eine Zeile. Zeile 12 humanizer.run_sync() befindet sich auf der obersten Ebene des Moduls, was bedeutet, dass jeder, der python main.py ausführt oder dieses Paket importiert, diese Zeile sofort auslöst – ohne Schalter, ohne Bestätigung, ohne Probelauf. Für normale Nutzungsszenarien ist dies ein kontraintuitives Design – seriöse Bibliotheken warten, bis man sie aufruft. Für Angreifer ist dies der kürzeste Weg.
3.2 Der zweite Schritt: Die zweifach verschlüsselte humanizer.py
src/services/humanizer.py ist die technisch interessanteste Datei in diesem Repository: Sie hat nur 42 Zeilen, aber eine Größe von 28,6 KB. Im Schnitt fast 700 Bytes pro Zeile, dies ist komprimierter Geheimtext. Wenn man sie aufbricht, ist es ein Trio, das wir Ebene für Ebene durchgehen.
Die erste Ebene: String-XOR-Obfuskierung. Alle lesbaren Bezeichner, Konstanten und URLs sind mit einem festen Schlüssel XOR-verknüpft. Ein statischer Blick oder grep findet keine Schlüsselwörter – kein http, kein socket, nichts, das nach Malware riecht.
Die zweite Ebene: HMAC-SHA256-Counter-Stream. Dies ist eine Standard-Konstruktion für Stromverschlüsselung: Der Schlüssel und ein inkrementierender Zähler werden in HMAC-SHA256 gespeist, um einen Schlüsselstrom zu erzeugen, der so lang ist wie der Geheimtext, und dann per XOR der Klartext wiederhergestellt. Sie ist eine Größenordnung höher als das feste XOR der ersten Ebene – derselbe Klartext liefert bei jeder Verschlüsselung ein anderes Ergebnis, direkter Byte-Vergleich findet keine Muster.
Die dritte Ebene: zlib-Komprimierung. Nach der Stromentschlüsselung muss es noch eine Standard-zlib-Dekomprimierung durchlaufen, um den endgültigen Python-Quellcode zu erhalten, der dann von builtins.exec in die globals des aktuellen Moduls injiziert und ausgeführt wird, wobei run_sync definiert wird. Die Datei enthält auch eine Anti-Manipulationsprüfung: Eine Reihe von Konstanten sind an den Entschlüsselungsparametern beteiligt; wenn der Geheimtext auch nur um ein Byte geändert wird, ist das Entschlüsselungsergebnis nicht wiederzuerkennen und run_sync wird niemals entstehen. Mit anderen Worten: Diese Payload ist immun gegen jeden Art von Reparaturversuch – Wenn Sie versuchen, einen Patch einzufügen, um zu sehen, was sie tut, tut es mir leid, ändern Sie ein Byte und sie wird nicht entschlüsselt.
Diese Kombination ist nicht einfach so hingeworfen. XOR blockiert Schlüsselwort-Scans, HMAC-Streams blockieren Byte-Analysen, zlib blockiert die Strukturerkennung, Anti-Manipulation blockiert Reparaturversuche durch Sicherheitsforscher. Für die überwältigende Mehrheit der Benutzer, die „ein Paket mal ausprobieren“, sind die ersten drei Ebenen bereits ausreichend.
3.3 Der dritte Schritt: Was die entschlüsselte Payload tut
Das Verhalten der durch statische Dekodierung (reine mathematische Operationen, keine Codeausführung) wiederhergestellten Payload ist wie folgt. Sie initiiert eine Klartext-HTTP-Anfrage an die C2-Adresse 172.239.96.53:8765, mit einem fest codierten Bearer-Token 094750aeef51f8e9d0c126b879c9df07 im Authentifizierungs-Header. Sie lädt das Modul der zweiten Stufe von /api/v1/client/manual_mapper.py herunter, schreibt es in den Pseudo-Pfad <ram:> – es wird nur im Speicher ausgeführt, ohne auf die Festplatte zu schreiben. Anschließend ruft es mit dem PAYLOAD_KEY 7c2101e76c97188da4c56d9c2f31712c manual_mapper.map_from_server(...) auf, um die endgültige Payload zu ziehen.
Drei Designdetails verdienen eine gesonderte Erwähnung. Erstens: Durchgehend Klartext-HTTP: Token und Schlüssel liegen offen im Verkehr, was bedeutet, dass die Betreiber entweder keine Angst vor Reverse Engineering haben (der Code ist ja ohnehin verschlüsselt) oder es sich einfach machen wollen – das wirkt nicht nach der Art eines Meisters, sondern eher wie „Masse statt Klasse“. Zweitens: Nur unter Windows wirksam: In einer Nicht-Win32-Umgebung wird direkt „win32 only“ geworfen, die Payload weiß, auf welchem System sie ist. Drittens: QUIET=True standardmäßig stillschweigend: Alle Exceptions werden verschluckt, ohne Informationen an den Benutzer auszugeben.
Diese drei Dinge zusammen bilden das Evasionstrio. Die Ausführung im Speicher bedeutet, dass Antivirenprogramme beim Scannen der Festplatte nichts finden – auf dem Dateisystem gibt es von Anfang an keine bösartige Datei, nur eine verschlüsselte Python-Quelle. Windows-only beschränkt das wahre Ich auf das größte, am wenigsten geschützte und am wenigsten wahrscheinliche Desktop-System, das von Sicherheitsforschern täglich genutzt wird. Stilles Fehlerbehandeln als Rückfallebene: Selbst bei Fehlern bleibt keine Spur. Mac- und Linux-Benutzer sehen beim Ausführen nur eine ruhige Fehlermeldung oder gar keine Ausgabe; die meisten werden nicht misstrauisch und schon gar nicht nachforschen. Die wirklich betroffenen Windows-Benutzer verwenden ein zweifelhaftes „Detektor-Umgehungs-Tool“, diese Identität schreckt sie natürlich davon ab, Hilfe bei legitimer Sicherheitssoftware zu suchen.
Der Inhalt der endgültigen Payload ist unbekannt – sie wird vom C2-Server zur Laufzeit entschieden, was auch immer heruntergeladen wird. Eine vernünftige Schlussfolgerung lässt sich nur ziehen: Ein Verbreitungskanal, maßgeschneidert für die Gruppe, die Detektoren umgehen will, lädt wahrscheinlich eine Spionage-Payload, aber das gehört in den Bereich der Spekulation und zählt im Text nicht als Fakten.
4. Drei Stellen im Quellcode, die einen Blick wert sind
4.1 humanizer.py: Ein technisches Musterbeispiel für ein Trio
42 Zeilen, 28,6 KB, dreifache Verschlüsselung plus Anti-Manipulation plus exec-Injektion – diese Datei ist an sich ein Lehrbuch der Obfuskation, das es wert ist, gesammelt zu werden. Ihr pädagogischer Wert liegt nicht in der Bösartigkeit, sondern darin, dass sie die Standardtaktik demonstriert, mit der sich die statische Analyse auseinandersetzen muss: Schlüsselwort-Scans werden von XOR blockiert, Byte-Vergleiche von HMAC-Streams, Strukturerkennung von zlib und Reparaturversuche von Anti-Manipulation. Jede Ebene für sich genommen ist öffentliche Technologie, zusammen ergibt sie eine Hülle, die für automatisierte Erkennung ziemlich unfreundlich ist. Wenn Sie das nächste Mal eine Python-Datei sehen mit „nur ein paar Dutzend Zeilen aber ein paar MB“ und „grep findet keine Strings“, das ist die erste Reaktion, die Sie haben sollten.
4.2 translation_chain.py: Eine 1403 Zeilen lange Bitcoin-Schlüsselbibliothek
Die angebliche Übersetzungskettendatei ist tatsächlich eine vendored Bitcoin-Schlüsselbibliothek: ECDSA, secp256k1, Taproot, WIF-Signaturen, alles vorhanden. Sie hat mit Übersetzung nichts zu tun, wird im gesamten Repository nirgendwo importiert, und requirements.txt listet auch keine Abhängigkeiten für sie – ecdsa, base58check, sympy, bitcoinutils fehlen alle. Ihre Rolle hier gibt es wahrscheinlich zwei Erklärungen: Erstens, um das Repositoryvolumen und die Zeilenanzahl aufzufüllen, damit das Projekt wie etwas aussieht. Zweitens, falls gefragt, kann man „Blockchain-bezogene Planungen“ behaupten. Wie auch immer, es ist ein Marker, der testet, ob der Benutzer wirklich den Quellcode liest: Wer bemerkt, dass mit dieser Datei etwas nicht stimmt, wird main.py wahrscheinlich nicht weiter ausführen.
4.3 llm_rewriter.py: Eine absichtlich unterbrochene Kette
Der Einstieg in die im README versprochene DeepSeek-Pipeline befindet sich hier: from .llm_client import chat_completions – aber llm_client.py existiert nicht. Das ist keine Nachlässigkeit, denn nirgendwo im gesamten Repository wurde chat_completions definiert. Mit anderen Worten: Die im README am attraktivsten beworbene Funktion „vierstufige Übersetzung und Umschreibung“ wurde nie implementiert; jeder Benutzer, der dem README folgt, erhält bereits in der Import-Phase einen ImportError. Die Angreifer kümmern das nicht: Sie brauchen die Leute nur dazu zu bringen, python main.py auszuführen, die restliche Funktion ist ohnehin nur Kulisse. Dass die Funktion nicht läuft, beweist gerade, dass die Kulisse nicht echt sein muss – solange das README gut aussieht.
5. Grenzen und Schutz
Drei Zweifel, nur Zweifel, keine Festlegungen. Der Inhalt der endgültigen Payload ist unbekannt, wird zur Laufzeit vom C2 heruntergeladen, es kann alles sein. Die Identität der Betreiber ist unbekannt, die Kontoinformationen sind fast leer, keine Zuordnung möglich. Die Zusammensetzung der Stars ist zweifelhaft – 729 Stars in drei Tagen passen offensichtlich nicht zur Kontohistorie, der Anteil echter Benutzer ist nicht zu überprüfen.
Zum Schutz gebe ich den Lesern drei machbare Dinge an die Hand. Erstens: Bevor Sie ein Paket installieren, nehmen Sie sich zwei Minuten Zeit, öffnen Sie die main.py oder die Einstiegsdatei: Gibt es auf der obersten Ebene einen Aufruf, der sofort beim Import ausgeführt wird? Stimmen Dateiname und Inhalt überein (bei einer Datei namens translation_chain, grep mal, ob translate drin vorkommt)? Passt die im README versprochene Funktion zur Anzahl der Dateien? Diese drei Fragen kann man stellen, ohne Code zu verstehen. Zweitens: Abhängigkeiten sollten Versionen fixieren (pinning) und auditiert werden: In der requirements.txt dieses Repositories ist plötzlich tornado==6.4.2 festgenagelt, die Abhängigkeitsliste allein sollte einen Verdacht auslösen – „Warum ausgerechnet das?“ – normale Projekte haben keinen Grund, eine genaue Version eines Frameworks festzunageln, das gar nicht genutzt wird. Drittens: Installieren Sie keine fragwürdigen „Detektor-Umgehungs“-Tools via pip: Ein Tool, das Sie aktiv dazu anleitet, Regeln zu brechen, können Sie nicht dazu zwingen, sich an Regeln zu halten. In der grauen Zone gibt es keinen Kundendienst, das gilt für Käufer und Opfer gleichermaßen.
Auf der Ebene der GitHub-Plattform sind die Erkennungsmerkmale für solche Proben bereits sehr musterhaft: Seit Jahren ruhige alte Konten, plötzliche Erstellung, README ist länger als der Code, das Wachstum der Stars passt nicht zu den Kontoassets, der Codekörper ist Geheimtext oder toter Code. Allein betrachtet kann jeder Punkt Zufall sein, aber wenn drei oder mehr gleichzeitig auftreten, schließen Sie die Seite einfach.
6. Ist es es wert und die richtige Haltung
Bei diesem Tool gibt es kaum etwas zu diskutieren, ob es sich lohnt; es ist eine Probe, die es wert ist, in ein Erkennungshandbuch aufgenommen zu werden. Es demonstriert die Standardbewegungen eines Supply-Chain-Angriffs, von der Köderauswahl über die Obfuskierungstechnik bis zur Tarnung auf der Plattformseite, jeder Schritt hat Lehrbuchcharakter. Für Sicherheitsforscher ist die dreifache Verschlüsselung plus Anti-Manipulation ein Obfuskierungsparadigma, das es wert ist, notiert zu werden; für normale Leser bestätigt es eine naive Erfahrung: Die Anzahl der Stars ist kein Sicherheits-Siegel, das README ist kein Funktionsbeweis, zwischen „es läuft“ und „es läuft sicher“ liegt eine ganze Quellcodelektüre.
Die richtige Haltung zur „Entfernung von KI-Mustern“ liegt nicht in grauen Tools. Die tägliche Praxis dieses Kontos war immer Whitelist-Umschreibung plus manuelles Umschreiben: Erst klar darüber werden, was dieser Text sagen soll, dann ihn in eigenen Worten neu schreiben, zuletzt die KI-generierten Dinge als Entwurf und nicht als Endprodukt behandeln. Dieser Weg umgeht keinen Detektor, denn das Ziel ist ohnehin, dass der Text wirklich vom Menschen stammt. Detektoren wie GPTZero und Turnitin bewegen sich selbst in einer grauen Zone – sie verletzen echtes menschliches Schreiben und halten dennoch niemanden ab, der sie umgehen will. Wenn man darauf setzt, sie zu täuschen, gewinnt man am Ende nur einen Text, der einem nicht gehört, und einen möglicherweise infizierten Prozess.
Fazit
text-humanizer beantwortet die Frage „Wie umgehe ich KI-Detektoren“ mit einem ordentlich geschriebenen README und die Frage „Wie umgehst du deine Verteidigung“ mit dem Quellcode. In Zeile 12 von main.py wird beim Import sofort ausgeführt, humanizer.py verpackt eine Anti-Manipulations-Payload mit dreifacher Verschlüsselung aus XOR plus HMAC-SHA256-Stream plus zlib, nach der Entschlüsselung initiiert sie Klartext-HTTP an 172.239.96.53:8765, lädt mit einem fest codierten Bearer-Token das Modul der zweiten Stufe herunter, führt es nur im Speicher aus, wirkt nur unter Windows und schluckt standardmäßig still alle Exceptions; die 1403 Zeilen lange Bitcoin-Schlüsselbibliothek und der Import einer nicht existierenden llm_rewriter.py sorgen dafür, dass das Repository wie ein Projekt aussieht. 729 Stars in drei Tagen passen nicht zum Konto mit einem Repository in vier Jahren und sechs Followern, das Funktionsversprechen passt nicht zum Code, der nicht läuft, der Übersetzungsdateiname passt nicht zur Bitcoin-Schlüsselbibliothek. Drei Unstimmigkeiten, das ist seine gesamte Selbstvorstellung. Zum Schluss noch einmal die Abgrenzung der Sicherheitsgrenzen: Klonen Sie dieses Repository nicht, installieren Sie es nicht, führen Sie es nicht aus.
Referenzen
- korcarc/text-humanizer README (Vierstufige Pipeline, Behauptung der Detektorumgehung, Sprachliste, Temperatur-Empfehlung)
- Statische Lesung des Quellcodes (nicht ausgeführt): main.py (Zeile 12 humanizer.run_sync()), src/services/humanizer.py (42 Zeilen, 28,6 KB, XOR-Obfuskierung, HMAC-SHA256-Counter-Stream, zlib, exec-Injektion, Anti-Manipulationsprüfung), src/conversion/translation_chain.py (1403 Zeilen Bitcoin-Schlüsselbibliothek, kein Import), src/standard/llm_rewriter.py (Import nicht existierender llm_client.py), requirements.txt (tornado==6.4.2)
- Statische Dekodierung der Payload (reine mathematische Operationen, nicht ausgeführt): C2 172.239.96.53:8765, Bearer 094750aeef51f8e9d0c126b879c9df07, manual_mapper.py Speicherausführung, win32 only, QUIET=True, PAYLOAD_KEY 7c2101e76c97188da4c56d9c2f31712c
- Repository-Daten: 729★, 83 Forks, erstellt am 2026-09-16, Autorenkonto registriert im 2020-04, 1 öffentliches Repository, 6 Follower (Stand 2026-09-20).