Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The location in memory of a function is computed at compile time and then stored for later use by the program. If an attacker can overwrite certain memory containing function pointers, they may  they may be able to execute arbitrary code. To mitigate the effects of such attacks, pointers to functions may can be encrypted at run time based on some runtime on the basis of some characteristics of the execution process such so that only a running process will be able to decode them.  This is only required for stored function pointers stored to writable memory, including the stack.  The Microsoft SDL [Microsoft 2012] recommends encoding long-lived pointers in your code.

Noncompliant Code Example

This noncompliant code example assigns the address of the printf() function to the log_fn function pointer, which can be allocated in the stack or data segment:

Code Block
bgColor#FFCCCC
langc

int (*log_fn)(const char *, ...) = printf;
/* ... */
log_fn("foo");

If a vulnerability exists in this program that allows an attacker can launch some kind of overwrite attack to overwrite the log_fn function pointer, such as a buffer overflow , they or arbitrary memory write, the attacker may be able to overwrite the value of printf with the location of an arbitrary function.

Compliant Solution (Windows)

Microsoft Windows provides the EncodePointer() and DecodePointer() function functions that encrypt and decrypt pointers using a secret that is unique to the given process.:

Code Block
bgColor#ccccff
langc
#include <Windows.h>
 
void 
int (*log_fn)(const char *, ...) = EncodePointer(printf);
/* ... */
DecodePointerint (log_*fn)("foo");

Compliant Solution (C1X)

Two similar functions are under consideration for the new C Standard, tentatively dubbed C1X.

C1X defines encode_pointer() to have the following behavior:

The encode_pointer function shall perform a transformation on the pf argument, such that the decode_pointer function shall reverse that transformation. Thus, for any pointer to function pfun,

Code Block
decode_pointer(encode_pointer( (void(*)()) pfun )

when converted to the type of pfun, shall equal pfun.

Code Block
bgColor#ccccff

int (*log_fnconst char *, ...) = (int (*)(const char *, ...) = encode_pointer(printf))DecodePointer(log_fn);
/* ... */
decode_pointer(log_fn)("foo");

Note that DecodePointer() does not return success or failure.  If an attacker has overwritten the pointer contained in log_fn, the pointer returned will be invalid and cause your application to crash.  However, this is preferable to giving an attacker the ability to execute arbitrary code. 

Risk Assessment

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

MSC16WIN04-C

high High

unlikely Unlikely

low Low

P9

L2

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

References

Wiki Markup
\[[MSDN|AA. C References#MSDN]\] [{{EncodePointer()}}|http://msdn.microsoft.com/en-us/library/bb432254(VS.85).aspx], [{{DecodePointer()}}|http://msdn.microsoft.com/en-us/library/bb432242(VS.85).aspx]

Related Guidelines

SEI CERT C++ Coding StandardVOID MSC16-CPP. Consider encrypting function pointers
MITRE CWECWE-311, Missing encryption of sensitive data
CWE-319, Cleartext Transmission of Sensitive Information

Bibliography

[MSDN]EncodePointer()
DecodePointer()

Microsoft Corporation 2012

Microsoft Security Development Lifecycle (SDL) – version 5.2Phase 3: Implementation

 

...

Image Added Image Added Image Removed      49. Miscellaneous (MSC)       Image Modified