Autor |
Beitrag |
sonny2007
Hält's aus hier
Beiträge: 14
|
Verfasst: So 11.05.14 18:16
Hallo zusammen,
heute habe ich mit dem ermitteln der BaseAdrr einer Exe beschäftigt.
Mein bisheriger Code
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| function TForm1.GetModuleBaseAdress(Modulname: string; dwProcessID : DWord): DWord; var hSnapShot : THandle; myModul: MODULEENTRY32; begin hSnapShot := CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwProcessId ); if (hsnapshot <> INVALID_HANDLE_VALUE) then begin myModul.dwSize := SizeOf(myModul); if (Module32First (hsnapshot, myModul)) then while Module32Next(hsnapshot, myModul) do if CompareStr(myModul.szModule ,ModulName ) <> 0 then result := myModul.modBaseAddr; <------- Wie übergebe ich hier die Adresse richtig, da ModBaseAdrr als PByte vorliegt end; CloseHandle(hSnapShot); end; |
Was ich nicht noch nicht verstehe ist wie ich das PByte der ModBaseaddr richtig übergebe. Könntet ihr mir in der Sache weiterhelfen ?
Grüße
s0n
Zuletzt bearbeitet von sonny2007 am So 11.05.14 21:31, insgesamt 1-mal bearbeitet
|
|
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: So 11.05.14 19:29
Was meinst du mit "übergeben"? Stimmt der Wert nicht, oder wie oder was?
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
sonny2007 
Hält's aus hier
Beiträge: 14
|
Verfasst: So 11.05.14 21:21
Sorry für die schlechte Erklärung.
er schreibt einen Fehler
Delphi-Quelltext 1:
| [DCC Fehler] DPS_Main.pas(80): E2010 Inkompatible Typen: 'Cardinal' und 'PByte' |
Deshalb die Frage, wie ich PByte richtig als result ausgebe.
Grüße
s0n
|
|
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Mo 12.05.14 01:34
Ah, okay, das macht Sinn. Delphi ist da viel typstrenger als C
In dem Record steht der Wert direkt als Zeiger auf die Adresse drin, du hättest den gerne als Zahlenwert. Es ist aber der gleiche Wert, ein einfacher Typecast hilft also:
Delphi-Quelltext 1:
| result := DWORD(myModul.modBaseAddr); |
Wobei das eigentlich nicht ganz richtig ist - auf 64bit-Plattformen wäre das falsch, da DWORD immer ein 32bit-Typ ist. Richtig wäre sowohl als Rückgabewert als auch im Cast der Typ PtrUInt (entspricht size_t in C) (sofern deine Delphi-Version den bereits kennt, tun aber alle aktuellen).
Delphi-Quelltext 1:
| result := PtrUInt(myModul.modBaseAddr); |
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
sonny2007 
Hält's aus hier
Beiträge: 14
|
Verfasst: Mo 12.05.14 09:27
Vielen Dank,
ich werde es heute Abend gleich mal probieren. Muss ehrlich gestehen, Winapi ist schon mal ein Part für sich. Wenn man bis jetzt nur den Delphi Syntax Komfort gewohnt ist.
Grüße
s0n
|
|
sonny2007 
Hält's aus hier
Beiträge: 14
|
Verfasst: Mo 12.05.14 17:32
So ich habe se gerade einmal probiert.
Jedoch gibt es zwei Probleme. Einmal erkennt er den Typ PtrUInt nicht. Da ich in meiner Hilfe nix finde, frage ich hier mal nach welche unit ich einbinden muß.
Des Weiteren habe ich zur Kontrolle alle Prozesse in eine einfach Listbox geaddet.
Jedoch taucht dort meine gesuchte Exe nicht auf ?
Wo liegt der Fehler ?
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92:
| unit DPS_Main;
interface
uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls,PSAPI,TLHelp32;
type TForm1 = class(TForm) Timer1: TTimer; Label1: TLabel; ListBox1: TListBox; Button1: TButton; procedure Button1Click(Sender: TObject); private function GetModuleBaseAdress(Modulname: string; dwProcessID : DWord): DWord; public end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject); var hWnd: THandle; hProc : THandle; pId : DWord; lBuf : integer; Bytesread: SIZE_T; adresse : pointer; puffer : DWORD; adr : cardinal; BaseAdress : DWord; const BaseAdressOffset = $01352FA0;
begin hWnd := FindWindow('ArenaNet_Dx_Window_Class', 'Guild Wars 2'); if hWnd = 0 then label1.Caption := 'Cannot find Window.' else begin GetWindowThreadProcessId(hWnd,@pID); BaseAdress := GetModuleBaseAdress('Gw2.exe',pID); hProc := OpenProcess(Process_VM_Read,false, pID); adr := BaseAdress+BaseAdressOffset; if hProc = 0 then label1.Caption := 'Error Openprocess' else ReadProcessMemory(hProc, ptr(adr), @puffer, sizeof(puffer), Bytesread); label1.Caption := FloatToStr(puffer); closehandle(hProc); end;
end;
function TForm1.GetModuleBaseAdress(Modulname: string; dwProcessID : DWord): DWord; var hSnapShot : THandle; myModul: MODULEENTRY32; temp : string; i: Integer; begin hSnapShot := CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwProcessID ); if (hsnapshot <> INVALID_HANDLE_VALUE) then begin myModul.dwSize := SizeOf(myModul); if (Module32First (hsnapshot, myModul)) then while Module32Next(hsnapshot, myModul) do begin temp := ''; for i := 0 to Length(Modulname) do temp := temp+myModul.szModule[i]; Listbox1.Items.Add(temp); if temp = ModulName then result := PtrUInt(myModul.modBaseAddr); end; end; CloseHandle(hSnapShot); end;
end. |
Vielen Dank im Voraus.
Grüße
s0n
|
|
SMO
      
