Гайд Продолжение серии. шема(оффсеты)+локал игрок

Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
вторая часть. читаем
Пожалуйста, авторизуйтесь для просмотра ссылки.

для IDA качаем плагины class informer и function string associate
заходим в IDA берем schemasystem.dylib(
Пожалуйста, авторизуйтесь для просмотра ссылки.
) и параллельно открываем schemasystem.dll. в обоих базах жмякаем Edit->Plugins->Function string associate -> continue (вкладка Edit доступна в нужном нам виде только когда вы сидите в IDA-view или в HEX-view)
ищем в dylibе символ FindTypeScopeForModule

идем по хрефу(наводим на название функции и жмем англ X) видим dq offset блаблабла жмякаем приходим к вмт.

находим функцию FindTypeScopeForModule в нашей вмт и видим что рядом есть функция с хрефом

наша функция на 3 позиции выше чем эта функция с хрефом.
в .dll базе edit->plugins->class informer->ok
ctrl+f CSchemaSystem

открываем. видим там нашу функцию с хрефом отсчитываем 3 вверх и вот наша функция.

чтобы удостовериться декомплим и чекаем код в обоих базах и видим что код почти одинаковый.


дальше ищем в dylibе символ FindDeclaredClass

хреф и идем к вмт, чекаем код функции, видим что по факту просто вызывается другая виртуальная функция этого же класса.

идем к вмт в .dll базе и ищем там функции где такой же простой код.

ну вот собственно мы нашли эту функцию - FindDeclaredClass.

реализуем на практике:
C++:
#include <fstream>
//структуры получены путем наблюдения глазиками в реклассе/дебагере той фигни которую вернула функция FindDeclaredClass, если интересно сделайте у себя там просто CMSG с возвратом этой функции и посмотрите в реклассе/дебагере
struct ClassDescription;

struct SchemaParent {

    ui idk;

    ClassDescription* parent;

};

struct ClassDescription {

    ui idk;//0

    ui classname;//8

    ui modulename;//10

    int sizeofclass;//18

    short memberstoiterate;//1c

    char pad[6];//20

    ui MemberInfo;//28

    ui idk2;//30

    SchemaParent* parent;//38

};


struct SchemaTypeDescription {

    ui idk;

    ui name;

    ui idk2;

};

struct MemberDescription {

    ui name;

    SchemaTypeDescription* schematypeptr;

    int offset;

    int idk;

    ui idk2;

};
typedef void* (*oCreateInterface)(const char*, int);
oCreateInterface pCreateInterface;
ui CreateInterface(const char* szModule, const char* szInterface) {

    pCreateInterface = (oCreateInterface)GetProcAddress(GetModuleHandleA(szModule), "CreateInterface");

    return (ui)pCreateInterface(szInterface, 0);

}

ui SchemaSystem = 0;

void SchemaDumpToFileFull(const char* _module, const char* _class) {

    ui Scope = ((ui(__fastcall*)(ui schemasys, const char* _mod))

        (*(ui*)(*(ui*)(SchemaSystem)+0x68)))(SchemaSystem, _module);

    if (!Scope) { CMSG("No such scope!\n"); return; }

    CMSG("Scope %s\n", n2hex(Scope));

    ui Test1 = ((ui(__fastcall*)(ui scope, const char* _class))

        (*(ui*)(*(ui*)(Scope)+0x10)))(Scope, _class);

    if (!Test1) { CMSG("No such class!\n"); return; }

    std::ofstream myfile;

    std::string filepath = "C:\\Users\\Dell\\Desktop\\DOTA_OFFSETS\\";

    filepath = filepath + _class + ".txt";

    myfile.open(filepath.c_str());

    ClassDescription* a = (ClassDescription*)Test1;

label_1: {}

    myfile << (cc)a->classname << "\n";

    if(!a->memberstoiterate) myfile << "<no members>" << "\n";

    for (ui i = 0; i < a->memberstoiterate; i++) {

        MemberDescription* z = (MemberDescription*)(a->MemberInfo + i * 0x20);

        myfile << "Member " << (const char*)z->name << " type " << (const char*)z->schematypeptr->name << " offset " << (const char*)n2hex(z->offset) << "\n";

        //CMSG("Member %s type %s offset %s\n", z->name, z->schematypeptr->name, n2hex(z->offset));

    }

    if (a->parent) { a = a->parent->parent; goto label_1; }

    myfile.close();

}

...

SchemaSystem = CreateInterface("schemasystem.dll", "SchemaSystem_001");
SchemaDumpToFileFull("client.dll", "C_DOTA_BaseNPC_Hero");//дампит C_DOTA_BaseNPC_Hero вместе со всеми его родителями.
...
учтите что шема описывает только классы client/server/и возможно других бесполезных дллок. так что какую-нибудь CNetworkSystem вы шемой не сдампите, да и в client.dll тоже не все классы можно сдампить. но для получения оффсетов у сущностей достаточно.

локалигрок. локальный C_DOTAPlayer
в доте C_DOTAPlayer это не сама сущность(герой на котором вы играете),а что-то вроде ваших глаз которыми вы видите все что происходит на экране, а герои и ваши призывные юниты это все сущности которые принадлежат вашему C_DOTAPlayer(то есть если ent->m_hOwnerEntity == (CHandle)C_DOTAPlayer то это сущность локального игрока)
CHandle это int состоящий из серийника и индекса сущностей(первые 17 и последние 15 байт соответственно), то есть чтобы получить индекс сущности мы берем CHandle и умножаем побитово на & 0x7FFF.
идем в engine2.dylib. ищем символы типа getlocalplayer, находим жмем хреф и идем в вмт, смотрим на какой позиции функция, идем в engine2.dll и ищем рядом с той же позицией в вмт CEngineClient функции, код которых выглядит точно так же и которые возвращают -1(что есть 0xFFFFFFFF) если что-то вдруг не так. класс. нашли(22).
(функа в dylibe)

(функа в длл)

(как видите код почти 1 в 1)
так же ищем IsInGame. тут применим логику. мы знаем что IsInGame идет сразу после GetMaxClients. идем в GetMaxClients чекаем код. ищем в .dll базе функцию точно с таким же кодом а потом просто находим следующую в вмт и это и будет IsInGame
(getmaxclients dylib)

(getmaxclients dll)

следующая за getmaxclients это isingame


typedef ui(__fastcall* fGLocalPlayerentindex)(ui self, ui ptrtoint, ui zero);//принимает указатель на int вторым параметром и засовывает туда результат.
fGLocalPlayerentindex GLocalPlayer;
typedef unsigned char(__fastcall* IsInGame)(ui);//тут параметр на самом деле чисто формальный, он не используется, можете и без него вызывать.
IsInGame InGame;

