~ruther/NosSmooth

ref: cf61a90c01f4422396808ed2f731127acc456529 NosSmooth/Local/NosSmooth.LocalCore/CharacterUnmanaged.cpp -rw-r--r-- 2.7 KiB
cf61a90c — František Boháček feat: add walk detour support 3 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include "CharacterUnmanaged.h"
#include <detours.h>

using namespace NosSmoothCore;

const BYTE WALK_OBJECT_PATTERN[] = { 0x33, 0xC9, 0x8B, 0x55, 0xFC, 0xA1, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00 };
const BYTE WALK_FUNCTION_PATTERN[] = { 0x55, 0x8B, 0xEC, 0x83, 0xC4, 0xEC, 0x53, 0x56, 0x57, 0x66, 0x89, 0x4D, 0xFA };

LPCSTR WALK_OBJECT_MASK = "xxxxxx????x????";
LPCSTR WALK_FUNCTION_MASK = "xxxxxxxxxxxxx";

void CharacterWalkDetourIn()
{
    DWORD position = 0;

    __asm
    {
        pushad
        pushfd

        mov position, edx
    }

    bool isAccepted = CharacterUnmanaged::GetInstance()->ExecuteWalkCallback(position);

    __asm
    {
        popfd
        popad
    }

    if (isAccepted) {
        CharacterUnmanaged::GetInstance()->Walk(position);
    }
}

// Detour entrypoint
// declspec naked to not mess up the stack
void __declspec(naked) CharacterWalkDetour()
{
    unsigned int returnPush;
    __asm {
        pop eax
        pop ebx
        mov returnPush, eax // we have to push this value on the stack before returning
    }

    CharacterWalkDetourIn();

    __asm {
        push returnPush
        ret
    }
}

CharacterUnmanaged::CharacterUnmanaged()
{
}

void CharacterUnmanaged::Setup(ModuleHook moduleHook)
{
    auto walkFunction = moduleHook.FindPattern(WALK_FUNCTION_PATTERN, WALK_FUNCTION_MASK);
    auto walkObject = *(unsigned int*)(moduleHook.FindPattern(WALK_OBJECT_PATTERN, WALK_OBJECT_MASK) + 0x6);

    if (walkFunction == 0)
    {
        throw "Could not find walk function.";
    }

    if (walkObject == 0)
    {
        throw "Could not find player object.";
    }

    _walkFunctionAddress = walkFunction;
    _characterObjectAddress = walkObject;
}

void CharacterUnmanaged::SetWalkCallback(NativeWalkCallback walkCallback)
{
    _walkCallback = walkCallback;
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    DetourAttach(&(PVOID&)_walkFunctionAddress, CharacterWalkDetour);
    DetourTransactionCommit();
}

void CharacterUnmanaged::Walk(DWORD position)
{
    unsigned int walkFunction = _walkFunctionAddress;
    unsigned int characterObject = _characterObjectAddress;

    __asm
    {
        push 1
        xor ecx, ecx
        mov edx, position
        mov eax, dword ptr ds : [characterObject]
        mov eax, dword ptr ds : [eax]
        call walkFunction
    }
}

void CharacterUnmanaged::ResetHooks()
{
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    DetourDetach(&(PVOID&)_walkFunctionAddress, CharacterWalkDetour);
    DetourTransactionCommit();
}

bool CharacterUnmanaged::ExecuteWalkCallback(const DWORD position)
{
    if (_walkCallback != nullptr) {
        return _walkCallback(position);
    }

    return true;
}
Do not follow this link