Preventing /*exploitation with*/ rebasing

From: Riley Hassell (rhassellat_private)
Date: Wed Feb 05 2003 - 17:42:13 PST

  • Next message: John Howie: "RE: Microsoft Security Bulletin MS03-005: Unchecked Buffer in Windows Redirector Could Allow Privilege Elevation (810577)"

    So the course of this talk with most likely go into generating a totally
    dynamic address space and once again, end in another theoretical solution,
    to an overly complex problem.
    
    Defeating Rebasing
    -------------------------------------
    
    Many operating systems with fault handling features and refined
    multitasking, reference address spaces with segments to permit these
    features and aid general performance. The majority of this behavior can be
    studied by following process creation and task switching. Start from the
    user API and step through until the entry point of the executable is
    reached.
    
    TEB: Thread Environment Block
    TIB: Thread Information Block
    PEB: Process Environment Block
    
    The TEB/TIB fs:[] segment references originated in the OS2 days and have
    since passed down into 9x client systems, and of course, Windows NT. During
    the process creation the PEB and TIB are initialized into the new virt and
    can be referenced by the fs segment. Modifying the address space referenced
    by fs and how fs is setup is possible... but by the time you're done you're
    designing a new operating system.
    
    As Ryan might say... It's all data ;) The data referenced in this delta can
    be referenced during a ret. You just need to find a set of bytes that forms
    the needed instruction. You may be able to modify this arena in a way that
    you can insert your own instructions. Maybe some of the TLS storage can be
    controlled by supplying malformed sizes in your exploit session... ;)
    
    Note: PEB locking pointers can be overwritten with format bugs and control
    structure based heap overflows.
    
    7FFDF000  00010000
    7FFDF004  FFFFFFFF
    7FFDF008  01000000  <- Executable image base ;)
    7FFDF00C  00071E90
    7FFDF010  00020000
    7FFDF014  00000000
    7FFDF018  00070000
    7FFDF01C  77FCF170  <- PEB fast Lock entry point
    7FFDF020  77F8313C  <- PEB lock entry point
    7FFDF024  77F8316D  <- PEB unlock entry point
    
    Brett Moore wrote me several months ago with a very interesting exploit
    concept using multiple writes. The first write you insert your needed
    instruction into writeable memory somewhere. The second write you overwrite
    some writeable entry point or hook, with the address of the inserted
    instruction.
    
    There's not much out there if you're interested in learning about the TIB
    and the PEB. If you really want to understand these structures and general
    loading behavior, learn Polish and Russian, then hit up some VX'er archives.
    If you end up talking to any of them, tell them that somebody is trying to
    stop exploits by rebasing dll's :)
    
    Rebasing... There's a reason why relocation sections exist. While doing your
    own relocations is possible, the design of such a system is extremely, and
    I'll say again, extremely complex. Just differentiating all the instructions
    from data is a fairly painful process. Maybe the ETCH guys did this at one
    point but as far as I know this has been a big hurdle in image modifcation
    for quite some time.
    
    Michal Zalewski provided some great examples of issue's you'll run into:
    
    MZ> Also, what if I wanted to pass a value 4325404 (0x42001c) to this
    MZ> function, and it is not a pointer, only looks this way? For example,some
    MZ> FOO_ASYNC flag is defined as 0x400000, FOO_LOCK as 0x020000, and
    voila,OR
    MZ> them and you have "a pointer".
    MZ> In other cases, say, with register calls, it is getting even nastier,
    MZ> because even if, one way or another, you managed to find out how every
    MZ> single function is going to use its parameters (not likely), register
    MZ> calls are still black magic.
    
    GetProcAddress ACL's...
    
    >
    > It is possible to intercept every call to GetProcAddress and determine
    > whether or not the call should be authorized based on a predetermined list
    > of known valid callers (runtime call stack analysis).
    
    Simply rewrite a micro GetProcAddress. GetProcAddress is basically an
    overstuffed RVA engine. This is defeated by "The payload brings the tools
    concept". Most userland hooking schemes can also easily be bypassed by using
    direct gates "Ex: Interupts Gates". You could also intercept a thread that
    has the neccesary privelege by snagging a hook in it's path.
    
    > This list of authorized callers must be constructed through the use of
    forensic profiling
    > tools in the case of other people's binaries, but can be constructed with
    > the help of additional API calls in the case of one's own code. Call a
    > profiling/tracing API before calling GetProcAddress. After compilation but
    > before deployment to production boxes you simply execute the code in
    profile
    > mode to generate a list of authorized callers. This list is then
    configured
    > as a static security setting adhered to by the security layer that sits
    > between GetProcAddress and the rest of the virtual world.
    
    Who's an authorized caller?
    
    Someone who has a "safe" caller address on the stack....
    
    If a the attacker start's offering instructions to your CPU... kiss your ass
    goodbye.
    Research AV/VX trends from the late 80's and early 90's.
    
    -R
    
    Riley Hassell
    Security Research Associate
    eEye Digital Security
    
    [DOW]
    



    This archive was generated by hypermail 2b30 : Thu Feb 06 2003 - 09:03:24 PST