дальше встает вопрос: а где логику(ну то есть те вещи которые наш чит будет делать каждый тик) чита-то делать? ну вот тут у вас куча вариантов, хукаем директикс/паинттраверс/что угодно, на этом хуке вы будете одновременно и рисовать и выполнять логику чита. лично я выбираю панораму потому что все равно ее придется использовать если мы собрались делать кулдауны абилок врагов(либо же можете с сервера качать иконки спеллов и рисовать их в директиксе или где-нибудь еще), ибо панорама хорошо обращается с системой ресурсов доты.
C++:
#define VT_METHOD(region, index) (*(ui*)(*(ui*)region + index * 8))
    CEngineClient = CreateInterface("engine2.dll", "Source2EngineToClient001");
    InGame = (IsInGame)VT_METHOD(CEngineClient, 26);
    GLocalPlayer = (fGLocalPlayerentindex)VT_METHOD(CEngineClient, 22);


Panorama = CreateInterface("panorama.dll", "PanoramaUIEngine001");

    Panorama2 = *(ui*)(Panorama + 0x28);
    MEMORY_BASIC_INFORMATION mbi;

    VirtualQuery((LPCVOID)*(ui*)Panorama2, &mbi, sizeof(mbi));

    VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &mbi.Protect);//ставим rwx протект
    oRunFrame = VT_METHOD(Panorama2,6);
    VT_METHOD(Panorama2, 6) = (ui)&hkRunFrame;//хукаем ранфрейм. это функция которая вызывается каждый кадр и рисует панельки.

    VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &mbi.Protect);//возвращаем протект
сделайте себе дамп класса C_DOTAGamerules, поищите в client.dylib симол _g_pGameRules, возьмите какой-нибудь хреф найдите его в .dll и сделайте сигу(есть ниже если что).
GameRules кстати если я не ошибаюсь удаляется по выходу из матча, так что дереференсите при входе в матч а не сразу при инжекте.
так вот, мы в своем ранфрейме будем чекать - если игрок в матче и стадия игры нормальная(ну то есть не стадия пика не стадия загрузки и не какая-нибудь еще другая ненужная нам стадия)(енум увидите ниже в фулл коде) то ищем локал игрока, потом ищем локал тиму и ищем сущности которые принадлежат нашему игроку. ну а потом что-нибудь с ними делаем(в некст туторах).
ну и да забыл сказать не советую в пабе гонять с читами на доту не ломая вак, каким бы говном вак не был, задетектить тот же вмт хук это очень простая задача. если бы вальвы захотели то в ксго и в доте читеров бы просто не было. так что не думайте сражаться с ваком, отрубайте/делайте че угодно я не знаю. иначе скорее всего отлетите. благо способы ломать вак существуют на белом свете так что ищите. а так для тестов создавайте лобби а локацию выбирайте вместо локалхоста стокгольм или где-нибудь еще. в общем на вальвовских серверах. добавляйте ботов и это будет почти 100% как паб
кароче я устал скринить все подряд)) чекайте код если че не поймете спрашивайте; ждите некст части
C++:
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#define ui unsigned long long
#define cc const char*
#pragma once
#include <ctime>
#include <string>
#include <Psapi.h>
#define InRange(x, a, b) (x >= a && x <= b)
#define getBit(x) (InRange((x & (~0x20)), 'A', 'F') ? ((x & (~0x20)) - 'A' + 0xA): (InRange(x, '0', '9') ? x - '0': 0))
#define getByte(x) (getBit(x[0]) << 4 | getBit(x[1]))
#define VT_METHOD(region, index) (*(ui*)(*(ui*)region + index * 8))
#define getEntityIndexclient(ent) (*(signed short*)(*(ui*)(ent + 0x10)+ 0x10) & 0x7FFF)
#define n2hex(x) ((ui)n2hexstr(x).c_str())
ui m_iHealth, m_iMaxHealth, m_flMana, m_flMaxMana, m_iCurrentLevel, m_hAbilities,
m_lifeState, m_hReplicatingOtherHeroModel, m_iTeamNum, m_hOwnerEntity,
m_clrRender, m_iGlowType,
m_glowColorOverride, a_m_iLevel, a_m_iManaCost, a_m_flCooldownLength, a_m_fCooldown,
a_m_bHidden, m_Glow, m_iHealthBarOffset, m_pGameSceneNode, m_vecAbsOrigin, m_fGameTime, m_nGameState;

enum GameState : int
{
    DOTA_GAMERULES_STATE_INIT = 0,
    DOTA_GAMERULES_WAIT_FOR_PLAYERS_TO_LOAD,
    DOTA_GAMERULES_HERO_SELECTION,
    DOTA_GAMERULES_STRATEGY_TIME,
    DOTA_GAMERULES_PREGAME,
    DOTA_GAMERULES_GAME_IN_PROGRESS,
    DOTA_GAMERULES_POSTGAME,
    DOTA_GAMERULES_DISCONNECT,
    DOTA_GAMERULES_TEAM_SHOWCASE,
    DOTA_GAMERULES_CUSTOM_GAME_SETUP,
    DOTA_GAMERULES_WAIT_FOR_MAP_TO_LOAD
};
template <typename I> std::string n2hexstr(I w, size_t hex_len = sizeof(I) << 1) {
    static const char* digits = "0123456789ABCDEF";
    std::string rc(hex_len, '0');
    for (size_t i = 0, j = (hex_len - 1) * 4; i < hex_len; ++i, j -= 4)
        rc[i] = digits[(w >> j) & 0x0f];
    return rc;
}
int vstrcmp(ui a, ui b) {
    return strcmp((cc)a, (cc)b);
}
int vstrcmp(cc a, ui b) {
    return strcmp(a, (cc)b);
}
int vstrcmp(ui a, cc b) {
    return strcmp((cc)a, b);
}
int vstrcmp(cc a, cc b) {
    return strcmp(a, b);
}
typedef void(__fastcall* ConMsg)(cc,ui,ui,ui);
ConMsg CMsg = 0;
void CMSG(cc pure) {

    CMsg(pure, 0, 0, 0);

}

void CMSG(cc format, ui p1) {

    CMsg(format, p1, 0, 0);

}

void CMSG(cc format, ui p1, ui p2) {

    CMsg(format, p1, p2, 0);

}

void CMSG(cc format, ui p1, ui p2, ui p3) {

    CMsg(format, p1, p2, p3);

}
ui FPat(const ui& start_address, const ui& end_address, const char* target_pattern) {
    const char* pattern = target_pattern;

    ui first_match = 0;

    for (ui position = start_address; position < end_address; position++) {
        if (!*pattern)
            return first_match;

        const unsigned char pattern_current = *reinterpret_cast<const unsigned char*>(pattern);
        const unsigned char memory_current = *reinterpret_cast<const unsigned char*>(position);

        if (pattern_current == '\?' || memory_current == getByte(pattern)) {
            if (!first_match)
                first_match = position;

            if (!pattern[2])
                return first_match;

            pattern += pattern_current != '\?' ? 3 : 2;
        }
        else {
            pattern = target_pattern;
            first_match = 0;
        }
    }

    return NULL;
}

