Interceptar Opengl32 con Detours y obtener un WH

Iniciado por 85, 9 Abril 2013, 19:29 PM

0 Miembros y 1 Visitante están viendo este tema.

85

Para terminar de redondear el tema de interceptar Opengl32 usando detours, muestro una pequeña base para crear un WH, utiliza una función personalizada para instalar un hook del tipo DETOUR.
Habíamos visto en otros tutoriales como se hace, y que se trata de una técnica intrusiva porque requiere parchear la memoria (código) del proceso víctima.
http://foro.elhacker.net/programacion_cc/detours-t168884.0.html
No tiene nada que ver con otros tutoriales que muestran como se modifican los valores de algunos punteros que corresponden a datos en el proceso.
Ej: http://foro.elhacker.net/programacion_cc/codigo_fuente_cheat_cs_16-t387341.0.html

Dejo el código funcional y el proyecto para descargar como siempre, dejo unas imágenes..

En este caso para diferenciarnos de otros tutoriales, explico la forma en que se puede cargar esta DLL en el proceso "hl.exe" que corresponde al juego Counter-Strike.

Se trata de ir a la carpeta del juego, y buscar una DLL de las que sabemos que no son necesarias en el juego pero de todas formas son cargadas al proceso.
Hay otras DLLs que son cargadas y algunas de sus funciones o todas, son utilizadas en el proceso, por lo que no se puede quitarlas, sino más bien hacer un 'wrapper' de ellas. Pero no quitarlas.

Vamos a ver una DLL que si la podemos quitar que se llama "DemoPlayer.dll". Vamos a quitarla y poner nuestra DLL con el WH en su lugar. Obviamente la tenemos que renombrar a "demoplayer.DLL" si es que no tiene ese nombre toda via.





Al final quiero decir que los sistemas de seguridad suelen escanear en la memoria, por ejemplo los primeros 5 bytes de algunas funciones para determinar si tienen 'detours'.
Pero a veces hacen otras comprobaciones como CRC32 de toda una función, o quien sabe que otras comprobaciones.. el tema es que este es un método intrusivo.

Código (cpp) [Seleccionar]


//
// Modifications: By 85
// Credits: gamedeception (detour function), SharkBoy999 base
// elhacker.net
// etalking.com.ar
// david_bs@live.com
// 2013
//

///////////////////////////////////////////////////////////////////////////////////////

#pragma comment(lib,"OpenGL32.lib")
#include <windows.h>
#include <gl/gl.h>
#include <tlhelp32.h>
#include<stdio.h>

///////////////////////////////////////////////////////////////////////////////////////

#define wallhack_key     GetAsyncKeyState(VK_NUMPAD1) &1
#define lambert_key GetAsyncKeyState(VK_NUMPAD2) &1
#define nosmoke_key GetAsyncKeyState(VK_NUMPAD3) &1
#define noflash_key GetAsyncKeyState(VK_NUMPAD4) &1

bool wallhack = true;
bool lambert = true;
bool nosmoke = true;
bool noflash = true;

bool bDrawingSmoke = false;
bool bDrawingFlash = false;

///////////////////////////////////////////////////////////////////////////////////////

typedef FARPROC (APIENTRY* GetProcAddress_t)(HMODULE, LPCSTR);
typedef void (APIENTRY* glBegin_t)(GLenum mode);
typedef void (APIENTRY* glViewport_t)(GLint x, GLint y, GLsizei width, GLsizei height);
typedef void (APIENTRY* glVertex3fv_t)(const GLfloat* v);
typedef void (APIENTRY* glVertex2f_t)(GLfloat,GLfloat);

///////////////////////////////////////////////////////////////////////////////////////

GetProcAddress_t pGetProcAddress = 0;
glBegin_t pglBegin;
glViewport_t pglViewport;
glVertex3fv_t pglVertex3fv;
glVertex2f_t pglVertex2f;

///////////////////////////////////////////////////////////////////////////////////////

void toggle(bool var)
{
   var = !var;
}

///////////////////////////////////////////////////////////////////////////////////////

