Debugger na wpisywanie do pamięci pewnej wartości

0

Witam,
czy jest jakiś debugger lub inne narzędzie, które na podstawie podanej przeze mnie liczby 32 bitowej jest w stanie sprawdzić gdzie ona jest wpisywana do pamięci podczas działania aplikacji?

O co chodzi?
Niestety ale w dość sporym programie mam gdzieś nadpisywanie pamięci. Problem w tym, że to nie jest taka prosta aplikacja. Problem jest dosyć złożony, bo jest to dllka, która hookuje główną aplikacje (grę zewnętrzną), korzysta z pamięci tej gry, itd. itd.
Problem polega na tym, że czasami pamięć się nadpisze w miejscu jakiegoś arraya, a konkretniej jego rozmiaru. A, że liczba która jest wpisywana zawsze do tego rozmiaru arraya jest konkretnym floatem (1057770468u [0.548032999f]), to pomyślałem, że gdybym miał debugger w którym wpisuję tą wartość a on mi wyprintuje w czasie rzeczywistym gdzie dana wartość jest zapisywana i pod jakim adresem instrukcje ją zapisują to mógłbym już coś zrobić.
Oczywiście można by było jakoś ustawić debuggera na rozmiar tego arraya i czekać, aczkolwiek jest taki problem, że takich arrayów jest dość sporo, a nadpisanie pamięci jest dość rzadkie.
Dodatkowo, wartość ta jest dość unikalna. W czystej grze ona się pojawia dosłownie 6 razy w pamięci, a już po działaniu dllki mojej niestety czasami występuje już 100/200 razy.

Pomysły?

0
#include <iostream>
using namespace std;

int main()
  {
   int x=0;
   cout<<"x="<<x<<"; &x="<<&x<<"; <- czyli adres w pamięci"<<endl;
   return 0;
  }

http://ideone.com/kkeDy4

0

@_13th_Dragon nie zrozumiałeś moich intencji. Jak mówiłem: problem jest złożony, i prawdę mówiąc to tu nie chodzi o indeksowanie w tablicach.
Warto dodać, że moja dllka dodatkowo wywołuje funkcje z gry w asmie. Poza tym, kod ma grubo ponad 30 tys linii kodu w C++ i asmie, a więc tu nie chodzi o zabawę w kotka i myszkę.

Mi trzeba ustawienie debuggera w taki sposób, że gdy wykryje, że aktualnie wykonywana instrukcja zapisuje do pamięci wartość 1057770468u to daje mi info gdzie ta instrukcja się znajduje i gdzie tą wartość wpisuje.

Edit:
Warto dodać, że tej wartości u mnie w kodzie oczywiście nie ma. Jakby była to bym tutaj nie przychodził.

0

Większość współczesnych debugerów ma czujkę na zmianę obszaru pamięci.
Poza tym masz coś takiego jak valgrid.

0

Ja o czymś takim nie słyszałem. Zresztą generowałoby masę false-positive a bardzo możliwe że wcale nie znalazłbyś tego czego szukasz. No bo skąd pewność że akurat jest to nadpisywane jednym zapisem do 4 bajtów? Równie dobrze mogą tam lecieć 4 osobne bajty ;) Ja bym na twoim miejscu spróbował się zastanowić CO to jest za wartość i skąd sie wzięła, inaczej może być ciężko.
(ciekawostka: raptem kilka dni temu był tu temat gdzie autor czytal jednego chara za pomocą scanf("%s do zmiennej typu char i nie zauważył że automatycznie dodawany jest \0 na koniec, co nadpisywało mu pewien wskaźnik... ;) )

0

Jak powiedziałem: problem w tym, że to jest dllka, a ja kodu gry którą hookuje nie mam. (To chyba proste).
Więc w tym przypadku np. Visual Studio Professional 2013 w którym pracuję oczywiście nic nie wykrywa w Debugu jak i w Releasie.
Poza tym, to może być problem nie w moim kodzie, ale w kodzie gry, w złym wywoływaniu funkcji gry, gdzieś pomylony wskaźnik przy wywoływaniu funkcji gry itd. itd. Tutaj łatwo o błąd gdziekolwiek.

Valgrid mówisz.. tylko czy to mi pomoże. Jak mówię: przydałby mi się jak cholera debugger który śledzi wykonywane instrukcje pod kątem co wpisują do pamięci.

@Shalom, pisałem już, że wyszukiwałem tej wartości w np. Cheat Engine, i widziałem że mało jest tych wartości. A konkretniej to w normalnej grze ich jest jedynie 6 sztuk, a już w podczepionej dllce roi się tego od ch**a, i co najważniejsze w ogóle te wartości się nie zmieniają. Są jedynie przypadki, że nieliczne się zmienią na 0 albo na jakiś normalny rozmiar arraya.
Co do tych 4 bajtów: patrzyłem w ogóle jak wygląda pamięć w obrębie tej zmiennej. Cała pamięć w obrębie jest nadpisana jak nic. Poza tym, znowu te wartości to są floaty od 0.f - 1.f. One się znikąd nie wzięły, tylko pytanie skąd i dlaczego. Namierzenie gdzie się zapisuje ta wartość byłoby super wielkim ułatwieniem.

Edit:

  • wcale nie mówię, że nadpisywanie dzieje się przez mov [], x, być może instrukcje floatowe asma są do tego używane.
0

Ale skad wiesz że to są floaty? Przecież równie dobrze nadpisanie może lecieć z innego miejsca. W tej przytoczonej przeze mnie sytuacji równie dobrze scanf mógł nadpisywać tablicę floatów a przecież wpisywał pojedyncze bajty ;)
Poza tym skoro to nie jest skompilowane z symbolami debugera to co chciałbyś osiągnąć? Zatrzymałby ci sie debuger na jakimś mov w assembly i nadal nie wiedziałbyś gdzie jest bląd ;]
Valgrind powinien przynajmniej wykryć zapis w złym miejscu w pamięci, tzn że ktoś np. pisze za tablicę, ale znów bez kodu albo symboli debugera to niewiele ci to da.