ui FPat(const char* module, const char* target_pattern) {
    MODULEINFO module_info = { 0 };

    if (!GetModuleInformation(GetCurrentProcess(), GetModuleHandleA(module), &module_info, sizeof(MODULEINFO)))
        return NULL;

    const ui start_address = ui(module_info.lpBaseOfDll);
    const ui end_address = start_address + module_info.SizeOfImage;

    return FPat(start_address, end_address, target_pattern);
}
inline ui GetAbsoluteAddress(ui instruction_ptr, int offset, int size)
{
    return instruction_ptr + *reinterpret_cast<int32_t*>(instruction_ptr + offset) + size;
}

typedef ui(__fastcall* fNextEnt)(ui, ui);
fNextEnt NextEnt;
ui CGameEntSystem;
ui ent_find_pat;
typedef ui(__fastcall* fGLocalPlayerentindex)(ui self, ui ptrtoint, ui zero);

fGLocalPlayerentindex GLocalPlayer;

typedef unsigned char(__fastcall* IsInGame)(ui);

IsInGame InGame;
typedef void* (*oCreateInterface)(const char*, int);
oCreateInterface pCreateInterface;
ui Panorama, Panorama2;
ui oRunFrame;
ui CreateInterface(const char* szModule, const char* szInterface) {


    pCreateInterface = (oCreateInterface)GetProcAddress(GetModuleHandleA(szModule), "CreateInterface");


    return (ui)pCreateInterface(szInterface, 0);


}
bool IsInMatch = false;
ui CEngineClient = 0;
int LocalPlayerIndex = -1;
ui LocalEnt = 0;
ui LocalPlayer;
unsigned char LocalTeam = 0;
ui framecounter = 0;//он нам нужен чисто ради теста тип каждые 600 кадров выводим в консоль нашу инфу.
bool msged = false;
void ExitedMatch() {
    IsInMatch = false;
    LocalPlayerIndex = -1;
    LocalEnt = 0;
    LocalPlayer = 0;
    LocalTeam = 0;
    framecounter = 0;
    msged = false;
    CMSG("exited match!\n");
}
ui GameRules, GameRulesPtr;
float GameTime() {
    return *(float*)(GameRules + m_fGameTime);
}
int GameState() {
    return *(int*)(GameRules + m_nGameState);
}

void EnteredMatch() {
    IsInMatch = true;
    GameRules = *(ui*)GameRulesPtr;
    CMSG("entered match!\n");

}
bool inited = false;

const char* getBaseClass(ui ent) {
    if (
        *(ui*)(ent + 0x10) == NULL
        ||
        *(ui*)(*(ui*)(ent + 0x10) + 0x8) == NULL
        ) return 0;
    return ***(const char****)(
        *(ui*)(ent + 0x10) + 0x8
        );
}

enum LifeState : char
{
    UnitAlive = 0, KillCam = 1, UnitDead = 2
};
void hkRunFrame() {
    ((void(__fastcall*)(ui))oRunFrame)(Panorama2);
    if (!inited) return;
    if (InGame(CEngineClient)) {
        if (!IsInMatch) EnteredMatch();
    }
    else if (IsInMatch) ExitedMatch();
    if (IsInMatch) {
        if (GameState() == DOTA_GAMERULES_GAME_IN_PROGRESS || GameState() == DOTA_GAMERULES_PREGAME) {
            if (!LocalTeam) {
                if (LocalPlayerIndex == -1) {
                    GLocalPlayer(CEngineClient, (ui)&LocalPlayerIndex, 0);
                    if (LocalPlayerIndex == -1) return;
                }
                if (!LocalPlayer) {
                    ui ent = NextEnt(CGameEntSystem, 0);

                    while (ent) {

                        if (*(ui*)(ent + 0x10))
                        {
                            if (getEntityIndexclient(ent) == LocalPlayerIndex) {
                                LocalPlayer = ent;
                                break;
                            }
                        }
                        *(ui*)(*(ui*)(ent + 0x10) + 0x58) == 0 ? ent = 0 : ent = *(ui*)(*(ui*)(*(ui*)(ent + 0x10) + 0x58));

                    }
                    if (!LocalPlayer) return;
                }
                if (!LocalTeam) {
                    LocalTeam = *(unsigned char*)(LocalPlayer + m_iTeamNum);
                    if (!LocalTeam) return;
                }
            }
            else {
                if (!LocalEnt) {
                    ui ent = NextEnt(CGameEntSystem, 0);

                    while (ent) {

                        if (*(ui*)(ent + 0x10))
                        {
                            if ((*(int*)(ent + m_hOwnerEntity) & 0x7FFF) == LocalPlayerIndex) {
                                if (!vstrcmp(getBaseClass(ent),"C_DOTA_BaseNPC_Hero")) {
                                    LocalEnt = ent;
                                    break;
                                }
                            }
                        }
                        *(ui*)(*(ui*)(ent + 0x10) + 0x58) == 0 ? ent = 0 : ent = *(ui*)(*(ui*)(*(ui*)(ent + 0x10) + 0x58));

                    }
                }
                else {
                    if (!msged) {
                        CMSG("local hero name: %s\n", *(ui*)(*(ui*)(LocalEnt + 0x10) + 0x18));
                        CMSG("local player index: %d\n", LocalPlayerIndex);
                        CMSG("local team: %d\n", LocalTeam);
                        msged = true;
                    }
                    framecounter++;
                    if (framecounter == 600) {
                        framecounter = 0;
                        CMSG("local hero health: %d\n", *(int*)(LocalEnt + m_iHealth));
                        CMSG("local hero level: %d\n", *(int*)(LocalEnt + m_iCurrentLevel));
                        CMSG("local hero lifestate: %d\n", *(char*)(LocalEnt + m_lifeState));//enum LifeState чекаем
                        CMSG("local hero mana: %s\n", (ui)std::to_string(*(float*)(LocalEnt + m_flMana)).c_str());
     
                    }
                }
            }
        }
    }
}
ui SchemaSystem;
template<typename T, ui SIZE>
class CArray {
public:
    T* elms[SIZE] = { 0 };
    ui count = 0;
    void operator=(T* elem) {
        elms[count++] = elem;
    };
    bool operator!() {
        return count == 0;
    }
    explicit operator bool() const
    {
        return count != 0;
    }
    T** begin() {
        return &elms[0];
    }
    T** end() {
        return &elms[count];
    }
    __forceinline T* last() {
        return elms[count - 1];
    }
    __forceinline T* first() {
        return elms[0];
    }
    void RemoveAndShift(T* elm) {
        for (ui i = 0; i < count; i++) {
            if (elms[i] == elm) {
                T* aa = elms[i];
                for (ui j = i; j < count; j++) {
                    if (elms[j + 1]) elms[j] = elms[j + 1];
                    else {
                        elms[j] = 0;
                        break;
                    }
                }
                count--;

            }
        }
    }
    void Destroy() {
        for (ui i = 0; i < count; i++) {
            delete elms[i];
        }
    }
};
struct ClassDescription;
struct SchemaParent {
    ui idk;
    ClassDescription* parent;
};
struct ClassDescription {
    ui idk;//0
    ui classname;//8
    ui modulename;//10
    int sizeofclass;//18
    short memberstoiterate;//1c
    char pad[6];//20
    ui MemberInfo;//28
    ui idk2;//30
    SchemaParent* parent;//38
};