void* Detour1(BYTE* src, const BYTE* dst, const int len)
{
BYTE* jmp = (BYTE*)malloc(len+5);
DWORD dwback;
while(!VirtualProtect(src, len, PAGE_READWRITE, &dwback));
memcpy(jmp, src, len);jmp+=len;
jmp[0] = 0xE9;
*(DWORD*)(jmp+1)=(DWORD)(src+len-jmp)-5;
src[0] = 0xE9;
*(DWORD*)(src+1)=(DWORD)(dst-src)-5;
while(!VirtualProtect(src, len, dwback, &dwback));
return (jmp-len);
}

///////////////////////////////////////////////////////////////////////////////////////

FARPROC APIENTRY new_GetProcAddress(HMODULE hModule, LPCSTR lpProcName)
{
//FARPROC fpResult = (*pGetProcAddress)(hModule, lpProcName);
FARPROC fpResult = pGetProcAddress(hModule, lpProcName);
if(HIWORD(lpProcName))
{
if(!lstrcmp(lpProcName,"GetProcAddress"))
return((FARPROC)&new_GetProcAddress);
}
return fpResult;
}

///////////////////////////////////////////////////////////////////////////////////////

void APIENTRY new_glBegin(GLenum mode)
{
if(wallhack)
{
if(mode == GL_TRIANGLE_STRIP || mode == GL_TRIANGLE_FAN)
glDepthRange( 0, 0.5 );
else
glDepthRange( 0.5, 1 );
}

if(lambert)
{
if(mode == GL_TRIANGLE_STRIP || mode == GL_TRIANGLE_FAN)
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
}

if(nosmoke)
{
if(mode==GL_QUADS)
{
GLfloat curcol[4];
glGetFloatv(GL_CURRENT_COLOR, curcol);
if(mode==GL_QUADS
&& (curcol[0]==curcol[1])
&& (curcol[0]==curcol[2])
&& (curcol[0]!=0.0)
&& (curcol[0]!=1.0))
{
bDrawingSmoke = true;
}
else
bDrawingSmoke = false;
}
}

if(noflash)
{
GLfloat color[4];
glGetFloatv(GL_CURRENT_COLOR, color);
if(mode == GL_QUADS && (color[0]==1 && color[1]==1 && color[2]==1) )
{
bDrawingFlash = true;
}
else
bDrawingFlash = false;
}
pglBegin(mode);
}

///////////////////////////////////////////////////////////////////////////////////////

void APIENTRY new_glViewport(GLint x, GLint y, GLsizei w, GLsizei h)
{
if(wallhack_key)
toggle(wallhack);
if(lambert_key)
toggle(lambert);
if(nosmoke_key)
toggle(nosmoke);
if(noflash_key)
toggle(noflash);
pglViewport(x,y,w,h);
}

///////////////////////////////////////////////////////////////////////////////////////

void APIENTRY new_glVertex3fv(const GLfloat* v)
{
if(bDrawingSmoke)
return;

pglVertex3fv(v);
}

///////////////////////////////////////////////////////////////////////////////////////

void APIENTRY new_glVertex2f(GLfloat x,GLfloat y)
{
/* if (bDrawingFlash)
{
GLfloat color[4];
glGetFloatv(GL_CURRENT_COLOR, color);
//color[0]=0, color[1]=0, color[2]=0;
glDisable(GL_TEXTURE_2D);
glColor4f(color[0], color[1], color[2], 0.01f);
}*/
pglVertex2f(x,y);
}

///////////////////////////////////////////////////////////////////////////////////////

void Hook(void)
{
pglBegin =        (glBegin_t)       Detour1((LPBYTE)glBegin,       (LPBYTE)new_glBegin, 6);
pglViewport =     (glViewport_t)    Detour1((LPBYTE)glViewport,    (LPBYTE)new_glViewport, 7);
pglVertex3fv =    (glVertex3fv_t)   Detour1((LPBYTE)glVertex3fv,   (LPBYTE)new_glVertex3fv, 6);
pglVertex2f =     (glVertex2f_t)    Detour1((LPBYTE)glVertex2f,    (LPBYTE)new_glVertex2f, 6);
}

