AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Offset bei AllocMem?

Ein Thema von Plastewolf · begonnen am 20. Sep 2013 · letzter Beitrag vom 24. Sep 2013
Antwort Antwort
Seite 1 von 2  1 2      
Plastewolf
(Gast)

n/a Beiträge
 
#1

Offset bei AllocMem?

  Alt 20. Sep 2013, 19:58
Hallöchen miteinander,

Ich beschäftige mich seit kurzem mit der Programmierung von DLL's. Der Sinn dahinter ist diese in ein externes Programm zu Injecten und dort ein ein Offset zu patchen. Der Grund hierfür ist relativ simpel: Es wurde bei der Entwicklung ein fixer Wert innerhalb der EXE für den verfügbaren Speicher gegeben, kommt man in die Situation mehr zu benötigen, so schwappt der Speicher über und überschreibt damit teile Nachbarspeicher, was natürlich zum Absturz führt. Bisher habe ich über einen Hex Editor einfach ein paar KB hinten an der EXE angehängt und über einen Debugger dann das Offset geändert. Jetzt kam mir die Idee man könnte das ganze doch viel eleganter über eine eigene DLL lösen könnte.

Die Theorie: Prozess starten, DLL laden, DLL reserviert Speicher, DLL patcht Offset zur Laufzeit, EXE schreibt nun in den von der DLL reservierten Speicher statt des eigenen.

Zu diesem Zweck habe ich mir die Dokumentation durchgelesen und bin über den Befehl AllocMem gestoßen. Wenn ich das ganze also richtig interpretiert habe, müsste ich mit der Funktion Addr := AllocMem(1024) genau 1 KB im Arbeitsspeicher reservieren und das dazu passende Offset an den Pointer ADDR übergeben.

Wenn ich jetzt aber über Showmessage(PChar(Addr)); das Offset von dem frisch Reservierten Speicher ausgeben will, bekomme ich einfach garnichts angezeigt.


Habe ich dabei etwas vergessen? Laut Doku müsste AllocMem einen Wert zurück liefern.


Vielen Dank schonmal im vorraus.
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#2

AW: Offset bei AllocMem?

  Alt 20. Sep 2013, 21:55
AllocMem gibt Dir einen Pointer auf den Speicherbereich zurück. Mit Showmessage(PChar(Addr)); würdest Du Dir den Inhalt des Speicherbereiches as "String" anzeigen lassen.

Delphi-Quellcode:
Const
  s: String = 'Hallo'#0;
var
  Addr: Pointer;
begin
  Addr := AllocMem(1024);
  try
    Move(s[1], Addr^, Length(s) * SizeOf(char)); // ein Stück Text in den Speicherbereich schieben
    Showmessage(PChar(Addr)); // und den Text anzeigen
    Showmessage(IntToHex(DWord(Addr), 8)); // den Wert der Adressse in HEX anzeigen
  finally
    FreeMem(Addr);
  end;
end;
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Plastewolf
(Gast)

n/a Beiträge
 
#3

AW: Offset bei AllocMem?

  Alt 20. Sep 2013, 22:12
Hallo Bummi,

Vielen Dank für dein Beispiel
Also habe ich das richtig verstanden: der Pointer übergibt einen Integer, welcher erst in einen HEX Wert umgewandelt werden muss (logisch). Das DWord verwende ich um es später als String zur Weiterverarbeitung zu nutzen und die 8 gibt an das alles über der üblichen Offset größe abgeschnitten wird.

Auf diese weise könnte man den Speicher theoretisch ja dynamisch berechnen lassen, jedoch weiß ich leider nicht wieviel Speicher das Programm exakt benötigt (da die Sperre damit raus ist, ändert sich der Speicher natürlich je nach Anwendung). Aber vermutlich ist es in der heutigen Zeit kein Problem mehr wenn ich einfach permanent für die Funktion einen Bereich von 16 MB deklariere statt der üblichen ~4 MB welche im Originalzustand verwendet werden um auf Nummer sicher zu gehen.

Danke nochmals!
  Mit Zitat antworten Zitat
Plastewolf
(Gast)

n/a Beiträge
 
#4

AW: Offset bei AllocMem?

  Alt 21. Sep 2013, 19:50
Entschuldige für den Doppelpost aber darf ich nochmals eine kleine Frage einwerfen?

Ich habe mir über den Debugger die von mir benötigten Offsets herausgesucht.