struct SchemaTypeDescription {
    ui idk;
    ui name;
    ui idk2;
};
struct MemberDescription {
    ui name;
    SchemaTypeDescription* schematypeptr;
    int offset;
    int idk;
    ui idk2;
};
class schemanetvar {
public:
    ui classname;
    ui name;
    ui _typename;
    int offset;
    schemanetvar(ui a, ui b, ui c, ui d) {
        classname = a;
        name = b;
        _typename = c;
        offset = d;
    }
};
class SchemaNetvarCollection {
public:
        CArray<schemanetvar, 1000> Netvars;
    void Add(cc _class, cc _module) {
        ui Scope = ((ui(__fastcall*)(ui schemasys, const char* _mod))
            (*(ui*)(*(ui*)(SchemaSystem)+0x68)))(SchemaSystem, _module);
        if (!Scope) { CMSG("No such scope %s!\n", (ui)_module); return; }
        ui Class = ((ui(__fastcall*)(ui scope, const char* _class))
            (*(ui*)(*(ui*)(Scope)+0x10)))(Scope, _class);
        if (!Class) { CMSG("No such class %s!\n", (ui)_class); return; }
        ClassDescription* a = (ClassDescription*)Class;
        for (ui i = 0; i < a->memberstoiterate; i++) {
            MemberDescription* z = (MemberDescription*)(a->MemberInfo + i * 0x20);
            Netvars = new schemanetvar(a->classname, z->name, z->schematypeptr->name, (ui)z->offset);
        }
    }
    schemanetvar* Get(ui name) {
        for (schemanetvar* netvar : Netvars) {
            if (!vstrcmp(netvar->name, name)) return netvar;
        }
        CMSG("no such netvar found in manager: %s\n", name);
    }
    schemanetvar* Get(ui _class, ui name) {
        for (schemanetvar* netvar : Netvars) {
            if (!vstrcmp(netvar->name, name) && !vstrcmp(netvar->classname, _class)) return netvar;
        }
        CMSG("no such netvar found in manager: %s\n", name);

    }
};
SchemaNetvarCollection* Netvars = 0;

void OnInject() {
    CMsg = (ConMsg)GetProcAddress(GetModuleHandleA("tier0.dll"), "Msg");

    ent_find_pat = FPat("client.dll", "48 83 EC 28 8B 02 83 F8 02 7D 12 48 8D 0D ? ? ? ? 48 83 C4 28 48 FF 25 ? ? ? ? 48 89 6C");
    if (ent_find_pat == 0) {
        CMSG("ent_find_pat is NULL :(");
        return;
    }
    NextEnt = (fNextEnt)GetAbsoluteAddress(ent_find_pat + 0x5a, 1, 5);
    CGameEntSystem = *(ui*)(GetAbsoluteAddress(ent_find_pat + 0x51, 3, 7));

    ui GameRulesXREF = FPat("client.dll", "48 8b 05 ? ? ? ? 48 85 c0 75 ? 0f 57 c0 c3 f3 0f 10 80 ? ? ? ? c3");
    if (!GameRulesXREF) { CMSG("pattern GameRulesXREF not found\n"); return; }

    GameRulesPtr = GetAbsoluteAddress(GameRulesXREF, 3, 7);

    CEngineClient = CreateInterface("engine2.dll", "Source2EngineToClient001");
    InGame = (IsInGame)VT_METHOD(CEngineClient, 26);
    GLocalPlayer = (fGLocalPlayerentindex)VT_METHOD(CEngineClient, 22);


    SchemaSystem = CreateInterface("schemasystem.dll", "SchemaSystem_001");
    Netvars = new SchemaNetvarCollection;
    Netvars->Add("C_BaseEntity", "client.dll");
    Netvars->Add("CGameSceneNode", "client.dll");
    Netvars->Add("C_DOTA_BaseNPC", "client.dll");
    Netvars->Add("C_DOTA_BaseNPC_Hero", "client.dll");
    Netvars->Add("C_DOTABaseAbility", "client.dll");
    Netvars->Add("C_DOTAGamerules", "client.dll");
    Netvars->Add("C_BaseModelEntity", "client.dll");
    Netvars->Add("CGlowProperty", "client.dll");
    m_iHealth = Netvars->Get((ui)"m_iHealth")->offset;
    m_iMaxHealth = Netvars->Get((ui)"m_iMaxHealth")->offset;
    m_flMana = Netvars->Get((ui)"m_flMana")->offset;
    m_flMaxMana = Netvars->Get((ui)"m_flMaxMana")->offset;
    m_iCurrentLevel = Netvars->Get((ui)"m_iCurrentLevel")->offset;
    m_hAbilities = Netvars->Get((ui)"m_hAbilities")->offset;
    m_lifeState = Netvars->Get((ui)"m_lifeState")->offset;
    m_hReplicatingOtherHeroModel = Netvars->Get((ui)"m_hReplicatingOtherHeroModel")->offset;
    m_iTeamNum = Netvars->Get((ui)"m_iTeamNum")->offset;
    m_hOwnerEntity = Netvars->Get((ui)"m_hOwnerEntity")->offset;
    m_clrRender = Netvars->Get((ui)"m_clrRender")->offset;
    m_Glow = Netvars->Get((ui)"m_Glow")->offset;
    m_iHealthBarOffset = Netvars->Get((ui)"m_iHealthBarOffset")->offset;
    m_iGlowType = Netvars->Get((ui)"m_iGlowType")->offset;
    m_glowColorOverride = Netvars->Get((ui)"m_glowColorOverride")->offset;
    a_m_iLevel = Netvars->Get((ui)"m_iLevel")->offset;
    a_m_iManaCost = Netvars->Get((ui)"m_iManaCost")->offset;
    a_m_flCooldownLength = Netvars->Get((ui)"m_flCooldownLength")->offset;
    a_m_fCooldown = Netvars->Get((ui)"m_fCooldown")->offset;
    a_m_flCooldownLength = Netvars->Get((ui)"m_flCooldownLength")->offset;
    a_m_bHidden = Netvars->Get((ui)"m_bHidden")->offset;
    m_pGameSceneNode = Netvars->Get((ui)"m_pGameSceneNode")->offset;
    m_vecAbsOrigin = Netvars->Get((ui)"m_vecAbsOrigin")->offset;
    m_fGameTime = Netvars->Get((ui)"m_fGameTime")->offset;
    m_nGameState = Netvars->Get((ui)"m_nGameState")->offset;

    Panorama = CreateInterface("panorama.dll", "PanoramaUIEngine001");

    Panorama2 = *(ui*)(Panorama + 0x28);
    MEMORY_BASIC_INFORMATION mbi;

    VirtualQuery((LPCVOID)*(ui*)Panorama2, &mbi, sizeof(mbi));

    VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &mbi.Protect);
    oRunFrame = VT_METHOD(Panorama2,6);
    VT_METHOD(Panorama2, 6) = (ui)&hkRunFrame;

    VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &mbi.Protect);

    CMSG("injection completed successfuly at %s, runframe at %s !\n", (ui)std::to_string(std::time(0)).c_str(), n2hex((ui)&hkRunFrame));
    inited = true;
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    if(ul_reason_for_call == 1)  CreateThread(0,0,(LPTHREAD_START_ROUTINE)OnInject,0,0,0);
    return TRUE;
}
ссылка на актуальный(01:39:10 07 Jun 2024) дамп шемы и прочих плюх:
Пожалуйста, авторизуйтесь для просмотра ссылки.
дамп шемы и ртти с июня 2015 до мая 2024(в ~3хмесячных инкрементах)
Пожалуйста, авторизуйтесь для просмотра ссылки.
дерьмодампер шемы и ртти оффлайн POC качества(на доту работает на ксго вроде тоже)
shitcode:
Пожалуйста, авторизуйтесь для просмотра ссылки.
 
