Подписывайтесь на наш 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);
 
берешь после этой функции ставишь еще одну, с произвольным уникальным кодом, и &вторая - &первая
А что если они скомпилируются в разных местах? Надо наверное ещё оптимизацию отключить
 
че правда? Ты буквально сделал то что я написал блять, там не обязательно было указывать ссылку на функцию, тут ты и обосрался, потому что делал бы сам - не поставил бы. Тем более если бы сам думал ты бы не оставил вторую функцию пустой, потому что это важно, короче пиздабол.
Уверен?) Про какую ссылку ты говоришь? Может ты про взятие указателя? Спешу тебя расстроить, в нормальных компиляторах (!=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%.

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

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

по теме: а вообще, мне кажется это XY вопрос, скажи для чего тебе надо сохранять функу в байты?
Тебе не кажется, так и есть. Я хотел написать проверку хэша метода в одну игрушку, чтобы при изменении метода новый хэш сравнивался со старым и выводил true или false. В принципе я закончил то, что делал. Спасибо @ maksim dabstep за помощь. Я поменял while на for и получилось что-то вроде этого:


Код:
Expand Collapse Copy
            for (byte* instructions = (byte*)methodPtr; *instructions != 0xC3; instructions++)
            {
                size++;
            }
 
Тебе не кажется, так и есть. Я хотел написать проверку хэша метода в одну игрушку, чтобы при изменении метода новый хэш сравнивался со старым и выводил true или false. В принципе я закончил то, что делал. Спасибо @ maksim dabstep за помощь. Я поменял while на for и получилось что-то вроде этого:


Код:
Expand Collapse Copy
            for (byte* instructions = (byte*)methodPtr; *instructions != 0xC3; instructions++)
            {
                size++;
            }
кринж
for (byte* instructions = (byte*)methodPtr; *instructions != 0xC3; instructions++) { size++; }
ну если так, то давайте вообще в одну строку этот мусор пихать.
C++:
Expand Collapse Copy
for (byte* instructions = (byte*)methodPtr; *instructions++ != 0xC3; size++);
C++:
Expand Collapse Copy
for (byte* instructions = (byte*)methodPtr; instructions[size] != 0xC3; size++);
C++:
Expand Collapse Copy
while (((unsigned char*)methodPtr)[size++] != 0xC3);
 
Последнее редактирование:
кринж

ну если так, то давайте вообще в одну строку этот мусор пихать.
C++:
Expand Collapse Copy
for (byte* instructions = (byte*)methodPtr; *instructions++ != 0xC3; size++);
Спасибо что показал истинные стандарты красоты кода которым ты придерживаешься, но я пишу на шарпе и у меня другие правила для себя. Если я так воспринимаю код, то почему это кринж?


Ей богу, меня всегда удивляло то, что когда ты задаешь вопрос на югейме, в ответах получаешь больше выебонов, чем решений. Сообщение выше даже не было адресовано тебе, хули ты на меня выебываешься?

А потом ещё удивляются почему вопросы не полные, а XY. Потому что тут половина на выебонах чисто поугарать с новичков приходят, не забывая, конечно же, о самоутверждении на счет нас, ведь это так круто.
 
ну а вообще и memchr мог бы заюзать
Ей богу, меня всегда удивляло то, что когда ты задаешь вопрос на югейме, в ответах получаешь больше выебонов, чем решений. Сообщение выше даже не было адресовано тебе, хули ты на меня выебываешься?
ага, читай прошлый коммент. https://yougame.biz/threads/315882/post-3068349
но я пишу на шарпе и у меня другие правила для себя
шарпер, дак сделал бы тему свою в разделе по шарпу. чего ты тут с плюсами забыл чтобы о своих правилах выписывать?
 
Назад
Сверху Снизу