вызывающий код, хранящийся в куче из vc++
-
29-08-2019 - |
Вопрос
Представьте, что я делаю что-то вроде этого:
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).