Code:
Offset   | Code
0042053B   MOV EDX,OFFSET 0055E170
00420704   MOV EAX,DWORD PTR DS:[EDX*4+EAX+55E170]
0042075D   MOV DWORD PTR DS:[EAX*4+55E170],EDI
004207C9   MOV DWORD PTR DS:[EAX*4+55E170],0
Im Klartext würde das bedeuten das ich nur eine Funktion brauche, welche das originale Offset "0055E170" mit dem neuen Offset der DLL ändert (BZW die gesamte Zeile neu schreibt).
Ich hatte hierfür zuerst den Befehl "WriteProcessMemory" vorgesehen, aber nachdem ich eine Weile herum probiert habe musste ich feststellen das dieser nicht so ganz so funktioniert wie ich es gerne möchte. Das liegt wohl auch daran das er für Integer Werte gedacht ist. Über Google fand ich einen Tipp der besagte das ich einfach über die integrierte ASM Funktion von Delphi arbeiten könnte, aber auch das führt eigentlich nur zu Speicherproblemen und fehlern.

Die naheliegenste Lösung liegt in diesem Fall also in dem von dir erwähnten "MOVE" Befehl. Leider konnte ich bisher noch nicht herausfinden wie ich diesen so verwenden kann das er eine Zeile im Arbeitsspeicher eines externen Programmes ändern kann. Erschwerend kommt dazu das ich derzeit nicht weiß wie ich das Handle abfragen soll, da die DLL bereits im Prozess integriert ist.

Ich müsste Theoretisch ja nur von Delphi den String "MOV EDX,OFFSET" kopieren, dann das neue Offset anhängen und letztendlich den ganzen Wert in Hex umwandeln lassen. Dann hätte ich eine Grundlage die ich in den Speicher schreiben könnte. Oder Irre ich mich dabei?
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#5

AW: Offset bei AllocMem?

  Alt 21. Sep 2013, 20:00
MSDN-Library durchsuchenWriteProcessMemory würde schon funktionieren, macht aber im eigenen Prozess keinen Sinn. Du kannst einfach mit Zeigern arbeiten z.b.
PByte($00401234)^ := $90; um ein NOP zu setzen. Dementsprechend kannst du auch mit PDWord($00401337)^ := $008457A4; die Adresse patchen.

Dein erster Versuch ist fehlgeschlagen, da du vermutlich die Memory Protection nicht geändert hast. Du musst bevor du irgendwas patchst mit MSDN-Library durchsuchenVirtualProtect das PAGE_EXECUTE_READWRITE Flag setzen, damit du in diesem Bereich schreiben kannst.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Plastewolf
(Gast)

n/a Beiträge
 
#6

AW: Offset bei AllocMem?

  Alt 21. Sep 2013, 20:31
Wenn ich das mit dem VirtualProtect jetzt richtig gesehen habe, müsste ich den Befehl also insgesamt 4x ausführen und dabei als ersten Parameter den Offset, dann die Größe des Bereiches gefolgt von der gewünschten Operation und schlussendlich einen willkürlichen Parameter der einfach nur dafür da ist die Voreinstellung zu sichern.


Der erste Code läuft also von 42053B bis 42053F was einer größe von 4 entspricht.

Delphi-Quellcode:

Code := StrToHex('MOV EDX,OFFSET '+NewOffset);

VirtualProtect('$42053B', 4, PAGE_EXECUTE_READWRITE, OldProtect);
PByte($0042053B)^ := Code;

Edit:

Ach entschuldige bitte mein Kopf ist heute scheinbar nichtmehr so ganz auf der Höhe... PByte kann ja logisch auch nur das Byte schreiben, das dann natürlich vorraussetzt das ich die Hex werte Pärchenweise übergeben müsste...

