C function pointer: Can I jump to heap memory assembler code?

久未见 提交于 2021-02-06 08:48:55

问题


Is it possible to create a dynamic function by allocating dynamic memory, writing some assembler opcodes to it (like 0x90 0xC2 for NOP RET), creating a function pointer which points to that dynamic memory and execute it like a regular function from within a C program?

Target should be a regular x86 Linux system.


回答1:


This memory doesn't have be heap memory (see note below). Moreover, I'd think that you can't change execution permission of heap memory.

On Linux, You can use the following:

#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

Note: On Linux, memory mapped by user is located in separate region (something like from 400000000000 and up to stack on x86 Linux, and probably 7f0000000000 on x64 one). Heap is located after ELF segments of the program and before region, available for mmap. Heap itself can be allocated directly using brk system call (superseded by malloc by now). See this example (got on my 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]

As you can see, heap is not executable (and is rightly so), so you can't use malloc to get executable memory.




回答2:


In general yes, but you need to go into system-specific things to do so. That's not very surprising I guess, since the fact that you're going to use binary assembly instructions is making it pretty clear.

You need to be aware that you can't assume that heap memory on modern operating systems is executable, so you might need to jump through some hoops to make it so. You can't just call malloc() and assume the returned pointer points to memory where you can execute code.

In Linux, you can use mmap() to ask the kernel to map you some memory, and by specifying the PROT_EXEC flag in the call you can ask it to make the memory executable too.




回答3:


Many systems have for a long time had flags on virtual memory pages that tells if they can contain executable code or not. Memory allocated of the heap most likely won't have this "executable" flag set. So no you can not directly do that.

If you want to do that you have to use OS specific functions, and may have to run the program as "administrator" or "root" to be able to do it, though it doesn't seem to be necessary.



来源:https://stackoverflow.com/questions/19634587/c-function-pointer-can-i-jump-to-heap-memory-assembler-code

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!