Odczytanie base address z procesu 64-bitowego

0

Mam problem z odczytaniem base address z 64bitowego procesu.
Normalnie stosuję tą funkcję:

function GetModuleBaseAddress2(PID: Cardinal; MName: String): dword_ptr;
var
 Snap: THandle;
  M32: TModuleEntry32;
begin

  Snap := CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,PID);
  if (Snap = 0) then
    Exit;
  if Module32First(Snap, M32) then begin
    repeat
      if MName = M32.szModule then begin
        Result := Cardinal(M32.modBaseAddr);
        Break;
      end;
    until not Module32Next(Snap, M32);
  end;
end;

Niestety przy procesie 64 bitowym nie jest spełniony warunek " if Module32First(Snap, M32)" i funkcja nic nie zwraca.

Próbowałem także z

 function GetModuleBaseAddress(ProcessID: Cardinal; MName: String): Pointer;
var
  Modules         : Array of HMODULE;
  cbNeeded, i     : Cardinal;
  ModuleInfo      : TModuleInfo;
  ModuleName      : Array[0..MAX_PATH] of Char;
  PHandle         : THandle;
begin
  Result := nil;
  SetLength(Modules, 1024);
  PHandle := OpenProcess(PROCESS_QUERY_INFORMATION + PROCESS_VM_READ, False, ProcessID);
  if (PHandle <> 0) then
  begin
    EnumProcessModules(PHandle, @Modules[0], 1024 * SizeOf(HMODULE), cbNeeded); //Getting the enumeration of modules
   //EnumProcessModulesEx(
    SetLength(Modules, cbNeeded div SizeOf(HMODULE)); //Setting the number of modules
    for i := 0 to Length(Modules) - 1 do //Start the bucle
    begin
      GetModuleBaseName(PHandle, Modules[i], ModuleName, SizeOf(ModuleName)); //Getting the name of module
      if AnsiCompareText(MName, ModuleName) = 0 then //If the module name match with the name of module we are looking for...
      begin
        GetModuleInformation(PHandle, Modules[i], @ModuleInfo, SizeOf(ModuleInfo)); //Get the information of module
        Result := ModuleInfo.lpBaseOfDll; //Return the information we want (The image base address)
        CloseHandle(PHandle);
        Exit;
     end;
    end;
  end;
end;

Także nie działa.
Dokładnie chodzi o grę Shadow of Mordor. Przy innych grach, których używałem do odczytania base address wszystko działa, niestety przy tej poległem i nie mogę rozgryźć problemu

0

Niestety przy procesie 64 bitowym nie jest spełniony warunek " if Module32First(Snap, M32)" i funkcja nic nie zwraca.

Funkcja nie może nic nie zwrócić; W Twoim kodzie zwraca wartość niezdefiniowaną lub domyślną, jeśli warunek nie zostanie spełniony - sprawdź w dokumentacji; Przydałoby się tak tę funkcję napisać, aby zawsze "coś" zwracała, bo na 100% dostajesz ostrzeżenie przy kompilacji, które nie wiem dlaczego ignorujesz;

Z samymi hackami nie pomogę, ale @olesio bawi(ł) się w te klocki, więc może coś doradzi.

0

Podpowiedź pierwsza:
https://www.assembla.com/spaces/slipstream/subversion/source/HEAD/unload_dll/proc_man.c?_format=raw

kod wskazuje na to że wołanie funkcji dla 64 bitowego procesu z procesu 32 bitowego może się nie udać.

Podpowiedź druga:
http://stackoverflow.com/questions/20068219/readprocessmemory-on-a-64-bit-proces-always-returns-error-299

0

Nic na teraz nie pomogę, bo jestem poza domem. Jutro dopiero po południu obadam. Drugi kod na systemach starszych od 98 powinien działać. Pewnie nie można pobrać nazwy 64 bitowego procesu, bo pełną ścieżkę / nazwę pobiera się wtedy z tego co kojarzę inaczej. Musiał byś przeanalizować źródło Cheat Engine i zobaczyć jak t tam jest dokładnie zrobione. Zobacz też czy PE Tools pokazuje jakieś konkretne dsne dla procesu tej gry.

@furious programming i to nie są żadne Hooki. To w uproszczeniu adres bazowy procesu. Przydać się to może przy operacjach na pamięci procesu. Kiedy nam Cheat Engin pokaże że dana wartość jest na przykład pod adresem NazwaExeka.exe+1234bcdf to wiemy że offset 1234bcdf jest względem adresu bazowego, który może być różny w zapeżności od systemu i warunków uruchomienia. Ostatnio musiałem się tym posiłkować robiąc trainer do trybu RPG do gry Polanie 2 dla żony znajomego. Początkowo myślałem, że ustalony adrs Pointera jest stały. Dopiero Analiza w Cheat Engine pod Windowsem XP na VM pokazało, że adres należy podać względem tego bazowego. Ale to gra dość stara i 32 bitwa. Wtedy skorzystałem z podobnego kodu jak ten drugi.

