Odczyt stringa ze znakami specjalnymi (ReadMemoryProcess)

0

Piszę malutki programik pod jedną grę (coś w rodzaju bota).
Potrzebuję pobrać stringa z odpowiedniej wartości w pamięci aplikacji. Robię więc tak:

string MemReadString(int address)
 {
         HWND hwnd;
         DWORD ProcessID;
         HANDLE hInstance;
         SIZE_T nbr;
         char bufor[255];

         hwnd = FindWindow('Nazwa_mojej_aplikacji', NULL);
         GetWindowThreadProcessId(hwnd, &ProcessID);
         hInstance = OpenProcess(PROCESS_VM_READ, false, ProcessID);
         if(hwnd)
         {
                 ReadProcessMemory(hInstance, (void*)address, &bufor, sizeof(char), 0);
         }
         return bufor;
 }

Odczytuje stringa z pamięci w ten sposób:

Zmienna = MemReadString(0x546CE0);

Wszystko fajnie, działa gdy ten string będzie w jakiejś naturalnej postaci, np. MojTekst123, ładnie zczyta wartość.
Jednak gdy string będzie wyglądał w postaci takiej (bo w takiej też może istnieć, z różnymi znakami): Moj_Specjalny_Tekst_~!@#$%^&*()-_=+[{]};:'"|<,>.?/

To już nie wyświetli poprawnie tylko dostaje jakieś krzaczki...

Jak pobrać poprawnie stringa, który może posiadać znaki specjalne?

0

Wszystko zależy od kodowania. Zwykły char zajmuje w pamięci 1bajt czyli mamy do dyspozycji tylko 255 znaków, czyli zwykłe ANSI bez nawet polskich znaków.
Użyj wchar, który ma do dyspozycji 2bajty, czyli o wieeele więcej. Pozostaje i tak jeszcze kwestia czy to UTF czy ISO, ale google jak zrobić konwersję już podpowie.

Zawsze mnie zastanawiało jak można zaczytać coś z innych programów, mam pytanie jak pobierasz ten adres?

0

Wiem gdzie znajduje się dokładny adres poprzez wyszukanie go w pamięci, np. CheatEngine albo WinHex. Ok spróbuje z tym wchar.

0

A za każdym kolejnym uruchomieniem gry, nie zajmuje ona innego adresu w pamięci?

0

Nie, zawsze ma stałe położenie w pamięci.

Niestety wchar nie pomógł.

Jakieś pomysły?

2

Ten kod i tak jest bez sensu, bo pobiera tylko jeden bajt (czwarty argument ReadProcessMemory). Potem z tego bufora próbujesz stworzyć string. Nie upewniasz się nawet, że jest zakończony \0. Ba, w sumie to nawet nie wiesz w jaki sposób zakodowany jest ten napis, a samych sposobów zapisu go istnieje kilka. Tworzenie napisu ze wskaźnika podanego do konstruktora std::string obejmuje tylko jeden.

Wróć do CheatEngine i tam upewnij się jak zapisany jest ten napis i w jakim jest kodowaniu.

0

Powiem tak:

Odwołuje się do konkretnego adresu, który jest stały. We wszystkich przypadkach jeżeli string jest w takiej naturalnej postaci np. Tekst1, MojTekst, TekstTekst itd. to zawsze znajduje się w adresie: 0x546CE0. Natomiast jeżeli string będzie zawierał znaki jakieś specjalne to zmienia całkowicie położenie w pamięci, dlaczego tak jest?

0

A dlaczego tak miało by nie być? Tak działa ten program i już. Jeśli chcesz go rozgryźć to musisz znaleźć fragment kodu odpowiedzialny za umieszczenie napisu w pamięci. Referencja do tego napisu jest gdzieś zapisana. Czy jest zapisana pod stałym adresem? Pewnie nie, i tu znowu powtarzasz cały proces aż znajdziesz referencję wskazującą na tą referencję właściwą. No i znowu, czy ta kolejna referencja będzie będzie miała stały adres, pewnie nie... i tak aż dojdziesz do czegoś co ma stały adres.

0

Dostałem podpowiedź od jednej osoby, po angielsku:

You only need to check the byte at position address + 20 and if it is 0F then that means that the address is really storing a pointer to a remote string.

Mam rozumieć, że jeżeli na pozycji tego adresu, czyli 0x546CE0 + 20 będzie 0F to znaczy, że ten adres tak naprawdę przechowuje wskaźnik do właściwego stringa?

Mógłby mi ktoś to przybliżyć?

0

szopenfx, właśnie sprawdziłem to w CheatEngine i jest niby pusto w podglądzie pamięci a heksadecymalnie jest zapisane 01.

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