Вопрос Как работать с asm, IDA, x32dbg и как связывать все это через FFI в Lua?

Начинающий
Статус
Оффлайн
Регистрация
18 Апр 2021
Сообщения
12
Реакции[?]
4
Поинты[?]
5K
Есть задача получить значение инвертера десинка через память игры. Я нашел asm код просчета этого самого инвертера в IDE и понял принцип его работы.
Что мне делать с ним дальше?
Нужно ли для нахождения значения инвертера использовать паттерны или просчет адреса памяти через реинтерп касты?
Что вообще делать и как это все работает?

Я понимаю что для этого нужно знать asm, который сейчас и пытаюсь учить.
Желательно объяснять это все дискорде, чтобы было понятнее и нагляднее.

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

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

Вложения

Начинающий
Статус
Оффлайн
Регистрация
18 Апр 2021
Сообщения
12
Реакции[?]
4
Поинты[?]
5K
Еще немного порылся в коде. Нашел где именно объявляется переменная инвертера и чему она равна. Получается что мне нужно либо вызывать функцию, либо искать переменную в стеке со смещением -0D.
1708859897810.png
На данный момент в lua я имею вот такой код:

Код:
local ffi = require("ffi")

local TH32CS_SNAPPROCESS = 0x00000002
local TH32CS_SNAPMODULE = 0x00000008
local INVALID_HANDLE_VALUE = ffi.cast("void*", -1)

ffi.cdef[[
    typedef uint32_t DWORD;
    typedef void* HANDLE;

    typedef struct {
        DWORD dwSize;
        DWORD cntUsage;
        DWORD th32ProcessID;
        uint32_t* th32DefaultHeapID;
        DWORD th32ModuleID;
        DWORD cntThreads;
        DWORD th32ParentProcessID;
        int pcPriClassBase;
        DWORD dwFlags;
        char szExeFile[260];
    } PROCESSENTRY32;

    typedef struct {
        DWORD dwSize;
        DWORD th32ProcessID;
        DWORD th32ModuleID;
        DWORD th32ModuleUsage;
        DWORD th32ModuleUsage2;
        void* modBaseAddr;
        DWORD modBaseSize;
        HANDLE hModule;
        char szModule[256];
        char szExePath[260];
    } MODULEENTRY32;

    DWORD GetProcessId(HANDLE Process);
    HANDLE CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID);
    HANDLE OpenProcess(int dwDesiredAccess, int bInheritHandle, int dwProcessId);
    int ReadProcessMemory(int hProcess, int lpBaseAddress, char* lpBuffer, int nSize, int* lpNumberOfBytesRead);

    int Process32First(HANDLE hSnapshot, void* lppe);
    int Process32Next(HANDLE hSnapshot, void* lppe);
    int Module32First(HANDLE hSnapshot, MODULEENTRY32* lpme);
    int Module32Next(HANDLE hSnapshot, MODULEENTRY32* lpme);
    int CloseHandle(HANDLE hObject);
]]

local function getProcessId(processName)
    local hSnapshot = ffi.C.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
    if hSnapshot == INVALID_HANDLE_VALUE then
        error("Failed to create a snapshot of the processes")
    end

    local pe32 = ffi.new("PROCESSENTRY32")
    pe32.dwSize = ffi.sizeof("PROCESSENTRY32")

    if ffi.C.Process32First(hSnapshot, pe32) == 0 then
        ffi.C.CloseHandle(hSnapshot)
        error("Failed to retrieve information about the first process in the snapshot")
    end

    repeat
        if ffi.string(pe32.szExeFile) == processName then
            ffi.C.CloseHandle(hSnapshot)
            return pe32.th32ProcessID
        end
    until ffi.C.Process32Next(hSnapshot, pe32) == 0

    ffi.C.CloseHandle(hSnapshot)
    return nil
end

