Function pointer dereference security

Discussion in 'C Programming' started by Nyang A. Phra, Nov 11, 2007.

  1. I have following code:

    union Pointer {
    void *objp;
    void (*funcp)();
    };

    Pointer p = ... ;

    ....

    p();

    ---

    Now, supposing that p were actually not a genuine function pointer but
    arbitrary or malicious data, could such code be theoretically
    exploited to hijack program execution, or does the C runtime check
    that a function call is made to a legitimate address?
     
    Nyang A. Phra, Nov 11, 2007
    #1
    1. Advertising

  2. Nyang A. Phra said:

    <snip>

    > p();
    >
    > ---
    >
    > Now, supposing that p were actually not a genuine function pointer


    ....then it would be the height of folly to treat it as if it were.

    --
    Richard Heathfield <http://www.cpax.org.uk>
    Email: -http://www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999
     
    Richard Heathfield, Nov 11, 2007
    #2
    1. Advertising

  3. > > Now, supposing that p were actually not a genuine function pointer
    >
    > ...then it would be the height of folly to treat it as if it were.


    Yeah kinda thought so, but what are the consequences? Does the runtime
    catch such errors and just die or could in theory anomalous program
    execution follow?

    Nyang
     
    Nyang A. Phra, Nov 11, 2007
    #3
  4. >I have following code:
    >
    >union Pointer {
    > void *objp;
    > void (*funcp)();
    >};
    >
    >Pointer p = ... ;
    >
    >...
    >
    >p();
    >
    >---
    >
    >Now, supposing that p were actually not a genuine function pointer but
    >arbitrary or malicious data, could such code be theoretically
    >exploited to hijack program execution, or does the C runtime check
    >that a function call is made to a legitimate address?


    Assuming that the pointer is to memory that is not mapped into the
    process or simply doesn't exist, your program will probably just
    crash. Some operating systems vary the load address of a program
    randomly each time it is executed so it's harder to guess what
    addresses will be available.

    Assuming that the pointer is to a buffer that the attacker managed
    to fill with code of his own choosing, possibly by buffer overflow,
    you're in deep, deep trouble. (Think 'virus' and 'botnet'). The
    attacker can do anything your program could. If your program was
    running with administrative privileges, you're really screwed.
    Buffer overflow is a technique used by a lot of viruses.

    Some operating systems have provisions that you cannot execute
    memory that is writable, making it harder to actually execute code
    by writing over function return addresses when overflowing an auto
    array. This isn't foolproof, but it does help. The program just
    quickly crashes.

    Assuming that the pointer is redirected from the expected routine to
    an existing routine in the C library that deletes files, there's
    probably not much that can be done, since it *is* legitimate code,
    and the function arguments might be legitimate also.
     
    Gordon Burditt, Nov 11, 2007
    #4
  5. Nyang A. Phra

    Ben Pfaff Guest

    "Nyang A. Phra" <> writes:

    >> > Now, supposing that p were actually not a genuine function pointer

    >>
    >> ...then it would be the height of folly to treat it as if it were.

    >
    > Yeah kinda thought so, but what are the consequences? Does the runtime
    > catch such errors and just die or could in theory anomalous program
    > execution follow?


    The runtime is permitted, but not obligated, to catch such
    errors. Most don't, so that anomalous program execution is
    likely.
    --
    "Structure padding is the use of extraneous materials to
    enhance the shape of a struct and make it more attractive to
    members of the opposite struct. (See also "struct silicone.")"
    --Eric Sosman
     
    Ben Pfaff, Nov 11, 2007
    #5
  6. On Nov 11, 7:37 am, (Gordon Burditt) wrote:
    > >I have following code:

    >
    > >union Pointer {
    > > void *objp;
    > > void (*funcp)();
    > >};

    >
    > >Pointer p = ... ;

    >
    > >...

    >
    > >p();

    >
    > >---

    >
    > >Now, supposing that p were actually not a genuine function pointer but
    > >arbitrary or malicious data, could such code be theoretically
    > >exploited to hijack program execution, or does the C runtime check
    > >that a function call is made to a legitimate address?

    >
    > Assuming that the pointer is to memory that is not mapped into the
    > process or simply doesn't exist, your program will probably just
    > crash. Some operating systems vary the load address of a program
    > randomly each time it is executed so it's harder to guess what
    > addresses will be available.
    >
    > Assuming that the pointer is to a buffer that the attacker managed
    > to fill with code of his own choosing, possibly by buffer overflow,
    > you're in deep, deep trouble. (Think 'virus' and 'botnet'). The
    > attacker can do anything your program could. If your program was
    > running with administrative privileges, you're really screwed.
    > Buffer overflow is a technique used by a lot of viruses.
    >
    > Some operating systems have provisions that you cannot execute
    > memory that is writable, making it harder to actually execute code
    > by writing over function return addresses when overflowing an auto
    > array. This isn't foolproof, but it does help. The program just
    > quickly crashes.
    >
    > Assuming that the pointer is redirected from the expected routine to
    > an existing routine in the C library that deletes files, there's
    > probably not much that can be done, since it *is* legitimate code,
    > and the function arguments might be legitimate also.


    Yeah makes sense. Will avoid the construction. Thanks.
     
    Nyang A. Phra, Nov 11, 2007
    #6
  7. Nyang A. Phra said:

    >> > Now, supposing that p were actually not a genuine function pointer

    >>
    >> ...then it would be the height of folly to treat it as if it were.

    >
    > Yeah kinda thought so, but what are the consequences?


    If a function pointer does not point at a function, then the consequences
    of dereferencing that pointer are undefined (which means anything may
    happen, including Very Bad Things).

    > Does the runtime
    > catch such errors and just die or could in theory anomalous program
    > execution follow?


    Both are possibilities.

    --
    Richard Heathfield <http://www.cpax.org.uk>
    Email: -http://www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999
     
    Richard Heathfield, Nov 11, 2007
    #7
  8. "Nyang A. Phra" <> writes:
    > I have following code:
    >
    > union Pointer {
    > void *objp;
    > void (*funcp)();
    > };
    >
    > Pointer p = ... ;
    >
    > ...
    >
    > p();

    [...]

    A few things about your code, not addressing your actual question
    (which has been answered by others).

    Given a declaration of type "union Pointer", you can't refer to the
    type as just "Pointer" (unless you've also declared a typedef).
    <OT>C++ lets you do this; C doesn't.<OT>

    If p is of type union Pointer, then p() is not the way to call the
    function, since p is not of function or pointer-to-function type.
    You'd need to use "p.funcp()".

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Looking for software development work in the San Diego area.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Nov 11, 2007
    #8
  9. Nyang A. Phra

    santosh Guest

    On Sunday 11 Nov 2007 5:16 am Nyang A. Phra <> wrote in
    article <>:

    >> > Now, supposing that p were actually not a genuine function pointer

    >>
    >> ...then it would be the height of folly to treat it as if it were.

    >
    > Yeah kinda thought so, but what are the consequences? Does the runtime
    > catch such errors and just die or could in theory anomalous program
    > execution follow?


    The runtime is not required to catch such conditions, and it typically
    doesn't. In most memory protected architectures the operating system
    will terminate the application for invalid/illegal instruction
    sequences, as soon as your program tries to execute data. Before that
    happens you may very likely trash your own data and program state. With
    some techniques like execute disable functionality the system may
    terminate your application even before it can actually execute any
    data.

    Note however that all this is highly system specific and the C Standard,
    in the interests of wide applicability, has nothing to say upon this
    other than that you have invoked Undefined Behaviour.
     
    santosh, Nov 11, 2007
    #9
  10. Nyang A. Phra

    Eric Sosman Guest

    Nyang A. Phra wrote:
    > I have following code:
    >
    > union Pointer {
    > void *objp;
    > void (*funcp)();
    > };
    >
    > Pointer p = ... ;
    >
    > ...
    >
    > p();


    The compiler must issue a diagnostic. The () function-call
    operator must follow an expression that yields a function pointer,
    and the expression `p' yields a union pointer.

    > Now, supposing that p were actually not a genuine function pointer but
    > arbitrary or malicious data, could such code be theoretically
    > exploited to hijack program execution, or does the C runtime check
    > that a function call is made to a legitimate address?


    Let's assume you wrote `p->funcp()' instead. Then it is your
    responsibility to see to it that `p->funcp' holds a valid function
    pointer value. If it does not, the behavior is undefined. (The
    fact that the value is stored in a union isn't important; you need
    to ensure its validity no matter where it resides.)

    Some C implementations may perform some kinds of validity
    check on function calls; if they do, the nature and thoroughness
    of the checking are unspecified, as are the consequences of
    failing the check. Others may just take you at your word and
    try to call the "function" at J. Random Location; again, the
    consequences are unspecified.

    Even if run-time checking verifies that the call is to a
    valid function, it's hard to imagine that it could ensure that
    the call is to the "intended" function. If the Evil Genius gets
    your program to call cos() when it thinks it's calling sqrt(),
    a run-time checking scheme is quite likely to let the E.G. get
    away with it. Mwaah-hah-hahaha!

    --
    Eric Sosman
    lid
     
    Eric Sosman, Nov 11, 2007
    #10
  11. Nyang A. Phra:

    > I have following code:
    >
    > union Pointer {
    > void *objp;
    > void (*funcp)();
    > };
    >
    > Pointer p
    > ...
    >
    > p();



    p.funcp();


    > ---
    >
    > Now, supposing that p were actually not a genuine function pointer but
    > arbitrary or malicious data, could such code be theoretically exploited
    > to hijack program execution, or does the C runtime check that a function
    > call is made to a legitimate address?



    If the hacker is already able to read and write from your RAM, then
    there's 101 ways in which they can make your computer do stuff. If I
    myself wanted to execute code on your machine, I'd simply copy my machine
    code into your RAM and then set the processor's program counter to the
    address of my machine code. Or, as you suggested, I could look for code
    in memory that executes a function, and then substitute the address of my
    own function. Having access to someone's RAM is like being in their
    house, knowing where they keep the car keys, knowing the code for the
    alarm. If someone has access to your RAM, then the shit has already hit
    the fan, and so it doesn't matter in the slightest what kind of other
    security holes you have.

    Function pointers are _the_ way in which we call functions, even if it
    doesn't seem obvious. For instance, given the statement:

    Func(5);

    "Func" is a pointer to a function, (or perhaps you can view it as a
    function which has "decayed" to a pointer to itself). This idea of a
    function's name being a pointer to the function is observable from:


    (***************************Func)(5);

    Avoiding using function pointers in your code to evade hackers would be
    like unplugging all the appliances in your house so nobody can steal you
    electricity:

    1) It's not gonna work
    2) You're depriving yourself of stuff

    If you don't want to be hacked, then put a password on your router, use
    WPA for your wireless, and make sure you haven't got any open ports --
    that'd be a start in anyway.

    --
    Tomás Ó hÉilidhe
     
    =?iso-8859-1?b?VG9t4XMg0yBoyWlsaWRoZQ==?=, Nov 11, 2007
    #11
  12. On Sat, 10 Nov 2007 20:56:19 -0800, "Nyang A. Phra" <>
    wrote:

    >I have following code:
    >
    >union Pointer {
    > void *objp;
    > void (*funcp)();
    >};
    >
    >Pointer p = ... ;
    >
    >...
    >
    >p();
    >
    >---
    >
    >Now, supposing that p were actually not a genuine function pointer but
    >arbitrary or malicious data, could such code be theoretically
    >exploited to hijack program execution, or does the C runtime check
    >that a function call is made to a legitimate address?


    Are you talking about p or p.funcp. The executable statement above is
    a syntax error that requires a diagnostic. Even though p and p.funcp
    are guaranteed to occupy the same address (or at least start at the
    same address), they do so as different types and are not
    interchangeable. p is a union. You cannot apply the "function
    operator", (), to it. p.funcp is a function pointer and p.funcp() is
    syntactically correct.

    If p.funcp has not been assigned the address of a function, then its
    value is indeterminate. Any attempt to dereference it invokes
    undefined behavior. There is no requirement in the standard for the
    code generated by such a statement to check to insure the address is
    valid. While the compilers I am experienced with do not generate code
    to perform this check, there is no prohibition against it either. But
    if a compiler were to generate such code, it would be above and beyond
    the requirements of the standard. Depending on such behavior would
    render your code extremely unportable.

    Once you have invoked undefined behavior, anything your operating
    system lets you get away with is possible. Hijacking your system is
    one possibility; formatting your hard disk is another. With the
    proper hardware add-ons, it could even route household voltage to your
    chair. One of the worst manifestations of undefined behavior is to
    appear to work correctly until you are demonstrating the program to
    your boss or an important client.


    Remove del for email
     
    Barry Schwarz, Nov 12, 2007
    #12
  13. Nyang A. Phra

    Richard Bos Guest

    Eric Sosman <> wrote:

    > Nyang A. Phra wrote:
    > > I have following code:
    > >
    > > union Pointer {
    > > void *objp;
    > > void (*funcp)();
    > > };
    > >
    > > Pointer p = ... ;
    > >
    > > ...
    > >
    > > p();

    >
    > The compiler must issue a diagnostic. The () function-call
    > operator must follow an expression that yields a function pointer,
    > and the expression `p' yields a union pointer.
    >
    > > Now, supposing that p were actually not a genuine function pointer but
    > > arbitrary or malicious data, could such code be theoretically
    > > exploited to hijack program execution, or does the C runtime check
    > > that a function call is made to a legitimate address?

    >
    > Let's assume you wrote `p->funcp()' instead. Then it is your
    > responsibility to see to it that `p->funcp' holds a valid function
    > pointer value. If it does not, the behavior is undefined. (The
    > fact that the value is stored in a union isn't important; you need
    > to ensure its validity no matter where it resides.)
    >
    > Some C implementations may perform some kinds of validity
    > check on function calls; if they do, the nature and thoroughness
    > of the checking are unspecified, as are the consequences of
    > failing the check. Others may just take you at your word and
    > try to call the "function" at J. Random Location; again, the
    > consequences are unspecified.


    Of course, the real question in all of this is: why _would_ you call
    through a pointer which might contain random data? _You_ control your
    pointers, nobody else. If you make sure that you only call a pointer
    when you already know that it points at one valid function or another
    (because, of course, you have assigned that function's address to this
    pointer yourself), there is no need for the implementation to even try
    to do so.

    Richard
     
    Richard Bos, Nov 14, 2007
    #13
  14. On Sat, 10 Nov 2007 20:56:19 -0800, "Nyang A. Phra" <>
    wrote:


    >I have following code:
    >
    >union Pointer {
    > void *objp;
    > void (*funcp)();
    >};
    >
    >Pointer p = ... ;
    >
    >...
    >
    >p();


    p.funcp();

    A perfectly good way to have self-modifying code, or execute loaded or
    transferred snippets of machine code. Or, with the converse, to dump the
    machine code of a function (for use later?).

    A perfectly horrid way of writing safe and maintainable code, of course.


    --
    #include <standard.disclaimer>
    _
    Kevin D Quitt USA 91387-4454 96.37% of all statistics are made up
     
    Kevin D. Quitt, Dec 20, 2007
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Denis Palmeiro

    NULL Pointer Dereference

    Denis Palmeiro, Jul 8, 2003, in forum: C Programming
    Replies:
    10
    Views:
    684
    Shill
    Jul 16, 2003
  2. Replies:
    9
    Views:
    565
    Bo Persson
    Feb 11, 2006
  3. somenath

    pointer dereference

    somenath, Jul 12, 2007, in forum: C Programming
    Replies:
    34
    Views:
    947
    Anurag
    Jul 18, 2007
  4. somenath

    pointer dereference

    somenath, Aug 9, 2007, in forum: C Programming
    Replies:
    12
    Views:
    691
    Martin Ambuhl
    Aug 10, 2007
  5. Nyang A. Phra

    Function pointer dereference security

    Nyang A. Phra, Nov 11, 2007, in forum: C Programming
    Replies:
    0
    Views:
    307
    Nyang A. Phra
    Nov 11, 2007
Loading...

Share This Page