Fallstudie * DownUnderCTF 2023

Finde die Flagge in
eine CTF-Binärdatei.

Verwenden Sie REA, um einen kleinen Flaggenprüfer zu überprüfen, seine Regeln in Gleichungen umzuwandeln und eine Eingabe zu finden, die das ursprüngliche Programm drucken lässt Correct!.

maskierte Quadrate Flaggenprüfer · Einfach · Linux x86-64

Sehen Sie sich die ursprüngliche Herausforderung an

Von einer binären zu einer geprüften Antwort

  1. 01 * Finden Sie den ScheckZeichenketten → Funktionen prüfen REA findet die Eingabeaufforderung, ihre Referenzen und den Code, der eine Eingabe akzeptiert oder ablehnt.
  2. 02 * Extrahieren Sie die Regeln36 zeichen · 26 summen REA gibt die Anweisungen und Daten hinter jeder Prüfung zurück. Der Agent wandelt sie in Gleichungen um.
  3. 03 * Lösen und ausführenWiederhergestellte Flagge → Korrekt!Ein Python-Skript löst die Gleichungen. REA erfasst das ursprüngliche Programm, das das Ergebnis akzeptiert.
Die Herausforderung stammt von Joseph und wurde im offiziellen Repository von DownUnderCTF veröffentlicht.

Finden Sie den Prüfcode

Das Handout ist eine 15 KB große ausführbare Datei. Es fragt nach einer Flagge und druckt dann Correct! oder Incorrect!. Beginnen Sie mit einer einfachen Anfrage an Ihren Agenten.

Ihr Codierungsagent

Verwenden Sie REA, um ms_flag_checker zu analysieren und das Flag zu finden. Erklären Sie, wie die Prüfungen funktionieren, und überprüfen Sie dann die Antwort mit dem Originalprogramm.

Eine Beispiel-Eingabeaufforderung, bei der die heruntergeladene Herausforderung lokal verfügbar ist und eine Analyse des Maschinencode-Programmanbieters verbunden ist.

  1. Folgen Sie der Eingabeaufforderung zu ihrer Funktion

    Vertreter → REA
    open_binary
    {"path": "ms_flag_checker"}
    
    search_strings
    {"pattern": "flag|correct|wrong|input",
     "mode": "regex", "case_sensitive": false}
    
    xrefs
    {"address": "0x102004"}
    
    resolve_containing_procedure
    {"address": "0x10126d"}
    REA → Agent * ausgewählte Ergebnisse
    0x102004  "What is the flag? "
    0x10201c  "Incorrect!"
    0x102027  "Correct!"
    
    Prompt referenced at: 0x10126d
    Containing function: 0x10124d

    Die Referenz gibt dem Agenten einen Ort zum Untersuchen, obwohl die ursprünglichen Funktionsnamen der ausführbaren Datei entfernt wurden.

  2. Lesen Sie den Checker und seine beiden Helfer

    Vertreter → REA
    analyze_function
    {"procedure": "0x10124d"}
    
    analyze_function
    {"procedure": "0x101189"}
    
    analyze_function
    {"procedure": "0x101217"}
    REA → Agent * ausgewählte Anweisungen
    0x1012c1: CMP EDI, 0x24
    0x1012c6: LEA RBX, [0x1040e0]
    0x1012cd: LEA RBP, [0x104060]
    0x1012d4: LEA R13, [RBX + 0x270]
    0x1012e1: CALL 0x00101189
    0x1012ec: CALL 0x00101217
    0x1012f1: CMP dword ptr [RBP], EAX
    0x1012f4: JNZ 0x00101335
    0x1012f6: ADD RBX, 0x18

    Die erste Schleife kopiert 36 Zeichencodes. Die Prüfschleife dekodiert eine Maske, summiert die ausgewählten Codes und vergleicht das Ergebnis mit einer gespeicherten Nummer. Seiner 0x18-byte-Schritte über 0x270 bytes ergeben 26 Masken.

Dies sind ausgewählte Ergebnisse einer neuen REA-Analyse. Der lokale Zielpfad wird für die Anzeige gekürzt; Adressen beziehen sich auf das importierte Bild von REA.

Ein Häkchen zeigt einen Charakter

Der Checker ordnet die Eingabe in einem 6 × 6-Raster an. Eine Maske wählt aus, welche Zellen zu einer Summe beitragen. Seine kompakte Codierung verwendet negative Zahlen, um Zellen zu überspringen, und positive Zahlen, um sie auszuwählen.

Die siebte Maske überspringt 21 Zellen, wählt Position 21 aus und überspringt dann 14. Nur diese Zelle trägt zur Summe bei. Der erforderliche Zeichencode ist 55, was bedeutet, dass das Zeichen 7 ist.
Die siebte Prüfung wählt nur eine Position aus. Offene Figur.

Lesen Sie die Maske und ihr Ziel aus der Binärdatei

Agent → REA · Byte lesen
{"address": "0x1040e0", "length": 624}
{"address": "0x104060", "length": 144}
REA → Agent * siebte Einträge
Mask at 0x104170:
eb 01 f2 00  →  -21, +1, -14, stop

Target at 0x104078:
37 00 00 00  →  55

