Вопрос Dota2 - Cast Target

Начинающий
Статус
Оффлайн
Регистрация
16 Авг 2022
Сообщения
36
Реакции[?]
4
Поинты[?]
4K
Hi, Is there any way that I can get which hero the enemy is looking at or which hero the enemy is casting its level?
For example I want to know if lion is casting it's ult on me. for heroes like sniper, spirit breaker, etc I can check the modifier list. but for heroes like lion idk what to do
 
Начинающий
Статус
Оффлайн
Регистрация
16 Авг 2022
Сообщения
36
Реакции[?]
4
Поинты[?]
4K
Okay I just moved to internal. is there any way to figure out who cast on us internally?
I want to make auto Counter-Spell ( for anti mage )
 
Shitcode lord 💩
Забаненный
Статус
Оффлайн
Регистрация
25 Ноя 2020
Сообщения
272
Реакции[?]
84
Поинты[?]
8K
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
C++:
// Hook CreateNetChannel 
bool Hooks::CreateNetChannel() {
    void* CreateNetChannel = Memory::GetVFunc<void*>(vmt.networkSystem, 26);
    if (!Hook(CreateNetChannel, hkCreateNetChannel, &oCreateNetChannel, "CreateNetChannel"))
        return false;

    return true;
}

// Hook PostReceivedNetMessage  in CreateNetChannel hook
INetChannel* hkCreateNetChannel(CNetworkSystem* thisptr, int unk, void* ns_addr, const char* str, unsigned int uUnk, unsigned int uUnk2) {
    INetChannel* ret = oCreateNetChannel(thisptr, unk, ns_addr, str, uUnk, uUnk2);
    DEBUG("[+] NetChannel Created => [%p]", (void*)ret);

    if (!vmt.NetChannel) {
        vmt.NetChannel = ret;
        void* PostReceivedNetMessage = Memory::GetVFunc<void*>(ret, 86);
        Hooks.Hook(PostReceivedNetMessage, hkPostReceivedNetMessage, &oPostReceivedNetMessage, "PostReceivedNetMessage");
    }

    return ret;
}

void hkPostReceivedNetMessage(INetChannel* thisptr, NetMessageHandle_t* messageHandle, google::protobuf::Message* msg, NetChannelBufType_t const* type, int bits) {
    short messageID = messageHandle->messageID;

    if (messageID == DOTA_UM_TE_Projectile) {
        CDOTAUserMsg_TE_Projectile* Projectile = (CDOTAUserMsg_TE_Projectile*)msg;

        int source = Projectile->source(); // Entity Handle
        int target = Projectile->target(); // Entity Handle
        bool is_attack = Projectile->is_attack();
       
        // Your logick here
        ..
        }
}
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
781
Реакции[?]
331
Поинты[?]
63K
C++:
// Hook CreateNetChannel
bool Hooks::CreateNetChannel() {
    void* CreateNetChannel = Memory::GetVFunc<void*>(vmt.networkSystem, 26);
    if (!Hook(CreateNetChannel, hkCreateNetChannel, &oCreateNetChannel, "CreateNetChannel"))
        return false;

    return true;
}

// Hook PostReceivedNetMessage  in CreateNetChannel hook
INetChannel* hkCreateNetChannel(CNetworkSystem* thisptr, int unk, void* ns_addr, const char* str, unsigned int uUnk, unsigned int uUnk2) {
    INetChannel* ret = oCreateNetChannel(thisptr, unk, ns_addr, str, uUnk, uUnk2);
    DEBUG("[+] NetChannel Created => [%p]", (void*)ret);

    if (!vmt.NetChannel) {
        vmt.NetChannel = ret;
        void* PostReceivedNetMessage = Memory::GetVFunc<void*>(ret, 86);
        Hooks.Hook(PostReceivedNetMessage, hkPostReceivedNetMessage, &oPostReceivedNetMessage, "PostReceivedNetMessage");
    }

    return ret;
}