Последнее редактирование:
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
забыл кстати упомянуть, что такое панорама. это обертка на директикс, на которой написан весь интерфейс в доте(кроме консоли которая на вгуи(другая обертка на директикс)). подробнее рассмотрим ее в некст туторах когда будем рисовать на экране.
 
Начинающий
Статус
Оффлайн
Регистрация
30 Мар 2020
Сообщения
324
Реакции[?]
24
Поинты[?]
12K
Какой инжектор ты бы порекомендовал использовать(Если впадлу делать свой)?
 
Начинающий
Статус
Оффлайн
Регистрация
30 Мар 2020
Сообщения
324
Реакции[?]
24
Поинты[?]
12K
Сегодня скомпилировал значит весь код в Release x64. Только что зашел в доту и заинжектил с помощью "extreme Injector v3". В консоли появилась надпись Successfully injected at Какой-то адресс. Создал Лобби ALL PICK, Штокхольм, Боты пассивные. Выбрал героя, появился и через пару секунд Вылет. Не знаешь почему?
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
Сегодня скомпилировал значит весь код в Release x64. Только что зашел в доту и заинжектил с помощью "extreme Injector v3". В консоли появилась надпись Successfully injected at Какой-то адресс. Создал Лобби ALL PICK, Штокхольм, Боты пассивные. Выбрал героя, появился и через пару секунд Вылет. Не знаешь почему?
x64dbg в руки и дебажишь. причин может быть миллиард
 
Начинающий
Статус
Оффлайн
Регистрация
15 Дек 2018
Сообщения
146
Реакции[?]
9
Поинты[?]
0
Привет, не понимаю как вызываются виртуальные функции, где можно почитать инфу? Недавно написал свою прогу с классом имеющим виртуальные методы и начал бегать в реклассе по нему, получил указатель на объект класса, перешел на него в реклассе, дальше перешел по адресу который в первых восьми байтах класса и дальше опять так же перешел и получил виртуальную таблицу, но как вызывать функции из нее, я не знаю
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
Привет, не понимаю как вызываются виртуальные функции, где можно почитать инфу? Недавно написал свою прогу с классом имеющим виртуальные методы и начал бегать в реклассе по нему, получил указатель на объект класса, перешел на него в реклассе, дальше перешел по адресу который в первых восьми байтах класса и дальше опять так же перешел и получил виртуальную таблицу, но как вызывать функции из нее, я не знаю
получи указатель на класс, считай отуда 8 байт, получишь вмт.
находишь индекс нужной тебе функции в какой-нибудь ида или где-нибудь еще, ну в общем ищешь саму функцию которую хочешь вызвать в этой вмт.
дальше считываешь из ячейки (vmt+index*8)(индекс с 0 начинается) 8 байт. дальше из этих 8 байт делаешь указатель на функцию. то есть говоришь компилятору
что это не просто какой-то мусор, а это нужно вызвать функцию по этому адресу.
псевдо-асм как вызываются вмт функции в оригинальной программе(ну той же доте например):
mov rcx, [MySuperClass]//Class* MySuperClass допустим
mov <какой-нибудь регистр который можно засрать>, [rcx]// vmt
mov <куда-нибудь в соответствии с конвенцией вызова>, <какие-то параметры для вызова функции>
call [<регистр из инструкции которая загрузила вмт в регистр>+index*8]//индекс заранее еще в компиляторе умножается на 8, то есть не 2*8 а 16 сразу будет в инструкции
тебе нужно сделать так чтобы твой компилятор собрал такой же код.
C++:
#include <iostream>
#pragma once
#define cc const char*
#define u64 unsigned long long
class Test {
public:
    virtual void print1(int a) { printf("print1 %d\n", a); }
    virtual void print2(int a) { printf("print2 %d\n", a); }
    virtual void print3(int a) { printf("print3 %d\n", a); }
    virtual void print4() { printf("print4 %d\n", I); }
    int I = 1;
};
template<typename... ArgTypes> auto __fastcall FastCall(u64 Funcpointer, ArgTypes... ArgVals) {
    return (
        ((u64(__fastcall*)(ArgTypes...)) Funcpointer)
        (ArgVals...)
        );
}
int main()
{
    //все это на х64
    Test a;
    Test* b = &a;//&a это указатель на класс, место в памяти где он хранится(ну точнее где хранятся его данные, то есть его вмт и члены)
    u64 vmt = *(u64*)b;//считываю 8 байт с ячейки где хранится класс и получаю вмт
    u64 vfunc1 = *(u64*)(vmt + 0 * 8);//нулевая по индексу(первая по счету) функция в вмт, print1
    u64 vfunc2 = *(u64*)(vmt + 1 * 8);//первая по индексу(вторая по счету) функция в вмт, print2
    u64 vfunc3 = *(u64*)(vmt + 2 * 8);//вторая по индексу(третья по счету) функция в вмт, print3
    auto f1 = (void(__fastcall*)(void*,int))vfunc1;//говорю указателю, что
    //это указатель на функцию конвенции __fastcall, но на самом деле это не совсем так
    //виртуальная функция это член класса, поэтому на самом деле она __thiscall.
    //однако на х64 __fastcall практически равен __thiscall
    //в том смысле что __thiscall это __fastcall где rcx = this, то есть первый параметр это
    //указатель на класс. то есть я могу забить на тот факт что это __thiscall и просто
    //сказать компилятору что это __fastcall и передать указатель на класс первым параметром.
    //также говорю компилятору что возврат void, то есть регистр возврата(rax) можно засирать
    //после данного вызова и ничего я с ним делать не собираюсь так как либо функция возвращает
    //какую-то дичь бесполезную(например функция с возвратом типа void,
    //она засирает в своем коде регистр rax потому что знает что она не должна ничего возвращать),
    //либо возврат просто мне не нужен.
    //если вдруг ты еще не понял, суть конвенции __thiscall в том, чтобы в регистре rcx
    //был указатель на класс, то есть чтобы функция __thiscall могла взаимодействовать с
    //членами класса. если указателя на класс не будет то откуда ей брать члены?
    //в нашем случае с print1, print2, print3 можно в rcx передать 0 спокойно потому что
    //там члены класса никак не используются.
    f1(b,5);//вызываю с параметрами Test*(rcx) и 5(rdx)
    f1(0, 5);//не крашнет потому что rcx не используется, то есть функция не взаимодействует
    //с членами класса. однако стоит сохранять последовательность, то есть даже если rcx
    //не используется, остальные параметры все равно должны передаваться начиная с rdx ибо
    //это __thiscall. естественно если rcx используется то передавая 0 можешь ожидать краш.
    //так что чтобы не париться всегда передавай указатель на класс в rcx - если функция захочет,
    //она его задействует, если не захочет - ничего плохого не произойдет
    ((void(__fastcall*)(void*,int))vfunc1)(b,6);//альтернативно в одну строчку
    ((void(__fastcall*)(void*,int))vfunc1)(0,6);//альтернативно в одну строчку, не крашит в данном случае
    FastCall(vfunc3, b,7);//альтернативно темплейтом - проще и красивее
    FastCall(vfunc3, 0,7);//альтернативно темплейтом - проще и красивее, не крашит в данном случае
    u64 vfunc4 = *(u64*)(vmt + 3 * 8);
    FastCall(vfunc4, b);//все норм
    FastCall(vfunc4, 0);//краш потому что rcx используется
}
Пожалуйста, авторизуйтесь для просмотра ссылки.
 