0

Uwierz mi, że to są floaty :-) Codzienne rozkodowywanie śmieci dało dużo doświadczenia.
Z tym, że scanfa to ja nigdzie nie mam. Takich funkcji u mnie w kodzie nie ma gdzie wykonywać. To jest tryb MP do gry która takiego trybu nie ma. Nadpisanie leci z trochę wcześniejszego miejsca niż ten size oczywiście. Oczywiście podmienia się również vtabela, wskaźnik na wartości itd. w tym arrayu i trochę bajtów wcześniej i później.
"Poza tym skoro to nie jest skompilowane z symbolami debugera to co chciałbyś osiągnąć? Zatrzymałby ci sie debuger na jakimś mov w assembly i nadal nie wiedziałbyś gdzie jest bląd ;]"
Widzisz, to jest zbyt płytkie myślenie... jeśli wiem gdzie jest ten mov no to wiem jedną rzecz: że to jest w grze albo że to jest w dllce. Jeśli to jest w grze no to patrzę disassemblerem w grę co gdzie się wywołuje, i dochodzę do miejsca w którym ja calluję tą funkcje z tej gry. I wiem gdzie jest błąd. No a jeśli to jest w dllce adres, no to znowu biorę disassemblera, i patrzę w dllce w jakiej funkcji, w której linii kodu nawet. I naprawiam. Tylko, że najpierw trzeba wiedzieć gdzie to się nadpisuje :-).

0

Źle mnie trochę zrozumiałeś ;) Ja po prostu przypuszczam że nawet jakbyś znalazł miejsce gdzie to sie nadpisuje to byłoby to z jakiegoś memcpy() albo innej standardowej funkcji, a bez symboli nie będziesz w zasadzie wiedział skąd została wywołana a w calym kodzie jest wołana wiele razy ;) Niemniej zobacz co ci powie valgrind. On wykryje ci, w teorii, każdy nieuprawniony zapis i odczyt.

0

Po to jest callstack, żeby namierzyć. Poza tym, w grze nie używa się memcpy i innych tego typu ciekawych rzeczy.
Wiesz.. to, że nie mam symboli to w zasadzie mi to niewiele przeszkadza. Sporo gry ja mam rozkodowanej, więc dla mnie to żaden problem.
Nie pytam was o to jak z adresu wyciągnąć informacje, tylko jak ten adres zdobyć. To pierwsze jest już moim problemem z którym poradzę sobie w 5 minut.

0

Móże @Bartosz Wójcik albo @Gynvael Coldwind coś będą mogli poradzić :)

0

Zainteresuj się czymś takim jak tracing warunkowy, oferują to debuggery takie jak OllyDbg. Czyli debugujesz sesję, zakładasz warunek śledzenia, np. gdy wartość rejestru będzie mieć jakąś wartość wtedy przerwij, uruchom tracing i czekaj na rezultaty.

Możesz takie coś osiągnąć także łatwo korzystając ze skryptów ODBScript.

Trudniejszym rozwiązaniem, choć całkiem wykonalnym jest własny debugger na WinApi (jeśli to Windows oczywiście), nie jest to takie trudne, odpalasz śledzenie aplikacji i co krok sprawdzasz stan rejestrów (x86, FPU, MMX, SSE etc.).

Wydaje mi się, że najłatwiejszym rozwiązaniem będą skrypty ODBScript.

Ja bym najpierw też najpierw sprawdził w jaki sposób zapisywane są te dane, czy np. kopiowane z innego rejonu pamięci, z rejestru 32 bitowego, z FPU, a dopiero potem mając tą wiedzę przystąpił do pisania skryptu.

0

Valgrind z tego co widzę odpada bo to chyba tylko linux. Ja wszystko muszę robić na Windowsie.

Nad własnym debuggerem również się zastanawiałem jako całkiem dobry pomysł, aczkolwiek sporo pisania, a efekt może być marny bo może to być problem znacznie głębszy niż wygląda. W ollym szukałem jakichś opcji ale nic nie znalazłem, w takim razie sprawdzę ten tracing warunkowy.
Nie sprawdzałem jeszcze w WinDbg czy czegoś nie ma, ale pewnie takich opcji to nie oferuje.

Dobra, dzięki za pomoc. Temat jeszcze nie wyczerpany ale wątpię, że ktokolwiek będzie wiedział więcej.

0

Nie znalazłeś, bo od tego jest tracing... Jak inaczej wyobrażasz sobie taką funkcjonalność debuggera? Takie coś można wykryć tylko w momencie zapisywania tej wartości. Skoro nie znasz adresów docelowych pamięci to nie możesz również założyć nigdzie breakpointów na zmianę pamięci (także typu hardware breakpoint).

Mówisz też, że to hack do gry, często są one dobrze zabezpieczane przed analizą i debugowaniem, więc polecam też Phant0m Plugin do ukrywania OllyDbg.

Jeśli ten hack nie jest zabezpieczony to ta cała dyskusja jest też zbędna, gdyż mógłbyś tą wartość znaleźć w samym hacku, bez jakiegoś śledzenia czy tracingu. Wstępna statyczna analiza np. w IDA czasami potrafi zaoszczędzić sporo pracy.

0

@mwl4 fajnie byłoby jakbyś podzielił sie później wynikami analizy ;)

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