When reading the kernel code, it is understood that the kernel distinguishes the permissions of a page by using the flag bit _page_read,_page_write,_page_execute in the page table entry.
The maximum difference between the address space code segments, data segments, heaps, and stacks in the kernel is also the difference between the permissions, and the system call Mprotect happens to be used to change the permissions of the memory pages.
Can the array on the stack be modified by Mprotect to execute the permission, and then copy the function contents to the array execution? Worth a try:
1#include <stdio.h>2#include <stdlib.h>3#include <sys/mman.h>4#include <sys/types.h>5#include <string.h>6#include <errno.h>7#include <unistd.h>8 9 intM_add (inti)Ten { One returni+Ten; A } - - intShow_map () the { - Charcommand[ the]; -sprintf (Command,"Cat/proc/%d/maps", Getpid ()); - System (command); + } - + intMain () A { at int(*func_p) (int); - intsize; - intret; - Charm[ +]; -Size = (Char*) Show_map-(Char*) M_add; -printf"size =%d\n", size); inFunc_p =m; - toret = Mprotect ((void*)((Long) func_p& (~0XFFFUL)),4096, prot_read| prot_write|prot_exec); + if(Ret <0){ -Perror ("Mprotect:"); the exit (ret); * } $ Panax Notoginseng memcpy (func_p,m_add,size); - theprintf"m_add () =%d\n", M_add ( -)); +printf"func_p (+) =%d\n", Func_p ( the)); Aprintf"M_add =%p, func_p =%p\n", M_add, func_p); the Show_map (); + return 0; -}
Execution Result:
Size = theM_add ( -) = thefunc_p ( the) = theM_add=0x561528db08c0, func_p =0x7ffd4c19e300561528db0000-561528db1000 R-XP00000000Fe on 477434/home/test/a. out561528fb0000-561528fb1000 r--p00000000Fe on 477434/home/test/a. out561528fb1000-561528fb2000 rw-p00001000Fe on 477434/home/test/a. out5615298e7000-561529908000Rw-p00000000 xx:xx 0[heap]7fcc3280c000-7fcc329a1000 R-XP00000000Fe on 329984/lib/x86_64-linux-gnu/libc-2.24. so7fcc329a1000-7fcc32ba1000---P00195000Fe on 329984/lib/x86_64-linux-gnu/libc-2.24. so7fcc32ba1000-7fcc32ba5000 r--p00195000Fe on 329984/lib/x86_64-linux-gnu/libc-2.24. so7fcc32ba5000-7fcc32ba7000 rw-p00199000Fe on 329984/lib/x86_64-linux-gnu/libc-2.24. so7fcc32ba7000-7fcc32bab000 rw-p00000000 xx:xx 07fcc32bab000-7fcc32bce000 R-XP00000000Fe on 329980/lib/x86_64-linux-gnu/ld-2.24. so7fcc32dbc000-7fcc32dbe000 rw-p00000000 xx:xx 07fcc32dcb000-7fcc32dce000 rw-p00000000 xx:xx 07fcc32dce000-7fcc32dcf000 r--p00023000ge[ on 329980/lib/x86_64-linux-gnu/ld-2.24. so7fcc32dcf000-7fcc32dd0000 rw-p00024000ge[ on 329980/lib/x86_64-linux-gnu/ld-2.24. so7fcc32dd0000-7fcc32dd1000 rw-p00000000 xx:xx 07ffd4c17e000-7ffd4c19e000 rw-p00000000 xx:xx 07ffd4c19e000-7ffd4c19f000 RWXP00000000 xx:xx 0[stack]7ffd4c1e1000-7ffd4c1e3000 r--p00000000 xx:xx 0[vvar]7ffd4c1e3000-7ffd4c1e5000 R-XP00000000 xx:xx 0[vdso]ffffffffff600000-ffffffffff601000 R-XP00000000 xx:xx 0[Vsyscall]
As you can see, the function pointer func_p actually points to the address of the char array m[1000], whose value is 0x7ffd4c19e300 is indeed located above the stack 7ffd4c19e000-7ffd4c19f000 , And its successful execution of +10 of the operation, returned the correct result.
This example does not actually apply the value, once the function has the library function the call, generally will have the error.
But it shows that from the C language down, stacks, heaps, data segments, code snippets are all memory, as long as the configuration is the same, there is no essential difference between each other.
The C language is the language in which memory is manipulated, and after it has been encapsulated by the operating system, it sees no difference in memory. All data types, you can interpret them as grammatical sugars.
So what's the difference between it and the assembly? The assembler is the language that operates the CPU and register, can access the CPU-specific instructions, can access a particular register, and the C language is originally intended to be the difference between the flattening architecture.
C-language Fancy gameplay copy function to array execution (requires Mprotect)