项目实战——外挂开发(30小时精通C++和外挂实战)

项目实战——外挂开发(30小时精通C++和外挂实战)

  • 外挂开发1-监控游戏
  • 外挂开发2-秒杀僵尸
  • 外挂开发3-阳光地址分析
  • 外挂开发4-模拟阳光
  • 外挂开发5-无限阳光

外挂开发1-监控游戏

外挂的本质
有两种方式
1,修改内存中的数据
2,更改内存中的代码
找到内存地址,从此地址开始写入4个字节90909090

改代码和改数据是一样的,改阳光找到一个内存地址,将想改的数值填充到内存空间去
改代码,找到内存地址,将想要填充的数据填到内存空间

数据和代码没有本质区别

在这里插入图片描述

该内存改代码都是找到内存地址,像内存地址填充数据

明白这些后开始写代码
有个细节监控植物大战僵尸是否打开

创建一个新的线程

While(1){
If(植物大战僵尸打开){
可以点击按钮
}else{
不可以点击按钮
}
Sleep(1000);//为了不让其太过于频繁,此处隔着1秒检测一次
}

此循环是死循环,跳不出,会堵塞进程,导致其他事情干不了

所有这个代码要放到子线程去执行

打开上次写的程序创建线程
线程只需创建一次,我们在外挂程序一打开就创建线程,在初始化的地方创建