Beiträge: 120
Erhaltene Danke: 18
D2005 Personal
|
Verfasst: Mo 12.05.14 18:02
sonny2007 hat folgendes geschrieben : | Was ich nicht noch nicht verstehe ist wie ich das PByte der ModBaseaddr richtig übergebe. Könntet ihr mir in der Sache weiterhelfen ? |
Hallo. Das ist prinzipiell dasselbe Problem wie bei deiner vorigen Frage, die ich beantwortet habe.
Du möchtest eine Speicheradresse (=Pointer) als ein DWORD (Cardinal) übergeben. Für 32-bit-Programme sind Speicheradressen in der Tat auch 32 bit groß und wie Martok schrieb kannst du einen Typecast machen: Result := DWORD(myModul.modBaseAddr). Delphi nörgelt, da Speicheradressen auch 64 bit groß sein können, nämlich bei 64-bit-Programmen. Selbst wenn du gar nicht vorhast, eine 64-bit-Version deines Programms zu kompilieren, Delphi ist da streng.
Besser als der Typecast wäre es, wenn deine Funktion "GetModuleBaseAdress" als Rückgabewert kein DWORD hätte, sondern ein "NativeInt" oder "NativeUInt". Noch besser wäre PByte. Denn PByte ist ein Pointertyp (da weiß man, dass man es mit Speicheradressen zu tun hat) und erlaubt auch Pointerarithmetik. Wenn "adr" und "BaseAdress" ebenfalls zu PByte geändert werden, solltest du problemlos Rechnungen wie "adr := BaseAdress+BaseAdressOffset+ ..." durchführen können.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26:
| function TForm1.GetModuleBaseAdress(Modulname: string; dwProcessID: DWord): PByte; var hSnapShot: THandle; myModul: MODULEENTRY32; temp: string; i: integer; begin hSnapShot := CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessID); if (hSnapShot <> INVALID_HANDLE_VALUE) then begin myModul.dwSize := SizeOf(myModul); if (Module32First(hSnapShot, myModul)) then while Module32Next(hSnapShot, myModul) do begin temp := ''; for i := 0 to Length(Modulname) do temp := temp + myModul.szModule[i]; ListBox1.Items.Add(temp); if temp = Modulname then Result := myModul.modBaseAddr; end; CloseHandle(hSnapShot); end else RaiseLastOSError; end; |
Probiers mal damit. Änderungen: CloseHandle wird nur aufgerufen, wenn hSnapShot auch tatsächlich ein gültiges Handle enthält. Falls nicht, dann wird per RaiseLastOSError eine Exception ausgelöst, die dir einen Fehlercode und eine Meldung präsentiert. Damit solltest du herausfinden können, wo es hängt.
PS: Welche Delphi-Version benutzt du eigentlich?
|
|
sonny2007 
Hält's aus hier
Beiträge: 14
|
Verfasst: Di 13.05.14 07:13
Ahhh,
das bringt schon mehr Licht ins dunkle. Danke für den Hinweis wie das mit PBYTE gemeint war. Das soweit klar.
Das Problem mit dem Finden in der Funktion "GetModuleBaseAdress" funktioniert jedoch nicht. Und vor allem gibt er auch keinen Fehler aus.
Er gibt einfach nil zurück.
Hier die aktuelle Funktion.
geändert:
Delphi-Quelltext 1: 2: 3: 4:
| .... adr : PByte; BaseAdress : PByte; ... |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27:
| function TForm1.GetModuleBaseAdress(Modulname: string; dwProcessID: DWord): PByte; var hSnapShot: THandle; myModul: MODULEENTRY32; temp: string; i: integer; begin Result := nil; hSnapShot := CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessID); if (hSnapShot <> INVALID_HANDLE_VALUE) then begin myModul.dwSize := SizeOf(myModul); if (Module32First(hSnapShot, myModul)) then while Module32Next(hSnapShot, myModul) do begin temp := ''; for i := 0 to Length(Modulname) do temp := temp + myModul.szModule[i]; ListBox1.Items.Add(temp); if temp = Modulname then Result := myModul.modBaseAddr; end; CloseHandle(hSnapShot); end else RaiseLastOSError; end; |
Ich benutze übrigens Delphi XE 2 - Architect Version (Original) . Habe mich bisher immer vor Pointer,Speicher & Winapi gedrückt. Doch in diesem Fall  ...
Grüße
s0n
Zuletzt bearbeitet von sonny2007 am Di 13.05.14 07:41, insgesamt 1-mal bearbeitet
|
|
sonny2007 
Hält's aus hier
Beiträge: 14
|
Verfasst: Di 13.05.14 07:40
Nach mehreren Versuchen durchforsten der msdn, Google und Foren bin ich auf folgenden Ansatz gestoßen.
Mit dieser Funktion wird die korrekte ImageAdresse( Baseadress ) zurück gegeben.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:
| function tform1.GetModuleBaseAddress(ModulName: String; cProcessID: Cardinal ): PByte; var Module : Array of HMODULE; cbNeeded, i : Cardinal; ModuleInfo : TModuleInfo; MName : Array[0..MAX_PATH] of Char; PHandle : THandle; begin Result := nil; Memo1.Clear; SetLength(Module, 1024); PHandle := OpenProcess(PROCESS_QUERY_INFORMATION + PROCESS_VM_READ, False, cProcessID); if (PHandle <> 0) then begin EnumProcessModules(PHandle, @Module[0], 1024 * SizeOf(HMODULE), cbNeeded); SetLength(Module, cbNeeded div SizeOf(HMODULE)); for i := 0 to Length(Module) - 1 do begin GetModuleBaseName(PHandle, Module[i], MName, SizeOf(MName)); Memo1.Lines.Add(MName); if AnsiCompareText(MName, ModulName) = 0 then begin GetModuleInformation(PHandle, Module[i], @ModuleInfo, SizeOf(ModuleInfo)); Result := PByte(ModuleInfo.lpBaseOfDll); CloseHandle(PHandle); Exit; end; end; end; end; |
Grüße s0n
|
|
SMO
      
