Подпишитесь на наш Telegram-канал, чтобы всегда быть в курсе важных обновлений! Перейти

C++ Считывание начала и конца функции в памяти. C++

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
29 Июл 2022
Сообщения
101
Реакции
28
Привет. Появилась проблемка, и только югеймеры смогут с ней справится. Есть адрес моей функции, который я получаю через "&". Помогите мне найти конец функции пожалуйста, чтобы я все байты инструкций мог всунуть в массив byte[] в виде int чисел?


Условно: У меня есть адрес 7FF71FAB9A80. Это начало моей функции. Как мне дойти до конца этой функции и все полученные байты скопировать массив? Это если говорить коротко.
 
берешь после этой функции ставишь еще одну, с произвольным уникальным кодом, и &вторая - &первая
 
да никак нахуй

можешь бежать по схеме

int size = 0;
while (*p != INSTRUCTION_RET) {
++p;
++size;
}

и в тупую искать инструкцию ret
В конце каждой функции 100% стоит ret? Просто я по памяти не очень сильно шарю и за плюсы тоже.
 
В конце каждой функции 100% стоит ret? Просто я по памяти не очень сильно шарю и за плюсы тоже.
нет, не стоит, но это самый простой способ.

позволь спросить - тебе это нахуя надо?
 
Используй либо дизассемблер, проходясь по телу функции (нужно учитывать, что функции могут кончаться и на jmp и на ret), либо конструкцию подобного рода.
C++:
Expand Collapse Copy
static void function_begin()
{
    // code
}
static void function_end() { };
auto function_size = reinterpret_cast<PBYTE>(&function_end) - reinterpret_cast<PBYTE>(&function_begin);
 
Используй либо дизассемблер, проходясь по телу функции (нужно учитывать, что функции могут кончаться и на jmp и на ret), либо конструкцию подобного рода.
C++:
Expand Collapse Copy
static void function_begin()
{
    // code
}
static void function_end() { };
auto function_size = reinterpret_cast<PBYTE>(&function_end) - reinterpret_cast<PBYTE>(&function_begin);
спасибо что передал мою идею кодом
 
Не заметил твоего сообщения, но все-же пользователю будет проще.
че правда? Ты буквально сделал то что я написал блять, там не обязательно было указывать ссылку на функцию, тут ты и обосрался, потому что делал бы сам - не поставил бы. Тем более если бы сам думал ты бы не оставил вторую функцию пустой, потому что это важно, короче пиздабол.
 
берешь после этой функции ставишь еще одну, с произвольным уникальным кодом, и &вторая - &первая
А что если они скомпилируются в разных местах? Надо наверное ещё оптимизацию отключить
 
че правда? Ты буквально сделал то что я написал блять, там не обязательно было указывать ссылку на функцию, тут ты и обосрался, потому что делал бы сам - не поставил бы. Тем более если бы сам думал ты бы не оставил вторую функцию пустой, потому что это важно, короче пиздабол.
Уверен?) Про какую ссылку ты говоришь? Может ты про взятие указателя? Спешу тебя расстроить, в нормальных компиляторах (!=MSVC) взятие адреса на функцию происходит только через &. Вторую функцию можно спокойно оставлять пустой и это прекрасно работает на различных компиляторах.
А что если они скомпилируются в разных местах? Надо наверное ещё оптимизацию отключить
Они будут друг за другом в любом случае, оптимизации отключать не стоит.
 
А что если они скомпилируются в разных местах? Надо наверное ещё оптимизацию отключить
я ни слова не сказал о том что определенные параметры не требуются)
 
Пожалуйста, авторизуйтесь для просмотра ссылки.


C++:
Expand Collapse Copy
const size_t get_instruction_size(uintptr_t addr)
{
    hde64_t instr = { 0 };
    size_t size = 0;

    for (;; addr += instr.len)
    {
        disasm64(reinterpret_cast<void*>(addr), &instr);

        size += instr.len;

        if (instr.flags & F_ERROR || size >= 5)
            break;
    }

    return size;
}
 
Тем более если бы сам думал ты бы не оставил вторую функцию пустой, потому что это важно
линкер не стрипнет функу если она где-то используется, а если даже и стрипнет (хотя такого быть не может т.к. компилер и линкер не должны ломать код) можно просто заюзать volatile

по теме: а вообще, мне кажется это XY вопрос, скажи для чего тебе надо сохранять функу в байты?
 
да никак нахуй

можешь бежать по схеме

int size = 0;
while (*p != INSTRUCTION_RET) {
++p;
++size;
}

и в тупую искать инструкцию ret
решение не может быть верным, так как может быть несколько инструкций ret в одной функции, да и этот байт не обязательно будет в ret, например вы столкнетесь на части какой-то другой инструкции.

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


C++:
Expand Collapse Copy
const size_t get_instruction_size(uintptr_t addr)
{
    hde64_t instr = { 0 };
    size_t size = 0;

    for (;; addr += instr.len)
    {
        disasm64(reinterpret_cast<void*>(addr), &instr);

        size += instr.len;

        if (instr.flags & F_ERROR || size >= 5)
            break;
    }

    return size;
}
вам надо еще учитывать условные переходы jnz/jmp/je и тд. также как и не обязательно что ret будет в самом конце из-за тех же переходов.

Используй либо дизассемблер, проходясь по телу функции (нужно учитывать, что функции могут кончаться и на jmp и на ret), либо конструкцию подобного рода.
C++:
Expand Collapse Copy
static void function_begin()
{
    // code
}
static void function_end() { };
auto function_size = reinterpret_cast<PBYTE>(&function_end) - reinterpret_cast<PBYTE>(&function_begin);
компилятор может твой бегин воткнуть после твоей end функции так что вариант может пройти, но не на 100%.

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

вот вам одно из действительно верных ответов по данной теме:
вы можете читать дебаг заголовки в них вы можете найти начало и конец практически любой функции.
 
Последнее редактирование:
Назад
Сверху Снизу