Вопрос Как получить значения регистров ASM | DLL 32bit [Решено]

Начинающий
Статус
Оффлайн
Регистрация
9 Мар 2021
Сообщения
135
Реакции[?]
11
Поинты[?]
6K
Есть у меня адрес, как по этому адресу получить значение регистра ebx?
Мне надо раз в 1 минуту записывать в std::vector штук 30 разных адресов которые появляются в регистре ebx.
Эти 30 адресов по адресу в ebx записываются ежемиллисекундно
 
Начинающий
Статус
Оффлайн
Регистрация
21 Апр 2024
Сообщения
33
Реакции[?]
22
Поинты[?]
21K
Есть у меня адрес, как по этому адресу получить значение регистра ebx?
Мне надо раз в 1 минуту записывать в std::vector штук 30 разных адресов которые появляются в регистре ebx.
Эти 30 адресов по адресу в ebx записываются ежемиллисекундно
ставишь на этот адрес int3 и утснавливаешь свой veh и там смотришь значение ebx.
 
Начинающий
Статус
Оффлайн
Регистрация
21 Мар 2021
Сообщения
95
Реакции[?]
29
Поинты[?]
7K
Трамплин хук установи и в его теле данные регистра уже прокидывай куда угодно, правда придётся чуть-чуть ASM кода накидать
 
Начинающий
Статус
Оффлайн
Регистрация
9 Мар 2021
Сообщения
135
Реакции[?]
11
Поинты[?]
6K
ставишь на этот адрес int3 и утснавливаешь свой veh и там смотришь значение ebx.
Спасибо, я через чатгпт пытался прогнать подобное, но я что-то не вдуплил, типа int3 ведь устанавливается на сам адрес инструкции, т.е. заменяет байты инструкции и как она тогда выполняться должна? Я просто не совсем понял эту тему.
Типа например сделать трамплинхук перед этой инструкцией + оставить место байтов под int3, после выполнить инструкции которые заменил на jmp и int3?


Трамплин хук установи и в его теле данные регистра уже прокидывай куда угодно, правда придётся чуть-чуть ASM кода накидать
Я сделал так, но у меня почему-то выводится в консоль постоянно один и тот же адрес, хоть он и верный из регистра ebx, но никаких других адресов больше нет, даже через минуту.
Хотя если я поставлю бряк на "mov ecx, ebx", то регистр ebx меняется


1731936877789.png
1731939900511.png

1731939924399.png

C++:
DWORD EntityNametags;
DWORD returnAddressNametags;

bool IsValidPointer(void* pointer)
{
    MEMORY_BASIC_INFORMATION mbi;
    if (VirtualQuery(pointer, &mbi, sizeof(mbi)))
    {
        DWORD protect = mbi.Protect;
        return protect == PAGE_EXECUTE_READWRITE || protect == PAGE_READWRITE; // || protect == PAGE_READONLY
    }
    return false;
}

__declspec(naked) void CodecaveNametags()
{
    __asm
    {
        //jump 5or6 byte
        mov [EntityNametags], ebx // 6 byte
        mov ecx, ebx // 2 byte
        call dword ptr[eax] // 2 byte
        fld dword ptr[eax + 0x08] // 3 byte
        jmp [returnAddressNametags] // 6 byte
    }
}

// Выполняется первым
void InjectCodecaveNametags(DWORD targetAddress)
{
    DWORD oldProtect;

    VirtualProtect((LPVOID)targetAddress, 7, PAGE_EXECUTE_READWRITE, &oldProtect);

    returnAddressNametags = targetAddress + 7;

    *(BYTE*)targetAddress = 0xE9; // JMP
    *(BYTE*)(targetAddress + 5) = 0x90; // NOP
    *(BYTE*)(targetAddress + 6) = 0x90; // NOP
    *(DWORD*)(targetAddress + 1) = (DWORD)&CodecaveNametags - (targetAddress + 5);

    IsValidPointer((void*)EntityNametags);

    //VirtualProtect((LPVOID)targetAddress, 7, oldProtect, &oldProtect);
}