Ewntualnie może pod kątem ustalania tego z pod WinAPI doraźnie pomóc może @Bartosz Wójcik.

0

Tak, chodzi o trainer. Niestety ciągle nie rozwiązałem problemu

0

Grzebanie w 64-bitowym procesie spod 32-bitowego programu to w ogóle kiepski pomysł. Windows dość ściśle izoluje te dwie platformy i może się po prostu nie dać.

A nawet jeśli by się dało, to byłoby to bardzo utrudnione. Przecież 64-bitowy proces ma 64-bitowe wskaźniki, z base address włącznie.

0

Nie umiem pomóc poki co, bo nie umiem poslużyć się EnumProcessModulesEx tak aby dla ostatniego parametru LIST_MODULES_ALL zwracało mi rozsądną ilość modułów. Ustawiam rozmiar tablicy na 1024, a wymagany rozmiar jest w okolicach kilkuset tysięcy. Jak wspomniał poprzednik, trzeba chyba inaczej robić we własnym kodzie jako procesie 32 bitowym do ogarnięcia 64 bitowego. Może @kAzek coś więcej podpowie, jak ustalić BaseAddress 64 bitowego procesu. Ja umiem tylko pełną ścieżkę. A z informacjami o modułach nie kombinowałem. A rozkłada mnie przeziębienie i niestety nie mam siły dalej kombinować z tym, bo ledwie siedzę, a nawet leżę przy komputerze.

0

Cheat engine jakoś sobie radzi z tym. Próbuje przeanalizować źródło, ale widzę że nie będzie łatwo

1

Kiedy nam Cheat Engin pokaże że dana wartość jest na przykład pod adresem NazwaExeka.exe+1234bcdf to wiemy że offset 1234bcdf jest względem adresu bazowego, który może być różny w zapeżności od systemu i warunków uruchomienia.

Okej, dobra, ale jeżeli NazwaExeka.exe jest procesem 64-bitowym, to się okazuje że wartość jest pod adresem 0x1234567890abcdef, a sam exek ma adres bazowy 0x0011223344556677. Jak się do tej komórki teraz niby odwołać spod 32-bitowego procesu?

Możemy mieć szczęście, jeżeli adres jest typu 0x0000000011223344, wtedy obcięcie go do 32-bitów 0x11223344 nie będzie katastrofą, ale nie ma takiej gwarancji.

Nie idźcie tą drogą.

1

Nie jest to możliwe. Nie ma innej odpowiedzi. Wszystkie 32-bitowe programy, które udostępniają taką możliwość robią to de facto za pomocą 64-bitowego kodu. Nawet jeżeli ładnie to ukrywają to pod spodem uruchamiają proces 64-bitowy i komunikują się z nim. A to można już wykonać na kilka sposobów - np. za pomocą COM i out-of-process server w surrogate (dllhost), który zajmie się i uruchomieniem procesu i serializacją (nie wiem na ile w Delphi/Pascalu będzie helperów do tego, bo ręczne bawienie się z proxy/stubs czy tlb może być męczące) albo zwykłe stworzenie procesu i komunikowanie się przez stdin/stdout, pipes albo cokolwiek innego sobie wymyślicie. 32-bitowy Process Monitor z Sysinternals zawiera w resource'ach swoją 64-bitową kopię ;).

0

Ok, to wiele wyjaśnia. Próbuję odczytać base address procesu 64bitowego z aplikacji 64 bit znów bez sukcesu.
Czy funkcje z pierwszego postu powinny działać w aplikacji 64bit?

0

Masz pierwszą poprawioną i dostosowaną do 64bit (oczywiście aplikacja ją wywołująca musi być 64 bit)

function GetModuleBaseAddress2(PID: Cardinal; MName: String): DWORD_PTR;
var
  hSnap: NativeUInt;
  M32: TModuleEntry32;
begin
  Result:= 0;
  hSnap:= CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, PID);
  if (hSnap = 0) then exit;
  M32.dwSize:= SizeOf(TModuleEntry32);
  if Module32First(hSnap, M32) then
  repeat
      if (AnsiCompareText(MName, M32.szModule) = 0) then
      begin
        Result:= Int64(M32.modBaseAddr);
        Break;
      end;
  until not Module32Next(hSnap, M32);
  CloseHandle(hSnap);
end;
0

Wszystko działa, wielkie dzięki za pomoc. Teraz będę kombinować nad komunikacją między procesami 32bit i 64bit

1 użytkowników online, w tym zalogowanych: 0, gości: 1