local function getModuleBaseAddress(processId, moduleName)
    local hSnapshot = ffi.C.CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processId)
    if hSnapshot == INVALID_HANDLE_VALUE then
        error("Failed to create a snapshot of the modules")
    end

    local me32 = ffi.new("MODULEENTRY32")
    me32.dwSize = ffi.sizeof("MODULEENTRY32")

    if ffi.C.Module32First(hSnapshot, me32) == 0 then
        ffi.C.CloseHandle(hSnapshot)
        error("Failed to retrieve information about the first module in the snapshot")
    end

    repeat
        if ffi.string(me32.szModule) == moduleName then
            ffi.C.CloseHandle(hSnapshot)
            return tonumber(ffi.cast("uintptr_t", me32.modBaseAddr))
        end
    until ffi.C.Module32Next(hSnapshot, me32) == 0

    ffi.C.CloseHandle(hSnapshot)
    return nil
end

local PROCESS_VM_READ = 0x100010000
local processId = getProcessId("csgo.exe")
local baseAddress = getModuleBaseAddress(processId, "ArcticTech.dll")
local offset = 0x868F

local handle = ffi.C.OpenProcess(PROCESS_VM_READ, false, processId)
if handle == nil then
    error("Failed to open the process")
end

local buffer = ffi.new("char[4]")
local bytesRead = ffi.new("DWORD[1]")

if ffi.C.ReadProcessMemory(ffi.cast("uintptr_t", handle), baseAddress + offset, buffer, 4, bytesRead) == 0 then
    error("Failed to read process memory")
end

print(buffer)
 
Pa$$ter
Пользователь
Статус
Оффлайн
Регистрация
9 Июн 2020
Сообщения
238
Реакции[?]
83
Поинты[?]
12K
а зачем ты рпм используешь? у тебя код луа в внешнем процессе?
а вообще скорее лучше будет находить непосредственно этот код по сигнатуре и заменять je на jne когда ты хочешь инвертировать чем пытаться это сделать в стеке как по ине
 
Начинающий
Статус
Оффлайн
Регистрация
18 Апр 2021
Сообщения
12
Реакции[?]
4
Поинты[?]
5K
а зачем ты рпм используешь? у тебя код луа в внешнем процессе?
а вообще скорее лучше будет находить непосредственно этот код по сигнатуре и заменять je на jne когда ты хочешь инвертировать чем пытаться это сделать в стеке как по ине
Мне человек подсказал что можно через рпм это сделать. И мне не нужно менять значение инвертера, мне нужно его гетнуть, поэтому зачем мне трогать jmp инструкции?
Еще я пытался убрать функции getProcessId и getModuleBaseAddress, но тогда мне рпм выбивал ошибку ( ERROR_INVALID_HANDLE ).
 
Pa$$ter
Пользователь
Статус
Оффлайн
Регистрация
9 Июн 2020
Сообщения
238
Реакции[?]
83
Поинты[?]
12K
Мне человек подсказал что можно через рпм это сделать. И мне не нужно менять значение инвертера, мне нужно его гетнуть, поэтому зачем мне трогать jmp инструкции?
Еще я пытался убрать функции getProcessId и getModuleBaseAddress, но тогда мне рпм выбивал ошибку ( ERROR_INVALID_HANDLE ).
У тебя луа внутри игры? Если да и ты хочешь использовать именно рпм вместо ffi.cast то можешь в качестве хендла передать -1
 
Начинающий
Статус
Оффлайн
Регистрация
18 Апр 2021
Сообщения
12
Реакции[?]
4
Поинты[?]
5K
У тебя луа внутри игры? Если да и ты хочешь использовать именно рпм вместо ffi.cast то можешь в качестве хендла передать -1
А как можно бейз адрес ддлки чита получить?
Мне чел сказал то что можно просто в иде его посмотреть.
 
Начинающий
Статус
Оффлайн
Регистрация
18 Апр 2021
Сообщения
12
Реакции[?]
4
Поинты[?]
5K
Умный человек подсказал мне что можно воспользоваться потоками.
Я придумал что можно получить ctx потока, получить из него регистр eip, сравнить его с нужным мне оффсетом и далее получить значение ebp.
Возможно я чего-то не до конца понимаю, но постоянно получать ctx потока и ловить момент когда eip будет необходимым мне числом либо вовсе невозможно, либо будет очень ресурсозатратно.

Как по итогу гетнуть значение то это :roflanBuldiga:

Код:
local ffi = require("ffi")
ffi.cdef[[
    typedef struct CONTEXT {
        uint32_t ContextFlags;
        uint32_t Dr0;
        uint32_t Dr1;
        uint32_t Dr2;
        uint32_t Dr3;
        uint32_t Dr6;
        uint32_t Dr7;
        uint32_t SegGs;
        uint32_t SegFs;
        uint32_t SegEs;
        uint32_t SegDs;
        uint32_t Edi;
        uint32_t Esi;
        uint32_t Ebx;
        uint32_t Edx;
        uint32_t Ecx;
        uint32_t Eax;
        uint32_t Ebp;
        uint32_t Eip;
        uint32_t SegCs;
        uint32_t EFlags;
        uint32_t Esp;
        uint32_t SegSs;
    } CONTEXT;

    void* GetThreadContext(void* hThread, CONTEXT* context);
]]

local kernel32 = ffi.load("kernel32")
local GetCurrentThread = kernel32.GetCurrentThread -- Тут будет поток дллки чита

local context = ffi.new("CONTEXT")
kernel32.GetThreadContext(GetCurrentThread(), context)

print("EIP: " .. string.format("%X", context.Eip)) -- Тут будет сравнение с оффсетом нужных инструкций

local ebp_value = ffi.cast("int*", context.Ebp - 0x0D)
print("Value at EBP - 0D: " .. ebp_value[0])
 
Эксперт
Статус
Оффлайн
Регистрация
29 Мар 2021
Сообщения
1,523
Реакции[?]
572
Поинты[?]
8K
ахахах мужик опять через луа чит дампит да сколько же можно то
 
Nike.lua
Олдфаг
Статус
Оффлайн
Регистрация
13 Окт 2020
Сообщения
2,748
Реакции[?]
1,466
Поинты[?]
2K
Просто посмотри в псевдокоде иды откуда эта вся хуйня берется, она по-любому хранится либо в какой то структуре, либо её значение можно получить из функции.

Если она берется из структуры - просто найди, куда эта структура летит после запуска Чита и получи ее адрес, а после поищи в иде смещение до твоего значения.

Если это можно получить из функции, то становится ещё легче. Находишь адрес функции, на всякий случай ставишь бряк на нее и смотришь, то ли ты нашел. Если да - составляешь паттерн на эту функу, копируешь ее определение типа int __fastcall sub_blablabla(), переводишь это в человеческий вид, чтобы можно было ее закастить и вызвать, а после чего просто по паттерну ищешь адрес, кастишь функцию и вызываешь.
 
Начинающий
Статус
Оффлайн
Регистрация
18 Апр 2021
Сообщения
12
Реакции[?]
4
Поинты[?]
5K
Просто посмотри в псевдокоде иды откуда эта вся хуйня берется, она по-любому хранится либо в какой то структуре, либо её значение можно получить из функции.

Если она берется из структуры - просто найди, куда эта структура летит после запуска Чита и получи ее адрес, а после поищи в иде смещение до твоего значения.

Если это можно получить из функции, то становится ещё легче. Находишь адрес функции, на всякий случай ставишь бряк на нее и смотришь, то ли ты нашел. Если да - составляешь паттерн на эту функу, копируешь ее определение типа int __fastcall sub_blablabla(), переводишь это в человеческий вид, чтобы можно было ее закастить и вызвать, а после чего просто по паттерну ищешь адрес, кастишь функцию и вызываешь.
Спасибо большое за идеи; Я бы конечно так и сделал, но есть маленький нюанс. Значение инвертера просчитывается локально. Т.е. принцип работы такой:

Гетается значение кейбинда инвертера
Проверяется включены ли доп. опции (например фристенд десинка, джиттер и т.д.)
И далее если в данный момент не отправляется пакет, тогда чит меняет yaw_offset относительно ЛОКАЛЬНО просчитанного инвертера.
Я конечно могу фулл переписать всю логику этого самого просчета, но это будет внеебичски запарно.
 
sapphire dev
Пользователь
Статус
Оффлайн
Регистрация
15 Мар 2018
Сообщения
186
Реакции[?]
123
Поинты[?]
35K
Я б помог, но я ничо не понял, когда пойму - расскажите мне.
 
Сверху Снизу