外挂、破解软件理论与实战
1 理论
1.1 不同操作系统下的可执行文件
- Windows【PE】
PE 格式,可移植可执行格式(Portable Executable),
是 Windows 下的主要可执行文件格式。别被名字迷惑了,PE 文件必须是 Windows 下的文件。
- Linux【ELF】
在Linux系统的可执行文件(ELF文件,Executable and Linkable Format,可执行链接格式)中,开头是一个文件头,用来描述程序的布局,整个文件的属性等信息,包括文件是否可执行、静态还是动态链接及入口地址等信息;生成的文件不是纯碎的二进制可执行文件了,因为包含的程序头不是可执行代码;将这种包含程序头的文件读入到内存后,从程序头中读取入口地址,跳转到入口地址执行;
- Mac【Mach-O】
Mach-O为Mach Object文件格式的缩写,它是一种用于可执行文件,目标代码,动态库,内核转储的文件格式。作为a.out格式的替代,Mach-O提供了更强的扩展性,并提升了符号表中信息的访问速度。
1.2 Windows下软件破解知识
◼ Windows平台软件破解必备知识
文件格式:PE文件
汇编语言:x86、x64汇编
工具:Ollydbg
Windows API
◼ OD常用快捷键
F2:切换断点
F9:运行程序
F7:Step Into
F8:Step Over
Ctrl + G:搜索代码
1.3 加壳与脱壳
-
一般的软件破解思路
-
加壳后的软件破解思路(在普通软件上多了一层)
1.4 外挂的本质
常见的外挂有2种做法:
-
修改内存中的数据
-
修改内存中的代码
通过OD软件修改汇编代码,然后重新保存为新的.exe文件
其实,数据和代码并没有本质区别,在内存中都是0和1
2 实战步骤
软件地址:
链接:https://pan.baidu.com/s/1pIogCuXPR87p91og09zZZQ?pwd=zj8k
提取码:zj8k
2.1 环境准备
visual studio 2022:c++桌面开发(MFC)、visual studio扩展开发
扩展开发:
2.2 OD汇编(Ollydbg)
将.exe文件转化为汇编
2.4 cheaterEngines
用于检测内存中数值变化
2.5 大体步骤
此处以
植物大战僵尸
为例
- 打开visual studio,创建MFC项目(类似于java中的swing)
- 自定义log宏,简化打印
- 事件注册(手动、自动)
- 绑定变量(手动、自动)
- 单选框状态读取(勾选、不勾选)
- 将植物大战僵尸的运行文件(.exe文件)拖动到OD中,观察汇编
- 修改汇编逻辑
前后修改尽量不动字节数,比如:前面一行代码占字节,我们修改后的代码占2字节,
那么我们就需要使用NOP填充,相当于是空,当cpu执行到nop时,会直接跳过,nop
只起到一个占用位置的作用
思路:
①秒杀僵尸:直接用僵尸的原有血量 - 僵尸的血量
②无限阳光:阳光存在一个struct中,通过地址找到值,然后使用API修改内存中的值
- 导出破解后的exe文件
- 使用spy++查找窗口
windows外挂桌面开发可能需要获取到运行文件的句柄(ID),然后控制
4. 修改visual studio中的代码【部分】
秒杀僵尸、无限阳光
// 用来监控游戏的线程
DWORD monitorThreadFunc(LPVOID lpThreadParameter) {
while (1) {
// 获得植物大战僵尸窗口的句柄
HWND windowHandle = FindWindow(CString("MainWindow"), CString("植物大战僵尸中文版"));
if (windowHandle == NULL) {
g_dlg->m_bnKill.SetCheck(FALSE);
g_dlg->m_bnSun.SetCheck(FALSE);
g_dlg->m_bnKill.EnableWindow(FALSE);
g_dlg->m_bnSun.EnableWindow(FALSE);
g_processHandle = NULL;
} else if (g_processHandle == NULL) {
g_dlg->m_bnKill.EnableWindow(TRUE);
g_dlg->m_bnSun.EnableWindow(TRUE);
// 获得植物大战僵尸的进程ID
DWORD processPid;
GetWindowThreadProcessId(windowHandle, &processPid);
// 获得植物大战僵尸的进程句柄
g_processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processPid);
}
if (g_dlg->m_bnSun.GetCheck()) { // 需要无限阳光
DWORD value = 9990;
WriteMemory(&value, sizeof(value), 0x6A9EC0, 0x320, 0x8, 0x0, 0x8, 0x144, 0x2c, 0x5560, -1);
}
// 休息睡眠
Sleep(1000);
}
return NULL;
}