Eli kuinka saan hookattua (koukutettua?) oman ohjelmani kaikkiin OpenGL-ohjelmiin? Haluaisin siis, että aina, kun ohjelma kutsuu SwapBufferssia, niin samalla se kutsuisi myös omaa SwapBufferssiani. Tarkoitus olisi aluksi tehdä perus FPS-counter ja sen jälkeen nauhoitusohjelma. Tiedän, että on mahdollista ja olen jopa löytänyt koodeja, jotka toimivat nauhoittajina, mutta en saa selvää, mitkä kohdat ovat hookkauksen kannalta oleellisia. Olisiko jollain täysin riisuttu ohjelma, joka tekee vain ja ainoastaa hookkauksen kaikkii OpenGL-ohjelmiin?
Edit. Windowsille olisi tarkoitus, muttei Linux-versiokaan haittaa
http://research.microsoft.com/en-us/projects/detours/
Materiaalia netti pullollaan. Suosittelen kääntymään http://www.gamedeception.net/ foorumin puoleen. Tuolla on myös paljon tutoriaaleja, sekä täysin valmiita pohjia. Etsi tuolta gd:stä ohjelma nimeltä winject ja käytä dll injektointia näin alkuun.
Luin vähän Wikipediasta. Ymmärtääkseni pitäisi tietää ohjelman osoitin. Mistäs saan kaikkien OpenGLää käyttävien ohjelmien osittimet talteen? Sen jälkeen pitäsisi onnistua.
Jos asenne on tuo, niin kannattaa varmaan jättää koko homma väliin ja tyytyä Frapsiin. Et tarvitse kaikkien OpenGL käyttävien ohjelmien osoitteita talteen, vaan tähän on ihan fiksukin ratkaisu. Pienellä oma-aloitteisuudella ja viitseliäisyydellä olisit jo tehnyt tuon ohjelmasi.
Luin vähän wikipediasta, jos joku kertoisi miten tienaan miljoonan minuutissa niin minun pitäisi rikastua.
Olen kyllä yrittänyt etsiä netistä, mutta ei ole osunut silmiin koodia, jonka saisin toimimaan. Todennäköisesti vika on minussa. Olen uusi näiden WinAPI:den ja dll injektion kanssa, joten voiko jo käynnissä olevan prosessin injektoida? Tässä koodia, josta joku saisi kertoa, missä vika:
bool DLLInjektoi(DWORD dwPid, char *DllPath) { HANDLE hProc; DWORD dwMemSize; LPVOID lpRemoteMem, lpLoadLibrary; BOOL ret = FALSE; if ((hProc = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD, FALSE, dwPid)) != NULL) { std::cout << "Vaihe 1: Suoritettu" << std::endl; dwMemSize = strlen(DllPath) + 1; if ((lpRemoteMem = VirtualAllocEx(hProc, NULL, dwMemSize, MEM_COMMIT, PAGE_READWRITE)) != NULL) { std::cout << "Vaihe 2: Suoritettu" << std::endl; if (WriteProcessMemory(hProc, lpRemoteMem, (LPCVOID) DllPath, dwMemSize, NULL)) { std::cout << "Vaihe 3: Suoritettu" << std::endl; // Pääse tähän saakka ja GetProcAddress:kin toimii lpLoadLibrary = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA"); if (CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE) lpLoadLibrary, lpRemoteMem, 0, NULL) != NULL) { std::cout << "Vaihe 4: Suoritettu" << std::endl; ret = TRUE; } } } } CloseHandle(hProc); return false; } int main(int argc, const char* argv[]) { #define DLL_PATH "D:\\...\\OGL_FPS_Dll.dll" std::cout << DLLInjektoi(2436 /*Otettu Tehtävienhallinnasta*/, DLL_PATH) << " " << GetLastError() << std::endl; std::cin.get(); return 0; }
Koodi on kopioitu tästä videosta: http://www.youtube.com/watch?v=H3O3hmXkt1I
Niin ja koodi tulostaa "0 0"
Koodin tulostus voisi olla kiinnostavampi, jos palauttaisit funktiosta joskus muutakin kuin falsen ja jos kutsuisit GetLastError-funktiota heti virheen jälkeen etkä vasta CloseHandlen jälkeen.
Ei tuosta "mielenkiintoisesta" tulostuksesta ollut tarkoituskaan katsoa muuta kuin GetLastErrorin koodi. Tässä näkee tietouteni WinAPI:sta, kun yritin kutsua GetLastErroria toisen funktion jälkeen. No, laitoin sen tuonne väliin ja tulostaa 5.
Edit. Koodi tulostaa nuo vaiheet kolmeen saakka. Eikä paljoa sano, että virhe on "Access Denied".
Anna OpenProcessille PROCESS_ALL_ACCESS.
Jostain kumman syystä sekään ei auta :(
if ((hProc = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD | PROCESS_ALL_ACCESS, FALSE, dwPid)) != NULL) // Eikä if ((hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid)) != NULL)
Molemmat tulostavat saman virheen.
Koodi toimii minulla, kunhan käyttää PROCESS_ALL_ACCESSia. Et voi injektoida 32-bittisestä prosessista 64-bittiseen tai toisin päin. Et voi myöskään injektoida esimerkiksi järjestelmänvalvojan oikeuksilla pyörivään prosessiin, jos ohjelmaasi ei ajeta yhtä korkeilla oikeuksilla.
Kiitos paljon Deffi. Juuri tuo bittisyys oli vialla. Eipä olisi kyllä millään tullut mieleen, mutta nyt toimii. Kiitos myös muille vastanneille. Tästä dll-injektiosta voisi myös olla aihetta koodivinkiksi, jos joku jaksaa tehdä :)
Aihe on jo aika vanha, joten et voi enää vastata siihen.