c语言游戏call调用,C语言-植物大战僵尸-刷僵尸call;fps游戏CS-方框透视(矩阵+传统)...

C语言-植物大战僵尸-刷僵尸call;fps游戏CS-方框透视(矩阵+传统)前言:大家好,我是向上先生,嘿嘿~最近在学习逆向、反汇编等等,首先我在非常感谢52pojie这个平台,差不多很多学习资源都是在这个平台得到的,也学到了非常多的知识;才申请会员通过,这是第一篇帖子。

一、植物大战僵尸辅助(远程线程注入)

主要讲解一个刷僵尸call,其他的功能自行学习,不懂的联评论后解答,首先通过CE和OD分析,通过搜索场上僵尸数量,作为突破口

thread-1123569-1-1.html

我们来到OD通过CTRL+G来到41de07这里,首先我们分析一下,刷僵尸这个call应该需要哪些参数,应该会有刷在哪里,刷什么僵尸,也许不会有参数,直接在call里通过代码随机生成等等情况;然后下断点,找到上一层调用的地方,观察堆栈变化根据返回地址找到调用的call;

thread-1123569-1-1.html

thread-1123569-1-1.html

由于栈是先进后出,调用关系就是由上到下,我们找的时候就应该由上往下跟随

thread-1123569-1-1.html

thread-1123569-1-1.html

thread-1123569-1-1.html

thread-1123569-1-1.html

将原来的eax==1 esi == 0  改为 eax == 2  esi == 1,后面又来了两次改为eax == 2  esi == 3,得出eax为行数,esi为类型

thread-1123569-1-1.html

接下来就简单了,我们需要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的入口

thread-1123569-1-1.html

thread-1123569-1-1.html

功能代码讲解:

getProcessHandleByName(char* name);根据进程名获取PID

thread-1123569-1-1.html

injectDll(HANDDLE handle,char* key,int address);通过远程线程注入Dll

thread-1123569-1-1.html

种植无CD线程函数

thread-1123569-1-1.html

刷僵尸功能

thread-1123569-1-1.html

主函数,入口

thread-1123569-1-1.html

thread-1123569-1-1.html

Dll完整代码:

7475c8e25616fa82a2fe85bc6ac87ac9.gif

dll.txt

(1.35 KB, 下载次数: 125)

2020-3-5 14:36 上传

点击文件名下载附件

下载积分: 吾爱币 -1 CB

(编译后会得到一个TestDll.dll)

功能控制完整代码:

7475c8e25616fa82a2fe85bc6ac87ac9.gif

功能.txt

(3.32 KB, 下载次数: 117)

2020-3-5 14:37 上传

点击文件名下载附件

下载积分: 吾爱币 -1 CB

测试代码结果如图:

thread-1123569-1-1.html

二、fps游戏 CS方框透视原理(矩阵+传统坐标转换)

我采用的是GDI窗口绘制,需要干的事就是创建一个窗口,这个窗口透明并且具有穿透效果和置于顶层等特点。然后就是根据敌人和自己坐标点绘制方框。

第一种方式:传统型转换坐标原理:

thread-1123569-1-1.html

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

{

// 获取敌人坐标

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;

}

传统方式效果图:

thread-1123569-1-1.html

thread-1123569-1-1.html

第二种方式:矩阵转换坐标

原理:

所谓矩阵就是关于游戏摄像机的一组数据,一般都是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矩阵图:

55fd2b2273b5a8b4531f72773c469d6e.gif

矩阵CE.png (960.39 KB, 下载次数: 4)

2020-3-5 15:32 上传

红色的就是矩阵,矩阵特点:第一个值在不开镜的情况下,一般不会超过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

{

// 获取敌人坐标

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;

}

矩阵方式效果图:

thread-1123569-1-1.html

thread-1123569-1-1.html

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值