Гайд External ConVars

https://qweme.dev
Пользователь
Статус
Оффлайн
Регистрация
25 Май 2022
Сообщения
165
Реакции[?]
87
Поинты[?]
21K
В связи с большим спросом, как и обещал пилю гайд по конварам

Для начала нам нужно найти хреф на конвар (я делаю это все в x64dbg)
1. Нажимаем ctrl+g и пишем client.entry
2. Пкм по тому что нашли (Search for > Current module > String references)
3. Ждем пока загрузит хрефы и вписываем dota_use_particle_fow (конвар который хотим менять через наш код, можно и любой другой)
4. C хрефа на название квара ты находишь функцию которая вызывает конструктор, в rcx прямо перед вызовом самого конструктора будет засунут квар ибо конструктор это __thiscall (не знаю как понятнее обьснить, Liberalist)
1660613591923.png

Дальше смотрим что читает значение (7FFC60562990 + 0x58, 0x58 оффсет на котором лежит значение квара) нашего конвара (F5 в CE)
1660614315916.png

Код:
7FFC5DA19514 - and rbp,-40
7FFC5DA19518 - mov rax,[7FFC605629C8] <<< Указатель на квар
7FFC5DA1951F - cmp dword ptr [rax+58],00
7FFC5DA19523 - mov rax,[7FFC60562B08]
7FFC5DA1952A - setne byte ptr [7FFC6074C718]
Бинго, осталось сделать сигу на 7FFC605629C8 (48 8B ? ? ? ? ? 83 78 58 ? 48 8B ? ? ? ? ? 0F 95)

Теперь в коде нам нужно засигсканить нашу хуйню, найти адрес и перезаписать

Кто то там пиздел в топиках, что питон не может сигсканить, ну так что, докажем обратное? xd
1660615081781.png

В питоне уже есть готовый модуль для работы с памятью в винде (pymem), и не поверите, там даже есть готовый патерн сканер, вау

Я же написал небольшую обертку над pymem (унаследовал класс и дописал свои функи)

Python:
class QwemeMemory(pymem.Pymem):
    def getAbsAddr(self, ptr: int, offset: int, size: int) -> int:
        return ptr + self.read_int(ptr + offset) + size
       
    def sigScan(self, module_name, pattern) -> int:
        module = pymem.process.module_from_name(self.process_handle, module_name)

        pattern_bytes_str = ""
        for byte in pattern.split(" "):
            if byte == "?":
                pattern_bytes_str += "."
            else:
                pattern_bytes_str += "\\x" + byte

        pattern_bytes = bytes(pattern_bytes_str, "utf-8")

        value = pymem.pattern.pattern_scan_module(self.process_handle, module, pattern_bytes)
        if value is None:
            value = 0

        return value
Осталось самое легкое - написать код)

Python:
def main() -> int:
    dota = QwemeMemory("dota2.exe")

    dota_use_particle_fow_ptr = dota.sigScan("client.dll", "48 8B ? ? ? ? ? 83 78 58 ? 48 8B ? ? ? ? ? 0F 95")
    dota_use_particle_fow_addr = dota.getAbsAddr(dota_use_particle_fow_ptr, 3, 7)

    dota_use_particle_fow_value = dota.read_ulonglong(dota_use_particle_fow_addr) + 0x58 # value of convar on 0x58
   
    dota.write_int(dota_use_particle_fow_value, 0) # equal dota_use_particle_fow 0
   
    return 0
ггвп, девочки и мальчики

Python:
import pymem
import pymem.process
import pymem.pattern


class QwemeMemory(pymem.Pymem):
    def getAbsAddr(self, ptr: int, offset: int, size: int) -> int:
        return ptr + self.read_int(ptr + offset) + size
        
    def sigScan(self, module_name, pattern) -> int:
        module = pymem.process.module_from_name(self.process_handle, module_name)

        pattern_bytes_str = ""
        for byte in pattern.split(" "):
            if byte == "?":
                pattern_bytes_str += "."
            else:
                pattern_bytes_str += "\\x" + byte

        pattern_bytes = bytes(pattern_bytes_str, "utf-8")

        value = pymem.pattern.pattern_scan_module(self.process_handle, module, pattern_bytes)
        if value is None:
            value = 0

        return value


def main() -> int:
    dota = QwemeMemory("dota2.exe")

    dota_use_particle_fow_ptr = dota.sigScan("client.dll", "48 8B ? ? ? ? ? 83 78 58 ? 48 8B ? ? ? ? ? 0F 95")
    dota_use_particle_fow_addr = dota.getAbsAddr(dota_use_particle_fow_ptr, 3, 7)

    dota_use_particle_fow_value = dota.read_ulonglong(dota_use_particle_fow_addr) + 0x58 # value of convar on 0x58
    
    dota.write_int(dota_use_particle_fow_value, 0) # equal dota_use_particle_fow 0
    
    return 0


if __name__ == "__main__":
    exit(main())
 
Пользователь
Статус
Оффлайн
Регистрация
8 Апр 2022
Сообщения
662
Реакции[?]
104
Поинты[?]
67K
можно же просто св читс пропатчить и все конвары юзать
1660618103892.png
jne на jmp
bytepatch((void)(FindPattern(GetModuleHandleW(L"engine2.dll"), "75 ? 48 8B 07 48 8B CF FF 50 38 48 8B D0")), (byte)"\xEB\x1E", 2);
 
https://qweme.dev
Пользователь
Статус
Оффлайн
Регистрация
25 Май 2022
Сообщения
165
Реакции[?]
87
Поинты[?]
21K
можно же просто св читс пропатчить и все конвары юзать
Посмотреть вложение 217102
jne на jmp
bytepatch((void)(FindPattern(GetModuleHandleW(L"engine2.dll"), "75 ? 48 8B 07 48 8B CF FF 50 38 48 8B D0")), (byte)"\xEB\x1E", 2);
а я разве сказал что нельзя? этот гайд о том как найти определенный конвар и поставить валью, к чему ты вообще это написал?

