|
1 | 1 | # HelpNDocTools |
| 2 | +# Hybrid DOS + PE32+ Single-EXE Projekt |
| 3 | + |
| 4 | +Kurz: Dieses Projekt verbindet 16-Bit DOS-Code und 64-Bit Windows (PE32+) Code in einem einzigen ausführbaren Image. Ziel ist eine *flat EXE*, die ohne traditionellen Linker erzeugt wird. Die ausführbare Datei startet unter DOS (z. B. DOSBox) den 16-Bit-Teil und unter Windows den 64-Bit-PE-Teil. |
| 5 | + |
| 6 | +## Inhalt des Repos |
| 7 | +- `winhdr.inc` — manueller PE32+ Header, Optional Header und Section Table (dynamisch berechnet). |
| 8 | +- `precalc.asm` — Makros / Berechnungen (SIZEOF_HEADERS, SIZEOF_IMAGE usw.). |
| 9 | +- `code64.asm` — Win64 Entry / Windows-Code (GUI / minimal). |
| 10 | +- `code16.asm` — DOS 16-Bit Stub (Interrupt-Services, DOS exit). |
| 11 | +- `start.asm` — Zusammenführung / Layout / Dispatcher. |
| 12 | +- `packed.zip` — (optional) Beispiel Build / Test-Artefakt. |
| 13 | + |
| 14 | +## Schlüsselideen & Probleme, die gelöst wurden |
| 15 | +1. **PE Header Konsistenz** |
| 16 | + - `SizeOfHeaders` im Optional Header **muss** mit dem realen, gepaddeten Header („file-padded to FILEALIGN“) übereinstimmen. |
| 17 | + - Fix: `dd SIZEOF_HEADERS` und `times (SIZEOF_HEADERS - ($ - $$)) db 0`. |
| 18 | + |
| 19 | +2. **SizeOfImage korrekt berechnen** |
| 20 | + - `SizeOfImage = ALIGN_UP(max(Section.VirtualAddress + Section.VirtualSize), SectionAlignment)`. |
| 21 | + |
| 22 | +3. **Win64 ABI / Stack-Alignment** |
| 23 | + - Beim Windows-Entry gilt: `RSP ≡ 8 (mod 16)` beim Eintritt. Vor jedem `call` muss jedoch `RSP ≡ 0 (mod 16)` sein **und** 32 Byte „shadow space“ müssen bereitstehen. |
| 24 | + - Fix im Prolog: `sub rsp, 40` (32B shadow + 8B alignment correction). Dann `mov ecx, <exitcode>` und `jmp qword [rel IAT_win32_ExitProcess]` (Tail-call, da ExitProcess nicht zurückkehrt). |
| 25 | + |
| 26 | +4. **EntryPoint-Ausrichtung vs. tatsächlicher Startcode** |
| 27 | + - Ein häufiger Fehler: `AddressOfEntryPoint` zeigt nicht exakt auf das Label, das den Win64-Prolog enthält (stattdessen z. B. 3 Byte früher). Folge: Loader startet bei `ret`/NOP → Crash. |
| 28 | + - Fix: Entry auf genau die erste Prolog-Instruktion setzen oder `.text` so anordnen, dass das erste Byte der Section der Prolog ist. Alternativ: 5-Byte `jmp` an den realen Einstieg setzen. |
| 29 | + |
| 30 | +5. **IAT / Import Table** |
| 31 | + - RIP-relative `call qword [rel IAT_ExitProcess]` muss auf einen gültigen QWORD zeigen, der vom Loader zur Laufzeit mit der Adresse der API gefüllt wird. |
| 32 | + - Debug: `dq <IATaddr>` prüfen und disassemblen (`u poi(IATaddr)` in WinDbg). |
| 33 | + |
| 34 | +## Build (Hinweis: verwendete NASM-Variante ist die Windows-Version) |
| 35 | +> Die Projekt-Buildschritte hängen von deinem Make/Build-Script ab. Grundsätzlich: |
| 36 | +1. Säubere altartefakte. |
| 37 | +2. `nasm` deine .asm-Dateien (so, wie dein Layout es erfordert). |
| 38 | +3. Resultat ist ein einzelnes EXE-Image (`dos.exe`). |
| 39 | + |
| 40 | +> Hinweis: In diesem Projekt wird bewusst **kein** linkerischer PE-Linker verwendet — die Sections, Header und IAT werden manuell in Assembler erzeugt. |
| 41 | +
|
| 42 | +## Test & Debug |
| 43 | +### Kurztests |
| 44 | +- SHA256 prüfen: `certutil -hashfile dos.exe SHA256` |
| 45 | +- Header prüfen: `dumpbin /headers dos.exe` (AddressOfEntryPoint, SizeOfHeaders, SizeOfImage, DataDirectories). |
| 46 | +- Imports prüfen: `dumpbin /imports dos.exe` |
| 47 | + |
| 48 | +### x64dbg (Entry / IAT prüfen) |
| 49 | +- `File → Open` → `dos.exe` |
| 50 | +- Break am EntryPoint (x64dbg hält idR automatisch). |
| 51 | +- Disasm: `sub rsp, 28h / mov ecx, 2 / jmp qword [rel ...]` |
| 52 | +- Rechtsklick auf `jmp` → `Follow in Dump` → `dq` → QWORD sollte auf `kernel32`/`ntdll` zeigen. |
| 53 | +- Wenn `dq` == 0 → IAT nicht gepatcht → prüfe `.idata`-Directory-/Section-RVAs. |
| 54 | + |
| 55 | +### WinDbg Checks (kompakt) |
| 56 | +- `bp @$exentry` ; `g` |
| 57 | +- `u rip L3` ; `r` |
| 58 | +- `r @$t0 = rip + <offset nach instr>` ; `dq @$t0 L1` |
| 59 | +- `lm` ; check module ranges |
| 60 | + |
| 61 | +## Troubleshooting (häufige Fehlerquellen) |
| 62 | +- `SizeOfHeaders` != tatsächliche Header-Padding → Loader patcht IAT/Sections falsch → Crash. |
| 63 | +- EntryPoint zeigt nicht exakt auf Prolog → RET/NOP am Anfang → Crash. |
| 64 | +- Stack-Alignment nicht berücksichtigt → `0xC0000005` bei WinAPI-Aufrufen. |
| 65 | +- IAT-RVA/Size falsch gesetzt → Loader füllt IAT nicht. |
| 66 | +- ASLR/Relocs (wenn Du reloc-stripped baust, wähle ein geeignetes `ImageBase`). |
| 67 | + |
| 68 | +## Hinweise zur Weitergabe / Lizenz |
| 69 | +- Dieses Projekt enthält gemischten Code (16-Bit / 64-Bit). Wenn du den Code in ein öffentliches Repo hochlädst, entferne evtl. lokale Pfade, private Keys oder persönliche Daten aus Headers. |
| 70 | + |
| 71 | + |
2 | 72 | **Update** on: 2025-10-05 11:15 pm<br> |
3 | 73 | <hr> |
4 | 74 | Working pre-alpha Release Code available under: [Playground](https://kallup.net/myapp/packed.zip). <br> |
|
0 commit comments