Interceptar con Detours el Opengl nativo por TEB

Iniciado por 85, 9 Abril 2013, 20:50 PM

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

85

Primero que nada quiero decir que voy a postear el código fuente público de un hack de karman, llamado Inexinferis FX de finales del 2010.
Es un código ya publicado sólo que no se observa demasiado por internet XD

Lo posteo porque es parte de los métodos que se estaban comentando en el foro últimamente, y se trata de utilizar 'detours' pero a un nivel más profundo que el que ofrece Openg32.dll, siendo Opengl32.dll el nivel más alto y el driver de la tarjeta gráfica lo más bajo. Intermediamente se tiene otra DLL de relacionada con Opengl32 pero perteneciente a la firma de la tarjeta gráfica, pero el tema es que hay muchas marcas de tarjetas gráficas y por lo tanto muchos drivers. Por lo que cada uno sabe lo que tiene XD

Esta es la información que se necesita manejar para poder entender como se determinan las direcciones de bajo nivel para Opengl por medio de lo que se llama TEB (Thread Environment Block), también conocido como TIB (Thread Information Block) por algunos, aunque otros insisten en que el TIB es miembro del TEB (Ver link de undocumented.ntinternals.net).
http://es.wikipedia.org/wiki/Win32_Thread_Information_Block
http://en.wikipedia.org/wiki/Win32_Thread_Information_Block
http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/Thread/TEB.html

Otros links
http://www.snoxd.net/index.php/topic/377-finding-the-thread-id-from-the-executable-name/
http://www.alex-ionescu.com/part1.pdf
http://www.ciphermonk.net/teb.php
http://nasutechtips.blogspot.com.ar/2011/01/thread-information-block-tib-and-fs.html
http://skypher.com/wiki/index.php/Hacking/Windows_internals/Process/Memory/TEB
http://stackoverflow.com/questions/9964236/tib-access-in-win32
http://software.intel.com/sites/products/documentation/doclib/stdxe/2013composerxe/compiler/cpp-win/GUID-F90BD123-AE25-4DC2-ADFB-B59067E77728.htm

Otros links que se pueden tomar en cuenta
http://www.nynaeve.net/?p=180
http://msdn.microsoft.com/es-ar/library/6yh4a9k1.aspx
http://msdn.microsoft.com/en-us/library/6yh4a9k1.aspx
http://msdn.microsoft.com/es-ar/library/y6h8hye8.aspx
http://msdn.microsoft.com/es-ar/library/2s9wt68x.aspx


En Opengl32.DLL básicamente se encuentran funciones que sólo hacen saltos hacia el nivel más bajo de Opengl, y para obtener las direcciones correctas del driver, se hace con este método del TEB.

Este es el ejemplo de glBegin

Citar
Pos: FS:[0x18]      Len: 4   Ver: Win9x y NT   -> Dirección lineal del TIB

con esos parámetros se consigue hacer un salto hacia el nivel bajo del que hablábamos (nvoglnt.dll en mi caso que tengo una tarjeta NVIDIA)


Luego hace otro salto hacia la función en sí.
Con OllyDBG se puede observar el estado de los registros para tener una mejor idea de como se obtienen las direcciones.
Mejor aún, para aquellos que prefieren leer una buena explicación les dejo este manual al respecto:
http://www.mediafire.com/?kmru385gmmcik46

Código (cpp) [Seleccionar]

//

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

#pragma comment(lib,"OpenGL32.lib")
#pragma comment(lib, "Version.lib")
#define _WIN32_WINNT 0x0500
#undef UNICODE
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <shlwapi.h>
#include <stdio.h>

#include "nt.h"

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

HANDLE hThread=NULL;
PBYTE dwFSBase,dwFSBase2;

HWND hdHalfLife;

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

typedef void (APIENTRY* glBlendFunc_t)(GLenum,GLenum);
typedef void (APIENTRY* glClear_t)(GLbitfield);
typedef void (APIENTRY* glVertex2f_t)(GLfloat,GLfloat);
typedef void (APIENTRY* glVertex3f_t)(GLfloat,GLfloat,GLfloat);
typedef void (APIENTRY* glVertex3fv_t)(const GLfloat*);
typedef void (APIENTRY* glBegin_t)(GLenum);
glBlendFunc_t pglBlendFunc=0;
glClear_t pglClear=0;
glVertex2f_t pglVertex2f=0;
glVertex3f_t pglVertex3f=0;
glVertex3fv_t pglVertex3fv=0;
glBegin_t pglBegin=0;

BOOL bFlash=FALSE;
BOOL bSky=FALSE;

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

