mercredi 19 mars 2014

[Tutorial] New method for advanced menu topic




After being bombarded by an old friend to get back into game hacking. I came back out of retirement with some fresh ideas.

With this return, I wanted to have one the snazziest menu available. While putting in the minimal amount of work possible.




The idea is simple. Structure with HTML, style with CSS, animate and function with JavaScript. Things I already do on a daily basis for a living.

The menu "emulator" is a C# executable with a WebBrowser control. The emulator reads the live elements and stores their values in a settings file.

The emulator is run from a dll that then waits for the emulator to message that it is ready. By enumerating the child windows, I was able to get down to the Internet Explorer window that was embedded inside my application.

Using PrintWindow() and a HBITMAP variable. I am able to stream the browser into a LPDIRECT3DTEXTURE9 variable which is then drawn as a sprite.

Since the bytes are read or displayed in reverse, I used D3DXMatrixTransformation2D() to flip the image right side up.

Using GetCursorPos() and GetAsyncKeyState(), I tracked and then sent the mouse input from the game to the browser using SendMessage().

I essentially made a quick in game browser that only displays my menu.
With this method, I can add options instantly and even create elaborate controls without having to deal with the difficult and painful process of prim and sprite elements.

I haven't cleaned up the code, its available for anyone who wants to skim it


PHP Code:







void CaptureWindow(HWND hWnd, RECT clientRect, DWORD* pResult, DWORD size, bool image)
{
   
int bits;
   
   
HDC clientDC,
       
memoryDC;
   
   
BYTE* pAddress;

   
DWORD* pRet;
   
   
HBITMAP hBitmap;

    
BITMAPINFO bmpInfo;

   
   
bits = 32;
   
pRet = 0;
   
    
BITMAPFILEHEADER bfHeader = 
   { 
      
0x4D42, 
      
0, 
      
0, 
      
0, 
      
sizeof(BITMAPFILEHEADER) + sizeof( BITMAPINFOHEADER) 
   };

    
BITMAPINFOHEADER biHeader = 
   {
      
sizeof( BITMAPINFOHEADER ),
        
clientRect.right,
        
clientRect.bottom,
        
1,
        
bits,
        
BI_RGB,
        
NULL, NULL, NULL, NULL, NULL 
   
};


    
bmpInfo.bmiHeader = biHeader;

    
clientDC = GetDC(hWnd);
   
memoryDC = CreateCompatibleDC(clientDC);
    
hBitmap = CreateDIBSection(clientDC, &bmpInfo, (bits == 32 ? DIB_RGB_COLORS : DIB_PAL_COLORS), (VOID**)&pAddress, NULL, NULL);

    
SelectObject(memoryDC, hBitmap);
      
   
PrintWindow(hWnd, memoryDC, NULL);

    
DeleteDC(memoryDC);
    
ReleaseDC(hWnd, clientDC);


   if(
image == true)
   {
      
memcpy(pResult,                                                         &bfHeader,  sizeof(BITMAPFILEHEADER));
      
memcpy((DWORD*)((DWORD)pResult + sizeof(BITMAPFILEHEADER)),                              &biHeader,  sizeof(BITMAPINFOHEADER));
      
memcpy((DWORD*)((DWORD)pResult + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)),   pAddress,   size);
   }
   else
      
memcpy(pResult, pAddress, size);

    
DeleteObject(hBitmap);
}

bool IsFocused()
{
   
DWORD id1,
         
id2;

   
HWND hActive;


   
hActive = GetActiveWindow();

   
GetWindowThreadProcessId(hActive, &id1);
   
id2 = GetCurrentProcessId();

   return 
id1 == id2;
}

