oss-sec mailing list archives

Re: PoC: Function Pointer Protection in C Programs


From: Hannes Frederic Sowa <hannes () stressinduktion org>
Date: Wed, 21 Aug 2013 23:20:02 +0200

Hi!

On Wed, Aug 21, 2013 at 04:43:13PM +0200, Stephen Röttger wrote:
Approach:
The basic idea of the thesis is to record all addresses that are
assigned to a function pointer variable at some place in the program (or
in one of the shared libraries) and if a function pointer is called,
verify that the address has been recorded previously. Thus, if an
attacker overwrites the fp variable with either the address of system()
or of a stack pivoting gadget, the fp call will fail, since these
adresses have never been assigned to a function pointer in the program.
The security of the approach relies on the assumption that no function
that can be abused for malicious purposes is ever assigned to a function
pointer, but this requirement will be weakened under future work.

How this works:
The compiler, GCC in my PoC, will register all assignments of function
pointer variables in the source code and will create a global variable
for the assigned function, which is initialized to the function's
address. Then, it replaces the address of the function in the assignment
with the address of the newly created variable:
    fp f = &printf;
becomes:
  printf_var = &printf;
    ...
    fp f = &printf_var;
Further, a global constructor is created that is run before the main
function of the program or before the shared library is loaded. This
constructor allocates a memory area where it stores the address of each
fp address previously registered. The created global variable is then
overwritten to point to the new memory area instead. Finally, the memory
area is mapped read only. Also, the variable where the address of this
area is stored has to be in read only memory as well to prevent
malicious overwrites. Putting it all together, the memory layout looks
like this:
                                    <read only>
 +-------+    +------------+    +------------------+    +----------+
 | fp f  | -> | printf_var | -> | protected memory | -> | printf() |
 +-------+    +------------+    +------------------+    +----------+
Additional instructions are emitted by the compiler before function
pointer calls. They will verify that the global variable (printf_var)
points to the protected memory region, from which it extracts the real
function pointer to be called. If an attacker is able to overwrite
either the function pointer or the global variable, he will only be able
to execute functions contained in the protected memory area (which he
can't overwrite since it is mapped read only during normal execution).

Thanks for doing research in this area! :)

Your approach seems to have some slight similarities with -fvtable-verify:
<http://gcc.gnu.org/ml/gcc-patches/2012-11/txt00001.txt>

Maybe some code sharing could be achieved?

Greetings,

  Hannes


Current thread: