Hardware-Emulation, wie?

Frage
Ich habe ein Windows-Programm der Messtechnik und möchte die Datenerfassungs-Hardware anderweitig anschließen. Die Hardware-Schnittstelle ist bekannt, aber die (Closed-Source-)Software soll nicht geändert werden. Die Software soll glauben mit der Original-Hardware zu „sprechen“.
Antwort
Programm DOS Windows 9x/Me Windows 32 bit Windows 64 bit
DOS nativ in DOS-Box InpOut32.dll läuft nicht
(Ausnahme: DosBox, Wine für Windows)
Win16 direkte I/O -nativ
mit VxD spezieller VDD erforderlich
Win32 direkte I/O giveio.sys laden Diese giveio.sys laden
(nur) mit VxD (nie gesehen) Simulierenden .SYS-Treiber schreiben
mit inpout32.dll nativ
mit giveio.sys läuft im allgemeinen
(Treiber wird gar nicht erst geladen)
nativ giveio.sys ersetzen!
mit speziellem 32-bit-.SYS-Treiber Nach einem 64-Bit-Treiber nachbohren, oder
SYS-Treiber disassemblieren
und für 64 Bit übersetzen + zertifizieren (*)
Win64 mit zertifiziertem .SYS-Treiber - nativ

Grundsätzlich wird hierfür ein sogenannter Virtueller Gerätetreiber benötigt. Da gibt's eine Menge Lösungsmöglichkeiten. (Windows NT oder Nachfolger sei vorausgesetzt.)

  1. Ist die Software 16-bittrig, ist ein Virtual Device Driver (VDD) die einfachste und beste Lösung. Man bleibt im unpriviligierten Modus und muss keinen Kernel-Mode-Treiber schreiben. Siehe Quelltext von meiner InpOut32.dll für einen Ausgangspunkt. VDDs funktionieren nur mit Nicht-Druckerport-Adressen zuverlässig (also nicht 0x378, 0x278 oder 0x3BC), daher ist es am besten, wenn die Software eine wahlfreie Adresse zulässt. Eventuell mitgelieferte Portzugriffs-Freigabe-Software ist zu deaktivieren. Wenn das nicht geht, dann gehe zu Punkt 6.
  2. Bei 32-Bit-Software liegt häufig eine altbekannte DLL wie inpout32.dll, dlportio.dll oder so dabei, welche die Portzugriffe abwickelt. Diese durch meine inpout32.dll (siehe oben) ersetzen und deren Quelltext so abändern, dass die gewünschte Funktionalität erreicht wird. Kein Kernmodus-Treiber, keine lahmen Exceptions, perfekt. (Von meiner inpout32.dll sollte nicht mehr viel übrig bleiben.)
  3. Wenn Punkt 2 nicht klappt, sollte man nachsehen, ob die Software unter Windows 98/Me läuft (laufen würde) und in diesem Fall direkten Portzugriff mit eingebauten in/out-Befehlen vollführt. Also kein VxD benötigt. Dann kann man wiederum meine InpOut32.dll bemühen, um Win9x/Me vorzugaukeln und die Portzugriffe per prozessglobalen Exception-Handler zu behandeln. Immer noch alles im unprivilegierten Modus.

    Sollte es sich herausstellen, dass es zwar funktioniert aber zu langsam läuft, muss man ebenfalls zu Punkt 4 weiter, aber es ist sehr wahrscheinlich, dass man das gesamte Vorhaben aufgeben muss: Die Software muss neu geschieben werden.

  4. Wenn auch das nicht klappt, muss man in den sauren Apfel beißen und einen Kernmodus-Treiber schreiben. Irgendwo muss es eine .sys-Datei geben, die die Ein/Ausgabe abwickelt. Diese erst mal disassemblieren; mit IDA. Am besten wäre es, den Treiber am „oberen Ende“ beim DeviceIoControl zu imitieren. Dazu muss man verstehen, wie die DeviceIoControl-Schnittstelle funktioniert. Das Ergebnis wäre hier ein Treiber, der bestmögliche Performance liefert und auch für 64-Bit-Windows-Versionen zur Verfügung steht. Diese ersetzt dann einfach die originale .sys-Datei.
  5. Wird das mit der DeviceIoControl-Schnittstelle zu kompliziert (etwa weil der Treiber Bloatware ist), sollte man nachsehen, ob die HAL-Funktionen READ_PORT_UCHAR usw. verwendet werden. In diesem Fall zapft man diese HAL-Funktionen an. Siehe vlpt.c, und alles löschen was mit IDT und Debugregistern zu tun hat.
  6. Wenn hingegen direkte Portzugriffe programmiert sind, nimmt man sich dieselbe vlpt.c und wirft alles heraus, was mit der Anzapfung von READ_PORT_UCHAR usw. zu tun hat. Da sich jedoch der meiste Kode um korrekte Stapelrahmen für den Aufruf anderer Kernel-Funktionen kümmert, kann man, wenn das nicht notwendig ist, den wesentlich einfacheren Quelltext von DongleKnacker zum Vorbild nehmen.
  7. Falls auch das schief geht, weil der Treiber das Bit 3 im CR4 vor jedem in/out-Befehl löscht, muss man zurück zum Punkt 4. (Denn dann ist's wohl ein Dongle, oder?) Oder man benutzt eine Virtual Machine (VM). In der VM lässt man das Programm mitsamt Treiber laufen, und außerhalb (im Gast-System) das DongleKnacker-Derivat. Kompliziert und fehleranfällig, aber die allerletzte Chance.
  8. Betrifft nur den Durchlass von I/O, nicht deren Umleitung: Die Modifikation des Task State Segments für 64-Bit-Windows. erledigt der neue Treiber giveio.sys. Der PatchGuard ist damit ebenfalls ausgetrickst, und der Treiber ist zertifiziert.
Die Punkte 1, 5, 6 und 7 erfordern Windows als 32-Bit-Version.