Последнее редактирование:
Начинающий
Статус
Оффлайн
Регистрация
15 Дек 2018
Сообщения
146
Реакции[?]
9
Поинты[?]
0
получи указатель на класс, считай отуда 8 байт, получишь вмт.
находишь индекс нужной тебе функции в какой-нибудь ида или где-нибудь еще, ну в общем ищешь саму функцию которую хочешь вызвать в этой вмт.
дальше считываешь из ячейки (vmt+index*8)(индекс с 0 начинается) 8 байт. дальше из этих 8 байт делаешь указатель на функцию. то есть говоришь компилятору
что это не просто какой-то мусор, а это нужно вызвать функцию по этому адресу.
псевдо-асм как вызываются вмт функции в оригинальной программе(ну той же доте например):
mov rcx, [MySuperClass]//Class* MySuperClass допустим
mov <какой-нибудь регистр который можно засрать>, [rcx]// vmt
mov <куда-нибудь в соответствии с конвенцией вызова>, <какие-то параметры для вызова функции>
call [<регистр из инструкции которая загрузила вмт в регистр>+index*8]//индекс заранее еще в компиляторе умножается на 8, то есть не 2*8 а 16 сразу будет в инструкции
тебе нужно сделать так чтобы твой компилятор собрал такой же код.
C++:
#include <iostream>
#pragma once
#define cc const char*
#define u64 unsigned long long
class Test {
public:
    virtual void print1(int a) { printf("print1 %d\n", a); }
    virtual void print2(int a) { printf("print2 %d\n", a); }
    virtual void print3(int a) { printf("print3 %d\n", a); }
    virtual void print4() { printf("print4 %d\n", I); }
    int I = 1;
};
template<typename... ArgTypes> auto __fastcall FastCall(u64 Funcpointer, ArgTypes... ArgVals) {
    return (
        ((u64(__fastcall*)(ArgTypes...)) Funcpointer)
        (ArgVals...)
        );
}
int main()
{
    //все это на х64
    Test a;
    Test* b = &a;//&a это указатель на класс, место в памяти где он хранится(ну точнее где хранятся его данные, то есть его вмт и члены)
    u64 vmt = *(u64*)b;//считываю 8 байт с ячейки где хранится класс и получаю вмт
    u64 vfunc1 = *(u64*)(vmt + 0 * 8);//нулевая по индексу(первая по счету) функция в вмт, print1
    u64 vfunc2 = *(u64*)(vmt + 1 * 8);//первая по индексу(вторая по счету) функция в вмт, print2
    u64 vfunc3 = *(u64*)(vmt + 2 * 8);//вторая по индексу(третья по счету) функция в вмт, print3
    auto f1 = (void(__fastcall*)(void*,int))vfunc1;//говорю указателю, что
    //это указатель на функцию конвенции __fastcall, но на самом деле это не совсем так
    //виртуальная функция это член класса, поэтому на самом деле она __thiscall.
    //однако на х64 __fastcall практически равен __thiscall
    //в том смысле что __thiscall это __fastcall где rcx = this, то есть первый параметр это
    //указатель на класс. то есть я могу забить на тот факт что это __thiscall и просто
    //сказать компилятору что это __fastcall и передать указатель на класс первым параметром.
    //также говорю компилятору что возврат void, то есть регистр возврата(rax) можно засирать
    //после данного вызова и ничего я с ним делать не собираюсь так как либо функция возвращает
    //какую-то дичь бесполезную(например функция с возвратом типа void,
    //она засирает в своем коде регистр rax потому что знает что она не должна ничего возвращать),
    //либо возврат просто мне не нужен.
    //если вдруг ты еще не понял, суть конвенции __thiscall в том, чтобы в регистре rcx
    //был указатель на класс, то есть чтобы функция __thiscall могла взаимодействовать с
    //членами класса. если указателя на класс не будет то откуда ей брать члены?
    //в нашем случае с print1, print2, print3 можно в rcx передать 0 спокойно потому что
    //там члены класса никак не используются.
    f1(b,5);//вызываю с параметрами Test*(rcx) и 5(rdx)
    f1(0, 5);//не крашнет потому что rcx не используется, то есть функция не взаимодействует
    //с членами класса. однако стоит сохранять последовательность, то есть даже если rcx
    //не используется, остальные параметры все равно должны передаваться начиная с rdx ибо
    //это __thiscall. естественно если rcx используется то передавая 0 можешь ожидать краш.
    //так что чтобы не париться всегда передавай указатель на класс в rcx - если функция захочет,
    //она его задействует, если не захочет - ничего плохого не произойдет
    ((void(__fastcall*)(void*,int))vfunc1)(b,6);//альтернативно в одну строчку
    ((void(__fastcall*)(void*,int))vfunc1)(0,6);//альтернативно в одну строчку, не крашит в данном случае
    FastCall(vfunc3, b,7);//альтернативно темплейтом - проще и красивее
    FastCall(vfunc3, 0,7);//альтернативно темплейтом - проще и красивее, не крашит в данном случае
    u64 vfunc4 = *(u64*)(vmt + 3 * 8);
    FastCall(vfunc4, b);//все норм
    FastCall(vfunc4, 0);//краш потому что rcx используется
}
Пожалуйста, авторизуйтесь для просмотра ссылки.
Спасибо тебе, это я понял, а зачем нужна функция CreateInterface? Как я понял она из доты
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
Спасибо тебе, это я понял, а зачем нужна функция CreateInterface? Как я понял она из доты
для получения указателей на классы доты. ну то есть тебе не нужно искать хреф на класс потом делать сигу и по сиге находить указатель на класс, потому что добрые вальвы облегчили тебе работу. ничего искать не надо, говоришь доте дай мне указатель на класс и она тебе его дает. ну естественно не все классы можно так получить. только те которые вальвы так обернули(я так понимаю они это сделали чтобы один модуль мог получить интерфейс из другого модуля, типо для удобства нежели просто захардкодить оффсет из другого модуля)
 