Geändert von Plastewolf (21. Sep 2013 um 20:39 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#7

AW: Offset bei AllocMem?

  Alt 21. Sep 2013, 20:42
Halbwegs. Du musst dir jetzt einfach die genauen Offsets raussuchen, an denen die Adresse steht. Du brauchst ja auch nicht die kompletten Instructions überschreiben. Es reicht ja die (4 Byte lange) Adresse.

Wenn du die genauen Offsets hast, wendest du darauf jeweils einmal VirtualProtect an und schreibst dann mit PDWord(OFFSET)^ := NEWADDRESS die neue Adresse rein.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Plastewolf
(Gast)

n/a Beiträge
 
#8

AW: Offset bei AllocMem?

  Alt 21. Sep 2013, 21:09
Ich glaube ich habe das noch nicht zu 100% verstanden.

Delphi-Quellcode:
procedure Grafikspeicher();
var
  Offset : String;
  Memory : Pointer;
  OldProtect : Cardinal;

begin
   Memory := AllocMem(16777216);
  try
    Offset := IntToHex(DWord(Memory), 8);
    VirtualProtect('$0042053E', 4, PAGE_EXECUTE_READWRITE, OldProtect);
    PDWord($0042053E)^ := PDWORD(Offset)^;
  finally
    FreeMem(Memory);
    Showmessage('Es ist ein Fehler aufgetreten. Bitte starten Sie den Computer neu!');
  end;
end;
Der Bereich 0042053E-0042053F enthält das Offset zu der ersten Adresse. Ohne das VP spuckt er zwar keinen Fehler aus, änderte allerdings noch während der parallelen Überwachung mit OllyDbg nicht den gewünschten Bereich. Wenn ich es mit der VirtualProtect Variante versuche sagt er mir nur das es keine überladene Version geben würde, was unzweifelhaft daran liegt das ich den Pointer falsch übergeben habe. Vielleicht kann man den gesamten Bereich des Programmes von anfang an auf RW setzen?



Edit:

Ich habe gerade Bemerkt das es scheinbar doch funktioniert, es gab ein Problem mit dem Injector. Jedoch kommt nach der Injection eigentlich nur Datenmüll heraus, da er auf das Offset MOV EDX,37E170 schreibt, welches den Direct3D Header initialisiert.

Edit2:

Also ich hatte mich bei dem Offset verrechnet. Das korrekte Offset lautete "0042053C - 0042053F". Wenn ich des jetzt über PDword schreiben lasse kommt folgendes heraus: "MOV EDX,00450037". Obwohl der Rückgabewert für den neuen Speicher hier liegen müsste: "7EEA0010". Ich finde irgentwie den Fehler nicht...

Edit3:

Alles klar ich habe das Problem nun selbst gelöst. Mein Ansatz war falsch, ich hätte mich nie auf den String Wert Offset beziehen dürfen sondern direkt den DWORD Wert von Memory nehmen sollen. Jetzt sollte es Funktionieren. Fraglich ist aber warum er die Messagebox aus dem Finally bereich auslöst.

Vielen Dank nochmals für deine Hilfe!


Edit 4:

Das Problem ist doch noch nicht so gelöst wie ich es gerne hätte
Er reserviert zwar augenscheinlich Arbeitsspeicher und übergibt die Offset, welche jetzt auch korrekt geschrieben wird, aber wie sich gerade Rausstellt gibt es keinen freien Speicher auf der übergebenen Adresse. Irgentwie ist das übergebene Offset auch immer das gleiche, müsste das sich nicht eigentlich bei jedem Start ändern?

Geändert von Plastewolf (21. Sep 2013 um 22:30 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#9

AW: Offset bei AllocMem?

  Alt 21. Sep 2013, 22:19
Du schreibst einen String, welcher den HEX Wert des neuen Speicherbereiches enthält an eine Stelle, die für ein DWORD gedacht ist. Das kann doch nichts geben. Korrekt wäre folgendes:
PDWord($0042053E)^ := DWord(Memory); Den grade alloziierten Speicher direkt im finally Block wieder freizugeben, würde ich auch lassen, wenn du nicht willst, dass dein gepatchtes Programm beim Zugriff darauf crasht.

Darf ich fragen, um welches Spiel / Programm es sich handelt?
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Plastewolf
(Gast)

n/a Beiträge
 
#10

AW: Offset bei AllocMem?

  Alt 21. Sep 2013, 22:38
Diese ganze WinApi Geschichte kostet ganz schön Nerven

Eigentlich dürfte der Finally Block doch nur dann ausgeführt werden wenn innerhalb der Try Schleife eine Exception ausgelöst wird oder irre ich mich da?
Edit: Ich habe gerade zur Sicherheit nochmals nachgelesen, ich habe mich also geirrt. Habe das ganze jetzt durch except ersetzt. Habe den Code von Bummi mit der Try Finally Schleife übernommen gehabt

Es handelt sich um das alte Spiel Krush Kill n Destroy 2 von 1997. Wenn man die Standartauflösung mittels eines HEX Editor Patches erhöht dann Crasht das ganze einfach. Das Problem war schnell gefunden da der Speicher fix vergeben wurde und so durch die erhöhung überschwappte. Ich möchte gerne einige Funktionen in meine DLL auslagern und damit ein paar Probleme lösen.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:57 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz