Autor Beitrag
sonny2007
Hält's aus hier
Beiträge: 14



BeitragVerfasst: So 11.05.14 18:16 
Hallo zusammen,

heute habe ich mit dem ermitteln der BaseAdrr einer Exe beschäftigt.

Mein bisheriger Code
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: 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 Threadstarter
Hält's aus hier
Beiträge: 14



BeitragVerfasst: So 11.05.14 21:21 
Sorry für die schlechte Erklärung.

er schreibt einen Fehler

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: 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:
ausblenden 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).
ausblenden 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 Threadstarter
Hält's aus hier
Beiträge: 14



BeitragVerfasst: 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 Threadstarter
Hält's aus hier
Beiträge: 14



BeitragVerfasst: 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 ?

ausblenden volle Höhe 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:
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
    { Private-Deklarationen }
    function GetModuleBaseAdress(Modulname: string; dwProcessID : DWord): DWord;
  public
    { Public-Deklarationen }
  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
  // WindowHandle ermitteln
  hWnd := FindWindow('ArenaNet_Dx_Window_Class''Guild Wars 2');
  if hWnd = 0 then
    label1.Caption := 'Cannot find Window.'
  else begin
    //PID
    GetWindowThreadProcessId(hWnd,@pID);
    BaseAdress := GetModuleBaseAdress('Gw2.exe',pID);
    // Handle OpenProcess
    hProc := OpenProcess(Process_VM_Read,false, pID);
    adr := BaseAdress+BaseAdressOffset;
    if hProc = 0 then
      label1.Caption := 'Error Openprocess'
    else
      //label1.Caption := FloatToStr(ReadData(hProc,$4455E048));
      ReadProcessMemory(hProc, ptr(adr), @puffer, sizeof(puffer), Bytesread); //READ  <---- Fehlerzeile
      label1.Caption := FloatToStr(puffer);
      closehandle(hProc);//close
    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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 120
Erhaltene Danke: 18


D2005 Personal
BeitragVerfasst: Mo 12.05.14 18:02 
user profile iconsonny2007 hat folgendes geschrieben Zum zitierten Posting springen:
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.


ausblenden 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 Threadstarter
Hält's aus hier
Beiträge: 14



BeitragVerfasst: 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:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
....
adr : PByte;
BaseAdress : PByte;
...


ausblenden 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 Threadstarter
Hält's aus hier
Beiträge: 14



BeitragVerfasst: 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.

ausblenden 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 <> 0then
  begin
    EnumProcessModules(PHandle, @Module[0], 1024 * SizeOf(HMODULE), cbNeeded); //Get Enum from Modul
    SetLength(Module, cbNeeded div SizeOf(HMODULE)); //Get Nr. from Modul
    for i := 0 to Length(Module) - 1 do //Start the loop
    begin
      GetModuleBaseName(PHandle, Module[i], MName, SizeOf(MName)); //Modulname
      Memo1.Lines.Add(MName);
      if AnsiCompareText(MName, ModulName) = 0 then
      begin
        GetModuleInformation(PHandle, Module[i], @ModuleInfo, SizeOf(ModuleInfo)); //Modul Information
        Result := PByte(ModuleInfo.lpBaseOfDll); //Image Base Address
        CloseHandle(PHandle);
        Exit;
      end;
    end;
  end;
end;



Grüße s0n
SMO
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 120
Erhaltene Danke: 18


D2005 Personal
BeitragVerfasst: Di 13.05.14 12:47 
user profile iconsonny2007 hat folgendes geschrieben Zum zitierten Posting springen:
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:


ausblenden volle Höhe 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:
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 <> 0then
  begin
    // Length(array) * SizeOf(array[0]) gibt IMMER die Größe eines dyn. array in Bytes
    EnumProcessModules(PHandle, @Module[0], Length(Module) * SizeOf(Module[0]), cbNeeded);
    // Get Enum from Modul
    SetLength(Module, cbNeeded div SizeOf(Module[0])); // Get Nr. from Modul
    for i := 0 to Length(Module) - 1 do                // Start the loop
    begin
      GetModuleBaseName(PHandle, Module[i], MName, SizeOf(MName)); // Modulname
      Memo1.Lines.Add(MName);
      if AnsiCompareText(MName, ModulName) = 0 then
      begin
        GetModuleInformation(PHandle, Module[i], @ModuleInfo, sizeof(ModuleInfo));
        // Modul Information
        Result := ModuleInfo.lpBaseOfDll; // kein Typecast nötig zwischen Pointer und PByte
        Break;                            // for-Schleife abbrechen
      end;
    end;
    CloseHandle(PHandle); // Handle schließen, egal ob ModulName gefunden wurde oder nicht
  end;
end;
sonny2007 Threadstarter
Hält's aus hier
Beiträge: 14



BeitragVerfasst: Mi 14.05.14 11:34 
uhhh,

das war dumm. Da hast du natürlich Recht :) ...
Danke für den Tipp !

Grüße
s0n