Начинающий
Статус
Оффлайн
Регистрация
15 Дек 2018
Сообщения
146
Реакции[?]
9
Поинты[?]
0
для получения указателей на классы доты. ну то есть тебе не нужно искать хреф на класс потом делать сигу и по сиге находить указатель на класс, потому что добрые вальвы облегчили тебе работу. ничего искать не надо, говоришь доте дай мне указатель на класс и она тебе его дает. ну естественно не все классы можно так получить. только те которые вальвы так обернули(я так понимаю они это сделали чтобы один модуль мог получить интерфейс из другого модуля, типо для удобства нежели просто захардкодить оффсет из другого модуля)
Хорошо, спасибо! Вот еще вопрос ( надеюсь я тебя еще не зае*ал ), я нашел в реклассе адрес на вмт в своей программе, тоесть u64 VMT = 0x7FF6B9B733B0;
Как мне сказать компилятору что это указатель?
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
(u64*)VMT;//указатель
* это служебный символ либо для объявления указателя если идет после типа (u64* сначала тип потом звездочка) либо для дереференса указателя(чтение по адресу указателя sizeof(type) байт и представление этих байт в виде type)
в случае дереференса звездочка ставится перед переменной и тип переменной должен быть указателем

u64 MyPtr = *(u64*)VMT это знчит из переменной VMT сделать указатель на u64(ну то есть ты говоришь компилятору что если ты собрался считывать по этому адресу то считывать нужно ровно восемь байт и на знак числа(плюс минус) тебе пофигу) а потом считать с этого указателя. указатель это тот же самый u64 (на x64) поэтому можешь считывать спокойно эти восемь байт а потом когда надо можешь это представлять как что угодно(допустим не просто u64 а указатель на класс DotaClass (DotaClass*)MyPtr)
 
Начинающий
Статус
Оффлайн
Регистрация
15 Дек 2018
Сообщения
146
Реакции[?]
9
Поинты[?]
0
(u64*)VMT;//указатель
* это служебный символ либо для объявления указателя если идет после типа (u64* сначала тип потом звездочка) либо для дереференса указателя(чтение по адресу указателя sizeof(type) байт и представление этих байт в виде type)
в случае дереференса звездочка ставится перед переменной и тип переменной должен быть указателем

u64 MyPtr = *(u64*)VMT это знчит из переменной VMT сделать указатель на u64(ну то есть ты говоришь компилятору что если ты собрался считывать по этому адресу то считывать нужно ровно восемь байт и на знак числа(плюс минус) тебе пофигу) а потом считать с этого указателя. указатель это тот же самый u64 (на x64) поэтому можешь считывать спокойно эти восемь байт а потом когда надо можешь это представлять как что угодно(допустим не просто u64 а указатель на класс DotaClass (DotaClass*)MyPtr)
Спасибо!
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
кстати указатель я предпочитаю объявлять как простое число потому, что к традиционному указателю со звездочкой нельзя адекватно прибавлять/вычитать.
int* abc = xxx;
printf("%d",*(abc + 4))
такой код(условно) лично у меня в визуалке иногда собирается в какуюто кашу. вместо прибавления 4 байт и считывания оттуда 4 байт он сделает какую нибудь хрень, например забудет прибавить и так считает, либо прибавит offset*sizeof(type). у тебя может норм скомпилить, а у меня компилит кашу, и у кого нибудь еще может тоже кашу собрать. поэтому в целях совместимости я использую указатель как число, тогда прибавление работает нормально, а потом просто делаю из числа указатель.
u64 abc = xxx;
printf("%d",*(int*)(abc+4))
в общем прибавляя или вычитая из традиционного указателя со звездочкой будь готов что компилятор тебя не поймет и соберет дичь. а может и норм собрать. поэтому указатель в коде должен быть простым числом, и становиться реальным указателем он должен только когда ты планируешь считывать с него.
 
Начинающий
Статус
Оффлайн
Регистрация
15 Дек 2018
Сообщения
146
Реакции[?]
9
Поинты[?]
0
кстати указатель я предпочитаю объявлять как простое число потому, что к традиционному указателю со звездочкой нельзя адекватно прибавлять/вычитать.
int* abc = xxx;
printf("%d",*(abc + 4))
такой код(условно) лично у меня в визуалке иногда собирается в какуюто кашу. вместо прибавления 4 байт и считывания оттуда 4 байт он сделает какую нибудь хрень, например забудет прибавить и так считает, либо прибавит offset*sizeof(type). у тебя может норм скомпилить, а у меня компилит кашу, и у кого нибудь еще может тоже кашу собрать. поэтому в целях совместимости я использую указатель как число, тогда прибавление работает нормально, а потом просто делаю из числа указатель.
u64 abc = xxx;
printf("%d",*(int*)(abc+4))
в общем прибавляя или вычитая из традиционного указателя со звездочкой будь готов что компилятор тебя не поймет и соберет дичь. а может и норм собрать. поэтому указатель в коде должен быть простым числом, и становиться реальным указателем он должен только когда ты планируешь считывать с него.
Хорошо, попробовал такой конструкцией вызвать FindTypeScopeForModule

