Diskuze: Grabovani her
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Neregistrovaný

Zobrazeno 50 zpráv z 50.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Nejsem si ted jisty, jestli chces zachytavat video/screeny nebo jen sbirat info ze hry.
U toho infa zalezi na tom, jak a v cem je napsan klient - pokud by to byl
treba C#, tak by stacilo ho jen disassemblovat a poupravit, jen by to nejspis
porusilo nejake licencni podminky .
Pokud v c/c++, tak budes muset zjistit, kam si to uklada, pak nacist jeho pamet a precist tu konkretni hodnotu.
Adresu zjistis treba disassemblovanim nebo jsou nejake programky, kam zadas hodnotu a ono ti ji to vyhleda vsude v pameti vybraneho programu, pak pri zmene zadas vyhledavani znovu a timhle postupne vyfiltrujes, ktera z adres bude asi ta, kterou hledas.
a nazvy tych programu ?(zisli by sa),ja som pouzil spy++ pre sledovanie triedy, ale daleko som nezasiel, neviem ako sa dostat do pamete programu.
Na scan pameti jsem kdysi (tak pred 10 roky ) pouzival ArtMoney, ale nevim,
jestli vubec jeste funguje, obdobne by mel fungovat CheatEngine
http://www.cheatengine.org/ .
Je dobre nejdrive zjistit co nejvice info - treba pouzit PEID, ten zanalyzuje
soubor a zjisti, v cem byl pravdepodobne naprogramovan, par informaci o tom je
treba tu:
http://www.itnetwork.cz/…ani-programu
budes muset pouzit winapi, funkci
http://msdn.microsoft.com/…=vs.85).aspx
do C# tu funkci naimportujes takhle:
[DllImport("Kernel32.dll")]
static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, UInt32 nSize, ref UInt32 lpNumberOfBytesRead);
tak dostal som sa k tomu
do akej premeny mam zadat adresu z ktorej chcem citat data?
moj kod :
[DllImport("Kernel32.dll")]
private static extern bool ReadProcessMemory(IntPtr hProcess, UIntPtr lpBaseAddress, [Out] byte[] lpBuffer, UIntPtr nSize, IntPtr lpNumberOfBytesRead);
[DllImport("kernel32.dll")]
static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, int dwProcessId);
private void Form1_Load(object sender, EventArgs e)
{
Process[] procs = Process.GetProcessesByName("PartyGaming");
int proccID = procs.Length == 0 ? 0 : procs[0].Id;
IntPtr pHandle = OpenProcess(0x1F0FFF, false, proccID);
UIntPtr baseAddress = (UIntPtr)procs[0].MainModule.BaseAddress.ToInt32() + 0x000506B4;
IntPtr readHandle = OpenProcess(0x0010, false, proccID);
byte[] bytes = new byte[24];
uint rw = 0;
uint size = sizeof(int);
ReadProcessMemory(pHandle, baseAddress, bytes, (UIntPtr)4, IntPtr.Zero);
string ownedcore = Encoding.UTF8.GetString(bytes);
txt.AppendText(ownedcore);
}
jo to uz mam vraci to string ale ne uplni, ako dam listener aby stale ked sa zmenia data, aby to znova oskenovalo ?
Budes muset skenovat dokola rucne.
no ak mam adresu ako z nej dostanem vsetok string? ako zistim velkost tych dat?
Zalezi na tom, jaky string to je.
Vetsina stringu konci bytem 0 - proste musis prochazet bajt po bajtu, dokud nenarazis na nulu, ale nekdy treba prvni bajt udava delku stringu.
ale z adresy sa neda nijako vicitam length jeho dat?
no stale mam s tym problemy, tu je moj akutalny kod(zrejme dost blby) vrati to sice string ale aj nejake cudne znaky, lebo neviem aku dlzku mam zadat do cyklu.
Process[] procs = Process.GetProcessesByName("PartyGaming");
int proccID = procs.Length == 0 ? 0 : procs[0].Id;
IntPtr pHandle = OpenProcess(0x1F0FFF, false, proccID);
byte[] bytes = new byte[4];
txt.Text = "";
for (int j = 0; j < 2500; j += 2)
{
ReadProcessMemory(pHandle, (UIntPtr)0x0636965C + j, bytes, (UIntPtr)4, IntPtr.Zero);
string ownedcore = Encoding.UTF8.GetString(bytes);
// txt.AppendText(ownedcore + "\n");
if(bytes[0] != 0)txt.AppendText(Convert.ToString(Convert.ToChar(bytes[0])));
}
Jakmile je bajt 0, mel bys prestat cist, ne jen ten znak vynechat a cist dal (pokud jsou to ty stringy ukonceny nulou).
Já měl teda zato, že string je pole charu a každé pole má na posledním
indexu 0
Tak jak to teda mam upravit som s toho jelen.
Vsak jo, ale ne uplne vzdy, treba ve starsich Delphi byl defaultni String takovy, ze prvni bajt oznacoval delku stringu a pak bylo pole charu (max. delka byla 255 znaku), ale byly samozrejme i jine String typy, ty umely vice znaku a zakonceni nulou.
Ten cyklus prepis na while a provadej ho, dokud nacteny bajt neni 0.
A taky ty dve 4 muzes prepsat na 1, nacitas vzdy ctyry bajty a ctes pak jen prvni, to je zbytecne.
tak skumal som to hlbsie v cheat engine, ale ta adresa kde sa uklada string sa meni priblizne raz za 2 sekundy, stale je ina a ina. To sa asi vyriesit neda ze? Ako by som mohol vybrat vsetky data z pamete procesu?
Vsechny data vyberes tak, ze ten cyklus nechas bezet od baseaddress tak
daleko, kam az jsou ulozeny data.
Problem je pak v tom, ze dostanes jen pole bajtu, nepoznas kde je ulozeny
string, kde cislo apod., takze bys v tom musel nejak vyhledavat ten retezec, ale
to nemusi bejt stoprocentni, pokud tam jsou treba vsechny retezce uz nekde
ulozeny (ale tenhle jeden retezec mozna bude v trochu jine
casti pameti, tak nejaka sance tu je).
String je pokazde jinde, protoze je dynamicky alokovany, nejspis se kazde 2
vteriny vytvori nova instance a uklada se pokazde nekam jinam na haldu.
Aby program mohl ten string pouzivat, tak adresa toho stringu nekde bude ulozena
v pameti jako ukazatel.
Reseni by bylo, ale uz by to chtelo aspon zakladni znalosti disassemblovani, musel bys najit v pameti misto, kde je ulozen ukazatel na ten string.
A pozor, aby to nebylo tak jednoduche, tak i to misto, kde je ulozen ten
ukazatel na string muze byt pokazde jine, techto zretezeni muze byt vic, proste
jde o to najit prvni ukazatel, ktery je vzdy na stejnem miste a kterym se
postupne dostanes az ke svemu stringu.
V nejhorsim pripade se dostanes az k mistu, ktere bylo v kodu nekde v metode
main() (nebo jeji obdobe).
ano, ten ten string sa tam ukaze a pak zmizi / alokuje sa, a pak se vytvory novy, no ale ani za boha neviem najst co ten string vytvara aka funkcia alebo dll
a nedal by sa vyhladat len textovy retazec v pameti procesu ? lebo sledoval som proces pomocou proces hacker a ten to stale krasne najde cely ten string co potrebujem
Netusim, jaky algoritmus ten program pouziva, mozna treba hleda pole znaku
ukoncene nulou, zacinajici na miste, kam nejaky ukazatel v pameti ukazuje a
obsahujici jen platne znaky (0x20 a vetsi + taby), to uz by byla docela velka
pravdepodobnost, ze to naslo platny string.
Nebo to treba i analyzuje strojovy kod, ale to uz jen spekuluji .
Ano, muzes nacist celou pamet a pak to prohledat, jestli tam neni ten retezec, ale mohl by tam byt treba ulozeny vicekrat (treba jednou seznam vsech retezcu, co se muzou zobrazit a jednu ten samotny retezec, ktery se ma zobrazit) apod., takze bys to musel treba kontrolovat, v ktere casti pameti jsi ho nasel.
Zkusit to kazdopadne muzes
Ktera funkce ten string vytvari se z binarky zjistuje vetsinou dost spatne
, casto tam vubec nejsou, po
prelozeni na strojak tam zustanou jen samotne instrukce a data, i kdyz nekdy se
tam daji najit nejake textove zbytky a da se podle toho neco identifikovat.
Zjistil bys to treba u .NET/Javy, kde se da ziskat z binarky zpatky cely kod.
Pokud ti to licence toho programu umoznuje , tak muzes zkusit se podivat na nej
treba programem OllyDbg.
Zajimava by pro tebe mohla byt treba funkce "Find all referenced strings", ktera
z exace vytaha vsechno, co povazuje za string (na ktery se nejaka cast kodu
odkazuje), pripadne pokud jsi odvazny , tak muzes zkusit debugovat a najit, kde se na ten string
odkazuje.
debug ten program neumoznuje, to som skusal, je totiz to dost zabezpeceny preto s tym je dost velky problem nieco tam najst ..., ale cez olly dbg najde tiez len akutalnu adresu, lebo totiz ono je to tak ak spustim program , a otvorim stol program vytovri dynamicky nove okno a prave z toho okna ja potrebujem citata data.
Debugovat muzes prave v Olly, jen samozrejme misto puvodniho jazyka se musis hrabat v assembleru.
Kazda ochrana se da obejit, jen to nekdy trva dele
Jinak pokud se vytvori okno, tak potrebujes najit, kde se v pameti vytvorilo to okno a pak dohledat ukazatel na Label (predpokladam, ze pro zobrazeni stavu pouzivaji Label) a u Labelu pak najit ukazatel na jeho Text.
este ma napadla moznost, ak je tak zlozite tahat z memory, ako by sa to dalo tahat priamo z klienta , pomocou hook by to neslo?
Co presne by jsi chtel hookovat?
Myslim, ze zadny typ zpravy by nebyl nejak relevantni pro tenhle pripad.
Mozna by ale slo odchytavat pakety a rozhodovat se na zaklade jich, pokud komunikace neprobiha pres SSL.
no napriklad ked som sledoval spravy z okna pomocou spy++ tak ich tam bolo
neuveritelne vela a boli medzi nimi dost stringov (ascii) plne citatelnych
tak mozno keby som sledoval vsetky spravy , tak mozno by stacilo odchytit urcity
typ spravy a nemusel by som to vselijakymi sposobmi hladat v memory. Len ze ako
sa zachytavaju spravy aj celkovy hook onom prave nic netusim. Ja som
programator(AS3,Air,Flex) a nie c# sice robil som uz aj v c# ale az tak dobre
ho nepoznam, hlavne preto pisem na forum aby sa mi dostalo rad a pomoci.Takze
velmi pekne ti dakujem Satik.
Vlastne by to pres messages mozna jit mohlo, ale s tim ti neporadim lip nez
google, messages jsem zachytaval naposledy nekde v Delphi pred davnou dobou
Neumi ten spy++ nejake filtrovani, ze by sis overil, jestli tam lita to, co potrebujes?
ne to nevie, mne by stacilo ako dam ten hook na okno, lebo ja si okno najdem, aj vsetky jeho handle mam,chcel som to pomocou cyklu vsetky jeho handle dat na nich hook a sledovat co sa deje a hladat tu potrebnu spravu
Pouziti hooku muzes zkusit okoukat treba tady
http://stackoverflow.com/…-application
tak nakoniec som sa vratil spet k pameti. . Idem na to ako debil
pravdepodobne.
tu je moj kod :
Process[] p = Process.GetProcessesByName("PartyGaming");
txt.AppendText(p[0].MainWindowTitle + "\n");
IntPtr appHandle = OpenProcess(0x1F0FFF, false, p[0].Id == 0 ? 0:p[0].Id);
string find = "Hand History";
byte[] buffer = new byte[sizeof(int)];
uint PTR = (uint)p[0].MainModule.BaseAddress;
int pocet = 0;
while (PTR != 0xFF000000)
{
buffer = new byte[sizeof(int)];
ReadProcessMemory(appHandle, (IntPtr)PTR, buffer, (UIntPtr)4, IntPtr.Zero);
string s = Encoding.UTF8.GetString(buffer);
if (s.IndexOf(find) != -1)
{
txt.AppendText(Encoding.UTF8.GetString(buffer) + "\n" + "found");
break;
}
PTR += 0x1;
pocet++;
s = "";
}
ked som to sputil okno uz nenabehlo . Ako to mozem zrychlit to prehladavanie pamete?
Necist ji po jednom bajtu, ale po vetsich blocich.
Ale zase to neprezen, kdyz nastavis vice nez 2048 bajtu, tak se ti vrati prazdny buffer.
A pole buffer nemusis pokazde vytvaret znova, staci ho vytvorit pred cyklem.
A preferoval bych nejdrive vse nacist do nejakeho velkeho pole bajtu (klidne nekolik desitek MB) a az po precteni pameti z toho najednou sestavit string a nejak to zpracovat.
Jo a asi nebudes potrebovat cist az do 0xFF000000, to je 4GB dat, tolik ten
proces asi nezabira
Pripadne muzes s pomoci funkce http://msdn.microsoft.com/…s.85%29.aspx zjistit, kde vsude
je program v pameti rozlezly.
takze ked som dal += 0x1 ( to se rovna 1 bajt?) ale ako? ked dam += 0x10 to budu 10 bajty? alebo ako to je?
PTR je jen adresa mista, odkud ctes.
Musis take zvetsit cteci buffer (pole, do ktereho nacitas blok dat) a u funkce readprocessmemory ten parametr, co mas ted 4, to je kolik bajtu chces precist.
Jinak cisla s 0x na zacatku jsou jen cisla zapsana hexadecimalne, takze 0x10 je jen jinak zapsana 16.
Process[] p = Process.GetProcessesByName("PartyGaming");
txt.AppendText(p[0].MainWindowTitle + "\n");
IntPtr appHandle = OpenProcess(0x1F0FFF, false, p[0].Id == 0 ? 0:p[0].Id);
List<IntPtr> children = GetAllChildrenWindowHandles(appHandle, 100);
// txt.Text = "";
// txt.AppendText(GetWindowTextRaw((IntPtr)0x0edc5d78) + "\n");
string find = "Hand History";
byte[] buffer = new byte[sizeof(int)];
uint PTR = (uint)p[0].MainModule.BaseAddress;
int pocet = 0;
while (PTR != 0xFF000000)
{
buffer = new byte[sizeof(int)];
ReadProcessMemory(appHandle, (IntPtr)PTR, buffer, (UIntPtr)1024, IntPtr.Zero);
string s = Encoding.UTF8.GetString(buffer);
txt.AppendText(Encoding.UTF8.GetString(buffer) + "\n" + "found");
PTR += 0x1;
pocet++;
s = "";
}
tak ked som zvecil to cislo tak mam stale problem zacne cyklus ale skonci errorom , kde moze byt chyba?
Musis zvetsit cislo na vsech 3 mistech, ted jsi jen zvetsil, kolik bajtu se
precte z pameti.
Musis zvetsit buffer, ted ctes 1024 bytu a snazis se to nacpat do bufferu
velkeho sizeof(int), coz jsou 4 bajty.
A i kdyby jsi cetl 4 bajty, tak ted ctes timhle zpusobem:
pokusny text ke cteni
a nactene sekvence:
poku
okus
kusn
usny
...
Coz asi nechces - musis PTR posouvat vic nez o jeden znak, kdyz jis jich
nacetl treba 1024
tak ich bude posuvat o tych 1024 ne?
Jen zopakuju to co napsal Satik. Čteš 1024B a snažíš se to narvat do 4B
- ten buffer musíš zvětšit na 1KB, aby se ti to tam vlezlo. Takže jen změn
velikost toho bufferu v inicializaci.
EDIT: jak se nato dívám, tak když načítáš 1KB tak i ten pointer si
posouvej o 1KB dopředu, takže ještě změň PTR+= 0x400
Jj, posun o 1024 znaku je idealni, kdyz ctes 1024 znaku .
Pokud bys posunoval jinak, nektere znaky by jsi nacetl vicekrat nebo nektere
vynechal
EDIT: mela to byt odpoved na Neaktivní uživatel
a ako zistim do kedy ten cyklus ma ist? da sa zistit velkost tej pouzivanej pamete procesu?
Uz jsem tu funkci posilal drive - VirtualQueryEx ti zjisti, kde cist a kde ne.
uzitecne odkazy:
http://msdn.microsoft.com/…s.85%29.aspx
http://msdn.microsoft.com/…s.85%29.aspx
cav chcem sa spytat ze ako sa da v cheat engine oznacit vsetky adresy na modro viem ze treba drzat neaku klavesu porad mi prosim
Zobrazeno 50 zpráv z 50.