Гайд Новые сигнатуры, индексы и оффсеты под обновления

Начинающий
Статус
Оффлайн
Регистрация
4 Апр 2024
Сообщения
28
Реакции[?]
1
Поинты[?]
1K
там вроде была функа Dump виртуальная она в консоль итем высирает, поищи вроде 6 индекс была щас не знаю какой(если ее еще не убрали конеш).
Все еще 6-ой индекс, но не совсем то, что нужно.
1717497557484.png
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
Все еще 6-ой индекс, но не совсем то, что нужно.
Посмотреть вложение 278262
Есть у кого-то актуальные оффсеты CEconItem?
дамп в помощь оффсеты искать. сопоставляешь то что видишь в консоли с тем что в памяти, если что-то неоднозначно/непонятно значит меняешь в памяти смотришь в дампе поменялось или нет
Все еще 6-ой индекс, но не совсем то, что нужно.
Посмотреть вложение 278262
можешь впринципе просто присылать самому себе фейковые CMsgSOMultipleObjects и не трогать руками ничего. собственно сама дота так и делает(от гс приходит CMsgSOMultipleObjects и из этого уже клиент шмоточки себе делает)
 
Начинающий
Статус
Оффлайн
Регистрация
4 Апр 2024
Сообщения
28
Реакции[?]
1
Поинты[?]
1K
присылать самому себе фейковые CMsgSOMultipleObjects и не трогать руками ничего
Ты имеешь ввиду хук RetrieveMessage и там создавать этот СMsgSOMultipleObjects?

клиент шмоточки себе делает
Создает EConItem на основе данных в CMsgSOMultipleObjects ?
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
Ты имеешь ввиду хук RetrieveMessage и там создавать этот СMsgSOMultipleObjects?


Создает EConItem на основе данных в CMsgSOMultipleObjects ?
1) да но и не только это(этого недостаточно. как минимум потому что RetrieveMessage ты не контроллируешь когда вызывается. толку от хука если не будет вызываться(надо заставлять вызывать))
2) да. ну сам подумай - сервак же сериализует, он же тебе не будет скидывать свою оперативку которая хер знает какую структуру имеет(мб сервак на линуксе? мб сервак не на интеловской архитектуре? мб еще что-то);(сериализованные данные примерно могут выглядеть как то что ты с Dump в консоли увидел токо не в виде строки естественно) клиент потом это десериализует и у себя делает шмотку в оперативке. можешь попробовать в реальной доте со стимом без ничего просто консоль открыть шмотку одеть и посмотреть че в консоль напишет(а тебе напишет что ты отправил ЭквипРеквест условно и получил ЭквипРеспонс и поверх него еще АпдейтМультипл)
 
Начинающий
Статус
Оффлайн
Регистрация
4 Апр 2024
Сообщения
28
Реакции[?]
1
Поинты[?]
1K
Я тут внезапно обнаружил, что объектов класса C_FogController несколько, в демке 2, с ботами вообще создается сначала 7 еще на стадии пика, при этом искомый будет 6-ым. После пика 5 из них удаляются и в самом начале матча создается еще 5 и сразу же удаляются и остается только 2.
При этом нужен только 1 и разница между ним и вторым в наличии имени на 0x18(CUtlSymbolLarge* m_name).
Ну и все бы хорошо но это второе имя присваивается в CEntityIdentity::SetEntityName, которое вызывается когда-то после OnAdd, а до тех пор, эти C_FogController идентичны по сути. Т.е. хук OnAdd с этим объектом не то чтобы помогает.
Сейчас я создал map<&C_FogController, C_FogController*>, после я запихиваю туда все эти объекты и выпиливаю из него все указатели, объекты которых засветились в OnRemove, затем я проверяю у кого есть имя на 0х18 и удаляю объект с этим именем.
Крч костыль, кто-то решал такое?
 
