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

Начинающий
Статус
Оффлайн
Регистрация
29 Июл 2022
Сообщения
101
Реакции[?]
28
Поинты[?]
29K
линкер не стрипнет функу если она где-то используется, а если даже и стрипнет (хотя такого быть не может т.к. компилер и линкер не должны ломать код) можно просто заюзать volatile

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


Код:
            for (byte* instructions = (byte*)methodPtr; *instructions != 0xC3; instructions++)
            {
                size++;
            }
 
Начинающий
Статус
Оффлайн
Регистрация
22 Дек 2023
Сообщения
264
Реакции[?]
16
Поинты[?]
17K
Тебе не кажется, так и есть. Я хотел написать проверку хэша метода в одну игрушку, чтобы при изменении метода новый хэш сравнивался со старым и выводил true или false. В принципе я закончил то, что делал. Спасибо @ OXXXYMlRON за помощь. Я поменял while на for и получилось что-то вроде этого:


Код:
            for (byte* instructions = (byte*)methodPtr; *instructions != 0xC3; instructions++)
            {
                size++;
            }
кринж
for (byte* instructions = (byte*)methodPtr; *instructions != 0xC3; instructions++) { size++; }
ну если так, то давайте вообще в одну строку этот мусор пихать.
C++:
for (byte* instructions = (byte*)methodPtr; *instructions++ != 0xC3; size++);
C++:
for (byte* instructions = (byte*)methodPtr; instructions[size] != 0xC3; size++);
C++:
while (((unsigned char*)methodPtr)[size++] != 0xC3);
 
Последнее редактирование:
Начинающий
Статус
Оффлайн
Регистрация
29 Июл 2022
Сообщения
101
Реакции[?]
28
Поинты[?]
29K
кринж

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


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

А потом ещё удивляются почему вопросы не полные, а XY. Потому что тут половина на выебонах чисто поугарать с новичков приходят, не забывая, конечно же, о самоутверждении на счет нас, ведь это так круто.
 
Начинающий
Статус
Оффлайн
Регистрация
22 Дек 2023
Сообщения
264
Реакции[?]
16
Поинты[?]
17K
ну а вообще и memchr мог бы заюзать
Ей богу, меня всегда удивляло то, что когда ты задаешь вопрос на югейме, в ответах получаешь больше выебонов, чем решений. Сообщение выше даже не было адресовано тебе, хули ты на меня выебываешься?
ага, читай прошлый коммент. https://yougame.biz/threads/315882/post-3068349
но я пишу на шарпе и у меня другие правила для себя
шарпер, дак сделал бы тему свою в разделе по шарпу. чего ты тут с плюсами забыл чтобы о своих правилах выписывать?
 
Начинающий
Статус
Оффлайн
Регистрация
29 Июл 2022
Сообщения
101
Реакции[?]
28
Поинты[?]
29K
ну а вообще и memchr мог бы заюзать

ага, читай прошлый коммент. https://yougame.biz/threads/315882/post-3068349

шарпер, дак сделал бы тему свою в разделе по шарпу. чего ты тут с плюсами забыл чтобы о своих правилах выписывать?
Покидай ещё стрелок пж, ведь про правила, сперва задал вопрос я тебе. Я даже не упоминал на каком языке я пишу ранее, а ты даже до этого доебался)
шарпер, дак сделал бы тему свою в разделе по шарпу. чего ты тут с плюсами забыл чтобы о своих правилах выписывать?
Ты не поверишь, но мой основной язык это си шарп, но я не утверждал что я пишу этот проект на шарпе. Я вахуе как можно быть таким высокомерным типом)

Это схуяли я должен создавать тему как шарп, если я не на шарпе пишу этот проект? Хули ты раскомандовался?
шарпер, дак сделал бы тему свою в разделе по шарпу.
Да даже если бы я этот проект хуярил на шарпе, то к твоёму сожалению там тоже доступна работа с указателями. Шах и мат
 