Anweisung MOVSX liest Maskenbytes als vorzeichenbehaftete Werte. Das ist der Grund eb bedeutet -21. Das Ziel ist eine Little-Endian-Ganzzahl. Zusammen sagen diese Bytes dem Agenten, dass code[21] = 55, also ist dieser Charakter 7.

Von der Anleitung zum lesbaren Scheck

Wählen Sie einen Schritt aus, um den Summierungshelfer und seinen Aufrufer mit derselben Regel in C zu verbinden.

REA * ausgewählte Originalanleitung
0x10121c: MOV ECX, 0x0

0x10122c: CMP dword ptr [RSI + RAX*0x1], 0x0
0x101230: JZ 0x00101223

0x101232: ADD ECX, dword ptr [RDI + RAX*0x1]

0x101223: ADD RAX, 0x4

0x1012f1: CMP dword ptr [RBP], EAX
0x1012f4: JNZ 0x00101335
Lesbare C · One-Check-Zusammenfassung
int check_one_mask(const int codes[36],
                   const int mask[36],
                   int target) {
    int total = 0;
    for (int i = 0; i < 36; ++i) {
        if (mask[i]) {
            total += codes[i];
        }
    }
    return total == target;
}

01 * Bei Null beginnen. ECX enthält die laufende Summe.

Die Anweisungen stammen vom Summierhelfer und seinem Aufrufer. Das C ist eine erklärende Zusammenfassung mit beschreibenden Namen und einer abgeflachten 36-Zellen-Schleife.

Löse die 26 Gleichungen

Die meisten Masken markieren mehrere Zellen. Zum Beispiel fügt die erste Prüfung 16 Zeichencodes hinzu und erfordert insgesamt 1441. Die überlappenden Auswahlen ergeben Gleichungen, die ein kleines Python-Skript zusammen lösen kann.

Python * Löser Auszug
from z3 import Int, Or, Solver, Sum, sat

codes = [Int(f"code_{i}") for i in range(36)]
solver = Solver()
alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_{}"
for code in codes:
    solver.add(Or(*[code == ord(c) for c in alphabet]))
for code, char in zip(codes, "DUCTF{"):
    solver.add(code == ord(char))
solver.add(codes[-1] == ord("}"))

for selected, target in checks:
    solver.add(Sum([codes[i] for i in selected]) == target)

assert solver.check() == sat
model = solver.model()
print("".join(chr(model.eval(code).as_long()) for code in codes))

Z3 ist ein Löser, der Werte findet, die diese Gleichungen erfüllen. Dieser Auszug verwendet die extrahierten Prüfungen und geht von einer DUCTF{…} flagge mit Buchstaben, Ziffern, Unterstrichen und geschweiften Klammern. Der vollständige Download enthält alle 26 Masken und Ziele.

Laden Sie den vollständigen Solver herunter

Überprüfen Sie die Antwort mit dem Originalprogramm

Die Prozesserfassung von REA zeichnet die ursprüngliche ausführbare Datei auf, die das gelöste Flag akzeptiert. Ändern eines ausgewählten Zeichens aus z zu y macht die erste Summe 1440 anstelle von 1441, und das Programm lehnt sie ab.

Eingang Beobachteter Output Ausstiegscode
Flagge des Lösers Correct! 0
Ein Charakter wurde geändert Incorrect! 255
Zeigen Sie das wiederhergestellte Flag und die erfasste Ausgabe an
REA * ursprüngliche Programmausgabe
What is the flag? DUCTF{ezzzpzzz_07bcda7bfe81faf43caa}
Correct!

Der wiederhergestellte Wert stimmt auch mit dem Flag in den veröffentlichten Challenge-Metadaten der Organisatoren überein, das nach dem Lösen der Binärdatei überprüft wurde.

Quelle, Zielidentität und Analysedetails

Neue Analyse und zwei Prozesserfassungen am 8. Oktober 2026 mit REA 4.1.0 mit Ghidra 12.1.4 auf Linux x64. Die Binärdatei ist eine gestrippte x86-64 ELF, 15.248 Byte.

Ursprüngliche ausführbare Datei * SHA-256
dcd3bec4f608e11f3a12ce461100aaf5f621851ee63a1f870d7c90d4e3dd51ae

Die Zeichenfolgenreferenzen, Funktionen und Konstanten wurden überprüft, bevor die Quelle oder Lösung des Veranstalters gelesen wurde. Der Python-Solver und das Diagramm wurden aus diesen REA-Ergebnissen erstellt.

Vergleiche mit der Quelle des Veranstalters · Metadaten und Flag abfragen · REA Hinweise zum Nachweis

Probieren Sie es selbst aus

Laden Sie die ursprüngliche Herausforderung und den Löser in einen Ordner herunter. Verwenden Sie die obige Eingabeaufforderung, um mit Ihrem Agenten Nachforschungen anzustellen, oder führen Sie das mitgelieferte Skript aus.

Terminal * lösen und ausführen
python3 -m venv .venv
.venv/bin/python -m pip install z3-solver
.venv/bin/python solve.py

chmod +x ms_flag_checker
./ms_flag_checker

Das Skript druckt ein Kandidatenflag; Fügen Sie es an der Eingabeaufforderung des Programms ein. Lösungsbedürfnisse Python und z3-solver. Zum Ausführen der ursprünglichen ausführbaren Datei ist Linux x86-64 erforderlich.

Richten Sie REA mit Ihrem Codierungsagenten ein

Oberen