Последнее редактирование:
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
Я тут внезапно обнаружил, что объектов класса C_FogController несколько, в демке 2, с ботами вообще создается сначала 7 еще на стадии пика, при этом искомый будет 6-ым. После пика 5 из них удаляются и в самом начале матча создается еще 5 и сразу же удаляются и остается только 2.
При этом нужен только 1 и разница между ним и вторым в наличии имени на 0x18(CUtlSymbolLarge* m_name).
Ну и все бы хорошо но это второе имя присваивается в CEntityIdentity::SetEntityName, которое вызывается когда-то после OnAdd, а до тех пор, эти C_FogController идентичны по сути. Т.е. хук OnAdd с этим объектом не то чтобы помогает.
Сейчас я создал map<&C_FogController, C_FogController*>, после я запихиваю туда все эти объекты и выпиливаю из него все указатели, объекты которых засветились в OnRemove, затем я проверяю у кого есть имя на 0х18 и удаляю объект с этим именем.
Крч костыль, кто-то решал такое?
не тестил(ну точнее тестил но поверхностно слишком тяп ляп) но попробуй, должно работать в теории
CBasePlayerController::m_hPawn->m_pCameraServices->m_PlayerFog->m_hCtrl
 
Начинающий
Статус
Оффлайн
Регистрация
4 Апр 2024
Сообщения
28
Реакции[?]
1
Поинты[?]
1K
C++:
static CMemAlloc* g_pMemAlloc = *Memory::GetExport<CMemAlloc**>("tier0.dll", "g_pMemAlloc");
1718652567535.png
Я правильно понимаю, что это(стянуто с McDota) является новым классом и в дилибах его нету? Или он там назван иначе?
И еще вопрос. Я так понимаю, что можно вместо хука OnAddEntity влезть в габеновский вектор в EntitySystem
1718654370402.png
Запихать туда то, что реализует OnEntityCreated на 0 индексе вмт и она будет вызываться на каждом тике.
Но я чет не понимаю, что я тут вижу.
По идее 3 это size, потом должно быть 3 элемента(по указателю) IEntityListener и первая ссылка это оно и есть, а дальше какой-то рандом.
1718654466525.png
 
Последнее редактирование:
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
C++:
static CMemAlloc* g_pMemAlloc = *Memory::GetExport<CMemAlloc**>("tier0.dll", "g_pMemAlloc");
Посмотреть вложение 279450
Я правильно понимаю, что это(стянуто с McDota) является новым классом и в дилибах его нету? Или он там назван иначе?
чекни
Пожалуйста, авторизуйтесь для просмотра ссылки.
там есть экспорты в tier0 в стиле
MemAlloc_ReallocFunc
MemAlloc_AllocFunc
MemAlloc_FreeFunc
там индексы эти есть
 
Начинающий
Статус
Оффлайн
Регистрация
4 Апр 2024
Сообщения
28
Реакции[?]
1
Поинты[?]
1K
И еще вопрос. Я так понимаю, что можно вместо хука OnAddEntity влезть в габеновский вектор в EntitySystem
Посмотреть вложение 279452
Запихать туда то, что реализует OnEntityCreated на 0 индексе вмт и она будет вызываться на каждом тике.
Но я чет не понимаю, что я тут вижу.
По идее 3 это size, потом должно быть 3 элемента(по указателю) IEntityListener и первая ссылка это оно и есть, а дальше какой-то рандом.
Посмотреть вложение 279453
Так, тут все путем, просто такая вот плотность да. Пихается туда, что угодно, реализующие интерфейс IEntityListener и дальше у этого объекта вызываются эти функции в зависимости от того, что произошло: создалось энтити - OnEntityCreated...
C++:
class IEntityListener {
public:
    virtual void OnEntityCreated(C_BaseEntity* ent) = 0;
    virtual void OnEntitySpawned(C_BaseEntity* ent) {};
    virtual void OnEntityDeleted(C_BaseEntity* ent) = 0;
    virtual void OnEntityParentChanged(C_BaseEntity* ent, C_BaseEntity* parent) {};
};
 
