Während der Laufzeit Prozeduren überschreiben, geht das?

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Kurzer
Beiträge: 1621
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

Während der Laufzeit Prozeduren überschreiben, geht das?

Beitrag von Kurzer »

Hallo,

leider komme ich letzter Zeit überwiegend mit Fragen, statt mit Lösungen und fertigen Codes daher. Das tut mir Leid, aber ich arbeite an einer Sache mit vielen, für mich neuen Themen (und ein wenig eingerostet bin ich bzgl. PB auch noch etwas). Ich hoffe dass das mal wieder anders sein wird.

Worum geht es?

Ich würde gern zur Laufzeit eines Programmes eine seiner Prozeduren mit einem Datenblock (Assemblercode) befüllen. Sinn und Zweck des ganzen soll ein Sicherheitsmechanismus sein. Der eigentliche Prozedurinhalt wird verschlüsselt in der Exe vorliegen. Die "Prozedurhülse" soll zu dem Zeitpunkt in der Exe existieren, aber eben nur Blödsinn oder NOPs enthalten. Diese Hülse soll dann zur Laufzeit mit eben jenem regulären Inhalt gefüllt werden, der da eigentlich reingehört.

Das ganze soll nicht auf dem Filesystem passieren, sondern ausschließlich im Speicher, damit die Exe zu keiner Zeit mit der regulären Prozedur auf Platte existiert.

Vom Prinzip her ist mir das alles klar, aber der Teufel steckt im Detail.

Der Plan war:

1) Es gibt auf Platte eine unmodifizierte Exe (z.B. SchütztMich.exe), die die reguläre Prozedur enthält. Und zwar so, wie sie von PB kompiliert worden ist. Außerdem enthält das Programm in der DataSection einen leeren DatenBlock, der so groß ist wie der Speicherbedarf der o.g. Prozedur

2) Der Beginn und das Ende der betreffende Prozedur bzw. der Speicheradressen zum Prozedur-Anfang und Ende muss irgendwie kenntlich gemacht werden. Z.B. durch einen String "PROCBEG" und "PROCEND"

3) Ein separates Patchprogramm lädt die SchützMich.exe in den Speicher und sucht anhand der beiden Strings die Position der zu verschlüsselnden Prozedur

4) Der Speicherblock, der die Prozedur repräsentiert, wird ausgelesen, verschlüsselt und in den leeren Datenblock in der DataSection geschrieben.

5) Der Speicherblock der soeben ausgelesenen Prozedur wird dann mit Müll gefüllt und die Schützmich.exe wieder auf Platte geschrieben (BinGeschützt.exe).

6) Die BinGeschützt.exe enzhält bereits eine entsprechende Prozedur, die zur Laufzeit den Datenblock aus der DataSection kopiert, entschlüsselt und so den mit Müll gefüllten Speicherbereich mit dem Inhalt der originalen Prozedur füllt.

Ich hoffe das war in etwa verständlich beschrieben.

Nun treten da einige Fragen und Probleme auf. Meine aktive Assemblerzeit ist nun auch schon Lichtjahre her und das war auf dem Amiga. Aber ich denke es wird ja Parallelen geben.

Abgesehen von den Dingen, die ich bisher übersehen habe oder gar nicht weiß, habe ich folgende Fragen zu dem Vorhaben:

- Ist es möglich den o.g. Kennungsstring "PROCBEG" in die Prozedur (also in die "Code Section" des Programms) einzufügen?

Mit Data.s "PROCBEG" geht es nicht, weil Data nur innerhalb einer DataSection erlaubt ist und die liegt nach dem Einlesen des Programms durch das Betriebssystem sicherlich in einem separaten Speicherbereich.
Mit Inline Assembler !dc.b "PROCBEG" geht es auch nicht, da der Assembler dann meckert "Illegal Instruction"

Mit Berechnung von Sprungmarkenadressen statt des Kennungsstrings hat es leider auch nicht funktioniert.

Code: Alles auswählen

aussen1:
Procedure.i blah(a)
innen1:
	ProcedureReturn a+1
innen2:
EndProcedure
aussen2:

;MessageRequester("",Str(?innen2-?innen1))
MessageRequester("",Str(?aussen2-?aussen1))
Die inneren werden nicht gefunden, die äußeren liefern 0.
Wie findet man also die betreffende Speicherstelle der Prozedur?

Manuell geht das schon, wenn man die Exe mit dem Disassembler "OlyDbg" untersucht und den so ermittelten Speicheroffset dann mittels Hexeditor in der Datei aufsucht. Wobei sich mir dann trotzdem die Frage stellt, ist der Offset (gemessen vom Programmanfang) noch der gleiche, wenn das Programm durch Windows in den Speicher geladen und ausgeführt wird?

- Gibt es bei Windows so etwas wie Reloc-tables?
Wenn ich mich richtig erinnere, war es beim Amiga so, dass alle lange Sprünge innerhalb eines Assemblerprogramms so ausgelegt waren, als würde das Programm ab Speicherstelle 0 beginnen. Wenn man also zu Speicherstelle 16 springen wollte, dann wurde JMP +16 (sinngemäß) codiert. Alle diese Sprünge wurden in einer Reloc-table in der "Exe" gespeichert (naja, beim Amiga hießen sie nicht Exen). Der Loader im Betriebssystem hat das Programm beim späteren Ausführen dann an irgend eine freie Speicherstelle im Speicher-Adressraum geladen - nehmen wir mal an, an die Speicherstelle 40000. Bei diesem Vorgang wurden dann alle JMP's im Programmcode mittles der Reloc-table "gepatcht". Das JMP +16 wurde mit JMP +40016 überschrieben, weil das neue Sprungziel nun an eben dieser Speicherstelle lag.

Wenn das bei Windows ähnlich ist, dann kann ich das ganze sicherlich knicken, da ich nicht weiß, ob der FASM irgendwelche relozierbaren Sprünge in meine Prozedur zaubert.

Tja, so weit gehen erstmal meine Gedanken hierzu. Ich vermute, dass das nicht so einfach sein wird.
Sollte jemand von euch dem Thema näher stehen, dann würde ich mich über hilfreiche Hinweise freuen.

Gruß Kurzer
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.12 x64, OS: Win 11 24H2 x64, Desktopscaling: 150%, CPU: I7 12700 H, RAM: 32 GB, GPU: Intel(R) Iris(R) Xe Graphics | NVIDIA GeForce RTX 3070
Useralter in 2025: 57 Jahre.
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Während der Laufzeit Prozeduren überschreiben, geht das?

Beitrag von GPI »

Mutierender Code ist ein ganz schlechter Programmierstiel und könnte allerhand Sicherheitssystem anschlagen lassen. Bspw. Virenscanner.

Aber generell gesagt: Sicherheistsysteme sind bei offenen Systemen wie Windows, Linux und Mac völliger Unsinn. Man kann immer den Code analysieren und modifizieren. Sowas kann nur auf geschlossenen Systemen (wie bspw. Konsolen) funktionieren. Warum wohl setzen so viele auf Cloud-Dienste? Der User kann sie schlicht nicht manipulieren.
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
Imhotheb
Beiträge: 192
Registriert: 10.10.2014 13:14
Computerausstattung: Intel 8086, 640 KB RAM, Hercules Video Adapter, 2 x 5 1/4" 360kb Floppy, MS-DOS 3
Wohnort: Wolfenbüttel

Re: Während der Laufzeit Prozeduren überschreiben, geht das?

Beitrag von Imhotheb »

ich hatte auch mal so etwas ähnliches gemacht ... und trotzdem ganz anders

den "fehlenden code" habe ich allerdings in eine dll gepackt, verschlüsselt und auf einem server liegen. das prog. holt sich die datei, nach einer Authentifizierung, vom Server, entschlüsselt sie im Speicher und lädt diese ... es wird nie auf Platte geschrieben ... man könnte die dll aber auch mit datasection an die exe anhängen ... hatte ich zum testen so gemacht
weil einfach einfach einfach ist ... mach' ich es anders
freak
PureBasic Team
Beiträge: 766
Registriert: 29.08.2004 00:20
Wohnort: Stuttgart

Re: Während der Laufzeit Prozeduren überschreiben, geht das?

Beitrag von freak »