BOOL CPVZCheaterDlg::OnInitDialog()此为初始化对话框
// TODO:  在此添加额外的初始化代码
CreateThread();创建线程,返回handle句柄,通过线程句柄可以操控线程
CreateThread(_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,_In_ SIZE_T dwStackSize,_In_ LPTHREAD_START_ROUTINE lpStartAddress,		函数地址,我们可以右击转到定义看此参数含义_In_opt_ __drv_aliasesMem LPVOID lpParameter,_In_ DWORD dwCreationFlags,_Out_opt_ LPDWORD lpThreadId
);
HANDLE WINAPI CreateThread
( __in_opt   LPSECURITY_ATTRIBUTES lpThreadAttributes, // 指向SECURITY_ATTRIBUTES 的指针,为新线程指定安全描述 __in       SIZE_T dwStackSize, // 初始化线程堆栈尺寸 __in       LPTHREAD_START_ROUTINE lpStartAddress, //线程函数所指向的地址起始函数   
__in_opt   LPVOID lpParameter, // 给线程函数传递的参数   
__in       DWORD dwCreationFlags, // 有关线程的标志  __out_opt  LPDWORD lpThreadId //系统分配给线程的ID);  

要在dlg.h中创建句柄对象

	//子线程句柄HANDLE m_monitorThread;m_monitorThread = CreateThread(NULL, NULL, func, NULL, NULL, NULL);
Func返回的应该是下面的类型值需要在全局区声明DWORD (WINAPI *PTHREAD_START_ROUTINE)(LPVOID lpThreadParameter
);//用来监控游戏的线程
DWORD WINAPI monitorThreadFunc(LPVOID lpThreadParameter){
return NULL;
}FindWindow();//查看窗口是否打开,两个参数窗口类名,窗口名称
FindWindowW(_In_opt_ LPCWSTR lpClassName,
_In_opt_ LPCWSTR lpWindowName);

都是字符串类型故使用
使用工具spy++,查找窗口的望远镜,拖到游戏窗口上去,
类型MainWindow
窗口名称Plants vs. Zombies GOTY

外挂开发2-秒杀僵尸

	//当游戏窗口关闭后,不仅禁止点击还要将之前打钩的去掉g_dlg->m_bnKill.SetCheck(FALSE);g_dlg->m_bnSun.SetCheck(FALSE);

接下来就是真正的秒杀僵尸了。

真的要秒杀僵尸该如何实现此功能
打开OD,将exe载入

CTR+G	找到修改内存的地址
00566D10  |.  89B5 C8000000 mov dword ptr ss:[ebp+0xC8],esi       

;

向上找到其生命值减少的代码

00566D06      2B7424 20     sub esi,dword ptr ss:[esp+0x20]

要想将其变成下方

00566D06      2BF6          sub esi,esi   
00566D08      90            nop
00566D09      90            nop

我们看的是其机器码就是将此内存地址00566D06开始的4个字节变成后面四个字节

00566D06      2B742420    

要想将其变成下方

00566D06      2BF69090      

这样就达到了秒杀僵尸的功能了,我们发现第一个字节都是一样的,我们改后面三个字节就可以了

00566D07     742420 	//原版不需要秒杀僵尸
00566D07     F69090   //需要秒杀僵尸

不需要秒杀僵尸就将742420 覆盖地址00566D07 的内存空间
需要秒杀僵尸就将F69090 覆盖地址00566D07 的内存空间,这两者来回切换,将内存的代码换来换去

这就牵扯到一个跨进程的问题,当勾选了秒杀僵尸后,就要将这3个字节写在植物大战僵尸的内存中。
这里有个函数

static HANDLE g_processHandle;//定义一个全局句柄,可以右击OpenProcess转到定义,发现返回是HANDLEWINAPI,OpenProcess,不需要指针//这里封装的是全局函数
// 将某个值写入植物大战僵尸内存(后面的可变参数是地址链,要以-1结尾)
void WriteMemory(void *value, DWORD valueSize, ...)				//第一个参数传数据,第二个是数据有多大,如数据只有3个字节,...是个地址链
{if (value == NULL || valueSize == 0 || g_processHandle == NULL) return;DWORD tempValue = 0;va_list addresses;va_start(addresses, valueSize);DWORD offset = 0;DWORD lastAddress = 0;while ((offset = va_arg(addresses, DWORD)) != -1){lastAddress = tempValue + offset;::ReadProcessMemory(g_processHandle, (LPCVOID)lastAddress, &tempValue, sizeof(DWORD), NULL);}va_end(addresses);::WriteProcessMemory(g_processHandle, (LPVOID)lastAddress, value, valueSize, NULL);
}
//下面是重载的函数比较简单,告诉写数据,数据占的字节,数据所在地址
void WriteMemory(void *value, DWORD valueSize, DWORD address) {WriteMemory(value, valueSize, address, -1);
}//下面三句代码放在此处是,肯定发现了游戏的窗口,句柄不为空,则进程句柄也不为空//获得植物大战僵尸的进程idDWORD processPid;GetWindowThreadProcessId(windowHandle, &processPid);//此处通过植物大战僵尸的窗口句柄拿到进程id//获得植物大战僵尸的进程句柄g_processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processPid);//PROCESS_ALL_ACCESS访问内存,传权限访问内存数据,//此时进程句柄拿到了,我们就可以秒杀僵尸了等操作void CPVZCheaterDlg::OnBnClickedKill()
{if (m_bnKill.GetCheck()){//需要秒杀僵尸BYTE data[] = {0xF6,0x90,0x90};//F69090 ,此处详情看Word,这是我们要写进内存的数据WriteMemory(data,sizeof(data),0x00566D07);//写入内存,需要进程句柄,具体内容如上所示,参数比较多相对复杂,这里直接封装了一些写内存的在上面//注意上面的写内存函数是我们自定义封装好的WriteMemory,而不是系统的WriteProcessMemory,在程序开头有,这里只需传三个参数,地址}else{//不需要秒杀僵尸BYTE data[] = { 0x74, 0x24, 0x20 };//742420 ,此处详情看Word,这是我们要写进内存的数据WriteMemory(data, sizeof(data), 0x00566D07);}
}

外挂开发就这么简单,步骤
先分析对应汇编在哪里,再搞清楚将汇编改成什么,搞清楚将汇编改成什么就能搞清楚将机器码换成什么,已经搞清楚将机器码换成什么到时候将内存地址写入对应机器码就可以了

外挂就是将内存中的数据或者机器码给换掉,这里其他僵尸如安全帽的秒杀就得靠自己找了,都是一样的

外挂开发3-阳光地址分析

#include <iostream>
using namespace std;int g_age;int main(){int a = 10;g_age = 20;//局部变量地址变来变去//cout << &a << endl;//00AFFA1C	00A3FBE0/*cout << &g_age << endl;*/getchar();return 0;
}

使用CE找到阳光内存地址
发现每次打开游戏阳光内存地址是不一样的

阳光是个类的成员变量,局部变量调用是在栈空间的,所以每次打开游戏内存地址不同
而全局变量只要编译之后,内存地址都是固定的

    7: 	int a = 10;
0076530E  mov         dword ptr [ebp-8],0Ah  8: 9: 	g_age = 20;
00765315  mov         dword ptr ds:[0076F354h],14h  

局部变量a的地址是ebp-8

全局变量g_age的值是0076F354h,它的地址是写死的,只要编译完了,最终机器码里就是这个
只要编译完了,那么之后无论打开多少次程序,执行的机器码都是那个机器码,那个机器码中的地址固定死的不会变

局部变量是会变的,a的地址是ebp-8,ebp寄存器中的值是会变的
但全局变量的地址0076F354h是固定死的。

大家都有的误区

内存是什么是虚拟内存,不是内存条上的地址,真正内存条上的东西是不允许你访问的,只允许操作系统访问,操作系统会将物理内存(真正内存条的内存)和虚拟内存挂钩

举例,32位系统没打开一个exe,都会为这个exe(也可以认为是进程)分配4GB的虚拟内存,如果再打开一个exe它也有4GB的虚拟内存。设这两个虚拟内存都有相同的内存地址0X110,但此内存地址对应的真正的物理内存地址是不同的,这个由操作系统管理。

我们程序员面对的都是虚拟内存,不管是什么开发,操作系统都是这样管理内存的。
我们讲的内存地址都是虚拟内存地址,不是内存条的物理内存地址,这就是操作系统内存管理的环节了。

向内存地址里面写代码,这个游戏无论打开还是关掉,这个外挂都是好使的,还有这个游戏和外挂放到被的电脑上打开,游戏和外挂都是好使的。这说明植物大战僵尸这个游戏它不管在谁的电脑上打开多少次,它的每句代码内存地址都是固定死的。

外挂开发4-模拟阳光

我们观察到阳光的地址值是发生变化的,证明阳光不是直接一个简单的全局变量,也不是局部变量内存,局部变量调用完就没了,我们发现游戏玩了很久阳光一直都在,不能说一个函数调用完这个阳光就没了。
阳光不是局部变量,那它可能是这样
有很多类,阳光是个类

#include <iostream>
using namespace std;//int g_age;
struct Sun{int temp1;int value;//阳光值
};//游戏数据可能会弄成全局
struct GameData{int temp;Sun *sun;
};GameData *g_data;int main(){g_data = new GameData();g_data->sun = new Sun();//首先创建一个阳光对象//程序每次打开都要new阳光,地址值变换g_data->sun->value = 20;cout << &g_data->sun->value << endl;getchar();return 0;
}

既然阳光地址值每次都不一样,那我们怎么去写外挂呢?
我们可以从GameData *g_data;入手,这个指针变量地址值是不变的,这是个全局变量,意味着内存地址不会变。

g_data指针指向GameData()对象,GameData()对象里的sun指针会指向Sun()对象,这个就是模拟的结构。

全局变量的地址值是不变的。
在这里插入图片描述

全局指针变量g_data的地址值是固定死的,它存储的是gamedata的地址,我们可以通过这个找到g_data的存储空间里存储的地址(new出来的是变化的),就能找到gamedata的存储空间,找到了gamedata的存储空间就能找到成员变量sun指针(跳过前面4个字节地址)变量的存储空间,知道它里面存储的值(阳光存储空间的地址值)就能找到阳光存储空间,就能找到阳光存储空间中的阳光值value(跳过前面8个字节地址)。

只要顺着这固定死的g_data的地址值就能一直找到最后。

无论new多少次都有办法找到value在哪里,虽然每次new的对象地址发生变化了。
只要结构是这样的,我们只要找到固定死的就能找到最后的value。

New出来的地址每次是不一样的。

使用汇编来表示

0x100	是全局变量g_data的地址值
[0x100]	这是gamedata对象的地址值(中括号是取出0x100地址所存储的值)
[0x100]  是变量temp的地址值
[0x100]+0x4	这是sun指针变量的地址值
[[0x100]+0x4]	这是sun对象的地址值(sun指针变量的地址所存的东西)
[[0x100]+0x4]	+ 0X8	这就是value阳光之的内存地址

尽管阳光之value是放到堆空间的,内存地址不断的变,但我仍然可以通过一些固定的数值找到value的存储空间。

我们在使用CE时,右下角有个手动添加地址(add address manual),这里可以添加地址(此处地址为 固定地址)

先添加地址为0080F354先勾选指针,有个偏移先偏移4,后偏移8.点击确定

外挂开发5-无限阳光

关键是找阳光的上级的固定地址值全局变量

不太好找,结构非常复杂

需要不断调试,找到

到此就讲完了
无CD是可以自己找的

每个游戏不一样,代码不同,主要难点在于分析代码,这个外挂就是改内存改代码仅此而已。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3267334.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

外文文献去哪个网站查找下载又快又准

今天收到好多同学的文献求助&#xff0c;大部分都是外文文献。那么外文文献去哪里查找下载比较好呢&#xff1f;本文小编就讲解一下自己平时是在什么网站上查找获取文献的&#xff0c;下面就用几篇求助文献演示一下获取过程&#xff1a; 第一篇、OVID数据库&#xff1a;A Crit…

录音教程分享:电脑在线录音,7款录音软件免费版公开!

在我们的日常生活中&#xff0c;不可避免地会遇到需要在电脑上录制各种系统内音频的场景。无论是记录一次讲座、一段对话&#xff0c;或者录制某个重要网站上的音频&#xff0c;这种需求变得愈发重要且广泛。然而&#xff0c;对许多人来说&#xff0c;在电脑上在线录音可能是一…

菜鸟从0学微服务——MyBatis-Plus

关于“菜鸟从0学微服务” 针对有编程基础&#xff0c;开始学习微服务的同学&#xff0c;我们陆续推出从0学微服务的笔记分享。力求从各个中间件的使用来反思这些中间件的作用和优势。 会分享的比较快&#xff0c;会记录demo演算和中间件的使用过程&#xff0c;至于细节的理论…

Spark_Oracle_II_Spark高效处理Oracle时间数据:通过JDBC桥接大数据与数据库的分析之旅

接前文背景&#xff0c; 当需要从关系型数据库&#xff08;如Oracle&#xff09;中读取数据时&#xff0c;Spark提供了JDBC连接功能&#xff0c;允许我们轻松地将数据从Oracle等数据库导入到Spark DataFrame中。然而&#xff0c;在处理时间字段时&#xff0c;可能会遇到一些挑战…

计算机网络知识-面试点1

1. 三握四挥 定义&#xff1a; 在计算机网络中&#xff0c;特别是TCP/IP协议中&#xff0c;“三握”指的是三次握手&#xff08;Three-way Handshake&#xff09;&#xff0c;而“四挥”则指的是四次挥手&#xff08;Four-way Handshake&#xff09;。这两个过程分别用于TCP连接…

模式Hash和history

vuerouter有两种路由模式Hash和history。区别&#xff1a;Hash为默认模式&#xff0c;url中包含一个#符号的哈希部分。优势&#xff1a;兼容性好&#xff0c;不需要后端服务器的特殊配置。缺点&#xff1a;不够美观&#xff0c;搜索引擎优化较差。History模式使用的浏览器的His…

多模态大模型应用中的Q-Former是什么?

多模态大模型应用中的Q-Former是什么&#xff1f; Q-Former是一种新型的神经网络架构&#xff0c;专注于通过查询&#xff08;Query&#xff09;机制来改进信息检索和表示学习。在这篇博客中&#xff0c;我们将详细探讨Q-Former的工作原理、应用场景&#xff0c;并在必要时通过…

leetcode日记(55)二进制求和

将短的字符串前面补充0&#xff0c;使两字符串对其再进行加法&#xff1a; class Solution { public:string addBinary(string a, string b) {int na.size();int mb.size();if(n>m) b.insert(0,n-m,0);else if(m>n) a.insert(0,m-n,0);string c;int jw0;for(int imax(n,…

【C++指南】类和对象(上)

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《数据结构与算法》 期待您的关注

PostgreSQL的pg-collector工具

PostgreSQL的pg-collector工具 pg-collector 是一个用于 PostgreSQL 数据库的监控和数据收集工具。它主要用于收集 PostgreSQL 实例的性能指标、查询统计和日志信息&#xff0c;以便进行数据库性能分析和故障排查。通过收集这些数据&#xff0c;管理员可以更好地了解数据库的运…

减少 95% 资源的向量搜索 | 使用云搜索的 DiskANN

当前尖端的向量近邻搜索算法&#xff0c;主要以图搜索算法为主&#xff0c;此类算法为了能够最大化搜索的速度与准确度&#xff0c;需要将对应的索引结构和原始数据存放在内存中&#xff0c;显然这不仅大大提高了成本&#xff0c;还限制了数据集的大小。例如在当前主流的内存型…

快递员工告诉你,寄快递如何薅羊毛(知道这个方法,立省好几百)

谁能想象自从去了快递公司上班后&#xff0c;知道了一个惊人的内幕&#xff01;&#xff01;现在发快递和大件的&#xff0c;全国不管寄到哪都才只要5块钱呢&#xff01;&#xff01; 上门取件不说&#xff0c;不管寄多少快递&#xff0c;寄到哪里&#xff0c;仅是原价的5折。 …

MongoDB教程(二十):MongoDB正则表达式

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、正则表…

csa笔记6-网络管理命令

nmcli命令 字符终端&#xff0c;可以立即生效且重启系统后配置也不会丢失 nmtui命令 可视终端&#xff0c;立即生效&#xff0c;重启有效 network.service 管理网络 RHEL 7 以前&#xff1a;使用network.service管理网络 RHEL 7&#xff1a;使用network.service和Netwo…

springboot高等职业院校实验室信息管理-计算机毕业设计源码24015

摘 要 本文旨在设计并实现一个基于Spring Boot框架的高等职业院校实验室信息管理系统。该系统采用B/S体系结构&#xff0c;以MySQL作为数据库管理平台&#xff0c;结合前端技术如HTML、CSS和JQuery&#xff0c;为用户提供一个功能全面、操作便捷的实验室信息管理平台。 在系统设…

短视频矩阵管理系统源码可靠吗?

1. 了解短视频矩阵管理系统 短视频矩阵管理系统是一个用于管理和优化短视频内容创作、发布和推广的软件平台。它可以帮助用户分析市场趋势、选择热门话题、智能剪辑视频、发布到多个短视频平台&#xff0c;以及监控和优化视频表现。这种系统对于短视频制作团队、自媒体运营者以…

记录|服务器资源申请评估(CPU,内存,宽带等)

目录 前言一、CPU二、内存三、磁盘四、带宽更新时间 前言 参考内容&#xff1a; CPU、内存、存储、带宽&#xff0c;一次性搞清楚服务器资源评估 在申请服务器时需要评估资源需求。少了不够用&#xff0c;多了也浪费。以下内容是对参考内容的提取和理解。 一、CPU 性能指标&am…

Jsoup爬虫——自学习梳理

——项目已完结&#xff08;源码在文末&#xff09; 一个较大的项目&#xff0c;通过后台进行网站爬虫&#xff0c;选择的是一个招聘类型的网站&#xff0c;爬取数据后会选择一部分放入到我们的数据库中&#xff0c;前台通过后台返回的Json数据进行展示&#xff1b;大概就是这样…

SSRF过滤攻击

SSRF绕过&#xff1a; 靶场地址&#xff1a;重庆橙子科技SSRF靶场 这个是毫无过滤的直接读取&#xff0c;但是一般网站会设置有对SSRF的过滤&#xff0c;比如将IP地址过滤。 下面是常用的绕过方式&#xff1a; 1.环回地址绕过 http://127.0.0.1/flag.php http://017700…

Qt基础 | 自定义界面组件 | 提升法 | 为UI设计器设计自定义界面组件的Widget插件 | MSVC2019编译器中文乱码问题

文章目录 一、自定义 Widget 组件1.自定义 Widget 子类2.自定义 Widget 组件的使用 二、自定义 Qt Designer 插件1.创建 Qt Designer Widget 插件项目2.插件项目各文件的功能实现3.插件的编译与安装4.使用自定义插件5.使用 MSVC 编译器输出中文的问题 一、自定义 Widget 组件 当…