Начинающий
Статус
Оффлайн
Регистрация
29 Июн 2019
Сообщения
8
Реакции[?]
0
Поинты[?]
0
Is CCvar/CVarNode changed? I've checked, everything is fine (I guess), but:

C++:
uint32_t CCVar::GetCVarCount()
{
    return Member<uint32_t>(0xA0);
}

CVarNode* CCVar::GetCVarNodeList()
{
    return Member<CVarNode*>(0x40);
}

    auto list = GetCVarNodeList();
    auto size = GetCVarCount();

    for (int i = 0; i < size; i++)
    {
        auto var = list[i].var;
        if (!var || !var->name)
            continue;

        CVarID id;
        id.m_pVar = var;
        id.impl = static_cast<uint64_t>(i);
        CVars[var->name] = id;
    }


struct CVar
{
    const char* name{};
    CVar* m_pNext{};
    PAD(16,1)
    const char* desc{};
    EConvarType type{};
    uint32_t timesChanged{};
    uint32_t flags{};
    PAD(4,2)
    int m_iCallbackIndex{};
    PAD(4,3)
    CVarValue value{};
    CVarValue defaultValue{};
}
When I'm iterating through list (GetCVarNodeList) some addresses are invalid. So it crashes when it tries to access var->name. GetCVarCount() returns 5203 and the list gets invalid addresses after 5120. Maybe I'm getting wrong size?

It sometime happens and sometime not !
 
Последнее редактирование:
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
Is CCvar/CVarNode changed? I've checked, everything is fine (I guess), but:

C++:
uint32_t CCVar::GetCVarCount()
{
    return Member<uint32_t>(0xA0);
}

CVarNode* CCVar::GetCVarNodeList()
{
    return Member<CVarNode*>(0x40);
}

    auto list = GetCVarNodeList();
    auto size = GetCVarCount();

    for (int i = 0; i < size; i++)
    {
        auto var = list[i].var;
        if (!var || !var->name)
            continue;

        CVarID id;
        id.m_pVar = var;
        id.impl = static_cast<uint64_t>(i);
        CVars[var->name] = id;
    }


struct CVar
{
    const char* name{};
    CVar* m_pNext{};
    PAD(16,1)
    const char* desc{};
    EConvarType type{};
    uint32_t timesChanged{};
    uint32_t flags{};
    PAD(4,2)
    int m_iCallbackIndex{};
    PAD(4,3)
    CVarValue value{};
    CVarValue defaultValue{};
}
When I'm iterating through list (GetCVarNodeList) some addresses are invalid. So it crashes when it tries to access var->name. GetCVarCount() returns 5203 and the list gets invalid addresses after 5120. Maybe I'm getting wrong size?

It sometime happens and sometime not !
try the count from 0x58
C++:
auto GetCvarList() const noexcept
{
    return std::span<const CvarNode>{ Member<const CvarNode*>(0x40), Member<std::uint16_t>(0x58) };
}
 
Начинающий
Статус
Оффлайн
Регистрация
4 Апр 2024
Сообщения
28
Реакции[?]
1
Поинты[?]
1K
Кто-то знает как можно получить имя героя, которого пикнул енеми?
В C_DOTAPlayerController есть CHandle сущности, он появляется там на стадии PRE_GAME, но в EntityList'e такой сущности просто нету(пока она в тумане войны), а в панораму, что-то вообще лезть не хочется.
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
Кто-то знает как можно получить имя героя, которого пикнул енеми?
В C_DOTAPlayerController есть CHandle сущности, он появляется там на стадии PRE_GAME, но в EntityList'e такой сущности просто нету(пока она в тумане войны), а в панораму, что-то вообще лезть не хочется.
попробуй PlayerResourcePlayerTeamData_t(из C_DOTA_PlayerResource::m_vecPlayerTeamData)::m_nSelectedHeroID
хиро айдишники есть в scripts\npc\npc_heroes.txt
или в DOTAHeroDefinition_t(в C_DOTAGameManager)
 
