本库有 Windows 版 与 Linux 版 两套实现,函数名、参数位宽、返回值语义完全一致,
因此下面的函数表两版通用;两版的平台差异(模块/符号解析方式、权限、依赖、文本编码)
集中在文中标注与"六、Linux 版差异"一节。
依赖:
- Windows:需系统安装 Keystone(MSYS2:
pacman -S mingw-w64-ucrt-x86_64-keystone),编译加 -lkeystone,运行时需 libkeystone.dll 可被找到
- Linux:编译只需 gcc + binutils;Keystone 为可选运行时依赖(dlopen 加载,
见"七、Linux 版构建与依赖")
| 函数 |
参数 |
返回值 |
用途 |
| fix_encoding() |
无 |
整数型 0 |
修复中文输出(Windows=切控制台代码页为 UTF-8;Linux=setlocale) |
| GetprocessID(进程名) |
进程名: 文本型 |
整数型 PID,0=未找到 |
按进程名取进程 ID |
| hex_to_dec(十六进制文本) |
十六进制: 文本型 |
长整数型,非法返回 0 |
十六进制文本转十进制数值 |
| dec_to_hex(十进制数值) |
数值: 长整数型 |
文本型(大写十六进制) |
十进制数值转十六进制文本;返回静态缓冲区,连续调用互相覆盖 |
| 函数 |
参数 |
返回值 |
用途 |
| GetprocessHWND(PID, 窗口标题, 窗口类名) |
PID: 整数型;标题/类名: 文本型,可空 |
整数型窗口句柄,失败返回 0 |
按 PID+标题+类名找窗口。Linux 无窗口句柄概念,恒返回 0(NULL) |
| Createthread(函数指针, 参数) |
函数: 子程序指针;参数: 通用型 |
整数型线程句柄,失败返回 0 |
创建线程(普通函数即可)。Linux 用 pthread 实现 |
| Waitthread(线程句柄) |
句柄: 整数型 |
整数型等待结果(0=线程已结束) |
无限等待线程结束。Linux 远程线程=轮询 /proc//task/ 直至退出 |
| Closethread(线程句柄) |
句柄: 整数型 |
逻辑型 |
关闭线程句柄 |
| 函数 |
参数 |
返回值 |
用途 |
| Memory64_Setprocess(PID, 模式) |
PID: 整数型;模式: 逻辑型 |
逻辑型 |
打开进程并保存句柄。Windows:真=nt 假=zw;Linux:真=优先 process_vm_readv,假=优先 /proc//mem(两条等价路径,失败自动回退) |
| Memory64_Openprocess(PID) |
PID: 整数型 |
整数型进程句柄,失败返回 0 |
打开进程 |
| Memory64_Close() |
无 |
逻辑型 |
关闭句柄并清空状态(Linux 会顺带回收 scratch 内存) |
| Memory64_ReadBytes(地址, 缓冲区, 长度) |
地址: 长整数型;缓冲区: 字节集;长度: 整数型(0=按4) |
逻辑型 |
读字节集 |
| Memory64_ReadByte(地址) |
地址: 长整数型 |
字节型 |
读 1 字节 |
| Memory64_ReadInt(地址) |
地址: 长整数型 |
整数型 |
读 4 字节整数 |
| Memory64_ReadFloat(地址) |
地址: 长整数型 |
小数型 |
读 4 字节浮点 |
| Memory64_ReadLong(地址) |
地址: 长整数型 |
长整数型 |
读 8 字节 |
| Memory64_ReadText(地址, 长度) |
地址: 长整数型;长度: 整数型(0=按20) |
文本型(UTF-16) |
读文本;静态缓冲 |
| Memory64_ReadTextA(地址, 长度) |
同上(0=按32) |
文本型(UTF-8) |
Linux 新增:读 UTF-8 文本;静态缓冲 |
| Memory64_WriteAddr(地址, 数据, 长度) |
地址: 长整数型;数据: 字节集;长度: 整数型 |
逻辑型 |
写字节集。Linux 下目标页只读时会自动回退 /proc//mem 或 ptrace POKEDATA,可改代码段 |
| Memory64_WriteByte / WriteInt / WriteFloat / WriteLong |
地址 + 数值 |
逻辑型 |
写各类数值 |
| Memory64_WriteText(地址, 文本) |
地址: 长整数型;文本: 文本型 |
逻辑型 |
写文本(UTF-16) |
| Memory64_WriteTextA(地址, 文本) |
同上 |
逻辑型 |
Linux 新增:写 UTF-8 文本 |
| Memory64_GetMatrix(地址, 矩阵) |
地址: 长整数型;矩阵: 4x4 小数型数组 |
逻辑型 |
读 4x4 矩阵 |
| Memory64_GetModuleBase(模块名) |
模块名: 文本型(如 "kernel32.dll" / "libc.so.6") |
长整数型基址,0=未找到 |
取模块基址。Windows=PEB 遍历;Linux=/proc//maps 里 offset=0 映射的起始地址(= ELF 头在目标进程内的地址) |
| Memory64_GetProcAddress(模块名, 函数名) |
模块名/函数名: 文本型 |
长整数型地址,0=未找到 |
取目标进程内 API/符号地址。Windows=PE 导出表(含转发导出递归);Linux=ELF .dynamic/.dynsym 解析(符号地址 = load_bias + st_value) |
| Memory64_ReadPointer(地址) |
地址: 长整数型 |
长整数型 |
读 8 字节指针 |
| Memory64_WritePointer(地址, 数值) |
地址: 长整数型;数值: 长整数型 |
逻辑型 |
写 8 字节指针 |
| Memory64_alloc(名称, 大小) |
名称: 文本型;大小: 整数型 |
长整数型基址,0=失败 |
申请可执行内存(Code Cave)。Windows=VirtualAllocEx(RWX);Linux=目标进程内 ptrace 注入 mmap(RWX)。重名返回 0(与实现一致) |
| Memory64_dealloc(名称) |
名称: 文本型 |
逻辑型 |
释放 Code Cave(Windows=VirtualFreeEx;Linux=munmap) |
| Memory64_definealloc(名称, 汇编代码) |
名称: 文本型;汇编代码: 文本型数组(每行一条指令) |
逻辑型 |
把汇编助记符写入 Code Cave(Keystone)。有非法行/超容量/Keystone 不可用则整体失败 |
| Memory64_createThread(名称) |
名称: 文本型(已 alloc 的 Code Cave) |
整数型线程句柄,0=失败 |
在目标进程创建线程,入口为 Code Cave(类似 CE 的 createThread)。Windows=CreateRemoteThread;Linux=clone(CLONE_VM|CLONE_THREAD...) 注入 |
| Memory64_AOBscan(特征码, 模块名) |
特征码: 文本型(如 "48 89 ?? 24");模块名: 文本型可空 |
长整数型地址,0=未找到 |
AOB 特征码扫描(模块名空=全部可读内存) |
参数与 Memory64 相同,仅地址/返回值宽度为 32 位(整数型)。
| 函数 |
用途 |
| Memory32_Setprocess / Memory32_Openprocess / Memory32_Close |
进程管理 |
| Memory32_ReadBytes / ReadByte / ReadInt / ReadFloat / ReadLong / ReadText / ReadTextA |
读取 |
| Memory32_WriteAddr / WriteByte / WriteInt / WriteFloat / WriteLong / WriteText / WriteTextA |
写入 |
| Memory32_GetMatrix |
读 4x4 矩阵 |
| Memory32_GetModuleBase / Memory32_GetProcAddress |
模块与 API 地址 |
| Memory32_ReadPointer / WritePointer |
指针读写 |
| Memory32_alloc / Memory32_dealloc |
Code Cave 管理 |
| Memory32_definealloc |
写入汇编助记符 |
| Memory32_createThread |
目标进程内创建线程执行 Code Cave |
| Memory32_AOBscan |
AOB 特征码扫描 |
PID = GetprocessID (“game.exe”) ' 取进程
Memory64_Setprocess (PID, 假) ' 打开
基址 = Memory64_GetModuleBase (“game.exe”) ' 模块基址
血量地址 = 基址 + hex_to_dec (“1A2B3C”) ' 计算偏移
Memory64_WriteInt (血量地址, 999) ' 写数值
' 注入 MessageBoxA
Memory64_Setprocess (PID, 假)
API地址 = Memory64_GetProcAddress (“user32.dll”, “MessageBoxA”)
洞地址 = Memory64_alloc (“INJECT”, 1024)
字符串地址 = Memory64_alloc (“lptext”, 32)
Memory64_WriteAddr (字符串地址, “Hello World!”, 13) ' 字符串写入目标进程
汇编代码 = { “mov rdx,0x” + dec_to_hex (字符串地址) } ' 文本型数组,每行一条指令
Memory64_definealloc (“INJECT”, 汇编代码)
' AOB 扫描
地址 = Memory64_AOBscan (“48 89 5C 24 ?? 48 8B 04 10”, “game.exe”)
' 目标进程内创建线程执行 Code Cave(类似 CE 的 createThread)
Memory32_Setprocess (PID, 真)
Memory32_alloc (“THREAD”, 64) ' 申请 Code Cave
汇编代码 = { “mov eax, 0x12345678”, “mov dword ptr [0x400000], eax”, “ret” }
Memory32_definealloc (“THREAD”, 汇编代码) ' 写入机器码
线程句柄 = Memory32_createThread (“THREAD”) ' 创建线程并执行
Waitthread (线程句柄) ' 等待线程结束
Closethread (线程句柄) ' 关闭线程句柄
Memory32_dealloc (“THREAD”) ' 释放 Code Cave
| 项 |
Windows 版 |
Linux 版 |
| 类型 |
windows.h 的 DWORD/BOOL/… |
同名类型在 linux/memory_module.h 内自定义,保证原型文本一致 |
| 模块基址 |
PEB → Ldr → InMemoryOrderModuleList |
/proc/<pid>/maps 中 offset=0 映射的起始地址(ELF 头地址) |
| 符号解析 |
PE 导出表(含转发导出递归) |
ELF .dynamic + .dynsym(STT_GNU_IFUNC 返回解析器地址,不执行解析) |
| 进程打开 |
OpenProcess(PROCESS_ALL_ACCESS) |
校验 /proc/<pid> 存在;权限在首次读写/注入时由内核判定 |
| 读写路径 |
Nt/ZwReadVirtualMemory(真=nt 假=zw) |
真=process_vm_readv/writev 优先,假=/proc//mem 优先,失败自动回退,最后可用 ptrace PEEK/POKEDATA 兜底 |
| 只读页写 |
WriteProcessMemory 可写代码段 |
process_vm_writev 不行,/proc//mem 可强写,库内自动回退,故同样可 patch 代码段 |
| Code Cave |
VirtualAllocEx / VirtualFreeEx |
目标进程内 mmap / munmap(ptrace 注入 syscall 完成) |
| 远程线程 |
CreateRemoteThread |
clone(CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM),由 wrapper 调代码洞后 exit |
| 线程等待 |
WaitForSingleObject |
本地线程=pthread_join;远程线程=轮询 /proc/<pid>/task/<tid> 是否存在 |
| 窗口句柄 |
EnumWindows 查找 |
恒返回 NULL(无该概念) |
| 文本编码 |
wchar_t = 2 字节(UTF-16) |
wchar_t = 4 字节,故用固定 2 字节的 mm_char16 保持 UTF-16 语义;另提供 ReadTextA/WriteTextA(UTF-8) |
| 权限要求 |
跨进程需管理员(UAC) |
同 uid 子进程可直接操作;跨进程受 yama/ptrace_scope、CAP_SYS_PTRACE 限制 |
| 汇编依赖 |
链接 -lkeystone |
dlopen 加载 libkeystone.so(可选依赖) |
cd linux
make # 构建 libmemory_module.so / .a、test、out/target32
make test # 构建并运行自测(含 32 位目标用例)
./test out/target32 aob # 只跑某阶段:tools selfmem module aob cave keystone local remote remote32
- Keystone(可选):
MM_KEYSTONE_LIB=/path/libkeystone.so,或把 libkeystone.so/.so.1 放进库搜索路径;
也可 ./fetch_keystone.sh 从 PyPI wheel 提取(发行版一般无 keystone 包)。
不可用时 definealloc 返回假,其余功能正常
- 32 位目标测试:由
target32.s(as --32 + ld -m elf_i386)生成静态 i386 ELF,不需要 32 位 libc/multilib
- 退出码:0 = 全部通过(SKIP 不算失败),1 = 有失败项
自测 linux/test.c 共 139 项,在 x86-64 主机 + 32 位(i386)目标进程下全部通过(0 失败),
覆盖:自进程读写全类型/UTF-16/UTF-8/只读页强写、模块基址(与 /proc/maps 独立对照)、
符号解析(与 dlsym 逐项对照)、AOB 扫描(全内存/模块内/反例)、Code Cave 与自进程线程、
Keystone 汇编端到端、本地线程 API,以及远程目标进程:远程读写、远程 mmap 注入、
远程 clone 建线程并执行代码洞、注入后目标代码页哈希不变(临时覆盖已还原)、远程 AOB 精确命中,
最后是 32 位目标:Memory32 读写、ELF32 位宽判定、只读页强写、i386 mmap2 注入、
i386 clone 建线程并执行代码洞。