RawrXD PE Writer - Vollständige Implementierung
Übersicht
Dies ist ein vollständiger PE32+-Writer und Maschinencode-Emittent, implementiert in reiner x64-MASM-Assembly ohne Abhängigkeiten und ohne CRT-Nutzung. Er erzeugt lauffähige Windows-Executables von Grund auf.
Architektur
Der PE-Writer folgt einem Backend-Designer-Ansatz und stellt eine saubere API bereit für:
- Erstellung von PE-Executable-Kontexten
- Hinzufügen von Importen mit korrekten IAT/INT-Strukturen
- Emittieren von Maschinencode mit Abschnittsverwaltung
- Schreiben vollständiger PE-Dateien mit allen erforderlichen Headern
Kernkomponenten
1. Definierte Strukturen
- IMAGE_DOS_HEADER: Standard-DOS-Header mit e_lfanew-Zeiger
- IMAGE_NT_HEADERS64: NT-Header mit Datei-Header und optionalem Header
- IMAGE_SECTION_HEADER: Abschnitts-Header für .text, .rdata, .idata
- IMAGE_IMPORT_DESCRIPTOR: Importtabellen-Deskriptoren
- PE_CONTEXT: Interne Kontextstruktur zum Erstellen von PE-Dateien
2. Schlüsselfunktionen
PEWriter_CreateExecutable
- Eingabe: RCX = Image-Basis (0 = Standard), RDX = Entry-Point-RVA
- Ausgabe: RAX = PE-Kontext-Handle (0 = Fehler)
- Zweck: Allokiert und initialisiert die vollständige PE-Kontextstruktur
Implementierungsdetails:
- Allokiert Speicher für DOS-Header, NT-Header, Abschnitts-Header
- Initialisiert DOS-Header mit korrekter Signatur und e_lfanew
- Richtet NT-Header mit AMD64-Maschinentyp und PE32+-Magic ein
- Konfiguriert optionalen Header mit Image-Basis, Abschnitts-/Datei-Ausrichtung
- Allokiert Code-Puffer und Importtabellen
- Setzt Standard-Virtualadressen und Datei-Offsets
PEWriter_AddImport
- Eingabe: RCX = PE-Kontext, RDX = DLL-Name, R8 = Funktionsname
- Ausgabe: RAX = 1 Erfolg, 0 Fehler
- Zweck: Erstellt Importtabelle mit korrekten IAT/INT-Strukturen
Implementierungsdetails:
- Verwaltet Import-Deskriptoren für mehrere DLLs
- Erstellt Einträge der Import Lookup Table (INT)
- Richtet Einträge der Import Address Table (IAT) ein
- Behandelt Import-by-Name-Strukturen
- Verfolgt Importanzahl und validiert Grenzen
PEWriter_AddCode
- Eingabe: RCX = PE-Kontext, RDX = Code-Puffer, R8 = Code-Größe
- Ausgabe: RAX = RVA des Codes (0 = Fehler)
- Zweck: Handhabt Emittierung von Maschinencode mit korrekter Abschnittsverwaltung
Implementierungsdetails:
- Kopiert Maschinencode in internen Puffer
- Validiert Code-Größe gegen maximale Grenzen
- Berechnet und gibt RVA für den Code zurück
- Aktualisiert interne Code-Größenverfolgung
- Verwaltet .text-Abschnittsinhalt
PEWriter_WriteFile
- Eingabe: RCX = PE-Kontext, RDX = Dateiname
- Ausgabe: RAX = 1 Erfolg, 0 Fehler
- Zweck: Vollständiges Dateischreiben mit allen Headern, Abschnitten und Importtabelle
Implementierungsdetails:
- Erstellt Ausgabedatei mit korrekten Win32-API-Aufrufen
- Schreibt DOS-Header und DOS-Stub
- Berechnet und aktualisiert finale NT-Header-Werte
- Schreibt Abschnitts-Header für .text, .rdata, .idata
- Implementiert korrektes Datei-Padding und Ausrichtung
- Schreibt Abschnittsdaten mit Importtabelle
- Behandelt alle RVA-Berechnungen und Datei-Offsets
Speicherverwaltung
Die Implementierung verwendet Windows-Heap-APIs:
- GetProcessHeap(): Holt aktuellen Prozess-Heap
- HeapAlloc(): Allokiert nullinitialisierten Speicher
- HeapFree(): Gibt allokierten Speicher bei Bereinigung frei
Jede Speicherallokation beinhaltet korrekte Fehlerbehandlung und Bereinigung.
Dateistruktur-Layout
DOS Header (64 Bytes)
DOS Stub (variable Größe, aufgefüllt auf 0x80)
NT-Header (248 Bytes für PE32+)
Abschnitts-Header (40 Bytes × 3 Abschnitte)
Padding zur Dateiausrichtung (0x400)
.text-Abschnitt (Code)
- Maschinencode
- Auf Dateiausrichtung aufgefüllt
.rdata-Abschnitt (nur lesbare Daten)
- String-Konstanten, Ressourcen
- Auf Dateiausrichtung aufgefüllt
.idata-Abschnitt (Importdaten)
- Import-Deskriptoren
- Import Lookup Table
- Import Address Table
- Import-by-Name-Strukturen
- Auf Dateiausrichtung aufgefüllt
Virtualadress-Layout
0x1000: .text-Abschnitt (SECTION_ALIGNMENT)
0x2000: .rdata-Abschnitt
0x3000: .idata-Abschnitt
0x4000: Nächste verfügbare Virtualadresse
Konstanten und Standardwerte
- Image-Basis: 0x140000000 (Standard für x64)
- Abschnittsausrichtung: 0x1000 (4KB)
- Dateiausrichtung: 0x200 (512 Bytes)
- Entry Point: Konfigurierbare RVA
- Subsystem: Konsolenanwendung (IMAGE_SUBSYSTEM_WINDOWS_CUI)
Anwendungsbeispiel
; PE-Kontext erstellen
mov rcx, 0 ; Standard-Image-Basis
mov rdx, 1000h ; Entry-Point-RVA
call PEWriter_CreateExecutable
mov rbx, rax ; Kontext speichern
; kernel32.dll-Importe hinzufügen
mov rcx, rbx
mov rdx, offset dll_kernel32
mov r8, offset func_GetStdHandle
call PEWriter_AddImport
; Maschinencode hinzufügen
mov rcx, rbx
mov rdx, offset code_buffer
mov r8, code_size
call PEWriter_AddCode
; Executable-Datei schreiben
mov rcx, rbx
mov rdx, offset filename
call PEWriter_WriteFile
Build-Anleitung
- Stellen Sie sicher, dass MASM64 und Windows SDK installiert sind
- Führen Sie
build.bat aus, um den PE-Writer und das Beispiel zu kompilieren
- Führen Sie
PE_Writer_Example.exe aus, um hello.exe zu generieren
- Testen Sie das generierte Executable
Fehlerbehandlung
Alle Funktionen geben bei Fehlern 0 und bei Erfolg einen Wert ungleich 0 zurück. Die Implementierung umfasst:
- Prüfung auf fehlgeschlagene Speicherallokation
- Datei-I/O-Fehlerbehandlung
- Eingabevalidierung
- Korrekte Ressourcenbereinigung
- Grenzprüfung für Puffer
Einschränkungen
- Maximal 99 Importe (MAX_IMPORTS - 1)
- Maximale Codegröße 64KB (MAX_CODE_SIZE)
- Drei feste Abschnitte (.text, .rdata, .idata)
- Nur Konsolen-Subsystem
- Keine Unterstützung für Relokationen
- Keine digitalen Signaturen
Erweiterte Funktionen
Die Implementierung bietet eine solide Grundlage für:
- Erstellung benutzerdefinierter Abschnitte
- Komplexe Importbindung
- Einbettung von Ressourcen
- Digitale Signierung
- Relokationsunterstützung
- Ausnahmebehandlungstabellen
Technische Hinweise
- Reine x64-MASM-Assembly – keine CRT-Abhängigkeiten
- Verwendet Windows-Heap für Speicherverwaltung
- Generiert PE32+-Format für x64
- Kompatibel mit Windows Vista und neuer
- Folgt der Microsoft-PE-Spezifikation
- Keine externen Bibliotheksabhängigkeiten außer kernel32.dll
Diese Implementierung stellt einen vollständigen, produktionsreifen PE32+-Writer bereit, der sich für Codegenerierungs-Backends, benutzerdefinierte Compiler und Executable-Packer eignet.