Вопрос

Представьте, что я делаю что-то вроде этого:

void *p = malloc (1000);
*((char*)p) = some_opcode;
*((char*)p+1) = another_opcode; // for the sake of the example: the opcodes are ok

....
etc...

Как я могу определить указатель на функцию для вызова p, как если бы это была функция?(я использую VC ++ 2008 express).

Спасибо

Это было полезно?

Решение

Для комментария не хватило места.Joe_Muc - это правильно.Вы не должны помещать код в память, полученную с помощью malloc или new.Вы столкнетесь с проблемами, если измените свойства страницы страниц, которые выделяет Windows.

Это не проблема, потому что использование VirtualAlloc() и связанных с ним WIn32 API очень просто:позвонить Виртуальный выделяемый ресурс() и установите flProtect Для [PAGE_EXECUTE_READWRITE][2]

Обратите внимание, что вам, вероятно, следует выполнить три выделения: одну защитную страницу, страницы, необходимые для вашего кода, затем еще одну защитную страницу.Это даст вам небольшую защиту от неправильного кода.

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

Далее, Windows X86 ABI (соглашения о вызовах) недостаточно хорошо документированы (я знаю, я смотрел).Есть кое-какая информация здесь, здесь, здесь Лучший способ увидеть, как все работает, - это посмотреть на код, сгенерированный компилятором.Это легко сделать с помощью \FA переключатели (всего их четыре).

Вы можете ознакомиться с 64-разрядными соглашениями о вызовах здесь.

Кроме того, вы все еще можете получить ассемблер макросов Microsoft МАСМ здесь.Я рекомендую написать ваш машинный код в MASM и посмотреть на его выходные данные, а затем попросить ваш генератор машинного кода выполнить аналогичные действия.

Данные Intel и AMD's руководства по процессорам являются хорошими справочниками - возьмите их, если у вас их нет.

Другие советы

На самом деле, маллок, вероятно, не будет это сокращать.В Windows вам, вероятно, нужно вызвать что-то вроде [VirtualAlloc](http://msdn.microsoft.com/en-us/library/aa366887 (ПРОТИВ 85).aspx) для того, чтобы получить исполняемую страницу памяти.

Начиная с малого:

void main(void)
{
    char* p = (char*)VirtualAlloc(NULL, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    p[0] = (char)0xC3;  // ret

    typedef void (*functype)();
    functype func = (functype)p;
    (*func)();
}

Следующий шаг для корректной работы с вашим кодом - сохранить регистр EBP.Это оставлено в качестве упражнения.:-)

Написав это, я запустил его с помощью malloc, и это тоже сработало.Это может быть связано с тем, что я использую учетную запись администратора на Windows 2000 Server.Другим версиям Windows может действительно потребоваться вызов VirtualAlloc.Кто знает.

Если у вас есть правильные коды операций на месте, вызов может быть таким же простым, как приведение к указателю функции и вызов ее.

typedef void (*voidFunc)();

char *p = malloc (1000);
p[0] = some_opcode;
p[1] = another_opcode; // for the sake of the example: the opcodes are ok
p[n] = // return opcode...

((voidFunc)p)();

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

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

Если вам нужно пометить страницу как исполняемую в системах POSIX (Linux, BSD и т.д.), ознакомьтесь с функция mmap(2).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top