2013-08-13 95 views
5

Sto provando a scrivere del codice per rilevare un wallhack per un gioco. Fondamentalmente, esistono alcuni hack che creano una finestra trasparente aera di Windows, e disegnano l'hack su questa finestra esterna, quindi non possono essere rilevati prendendo uno screenshot del gioco stesso.Rileva gioco hack tramite analisi screenshot C#

Il mio approccio al momento è quello di - 1. fare uno screenshot della finestra di gioco. 2. prendere uno screenshot del desktop di Windows per le stesse coordinate. 3. eseguire l'analisi delle immagini per confrontare lo screenshot 1 con lo screenshot 2 per vedere se c'è una differenza.

Il mio problema è che lo screenshot 1 e lo screenshot 2 non vengono eseguiti contemporaneamente, quindi è possibile disegnare nuovi frame di gioco tra i due screenshot, causando falsi positivi quando le immagini vengono confrontate.

Desidero sapere se esiste un modo per coordinare gli screenshot in modo che si verifichino esattamente nello stesso momento? o in qualche modo fermare lo schermo disegnando nuovi fotogrammi fino a quando i miei screenshot sono finiti?

Questo è il codice che uso per scattare screenshot. Nota, ho persino provato a prendere i 2 screenshot in parallelo accodando due elementi di lavoro. Tuttavia, anche questo non comporta che gli screenshot avvengano esattamente nello stesso momento. Quindi mi chiedo se c'è un modo per interrompere ulteriori aggiornamenti dello schermo dalla scheda grafica fino alla fine delle mie schermate? O in qualsiasi altro modo posso farlo?

public void DoBitBlt(IntPtr dest, int width, int height, IntPtr src) 
    { 
     GDI32.BitBlt(dest, 0, 0, width, height, src, 0, 0, GDI32.SRCCOPY); 
    } 

    public struct Windows 
    { 
     public Bitmap window; 
     public Bitmap desktop; 
    } 
    public Windows CaptureWindows(IntPtr window, IntPtr desktop, User32.RECT coords) 
    { 
     Windows rslt = new Windows(); 
     // get te hDC of the target window 
     IntPtr hdcSrcWindow = User32.GetWindowDC(window); 
     IntPtr hdcSrcDesktop = User32.GetWindowDC(desktop); 

     // get the size 
     int width = coords.right - coords.left; 
     int height = coords.bottom - coords.top; 

     // create a device context we can copy to 
     IntPtr hdcDestWindow = GDI32.CreateCompatibleDC(hdcSrcWindow); 
     IntPtr hdcDestDesktop = GDI32.CreateCompatibleDC(hdcSrcDesktop); 
     // create a bitmap we can copy it to, 
     // using GetDeviceCaps to get the width/height 
     IntPtr hBitmapWindow = GDI32.CreateCompatibleBitmap(hdcSrcWindow, width, height); 
     IntPtr hBitmapDesktop = GDI32.CreateCompatibleBitmap(hdcSrcDesktop, width, height); 
     // select the bitmap object 
     IntPtr hOldWindow = GDI32.SelectObject(hdcDestWindow, hBitmapWindow); 
     IntPtr hOldDesktop = GDI32.SelectObject(hdcDestDesktop, hBitmapDesktop); 
     // bitblt over 
     var handle1 = new ManualResetEvent(false); 
     var handle2 = new ManualResetEvent(false); 
     Action actionWindow =() => { try { DoBitBlt(hdcDestWindow, width, height, hdcSrcWindow); } finally { handle1.Set(); } }; 
     Action actionDesktop =() => { try { DoBitBlt(hdcDestDesktop, width, height, hdcSrcDesktop); } finally { handle2.Set(); } }; 
     ThreadPool.QueueUserWorkItem(x => actionWindow()); 
     ThreadPool.QueueUserWorkItem(x => actionDesktop()); 
     WaitHandle.WaitAll(new WaitHandle[] { handle1, handle2 }); 

     rslt.window = Bitmap.FromHbitmap(hBitmapWindow); 
     rslt.desktop = Bitmap.FromHbitmap(hBitmapDesktop); 

     // restore selection 
     GDI32.SelectObject(hdcDestWindow, hOldWindow); 
     GDI32.SelectObject(hdcDestDesktop, hOldDesktop); 
     // clean up 
     GDI32.DeleteDC(hdcDestWindow); 
     GDI32.DeleteDC(hdcDestDesktop); 
     User32.ReleaseDC(window, hdcSrcWindow); 
     User32.ReleaseDC(desktop, hdcSrcDesktop); 
     // free up the Bitmap object 
     GDI32.DeleteObject(hBitmapWindow); 
     GDI32.DeleteObject(hBitmapDesktop); 
     return rslt; 
    } 
+3

Non credo che quello che stai facendo sia etico. Il tuo rilevatore "wallhack" sta raccogliendo informazioni che un utente potrebbe non voler divulgare. Perché un utente acconsente a prendere catture di schermo del proprio desktop mentre gioca? Il comportamento che stai cercando di implementare rientra nella classificazione del cavallo di Troia. Questo è ovviamente se non stai mentendo sullo scopo del tuo programma.

+0

Questo potrebbe essere un uso appropriato di ['Parallel.Foreach'] (http://msdn.microsoft.com/en-us/library/system.threading.tasks.parallel.foreach.aspx). 'ThreadPool' non garantisce il parallelismo. – Romoku

+2

Supponi di avere il tuo gioco aperto in una finestra, ma poi apri un browser web su quella finestra (google qualcosa | controlla il mio conto bancario | naviga su Facebook | fai qualcosa di illegale) e fai uno screenshot di quello.Registrerai un falso positivo - che sto imbrogliando quando non lo sono, e se decidi che dovresti caricare lo screenshot "falso" per prova/verifica, potresti catturare accidentalmente i miei dettagli privati. –

risposta

1

Non si ha intenzione di essere in grado di avere entrambe le immagini contemporaneamente, a meno che non si risorsa ad alcuni accelarators grafici, il che significa che questo sistema non funziona in tutti i computer ...

di smettere di rendering, in quanto è un gioco, penso che non sia una buona idea ... vuoi che il tuo gioco funzioni senza intoppi.

Invece vorrei suggerire di archiviare in memoria le immagini del tuo gioco recentemente renderizzate, e quando prendi lo screenshot confrontalo con loro. Se riesci ad aggiungere qualche indizio visivo per decidere quale dei fotogrammi recenti confrontare, allora funzionerà molto meglio, perché altrimenti dovrai confrontare lo screenshot a tutti loro e questo sicuramente mangerà del tempo CPU/GPU.

Stai utilizzando GDI per il rendering? in tal caso, ciò che si desidera è archiviare i frame del gioco in DIB (Device Independent Bitmaps) per poterli confrontare.

Per quanto riguarda l'indizio per decidere quale immagine utilizzare, vorrei fare una sorta di rappresentazione del tempo sullo schermo, forse un singolo pixel che cambia colore. In tal caso, leggerai il colore di quel pixel, usalo per trovare il fotogramma giusto e procedilo per confrontare l'intera immagine.

+0

Se si ha cooperazione dal gioco, non è necessario salvare effettivamente i vecchi fotogrammi. Un solido checksum di vecchi fotogrammi, o dati nascosti nei bit a basso colore usando la steganografia, sarebbe perfettamente sufficiente per determinare se l'acquisizione dell'immagine sullo schermo è stata modificata. –