u64 VMT = *(u64*)SchemaSystem;
u64 FindTypeScopeForModule = *(u64*)(VMT + 68 * 8);

auto MyScope = (u64(__fastcall*)(u64 _schema, ch _module))FindTypeScopeForModule;
u64 MyScopeCalled = MyScope(SchemaSystem, "SchemaSystem.dll");

но при попытке инжекта получил краш, с чем это связано?
пытался вывести чере CMSG("MyScopeCalled %s\n", n2hex(MyScopeCalled)); чтобы сверить идентично ли он возвращает скоуп с твоим кодом
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
Хорошо, попробовал такой конструкцией вызвать FindTypeScopeForModule

u64 VMT = *(u64*)SchemaSystem;
u64 FindTypeScopeForModule = *(u64*)(VMT + 68 * 8);

auto MyScope = (u64(__fastcall*)(u64 _schema, ch _module))FindTypeScopeForModule;
u64 MyScopeCalled = MyScope(SchemaSystem, "SchemaSystem.dll");

но при попытке инжекта получил краш, с чем это связано?
пытался вывести чере CMSG("MyScopeCalled %s\n", n2hex(MyScopeCalled)); чтобы сверить идентично ли он возвращает скоуп с твоим кодом
ты не переборщил 68 индекс вызывать?))) 0x68 в моем коде это уже и есть оффсет от вмт, это не индекс. это произведение индекса на восемь. там 13 индекс, то есть 13*8, то есть 0x68, то есть десятичная система 104, а у тебя 68*8, то есть 68 индекс, то есть супер пупер дофига ты улетел и вызываешь не ту функцию. просто я в ида сразу оффсет посчитал 0x68 а потом на 8 поделить и написать в коде 13*8 забыл, то есть вмт условно по адресу 1000 находится, а нужная мне функция находится на 1068, я просто беру вмт и прибавляю к ней 0x68(а надо бы для понятности было написать 13*8)
 
Последнее редактирование:
Начинающий
Статус
Оффлайн
Регистрация
15 Дек 2018
Сообщения
146
Реакции[?]
9
Поинты[?]
0
ты не переборщил 68 индекс вызывать?))) 0x68 в моем коде это уже и есть оффсет от вмт, это не индекс. это произведение индекса на восемь. там 13 индекс, то есть 13*8, то есть 0x68, то есть десятичная система 104, а у тебя 68*8, то есть 68 индекс, то есть супер пупер дофига ты улетел и вызываешь не ту функцию. просто я в ида сразу оффсет посчитал 0x68 а потом на 8 поделить и написать в коде 13*8 забыл, то есть вмт условно по адресу 1000 находится, а нужная мне функция находится на 1068, я просто беру вмт и прибавляю к ней 0x68(а надо бы для понятности было написать 13*8)
Спасибо!
 
Последнее редактирование:
Начинающий
Статус
Оффлайн
Регистрация
15 Дек 2018
Сообщения
146
Реакции[?]
9
Поинты[?]
0
ты не переборщил 68 индекс вызывать?))) 0x68 в моем коде это уже и есть оффсет от вмт, это не индекс. это произведение индекса на восемь. там 13 индекс, то есть 13*8, то есть 0x68, то есть десятичная система 104, а у тебя 68*8, то есть 68 индекс, то есть супер пупер дофига ты улетел и вызываешь не ту функцию. просто я в ида сразу оффсет посчитал 0x68 а потом на 8 поделить и написать в коде 13*8 забыл, то есть вмт условно по адресу 1000 находится, а нужная мне функция находится на 1068, я просто беру вмт и прибавляю к ней 0x68(а надо бы для понятности было написать 13*8)
Спасибо! Теперь мне удалось вызвать ее!!!
 
Начинающий
Статус
Оффлайн
Регистрация
12 Сен 2020
Сообщения
42
Реакции[?]
3
Поинты[?]
0
а как найти название класса для вызова функции declaredClass у schemasystemtypescope (как у схемы - "sсhemasystem_001")?
это оно CSchemaSystemTypeScope::Type_DeclaredClass?.
 
Последнее редактирование:
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
а как найти название класса для вызова функции declaredClass у schemasystemtypescope (как у схемы - "sсhemasystem_001")?
это оно CSchemaSystemTypeScope::Type_DeclaredClass?.
не уверен что тебя понял, так что если ответ не удовлетворяет то перефразируй
schemasystem_001 это название интерфейса,а не класса. эта строка имеет значение только для функции CreateInterface и нигде больше. CSchemaSystemTypeScope::FindDeclaredClass принимает имя класса в том виде в каком оно было зарегистрировано в Schema, а зарегистрировано оно было в таком виде в каком оно и есть в сурс файлах вальве(class My_Class), а какое оно в сурс файлах вальве можно узнать через RTTI(IDA->Class informer). так что ты находишь там какой-нибудь класс который тебе нужен(C_BaseEntity), вбиваешь его в шему(FindDeclaredClass("C_BaseEntity")) и если тебе вернуло 0 то значит такой класс не зарегистрирован, а если вернуло не 0 то обрабатываешь.
хотя раз praydog сделал генератор сдк, то очевидно что он смог механически получить все зарегистрированные классы. почитай там сурсы у него. если не ошибаюсь то там вроде в самом CSchemaSystemTypeScope на каком-то оффсете просто массив лежит с зареганными классами. но толку мало от этого Source2Gen потому что в шеме половина описанных классов - мусор, а остальная половина хоть и полезная но ее очень мало. поэтому я просто ручками ввожу ей несколько классов и не парюсь.
 
Последнее редактирование:
Начинающий
Статус
Оффлайн
Регистрация
12 Сен 2020
Сообщения
42
Реакции[?]
3
Поинты[?]
0
//структуры получены путем наблюдения глазиками в реклассе/дебагере той фигни которую вернула функция FindDeclaredClass, если интересно сделайте у себя там просто CMSG с возвратом этой функции и посмотрите в реклассе/дебагере
хочу понять как эти структуры получились, пытаюсь вызвать функцию FindDeclaredClass, но не получается:
SchemaSystemTypeScope = CreateInterface("schemasystem.dll", " CSchemaSystemTypeScope::Type_DeclaredClass");
ui VMT = *(ui*)SchemaSystemTypeScope;
ui DeclaredClass = *(ui*)(VMT + 2 * 8);
auto MyDeclaredClass = (ui(__fastcall*)(ui _schema, cc _module))DeclaredClass;
ui MyFindDeclaredClass = MyDeclaredClass(SchemaSystemTypeScope , "SchemaSystem.dll");
CMSG("MyFinDeclaredClass %s\n", n2hex(MyFindDeclaredClass));
 
Последнее редактирование:
Сверху Снизу