Последнее редактирование:
Начинающий
Статус
Оффлайн
Регистрация
22 Дек 2023
Сообщения
264
Реакции[?]
16
Поинты[?]
17K
Да даже если бы я этот проект хуярил на шарпе, то к твоёму сожалению там тоже доступна работа с указателями. Шах и мат
а кто сказал что она не доступна на шарпе?
 
Начинающий
Статус
Оффлайн
Регистрация
29 Июл 2022
Сообщения
101
Реакции[?]
28
Поинты[?]
29K
а кто сказал что она не доступна на шарпе?
Бро, извини меня, я себя как неадекват повел. Просто когда ты целый день сидишь за кодом, и в итоге твой код стайл засирает рандомный чел, то от этого оч подгарает
 
Начинающий
Статус
Оффлайн
Регистрация
22 Дек 2023
Сообщения
264
Реакции[?]
16
Поинты[?]
17K
Бро, извини меня, я себя как неадекват повел. Просто когда ты целый день сидишь за кодом, и в итоге твой код стайл засирает рандомный чел, то от этого оч подгарает
рандомный тип это ты. и да шарп это дерьмо!
 
Пользователь
Статус
Оффлайн
Регистрация
13 Сен 2021
Сообщения
633
Реакции[?]
117
Поинты[?]
44K
че правда? Ты буквально сделал то что я написал блять, там не обязательно было указывать ссылку на функцию, тут ты и обосрался, потому что делал бы сам - не поставил бы. Тем более если бы сам думал ты бы не оставил вторую функцию пустой, потому что это важно, короче пиздабол.
мы вертимся вокруг тебя, поверь мне. крутимся и кружимся...
 
✊Rot Front✊
Пользователь
Статус
Оффлайн
Регистрация
2 Июл 2020
Сообщения
132
Реакции[?]
258
Поинты[?]
86K
Я лишь скажу пару моментов при получении длины функции при дизассемблировании(это относится больше при компиляции c++ Microsoft Visual Studio):
1)очень трудно определить длину функции, а если вы захотите перенести её в другой участок памяти, то вам нужно исправлять все команды, где есть относительные прыжки(эти примеры, чтобы было понятнее):
call 0xdeadc0de,jmp 0xdeadc0de, lea reg,qword[rip+...],jmp/call qword ptr[rip+offset_value] и другие.
2)можно использовать выравнивание функции, созданное компилятором, например( int3, nop qword [rax], eax(начало новой функции) и другие).
3)если в функции нет jcc и прыжков, то можно дизассемблировать до ret(дизассемблировать тупо до команды ret не совсем хорошая идея т.к компилятор может вставить несколько(очень редко происходит т.к делает обычно jmp)
(правда, нужно придумать определение тогда noreturn функций, но я отвечу: дом горел, а я руки грел).
4)лучше по возможностей использовать pdb парсер, ибо с ним меньше геморроя(моё мнение и не вижу смысл создавать велосипед, но не всем понравится).
Теперь моё не совсем удачное решение(снизу опишу почему) и примеры:

Example:
    auto ntdll_base = GetModuleHandleW(L"ntdll.dll");
    auto kernel32_base = GetModuleHandleW(L"kernelbase.dll");
    CHAR* addr_user_except = (CHAR*)GetProcAddress(ntdll_base, "KiUserExceptionDispatcher");
    CHAR* addr_add_table = (CHAR*)GetProcAddress(ntdll_base, "RtlAddFunctionTable");
    CHAR* addr_open_proc = (CHAR*)GetProcAddress(kernel32_base, "OpenProcess");
   
    printf("KiUserExceptionDispatcher size ->\t%p\n", get_len_fun(addr_user_except));
    printf("RtlAddFunctionTable size ->\t%p\n", get_len_fun(addr_add_table));
    printf("OpenProcess size ->\t%p\n", get_len_fun(addr_open_proc));
