Выражение не может быть использовано как функция, функция машинного кода c ++ - PullRequest
0 голосов
/ 08 сентября 2018

Я генерирую машинный код для выполнения переполнения буфера и хотел быстрый и простой способ вставить байт-код в программу и посмотреть, как он работает на моем хост-компьютере.

Я искал способы динамического генерирования функций в C ++ и наткнулся на этот вопрос с этим очень интересным ответом . За это проголосовали совсем немного, и, похоже, никто не оспаривает то, что они сказали.

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

Вот мой код:

int main()
{
    uint8_t machinecode[] = {0x90, 0x0F, 0x01};

    *reinterpret_cast<void**>(&machinecode)();

    return 0;
}

Ответы [ 2 ]

0 голосов
/ 08 сентября 2018

Ответ SkepticalEmpiricist был правильным и решил проблему с компиляцией, поэтому я пометил ее как правильную.

Однако мне нужно было создать функцию для выделения исполняемой памяти с помощью VirtualAlloc:

uint8_t* alloc_executable(uint32_t alloc_size)
{
    if(!alloc_size)
        return nullptr;

    return reinterpret_cast<uint8_t*>(VirtualAlloc(NULL, alloc_size, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE));
}

Моя main функция:

int main()
{
    /*
    * nop - 0x90
    * ret - 0xC3
    */
    uint8_t machinecode[] = {0x90, 0xC3};
    uint32_t machinecode_size = ARRAYSIZE(machinecode);

    uint8_t* exec_mem = alloc_executable(machinecode_size);

    memcpy(exec_mem, bytecode, machinecode_size);

    FlushInstructionCache(GetCurrentProcess(), exec_mem, machinecode_size);

    auto func = reinterpret_cast<void(*)()>(exec_mem);

    func();

    return 0;
}

Процесс возвращает 0 без ошибок.

ТАКЖЕ: Очевидно, что это специфично для Windows. Моя target платформа x64 для Windows 10.

0 голосов
/ 08 сентября 2018

Что касается валидности кода для компиляции, в надежде, что я правильно понимаю ваш вопрос, вам нужно привести к вызываемому элементу, который в данном случае равен void(*)(), а не просто void*, и вам нужен дополнительный набор скобок:

(*reinterpret_cast<void(*)()>(bytecode))();

См. здесь вживую , но я не уверен, что это то, что вы действительно хотите запустить, даже в предоставленном вами контексте.

...