使用Qt实战开发编写spy++

这是很多年前草堂教程网站长学习WINDOWS开发的笔记,该技术使用到了QT跟C++以及WINDOWS系统编程技术.


Qt编写spyxx主界面

1.png

  • 难点在于用圆圈光标选中的时候画了一个矩形框,选中下一个窗口之前画的窗口又变成原来的样子,下一个窗口画一个矩形框。(主要的意思就是说,之前选中的没框了,现在选中的有框)

使用到的API及代码

  1. 选中一个点就可以获取窗口句柄的API (WindowFromPoint)

  2. 获取Lable控件的事件,子类化重写虚时间方法。

    


    //鼠标按下事件
    void mousePressEvent(QMouseEvent *ev);
    //鼠标释放事件
    void mouseReleaseEvent(QMouseEvent *ev);
     //鼠标移动时间
    void mouseMoveEvent(QMouseEvent *ev);


按下的时候
如下图把Lable图标换成空白的,鼠标光标换成圆圈图片

c32acc80-c3ea-4fd3-8928-d14559667635.png



void FindIcon::mousePressEvent(QMouseEvent *ev)
{  
   //设置lable图标
    this->setPixmap(QPixmap(QString::fromUtf8(":/Spyxx/res/ICO_choose.ICO")));
    //设置光标
    setCursor(QPixmap(QString::fromUtf8(":/Spyxx/res/CUR10.CUR")));
}
移动的时候根据点获取窗口句柄画矩形
void FindIcon::mouseMoveEvent(QMouseEvent *ev)
{
  //获取整个桌面的坐标
    POINT pt;
    pt.x = ev->globalX();
    pt.y = ev->globalY();
   //通过桌面坐标获取窗口句柄
    HWND hwnd=WindowFromPoint(pt);
    //画矩形
    if(hwnd==NULL)
    {
        return;
    }
    if(m_hpre==NULL)
    {
        Draw(m_hpre);
        m_hpre = hwnd;
        Draw(hwnd);
    }
    else
    {
        if(m_hpre!=hwnd)
        {
            Draw(m_hpre);     
            m_hpre = hwnd; 
            Draw(hwnd);
            emit SetText((int)hwnd);
        } 
    }
}

画矩形的函数这里使用到了异或笔这个概念 

int SetROP2( HDC hdc, int fnDrawMode);
函数调用成功后,返回调用前的模式,调用失败则返回零。


void FindIcon::Draw(HWND hWnd)
{
    //获取整个桌面DC
    HWND hDesktop = GetDesktopWindow();
    //需要画矩形的DC
    HDC hDC = GetDC(hDesktop);
    RECT rc;
    GetWindowRect(hWnd, &rc);
    //创建笔
    HPEN  hPen = CreatePen(PS_SOLID,
        5,
        RGB(0, 0, 0));
    //设置为异或笔
    SetROP2(hDC, R2_NOTXORPEN);
    //为dc选择画笔
    SelectObject(hDC, hPen);
    SelectObject(hDC, GetStockObject(NULL_BRUSH));
    //画矩形
    Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
    //释放DC
    ReleaseDC(hDesktop, hDC);
}

到这里主界面差不多就写完了。

spyxx拦截消息

替换消息过程回调函数

要拦截其他进程消息的,肯定需要使用到进程间的通信,这里就需要用到dll远程线程注入技术替换消息过程函数

代码

远程线程注入dll的代码,窗口m_hwnd为已知的,如果未知需要自己找到注入的窗口句柄(可以使用FindWindow)



