【技术分享】Python3 透视自瞄外挂制作
2022-07-20 / 0 评论 / 1,678 阅读 / 422 点赞

【技术分享】Python3 透视自瞄外挂制作

发光的神
2022-07-20 / 0 评论 / 1,678 阅读 / 正在检测是否收录...

简介

Memory64内存模块是自己无聊的时候封装的,它可以轻松的操作进程中的内存,做一些游戏辅助还是可以的,模块源码已上传Github上,现在的版本是1.0.3后续会继续更新的。

larth7dg.png

Github 项目

安装教程

laru5lhk.png

pip install Memory64

1.通过Python自带的pip工具就可以安装模块,模块只支持32位Python,64位Python并不兼容。

使用步骤

laru6rgn.png

python -c "import Memory64; print(Memory64.version)"

1.安装好后,在终端输入这行命令,查看下模块版本,正常显示没有报错就证明安装成功了。

取64位模块地址

lartz181.png

from Memory64.Bin32 import *

hwnd = Openhwnd("Calculator.exe")  # 打开进程句柄
pid = GetProcPid("Calculator.exe")  # 获取进程PID
mod1 = GetModuleAddr64(hwnd, "shlwapi.dll")  # 通过进程句柄获取64位程序模块基址
mod2 = GetModule2(pid, "shlwapi.dll")  # 通过进程PID获取64位程序模块基址
print(pid, hwnd, mod1, mod2)  # 输出进程PID, 进程句柄, 输出模块基址

2.这里我用64位程序计算器,做一个演示看看能不能读到内存地址,很显然是没问题的。

读64位进程内存

larug2d2.png

from Memory64.Bin32 import *

hwnd = Openhwnd("Calculator.exe")  # 打开名为"Calculator.exe"的程序句柄
mod1 = GetModuleAddr64(hwnd, "shlwapi.dll")  # 通过进程句柄获取模块基址"shlwapi.dll"
print(ReadMemory64Int(hwnd, mod1))  # 读取指定模块基址的64位内存整数

3.通过模块读下地址数值,也是没有问题的,后面就不演示了,直接放代码。

写64位进程内存

from Memory64.Bin32 import *

hwnd = Openhwnd("Calculator.exe")  # 打开名为"Calculator.exe"的程序句柄
mod1 = GetModuleAddr64(hwnd, "shlwapi.dll")  # 获取模块"shlwapi.dll"的基址
addr = ReadMemory64Int(hwnd, 0x7FF8E64CEC48)  # 从指定地址读取64位内存整数
addr2 = ReadMemory64Int(hwnd, mod1 + 0x4EC48)  # 使用模块基址加上偏移读取64位内存整数
print(addr, addr2)  # 输出两个读取的内存地址值
WriteMemory64Int(hwnd, mod1 + 0x4EC48, 10)  # 在模块基址加上偏移地址写入整数值10
WriteMemory64Float(hwnd, mod1 + 0x4EC48, 5.261)  # 写入小数值5.261
WriteMemory64Int(hwnd, mod1 + 0x4EC48, 10)  # 在同一地址写入整数值10
bytesa = "11 33 30 32 32 33 35 40 40 58"  # 定义一个字节集数据
WriteMemory64Bytes(hwnd, 0x7FF77E2BE72E, bytesa, 10)  # 写入指定地址的字节集数据

绘制透明方框

larvgvso.png

from Memory64 import FindWindowPid   # 导入内存访问模块
import Memory64.D3Gui                # 导入图形绘制模块

hwnd = FindWindowPid(None, "xxx")[0]  # 通过窗口名称查找窗口句柄
draw = Memory64.D3Gui.ExecDraw(hwnd)  # 初始化图形绘制模块

while True:
    draw.startLoop()                   # 开始绘制段
    draw.drawRect(100, 100, 100, 100, 5, (255, 254, 0))  # 绘制矩形,参数依次是起始 x 坐标, 起始 y 坐标, 宽度, 高度, 边框宽度, 颜色 (R, G, B)
    draw.endLoop()                     # 结束绘制段

如何打包

最好用这种形式打包:打包方式


