(1).查找适合的劫持对象
劫持Dll为:Version.dll 路径为红色的为程序运行再加载进来DLL的,网上这个dll的劫持源码也很多
(2). 加载系统原DLL:
(3).转发导出函数:
(4).加载检测模块:
劫持注入大概原理就是这样,这里推荐一款工具:AheadLib 因为懒我也用的工具生成的劫持代码
https://bbs.pediy.com/thread-196111.htm
(1).寻找信息提示CALL
可以看到鼠标焦点离开游戏窗口时弹出这个信息提示,我们OD搜索字符串: Click to resume game
找到字符串后双击进入,可以看到压入字符串常量的CALL都同一个,我们猜想应该是格式化字符串的。
上面是格式化函数,那下面 call eax 就一定是提示Call了
可以看到ecx 为游戏基址的值,下面开始重载这个函数
判断是否进入游戏很简单 ,判断游戏基址的值是否为NULL即可
(一) .为什么要采用劫持注入?
(二) .封装什么提示函数?
(三) .检测为什么要初始化?
(四) .Crc校验的原理和数据校验的原理是什么?
为什么要采用劫持注入?
- 劫持注入更为简单方便,不用控制注入的时机。
- 劫持注入可以更根底的应用各种检测,不用担心没有权限。
- 方便采集和备份原始数据
封装什么提示函数?
- 有防必有攻,弹出消息框可以更为显著的对抗检测 Ps:不然直接退出岂不很猥琐 (/手动滑稽)
- 寻找到游戏提示的消息框封装成函数方便调用 (强迫症患者的需要,不然直接MessageBox() 也行)
- Patch掉鼠标焦点移动到游戏窗口外出现的暂停窗口
检测为什么要初始化?
- 采集和备份原数据
- 判断各类数据是否初始化以便于开启检测
Crc校验的原理和数据校验的原理是什么?
- Crc检测也称 “循环冗余校验“ ,这里我们采用的是Crc32
- 采集主模块镜像Crc校验值对于原数据,不想等则非法内存
- 数据校验的对象为阳光值 ,判断值是否为非法数据和对比短时间差阳光的变化值
三 .收集数据和实现
- 劫持注入更为简单方便,不用控制注入的时机。
- 劫持注入可以更根底的应用各种检测,不用担心没有权限。
- 方便采集和备份原始数据
封装什么提示函数?
- 有防必有攻,弹出消息框可以更为显著的对抗检测 Ps:不然直接退出岂不很猥琐 (/手动滑稽)
- 寻找到游戏提示的消息框封装成函数方便调用 (强迫症患者的需要,不然直接MessageBox() 也行)
- Patch掉鼠标焦点移动到游戏窗口外出现的暂停窗口
检测为什么要初始化?
- 采集和备份原数据
- 判断各类数据是否初始化以便于开启检测
Crc校验的原理和数据校验的原理是什么?
- Crc检测也称 “循环冗余校验“ ,这里我们采用的是Crc32
- 采集主模块镜像Crc校验值对于原数据,不想等则非法内存
- 数据校验的对象为阳光值 ,判断值是否为非法数据和对比短时间差阳光的变化值
三 .收集数据和实现
封装什么提示函数?
- 有防必有攻,弹出消息框可以更为显著的对抗检测 Ps:不然直接退出岂不很猥琐 (/手动滑稽)
- 寻找到游戏提示的消息框封装成函数方便调用 (强迫症患者的需要,不然直接MessageBox() 也行)
- Patch掉鼠标焦点移动到游戏窗口外出现的暂停窗口
检测为什么要初始化?
- 采集和备份原数据
- 判断各类数据是否初始化以便于开启检测
Crc校验的原理和数据校验的原理是什么?
- Crc检测也称 “循环冗余校验“ ,这里我们采用的是Crc32
- 采集主模块镜像Crc校验值对于原数据,不想等则非法内存
- 数据校验的对象为阳光值 ,判断值是否为非法数据和对比短时间差阳光的变化值
三 .收集数据和实现
- 有防必有攻,弹出消息框可以更为显著的对抗检测 Ps:不然直接退出岂不很猥琐 (/手动滑稽)
- 寻找到游戏提示的消息框封装成函数方便调用 (强迫症患者的需要,不然直接MessageBox() 也行)
- Patch掉鼠标焦点移动到游戏窗口外出现的暂停窗口
检测为什么要初始化?
- 采集和备份原数据
- 判断各类数据是否初始化以便于开启检测
Crc校验的原理和数据校验的原理是什么?
- Crc检测也称 “循环冗余校验“ ,这里我们采用的是Crc32
- 采集主模块镜像Crc校验值对于原数据,不想等则非法内存
- 数据校验的对象为阳光值 ,判断值是否为非法数据和对比短时间差阳光的变化值
三 .收集数据和实现
检测为什么要初始化?
- 采集和备份原数据
- 判断各类数据是否初始化以便于开启检测
Crc校验的原理和数据校验的原理是什么?
- Crc检测也称 “循环冗余校验“ ,这里我们采用的是Crc32
- 采集主模块镜像Crc校验值对于原数据,不想等则非法内存
- 数据校验的对象为阳光值 ,判断值是否为非法数据和对比短时间差阳光的变化值
三 .收集数据和实现
- 采集和备份原数据
- 判断各类数据是否初始化以便于开启检测
Crc校验的原理和数据校验的原理是什么?
- Crc检测也称 “循环冗余校验“ ,这里我们采用的是Crc32
- 采集主模块镜像Crc校验值对于原数据,不想等则非法内存
- 数据校验的对象为阳光值 ,判断值是否为非法数据和对比短时间差阳光的变化值
三 .收集数据和实现
Crc校验的原理和数据校验的原理是什么?
- Crc检测也称 “循环冗余校验“ ,这里我们采用的是Crc32
- 采集主模块镜像Crc校验值对于原数据,不想等则非法内存
- 数据校验的对象为阳光值 ,判断值是否为非法数据和对比短时间差阳光的变化值
三 .收集数据和实现
- Crc检测也称 “循环冗余校验“ ,这里我们采用的是Crc32
- 采集主模块镜像Crc校验值对于原数据,不想等则非法内存
- 数据校验的对象为阳光值 ,判断值是否为非法数据和对比短时间差阳光的变化值
三 .收集数据和实现
- 寻找及封装PvzMessageBox() 消息提示函数
//格式化函数 Data[4]=Text Data[0x14]=len
char * Check::PvzFormatText(char* Data, LPCTSTR lpFormat, size_t strlen)
{
strcpy(&Data[4], lpFormat);
Data[0x14] = strlen;
Data[0x18] = 0xF;
return Data;
//__try{
// ZeroMemory(MessageData, sizeof(char*));
// __asm{
// lea ecx, MessageData
// mov dword ptr[ecx + 0x18], 0xF
// mov edi, strlen
// push edi
// lea edi, lpFormat
// mov edi, [edi]
// push edi
// mov eax, CallFormat
// call eax
// }
//}
//__except (0){
// return NULL;
//}
//Asm
}
//信息提示CALL
int Check::PvzMessageBox(LPCTSTR lpCaption, LPCTSTR lpText, LPCTSTR lpButton)
{
DWORD dwButton = (DWORD)PvzFormatText(PvzMessageData.szButton, lpButton, strlen(lpButton));
DWORD dwText = (DWORD)PvzFormatText(PvzMessageData.szText, lpText, strlen(lpText));
DWORD dwCaption = (DWORD)PvzFormatText(PvzMessageData.szCaption, lpCaption, strlen(lpCaption));
__try{
__asm{
push 3
mov eax, [dwButton]
push eax
mov eax, [dwText]
push eax
mov eax, [dwCaption]
push eax
push 1
push 0x13
mov ecx,GameBase
mov ecx, [ecx]
mov eax, [ecx]
mov eax, [eax + 0x120]
call eax
}
//delete[] TmpData;
}
__except (0){
}
return true;
}
(2).Patch
掉暂停窗口
BOOL Check::PatchPauseWnd()
{
DWORD PatchAddr = 0x00452720; //
BYTE OldData[1] = { 0x56 }; //push esi
BYTE PatchData[1] = { 0xC3 }; //ret
BYTE bufRead[1] = { 0 };
BOOL bIsPatched = FALSE; //是否已找到目标并完成修改
DWORD dwOldProtect;
HANDLE hProcess = GetCurrentProcess();
if (this->bInit)//如果已初始化就还原
{
VirtualProtect((LPVOID)PatchAddr, sizeof(DWORD), PAGE_READWRITE, &dwOldProtect);
WriteProcessMemory(hProcess, (LPVOID)PatchAddr, &OldData, sizeof(OldData), NULL);
bIsPatched = TRUE;
VirtualProtect((LPVOID)PatchAddr, sizeof(DWORD), dwOldProtect, &dwOldProtect);
}
else
{
while (!bIsPatched)
{
VirtualProtect((LPVOID)PatchAddr, sizeof(DWORD), PAGE_READWRITE, &dwOldProtect);
ReadProcessMemory(hProcess, (LPVOID)PatchAddr, (LPVOID)bufRead, sizeof(bufRead), NULL);
if (memcmp(bufRead, OldData, sizeof(OldData)) == 0)
{
WriteProcessMemory(hProcess, (LPVOID)PatchAddr, &PatchData, sizeof(PatchData), NULL);
bIsPatched = TRUE;
}
VirtualProtect((LPVOID)PatchAddr, sizeof(DWORD), dwOldProtect, &dwOldProtect);
}
}
return bIsPatched;
//00452720 56 push esi
// 00452721 8BF1 mov esi, ecx
// 00452723 80BE 15090000 0 > cmp byte ptr ds : [esi + 0x915], 0x0
// 0045272A 75 0F jnz short PlantsVs.0045273B
// 0045272C E8 9FFFFFFF call PlantsVs.004526D0
// 00452731 84C0 test al, al
// 00452733 74 06 je short PlantsVs.0045273B
// 00452735 56 push esi
// 00452736 E8 750F0000 call PlantsVs.004536B0
// 0045273B 5E pop esi; 7FFE0010
// 0045273C C3 retn
}
(1).判断是否已进入游戏
判断是否进入游戏很简单 ,判断游戏基址的值是否为NULL即可
(2).获取主模块镜像Begin地址及长度
(3).初始化Crc表及保存Crc原始校验值
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!