void APIENTRY New_glBegin(GLenum mode){

if(mode==GL_TRIANGLE_STRIP||mode==GL_TRIANGLE_FAN)
glDisable(GL_DEPTH_TEST);
else if(mode!=GL_QUADS&&mode!=GL_LINES)
glEnable(GL_DEPTH_TEST);

if(mode==GL_QUADS){
float col[4];
       glGetFloatv(GL_CURRENT_COLOR, col);
       bFlash=(col[0]==1.0&&col[1]==1.0&&col[2]==1.0&&col[3]>0.2);
bSky=TRUE;
   }
else
bSky=FALSE;
pglBegin(mode);
}

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

void APIENTRY New_glClear(GLbitfield mask){

if(mask==GL_DEPTH_BUFFER_BIT){
mask+=GL_COLOR_BUFFER_BIT;
glClearColor(0.0f,0.0f,0.0f,0.0f);
}
pglClear(mask);
}

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

void APIENTRY New_glVertex3fv(const GLfloat* v){

if(bSky) return;
pglVertex3fv(v);
}

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

void APIENTRY New_glVertex2f(GLfloat x, GLfloat y){

if(bFlash&&x==0.0&&y==0.0) glColor4f(1.0f,1.0f,1.0f,0.2f);
   pglVertex2f(x,y);
}

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

void APIENTRY New_glVertex3f(GLfloat x, GLfloat y, GLfloat z){

glColor3f(1.0f,1.0f,1.0f);
pglVertex3f(x,y,z);
}

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

BOOL GetDllVersion(HMODULE hLibModule, DLLVERSIONINFO* aVersion){
 
   CHAR fileName[MAX_PATH];
   UINT len=0;
   VS_FIXEDFILEINFO* vsfi=NULL;
   DWORD handle=0;
   DWORD size=GetModuleFileName(hLibModule,fileName,MAX_PATH);
   fileName[size]=0;
   size=GetFileVersionInfoSize(fileName, &handle);
   BYTE* versionInfo=new BYTE[size];
   if(!GetFileVersionInfo(fileName,handle,size,versionInfo)){
delete[] versionInfo;
       return FALSE;
   }
   VerQueryValue(versionInfo,"\\",(PVOID*)&vsfi,&len);
   aVersion->dwMajorVersion=HIWORD(vsfi->dwFileVersionMS);
   aVersion->dwMinorVersion=LOWORD(vsfi->dwFileVersionMS);
   aVersion->dwBuildNumber=HIWORD(vsfi->dwFileVersionLS);
   aVersion->dwPlatformID=LOWORD(vsfi->dwFileVersionLS);
   delete[] versionInfo;
   return TRUE;
}

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

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);
}

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

/*
DWORD GetProcessThreadId(unsigned long ProcessId)
{
   HANDLE hSnapThread = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, ProcessId);
   if(hSnapThread == INVALID_HANDLE_VALUE) return NULL;
   THREADENTRY32 te;
   te.dwSize = sizeof(THREADENTRY32);
   if(Thread32First(hSnapThread, &te))
   {
      do
      {
           if(te.th32OwnerProcessID == ProcessId) {
               CloseHandle(hSnapThread);
               return te.th32ThreadID;
           }

      } while(Thread32Next(hSnapThread, &te));
   }
   CloseHandle(hSnapThread);
   return 0;
}*/

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

