Вернуться к выполнению функции после хука.

WmzBot

Постоялец
Участник
Старожил I степени
Сообщения
589
Розыгрыши
0
Решения
2
Репутация
68
Реакции
202
Баллы
1 075
Доброго времени. Такое дело, в С++ не очень давно. решил поработать с хуками, взял исход ванганта (интерлюд) решил хукнуть функцию, так для опыта.
Написал хук на адресс функции (0x008257C0, "User::EquipItem()"); cс таким вот содержимым.
C++:
.header
    static bool User_UseItem(User *pUser, CItem *pItem);

.cpp
    g_HookManager.WriteCall( 0x008257C0, CAntiExploit::User_UseItem, 0);

bool CAntiExploit::User_UseItem(User *pUser, CItem *pItem)
{
    if (pItem->pSID->nItemID > 0)
    {
        pUser->pSocket->SendSystemMessage(L"You odel odejdu!!!");
    }else
    {
        pUser->pSocket->SendSystemMessage(L"You goliy !!!");

    }
    typedef bool (*f)(CItem*);
    return f(0x008257C0L)(pItem);
}
При вызове функции в игре, при одевании предмета, условия, написаные мной в моей функции выполняются, мне пишет в систем чат что я одел одежду, но сервер крашится, так как продолжения нет, вот собственно и вопрос, как мне после выполнения моего хука функции, вернутся в стандартную функцию l2servera.
 

А почему у тебя в хуке 2 параметра а пытаясь вызвать оригинал ты передаешь 1 аргумент всего лишь?
 
А почему у тебя в хуке 2 параметра а пытаясь вызвать оригинал ты передаешь 1 аргумент всего лишь?
это неудачный пример я сюда выписал вам. оно не с двумя передаваемыми, не с одним не хочет возвращаться к реальной функции. знаю, что нужно писать ссылки в asm на мою функцию и потом обратно, это я не умею, это я сейчас начал учить. как я понял без asm частично заменить функцию. сервера на мою не получится.
 
Я бы попробовал так:
return ((bool(__stdcall*)(User*, CItem*))(0x008257C0))(pUser, pItem);
соглашение о вызове подставь правильное
И что вообще делает WriteCall у тебя?
 
Я бы попробовал так:
return ((bool(__stdcall*)(User*, CItem*))(0x008257C0))(pUser, pItem);
соглашение о вызове подставь правильное
И что вообще делает WriteCall у тебя?
вагантовый хукменеджер, из его проэкта.
C++:
void CHookManager::WriteCall(UINT64 Address, PVOID Function, SIZE_T Nops, LPBYTE OrgBytes)
{
    if(Address && Function)
    {
        Lock();
        SIZE_T Size = 5 + Nops;
        if(ValidOrgBytes(Address, OrgBytes, Size))
        {
            if(TryWrite(Address, Size))
            {
                DWORD dwOldProtect = NULL;
                SIZE_T BytesWritten = NULL;

                PUCHAR Buffer = new unsigned char[Size];
                if(Buffer)
                {
                    memset(Buffer, 0, Size);
                    Buffer[0]=CALL;
                    UINT functionAddr = (UINT)Function;
                    functionAddr-=Address+5;
                    memcpy(&Buffer[1], &functionAddr, 4);
                
                    if(Nops)
                    {       
                        for(int n=5; n<Size; n++)
                        {
                            Buffer[n]=0x90;
                        }
                    }

                    HANDLE     hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, GetCurrentProcessId());
                    if(hProcess)
                    {
                        if(!VirtualProtect((LPVOID)Address, Size, PAGE_EXECUTE_READWRITE, &dwOldProtect))
                        {
                            ShowMessage("Hook Manager", "Failed to set new protection with VirtualProtect at address [%p]!", Address);
                        }
                        if (WriteProcessMemory(hProcess, (LPVOID)Address, Buffer, Size, &BytesWritten))
                        {
                            Write(Address, Size);
                        }else
                        {
                            ShowMessage("Hook Manager", "Failed to write process memory at address[%p]!", Address);
                            Unlock();
                            ExitProcess(0);   
                            return;
                        }
                        if(!VirtualProtect((LPVOID)Address, Size, dwOldProtect, &dwOldProtect))
                        {
                            ShowMessage("Hook Manager", "Failed to set old protection with VirtualProtect at address [%p]!", Address);
                        }
                        CloseHandle(hProcess);
                    }else
                    {
                        ShowMessage("Hook Manager", "Failed to get process handle!");
                        Unlock();
                        ExitProcess(0);
                        return;
                    }
                    delete [] Buffer;
                }else
                {
                    ShowMessage("Hook Manager", "Cannot allocate memory for buffer!");
                    Unlock();
                    ExitProcess(0);
                    return;
                }

            }
        }
        Unlock();
    }
}