std::vector<EntityBetter*> FilterNametags()
{
    std::vector<EntityBetter*> entities;

    if (!IsValidPointer((void*)EntityNametags))
    {
        std::cout << "BLOCK 1111111111111111111111111" << std::endl;
        return entities;
    }
    std::cout << "FilterNametags | " << "EntityNametags: 0x" << std::hex << EntityNametags << std::dec << std::endl;
    for (int i = 0; i < 100; ++i)
    {
        EntityBetter* scanForEntity = (EntityBetter*)EntityNametags;
        std::cout << "For | " << "scanForEntity: 0x" << std::hex << scanForEntity << std::dec << std::endl;
        if (scanForEntity->team > 0 && scanForEntity->team < 6) // scanForEntity->team != hudCaps->teamPlayer && scanForEntity->dead_0 != 0
        {
            std::cout << "If | " << "team: " << scanForEntity->team << std::endl;
            //std::cout << "If | " << "dead_0: " << scanForEntity->dead_0 << std::endl;

            entities.push_back(scanForEntity);
        }
    }
    return entities;
}
 
Последнее редактирование:
Начинающий
Статус
Оффлайн
Регистрация
21 Апр 2024
Сообщения
33
Реакции[?]
22
Поинты[?]
21K
Типа например сделать трамплинхук перед этой инструкцией + оставить место байтов под int3, после выполнить инструкции которые заменил на jmp и int3?
Не совсем понял что ты имеешь ввиду все намного проще.Сначала ты берешь ту инструкцию,которую ты заменишь инт3 в твоем случае mov ecx, ebx,копируешь эти байты.Потом в вехе когда срабатывает твой бряк на инт3 пишешь логику свою.После делаешь VirtualAlloc и туда записываешь инструкцию которую ты пропатчил,чтобы она выполнилась + делаешь прыжок на адрес после той инструкции что ты затер,меняешь rip на свой трамполин,выполняется инструкцию которая ты затер и прыгает трамполин на инструкцию после,в итоге лоигка программы сохраняется.Короч смотри код,я как то такую хуйню делал мб разберешь.
C++:
LONG WINAPI VectoredHandler(PEXCEPTION_POINTERS pExceptionInfo) {
    // Check if the exception is an INT3 (Breakpoint) exception
    if (pExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT) {

//        PrintRegistersAndStack(pExceptionInfo->ContextRecord);
       LogStackRegisters(pExceptionInfo->ContextRecord);//Логика моегоо хука

        printf("Exception trigerred:0x%llx\n", pExceptionInfo->ContextRecord->Rip);

        std::vector<uint8_t> trampolineBytes;

        void* trampoline = VirtualAlloc(NULL,1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (!trampoline) {
            std::cerr << "Failed to allocate memory for trampoline." << std::endl;
            return EXCEPTION_CONTINUE_SEARCH;
        }

        void* ripAddress = reinterpret_cast<void*>(pExceptionInfo->ContextRecord->Rip);
        auto it = originalInstructions.find(ripAddress);//Берем оригинальные байты которую мы запатчили

        const std::vector<BYTE>& originalBytes = it->second;
        size_t length = originalBytes.size();

        trampolineBytes.insert(trampolineBytes.end(), originalBytes.begin(), originalBytes.end());
        //Записываем их в трамполин
        // Add JMP [RIP+0x0] (6 bytes) for an absolute jump
        trampolineBytes.push_back(0xFF);    // JMP opcode
        trampolineBytes.push_back(0x25);    // RIP-relative addressing mode

        // Reserve space for the 4-byte RIP-relative offset and copy 0x00000000
        uint32_t offset = 0x00000000;
        trampolineBytes.resize(trampolineBytes.size() + sizeof(uint32_t));
        memcpy(&trampolineBytes[trampolineBytes.size() - sizeof(uint32_t)], &offset, sizeof(uint32_t));

        // Reserve space for the 8-byte address and copy the return address
        uintptr_t returnAddress = pExceptionInfo->ContextRecord->Rip + length;
        trampolineBytes.resize(trampolineBytes.size() + sizeof(uintptr_t));
        memcpy(&trampolineBytes[trampolineBytes.size() - sizeof(uintptr_t)], &returnAddress, sizeof(uintptr_t));
            //Делаем прыжок на следующую инструкцию после патча
        // Copy the "stolen bytes" (overwritten instruction) to the trampoline
        memcpy(trampoline, trampolineBytes.data(), trampolineBytes.size());

        pExceptionInfo->ContextRecord->Rip = reinterpret_cast<uintptr_t>(trampoline);

        return EXCEPTION_CONTINUE_EXECUTION;
    }
    return EXCEPTION_CONTINUE_SEARCH;
}
Надеюсь поможет
P.S.Это для x64
 
Начинающий
Статус
Оффлайн
Регистрация
9 Мар 2021
Сообщения
135
Реакции[?]
11
Поинты[?]
6K
Не совсем понял что ты имеешь ввиду все намного проще.Сначала ты берешь ту инструкцию,которую ты заменишь инт3 в твоем случае mov ecx, ebx,копируешь эти байты.Потом в вехе когда срабатывает твой бряк на инт3 пишешь логику свою.После делаешь VirtualAlloc и туда записываешь инструкцию которую ты пропатчил,чтобы она выполнилась + делаешь прыжок на адрес после той инструкции что ты затер,меняешь rip на свой трамполин,выполняется инструкцию которая ты затер и прыгает трамполин на инструкцию после,в итоге лоигка программы сохраняется.Короч смотри код,я как то такую хуйню делал мб разберешь.
C++:
LONG WINAPI VectoredHandler(PEXCEPTION_POINTERS pExceptionInfo) {
    // Check if the exception is an INT3 (Breakpoint) exception
    if (pExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT) {

//        PrintRegistersAndStack(pExceptionInfo->ContextRecord);
       LogStackRegisters(pExceptionInfo->ContextRecord);//Логика моегоо хука

        printf("Exception trigerred:0x%llx\n", pExceptionInfo->ContextRecord->Rip);

        std::vector<uint8_t> trampolineBytes;

        void* trampoline = VirtualAlloc(NULL,1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (!trampoline) {
            std::cerr << "Failed to allocate memory for trampoline." << std::endl;
            return EXCEPTION_CONTINUE_SEARCH;
        }

        void* ripAddress = reinterpret_cast<void*>(pExceptionInfo->ContextRecord->Rip);
        auto it = originalInstructions.find(ripAddress);//Берем оригинальные байты которую мы запатчили

        const std::vector<BYTE>& originalBytes = it->second;
        size_t length = originalBytes.size();

        trampolineBytes.insert(trampolineBytes.end(), originalBytes.begin(), originalBytes.end());
        //Записываем их в трамполин
        // Add JMP [RIP+0x0] (6 bytes) for an absolute jump
        trampolineBytes.push_back(0xFF);    // JMP opcode
        trampolineBytes.push_back(0x25);    // RIP-relative addressing mode

        // Reserve space for the 4-byte RIP-relative offset and copy 0x00000000
        uint32_t offset = 0x00000000;
        trampolineBytes.resize(trampolineBytes.size() + sizeof(uint32_t));
        memcpy(&trampolineBytes[trampolineBytes.size() - sizeof(uint32_t)], &offset, sizeof(uint32_t));

        // Reserve space for the 8-byte address and copy the return address
        uintptr_t returnAddress = pExceptionInfo->ContextRecord->Rip + length;
        trampolineBytes.resize(trampolineBytes.size() + sizeof(uintptr_t));
        memcpy(&trampolineBytes[trampolineBytes.size() - sizeof(uintptr_t)], &returnAddress, sizeof(uintptr_t));
            //Делаем прыжок на следующую инструкцию после патча
        // Copy the "stolen bytes" (overwritten instruction) to the trampoline
        memcpy(trampoline, trampolineBytes.data(), trampolineBytes.size());

        pExceptionInfo->ContextRecord->Rip = reinterpret_cast<uintptr_t>(trampoline);

        return EXCEPTION_CONTINUE_EXECUTION;
    }
    return EXCEPTION_CONTINUE_SEARCH;
}
Надеюсь поможет
P.S.Это для x64
Люблю тебя
 
Сверху Снизу