void hkPostReceivedNetMessage(INetChannel* thisptr, NetMessageHandle_t* messageHandle, google::protobuf::Message* msg, NetChannelBufType_t const* type, int bits) {
    short messageID = messageHandle->messageID;

    if (messageID == DOTA_UM_TE_Projectile) {
        CDOTAUserMsg_TE_Projectile* Projectile = (CDOTAUserMsg_TE_Projectile*)msg;

        int source = Projectile->source(); // Entity Handle
        int target = Projectile->target(); // Entity Handle
        bool is_attack = Projectile->is_attack();
     
        // Your logick here
        ..
        }
}
(пишу просто так если ты вдруг не знал или если не тебе так мб другим пригодится. кр4 на будущее просто так к слову)
вместо того чтобы хукать "конструктор"(ну "создатель") нетчана, и потом из него доставать нетчан и уже потом хукать в нетчане, ты можешь сделать сигу на хреф на вмт нетчана(хрефы на вмт есть в конструкторе и деструкторе(ну кто-то же записывает вмт в [rcx+0] правильно? это конструктор делает. деструктор при деструкции тоже восстанавливает оригинальную вмт своей порции(у каждой наследованной порции свой конструктор и деструктор. их много) в случае классов с наследованием)), делаешь сигу на конструктор, из него из хрефа берешь вмт и потом сразу просто в самой вмт хукаешь. вовсе не нужна сама инстанция нетчана - нужна только сама вмт. для шедоу вмт(это подмена самой втейблы в инстанции(на свою собственную которая является копией оригинала и при этом содержит в себе вмт хуки). сама оригинальная вмт не модифицируется) уже нужна именно сама инстанция а не вмтшка. а для обычного вмт хука токо сама вмт нужна(которая с сиги берется)
этот приём очень удобно использовать в таких ситуациях когда инстанцию сложно раздобыть + ты не будешь зависеть от обстоятельств(бывает такое что инстанция тебе не сразу доступна. банально условно ты реинжектнешь свой чит внутри катки - и че откуда ты свой нетчан будешь брать если креейтнетчан уже не будет вызываться в ближайшее время? в катку придется перезаходить чтобы заинитить этот хук. вот иногда бывает удобнее в таких ситуациях если они частые просто с сиги вмт получать). ну то есть для вмт хука инстанция тебе нужна просто только для того чтобы из нее достать втейблу. так вот эту втейблу ты можешь достать из конструктора просто сделав сигу на конструктор(в нем инструкция типа mov [rcx], vftable_ptr)
сига кстати на конструктор нетчана довольно живучая
‎файл с сигой ласт модифаед Wednesday, ‎December ‎15, ‎2021, ‏‎21:16:08
у меня дота от ~начала января этого года(не обновлял пока до современной но там скорее всего тоже эта сига жива) и эту сигу все еще находит успешно. конструктор/деструктор невероятно просто находятся если у тебя уже есть вмт нетчана(например с инстанции достал и логнул например). в дебагере/в иде просто хрефы ищешь на саму вмт и всё.
1676573819805.png
C++:
//old example shitcode
class CNetworkChannel : public VClass
{
    class Constructor : PatternParent < Constructor,
        "networksystem.dll",
        "CNetworkChannel::CNetworkChannel",
        "40 53 56 57 41 56 48 83 ec ?? 45 33 f6 48 8d 71"
    >
    {
    public:
        static inline VFTable vmt{};
        static void Initialize()
        {
            constexpr InstructionProperties lea{ 3,7 };
            vmt = { GetAbsoluteAddress<lea, void*>(GetLocation<std::uintptr_t>() + 0x15) };
            if (RTTIReader::Read<1>(vmt) != "CNetChan")
                throw std::runtime_error{"CNetworkChannel::CNetworkChannel -> invalid vmt"};
        }
    };
    ...
    static VMTHook InstallHooks()
    {
        return { Constructor::vmt, SendMessageHook{}, RecvMessageHook{} };
    }
 
Последнее редактирование:
Ревёрсер среднего звена
Пользователь
Статус
Оффлайн
Регистрация
24 Ноя 2022
Сообщения
303
Реакции[?]
108
Поинты[?]
57K
(пишу просто так если ты вдруг не знал или если не тебе так мб другим пригодится. кр4 на будущее просто так к слову)
вместо того чтобы хукать "конструктор"(ну "создатель") нетчана, и потом из него доставать нетчан и уже потом хукать в нетчане, ты можешь сделать сигу на хреф на вмт нетчана(хрефы на вмт есть в конструкторе и деструкторе(ну кто-то же записывает вмт в [rcx+0] правильно? это конструктор делает. деструктор при деструкции тоже восстанавливает оригинальную вмт своей порции(у каждой наследованной порции свой конструктор и деструктор. их много) в случае классов с наследованием)), делаешь сигу на конструктор, из него из хрефа берешь вмт и потом сразу просто в самой вмт хукаешь. вовсе не нужна сама инстанция нетчана - нужна только сама вмт. для шедоу вмт(это подмена самой втейблы в инстанции(на свою собственную которая является копией оригинала и при этом содержит в себе вмт хуки). сама оригинальная вмт не модифицируется) уже нужна именно сама инстанция а не вмтшка. а для обычного вмт хука токо сама вмт нужна(которая с сиги берется)
этот приём очень удобно использовать в таких ситуациях когда инстанцию сложно раздобыть + ты не будешь зависеть от обстоятельств(бывает такое что инстанция тебе не сразу доступна. банально условно ты реинжектнешь свой чит внутри катки - и че откуда ты свой нетчан будешь брать если креейтнетчан уже не будет вызываться в ближайшее время? в катку придется перезаходить чтобы заинитить этот хук. вот иногда бывает удобнее в таких ситуациях если они частые просто с сиги вмт получать). ну то есть для вмт хука инстанция тебе нужна просто только для того чтобы из нее достать втейблу. так вот эту втейблу ты можешь достать из конструктора просто сделав сигу на конструктор(в нем инструкция типа mov [rcx], vftable_ptr)
сига кстати на конструктор нетчана довольно живучая
‎файл с сигой ласт модифаед Wednesday, ‎December ‎15, ‎2021, ‏‎21:16:08
у меня дота от ~начала января этого года(не обновлял пока до современной но там скорее всего тоже эта сига жива) и эту сигу все еще находит успешно. конструктор/деструктор невероятно просто находятся если у тебя уже есть вмт нетчана(например с инстанции достал и логнул например). в дебагере/в иде просто хрефы ищешь на саму вмт и всё.
Посмотреть вложение 238866
C++:
//old example shitcode
class CNetworkChannel : public VClass
{
    class Constructor : PatternParent < Constructor,
        "networksystem.dll",
        "CNetworkChannel::CNetworkChannel",
        "40 53 56 57 41 56 48 83 ec ?? 45 33 f6 48 8d 71"
    >
    {
    public:
        static inline VFTable vmt{};
        static void Initialize()
        {
            constexpr InstructionProperties lea{ 3,7 };
            vmt = { GetAbsoluteAddress<lea, void*>(GetLocation<std::uintptr_t>() + 0x15) };
            if (RTTIReader::Read<1>(vmt) != "CNetChan")
                throw std::runtime_error{"CNetworkChannel::CNetworkChannel -> invalid vmt"};
        }
    };
    ...
    static VMTHook InstallHooks()
    {
        return { Constructor::vmt, SendMessageHook{}, RecvMessageHook{} };
    }
Кстати интересный подход к нахождению нетчана, возьму на заметку
 
Shitcode lord 💩
Забаненный
Статус
Оффлайн
Регистрация
25 Ноя 2020
Сообщения
272
Реакции[?]
84
Поинты[?]
8K
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
(пишу просто так если ты вдруг не знал или если не тебе так мб другим пригодится. кр4 на будущее просто так к слову)
вместо того чтобы хукать "конструктор"(ну "создатель") нетчана, и потом из него доставать нетчан и уже потом хукать в нетчане, ты можешь сделать сигу на хреф на вмт нетчана(хрефы на вмт есть в конструкторе и деструкторе(ну кто-то же записывает вмт в [rcx+0] правильно? это конструктор делает. деструктор при деструкции тоже восстанавливает оригинальную вмт своей порции(у каждой наследованной порции свой конструктор и деструктор. их много) в случае классов с наследованием)), делаешь сигу на конструктор, из него из хрефа берешь вмт и потом сразу просто в самой вмт хукаешь. вовсе не нужна сама инстанция нетчана - нужна только сама вмт. для шедоу вмт(это подмена самой втейблы в инстанции(на свою собственную которая является копией оригинала и при этом содержит в себе вмт хуки). сама оригинальная вмт не модифицируется) уже нужна именно сама инстанция а не вмтшка. а для обычного вмт хука токо сама вмт нужна(которая с сиги берется)
этот приём очень удобно использовать в таких ситуациях когда инстанцию сложно раздобыть + ты не будешь зависеть от обстоятельств(бывает такое что инстанция тебе не сразу доступна. банально условно ты реинжектнешь свой чит внутри катки - и че откуда ты свой нетчан будешь брать если креейтнетчан уже не будет вызываться в ближайшее время? в катку придется перезаходить чтобы заинитить этот хук. вот иногда бывает удобнее в таких ситуациях если они частые просто с сиги вмт получать). ну то есть для вмт хука инстанция тебе нужна просто только для того чтобы из нее достать втейблу. так вот эту втейблу ты можешь достать из конструктора просто сделав сигу на конструктор(в нем инструкция типа mov [rcx], vftable_ptr)
сига кстати на конструктор нетчана довольно живучая
‎файл с сигой ласт модифаед Wednesday, ‎December ‎15, ‎2021, ‏‎21:16:08
у меня дота от ~начала января этого года(не обновлял пока до современной но там скорее всего тоже эта сига жива) и эту сигу все еще находит успешно. конструктор/деструктор невероятно просто находятся если у тебя уже есть вмт нетчана(например с инстанции достал и логнул например). в дебагере/в иде просто хрефы ищешь на саму вмт и всё.
Посмотреть вложение 238866
C++:
//old example shitcode
class CNetworkChannel : public VClass
{
    class Constructor : PatternParent < Constructor,
        "networksystem.dll",
        "CNetworkChannel::CNetworkChannel",
        "40 53 56 57 41 56 48 83 ec ?? 45 33 f6 48 8d 71"
    >
    {
    public:
        static inline VFTable vmt{};
        static void Initialize()
        {
            constexpr InstructionProperties lea{ 3,7 };
            vmt = { GetAbsoluteAddress<lea, void*>(GetLocation<std::uintptr_t>() + 0x15) };
            if (RTTIReader::Read<1>(vmt) != "CNetChan")
                throw std::runtime_error{"CNetworkChannel::CNetworkChannel -> invalid vmt"};
        }
    };
    ...
    static VMTHook InstallHooks()
    {
        return { Constructor::vmt, SendMessageHook{}, RecvMessageHook{} };
    }
Таки да, с ре-инжектом это и правда поможет. Задолбался уже доту перезапускать xd
Чет вообще не додумался просто сигой сделать, хотя это вроде супер очевидно.
 
Начинающий
Статус
Оффлайн
Регистрация
12 Ноя 2022
Сообщения
63
Реакции[?]
23
Поинты[?]
3K
C++:
//old example shitcode
class CNetworkChannel : public VClass
{
    class Constructor : PatternParent < Constructor,
        "networksystem.dll",
        "CNetworkChannel::CNetworkChannel",
        "40 53 56 57 41 56 48 83 ec ?? 45 33 f6 48 8d 71"
    >
    {
    public:
        static inline VFTable vmt{};
        static void Initialize()
        {
            constexpr InstructionProperties lea{ 3,7 };
            vmt = { GetAbsoluteAddress<lea, void*>(GetLocation<std::uintptr_t>() + 0x15) };
            if (RTTIReader::Read<1>(vmt) != "CNetChan")
                throw std::runtime_error{"CNetworkChannel::CNetworkChannel -> invalid vmt"};
        }
    };
    ...
    static VMTHook InstallHooks()
    {
        return { Constructor::vmt, SendMessageHook{}, RecvMessageHook{} };
    }
У тебя SendMessageHook и Recv это классы? Что из себя представляют? Просто индекс и колбэк? Интересно с архитектурной точки зрения.

Просто взгляд со стороны, не критика. Тем более если код старый мог поменять.
Проверка по RTTI нравится. 2 stage initialization не очень нравится.
По сути чтобы либу выгрузить правильно для повторного инжекта нужно сделать 2 действия вручную UninstallHooks() и Unitialize() причём в правильном порядке.

PS. Вак не ебёт за патч внутри вмт?
 
Последнее редактирование:
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
781
Реакции[?]
331
Поинты[?]
63K
У тебя SendMessageHook и Recv это классы? Что из себя представляют? Просто индекс и колбэк? Интересно с архитектурной точки зрения.

Просто взгляд со стороны, не критика. Тем более если код старый мог поменять.
Проверка по RTTI нравится. 2 stage initialization не очень нравится.
По сути чтобы либу выгрузить правильно для повторного инжекта нужно сделать 2 действия вручную UninstallHooks() и Unitialize() причём в правильном порядке.

PS. Вак не ебёт за патч внутри вмт?
не, там RAII. InstallHooks посмотри что возвращает(возвращает объект который отвечает за жизнь хуков. он убирает хуки за собой когда умирает). я вручную нихуя не делаю при деините.
а Initialize это инит конкретно для сиги(у меня "сига" это не просто сама сига как строка но еще и ассоциированные с ней данные - например в данном случае сама сига то на конструктор, а в конструкторе я с оффсета вмт считываю. вот вмт у меня и лежит в сиге)(там нету деинита сигу незачем деинитить xD). просто часто бывает что тебе не только сама сига должна найтись, но ты еще и с оффсета должен считать данные там и тд и тп и вот я всё это в ините сиги делаю(и если чето идет не так то кидаю ашипку). у меня просто сиги пачкой(естесна автоматизированно) хранятся и я их сразу чуть ли не первым шагом в ините чита ищу(и при нахождении инит вызываю) и если какую-либо сигу не найдет(или при чтении с оффсета от сиги там че-нибудь по пизде например пойдет) то я сразу в начале инита еще пизды получу(еще до установки всяких хуков и тд) и сразу об этом узнаю
а так да, классы хуков это просто классы с индексом и коллбеком(менеджер хуков(тот кто хуки ставит) из этого класса-хука берет индекс и коллбек и дальше делает что надо с ними)
C++:
class ShitHook : public BaseVMTHook<ShitHook, 228>//index 228
{
public:
    static return_type Hook(void* thisptr, blablabla) noexcept
    {
        ...
        return CallOriginal(thisptr, blablabla);
    }
};
+ там трансляция конвенции(ну в современном коде а не в этом старом) в __cdecl(для х86 и х64 совместимости и упрощения жизни на х86. на х64 все конвенции одинаковые а на х86 там всё сложно, приходится __fastcall юзать из него ecx доставать edx выбрасывать и тд и тп(а вот на х64 в фасткалле уже не нельзя нихуя выбрасывать, там rdx полезный регистр). можно жизнь себе облегчить засунув в вмт хук не сам финальный коллбек твоего хука, а "транслятор" который имеет __fastcall конвенцию, (через #ifdef WIN32 блаблабла, на х64 не надо ничего делать) выкидывает если надо edx на х86 и вызывает финальный коллбек который __cdecl)
на х64 нихуя не надо делать поэтому там всё напрямую, а в х86 условно:
C++:
//x86
void myhook(void* thisptr, void* param1, void* param2, blablabla...);
void __fastcall myhook_translate(void* thisptr, void* edx_musor, void* param1, void* param2, blablabla...)
{
    return myhook(thisptr, param1, param2, blablabla...);//едх в мусор ибо на самом деле оригинал это __thiscall и там нету едх. фасткалл используется просто как "абуз" чтобы достать есх ибо компилятор не дает thiscall юзать
}
install_hook(..., &myhook_translate)
ток в более автоматизированном режиме)
за обычные вмт хуки да, наверно вак ебет(ну он хоть и тупой но не настолько же тупой чтобы супер старые техники не детектить)
RTTIReader это:
//щиткод как обычно на скорую руку написанный особо не тесщенный и тд полюбас там багов и прочей хуйни дохуя. ну так то вроде работает и на х64 и на х86(там ифдефы есть) но опять таки особо не тестил
//вся суть в том что в ВМТ(если ртти не вырублен в компиляторе. в доте он врублен) в МИНУС ПЕРВОЙ(-1) ячейке(то есть на одну ячейку выше чем нулевая(первая) функция) лежит мета-информация в виде RVA оффсетов от начала модуля где вмт находится, и по этим оффсетам там лежит всякая хуйня типо имён и тд
RTTIReader:
/*
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
super super shitcode copy&paste from:
https://github.com/ReClassNET/ReClass.NET/blob/master/ReClass.NET/Memory/RemoteProcess.cs#L215
test & fix before using
*/
#include <Windows.h>
#include <dbghelp.h>
#pragma comment(lib, "Dbghelp.lib")
...
class RTTIReader
{
    class schema
    {
        std::uint64_t idk1;
        std::uint64_t idk2;
    public:
        std::uint32_t descriptor_offset;
    private:
        std::uint32_t base_offset;
    public:
        auto GetBaseAddress() const noexcept
        {
#ifdef _WIN64
            return reinterpret_cast<std::uintptr_t>(this) - base_offset;
#else
            return reinterpret_cast<std::uintptr_t>(this);
#endif
        }
    };
    class descriptor
    {
    public:
        std::uint64_t idk;
        std::uint32_t class_count;
        std::uint32_t baseClassArrayPtr;
    };  
    class class_descriptor
    {
    public:
        std::uint32_t type_descriptor_offs;
    };  
    class type_descriptor
    {
        std::uintptr_t vftable;
        std::uintptr_t idfk;
        std::uint32_t somesig;
        char name;
    public:
        std::string_view GetName() const noexcept
        {
            return { &name };
        }
    };
    template<typename ReturnType = std::uintptr_t>
    static ReturnType TranslateAddress(std::uintptr_t address, std::uintptr_t base) noexcept
    {
#ifdef _WIN64
        return reinterpret_cast<ReturnType>(base + address);
#else
        return reinterpret_cast<ReturnType>(address);
#endif
    }
public:
    template<std::size_t Depth = (std::numeric_limits<std::size_t>::max)()>
    static std::string Read(const VClass& instance) noexcept
    {
        return Read<Depth>(instance.GetVMT());
    }
    template<std::size_t Depth = (std::numeric_limits<std::size_t>::max)()>
    static std::string Read(const VFTable& vmt) noexcept
    {
        try {
            auto vftbl_ptr = vmt.GetPtr<const schema**>();
            if (!vftbl_ptr) return {};
            const auto schema = *(vftbl_ptr - 1);
            if (!schema) return {};
            const auto base = schema->GetBaseAddress();
            if (!base) return {};
            const auto descriptor_ptr = TranslateAddress<const descriptor*>(schema->descriptor_offset, base);
            if (!descriptor_ptr) return {};
            const auto class_count = descriptor_ptr->class_count;
            if (!(class_count > 0 && class_count < 25)) return {};
            const auto array_ptr = TranslateAddress<const std::uint32_t*>
                (descriptor_ptr->baseClassArrayPtr, base);
            if (!array_ptr) return {};
            std::string result{};
            bool firstIteration = true;
            for (
                const std::span<const std::uint32_t> offset_tbl{ array_ptr, (std::min)(
                    static_cast<std::size_t>(class_count), Depth
                    ) };
                const auto offs : offset_tbl)
            {
                const auto element_ptr = TranslateAddress<const class_descriptor*>
                    (offs, base);
                if (!element_ptr) continue;

                const auto type_desc = TranslateAddress<const type_descriptor*>
                    (element_ptr->type_descriptor_offs, base);
                if (!type_desc) continue;

                if (!firstIteration)
                    result += " : ";

                const auto type_name = type_desc->GetName();
                if (type_name.ends_with("@@"))
                {
                    std::string full_name;
                    full_name.reserve(type_name.length() + 2);
                    full_name += "?";
                    full_name += type_name;
                    std::string undecorated_buffer{};
                    undecorated_buffer.reserve(256);
                    const auto bufSize = UnDecorateSymbolName(
                        full_name.c_str(),
                        undecorated_buffer.data(),
                        static_cast<DWORD>(undecorated_buffer.capacity()),
                        UNDNAME_NAME_ONLY
                    );
                    if (bufSize != 0)
                    {
                        result += std::string_view{ undecorated_buffer.data(), bufSize };
                    }
                    else
                        result += type_name;
                }
                else
                    result += type_name;
                firstIteration = false;
            }
            return result;
        }
        catch (...) {
            return {};
        }
    }
};
 
Последнее редактирование:
Начинающий
Статус
Оффлайн
Регистрация
12 Ноя 2022
Сообщения
63
Реакции[?]
23
Поинты[?]
3K
не, там RAII. InstallHooks посмотри что возвращает(возвращает объект который отвечает за жизнь хуков. он убирает хуки за собой когда умирает). я вручную нихуя не делаю при деините.
Понял, если RAII тогда чотко всё. Единственное тогда странно почему просто не хранить в самом классе, зачем передавать владение вызывающему. Больше связанности получается между разными частями кода. Ну ладно я всего когда не видел трудно так судить, да и дело вкуса.

Спасибо что немного показал свой взгляд на хуки.
Делаю headeronly либу для safe(с копированием) VMT хуков которой пользуюсь давно(для хука виртуалки достаточно передать на неё member pointer если есть SDK, типо не нужно запоминанть индексы высчитывать их всё время и тд), хочу её в опенсорс выложить и думал как раз как лучше интерфейс для взаимодействия предоставить, единственное я исключения не уважаю, потому factory скорее всего будет чтобы вернуть ошибку, а в конструкторе нельзя.

По поводу RTTI я шарю, а вот про проблему с edx в x86 хуках никогда не слышал потому что не работал с x86 особо, благодарю
 
Последнее редактирование:
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
781
Реакции[?]
331
Поинты[?]
63K
Понял, если RAII тогда чотко всё. Единственное тогда странно почему просто не хранить в самом классе, зачем передавать владение вызывающему. Больше связанности получается между разными частями кода. Ну ладно я всего когда не видел трудно так судить, да и дело вкуса.

Спасибо что немного показал свой взгляд на хуки.
Делаю headeronly либу для safe(с копированием) VMT хуков которой пользуюсь давно(для хука виртуалки достаточно передать на неё member pointer если есть SDK, типо не нужно запоминанть индексы высчитывать их всё время и тд), хочу её в опенсорс выложить и думал как раз как лучше интерфейс для взаимодействия предоставить, единственное я исключения не уважаю, потому factory скорее всего будет чтобы вернуть ошибку, а в конструкторе нельзя.

По поводу RTTI я шарю, а вот про проблему с edx в x86 хуках никогда не слышал потому что не работал с x86 особо, благодарю
там в х86 ваще ад. компилятор с++ не даёт просто так __thiscall повесить на обычные функции, выебывается. поэтому люди юзают __fastcall для "эмуляции" __thiscall(они практически одинаковые, просто у фасткалла еще и в edx данные есть). т.к. сама реальная функция __thiscall, то в edx у нее данных естественно нет, и поэтом ты в своём хуке который __fastcall должен игнорить(ну то есть он у тебя в функции как параметр есть но ты с ним ничего не делаешь) edx(ибо ты фасткалл используешь только в качестве "абуза", настоящая конвенция то __thiscall, просто тебе компилятор не дает ее нацепить). также некоторые люди еще всякие приколюхи выдумывают чтобы официально __thiscall можно было ставить(но мне такое не по вкусу) - оформляют хук в качестве мембер функции
Пожалуйста, авторизуйтесь для просмотра ссылки.

еще иногда есть ситуации когда конвенция ваще абсолютно ебанутая(компилятор намеренно "оптимизирует" и создает свою кастомную нелегальную неофициальную конвенцию). ида вроде такие конвенции обычно __usercall помечает(типа кастомная хуйня кр4 ебанутая, выдумка компилятора).
у конвенции два основных аспекта - передача аргументов в функцию(что куда в какие регистры и тд) и "подчистка"(кто подчищает(вызывающий, вызываемый), как и тд). так вот иногда компиляторы в целях оптимизации выдумывают свою собственную конвенцию неофициальную которая совмещает в себе передачу аргументов из одной конвенции, а подчистку из другой - тогда приходится либо какието выебоны с __asm придумывать либо какие-то другие абузы юзать. помню долго сидел и думал хули крашит когда функу вызывал(ведь сука крашило то не сразу - крашило потом(т.к. стек был засран изза некорректной очистки) в какой-то жопе) когда такую хуйню встретил.
 
Начинающий
Статус
Оффлайн
Регистрация
12 Ноя 2022
Сообщения
63
Реакции[?]
23
Поинты[?]
3K
там в х86 ваще ад. компилятор с++ не даёт просто так __thiscall повесить на обычные функции, выебывается. поэтому люди юзают __fastcall для "эмуляции" __thiscall(они практически одинаковые, просто у фасткалла еще и в edx данные есть). т.к. сама реальная функция __thiscall, то в edx у нее данных естественно нет, и поэтом ты в своём хуке который __fastcall должен игнорить(ну то есть он у тебя в функции как параметр есть но ты с ним ничего не делаешь) edx(ибо ты фасткалл используешь только в качестве "абуза", настоящая конвенция то __thiscall, просто тебе компилятор не дает ее нацепить). также некоторые люди еще всякие приколюхи выдумывают чтобы официально __thiscall можно было ставить(но мне такое не по вкусу) - оформляют хук в качестве мембер функции
Пожалуйста, авторизуйтесь для просмотра ссылки.

еще иногда есть ситуации когда конвенция ваще абсолютно ебанутая(компилятор намеренно "оптимизирует" и создает свою кастомную нелегальную неофициальную конвенцию). ида вроде такие конвенции обычно __usercall помечает(типа кастомная хуйня кр4 ебанутая, выдумка компилятора).
у конвенции два основных аспекта - передача аргументов в функцию(что куда в какие регистры и тд) и "подчистка"(кто подчищает(вызывающий, вызываемый), как и тд). так вот иногда компиляторы в целях оптимизации выдумывают свою собственную конвенцию неофициальную которая совмещает в себе передачу аргументов из одной конвенции, а подчистку из другой - тогда приходится либо какието выебоны с __asm придумывать либо какие-то другие абузы юзать. помню долго сидел и думал хули крашит когда функу вызывал(ведь сука крашило то не сразу - крашило потом(т.к. стек был засран изза некорректной очистки) в какой-то жопе) когда такую хуйню встретил.
А как он имеют право такие функции делать? есть ABI он обязан ему следовать иначе всё сломается.

Пожалуйста, авторизуйтесь для просмотра ссылки.

декомпайлер может неправильно определять либо реально какой то inline asm.
Но компилятор не имеет права без особых указаний так себя вести, вдруг кто то эту функцию в export засунет.
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
781
Реакции[?]
331
Поинты[?]
63K
А как он имеют право такие функции делать? есть ABI он обязан ему следовать иначе всё сломается.

Пожалуйста, авторизуйтесь для просмотра ссылки.

декомпайлер может неправильно определять либо реально какой то inline asm.
Но компилятор не имеет права без особых указаний так себя вести, вдруг кто то эту функцию в export засунет.
ну да ида может ошибаться, но я там лично удостоверился что там кастомная конвенция
ну да я же говорил в целях оптимизации(это и есть в какой-то степени "особые указания", оптимизацию же ктото включил) это скорее всего было сделано - наверно линк тайм код генерейшн был включён в настройках проекта, у него как раз в доках
1676815056847.png
+ там функция как раз вызывалась изнутри dynamic initializer'ов или чего-то подобного, а за это как раз линкер отвечает
 
Начинающий
Статус
Оффлайн
Регистрация
16 Авг 2022
Сообщения
36
Реакции[?]
4
Поинты[?]
4K
C++:
// Hook CreateNetChannel
bool Hooks::CreateNetChannel() {
    void* CreateNetChannel = Memory::GetVFunc<void*>(vmt.networkSystem, 26);
    if (!Hook(CreateNetChannel, hkCreateNetChannel, &oCreateNetChannel, "CreateNetChannel"))
        return false;

    return true;
}

// Hook PostReceivedNetMessage in CreateNetChannel hook
INetChannel* hkCreateNetChannel(CNetworkSystem* thisptr, int unk, void* ns_addr, const char* str, unsigned int uUnk, unsigned int uUnk2) {
    INetChannel* ret = oCreateNetChannel(thisptr, unk, ns_addr, str, uUnk, uUnk2);
    DEBUG("[+] NetChannel Created => [%p]", (void*)ret);

    if (!vmt.NetChannel) {
        vmt.NetChannel = ret;
        void* PostReceivedNetMessage = Memory::GetVFunc<void*>(ret, 86);
        Hooks.Hook(PostReceivedNetMessage, hkPostReceivedNetMessage, &oPostReceivedNetMessage, "PostReceivedNetMessage");
    }

    return ret;
}

void hkPostReceivedNetMessage(INetChannel* thisptr, NetMessageHandle_t* messageHandle, google::protobuf::Message* msg, NetChannelBufType_t const* type, int bits) {
    short messageID = messageHandle->messageID;

    if (messageID == DOTA_UM_TE_Projectile) {
        CDOTAUserMsg_TE_Projectile* Projectile = (CDOTAUserMsg_TE_Projectile*)msg;

        int source = projectile->source(); // entity handle
        int target = projectile->target(); // entity handle
        bool is_attack = Projectile->is_attack();
     
        // Your logic here
        ..
        }
}
Thanks for your help. But some abilities exist without creating a projectile ( Engima Q, Winter Wyvern R, Outworld Destroyer W ), so it only works for abilities that create a projectile like sniper ultimate. I was hoping to find a more general way
 
Начинающий
Статус
Оффлайн
Регистрация
13 Янв 2020
Сообщения
5
Реакции[?]
0
Поинты[?]
0
Thanks for your help. But some abilities exist without creating a projectile ( Engima Q, Winter Wyvern R, Outworld Destroyer W ), so it only works for abilities that create a projectile like sniper ultimate. I was hoping to find a more general way
I guess, you can check if caster's forward vector is directed to unit, considering ability's cast range.
math trick:
/**
 * [USER=804731]@param[/USER] {Vector} v1
 * [USER=804731]@param[/USER] {Vector} v2
 * [USER=804731]@param[/USER] {number?} tolerance
 * @returns {boolean}
 */
isIn(v1, v2, tolerance) {
    tolerance = tolerance || 50;
    if (this.x >= Math.max(v1.x, v2.x) + tolerance || this.x <= Math.min(v1.x, v2.x) - tolerance || this.y <= Math.min(v1.y, v2.y) - tolerance || this.y >= Math.max(v1.y, v2.y) + tolerance) {
        return false;
    } else if (v1.x == v2.x) {
        return Math.abs(v1.x - this.x) < tolerance;
    } else if (v1.y == v2.y) {
        return Math.abs(v1.y - this.y) < tolerance;
    };
    return Math.abs(((v2.x - v1.x) * (v1.y - this.y)) - ((v1.x - this.x) * (v2.y - v1.y))) / Math.sqrt((v2.x - v1.x) * (v2.x - v1.x) + (v2.y - v1.y) * (v2.y - v1.y)) < tolerance;
};

const casterpos = caster.GetAbsOrigin(false);
const casterpos_added = casterpos.add(caster.GetForward(false).scale(ability_info["cast_range"]+ability_info["aoe_radius"]));
const unitpos = unit.GetAbsOrigin(false);

const can_cast = unitpos.isIn(casterpos, casterpos_added);
 
Похожие темы
Сверху Снизу