и сам код:
очень плохой код,но лучше предлагайте идеи,а не чешите своим языком:
    auto get_len_fun(CHAR* runtime_address) -> uint32_t
    {

        uint8_t* mem = NULL;
        uint8_t* mem_pos = NULL;
        uint8_t* mem_max_pos = NULL;
        dis_fun dis_fun = { NULL };
        ZydisDisassembledInstruction info_instr = { NULL };

        mem = (uint8_t*)(runtime_address);


        while (ZYAN_SUCCESS(ZydisDisassembleIntel(
            dis_mode,
            reinterpret_cast<ZyanU64>(mem),
            mem,
            MAX_LENGHT_INSTR,
            &info_instr
        )))
        {
            switch (info_instr.info.mnemonic)
            {
            case ZYDIS_MNEMONIC_INT3:
            {
                if ((dis_fun.is_jcc || dis_fun.is_ret) && mem >= mem_max_pos)
                {
                    return dis_fun.lenght_fun;
                }

                if (!dis_fun.aling_break)
                {
                    dis_fun.aling_break++; // fist change
                }

                if (dis_fun.aling_break && dis_fun.is_last_bp)
                {
                    dis_fun.aling_break++; //change
                }

                if (
                    dis_fun.is_last_bp &&
                    dis_fun.aling_break >= MAX_ALINGHT_BP &&
                    mem >= mem_max_pos
                    )
                {
                    return dis_fun.lenght_fun - dis_fun.aling_break + 1;
                }
                dis_fun.is_last_bp = TRUE;
                dis_fun.is_last_exit = FALSE;
                dis_fun.is_jcc = FALSE;
                dis_fun.is_ret = FALSE;

                dis_fun.lenght_fun += info_instr.info.length;
                mem += info_instr.info.length;

                break;
            }

            case ZYDIS_MNEMONIC_NOP:
            {
                if (
                    info_instr.info.length >= sizeof(uint16_t) || // 0x66 ... 0x90
                    info_instr.info.operand_count_visible >= sizeof(uint16_t) //nop qword [rax], eax
                    )
                {
                    if (dis_fun.is_last_exit && mem >= mem_max_pos)
                    {
                        return dis_fun.lenght_fun - dis_fun.aling_break;
                    }
                }

                dis_fun.is_last_exit = FALSE;
                dis_fun.is_last_bp = FALSE;
                dis_fun.is_jcc = FALSE;
                dis_fun.is_ret = FALSE;

                dis_fun.lenght_fun += info_instr.info.length;
                mem += info_instr.info.length;
                break;
            }

            case ZYDIS_MNEMONIC_SUB:
            {
                if (dis_fun.is_last_bp || dis_fun.is_last_exit)
                {
                    if (info_instr.operands[0].mem.base == ZYDIS_REGISTER_RSP &&
                        info_instr.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY
                        )
                    {
                        return dis_fun.lenght_fun - dis_fun.aling_break + 1;
                    }
                }
                dis_fun.is_last_exit = FALSE;
                dis_fun.is_last_bp = FALSE;
                dis_fun.is_jcc = FALSE;
                dis_fun.is_ret = FALSE;

                dis_fun.lenght_fun += info_instr.info.length;
                mem += info_instr.info.length;
                break;
            }

            case ZYDIS_MNEMONIC_RET:
            {
                dis_fun.is_last_exit = TRUE;
                dis_fun.is_last_bp = FALSE;
                dis_fun.is_jcc = FALSE;
                dis_fun.is_ret = TRUE;

                dis_fun.aling_break = NULL;


                if (!dis_fun.jcc_count || (dis_fun.jcc_count && mem >= mem_max_pos)) //Functhion don't have jcc
                {

                    return dis_fun.lenght_fun + info_instr.info.length;
                }
                dis_fun.lenght_fun += info_instr.info.length;
                mem += info_instr.info.length;


                break;
            }



            case ZYDIS_MNEMONIC_JMP:
            case ZYDIS_MNEMONIC_JB:
            case ZYDIS_MNEMONIC_JBE:
            case ZYDIS_MNEMONIC_JCXZ:
            case ZYDIS_MNEMONIC_JECXZ:
            case ZYDIS_MNEMONIC_JKNZD:
            case ZYDIS_MNEMONIC_JKZD:
            case ZYDIS_MNEMONIC_JL:
            case ZYDIS_MNEMONIC_JLE:
            case ZYDIS_MNEMONIC_JNB:
            case ZYDIS_MNEMONIC_JNBE:
            case ZYDIS_MNEMONIC_JNL:
            case ZYDIS_MNEMONIC_JNLE:
            case ZYDIS_MNEMONIC_JNO:
            case ZYDIS_MNEMONIC_JNP:
            case ZYDIS_MNEMONIC_JNS:
            case ZYDIS_MNEMONIC_JNZ:
            case ZYDIS_MNEMONIC_JO:
            case ZYDIS_MNEMONIC_JP:
            case ZYDIS_MNEMONIC_JRCXZ:
            case ZYDIS_MNEMONIC_JS:
            case ZYDIS_MNEMONIC_JZ:
            {

                dis_fun.is_last_exit = FALSE;
                dis_fun.is_last_bp = FALSE;
                dis_fun.is_jcc = TRUE;
                dis_fun.is_ret = FALSE;

                if (info_instr.info.mnemonic == ZYDIS_MNEMONIC_JMP)
                {
                    if (dis_fun.lenght_fun == NULL)
                    {
                        return info_instr.info.length;
                    }

                    dis_fun.is_last_exit = TRUE;

                    mem_pos = reinterpret_cast<uint8_t*>(get_absolute_address(&info_instr, reinterpret_cast<ZyanU64>(mem)));
                    if (mem_pos &&
                        mem >= mem_max_pos &&
                        mem >= mem_pos)
                    {
                        return dis_fun.lenght_fun + info_instr.info.length;
                    }
                }
                else
                {
                    //Fix for DLL main
                    mem_pos = reinterpret_cast<uint8_t*>(get_absolute_address(&info_instr, reinterpret_cast<ZyanU64>(mem)));

                    if (mem_pos && mem_pos > mem)
                    {
                        if (mem_max_pos == NULL)
                        {
                            mem_max_pos = mem_pos;
                        }
                        else if (mem_pos > mem_max_pos)
                        {
                            mem_max_pos = max(mem_max_pos, mem_pos);
                        }
                    }
                    dis_fun.jcc_count++;
                }
                mem_pos = NULL;
                dis_fun.aling_break = NULL;


                dis_fun.lenght_fun += info_instr.info.length;
                mem += info_instr.info.length;

                break;
            }
            default:
            {
                if (*mem == NULL)
                {
                    return dis_fun.lenght_fun - dis_fun.aling_break;
                }
                dis_fun.is_last_bp = FALSE;
                dis_fun.is_ret = FALSE;
                dis_fun.is_last_exit = FALSE;
                dis_fun.is_jcc = FALSE;
                dis_fun.aling_break = NULL;

                dis_fun.lenght_fun += info_instr.info.length;
                mem += info_instr.info.length;
                break;
            }
            }
        }
        return NULL;
    }
KiUserExceptionDispatcher:
Screenshot_672.pngRtlAddFunctionTable:Screenshot_670.png
OpenProcess:
Screenshot_671.png

Проблемы:
1)сделать определение функции, когда идёт прыжок к импорту аля:
_crt_atexit_0 proc near
jmp cs:__imp__crt_atexit
_crt_atexit_0 endp
у меня тут костыль, когда функция делает jmp(сделайте проверку ,что указатель в другой секции(т.е не текущая секция)
2)не совсем корректно берёт размер функции у Sleep в kernelbase.dll(хотя там прыжок в функцию SleepEx
3)есть другие моменты, но мне лень их вспоминать
P.S отправные моменты я уже сказал,но используйте свою голову.
Буду признателен, если скажите ошибки(помимо кода написанного явно под чем-то :grin: )
 
Начинающий
Статус
Оффлайн
Регистрация
22 Дек 2023
Сообщения
264
Реакции[?]
16
Поинты[?]
17K
4)лучше по возможностей использовать pdb парсер, ибо с ним меньше геморроя(моё мнение и не вижу смысл создавать велосипед, но не всем понравится).
вы можете читать дебаг заголовки в них вы можете найти начало и конец практически любой функции.(инфо для исключений)
 
Сверху Снизу