Ответ 1
В этой памяти нет памяти кучи (см. примечание ниже). Более того, я думаю, что вы не можете изменить разрешение кучи памяти.
В Linux вы можете использовать следующее:
#include <sys/mman.h>
size_t size = 0x1000; // 1 page
// this will be mapped somewhere between /lib/x86_64-linux-gnu/ld-2.15.so
// and stack (see note and memory map below)
void *code = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, -1, 0);
// use `code` to write your instructions
// then store location at which you want to jump to in `fp`
void *fp = ...;
mprotect(code, size, PROT_READ | PROT_EXEC);
// use some inline assembly to jump to fp
Примечание. В Linux память, отображаемая пользователем, находится в отдельной области (что-то вроде 400000000000
и до стека на x86 Linux и, возможно, 7f0000000000
на x64 one). Куча расположена после сегментов ELF программы и до области, доступных для mmap
. Сама куча может быть выделена непосредственно с помощью системного вызова brk
(заменяется на malloc
). См. Этот пример (полученный на моем Ubuntu 12.10 x64):
➜ ~ ps
PID TTY TIME CMD
9429 pts/3 00:00:07 zsh
20069 pts/3 00:00:00 git-credential-
22626 pts/3 00:00:00 ps
➜ ~ cat /proc/9429/maps
00400000-004a2000 r-xp 00000000 08:01 6291468 /bin/zsh5
006a1000-006a2000 r--p 000a1000 08:01 6291468 /bin/zsh5
006a2000-006a8000 rw-p 000a2000 08:01 6291468 /bin/zsh5
006a8000-006bc000 rw-p 00000000 00:00 0
01a51000-01fd8000 rw-p 00000000 00:00 0 [heap]
...
7f6529d61000-7f6529d91000 rw-p 00000000 00:00 0
...
7f652d0d3000-7f652d0d5000 rw-p 00023000 08:01 44833271 /lib/x86_64-linux-gnu/ld-2.15.so
7fffd7c7f000-7fffd7cae000 rw-p 00000000 00:00 0 [stack]
7fffd7dff000-7fffd7e00000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Как вы можете видеть, heap
не является исполняемым (и это правильно), поэтому вы не можете использовать malloc
для получения исполняемой памяти.