UPD:
и вообще у тебя интернал чит, возьми интерфейс конваров, спизди класс с mcdota и сиди радуйся, какой нахуй патч xd, там даже реверсить не нужно, все за тебя уже сделали
 
Начинающий
Статус
Оффлайн
Регистрация
21 Июн 2020
Сообщения
5
Реакции[?]
1
Поинты[?]
0
не проще написать класс ConVar и сделать по подобию луашного?
E8 ? ? ? ? 48 8B D0 4C 8D 05 ? ? ? ? 48 8B CF FF 93 ? ? ? ? C6 44 24 ? ? 4C 8D 4C 24 ? 48 89 44 24 ? 4C 8D 05 ? ? ? ? 66 44 89 6C 24 ? 33 D2 48 8B 07 48 8B CF FF 90 ? ? ? ? F6 44 24 ? ? 74 1B
и ничего патчить не нужно будет
SearchConVar("sv_cheats"):SetInt(1) (lua), можно логгить адреса кваров
 
https://qweme.dev
Пользователь
Статус
Оффлайн
Регистрация
25 Май 2022
Сообщения
165
Реакции[?]
87
Поинты[?]
21K
не проще написать класс ConVar и сделать по подобию луашного?
E8 ? ? ? ? 48 8B D0 4C 8D 05 ? ? ? ? 48 8B CF FF 93 ? ? ? ? C6 44 24 ? ? 4C 8D 4C 24 ? 48 89 44 24 ? 4C 8D 05 ? ? ? ? 66 44 89 6C 24 ? 33 D2 48 8B 07 48 8B CF FF 90 ? ? ? ? F6 44 24 ? ? 74 1B
и ничего патчить не нужно будет
SearchConVar("sv_cheats"):SetInt(1) (lua), можно логгить адреса кваров
там не нужны сиги вообще, ибо нахуя, у тебя есть готовый интерфейс
Код:
vmt.cvar = tier0->LoadInterface<ICvar>("VEngineCvar007", 42);
Код:
vmt.cvar->FindCommandBase("sv_cheats")->SetInt(1);
C++:
class ConCommandBase {
public:
    // Get
    float GetFloat() {
        typedef float (*Fn)(void*);
        return Memory::GetVFunc<Fn>(this, 13)(this);
    }
    int GetInt() {
        typedef int (*Fn)(void*);
        return Memory::GetVFunc<Fn>(this, 14)(this);
    }
    bool GetBool() {
        typedef bool (*Fn)(void*);
        return Memory::GetVFunc<Fn>(this, 15)(this);
    }
    // Set
    void SetString(const char* value) {
        typedef void (*Fn)(void*, const char*);
        Memory::GetVFunc<Fn>(this, 16)(this, value);
    }
    void SetFloat(float value) {
        typedef void (*Fn)(void*, float);
        Memory::GetVFunc<Fn>(this, 17)(this, value);
    }
    void SetInt(int value) {
        typedef void (*Fn)(void*, int);
        Memory::GetVFunc<Fn>(this, 18)(this, value);
    }
    void SetBool(bool value) {
        typedef void (*Fn)(void*, bool);
        Memory::GetVFunc<Fn>(this, 19)(this, value);
    }
};

class ICvar {
public:
    ConCommandBase* FindCommandBase(char const* convar) {
        typedef ConCommandBase* (*Fn)(void*, char const*);
        return Memory::GetVFunc<Fn>(this, 16)(this, convar);
    }
};
 
Начинающий
Статус
Оффлайн
Регистрация
21 Июн 2020
Сообщения
5
Реакции[?]
1
Поинты[?]
0
там не нужны сиги вообще, ибо нахуя, у тебя есть готовый интерфейс
Код:
vmt.cvar = tier0->LoadInterface<ICvar>("VEngineCvar007", 42);
Код:
vmt.cvar->FindCommandBase("sv_cheats")->SetInt(1);
C++:
class ConCommandBase {
public:
    // Get
    float GetFloat() {
        typedef float (*Fn)(void*);
        return Memory::GetVFunc<Fn>(this, 13)(this);
    }
    int GetInt() {
        typedef int (*Fn)(void*);
        return Memory::GetVFunc<Fn>(this, 14)(this);
    }
    bool GetBool() {
        typedef bool (*Fn)(void*);
        return Memory::GetVFunc<Fn>(this, 15)(this);
    }
    // Set
    void SetString(const char* value) {
        typedef void (*Fn)(void*, const char*);
        Memory::GetVFunc<Fn>(this, 16)(this, value);
    }
    void SetFloat(float value) {
        typedef void (*Fn)(void*, float);
        Memory::GetVFunc<Fn>(this, 17)(this, value);
    }
    void SetInt(int value) {
        typedef void (*Fn)(void*, int);
        Memory::GetVFunc<Fn>(this, 18)(this, value);
    }
    void SetBool(bool value) {
        typedef void (*Fn)(void*, bool);
        Memory::GetVFunc<Fn>(this, 19)(this, value);
    }
};

class ICvar {
public:
    ConCommandBase* FindCommandBase(char const* convar) {
        typedef ConCommandBase* (*Fn)(void*, char const*);
        return Memory::GetVFunc<Fn>(this, 16)(this, convar);
    }
};
не знал об этом, использовал луашную апишку для этого
сига на луашный квар
на интерфейс тогда переделаю
 
https://qweme.dev
Пользователь
Статус
Оффлайн
Регистрация
25 Май 2022
Сообщения
165
Реакции[?]
87
Поинты[?]
21K
Сверху Снизу