Начинающий
Статус
Оффлайн
Регистрация
4 Апр 2024
Сообщения
28
Реакции[?]
1
Поинты[?]
1K
попробуй PlayerResourcePlayerTeamData_t(из C_DOTA_PlayerResource::m_vecPlayerTeamData)::m_nSelectedHeroID
хиро айдишники есть в scripts\npc\npc_heroes.txt
или в DOTAHeroDefinition_t(в C_DOTAGameManager)
К сожалению C_DOTA_PlayerResource энеми вообще в EntityList'e не появляется.
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
К сожалению C_DOTA_PlayerResource энеми вообще в EntityList'e не появляется.
пруф? на локалке и в стокгольме проверил все работает. плеер ресурс если что только один, глобальный. там вектор с данными по всем игрокам.
1724857396508.png
1724857426575.png
C++:
-----members of class C_DOTA_PlayerResource-----
    ...
    C_UtlVectorEmbeddedNetworkVar< PlayerResourcePlayerTeamData_t > m_vecPlayerTeamData(offset 0x550, size 0x50, align 0x8)
1724857573211.png
 
Начинающий
Статус
Оффлайн
Регистрация
4 Апр 2024
Сообщения
28
Реакции[?]
1
Поинты[?]
1K
пруф? на локалке и в стокгольме проверил все работает. плеер ресурс если что только один, глобальный. там вектор с данными по всем игрокам.
Посмотреть вложение 284341
Посмотреть вложение 284342
C++:
-----members of class C_DOTA_PlayerResource-----
    ...
    C_UtlVectorEmbeddedNetworkVar< PlayerResourcePlayerTeamData_t > m_vecPlayerTeamData(offset 0x550, size 0x50, align 0x8)
Посмотреть вложение 284343
Протупил мальца, я чет думал, что там этих C_DOTA_PlayerResource на каждый C_DOTAPlayerController.
Но я же одним PlayerResourcePlayerTeamData_t не смогу соотнести этот HeroID с конкретным C_DOTAPlayerController?
Я нашел вектор PlayerResourcePlayerData_t, там есть имя учетки Steam и SteamID, и вроде даже по индексам с PlayerResourcePlayerTeamData_t совпадает.
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
Протупил мальца, я чет думал, что там этих C_DOTA_PlayerResource на каждый C_DOTAPlayerController.
Но я же одним PlayerResourcePlayerTeamData_t не смогу соотнести этот HeroID с конкретным C_DOTAPlayerController?
Я нашел вектор PlayerResourcePlayerData_t, там есть имя учетки Steam и SteamID, и вроде даже по индексам с PlayerResourcePlayerTeamData_t совпадает.
C_DOTAPlayerController::m_nPlayerID это вроде индекс в массивах в плеерресурсе. в самом PlayerResourcePlayerData_t есть m_nPlayerSlot(вроде +1 прибавляешь и получить индекс сущности контроллера). потести сам
 