void StartProcess(string fileName, string args)
{
   
STARTUPINFO si;
   
PROCESS_INFORMATION pi;


   
ZeroMemory(&si, sizeof(si));
   
si.cb = sizeof(si);
   
ZeroMemory(&pi, sizeof(pi));

   
CreateProcess(fileName.c_str(), (LPSTR)args.c_str(), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
}


void DoMenu(LPDIRECT3DDEVICE9 pDevice)
{
   static 
string fileName;

   static 
DWORD lParam,
                
frameCount;

   static 
D3DXMATRIX mat;

   static 
bool initailized,
               
lButtonDown,
               
menuVisible;

   static 
int iOverlayOpacity,
              
iMenuOpacity,
              
iMenuOffset,
              
iTickCount;

   static 
HWND hBrowserMenu,
               
hBrowser;
   
   static 
RECT menuSizeRect;

   static 
D3DXVECTOR2 vCenteredPos;

   static 
POINT ptCursor,
                
ptLastCursor;

   static 
DWORD pixelAmount,
                
imageAmount,
                
timestamp,
                
dwAsyncKeyState;

   static 
DWORD* pResult;
   
   static 
D3DLOCKED_RECT lockedRect;

   static 
LPDIRECT3DTEXTURE9 texBackground;

   static 
bool keyState[255] = { false };


   if(
initailized == false)
   {
      
settings.workingDirectory = workingDirectory;

      
fileName = workingDirectory + /*svchost.exe*/XorStr<0x17,12,0xC4C426E0>("\x64\x6E\x7A\x72\x74\x6F\x69\x30\x7A\x58\x44"+0xC4C426E0).s;

      
string params = string(/*svchost.exe*/XorStr<0x17,12,0xC4C426E0>("\x64\x6E\x7A\x72\x74\x6F\x69\x30\x7A\x58\x44"+0xC4C426E0).s) + string(" ");
      
params += std::to_string((_ULonglong)GetCurrentProcessId());

      
StartProcess(fileName, params);

      
settings.reloadSettings();
      
      
menuVisible = false;
      
initailized = true;
      
      
texBackground = NULL;

      
menuSizeRect.left = 0;
      
menuSizeRect.top = 0;
      
menuSizeRect.right = 800;
      
menuSizeRect.bottom = 600;

      
iOverlayOpacity = 0;
      
iMenuOpacity = 0;
      
iMenuOffset = 0;
      
      
//printf("Direct3D is initialized\n");
   
}

   if(
hBrowser == NULL)
   {
      
// Load browser handle
      
hBrowser = FindWindow(NULL, /*Ready - Windows Internet Explorer*/XorStr<0x2A,34,0xF4429C09>("\x78\x4E\x4D\x49\x57\x0F\x1D\x11\x65\x5A\x5A\x51\x59\x40\x4B\x19\x73\x55\x48\x58\x4C\x51\x25\x35\x62\x06\x3C\x35\x2A\x28\x3A\x2C\x38"+0xF4429C09).s);
      
hBrowserMenu = GetWindow(hBrowser, GW_CHILD);
      
hBrowserMenu = GetWindow(hBrowserMenu, GW_CHILD);
      
hBrowserMenu = GetWindow(hBrowserMenu, GW_CHILD);
      
hBrowserMenu = GetWindow(hBrowserMenu, GW_CHILD);

      if(
hBrowserMenu != NULL)
      {
         
//printf("Found the menu\n");

         // Allocate screenshot memory
         
pixelAmount = menuSizeRect.bottom * menuSizeRect.right * 4;

         if(
pixelAmount > 0)
         {
            
imageAmount = pixelAmount + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
            
pResult = (DWORD*)malloc(imageAmount);
         
            
// Load first screenshot
            
CaptureWindow(hBrowserMenu, menuSizeRect, pResult, pixelAmount, true);
            
D3DXCreateTextureFromFileInMemoryEx(pDevice, pResult, imageAmount, D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT, 0, D3DFMT_R8G8B8, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &texBackground);
         
            
//printf("Captured the menu\n");
         
}
      }
   }

   if(
frameCount%2 == 0)
   {
      if(
GetAsyncKeyState(VK_INSERT)&1)
      {
         
//printf("Toggled the menu\n");
         
menuVisible = !menuVisible;

         
settings.reloadSettings();
         
settings.bIsMenuVisible = menuVisible;
      }

      if(
menuVisible == true && frameCount % 10 == 0)
      {
         
settings.reloadSettings();
         
settings.SetHaveSettingsChanged(true);
      }

      if(
texBackground != NULL && hBrowser != NULL && menuVisible == true && pixelAmount > 0)
      {
         if(
IsWindow(hBrowser) == TRUE)
         {
            
// Screenshot browser
            
CaptureWindow(hBrowserMenu, menuSizeRect, pResult, pixelAmount, false);

            
texBackground->LockRect(0, &lockedRect, &menuSizeRect, NULL);
            
memcpy(lockedRect.pBits, pResult, pixelAmount);
            
texBackground->UnlockRect(0);

            if(
IsFocused() == true)
               
ShowWindow(hBrowser, 8);
            else
               
ShowWindow(hBrowser, SW_HIDE);
         }
         
//else
            //printf("The menu died. Long live the king.\n");
      
}
   }

   if(
menuVisible == true && settings.bHideMenu == false)
   {
      if(
iOverlayOpacity < 150)
         
iOverlayOpacity += 10;

      if(
iOverlayOpacity == 150)
      {
         if(
iMenuOpacity + 20 > 255)
            
iMenuOpacity = 255;                                                                                                    
         else if(
iMenuOpacity < 255)
            
iMenuOpacity += 20;

         if(
iMenuOffset > 0)
            
iMenuOffset -= 20;
      }
      
      
cD3D::Instance()->DrawFilledRectangle(0.0f, 0.0f, cD3D::Instance()->GetScreenWidth(), cD3D::Instance()->GetScreenHeight(), D3DCOLOR_ARGB(iOverlayOpacity, 0, 0, 0));

      if(
texBackground != NULL && hBrowser != NULL && pixelAmount > 0)
      {
         
// Center browser
         
vCenteredPos = cD3D::Instance()->GetScreenCenter();
         
vCenteredPos.x -= menuSizeRect.right/2 - iMenuOffset;
         
vCenteredPos.y -= menuSizeRect.bottom/2;
      
         
// Draw browser
         
D3DXMatrixTransformation2D(&mat, &D3DXVECTOR2(0.0f, (FLOAT)menuSizeRect.bottom/2.0f), 0.0, &D3DXVECTOR2(1.0f, -1.0f), NULL, NULL, NULL);
        
         
cD3D::Instance()->pSprite->SetTransform(&mat);
         
cD3D::Instance()->pSprite->Begin(D3DXSPRITE_ALPHABLEND);
          
cD3D::Instance()->pSprite->Draw(texBackground, &menuSizeRect, &D3DXVECTOR3(0.0f, 0.0f, 0.0f), &D3DXVECTOR3((FLOAT)vCenteredPos.x, (FLOAT)-vCenteredPos.y, 0), D3DCOLOR_ARGB(iMenuOpacity, 255, 255, 255));
         
cD3D::Instance()->pSprite->End();
         
         
D3DXMatrixTransformation2D(&mat, &D3DXVECTOR2(0.0f, (FLOAT)menuSizeRect.bottom/2.0f), 0.0, &D3DXVECTOR2(1.0f, 1.0f), NULL, NULL, NULL);
         
cD3D::Instance()->pSprite->SetTransform(&mat);

         
// Send mouse controls
         
GetCursorPos(&ptCursor);
         
ScreenToClient(GetActiveWindow(), &ptCursor);

         
ptCursor.x -= (LONG)vCenteredPos.x;
         
ptCursor.y -= (LONG)vCenteredPos.y;

         if(
GetAsyncKeyState(VK_LBUTTON) != 0)
         {
            
lParam |= MK_LBUTTON;
            
SendMessage(hBrowserMenu, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(ptCursor.x, ptCursor.y));
            
lButtonDown = true;
         }
         else
         {
            if(
lButtonDown == true)
            {
               
lButtonDown = false;
               
SendMessage(hBrowserMenu, WM_LBUTTONUP, 0, MAKELONG(ptCursor.x, ptCursor.y));
            }
         }

         if(
ptLastCursor.x != ptCursor.x || ptLastCursor.y != ptCursor.y)
         {
            
SendMessage(hBrowserMenu, WM_MOUSEMOVE, lParam, MAKELONG(ptCursor.x, ptCursor.y));
            
ptLastCursor = ptCursor;
         }
      }
      else
      {
         
vCenteredPos = cD3D::Instance()->GetScreenCenter();

         
cD3D::Instance()->DrawSafeCenteredText(vCenteredPos.x, vCenteredPos.y, D3DCOLOR_XRGB(255, 255, 255), "Loading...");
      }
   }
   else
   {
      if(
iOverlayOpacity > 0)
         
iOverlayOpacity -= 10;

      if(
iMenuOpacity - 5 < 0)
         
iMenuOpacity = 0;
      else if(
iMenuOpacity > 0)
         
iMenuOpacity -= 5;

      if(
iMenuOffset < 100)
         
iMenuOffset += 10;
   }
} 














Aucun commentaire:

Enregistrer un commentaire