include "stdafx.h"
#include "dnfglobal.h"
/************************************************************************/
/* 技能修改
004CC750 55 push ebp
004CC751 8BEC mov ebp, esp
004CC753 83EC 10 sub esp, 10
004CC756 60 pushad
004CC757 9C pushfd
004CC758 B8 00000B01 mov eax, 010B0000
004CC75D FFD0 call eax
004CC75F 83E8 09 sub eax, 9
004CC762 50 push eax
004CC763 - E9 904EBF00 jmp 010C15F8
004CC768 2D 68407DB1 sub eax, B17D4068
004CC76D 59 pop ecx
004CC76E E8 ED8AFFFF call 004C5260
004CC773 8945 00 mov dword ptr [ebp], eax
004CC776 FF3424 push dword ptr [esp]
004CC779 FF3424 push dword ptr [esp]
004CC77C 57 push edi
004CC77D 66:C74424 04 61>mov word ptr [esp+4], 4961
004CC784 8D6424 4C lea esp, dword ptr [esp+4C]
004CC788 ^ E9 5064FAFF jmp 00472BDD
*/
/************************************************************************/
BYTE* g_SuperSkillMemory;
extern CRITICAL_SECTION g_cs;
extern void OutToHookLog(const char *szFormat, ...);
DWORD g_destAddress; // 全局变量,保存无敌地址
/************************************************************************/
/* 调用修改技能 */
/************************************************************************/
DWORD __stdcall CallModifySkill(DWORD dwEsp)
{
DWORD dwTmp = *(DWORD*)(g_SuperSkillMemory + 4);
__asm
{
mov eax, dwTmp ;
push dwEsp ;
call eax ;
}
}
DWORD __stdcall MyFillMemory(DWORD addrTmp)
{
BYTE* pByte = (BYTE*)addrTmp;
*pByte = 0x60;
*(pByte + 1) = 0x9C;
*(pByte + 2) = 0x54;
*(pByte + 3) = 0xB9;
*(DWORD*)(pByte + 4) = (DWORD)g_SuperSkillMemory;
*(pByte + 8) = 0xE8;
*(DWORD*)(pByte + 9) = (DWORD)CallModifySkill - addrTmp - 5 - 8;
OutToHookLog("CallModifySkill函数地址:%#x,addrTmp地址:%#x",(DWORD)CallModifySkill, addrTmp);
*(pByte + 0xD) = 0x9D;
*(pByte + 0xE) = 0x61;
memcpy(pByte+0xF, (g_SuperSkillMemory + 0x14), 6);
*(pByte + 0x15) = 0xE9;
*(DWORD*)(pByte + 0x16) = (g_dwSkillCall + 6) - (DWORD)(pByte + 0x15) - 5;
return 0;
}
/************************************************************************/
/* 恢复hook的函数 */
/************************************************************************/
DWORD __stdcall RestoreHookFunction()
{
EnterCriticalSection(&g_cs);
if (*(DWORD*)(g_SuperSkillMemory + 0x30) == 0)
{
return 1;
}
DWORD dwProtected = 0;
if (!VirtualProtect((LPVOID)g_dwSkillCall, 5, 0x40, &dwProtected))
{
return 2;
}
memcpy((PBYTE)g_dwSkillCall, (PBYTE)(g_SuperSkillMemory + 0x14), 6);
VirtualProtect((LPVOID)g_dwSkillCall, 5, dwProtected, &dwProtected);
*(DWORD*)(g_SuperSkillMemory + 0x0C) = 0;
LeaveCriticalSection(&g_cs);
return 0;
}
/************************************************************************/
/* 设置鬼剑士的必杀技能 */
/************************************************************************/
int __stdcall ModifySwordman(DWORD dwEsp)
{
int v1;
signed int v2;
int v3;
int result;
v1 = dwEsp;
v3 = *(DWORD *)(dwEsp + 16);
v2 = *(DWORD *)(v3 + 4);
if ( v2 == 20028 )
{
*(DWORD *)(v3 + 4) = 20044;
*(DWORD *)(*(DWORD *)(v1 + 16) + 8) = 900;
*(DWORD *)(*(DWORD *)(v1 + 16) + 16) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 20) = 85;
*(DWORD *)(*(DWORD *)(v1 + 16) + 24) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 28) = 82;
*(DWORD *)(*(DWORD *)(v1 + 16) + 32) = 4;
*(DWORD *)(*(DWORD *)(v1 + 16) + 36) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 40) = 14;
*(DWORD *)(*(DWORD *)(v1 + 16) + 48) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 52) = 0;
result = 0;
}
else
{
if ( v2 == 20050 )
{
*(DWORD *)(v3 + 4) = 20044;
*(DWORD *)(*(DWORD *)(v1 + 16) + 8) = 1200;
*(DWORD *)(*(DWORD *)(v1 + 16) + 12) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 16) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 20) = 123;
*(DWORD *)(*(DWORD *)(v1 + 16) + 24) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 28) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 32) = 4;
*(DWORD *)(*(DWORD *)(v1 + 16) + 36) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 40) = 100;
*(DWORD *)(*(DWORD *)(v1 + 16) + 48) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 52) = 0;
result = 0;
}
else
{
if ( v2 == 20016 )
{
*(DWORD *)(v3 + 4) = 20044;
*(DWORD *)(*(DWORD *)(v1 + 16) + 8) = 900;
*(DWORD *)(*(DWORD *)(v1 + 16) + 12) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 16) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 20) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 24) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 28) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 32) = 4;
*(DWORD *)(*(DWORD *)(v1 + 16) + 36) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 40) = 2;
*(DWORD *)(*(DWORD *)(v1 + 16) + 48) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 52) = 0;
}
result = 0;
}
}
return result;
}
/************************************************************************/
/* 设置格斗家的必杀技能 */
/************************************************************************/
int __stdcall ModifyWrestleWoman(DWORD dwEsp)
{
int v1;
int v2;
int result;
v1 = dwEsp;
v2 = *(DWORD *)(dwEsp + 16);
if ( *(DWORD *)(v2 + 4) == 24003 )
{
*(DWORD *)(v2 + 4) = 20044;
*(DWORD *)(*(DWORD *)(v1 + 16) + 8) = 1200;
*(DWORD *)(*(DWORD *)(v1 + 16) + 12) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 16) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 20) = 60;
*(DWORD *)(*(DWORD *)(v1 + 16) + 24) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 28) = 60;
*(DWORD *)(*(DWORD *)(v1 + 16) + 32) = 4;
*(DWORD *)(*(DWORD *)(v1 + 16) + 36) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 40) = 33;
*(DWORD *)(*(DWORD *)(v1 + 16) + 48) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 52) = 0;
result = 0;
}
else
{
result = 1;
}
return result;
}
/************************************************************************/
/* 设置木仓手的必杀技能 */
/************************************************************************/
int __stdcall ModifyGunman(DWORD dwEsp)
{
int v1;
int v2;
int result;
v1 = dwEsp;
v2 = *(DWORD *)(dwEsp + 16);
if ( *(DWORD *)(v2 + 4) == 22219 )
{
*(DWORD *)(v2 + 4) = 20044;
*(DWORD *)(*(DWORD *)(v1 + 16) + 8) = 550;
*(DWORD *)(*(DWORD *)(v1 + 16) + 16) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 20) = 55;
*(DWORD *)(*(DWORD *)(v1 + 16) + 24) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 28) = 74;
*(DWORD *)(*(DWORD *)(v1 + 16) + 32) = 4;
*(DWORD *)(*(DWORD *)(v1 + 16) + 36) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 40) = 4;
*(DWORD *)(*(DWORD *)(v1 + 16) + 48) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 52) = 0;
result = 0;
}
else
{
result = 1;
}
return result;
}
/************************************************************************/
/* 设置法师的必杀技能 */
/************************************************************************/
int __stdcall ModifyEnchanter (DWORD dwEsp)
{
int v1;
int v2;
signed int result;
v1 = dwEsp;
v2 = *(DWORD *)(dwEsp + 16);
if ( *(DWORD *)(v2 + 4) == 23007 )
{
*(DWORD *)(v2 + 4) = 20044;
*(DWORD *)(*(DWORD *)(v1 + 16) + 8) = 1500;
*(DWORD *)(*(DWORD *)(v1 + 16) + 12) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 16) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 20) = 60;
*(DWORD *)(*(DWORD *)(v1 + 16) + 24) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 28) = 60;
*(DWORD *)(*(DWORD *)(v1 + 16) + 32) = 4;
*(DWORD *)(*(DWORD *)(v1 + 16) + 36) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 40) = 33;
*(DWORD *)(*(DWORD *)(v1 + 16) + 48) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 52) = 0;
result = 0;
}
else
{
result = 1;
}
return result;
}
/************************************************************************/
/* 设置牧师的必杀技能 */
/************************************************************************/
int __stdcall ModifyPriest(DWORD dwEsp)
{
int v1;
int v2;
signed int result;
v1 = dwEsp;
v2 = *(DWORD *)(dwEsp + 16);
if ( *(DWORD *)(v2 + 4) == 21002 )
{
*(DWORD *)(v2 + 4) = 21017;
*(DWORD *)(*(DWORD *)(v1 + 16) + 8) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 16) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 20) = 55;
*(DWORD *)(*(DWORD *)(v1 + 16) + 24) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 28) = 74;
*(DWORD *)(*(DWORD *)(v1 + 16) + 32) = 4;
*(DWORD *)(*(DWORD *)(v1 + 16) + 36) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 40) = 100;
*(DWORD *)(*(DWORD *)(v1 + 16) + 48) = 0;
*(DWORD *)(*(DWORD *)(v1 + 16) + 52) = 0;
result = 0;
}
else
{
result = 1;
}
return result;
}
/************************************************************************/
/* 核心函数,修改人物技能 */
/************************************************************************/
DWORD __stdcall ModifySkill(DWORD dwEsp)
{
// 根据人物职业设置技能
ModifySwordman(dwEsp);
ModifyWrestleWoman(dwEsp);
ModifyGunman(dwEsp);
ModifyEnchanter(dwEsp);
ModifyPriest(dwEsp);
return 0;
}
/************************************************************************/
/* 分配一段内存 */
/************************************************************************/
BOOL __stdcall SetInlineHookMemory()
{
g_SuperSkillMemory = new BYTE[0x248];
ZeroMemory(g_SuperSkillMemory,0x248);
OutToHookLog("初始化HookSkill内存:%#x", g_SuperSkillMemory);
// 第一段复制为ccc
memset(g_SuperSkillMemory + 0x14, 0xCC, 20);
*(DWORD*)(g_SuperSkillMemory + 4) = (DWORD)ModifySkill;
OutToHookLog("ModifySkill函数地址:%#x", *(DWORD*)(g_SuperSkillMemory + 4));
*(DWORD*)(g_SuperSkillMemory + 0x2C) = g_dwSkillCall;
*(DWORD*)(g_SuperSkillMemory + 0x34) = (DWORD)VirtualAlloc(0, 0x14, 0x1000, 0x40);
OutToHookLog("VirtualAlloc函数地址:%#x", *(DWORD*)(g_SuperSkillMemory + 0x34));
if (*(DWORD*)(g_SuperSkillMemory + 0x34) == NULL)
{
return FALSE;
}
*(DWORD*)(g_SuperSkillMemory + 0x30) = 6;
*(DWORD*)(g_SuperSkillMemory + 0x38) = 1;
*(DWORD*)(g_SuperSkillMemory + 0x14) = *(DWORD*)g_dwSkillCall;
*(DWORD*)(g_SuperSkillMemory + 0x18) = *(WORD*)((BYTE*)g_dwSkillCall + 4);
*(DWORD*)(g_SuperSkillMemory + 0x28) = (DWORD)CallModifySkill;
OutToHookLog("CallModifySkill函数地址:%#x", *(DWORD*)(g_SuperSkillMemory + 0x28));
MyFillMemory(*(DWORD*)(g_SuperSkillMemory + 0x34));
return TRUE;
}
/************************************************************************/
/* 释放全局内存区 */
/************************************************************************/
VOID __stdcall ReleaseInlineHookMemory()
{
EnterCriticalSection(&g_cs);
if (g_SuperSkillMemory != NULL)
{
if(*(DWORD*)(g_SuperSkillMemory + 0x34) != NULL)
{
VirtualFree((LPVOID)*(DWORD*)(g_SuperSkillMemory + 0x34), 0x14, 0x1000);
*(DWORD*)(g_SuperSkillMemory + 0x34) = 0;
}
delete [] g_SuperSkillMemory;
g_SuperSkillMemory = NULL;
OutToHookLog("释放Hook内存");
}
LeaveCriticalSection(&g_cs);
}
/************************************************************************/
/* 设置超级无敌必杀技 hook 4cc750函数 */
/************************************************************************/
int __stdcall SetSuperSkill()
{
EnterCriticalSection(&g_cs);
// 判断是否已经hook
if (*(DWORD*)(g_SuperSkillMemory + 0x0C) == 0)
{
OutToHookLog("释放技能");
*(DWORD*)(g_SuperSkillMemory + 0x10) = 0x3E8;
if (*(DWORD*)(g_SuperSkillMemory + 0x30) == 0)
{
OutToHookLog("0x30退出");
return 1;
}
DWORD dwProtected = 0;
if (!VirtualProtect((LPVOID)g_dwSkillCall, 5, 0x40, &dwProtected))
{
OutToHookLog("viriualProtect退出");
return 2;
}
memcpy((PBYTE)(g_SuperSkillMemory + 0x14), (PBYTE)g_dwSkillCall, 6);
*(PBYTE)g_dwSkillCall = 0xE9;
*(DWORD*)((PBYTE)g_dwSkillCall + 1) = *(DWORD*)(g_SuperSkillMemory + 0x34) - g_dwSkillCall - 5;
VirtualProtect((LPVOID)g_dwSkillCall, 5, dwProtected, &dwProtected);
*(DWORD*)(g_SuperSkillMemory + 0x0C) = GetTickCount();
}
LeaveCriticalSection(&g_cs);
return 0;
}
/************************************************************************/
/* src : 起始地址 nSrcLen:地址范围
flw:要搜索的代码, 0,255,255,255,255,255,255,255,255,1,0,0,0,0
nflwLen:要搜索的代码长度
dwPosArray: 找到的地址存放数组
返回值:返回存放到dwPosArray数组中的地址个数。
*/
/************************************************************************/
DWORD __stdcall FindWudiPos(BYTE* src, BYTE * flw, DWORD nSrcLen,DWORD nflwLen,DWORD *dwPosArray)
{
DWORD dwFoundNumber = 0;
DWORD dwXiangTong ;
for(DWORD i = 0; i < nSrcLen -nflwLen ; i ++)
{
dwXiangTong = 0;
for(DWORD j = 0 ; j < nflwLen; j ++)
{
if(src[ i + j] == flw[j])
dwXiangTong++;
if(dwXiangTong == nflwLen )
{
//找到数据
dwPosArray[dwFoundNumber] = (DWORD)(src + i);
dwFoundNumber++;
}
}
}
return dwFoundNumber;
}
/************************************************************************/
/* 在上面找出的系列地址中,筛选出有效的地址来,存放到 outArray中
筛选条件:****17**,****4F**
返回值表示筛选出的有效地址的个数。
*/
/************************************************************************/
DWORD __stdcall SearchAddress(DWORD *dwPosArray,DWORD nLen,DWORD *outArray)
{
DWORD destAddress;
DWORD dwFoundNumber = 0;
for(DWORD i = 0;i<nLen;i++)
{
destAddress = dwPosArray;
__asm
{
push ecx ;
mov eax,destAddress ;
mov ecx,eax ;
and eax,0ff00h ;
shr eax,8 ;
//cmp al,17h ;是17h 格斗
//jz YOUXIAO ;
cmp al,4fh ;是4fh 法师
jnz WUXIAO ;
//YOUXIAO:
mov eax,dwFoundNumber ;dwFoundNumber作为数组索引值
shl eax,2 ;
add eax,outArray ;找到数组中该索引所在的位置
mov [eax],ecx ;将找到的地址写入数组中
inc dwFoundNumber ;
WUXIAO:
pop ecx;
}
}
return dwFoundNumber;
}
/************************************************************************/
/* 设置无敌值 暂时只修改一个,测试出现修改两个会出现两个无敌
下一步需要测试判断人物类型,根据任务类型来修改无敌,免得出现
人物和怪都是无敌。
TODO:需要加上职业的判断
*/
/************************************************************************/
void __stdcall SetWuDivalue(DWORD *outArray,DWORD nLen,BYTE nvalue)
{
char msg[100] = {0};
DWORD destAddress;
DWORD modifyAddr;
/*for (DWORD i = 0 ; i < nLen ; i++)*/
{
destAddress = outArray[0];//outArray;
g_destAddress = destAddress;
OutToHookLog("当前搜索到的有效内存地址是: %x",destAddress);
_asm
{
push ebx;
mov eax,destAddress ;
sub al, 10h ;
and al, 0f0h ;
add al, 0dh ;
mov modifyAddr,eax ;
mov bl, nvalue ;
mov byte ptr[eax],bl;
pop ebx ;
}
OutToHookLog("设置内存地址是: %x",modifyAddr);
}
}
/************************************************************************/
/* 设置无敌 为了遍历速度,设置搜索范围为:0x00400000 ~ 0x10000000 */
/************************************************************************/
void __stdcall Noodles()
{
if (g_destAddress == 0)
{
BYTE wudiTezheng[] = {0,255,255,255,255,255,255,255,255,1,0,0,0,0}; //无敌特征码
DWORD AllAddress[100] = {0};
DWORD youxiaoAddr[10] = {0};
SYSTEM_INFO sysInfo;
MEMORY_BASIC_INFORMATION memInfo;
GetSystemInfo(&sysInfo);
for (DWORD i = 0x00400000/*(DWORD)sysInfo.lpMinimumApplicationAddress*/; i < 0x10000000/*(DWORD)sysInfo.lpMaximumApplicationAddress*/; i +=0x1000)
{
VirtualQuery((LPVOID)i,&memInfo,sizeof(MEMORY_BASIC_INFORMATION));
if(memInfo.State == MEM_COMMIT && (memInfo.AllocationProtect == PAGE_READWRITE)
&& (memInfo.Protect == PAGE_READWRITE))
{
DWORD dwAllAddress = FindWudiPos((BYTE *)i, wudiTezheng, 0x1000,sizeof(wudiTezheng),AllAddress);
DWORD dwYouxiao = 0;
if(dwAllAddress > 0)
{
dwYouxiao = SearchAddress(AllAddress,dwAllAddress,youxiaoAddr);
if(dwYouxiao)
{
SetWuDivalue(youxiaoAddr,dwYouxiao,1);
}
}
//
}
}
}
else
{
_asm
{
push ebx;
mov eax,g_destAddress ;
sub al, 10h ;
and al, 0f0h ;
add al, 0dh ;
mov bl, 1 ;
mov byte ptr[eax],bl ;
pop ebx ;
}
}
}
/************************************************************************/
/* 取消无敌 */
/************************************************************************/
void __stdcall UnNoodles()
{
_asm
{
push ebx;
mov eax,g_destAddress ;
sub al, 10h ;
and al, 0f0h ;
add al, 0dh ;
mov bl, 0 ;
mov byte ptr[eax],bl ;
pop ebx ;
}
}
-