外挂类型分类

  1. AI外挂

    • 基于目标检测模型,如 YOLOv5。
    • 通过训练目标检测模型,对游戏画面进行分析,检测敌人并自动移动射击。
    • 其原理简单,主要依赖于图像处理与深度学习模型,效果一般,适用于辅助操作,但不涉及游戏内修改。
  2. 内存外挂

    • 使用工具如 Cheat Engine(CE)或 Ollydbg(OD)进行内存操作。
    • 强大的内存修改能力,可以直接更改游戏数据,但容易被反作弊系统检测。
    • 需要掌握游戏内存结构以及通过端口拦截或hook技术来规避检测。
  3. 封包外挂

    • 使用工具如 WPE来抓包并修改数据包。
    • 能够欺骗服务器,通过修改包内容实现功能,例如刷枪、强登账号等。
    • 数据包(TCP/UDP)可能部分加密,通过技术如异或解密来获取未加密数据部分。
  4. 脚本外挂

    • 模拟玩家的鼠标、键盘操作,通过脚本自动化完成任务。
    • 比较简单,适合用来执行重复性操作,但效果有限,仅能辅助功能性增强。

代码实现原理

  • Python3 实现

    • 代码结构基于图像处理、内存修改或网络抓包技术。
    • Python可以通过封装库、调用Windows API 或使用现成工具库来实现外挂功能。
    • 例如,可以使用 Memory64 库或直接调用内存操作来实现内存外挂。
  • 工具推荐

    • Cheat Engine (CE):内存操作与调试工具。
    • Ollydbg (OD):二进制文件调试工具,适用于反汇编和内存调试。
    • WPE:抓包工具,用于数据包编辑与欺骗服务器。
  • 实现说明

    • 所有外挂技术基础都是基于对游戏系统的分析和利用系统漏洞进行功能扩展。
    • 所有方法都涉及一定程度的反向工程与安全风险,因此需要谨慎使用。
  • 注意事项

    • 所有外挂功能都需要在合法范围内使用,否则可能面临法律后果或账户封禁。
    • 游戏外挂涉及风险,因此建议仅用于学习和研究,切勿用于商业或非法用途。

自瞄代码

from Memory64 import *  # 导入自定义的内存访问模块
from math import *

# 获取游戏窗口句柄和进程ID
hwnd, thre, pid = FindWindowPid("Valve001", None)  # 取游戏窗口句柄
func = SetupProce(pid)  # 设置进程
Modlue_m = func.GetBaseAddr("cstrike.exe")  # 获取模块基址
Modlue_e = func.GetBaseAddr("engine_amxx.dll")

# 读取特定内存地址的玩家坐标
Pom = func.ReadMemory(Modlue_m + 0x1033240)

# 计算二维坐标之间的距离
def Get_Distance(x1, y2, ex, ey):
    return sqrt((x1 - ex)**2 + (y2 - ey)**2) / 20

# 启动自瞄功能
def Start_AiMBot():
    my_x = func.ReadMemory_float(Pom + 0x88)  # 读取玩家 x 坐标
    my_y = func.ReadMemory_float(Pom + 0x8C)
    my_z = func.ReadMemory_float(Pom + 0x90)
    Enemy_data = []  # 存储敌人数据
    Number = 133988  # 初始读取偏移地址

    # 遍历敌人的坐标
    for _ in range(0, 10):
        Number += 4
        Poe = func.ReadMemory(Modlue_e + Number)  # 读取敌人坐标
        enemy_x = func.ReadMemory_float(Poe + 0x88)
        enemy_y = func.ReadMemory_float(Poe + 0x8C)
        enemy_z = func.ReadMemory_float(Poe + 0x90)
        enemy_hp = func.ReadMemory_float(Poe + 0x1E0)

        differ_x = enemy_x - my_x
        differ_y = enemy_y - my_y
        _distan = sqrt(differ_x**2 + differ_y**2)

        differ = Get_Distance(my_x, my_y, enemy_x, enemy_y)
        AiMBot_y = atan((my_z - enemy_z) / _distan) / pi * 180

        # 计算角度
        if differ_x > 0 and differ_y > 0:
            AiMBot_x = atan(differ_y / differ_x) / pi * 180  # 计算第一象限

        if differ_x < 0 and differ_y > 0:
            AiMBot_x = atan(differ_y / differ_x) / pi * 180 + 180  # 计算第二象限

        if differ_x < 0 and differ_y < 0:
            AiMBot_x = atan(differ_y / differ_x) / pi * 180 + 180  # 计算第三象限

        if differ_x > 0 and differ_y < 0:
            AiMBot_x = atan(differ_y / differ_x) / pi * 180  # 计算第四象限

        Enemy_data.append([differ, enemy_hp, AiMBot_x, AiMBot_y])
        Enemy_data.sort()
        if Enemy_data[0][1] < 1:
            del Enemy_data[0]  # 删除血量小于1的敌人数据

    try:
        func.WriteMemory_float(Modlue_m + 0x19E10C4, Enemy_data[0][3] + 1)  # 设置准星 y 轴位置
        func.WriteMemory_float(Modlue_m + 0x19E10C8, Enemy_data[0][2])  # 设置准星 x 轴位置
    except Exception:
        pass