void DialogWM::SetPro()
{
    //通过句柄获取进程句柄ID
    DWORD dwPid = 0;
    DWORD dw = 0;;
    DWORD dwTid = 0;
     GetWindowThreadProcessId(m_hwnd, &dwPid);
     //通过进程ID获取进程句柄
     handle=OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwPid);
    if(handle==NULL)
    {
        OutputDebugStringA("Get PID Faild ");
    }
       //为进程申请空间
       LPVOID lpaddr=VirtualAllocEx(handle, NULL, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
       //Write Data
    //注意写入路径的dll
       WriteProcessMemory(handle, lpaddr, "E:\\\\CC++project\\c++\\第二阶段作业\\Spy\\bin\\hookdll.dll", sizeof("E:\\CC++project\\c++\\第二阶段作业\\Spy\\bin\\hookdll.dll"), &dw);
       //远程注入
       HANDLE  hRemoteThread= CreateRemoteThread(handle, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibraryA, lpaddr,0 ,NULL);
       WaitForSingleObject(hRemoteThread, INFINITE);
       //获取退出码为了卸载dll
       GetExitCodeThread(hRemoteThread, &dwExitCode);
}

卸载dll代码


//释放dll
    CreateRemoteThread(handle,
        NULL,
        0,
        (LPTHREAD_START_ROUTINE)FreeLibrary,
        (LPVOID)dwExitCode,
        0,
        NULL);
    CloseHandle(handle);

dll的代码


//共享节用了获取句柄
#pragma data_seg("MY_DATA") 
int nDataBase = 0;
#pragma data_seg()
#pragma comment(linker,"/section:MY_DATA,rws")
HWND hmain = 0;
LONG old_proc = 0;
DWORD ThreadFunc(LPVOID lpParam)
{
    HMODULE h_mod = GetModuleHandleA("spyxx.dll");
    FreeLibraryAndExitThread(h_mod, 0);
    return 0;
}
LRESULT CALLBACK New_Proc(HWND hWnd, UINT msg,
    WPARAM wParam, LPARAM lParam)
{
    //自定义的消息循环
    switch (msg)
    {
    case WM_COMMAND:
    {
        SendMessageA(hmain, WM_COMMAND, wParam, lParam);
    }
    break;
    default:
        break;
    }
    //交给原消息循环处理
    return  CallWindowProc((WNDPROC)old_proc, hWnd, msg, wParam, lParam);
}
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    {
        //获取窗口句柄
        hmain = FindWindowA(NULL, "Dialog");
        HWND hwnd = (HWND)nDataBase;
        if (hwnd != 0)
        {
            old_proc = SetWindowLongA(hwnd,
                GWL_WNDPROC,
                (LONG)New_Proc);   
        }
    }
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    {
        SetWindowLongA((HWND)nDataBase,
            GWL_WNDPROC,
            (LONG)old_proc);
    }
    case DLL_PROCESS_DETACH:
    {
    }
        break;
    }
    return TRUE;
}


hook窗口信息回调函数

dll代码

HHOOK g_hook;
LRESULT OldWindowProc;
HMODULE g_hondle;
LRESULT CALLBACK CallWndProc(
    int nCode,      // hook code
    WPARAM wParam,  // current-process flag
    LPARAM lParam   // message data
    )
{
    if (nCode<0)
    {
        return  CallNextHookEx(g_hook,nCode,wParam,lParam);
    }
    PCWPSTRUCT cs = (PCWPSTRUCT)lParam;
    if (cs->message == WM_COMMAND)
    {
        OutputDebugStringA("WM_COMMANDhook");
    }
    return  CallNextHookEx(g_hook, nCode, wParam, lParam);
}
extern "C" __declspec(dllexport) void MySetHook()
{
    g_hook = SetWindowsHookEx(
        WH_CALLWNDPROC,
        CallWndProc,
        g_hondle,
        0);
}
extern "C" __declspec(dllexport) void MyUnHook()
{
    UnhookWindowsHookEx(g_hook);
}
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    {
        g_hondle = hModule;
    }
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}



转载请说明出处
草堂教程网 » 使用Qt实战开发编写spy++

发表评论

欢迎 访客 发表评论

一个纯粹的精品教程收录分享站点

查看演示 官网购买