extern "C" { WCHAR strAveStealth[] = L"ave_stealth"; } void L2Ex::NewAve() { WriteServerHook((BYTE *)0x8F0E36, (DWORD *)AveFix, 2); } extern "C" { void CharSelectInfoFix(BYTE *pSocket, const char *szFormat, BYTE bOpCode, DWORD dwCharNum, DWORD dwPacketSize, DWORD *pOldPacket); void UserInfoFix(BYTE *pSocket, const char *szFormat, ...); void AveFix(); } void L2Ex::WriteServerHook(BYTE *pAddress, DWORD *pFunction, BYTE bNops) { BYTE Call = 0xE9; BYTE Nop = 0x90; WriteServerMemory((DWORD *)(pAddress), &Call, 1); DWORD pFuncAddress = (DWORD)pFunction - (DWORD)(pAddress + 5); WriteServerMemory((DWORD *)(pAddress + 1), (LPVOID)&pFuncAddress, sizeof(pFuncAddress)); for (int i = 6; i < bNops + 6; i++) { WriteServerMemory((DWORD *)(pAddress + i), &Nop, 1); } } PUBLIC AveFix EXTERNDEF strAveStealth:PTR .CODE AveFix PROC mov rdi, strAveStealth mov rsi, rdx ; skilldata name buffer mov ecx, 0C0h ; length of abnormal name including null (12 for ave_stealth) repe cmpsw ; compare words jnz short lbNotAVE ; jump back to the server mov rax, [rbp+0F0h] mov dword ptr [rax+0D4h], 100000h ; move ave id (i have no idea what the id for stealth is so...) mov rax, 8F7386h jmp rax ; jump to return of skilldata function lbNotAVE: mov rax, [rbp+0F0h] ; replace overwritten code mov rbx, 8F0E3Dh jmp rbx AveFix ENDP END