# 程序主逻辑
if __name__ == '__main__':
    try:
        while True:
            if MonitorHotkeys(0x20) != 0:  # 按空格键开启自瞄
                Start_AiMBot()
    except KeyboardInterrupt:
        exit()

自瞄讲解

透视代码

from Memory64 import *  # 导入内存访问模块
import Memory64.D3Gui  # 导入图形绘制模块
import numpy as np  # 导入数学操作模块

# 获取游戏窗口句柄和进程ID
hwnd, thre, pid = FindWindowPid("Valve001", None)
Addr = SetupProce(pid)  # 设置目标进程
Modlue_e = Addr.GetBaseAddr("amxmodx_mm.dll")  # 获取模块基址
Draws = Memory64.D3Gui.ExecDraw(hwnd)  # 初始化图形绘制对象

# 初始化矩阵和窗口尺寸
Matarray = np.zeros([4, 4])
GameWinWidth = 1030 / 2
GameWinHeight = 797 / 2

# 开启循环绘制
while True:
    Draws.startLoop()  # 启动绘制循环
    initNumber = -4  
    for i in range(4):
        for j in range(4):
            initNumber += 4
            Matarray[i][j] = Addr.ReadMemory_float(0x2C20100 + initNumber)  # 读取矩阵数据

    offset = 0xFFFFFFFFFFFFFCDC
    for _ in range(2):  # 读取敌人坐标数据
        offset += 0x324
        Poe = Addr.ReadMemory(Modlue_e + 0x1CFE08)  # 读取敌人数据块基址
        enemy_x = Addr.ReadMemory_float(Poe + 0x88 + offset)  # 读取敌人 x 坐标
        enemy_y = Addr.ReadMemory_float(Poe + 0x8C + offset)  # 读取敌人 y 坐标
        enemy_z = Addr.ReadMemory_float(Poe + 0x90 + offset)  # 读取敌人 z 坐标

        # 计算投影坐标
        Vorz = Matarray[0][2] * enemy_x + Matarray[1][2] * enemy_y + Matarray[2][2] * enemy_z + Matarray[3][2]
        row = 1 / Vorz
        VorX = GameWinWidth + (Matarray[0][0] * enemy_x + Matarray[1][0] * enemy_y + Matarray[2][0] * enemy_z + Matarray[3][
            0]) * row * GameWinWidth  # x 坐标投影
        VorY = GameWinHeight - (Matarray[0][1] * enemy_x + Matarray[1][1] * enemy_y + Matarray[2][1] * (enemy_z - 50) + Matarray[3][
            1]) * row * GameWinHeight  # y 坐标投影
        VorY2 = GameWinHeight - (Matarray[0][1] * enemy_x + Matarray[1][1] * enemy_y + Matarray[2][1] * (enemy_z + 30) + Matarray[3][
            1]) * row * GameWinHeight  # 第二个 y 坐标投影

        if Vorz < 0:  # 如果投影深度小于零,跳过当前循环
            continue

        FanHeight = VorY - VorY2  # 计算高度差
        FanWidth = FanHeight * 0.5  # 计算宽度
        Draws.drawText("ACT忆梦", 30, 20, 50, (255, 255, 0))  # 绘制文本
        Draws.drawRect(VorX - FanWidth / 2, VorY2, FanWidth, FanHeight, 2, (255, 255, 0))  # 绘制矩形

    Draws.endLoop()  # 结束绘制循环

lor08b16.png

自瞄效果

透视效果

422

评论 (0)

取消
0:00