DWORD WINAPI Thread(LPVOID lpParam){

   DWORD dwThreadId,dwProcessId,dwOGLOffset;
   CONTEXT Context;
   LDT_ENTRY SelEntry;
   HMODULE hModule;
   Context.ContextFlags=CONTEXT_FULL|CONTEXT_DEBUG_REGISTERS;
   DWORD dwTLSIndex=0;
   DLLVERSIONINFO oglVersion;

   while(((hdHalfLife=FindWindow("Valve001",NULL))==NULL)
             &&((hdHalfLife=FindWindow(NULL,"Counter-Strike"))==NULL))
                     Sleep(100);

   while((hModule=GetModuleHandle("Opengl32.dll"))==NULL)
             Sleep(100);

   if(GetDllVersion(hModule,&oglVersion)){

       if(oglVersion.dwMajorVersion==5&&oglVersion.dwMinorVersion==1){
           dwTLSIndex=0xAC80C;
}
else if(oglVersion.dwMajorVersion==6&&oglVersion.dwMinorVersion==0){
           dwTLSIndex=0xAB958;
}
else if(oglVersion.dwMajorVersion==6&&oglVersion.dwMinorVersion==1){
           dwTLSIndex=0xA100C;
}
       else
       {
            //MessageBox(hdHalfLife,"Incompatible OpenGL Version...\n\nSorry man...","Inexinferis FX Series - Karman",0);
           ExitThread(0);
           return 0;
       }
   }
   else
   {
       //MessageBox(hdHalfLife,"Can't Get OpenGL Version...\n\nWrong OpenGL???","Inexinferis FX Series - Karman",0);
ExitThread(0);
       return 0;
   }

   //DWORD ProcessId = GetCurrentProcessId();
   //DWORD ProcessThreadId = GetProcessThreadId(ProcessId);
   dwThreadId=GetWindowThreadProcessId(hdHalfLife,&dwProcessId);
   HANDLE hThread=OpenThread(THREAD_GET_CONTEXT|THREAD_SUSPEND_RESUME|THREAD_QUERY_INFORMATION,FALSE,dwThreadId);

   if(!hThread){
       //MessageBox(hdHalfLife,"Couldn't Get Proccess Info...\n\nAntivirus???","Inexinferis FX Series - Karman",0);
       CloseHandle(hThread);
       ExitThread(0);
       return 0;
   }

   GetThreadContext(hThread,&Context);
   GetThreadSelectorEntry(hThread, Context.SegFs, &SelEntry);
   dwFSBase = (PBYTE)((SelEntry.HighWord.Bits.BaseHi<<24)|(SelEntry.HighWord.Bits.BaseMid<<16)|SelEntry.BaseLow);

   if(!dwFSBase||IsBadReadPtr((PVOID)dwFSBase,sizeof(DWORD))){
       //MessageBox(hdHalfLife,"Couldn't Get TEB From Opengl32.dll\n\nMake Sure that you are Running the Game in OpenGl Mode...","Inexinferis FX Series - Karman",0);
       CloseHandle(hThread);
       ExitThread(0);
       return 0;
   }

   dwOGLOffset=((DWORD)hModule)+dwTLSIndex;
   if(!dwTLSIndex||IsBadReadPtr((PVOID)dwOGLOffset,sizeof(DWORD))){
       //MessageBox(hdHalfLife,"Couldn't Read From Opengl32.dll Address\n\nMaybe your OpenGL driver is not compatible...","Inexinferis FX Series - Karman",0);
      CloseHandle(hThread);
      ExitThread(0);
      return 0;
   }
   //multiple redirect...
   do{
          Sleep(10);
          dwFSBase2=(PBYTE)(*(PDWORD)((DWORD)dwFSBase+(*(PDWORD)dwOGLOffset)));
   }while(dwFSBase2==NULL);

/*
  dwFSBase2=(PBYTE)(*(PDWORD)((DWORD)dwFSBase+(*(PDWORD)0x5F1CC80C)));
  if(!dwFSBase2){
      CloseHandle(hThread);
      ExitThread(0);
      return 0;
  }*/

               


  //MessageBox(hdHalfLife,"http://www.inexinferis.com.ar/foro","Inexinferis FX Series - Karman",0);
  SuspendThread(hThread);

  ////////
  // Hooks

  // 0x01D46862  opengl32.glClear [EAX+32C] -> 0x69609A20 [12]
  pglClear= (glClear_t)Detour1((PBYTE)(*(PDWORD)(dwFSBase2+0x32C)),(PBYTE)New_glClear,12);
   
  // 0x01D3CF1D  opengl32.glVertex2f [EAX+92C] -> 0x69606320 [12]
  pglVertex2f= (glVertex2f_t)Detour1((PBYTE)(*(PDWORD)(dwFSBase+0x92C)),(PBYTE)New_glVertex2f,12);
   
  pglVertex3f= (glVertex3f_t)Detour1((PBYTE)(*(PDWORD)(dwFSBase+0x94C)),(PBYTE)New_glVertex3f,12);
   
  // 0x01D936C5 opengl32.glVertex3fv [EAX+950] -> 0x696073F0 [12]
  pglVertex3fv= (glVertex3fv_t)Detour1((PBYTE)(*(PDWORD)(dwFSBase+0x950)),(PBYTE)New_glVertex3fv,12);
   
  // 0x01D93681 opengl32.glBegin [EAX+7CC] -> 0x695FD250 [8]
  pglBegin= (glBegin_t)Detour1((PBYTE)(*(PDWORD)(dwFSBase+0x7CC)),(PBYTE)New_glBegin, 8);

   ////////

   ResumeThread(hThread);
   CloseHandle(hThread);

   ExitThread(0);
   return 0;
}

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

BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, LPVOID lpvReserved){
 
if(fdwReason==DLL_PROCESS_ATTACH){
   
DisableThreadLibraryCalls(hInstance);
hThread=CreateThread(NULL,0,Thread,NULL,0,NULL);
}
return (TRUE);
}

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



PROYECTO MS Visual C++ 2010 Express
http://www.mediafire.com/?yttdt8712ymvj2r
Me cerraron el Windows Live Spaces, entonces me creé un WordPress XD
http://etkboyscout.wordpress.com/

