通过截图分析C#检测游戏破解
本文关键字:检测 游戏 破解 | 更新日期: 2023-09-27 18:27:33
我正在尝试编写一些代码来检测游戏的wallhack。基本上,存在一些创建windows航空透明窗口的黑客,他们将黑客绘制到这个外部窗口上,因此无法通过拍摄游戏本身的屏幕截图来检测到。
我目前的做法是-1.拍摄游戏窗口的屏幕截图。2.对于相同的坐标,截取windows桌面的屏幕截图。3.执行图像分析以比较屏幕截图1和屏幕截图2,以查看是否存在差异。
我的问题是,屏幕截图1和屏幕截图2不是同时执行的,因此可以在两个屏幕截图之间绘制新的游戏帧,从而在比较图像时导致误报。
我想知道是否有办法协调屏幕截图,让它们同时出现?或者以某种方式停止屏幕绘制任何新的框架,直到我的屏幕截图完成?
这是我用来截屏的代码。注意,我甚至试图通过排队两个工作项目来并行拍摄这两个屏幕截图。然而,即使这样也不会导致屏幕截图同时发生。所以我想知道是否有办法在我的屏幕截图完成之前停止图形卡对屏幕的任何进一步更新?或者我能用其他方法做到这一点吗?
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;
}
除非你为一些图形加速器提供资源,否则你不可能同时拥有两个屏幕截图,这意味着这不会在每台计算机上都起作用。。。
关于停止渲染,因为这是一个游戏,我认为这不是一个好主意。。。你希望你的比赛顺利进行。
相反,我建议将最近渲染的游戏图像存储在内存中,当你拍摄屏幕截图时,将其与它们进行比较。如果你可以添加一些视觉线索来决定与最近的哪一帧进行比较,那么它会更好地工作,因为否则你将不得不将屏幕截图与所有帧进行比较——这肯定会占用一些CPU/GPU时间。
你正在使用GDI进行渲染吗?如果是这样的话,你想要的是将游戏的帧存储在DIB(设备独立位图)中,以便能够进行比较。
至于决定使用哪种图像的线索,我会在屏幕上选择某种时间表示,也许是一个改变颜色的像素。如果是这样的话,你将读取该像素的颜色,用它来找到正确的帧,然后他们对整个图片进行比较。