Я бы попробовал так:
return ((bool(__stdcall*)(User*, CItem*))(0x008257C0))(pUser, pItem);
соглашение о вызове подставь правильное
И что вообще делает WriteCall у тебя?

А вот за соглашение спасибо, попробую с ним и двумя переданными аргументами. по результату отпишусь.
 
у тебя будет рекурсия ибо в оригинальной функции идет перенаправление на твою и потом из твоей идет вызов в оригинальную и опять в твою. Это по мимо того что аргументы не верны и соглашение ( тут __thiscall скорей всего ).
 
Доброго времени. Такое дело, в С++ не очень давно. решил поработать с хуками, взял исход ванганта (интерлюд) решил хукнуть функцию, так для опыта.
Написал хук на адресс функции (0x008257C0, "User::EquipItem()"); cс таким вот содержимым.
C++:
.header
    static bool User_UseItem(User *pUser, CItem *pItem);

.cpp
    g_HookManager.WriteCall( 0x008257C0, CAntiExploit::User_UseItem, 0);

bool CAntiExploit::User_UseItem(User *pUser, CItem *pItem)
{
    if (pItem->pSID->nItemID > 0)
    {
        pUser->pSocket->SendSystemMessage(L"You odel odejdu!!!");
    }else
    {
        pUser->pSocket->SendSystemMessage(L"You goliy !!!");

    }
    typedef bool (*f)(CItem*);
    return f(0x008257C0L)(pItem);
}
При вызове функции в игре, при одевании предмета, условия, написаные мной в моей функции выполняются, мне пишет в систем чат что я одел одежду, но сервер крашится, так как продолжения нет, вот собственно и вопрос, как мне после выполнения моего хука функции, вернутся в стандартную функцию l2servera.

Как уже написали выше - ты получаешь бесконечную рекурсию. При установке хука необходимо сохранять адрес трамплина в оригинальную функцию. Как ставить хуки можешь посмотреть, к примеру, тут -
Второй момент - calling conventions. Если ты хукаешь метод класса, то ты не можешь для него просто взять и объявить хук как __thiscall, компилятор такое не соберет (есть исключения, но сейчас не о них).
Для хуков методов класс применяют трюк с __fastcall, который схож с __thiscall и имеет лишь небольшие различия:
При __fastcall первые 2 аргумента передаются в регистрах ECX и EDX.
При __thiscall контекст выполнения this передается через регистр ECX, а аргументы через стек.

Допустим это сигнатура метода класса:
C++:
int ololo(int a1, int a2, int a3);

Тогда хук будет выглядеть примерно так:
C++:
int __fastcall ololo_hook(void* _this, int EDX_stub, int a1, int a2, int a3);
 
Как уже написали выше - ты получаешь бесконечную рекурсию. При установке хука необходимо сохранять адрес трамплина в оригинальную функцию. Как ставить хуки можешь посмотреть, к примеру, тут -
Второй момент - calling conventions. Если ты хукаешь метод класса, то ты не можешь для него просто взять и объявить хук как __thiscall, компилятор такое не соберет (есть исключения, но сейчас не о них).
Для хуков методов класс применяют трюк с __fastcall, который схож с __thiscall и имеет лишь небольшие различия:
При __fastcall первые 2 аргумента передаются в регистрах ECX и EDX.
При __thiscall контекст выполнения this передается через регистр ECX, а аргументы через стек.

Допустим это сигнатура метода класса:
C++:
int ololo(int a1, int a2, int a3);

Тогда хук будет выглядеть примерно так:
C++:
int __fastcall ololo_hook(void* _this, int EDX_stub, int a1, int a2, int a3);
Спасибо за подсказку, все верно, fastcall в моем случае будет правильным. Вашими постами, вы помогли мне дойти до сути, и сделать свой первый хук, спасибо ещё раз!!!
 
Для хуков методов класс применяют трюк с __fastcall, который схож с __thiscall и имеет лишь небольшие различия:
При __fastcall первые 2 аргумента передаются в регистрах ECX и EDX.
При __thiscall контекст выполнения this передается через регистр ECX, а аргументы через стек.
Вы забыли добавить что это верно для х86 (о чем свидетельствуют названия регистров).

В х64 немного по другому. thiscall в вин64 игнорируется, используется только fastcall - 4 аргумента передаются в регистрах rcx, rdx, r8, r9 (или xmm0, xmm1, xmm2, xmm3 для float), остальные также через стек.
 
Автор хукает L2server.exe из C4 PTS, который -таки 64битный :)
 
Автор хукает L2server.exe из C4 PTS, который -таки 64битный :)
Тогда неувязочка вышла, так как думал, что автор ковыряется в клиенте :)
В любом случае по ключевым словам он мог найти информацию и для x64
 
Назад
Сверху Снизу