BloodSharp




85

#2
Dejo un par de links más
http://www.codeproject.com/Articles/29174/Win32-TIB
http://www.microsoft.com/msj/archive/s2ce.aspx

http://www.gamedeception.net/threads/8866-TIB-Opengl-hooking
Y esto lo saqué de gamedeception (2ci- y Organner), es otro intento.. aunque sino no da los resultados que se esperan, mejor obtener un puntero al selector FS del hilo creador de la ventana, y después hacer [eax+OFFSET] tal como en Opengl32.dll. No hay TIB específico para Opengl32, sino más bien es el TIB del hilo en el que se llama a Opengl32.

Código (cpp) [Seleccionar]

typedef void(__stdcall* t_glBegin)(GLenum);
t_glBegin pOrig_glBegin = NULL;

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

void __stdcall HOOK_glBegin(GLenum mode)
{
static bool once=false;
if(!once){

printf("\n");
printf("DLL -> HOOK_glBegin!\n");
system("pause");
once=true;
}

(*pOrig_glBegin)(mode);
}

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

DWORD* OGL_GetFuncForOffset( DWORD dwTIBOffset )
{
DWORD* retval=0;
__asm {
mov eax, fs:[0x18]; // TIB
add eax, dwTIBOffset;
mov eax, [eax]
mov retval, eax
}
return retval;
}

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

bool OGL_IsOffsetHooked( DWORD dwTIBOffset, DWORD* dwOriginal, DWORD* dwHook )
{
return( OGL_GetFuncForOffset( dwTIBOffset ) == dwHook );
}

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

void OGL_HookTIB( DWORD dwTIBOffset, DWORD* dwOriginal, DWORD* dwHook )
{
if( OGL_IsOffsetHooked( dwTIBOffset, dwOriginal, dwHook ) ){
return;
}

__asm {
mov eax, dword ptr fs:[0x18]; // TIB
add eax, dwTIBOffset; // add offset needed
mov ecx, [eax] // get the function offset
mov ebx, [dwOriginal] // grab addr of original
mov [ebx], ecx; // move it into our pointer
mov ecx, dwHook; // move offset of our hook into ecx
mov [eax], ecx; // move ecx into opengl's info space
}
}

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

#define ofs_glBegin     0x7CC
#define ofs_glVertext3f 0x94C
#define ofs_glPopMatrix 0x9E4

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

DWORD dwReplaceDriverAddress(DWORD dwIndex, DWORD dwNewFunction)
{
   DWORD* dwTIB = NULL;
DWORD teb=0;
PTEB myTEB;

      __asm
      {
           mov eax, dword ptr fs:[18h]
           add eax, dwIndex
           mov dwTIB, eax
           mov myTEB,eax
      }

printf("myTEB 0x%X\n",myTEB);
printf("dwIndex 0x%X\n",dwIndex);
printf("dwTIB 0x%X\n",dwTIB);
printf("*dwTIB 0x%X\n",*dwTIB);
printf("dwNewFunction 0x%X\n",dwNewFunction);
system("pause");

       DWORD g_dwReturnValue = *dwTIB;
       //*dwTIB = dwNewFunction;
       //printf("*dwTIB 0x%X\n",*dwTIB);
       return g_dwReturnValue;
}

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

void thread(){

while(1){

if(GetModuleHandle("opengl32.dll")){

pOrig_glBegin = (t_glBegin)dwReplaceDriverAddress(ofs_glBegin,(DWORD)HOOK_glBegin);

if(pOrig_glBegin){

   printf("pOrig_glBegin 0x%X\n",pOrig_glBegin);
   system("pause");
}
break;
}

Sleep(300);
}
}

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

BOOL APIENTRY DllMain(HINSTANCE i, DWORD reason, LPVOID res){

if(reason == DLL_PROCESS_ATTACH){

if(GetModuleHandle("opengl32.dll")){

pOrig_glBegin = (t_glBegin)dwReplaceDriverAddress(ofs_glBegin,(DWORD)HOOK_glBegin);

if(pOrig_glBegin){
   printf("pOrig_glBegin 0x%X\n",pOrig_glBegin);
   system("pause");
}
}

//CreateThread(0,0,(unsigned long (__stdcall *)(void *))thread,0,0,0);
}
return (true);
}


PS: Ese código la sarpa, parece un multihack XD.. y tiene la librería de karman IntelliAPIHooking, nice  >:D
Me cerraron el Windows Live Spaces, entonces me creé un WordPress XD
http://etkboyscout.wordpress.com/

Luchoz95

Esta buenisimoooo mira lo que pude haceer ..