> Das ganze soll nicht auf dem Filesystem passieren, sondern ausschließlich im Speicher, damit die Exe zu keiner Zeit mit der regulären Prozedur auf Platte existiert.

Man kann aber jederzeit einen Debugger auf das laufende Programm loslassen und sich den "geheimen" Code anschauen. Wozu also der Aufwand?

Bin jetzt kein Experte für das Thema, aber ich denke du kannst deinen Plan etwas vereinfachen. Die Manipulation der Exe auf Platte kannst du dir sparen. Lade einfach den "geheimen" Code in einen ganz neuen Speicherbereich und rufe das Ergebnis per Prototype auf.

Also:
- "geheimen" code verschlüsselt in DataSection einbinden
- bei Start neuen Speicher allokieren, Code dahin entschlüsseln, speicher als "ausführbar" markieren
- Speicher per Prototype aufrufen um den Code auszuführen
Benutzeravatar
Kurzer
Beiträge: 1621
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

Re: Während der Laufzeit Prozeduren überschreiben, geht das?

Beitrag von Kurzer »

Hallo GPI,

danke für Dein feedback. Sicherlich hast Du recht was den Virenalarm angeht und mein Ansatz ist vermutlich auch mit "Kanonen auf Spatzen geschossen", ich würde trotzdem gern eine Art Schutz realisieren wollen.

Meine jetzige Überlegung geht dahin, dass ich die Prozeduren innerhalb der Exe über "Interface" und "VTables" aufrufe - so wie das Beispiel in der PB Hilfe es zeigt. Die Sprungadressen liegen ja separat in der DataSection und können auf die von mir beschriebene Art und Weise überschrieben/codiert werden. Zwar liegt dann der eigentliche Prozedurcode "offen", aber das mit den codierten VTAble-Adressen würde mir eigentlich schon reichen. Das System soll keinem "Hacker-Contest" standhalten.

Ich habe mir folgenden Testcode geschrieben, um mich mit der Interface- und VTable Thematik auseinanderzusetzen.

Code: Alles auswählen

EnableExplicit

Interface MyTest
	Requester()
EndInterface

Global Call.MyTest = ?VTable

Procedure Requester()
 	MessageRequester("", "Geht!")
EndProcedure

Procedure Callit()
	Call\Requester()	
EndProcedure  ; <-- Hier gibt es einen IMA

Callit()

DataSection
	VTable:
	Data.i ?Procedures
	Procedures:
	Data.i @Requester()
EndDataSection
Leider bricht das Programm am Ende der Prozedur "Callit()" mit einer Zugriffsverletzung ab.
Kann mir jemand sagen was da noch nicht korrekt ist?

PS: Hallo Imhotheb, danke auch für Deinen Post. Habe ich erst jetzt gesehen. Das mit dem Runterladen kommt zwar nicht infrage, aber die Sache mit dem Starten einer DLL im Speicher klingt interessant. Hast Du da evtl. noch ein bisschen Code, anhand dessen man das nachvollziehen kann? Würde mich freuen.

Edit: Freak, wenn ich das richtig verstehe, geht das auch in die Richtung, die Imhotheb beschrieben hat. Danke.
Ich begebe mich mal auf die Suche nach einem Beispiel. :allright:
Zuletzt geändert von Kurzer am 10.11.2015 20:33, insgesamt 2-mal geändert.
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.12 x64, OS: Win 11 24H2 x64, Desktopscaling: 150%, CPU: I7 12700 H, RAM: 32 GB, GPU: Intel(R) Iris(R) Xe Graphics | NVIDIA GeForce RTX 3070
Useralter in 2025: 57 Jahre.
Benutzeravatar
Imhotheb
Beiträge: 192
Registriert: 10.10.2014 13:14
Computerausstattung: Intel 8086, 640 KB RAM, Hercules Video Adapter, 2 x 5 1/4" 360kb Floppy, MS-DOS 3
Wohnort: Wolfenbüttel

Re: Während der Laufzeit Prozeduren überschreiben, geht das?

Beitrag von Imhotheb »

grundsätzlich bin ich auch der Meinung, das man ALLES knacken kann ... aber trotzdem kann man es etwas schwerer machen ;)
weil einfach einfach einfach ist ... mach' ich es anders
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Während der Laufzeit Prozeduren überschreiben, geht das?

