Re: LD_PRELOAD potential problems

From: Phillip Vandry (vandryat_private)
Date: Fri May 14 1999 - 08:58:34 PDT

  • Next message: Darren J Moffat - Enterprise Services OS Product Support Group: "Re: LD_PRELOAD potential problems"

    You should note of course that LD_PRELOAD will not work for any setuid
    or setgid binary. Users thus cannot do anything they wouldn't have been
    able to do otherwise by modifying code or compiling their own using this
    trick.
    
    I agree that LD_PRELOAD is very easy to use, but vendors shipping
    statically linked binaries is a big inconvenience, and I don't believe
    they should do it on account of the LD_PRELOAD hack. It's just not
    worth it.
    
    Here are some of the disadvantages of a statically linked binary:
    
    - It's big on disk. Not only that but if there are multiple binaries that
    share code (and what two binaries don't share at least code from libc?),
    the size of this code is multiplied by the number of binaries.
    - It's big in memory. Same argument, but this time regarding code that it
    duplicated in memory (shared libraries are mapped only once)
    - It's compatible with only one version of the operating system. (libc's
    kernel interfaces are always free to change)
    - The binary won't benefit from bugfixes in the vendor's system libraries.
    - In many cases, it may not even be possible. For example, in Solaris,
    using the name service switch REQUIRES a dynamically linked binary, and
    keep in mind that you need the name service switch for all getXXXbyYYY()
    functions.
    
    In fact, it's not hard using gdb and breakpoints to override any desired
    function in statically linked binaries too. (Harder if it's stripped,
    admitedly).
    
    If you must, extract those functions which you consider critical from
    libc.a, and link those into the main binary (or even use syscall()
    directly, but please link your stuff dynamically!
    
    I assume that in your original message you are referring to an example of
    using time() for a task such as forcing a demo copy of software to
    expire (and overriding time() to fool the scheme). Similar situations
    occur with binaries that check a machine's hostid or IP address to
    verify license to use it.
    
    In all these cases, if you are writing software that does this, and you
    want to protect yourself from people bypassing your tests, you definately
    need to contort your code a bit. If there's a function called
    check_license() and a user can overwrite the beginning of this function
    with code for "return 0" and that totally bypasses all your checks, then
    you got fooled pretty easily. I suggest the following:
    
    - Check this inside main() or some other big long function to discourage
    disassembly/decompilation.
    - Arrange that it is not possible to bypass your checks by nopping out a
    single function/function call
    - Don't print a message immediately after you do the checks. The user will
    be able to set a breakpoint at the place where you print your message
    (since you ultimately have to make a system call to print text) and know
    pretty much what section of your code is making the checks.
    
    Tangeant: On Solaris, you can override the system call of your choice
    by making a kernel module that goes in the kernel/sys subdirectory. I
    do not have documentation as to how that's done, but this method of
    overriding a system call is virtually undetectable by user level
    software. On OSes where you have source, of course, you're free to
    modify system calls with even more ease!
    
    -Phil
    
    > Many UNIX systems allow you to "pre-load" shared libraries by setting
    > an environment variable LD_PRELOAD.  This allows you to do interesting
    > things like replace standard C library functions or even the C
    > interfaces to system calls with your own functions.
    >
    > I recently ran across a piece of software which depended upon knowing
    > the time reasonably accurately.  By replacing the time(2) UNIX system
    > call with my own function, I was able to fool the program and get it
    > to misbehave, without the inconvenience of actually changing the system
    > time or even requiring root privileges.
    >
    > If you are writing programs which depend on C library functions or
    > UNIX system calls for secure operation, please distribute only
    > statically-linked versions, as the effort to fool statically-linked
    > binaries is a lot higher than a simple LD_PRELOAD spoof.
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:45:55 PDT