jsp网站开发典型模块与实例精讲,做网站的怎么获取客户信息,wordpress for linux,公共信息服务平台官网项目实战——外挂开发#xff08;30小时精通C和外挂实战#xff09; 外挂开发1-监控游戏外挂开发2-秒杀僵尸外挂开发3-阳光地址分析外挂开发4-模拟阳光外挂开发5-无限阳光 外挂开发1-监控游戏
外挂的本质 有两种方式 1#xff0c;修改内存中的数据 2#xff0c;更改内存中… 项目实战——外挂开发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载入
CTRG 找到修改内存的地址
00566D10 |. 89B5 C8000000 mov dword ptr ss:[ebp0xC8],esi ;
向上找到其生命值减少的代码
00566D06 2B7424 20 sub esi,dword ptr ss:[esp0x20]要想将其变成下方
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转到定义发现返回是HANDLEWINAPIOpenProcess不需要指针//这里封装的是全局函数
// 将某个值写入植物大战僵尸内存后面的可变参数是地址链要以-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-8ebp寄存器中的值是会变的 但全局变量的地址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是可以自己找的
每个游戏不一样代码不同主要难点在于分析代码这个外挂就是改内存改代码仅此而已。