Beitrag von GPI »

Das Beispiel in der Hilfe ist schlecht gewählt, mach es so:

Code: Alles auswählen

    EnableExplicit

    Interface MyTest
       Requester()
    EndInterface

    Global Call.MyTest = ?object

    Procedure Requester(*self)
        Debug "geht"
    EndProcedure

    Procedure Callit()
      Call\Requester()   
      Debug "2"
    EndProcedure  ; <-- Hier gibt es einen IMA
    
    call\Requester()
    Callit()

    DataSection
       Object:
       Data.i ?vtable
       vtable:
       Data.i @Requester()
    EndDataSection
sämtliche Proceduren von Interfaces geben als erstes immer die Adresse des Objects zurück und das erste Element des Objects muss ein Link auf die vTable sein.

Das mit der vTable ist auf jeden Fall ein besserer Ansatz. Aber nur so ein Tip: Wenn du feststellst, das dein Programm nicht "legal" ist, dann solltest du es nicht mit einer Meldung kund tun. Schränk die funktionalität ein. bspw. wenn du kodierte Daten speicherst, lass den User 10x eine Datei speichern und beim 11x verweigerst du das lesen der Datei. Der Zähler muss natürlich in der Datei versteckt sein. Sobald der Hacker weis, das was nicht stimmt, schaut er nach. Wenn aber erstmal alles läuft, ist es was anderes.
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
JMaker
Beiträge: 102
Registriert: 19.01.2015 10:18

Re: Während der Laufzeit Prozeduren überschreiben, geht das?

Beitrag von JMaker »

Ich höre in letzter Zeit des öfteren vTable.

Was ist vTable? Virtuelle Tabelle? :-)
Ich benutze Pure Basic 5.30 auf Microsoft Windows 7.
Gruß
JM
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: Während der Laufzeit Prozeduren überschreiben, geht das?

Beitrag von GPI »

Begriff der aus der Objektorientierten Programmierung kommt. In Handbuch wird der Begriff falsch bezeichnet, da wird das Object als vTable bezeichnet.

In der vTable sind die Adressen der Methoden angegeben, die zum Object gehören. Beim Interface gibt man den ersten Parameter nicht mit an, aber bei der tatsächlichen Definition der Methoden/Proceduren muss man ihn angeben. Das war der Fehler, den ich korrigiert hab.

Mehr hier: https://de.wikipedia.org/wiki/Tabelle_v ... r_Methoden (wobei das da nicht wirklich verständlich ist) :)
Zuletzt geändert von GPI am 10.11.2015 20:58, insgesamt 1-mal geändert.
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
Kurzer
Beiträge: 1621
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

Re: Während der Laufzeit Prozeduren überschreiben, geht das?

Beitrag von Kurzer »

GPI hat geschrieben: ...
Das mit der vTable ist auf jeden Fall ein besserer Ansatz. Aber nur so ein Tip: Wenn du feststellst, das dein Programm nicht "legal" ist, dann solltest du es nicht mit einer Meldung kund tun. Schränk die funktionalität ein. bspw. wenn du kodierte Daten speicherst, lass den User 10x eine Datei speichern und beim 11x verweigerst du das lesen der Datei. Der Zähler muss natürlich in der Datei versteckt sein. Sobald der Hacker weis, das was nicht stimmt, schaut er nach. Wenn aber erstmal alles läuft, ist es was anderes.
Danke für die funktionierende Lösung :allright:

Ja, dazu hatte ich mir auch schon Gedanken gemacht und mir überlegt, dass im "gehackten" Zustand einfach einige Rechenergebnisse falsch sein werden. Also, dass für einige Prozeduren 2 oder 3 Versionen vorliegen, die alle das (fast) gleiche machen, aber nur eine eben das richtige.
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.12 x64, OS: Win 11 24H2 x64, Desktopscaling: 150%, CPU: I7 12700 H, RAM: 32 GB, GPU: Intel(R) Iris(R) Xe Graphics | NVIDIA GeForce RTX 3070
Useralter in 2025: 57 Jahre.
Antworten