///////////////////////////////////////////////////////////////////////////////////////

bool APIENTRY DllMain(HANDLE hModule, DWORD  dwReason, LPVOID lpReserved)
{
if(dwReason == DLL_PROCESS_ATTACH)
{
// No es necesario este Detour para la demostración..
pGetProcAddress = (GetProcAddress_t)Detour1((LPBYTE)GetProcAddress,
(LPBYTE)new_GetProcAddress, 5);

if(GetModuleHandle("Opengl32.dll"))
Hook();
}
else if(dwReason == DLL_PROCESS_DETACH)
{
// Restaurar bytes en GPA

// (no hace falta suspender el mismo hilo! no sirve para nada XD)

// Salida con retardo.
// Permite que se ejecuten los últimos llamados a GPA
// (Y no hace falta restaurar los bytes parcheados XD)
ExitProcess(100);
}
return (true);
}

///////////////////////////////////////////////////////////////////////////////////////



otra cosa que quiero agregar, es que el 'hook' a GetProcAddress no es necesario, pero está hecho y sirve para demostrar algo importante.

cuando salimos del juego, osea del proceso, antes se descargan las DLLs entre otras cosas, pero cuando se descarga nuestra DLL la memoria del proceso continua parcheada (los hooks que instalamos), y las referencias a los hooks son inválidas ya que la DLL se ha descargado.

Esto no importa para Opengl32 porque nadie va a utilizar Opengl32 al salir, pero con GetProcAddress si pasa esto. Por eso se debería considerar restaurar los bytes parcheados en GetProcAddress, o más fácil es hacer que la DLL se descargue cuando ya no sea necesaria (cuando no se haga más referencia a los hooks). Con un ExitProcess(100) queda resuelto, en realidad no investigué acerca de este tema, sólo traté de arreglarlo de alguna forma. Pero es un detalle a considerar.

PROYECTO
http://www.mediafire.com/?qfb65fsfgaf5doa

Me cerraron el Windows Live Spaces, entonces me creé un WordPress XD
http://etkboyscout.wordpress.com/

Luchoz95

puede ser que los GetAsyncKeyState no funcionen? lo probe y no me andubo

85

#2
Si eso estaba en el código original de SharkBoy999, no lo quité pero eso no funciona así, es decir vos comprobás si GetAsyncKeyState es diferente de 0, ya que la especificación de la MSDN dice que si el bit más significativo es 1 es que la llave está presionada, y dice que no se tome en cuenta otros comportamientos, por lo tanto no hace falta usar máscara de bits, sólamente comprobando que no sea 0 es suficiente.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms646293(v=vs.85).aspx


EDIT: XD aparte la función 'toggle' es cualquier cosa , es decir no le des bola al resto del código porque pertenece a la base de SharkBoy999, es un man que hizo un par de hacks en el pasado y siempre que publicaba códigos lo hacía poniendo errores para que no los compile cualquiera o para que no funcionen. Lo mismo hacían muchos otros.

Es decir, concentráte en el método del HOOK

Saludos
Me cerraron el Windows Live Spaces, entonces me creé un WordPress XD
http://etkboyscout.wordpress.com/

Luchoz95

jaja ! bueno me quedaba esa duda ! , dale voy a concentrarme en eso, excelente aporte 85!

Saludos!

85


Este es un ejemplo de uso también.. lo busqué en Google  :P

#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

if( KEY_DOWN(VK_LBUTTON) ){
keybd_event( VK_LBUTTON, 0, KEYEVENTF_KEYUP, 0 );
}


0x8000 = SHRT_MAX
http://www.cplusplus.com/reference/climits/

Lo que podés hacer es usar un hilo aparte para detectar las llaves, y usar una variable global por ejemplo para comprobar en alguna de las funciones de Opengl32. En los hacks se usa un sistema de variables de control, pero es otro tema ya que no se utiliza GetAsyncKeyState sino que hay una función del juego que sirve para obtener información de llaves presionadas.
Me cerraron el Windows Live Spaces, entonces me creé un WordPress XD
http://etkboyscout.wordpress.com/