C语言-植物大战僵尸-刷僵尸call;fps游戏CS-方框透视(矩阵+传统)前言:大家好,我是向上先生,嘿嘿~最近在学习逆向、反汇编等等,首先我在非常感谢52pojie这个平台,差不多很多学习资源都是在这个平台得到的,也学到了非常多的知识;才申请会员通过,这是第一篇帖子。
一、植物大战僵尸辅助(远程线程注入)
主要讲解一个刷僵尸call,其他的功能自行学习,不懂的联评论后解答,首先通过CE和OD分析,通过搜索场上僵尸数量,作为突破口
我们来到OD通过CTRL+G来到41de07这里,首先我们分析一下,刷僵尸这个call应该需要哪些参数,应该会有刷在哪里,刷什么僵尸,也许不会有参数,直接在call里通过代码随机生成等等情况;然后下断点,找到上一层调用的地方,观察堆栈变化根据返回地址找到调用的call;
由于栈是先进后出,调用关系就是由上到下,我们找的时候就应该由上往下跟随
将原来的eax==1 esi == 0 改为 eax == 2 esi == 1,后面又来了两次改为eax == 2 esi == 3,得出eax为行数,esi为类型
接下来就简单了,我们需要edi的值,去CE中直接直接搜索edi的值,下访问断点是要保证od必须脱钩,否则不可以。结果edi的值为 [[6a9ec0 ]+ 0x768]。
代码讲解:
1、dll代码:
DWORD WINAPI readCount(LPVOIDlParam)是自己dll里创建线程的回调函数
BOOL APIENTRY DllMain(HANDLE hModule,,DWORD ul_reason_for_call,,LPVOID lpReserved) 是Dll的入口
功能代码讲解:
getProcessHandleByName(char* name);根据进程名获取PID
injectDll(HANDDLE handle,char* key,int address);通过远程线程注入Dll
种植无CD线程函数
刷僵尸功能
主函数,入口
Dll完整代码:
dll.txt
(1.35 KB, 下载次数: 195)
(编译后会得到一个TestDll.dll)
功能控制完整代码:
功能.txt
(3.32 KB, 下载次数: 189)
测试代码结果如图:
二、fps游戏 CS方框透视原理(矩阵+传统坐标转换)
我采用的是GDI窗口绘制,需要干的事就是创建一个窗口,这个窗口透明并且具有穿透效果和置于顶层等特点。然后就是根据敌人和自己坐标点绘制方框。
第一种方式:传统型转换坐标原理:
CE搜索自己和敌人坐标标的基址,我喜欢找z坐标,然后x、y坐标就是z坐标地址 -8、-4;x、y、z坐标不会东一个西一个,因为在3d游戏中坐标都是通过向量Vector3存储,我们找的很多都是游戏引擎规定好了的东西。就不带着大家去找了,给大家说一下方法就行了,掌握方法;
自己坐标:
CE搜索方法:通过搜索z坐标,CE选择未知的初始值,改变Z坐标,然后改变了或者增加了或者减少了,不动时未改变不断过滤;说的迷迷糊糊~~哈哈
自己坐标基址:0x223d24d4
Z坐标:+ 0x350
X坐标:+ 0x348
Y坐标:+ 0x34c
敌人坐标:
CE搜索方法:通过自己坐标位置,然后搜索值大于,值小于,改变,未改变,不断过滤。
第一个敌人基址:0x223d24e4
Z坐标:+ 0x350
X坐标:+ 0x348
Y坐标:+ 0x34c
鼠标:
CE搜索方法:通过移动鼠标,搜索改变了,未改变,不断过滤。
鼠标X: 0x20326ec0
鼠标Y: 0x20326ebc
传统坐标换算关键代码:
[C] 纯文本查看 复制代码 // 线程函数 透视
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
DWORD addr;
while(F1_Statue)
{
// 读取自己信息
ReadProcessMemory(handle,(void*)(0x223d24d4),&addr,sizeof(DWORD),NULL);
ReadProcessMemory(handle,(void*)(addr+0x348),&selfBody.x,sizeof(DWORD),NULL);
ReadProcessMemory(handle,(void*)(addr+0x34c),&selfBody.y,sizeof(DWORD),NULL);
ReadProcessMemory(handle,(void*)(addr+0x350),&selfBody.z,sizeof(DWORD),NULL);
ReadProcessMemory(handle,(void*)(addr+0x22c),&selfBody.ct,sizeof(DWORD),NULL);
ReadProcessMemory(handle,(void*)(addr+0x9C),&selfBody.hp,sizeof(DWORD),NULL);
for(int i = 1;i<sum;i++)
{
// 获取敌人坐标
ReadProcessMemory(handle,(void*)(0x223d24d4 + i * 0x10),&addr,sizeof(DWORD),NULL);
ReadProcessMemory(handle,(void*)(addr+0x348),&emBox[i-1].x,sizeof(DWORD),NULL);
ReadProcessMemory(handle,(void*)(addr+0x34c),&emBox[i-1].y,sizeof(DWORD),NULL);
ReadProcessMemory(handle,(void*)(addr+0x350),&emBox[i-1].z,sizeof(DWORD),NULL);
ReadProcessMemory(handle,(void*)(addr+0x22c),&emBox[i-1].ct,sizeof(DWORD),NULL);
// 血量
ReadProcessMemory(handle,(void*)(addr+0x9C),&emBox[i-1].hp,sizeof(DWORD),NULL);
// 计算方框坐标tan(a-b) = [tan(a)-tan(b)]/[1+tan(a)tan(b)]
ReadProcessMemory(handle,(void*)0x20326ec0,&mousePoint.x,sizeof(DWORD),NULL);
ReadProcessMemory(handle,(void*)0x20326ebc,&mousePoint.y,sizeof(DWORD),NULL);
//tan(b)
//判断象限
if((emBox[i-1].x - selfBody.x) > 0)
{
// 一四象限
if((emBox[i-1].y - selfBody.y) > 0)
{
// 一 坐标转换代码
float tanA = tan((mousePoint.x*3.1415/180.0));
float tanB = (emBox[i-1].y - selfBody.y)/(emBox[i-1].x - selfBody.x);
emBox[i-1].cx = (box.width/2) + (box.width/2)*((tanA - tanB)/(1+tanA*tanB)) -10;
float sqrtX = sqrt((emBox[i-1].x - selfBody.x)*(emBox[i-1].x - selfBody.x) + (emBox[i-1].y - selfBody.y)*(emBox[i-1].y - selfBody.y));
tanA = tan((-mousePoint.y*3.1415/180.0));
tanB = (emBox[i-1].z - 68 - selfBody.z)/sqrtX;
emBox[i-1].cy = (box.height/2) + (box.height/2)*((tanA - tanB)/(1+tanA*tanB)) + 50*tanA;
tanB = (emBox[i-1].z - selfBody.z)/sqrtX;
emBox[i-1].ch = (box.height/2) + (box.height/2)*((tanA - tanB)/(1+tanA*tanB)) + 50*tanA;
}
}
}
InvalidateRect(hwnd,NULL,true);
Sleep(150);
}
return 0;
}
传统方式效果图:
第二种方式:矩阵转换坐标
原理:
所谓矩阵就是关于游戏摄像机的一组数据,一般都是4*4和4*3,这是游戏引擎决定的;然后根据这组数据套用公式直接可以得到屏幕坐标,至于公式怎么来的,这里一下子也说不清,感兴趣的可以自己去学习一下,有点复杂,就是一些列的矩阵计算。
公式:
Temp = 矩阵[2][0] * 敌人X坐标 + 矩阵[2][1] * 敌人Y坐标 + 矩阵[2][2] * 敌人Z坐标 + 矩阵[2][3];
计算比例 = 1 / Temp;
屏幕X坐标 = 屏幕/2 + (屏幕/2 )* 计算比例 * (矩阵[0][0] * 敌人X坐标 + 矩阵[0][1] * 敌人Y坐标 + 矩阵[0][2] * 敌人Z坐标 + 矩阵[0][3]);
屏幕Y坐标 = 屏幕/2 + (屏幕/2 )* 计算比例 * (矩阵[1][0] * 敌人X坐标 + 矩阵[1][1] * 敌人Y坐标 + 矩阵[1][2] * 敌人Z坐标 + 矩阵[1][3]);
CE搜索方法:
通过一把狙,不要也行~~,未知初始值,移动鼠标改变,不动未改变,开镜改变,收镜改变,不断过滤~~哈哈也是迷迷糊糊。主要我描述不清楚,还是要通过视频,自己在网上找一些
CS矩阵图:
红色的就是矩阵,矩阵特点:第一个值在不开镜的情况下,一般不会超过2不会小于-2且开局不动都是0;第一行第三个值不会变;有一行或列是比较大的数值。满足这几个条件一般都是矩阵~~
[C] 纯文本查看 复制代码 // 线程函数 透视
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
float matrixData[4][4] = {0};
DWORD addr;
while(F1_Statue)
{
int temp = 0;
for(int k = 0;k < 4;k++)
{
for(int j = 0; j < 4;j++)
{
ReadProcessMemory(handle,(void*)(0x2048BC9C + temp * 0x4),&matrixData[k][j],sizeof(DWORD),NULL);
temp++;
}
}
// 读取自己信息
ReadProcessMemory(handle,(void*)(0x223d24d4),&addr,sizeof(DWORD),NULL);
ReadProcessMemory(handle,(void*)(addr+0x348),&selfBody.x,sizeof(DWORD),NULL);
ReadProcessMemory(handle,(void*)(addr+0x34c),&selfBody.y,sizeof(DWORD),NULL);
ReadProcessMemory(handle,(void*)(addr+0x350),&selfBody.z,sizeof(DWORD),NULL);
ReadProcessMemory(handle,(void*)(addr+0x22c),&selfBody.ct,sizeof(DWORD),NULL);
ReadProcessMemory(handle,(void*)(addr+0x9C),&selfBody.hp,sizeof(DWORD),NULL);
for(int i = 1;i<sum;i++)
{
// 获取敌人坐标
ReadProcessMemory(handle,(void*)(0x223d24d4 + i * 0x10),&addr,sizeof(DWORD),NULL);
ReadProcessMemory(handle,(void*)(addr+0x348),&emBox[i].x,sizeof(DWORD),NULL);
ReadProcessMemory(handle,(void*)(addr+0x34c),&emBox[i].y,sizeof(DWORD),NULL);
ReadProcessMemory(handle,(void*)(addr+0x350),&emBox[i].z,sizeof(DWORD),NULL);
ReadProcessMemory(handle,(void*)(addr+0x22c),&emBox[i].ct,sizeof(DWORD),NULL);
// 血量
ReadProcessMemory(handle,(void*)(addr+0x9C),&emBox[i].hp,sizeof(DWORD),NULL);
// 屏幕坐标
emBox[i].cz = matrixData[2][0] * emBox[i].x + matrixData[2][1] * emBox[i].y + matrixData[2][2] * emBox[i].z + matrixData[2][3];
emBox[i].cz = 1 / emBox[i].cz;
// 通过矩阵数据转换为屏幕坐标
emBox[i].cx = (box.width/2) + (box.width/2) * emBox[i].cz * (matrixData[0][0] * emBox[i].x + matrixData[0][1] * emBox[i].y + matrixData[0][2] * emBox[i].z + matrixData[0][3]);
emBox[i].cy = (box.height/2) - (box.height/2) * emBox[i].cz * (matrixData[1][0] * emBox[i].x + matrixData[1][1] * emBox[i].y + matrixData[1][2] * emBox[i].z + matrixData[1][3]);
emBox[i].ch = (box.height/2) - (box.height/2) * emBox[i].cz * (matrixData[1][0] * emBox[i].x + matrixData[1][1] * emBox[i].y + matrixData[1][2] * (emBox[i].z + 68) + matrixData[1][3]);
}
InvalidateRect(hwnd,NULL,true);
Sleep(150);
}
return 0;
}
矩阵方式效果图:
|