zoukankan      html  css  js  c++  java
  • qt 取进程列表,读写内存, 写字节集

    1. 导入库 pro
    win32:LIBS += -lpsapi
    win32:LIBS += -lkernel32
    
    1. 获取列表
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <windows.h>
    #include <QtDebug>
    #include <locale>
    #include <tchar.h>
    #include <string>
    #include <QMessageBox>
    #include <stdio.h>
    #include <psapi.h>
    
    void MainWindow::on_pushButton_2_clicked()
    {
        DWORD PID = 0;
        // 获取进程标识符列表。
        DWORD aProcesses[1024], cbNeeded;
    
        if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
        {
            qDebug() << "获取失败";
            return;
        }
    
        // 计算返回了多少个进程标识符。
        unsigned int cProcesses = cbNeeded / sizeof(DWORD);
    
        // 打印每个进程的名称和进程标识符。
        unsigned int i;
        for ( i = 0; i < cProcesses; i++ )
        {
            DWORD processID = aProcesses[i];
            if(processID == 0 ) continue;
    
    
            char buff[255];
            // 打开现有的本地过程对象
            HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |PROCESS_VM_READ,FALSE, processID );
            if(hProcess == NULL)continue;
    
            // 获取进程名称。
            HMODULE hMod;
            DWORD cbNeeded;
    
            if (EnumProcessModules(hProcess, &hMod, sizeof(hMod),&cbNeeded) )
            {
                GetModuleBaseNameA(hProcess, hMod, (LPSTR)&buff, DWORD(sizeof(buff)/sizeof(char)));
            }
    
            QString s= QString::fromLocal8Bit(buff);
            if(s == "game2.exe"){
                PID = processID;
                break;
            }
    
            // 释放该过程的句柄。
            CloseHandle( hProcess );
        }
    
    
        if(PID == 0) return;
    
        // 获取进程所有访问权限 https://docs.microsoft.com/zh-cn/windows/win32/procthread/process-security-and-access-rights
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE, PID);
        if(hProcess == NULL) return;
    
        // 读内存 https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-readprocessmemory
        int hpAddress = 0x004B3724;
        int hp;
        // 进程句柄, 内存地址, 值引用,值的字节大小, null
        ReadProcessMemory(hProcess, (LPCVOID)hpAddress, &hp, sizeof(hp), 0);
        qDebug() << hp;
    
        // 写内存 https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory
        // 注:这里的int是4字节类型,如果是单浮点那么你就要用float,虽然两个都是4字节,但是就是会出问题
        int newHP = 100;
        if(WriteProcessMemory(hProcess, (LPVOID)hpAddress, (LPCVOID)&newHP, sizeof(newHP), 0 )){
            qDebug() << "写入ok.";
        }
    
        CloseHandle(hProcess);
    }
    

    在代码中获取动态内存

    1. 先在CE中获取基址,如:

      上面找到的基址就是"Game.exe"+00ABBBB0,就算重启游戏后,这个地址也不会变,然后按照对应的偏移量,更着读下去,就能获取到最后的值

    2. 编写代码

    // 获取人物当前的x坐标
    float Game::getX()
    {
        // 基址 "Game.exe"+00ABBBB0 => 8A0000+00ABBBB0
        int x;
    
        // 第0层
        ReadProcessMemory(gameProcess, (LPCVOID)(9043968+11254704), &x, 4, 0);
        qDebug() << "第0层: " << x;
    
        // 第1次层 偏移48位,这里转为10进制来运算
        ReadProcessMemory(gameProcess, (LPCVOID)(x+72), &x, 4, 0);
        qDebug() << "第1层: " <<x;
    
        // 第2层,将第1层的结果偏移8位
        ReadProcessMemory(gameProcess, LPCVOID(x+8), &x, 4, 0);
        qDebug() << "第2层: " <<x;
    
        // 第3层,将第2层的结果偏移14位
        ReadProcessMemory(gameProcess, LPCVOID(x+20), &x, 4, 0);
        qDebug() << "第3层: " <<x;
    
        // 第4层,将第3层的结果偏移2c位
        x += 44;
        qDebug() << "第4层: " <<x;
    
        // 获取结果,如果要修改内存也可以在这里修改
        float r;
        ReadProcessMemory(gameProcess, LPCVOID(x), &r, 4, 0);
        qDebug() << "x: " << r;
    
        return r;
    }
    

    上面的"Game.exe"+00ABBBB0 = 0135bbb0,然后0135bbb0 - 00ABBBB0 = 8A0000

    1. 打印结果,这里全部是10进制,箭头后面的16进制手动加上去的
    第0层:  30277160   -> 1CD FE28
    第1层:  30034224   -> 1CA 4930
    第2层:  719894592  -> 2AE8 B840
    第3层:  882993840  -> 34A1 6AB0
    第4层:  882993884  -> 34A1 6ADC‬
    x:  455.14
    

    写字节集, 将点击一次-1的程序,改为每点击一次+2

    旧的:

    00401881 - 83 E8 01 - sub eax,01
    

    新的:

    00401881 - 83 c0 02 - add eax,02
    

    注:00401881是基址

    代码:

        DWORD PID = 0;
        DWORD aProcesses[1024], cbNeeded;
    
        if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
        {
            qDebug() << "获取失败";
            return;
        }
    
        unsigned int cProcesses = cbNeeded / sizeof(DWORD);
        unsigned int i;
        for ( i = 0; i < cProcesses; i++ )
        {
            DWORD processID = aProcesses[i];
            if(processID == 0 ) continue;
    
            char buff[255];
            HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |PROCESS_VM_READ,FALSE, processID );
            if(hProcess == NULL)continue;
            HMODULE hMod;
            DWORD cbNeeded;
    
            if (EnumProcessModules(hProcess, &hMod, sizeof(hMod),&cbNeeded) )
            {
                GetModuleBaseNameA(hProcess, hMod, (LPSTR)&buff, DWORD(sizeof(buff)/sizeof(char)));
            }
    
            QString s= QString::fromLocal8Bit(buff);
            if(s == "xxx.exe"){
                PID = processID;
                break;
            }
            CloseHandle( hProcess );
        }
    
    
        if(PID == 0) return;
    
        // 进程句柄
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE, PID);
        if(hProcess == NULL) return;
        
        // 要写入的字节集
        BYTE data[3] = {0x83, 0xc0, 0x02};
        int r = WriteProcessMemory(hProcess, LPVOID(0x401881), LPCVOID(data), SIZE_T(3), NULL);
        qDebug() << r;
    
        // 写入成功后,再次点击就能发现每次-1变成了+2
    

    参考:

    DLL 简单注入C++ video1 video2

    #include <iostream>
    #include <windows.h>
    #include <Psapi.h>
    
    DWORD  findPID(std::string name)
    {
    	DWORD PID = 0;
    	// 获取进程标识符列表。
    	DWORD aProcesses[1024], cbNeeded;
    
    	if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
    	{
    		std::cout << "EnumProcesses Error." << std::endl;
    		return PID;
    	}
    	unsigned int cProcesses = cbNeeded / sizeof(DWORD);
    	unsigned int i;
    	for (i = 0; i < cProcesses; i++)
    	{
    		DWORD processID = aProcesses[i];
    		if (processID == 0) continue;
    		char buff[255];
    		HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
    		if (hProcess == NULL) continue;
    
    		HMODULE hMod;
    		DWORD cbNeeded;
    		if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded))
    		{
    			GetModuleBaseNameA(hProcess, hMod, (LPSTR)&buff, DWORD(sizeof(buff) / sizeof(char)));
    		}
    		if (buff == name) {
    			PID = processID;
    			break;
    		}
    		CloseHandle(hProcess);
    	}
    	return PID;
    };
    
    int main()
    {
    	DWORD PID = findPID("Game.exe");
    	if (!PID)
    	{
    		printf("程序没找到");
    		return 0;
    	}
    
    	// 我编写的DLL
    	LPCSTR myDLLPath = "C:\Users\ajanuw\Desktop\injectDll\Release\injectDll.dll";
    	int nSize = strlen(myDLLPath) + 1;
    
    	// 打开一个现有的本地过程对象
    	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
    
    	// 在指定进程的虚拟地址空间内保留,提交或更改内存区域的状态。
        // 该函数将其分配的内存初始化为零。
    	LPVOID pDLLPath = VirtualAllocEx(hProcess, 0, nSize,
    		MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    
    	// 在指定的进程中将数据写入内存区域。
        // 必须写入整个区域,否则操作将失败。
    	BOOL writeOk = WriteProcessMemory(hProcess, pDLLPath, LPCVOID(myDLLPath), nSize, 0);
    
    	// 创建一个在另一个进程的虚拟地址空间中运行的线程。
    	HANDLE pLoadThread = CreateRemoteThread(hProcess, 0, 0, (LPTHREAD_START_ROUTINE)LoadLibraryA,
    		pDLLPath, 0, 0);
    
    	// 等待直到指定的对象处于发信号状态或超时间隔过去
    	WaitForSingleObject(pLoadThread, INFINITE);
    
    	if (pLoadThread == NULL) {
    		std::cout << "pLoadThread error." << std::endl;
    		return 0;
    	}
    	else CloseHandle(pLoadThread);
    
    	if (hProcess) CloseHandle(hProcess);
    
    
    	// std::cout << "DLL path alloc at: " << pDLLPath << std::endl;
    	// std::cin.get();
    
    	// 在指定进程的虚拟地址空间内释放,解除授权或释放并解除授权的内存区域。
    	// VirtualFreeEx(hProcess,pDLLPath, strlen(myDLLPath) + 1,MEM_RELEASE);
    
    	return 0;
    }
    

    injectDll.cpp:

    // dllmain.cpp : 定义 DLL 应用程序的入口点。
    #include "pch.h"
    #include <Windows.h>
    #include <iostream>
    
    void Mythread(HMODULE hModule)
    {
        
        std::cout << "<------------------------->" << std::endl;
        std::cout << "inject dll" << std::endl;
        std::cout << "<------------------------->" << std::endl;
        Sleep(3000);
        MessageBoxA(0, "a", "b", 0);
    }
    
    BOOL APIENTRY DllMain( HMODULE hModule,
                           DWORD  ul_reason_for_call,
                           LPVOID lpReserved
                         )
    {
        switch (ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:
            CloseHandle(CreateThread(0,0, (LPTHREAD_START_ROUTINE)Mythread, hModule, 0, 0));
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
        }
        
        return TRUE;
    }
    
    
    

    显示连接DLL

    #include <iostream>
    #include <Windows.h>
    
    typedef void (CALLBACK* LPFNDLLFUNC1)();
    
    int main()
    { 
        LPFNDLLFUNC1 fun;
        // 获取DLL中的a函数,LPFNDLLFUNC1类型对上
        fun = (LPFNDLLFUNC1)GetProcAddress(
                // or LoadLibrary(TEXT("C:\Users\ajanuw\Desktop\Game\Debug\ADll.dll")),
                GetModuleHandle(TEXT("C:\Users\ajanuw\Desktop\Game\Debug\ADll.dll")), 
                "a"
           );
            if (NULL != fun)
            {
                fun();
            }
            else {
                std::cout << "GetProcAddress error." << std::endl;
            }
        
        return 0;
    }
    

    另一种找pid的方法

    #include <iostream>
    #include <Windows.h>
    #include <TlHelp32.h>
    
    using namespace std;
    
    DWORD getPID(const wchar_t* name)
    {
    	DWORD pid = 0;
    	HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    	if (hSnap != INVALID_HANDLE_VALUE)
    	{
    		PROCESSENTRY32 pe;
    		pe.dwSize = sizeof(pe);
    		if (Process32First(hSnap, &pe))
    		{
    			do {
    				if (!_wcsicmp(pe.szExeFile, name)) {
    					pid = pe.th32ProcessID;
    					break;
    				}
    			} while (Process32Next(hSnap, &pe));
    		}
    	}
    	CloseHandle(hSnap);
    	return pid;
    }
    
    
    
    int main()
    {
    	cout << getPID(L"game2.exe") << endl;
    }
    
  • 相关阅读:
    2017的结束2018的开始
    .NET Core使用swagger进行API接口文档管理
    数据库可扩展设计方案
    容量估算--随时更新
    分库分表设计基础
    利用bucardo搭建PostgreSQL数据库双活
    通过pgAgent实现PostgreSQL上的自动作业
    MySQL主主配置
    Oracle统计信息不准(谓词越界)造成的性能问题
    获取Oracle中SQL语句的执行计划
  • 原文地址:https://www.cnblogs.com/ajanuw/p/12849022.html
Copyright © 2011-2022 走看看