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;
}

qt 取进程列表,读写内存, 写字节集的更多相关文章

  1. Linux就这个范儿 第15章 七种武器 linux 同步IO: sync、fsync与fdatasync Linux中的内存大页面huge page/large page David Cutler Linux读写内存数据的三种方式

    Linux就这个范儿 第15章 七种武器  linux 同步IO: sync.fsync与fdatasync   Linux中的内存大页面huge page/large page  David Cut ...

  2. (转载)C#使用MemoryStream类读写内存

    MemoryStream和BufferedStream都派生自基类Stream,因此它们有很多共同的属性和方法,但是每一个类都有自己独特的用法.这两个类都是实现对内存进行数据读写的功能,而不是对持久性 ...

  3. MemoryStream类读写内存

    和FileStream一样,MemoryStream和BufferedStream都派生自基类Stream,因此它们有很多共同的属性和方法,但是每一个类都有自己独特的用法.这两个类都是实现对内存进行数 ...

  4. Linux就这个范儿 第18章 这里也是鼓乐笙箫 Linux读写内存数据的三种方式

    Linux就这个范儿 第18章  这里也是鼓乐笙箫  Linux读写内存数据的三种方式 P703 Linux读写内存数据的三种方式 1.read  ,write方式会在用户空间和内核空间不断拷贝数据, ...

  5. 启动期间的内存管理之build_zonelists初始化备用内存域列表zonelists--Linux内存管理(十三)

    1. 今日内容(第二阶段(二)–初始化备用内存域列表zonelists) 我们之前讲了在memblock完成之后, 内存初始化开始进入第二阶段, 第二阶段是一个漫长的过程, 它执行了一系列复杂的操作, ...

  6. C#使用MemoryStream类读写内存

    MemoryStream和BufferedStream都派生自基类Stream,因此它们有很多共同的属性和方法,但是每一个类都有自己独特的用法.这两个类都是实现对内存进行数据读写的功能,而不是对持久性 ...

  7. Qt 下载列表地址

    每次下载Qt总是找好长时间,收藏一下地址 Qt 下载列表地址 https://www.qt.io/download-open-source/#section-9 教育网镜像下载 http://mirr ...

  8. Qt: 读写二进制文件(写对象, 原始数据等)

    #include <iostream>#include <QFile>#include <QImage>#include <QMap>#include ...

  9. Qt 下快速读写Excel指南(尘中远)

    Qt Windows 下快速读写Excel指南 很多人搜如何读写excel都会看到用QAxObject来进行操作,很多人试了之后都会发现一个问题,就是慢,非常缓慢!因此很多人得出结论是QAxObjec ...

随机推荐

  1. CF486B

    扯在前面 本人找规律找了很长时间,然后发现找到规律之后其实是lj题,于是五分钟敲完代码,然后WA了两发 正文 题意: A, B 都是 n*m 的 01 矩阵,已知 B 矩阵是由A矩阵以一种规则生成 B ...

  2. LOJ10082

    题目描述 原题来自:Centrual Europe 2005 我们有N个字符串,每个字符串都是由 a 至 z 的小写英文字母组成的.如果字符串A的结尾两个字符刚好与字符串B的开头两个字符匹配,那么我们 ...

  3. SpringMVC听课笔记(七:Restful CRUD)

    这章貌似没有什么可讲的,可以看GitHub工程代码: https://github.com/heyboom/SpringMVC_Rest_CRUD

  4. Integer的十进制转二,八,十六进制

    1,toBinaryString(int i) 将i以二进制形式输出出来 2,toOctalString(int i)将i以八进制形式输出出来 3,toHexString(int i)将i以十六进制形 ...

  5. valgrind和Kcachegrind性能分析工具详解

    一.valgrind介绍 valgrind是运行在Linux上的一套基于仿真技术的程序调试和分析工具,用于构建动态分析工具的装备性框架.它包括一个工具集,每个工具执行某种类型的调试.分析或类似的任务, ...

  6. react+ant design 项目执行yarn run eject 命令后无法启动项目

    如何将内建配置全部暴露? 使用create-react-app结合antd搭建的项目中,项目目录没有该项目所有的内建配置, 1.执行yarn run eject 执行该命令后,运行项目yarn sta ...

  7. IP路由__静态路由

    1.静态路由的优缺点: 优点:对于路由器的CPU没有管理性开销,它意味着如果你不使用动态路由选择的话,你可能应该购买更为便宜的路由器.在路由器之间没有带宽占用,它意味着在WAN链接中你可以节省更多的钱 ...

  8. JVM调优之垃圾定位、垃圾回收算法、垃圾处理器对比

    谈垃圾回收器之前,要先讲讲垃圾回收算法,以及JVM对垃圾的认定策略,JVM垃圾回收器是垃圾回收算法的具体实现,了解了前面的前置知识,有利于对垃圾回收器的理解. 什么是垃圾? 垃圾,主要是指堆上的对象, ...

  9. Java之jdk环境变量配置

    1.jdk下载(按平时下载,注意一下路径就行)2.配置环境变量 :JAVA_HOME.Path.ClassPath3.检查是否成功:(查一下版本,可省略).运行环境(java.javac) 2:电脑- ...

  10. [SCOI2009] [BZOJ1026] windy数

    windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道, 在A和B之间,包括A和B,总共有多少个windy数?\(1 \le A \le ...