Начинающий
Статус
Оффлайн
Регистрация
4 Апр 2024
Сообщения
28
Реакции[?]
1
Поинты[?]
1K
1) да но и не только это(этого недостаточно. как минимум потому что RetrieveMessage ты не контроллируешь когда вызывается. толку от хука если не будет вызываться(надо заставлять вызывать))
2) да. ну сам подумай - сервак же сериализует, он же тебе не будет скидывать свою оперативку которая хер знает какую структуру имеет(мб сервак на линуксе? мб сервак не на интеловской архитектуре? мб еще что-то);(сериализованные данные примерно могут выглядеть как то что ты с Dump в консоли увидел токо не в виде строки естественно) клиент потом это десериализует и у себя делает шмотку в оперативке. можешь попробовать в реальной доте со стимом без ничего просто консоль открыть шмотку одеть и посмотреть че в консоль напишет(а тебе напишет что ты отправил ЭквипРеквест условно и получил ЭквипРеспонс и поверх него еще АпдейтМультипл)
А можешь подсказать из чего делается CMsgSOMultipleObjects? Т.е. что в него сериализавать? Я по нему вообще инфы никакой не вижу, кроме нищих доков каких-то
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
А можешь подсказать из чего делается CMsgSOMultipleObjects? Т.е. что в него сериализавать? Я по нему вообще инфы никакой не вижу, кроме нищих доков каких-то
CMsgSOMultipleObjects содержит новые(objects_added), измененные объекты(objects_modified), и те что надо удалить(objects_removed), в виде множеств SingleObject, каждый из которых имеет эконайди(который говорит нам что же за хуйня перед нами) и сериализованный объект этот эконовский(который айдишнику соответствует)
что-то типо такого
C++:
    void UpdateItems(const std::ranges::range auto& rng)
    {
        if (!std::ranges::empty(rng))
        {
            CMsgSOMultipleObjects upd{};
            *upd.mutable_owner_soid() = Inventory_SOID();
            upd.set_version(0);
            upd.set_service_id(1);

            for (const CSOEconItem* pbitem : rng)
            {
                auto obj = upd.add_objects_modified();
                obj->set_type_id(std::to_underlying(EEconTypeID::k_EEconTypeItem));
                *obj->mutable_object_data() = SerializeProtobufMessage_use_stdstring(*pbitem);
            }

            move_to_pending(GlueFakePBMessage(k_ESOMsg_UpdateMultiple, upd));
        }
    }
C++:
enum class EEconTypeID : int
{
    //from cstrike15
    k_EEconTypePersonaDataPublic = 2,
    k_EEconTypeGameAccountClient = 7,
    k_EEconTypeGameAccount = 8,
    k_EEconTypeEquipInstance = 31,
    k_EEconTypeDefaultEquippedDefinitionInstanceClient = 43,
    k_EEconTypeCoupon = 45,
    k_EEconTypeQuest = 46,

