首页
社区
课程
招聘
[原创]"破解"QQ找茬
发表于: 2010-9-26 09:54 25297

[原创]"破解"QQ找茬

2010-9-26 09:54
25297

前几天寝室里几个哥们玩QQ,找茬,我们六人还找不过一人,甚是郁闷,于是我决定编写一个找茬程序。
效果图如下。配置菜单里是相关参数的设置,点击截图菜单项后窗口自动移动,并显示出两幅图的不同。技术含量不是很高。
我传了一个效果图,1.jpg,那个紫色圆形是随着鼠标动而动产生的,方便定位。
注释确实太少了。
我说一下思路吧,先把窗口移到右边,截取桌面左边图像,再移到左边,截取右边图像,并进行异或操作,这样不同的地方就显示出来了。
我本想给游戏窗口发鼠标消息的,可一想,这个图片较小,不同之处也少,干脆又人来定位得了。如果要自动定位的话,我想用内存设备描述表中位图句柄来得到图像像素数据,不知道有更好的方法没。还请高人指教!
上传附件不太方便,贴代码吧
#include <windows.h>
#include "resource.h"

#define         ID_TIMER 1
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

POINT        left,right;
int         height,width;
int                cxSize,cySize;
HDC        hdcMem;/////////////////////////内存DC
HBITMAP hBitmap;
POINT                pt;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("SCR_COPY") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;

     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (hInstance,szAppName) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = szAppName ;
     wndclass.lpszClassName = szAppName ;

     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     
     hwnd = CreateWindow (szAppName,                  // window class name
                          TEXT ("SCR_COPY"), // window caption
                          WS_OVERLAPPEDWINDOW,        // window style
                          CW_USEDEFAULT,              // initial x position
                          CW_USEDEFAULT,              // initial y position
                          CW_USEDEFAULT,              // initial x size
                          CW_USEDEFAULT,              // initial y size
                          NULL,                       // parent window handle
                          NULL,                       // window menu handle
                          hInstance,                  // program instance handle
                          NULL) ;                     // creation parameters
     
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
     
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }

       

     return msg.wParam ;
}
///////////////////////////////////////////////////////////////////
void CALLBACK TimerProc(HWND hwnd,UINT message,UINT iTimerID,DWORD dwTime)
{
        HDC        hdc_me = GetDC(hwnd);
        POINT        pos,pos2;
        HBRUSH        hBrush;
        BitBlt(hdc_me,0,pt.y,width,height,
                   hdcMem,0,0,SRCCOPY);  
        hBrush = CreateSolidBrush(RGB(255,100,255));
        SelectObject(hdc_me,hBrush);

        GetCursorPos(&pos);
        pos2 = pos;
        ScreenToClient(hwnd,&pos2);
        Ellipse(hdc_me,pos.x-cxSize/2-5,pos2.y-5,pos.x-cxSize/2+5,pos2.y+5);
        DeleteObject(hBrush);
        ReleaseDC(hwnd,hdc_me);

}
///////////////////////////////////////////////////////////////////
BOOL CALLBACK AboutDlgProc(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)
{
        switch(message)
        {
        case WM_INITDIALOG:
                return TRUE;
        case WM_COMMAND:
                switch(LOWORD(wParam))
                {
                case IDOK:
                        EndDialog(hDlg,0);
                        return TRUE;
                }
                break;
        }
       
        return FALSE;
}
///////////////////////////////////////////////////////////////////
BOOL CALLBACK DlgProc(HWND hDlg,UINT message,
                                          WPARAM wParam,LPARAM lParam)
{

        switch(message)
        {
                case WM_INITDIALOG:
                        SetDlgItemInt(hDlg,IDC_L_X,left.x,0);
                        SetDlgItemInt(hDlg,IDC_L_Y,left.y,0);
                        SetDlgItemInt(hDlg,IDC_R_X,right.x,0);
                        SetDlgItemInt(hDlg,IDC_R_Y,right.y,0);
                        SetDlgItemInt(hDlg,IDC_HEIGHT,height,0);
                        SetDlgItemInt(hDlg,IDC_WIDTH, width,0);
                                return 0;
                case WM_CLOSE:
                        EndDialog(hDlg,FALSE);
                        return 0;
                case WM_COMMAND:
                        switch(LOWORD(wParam))
                        {
                        case IDOK:
                                left.x  = GetDlgItemInt(hDlg,IDC_L_X,NULL,0);
                                left.y  = GetDlgItemInt(hDlg,IDC_L_Y,NULL,0);
                                right.x  = GetDlgItemInt(hDlg,IDC_R_X,NULL,0);
                                right.y  = GetDlgItemInt(hDlg,IDC_R_Y,NULL,0);
                                height  = GetDlgItemInt(hDlg,IDC_HEIGHT,NULL,0);
                                width  = GetDlgItemInt(hDlg,IDC_WIDTH,NULL,0);
                                EndDialog(hDlg,TRUE);
                                return TRUE;
                        }
        }
        return 0;
}
TCHAR szString[] = TEXT ("Hello, 千里眼") ;

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{       
         static                HINSTANCE        hInstance;
         static                count  = 0;
         
         static                flag = 0;
         HDC                hdc_me,hdc;//依次为窗口设备描述表,桌面DC
         
         PAINTSTRUCT ps ;
         HWND                desk_hwnd = GetDesktopWindow();
         switch (message)
         {       
                  case WM_CREATE:
                         left.x  = 8;
                         left.y  = 192;
                         right.x  = 517;
                         right.y  = 192;
                         cxSize = GetSystemMetrics(SM_CXSCREEN);
                         cySize = GetSystemMetrics(SM_CYSCREEN);
                         width = cxSize/2;
                         height = cySize;
                       
                          hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
                         RegisterHotKey(hwnd,100,0,VK_F4);
                         SetWindowPos(hwnd,HWND_TOPMOST,
                                        0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
                        return 0;
                                
                 case WM_COMMAND:
                                 switch(LOWORD(wParam))
                                 {
                                        case IDM_START:
                                                        if(DialogBox(hInstance,TEXT("SCR_COPY"),hwnd,DlgProc))
                                                                 InvalidateRect(hwnd,NULL,TRUE);
                                                         return 0;
                                       
                                        case IDM_CUT:
                                                        MoveWindow(hwnd,cxSize/2,0,width,height,TRUE);//窗口移到右边
                                                        Sleep(200);//稍等一下
                                                  hdc_me = GetDC(hwnd);
                                                  hdcMem = CreateCompatibleDC(hdc_me);//内存设备描述表
                                                  if(hBitmap)
                                                  {
                                                          DeleteObject(hBitmap);
                                                          hBitmap = NULL;
                                                  }
                                                  hBitmap = CreateCompatibleBitmap(hdc_me,width,height);
                                                  SelectObject(hdcMem,hBitmap);

                                                  hdc = GetDCEx(desk_hwnd,0,DCX_LOCKWINDOWUPDATE);
                                                  pt = left;
                                                  ScreenToClient(hwnd,&pt);                                                         
                                                  //BitBlt(hdc_me,0,pt.y,width,height,
                                                        //                        hdc,left.x,left.y,SRCCOPY);
                                                  BitBlt(hdcMem,0,0,width,height,
                                                                 hdc,left.x,left.y,SRCCOPY);//桌面左边图像放入内存

                                             MoveWindow(hwnd,0,0,width,height,TRUE);//窗口移到右边
                                                 Sleep(200);

                                                        //右边图像放入内存并进行异或操作
                                         BitBlt(hdcMem,0,0,width,height,       
                                                        hdc,right.x,right.y,SRCINVERT);
                                                 BitBlt(hdc_me,0,pt.y,width,height,
                                                        hdcMem,0,0,SRCCOPY);
                                                // BitBlt(hdc_me,0,0,width,height,
                                                //                hdcMem,0,0,SRCCOPY);  //程序编写时测试代码
                                                 if(flag)
                                                        KillTimer(hwnd,ID_TIMER);
                                                 flag = 1;
                                                 SetTimer(hwnd,ID_TIMER,50,TimerProc);
                                                 ReleaseDC(hwnd,hdc_me);
                                                 ReleaseDC(desk_hwnd,hdc);
                                                       
                                                        return 0;
                                        case IDM_ABOUT:
                                                DialogBox(hInstance,TEXT("AboutBox"),hwnd,AboutDlgProc);
                                                return 0;
                                 }
                      break;
                case WM_PAINT:
          hdc = BeginPaint (hwnd, &ps) ;
                  
                  TextOut(hdc,50,50,szString,lstrlen(szString));
          EndPaint (hwnd, &ps) ;
          return 0 ;     
                case WM_HOTKEY:
                                if(IsWindowVisible(hwnd))
                                        ShowWindow(hwnd,SW_HIDE);
                                else       
                                        ShowWindow(hwnd,SW_SHOW);
                                        SendMessage(hwnd,WM_COMMAND,IDM_CUT,0);
                                return 0;
                case WM_DESTROY:
                          KillTimer(hwnd,ID_TIMER);
                      PostQuitMessage (0) ;
                      return 0 ;
         }
         return DefWindowProc (hwnd, message, wParam, lParam) ;
}

代码简单,就不多说了。各位看官莫笑。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 8
支持
分享
最新回复 (40)
雪    币: 145
活跃值: (85)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
2
为何不上传源码?

注释太少。。。。。。看不懂
2010-9-26 10:09
0
雪    币: 440
活跃值: (119)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
3
恩,我上大学的时候也写过找茬的外挂,原理就是比较两幅图的不同,然后递归出五个不同区域来,呵呵~~~
2010-9-26 10:52
0
雪    币: 354
活跃值: (157)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
4
源码就在上面,注释确实有点少,因为程序较短的缘故。我说一下思路吧,先把窗口移到右边,截取桌面左边图像,再移到左边,截取右边图像,并进行异或操作,这样不同的地方就显示出来了。
2010-9-26 10:53
0
雪    币: 354
活跃值: (157)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
5
我本想给游戏窗口发鼠标消息的,可一想,这个图片较小,不同之处也少,干脆又人来定位得了,踏雪流云打算用什么方法得到图像像素数据,我想用内存设备描述表中位图句柄,不知道有更好的方法没。还请高人指教!
2010-9-26 10:57
0
雪    币: 440
活跃值: (119)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
6
恩,我当时是注册了几个热键,Alt+1截取两张图片,Alt+2显示5处不同,Alt+3模拟按键点击不同区域等。获取图像的方式是GetDC,当时的找茬图片在目标窗口的像素位置是不固定的,因此我在精确获取图片时遇到了些问题,我对图像处理不熟,因此只是简单的把获得的两张图片做像素比较,然后得到一个二值化的图像,进行了边缘区域检测确定五个区域。。。
2010-9-26 11:15
0
雪    币: 85
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
原创要支持的,赞个
2010-9-26 12:15
0
雪    币: 12
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
恩  还不错
2010-9-26 12:27
0
雪    币: 354
活跃值: (157)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
9
其实可以用鼠标单击不同之处然后将鼠标消息发给qq游戏窗口,这样方便点。
2010-9-26 13:40
0
雪    币: 440
活跃值: (119)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
10
恩,呵呵,当时我就是这么做的,给qq找茬发送鼠标点击消息~~~
2010-9-26 13:45
0
雪    币: 9
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
正在学习windows API,想找找相关资料,看到楼主的帖,受益了
2010-9-26 14:01
0
雪    币: 354
活跃值: (157)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
12
现在程序还有点问题,运行后第一次点击截图时,屏幕左边的图像丢失,以后点击则没问题,想了很久也没知道为什么。我在热键里给程序发送菜单消息,则每次都丢失左边的图像。
2010-9-26 22:44
0
雪    币: 354
活跃值: (157)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
13
代码改了下,现在按F4就行了,添了些注释,重新上传了附件。
2010-9-27 14:26
0
雪    币: 1160
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
崔然看不懂,但还是谢谢楼主
2010-9-27 15:47
0
雪    币: 177
活跃值: (278)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
DWORD dw1 = *(DWORD*)(0x47E858+0x27C7C+0xA20);
DWORD dw2 = *(DWORD*)(0x47E858+0x27C7C+0x18+0x4);
DWORD dwECX = 0;
__asm
{        mov eax, dw1
        mov ecx, dw2
        imul eax, eax, 0x0c0
        add ecx, eax
        mov dwECX, ecx
}
//以上代码得到一个dwECX的值,这个等会赋值给ecx,有用。

//以下公式可以得到两个大小为2*5的数组,每个数组5个WORD,分别是每个茬所在的框框的左上角的坐标
[ECX+EAX*2+16]------>X坐标
[ECX+EAX*2+2A]------>Y坐标
ecx就是刚才一段代码得到,eax从0~4,读出数组。

这样就可以得到每个茬的框框的左上角坐标了,然后X和Y各偏移3个像素,模拟一次点击,自动找茬。
2010-9-27 16:41
0
雪    币: 177
活跃值: (278)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
0x4A6F90
//以上地址存放的是点击错误之后的几秒惩罚,锁定为0就可以避免惩罚,当然你可以往上回溯以下,可以做的更完美。
2010-9-27 16:44
0
雪    币: 177
活跃值: (278)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
我想我的内存挂的速度应该要高于你的图片比较吧
2010-9-27 16:45
0
雪    币: 5334
活跃值: (3724)
能力值: ( LV13,RANK:283 )
在线值:
发帖
回帖
粉丝
18
mark,学习
2010-9-27 21:27
0
雪    币: 89
活跃值: (185)
能力值: ( LV9,RANK:270 )
在线值:
发帖
回帖
粉丝
19
呵呵,找茬这个偶也写过,后来有一段时间,TX把某一张图片中间增加了几个像素的干扰条。还是内存挂比较爽,呵呵。
2010-9-27 23:57
0
雪    币: 229
活跃值: (508)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
20
大学时写过一个,,比你这个稍微漂亮些。。。
2010-9-28 09:43
0
雪    币: 326
活跃值: (41)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
21
// 你操作的DC是哪个?会是不是直接操作的QQ的窗口DC的原因,导致左边为花了呢。具体代码没看。一会去研究下。

看的头疼。代码风格让人头直晕。呵呵。我看了一下,好像没什么问题吧。那个代码现在还有那个花屏的问题没?
2010-9-29 13:02
0
雪    币: 145
活跃值: (85)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
22
哎,,,我用OD怎么就没找到呢!
2010-9-30 12:44
0
雪    币: 145
活跃值: (85)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
23
什么意思?
[ECX+EAX*2+16]------>X坐标
这是OD里找到的么?????
2010-9-30 12:47
0
雪    币: 145
活跃值: (85)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
24
我只到找了调用错误声音的地方,估计和惩罚时间 代码不远
2010-9-30 12:48
0
雪    币: 214
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
不错的东西 不错的东西
2010-10-4 14:50
0
游客
登录 | 注册 方可回帖
返回
//