Beiträge: 120
Erhaltene Danke: 18
D2005 Personal
|
Verfasst: Di 13.05.14 12:47
sonny2007 hat folgendes geschrieben : | Das Problem mit dem Finden in der Funktion "GetModuleBaseAdress" funktioniert jedoch nicht. Und vor allem gibt er auch keinen Fehler aus. |
Seltsam, bei meinem Test hat es funktioniert. Habe aber kein Guild Wars 2, sondern ein anderes Programm benutzt.
Die neue Funktion geht bei mir auch. Allerdings ist ein kleiner Fehler drin: du schließt das Handle nur, wenn das gewünschte Modul wirklich gefunden wird. Wenn es nicht gefunden wird, bleibt das Handle offen (Leak). Ich würde es so machen:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34:
| function TForm1.GetModuleBaseAddress(ModulName: string; cProcessID: Cardinal): PByte; var Module: array of HMODULE; cbNeeded: Cardinal; i: Integer; ModuleInfo: TModuleInfo; MName: array [0 .. MAX_PATH] of Char; PHandle: THandle; begin Result := nil; Memo1.Clear; SetLength(Module, 1024); PHandle := OpenProcess(PROCESS_QUERY_INFORMATION + Process_VM_Read, false, cProcessID); if (PHandle <> 0) then begin EnumProcessModules(PHandle, @Module[0], Length(Module) * SizeOf(Module[0]), cbNeeded); SetLength(Module, cbNeeded div SizeOf(Module[0])); for i := 0 to Length(Module) - 1 do begin GetModuleBaseName(PHandle, Module[i], MName, SizeOf(MName)); Memo1.Lines.Add(MName); if AnsiCompareText(MName, ModulName) = 0 then begin GetModuleInformation(PHandle, Module[i], @ModuleInfo, sizeof(ModuleInfo)); Result := ModuleInfo.lpBaseOfDll; Break; end; end; CloseHandle(PHandle); end; end; |
|
|
sonny2007 
Hält's aus hier
Beiträge: 14
|
Verfasst: Mi 14.05.14 11:34
uhhh,
das war dumm. Da hast du natürlich Recht  ...
Danke für den Tipp !
Grüße
s0n
|
|
|