    //xref "Create(CEconItem)"
    k_EEconTypeItem = 1,
    //xref "Create(CEconItemDropRateBonus)"
    k_EEconTypeItemDropRateBonus = 38,
    //xref "Create(CEconItemTournamentPassport)"
    k_EEconTypeItemTournamentPassport = 42,
    //xref "Create(CDOTAGameAccountClient)"
    k_EEconTypeDOTAGameAccountClient = 2002,
    //xref "Create(CDOTAParty)"
    k_EEconTypeParty = 2003,
    //xref "Create(CDotaDynamicLobby)"
    k_EEconTypeDynamicLobby = 2004,
    //xref "Create(CDOTAPartyInvite)"
    k_EEconTypePartyInvite = 2006,
    //xref "Create(CDOTAGameHeroFavorites)"
    k_EEconTypeGameHeroFavorites = 2007,
    //xref "Create(CDOTATournament)"
    k_EEconTypeTournament = 2009,
    //xref "Create(CDOTAPlayerChallenge)"
    k_EEconTypePlayerChallenge = 2010,
    //xref "Create(CDOTALobbyInvite)"
    k_EEconTypeLobbyInvite = 2011,
    //xref "Create(CDOTAGameAccountPlus)"
    k_EEconTypeGameAccountPlus = 2012,
    //xref "Create(CDOTALobby)"
    k_EEconTypeLobby = 2013,
    //xref "Create(CDotaStaticLobby)"
    k_EEconTypeStaticLobby = 2014,
    //xref "Create(CDotaServerDynamicLobby)"
    k_EEconTypeServerDynamicLobby = 2015,
    //xref "Create(CDotaServerStaticLobby)"
    k_EEconTypeServerStaticLobby = 2016,
    //xref "Create(CDOTAChatWheel)"
    k_EEconTypeChatWheel = 2017,
};
...
    /*
    from client.dll vtables
    GCSDK::CProtoBufSharedObject<class CSOEconGameAccountClient, k_EEconTypeGameAccountClient>
    GCSDK::CProtoBufSharedObject<class CSOEconItemDropRateBonus, k_EEconTypeItemDropRateBonus>
    GCSDK::CProtoBufSharedObject<class CSOEconItemTournamentPassport, k_EEconTypeItemTournamentPassport>
    GCSDK::CProtoBufSharedObject<class CSODOTAGameAccountClient, k_EEconTypeDOTAGameAccountClient>
    GCSDK::CProtoBufSharedObject<class CSODOTAParty, k_EEconTypeParty>
    GCSDK::CProtoBufSharedObject<class CSODOTALobby, k_EEconTypeDynamicLobby>
    GCSDK::CProtoBufSharedObject<class CSODOTAPartyInvite, k_EEconTypePartyInvite>
    GCSDK::CProtoBufSharedObject<class CSODOTAGameHeroFavorites, k_EEconTypeGameHeroFavorites>
    GCSDK::CProtoBufSharedObject<class CMsgDOTATournament, k_EEconTypeTournament>
    GCSDK::CProtoBufSharedObject<class CSODOTAPlayerChallenge, k_EEconTypePlayerChallenge>
    GCSDK::CProtoBufSharedObject<class CSODOTALobbyInvite, k_EEconTypeLobbyInvite>
    GCSDK::CProtoBufSharedObject<class CSODOTAGameAccountPlus, k_EEconTypeGameAccountPlus>
    GCSDK::CProtoBufSharedObject<class CSODOTAStaticLobby, k_EEconTypeStaticLobby>
    GCSDK::CProtoBufSharedObject<class CSODOTAServerLobby, k_EEconTypeServerDynamicLobby>
    GCSDK::CProtoBufSharedObject<class CSODOTAServerStaticLobby, k_EEconTypeServerStaticLobby>
    GCSDK::CProtoBufSharedObject<class CSODOTAChatWheel, k_EEconTypeChatWheel>
    */

    so_bind_stuff(EEconTypeID::k_EEconTypeGameAccountClient, CSOEconGameAccountClient);
    so_bind_stuff(EEconTypeID::k_EEconTypeItemDropRateBonus, CSOEconItemDropRateBonus);
    so_bind_stuff(EEconTypeID::k_EEconTypeItemTournamentPassport, CSOEconItemTournamentPassport);
    so_bind_stuff(EEconTypeID::k_EEconTypeDOTAGameAccountClient, CSODOTAGameAccountClient);
    so_bind_stuff(EEconTypeID::k_EEconTypeParty, CSODOTAParty);
    so_bind_stuff(EEconTypeID::k_EEconTypeDynamicLobby, CSODOTALobby);
    so_bind_stuff(EEconTypeID::k_EEconTypePartyInvite, CSODOTAPartyInvite);
    so_bind_stuff(EEconTypeID::k_EEconTypeGameHeroFavorites, CSODOTAGameHeroFavorites);
    so_bind_stuff(EEconTypeID::k_EEconTypeTournament, CMsgDOTATournament);
    so_bind_stuff(EEconTypeID::k_EEconTypePlayerChallenge, CSODOTAPlayerChallenge);
    so_bind_stuff(EEconTypeID::k_EEconTypeLobbyInvite, CSODOTALobbyInvite);
    so_bind_stuff(EEconTypeID::k_EEconTypeGameAccountPlus, CSODOTAGameAccountPlus);
    so_bind_stuff(EEconTypeID::k_EEconTypeStaticLobby, CSODOTAStaticLobby);
    so_bind_stuff(EEconTypeID::k_EEconTypeServerDynamicLobby, CSODOTAServerLobby);
    so_bind_stuff(EEconTypeID::k_EEconTypeServerStaticLobby, CSODOTAServerStaticLobby);
    so_bind_stuff(EEconTypeID::k_EEconTypeChatWheel, CSODOTAChatWheel);

    so_bind_stuff(EEconTypeID::k_EEconTypeItem, CSOEconItem);
 
Сверху Снизу