RE: Preventing exploitation with rebasing

From: Riley Hassell (rhassellat_private)
Date: Tue Feb 04 2003 - 10:54:50 PST

  • Next message: Mark Martinec: "Re: GLSA: Mail-SpamAssasin"

    Unfortunately I think this won't work on most modern operating systems.
    mages without relocation sections "fixups" cannot be rebased. Most loaders
    create an environment block where process specific information is stored.
    TIB's,TEB's and other process information/management structures also exist
    in this delta. A simple scan of the first several thousand bytes yields
    various useful byte sequences.
    
    This method may even be used for cross version ret offsetting on various
    platforms. Each example would require more research to test the validity of
    these offsets, but as initial evidence this would suffice. Your dynamic
    loader (rva) engine would need to use the PEB or the fs segment to find a
    base to start from.. but then you're as good as new.
    
    int main()
    {
    	char buffer[8];
    	DWORD regnum=0;
    
    					   //:0x7FFD2DA7 jmp eax
    
    	strcpy(buffer,"............\xa7\x2d\xfd\x7f");
    }
    
    
    
    -R
    
    Also remember to rebase dll data sections. There's a load config table in
    the section...
    
    Riley Hassell
    Security Research Associate
    eEye Digital Security
    
    
    
    > -----Original Message-----
    > From: David Litchfield [mailto:davidat_private]
    > Sent: Monday, February 03, 2003 9:09 PM
    > To: bugtraqat_private; ntbugtraqat_private;
    > vulnwatchat_private
    > Subject: Preventing exploitation with rebasing
    >
    >
    > Defeating Exploits
    > **************
    > The ideas in this "paper" present a method for defeating exploits; not the
    > actual vulnerability. Before getting to the details let's consider slammer
    > (again).
    >
    > What made slammer so successful?
    > The overriding factor that made slammer so successful was it's ability to
    > spread. What made it's spread a foregone conclusion was the fact
    > that every
    > vulnerable SQL Server/MSDE had a "jmp esp" instruction at address
    > 0x42B0C9DC. This was the address that was used to gain control of the  SQL
    > Server's path of execution to a point where the worm's payload, the
    > "arbitrary code", would be executed.
    >
    > This address is in a dynamic link library (DLL) , sqlsort.dll which has an
    > "image base" of 0x42AE0000.
    >
    > Every image file, DLL or executable, has an "Image Base" and this base is
    > the preferred location where the file should be loaded into memory by the
    > Windows Loader. [I don't want to digress, here, as to what happens if
    > there's a conflict. See the references at the end.] Now if this Image Base
    > on one particular system had been 0x42AF0000 then the worm would
    > have failed
    > to infect this particular box; the "jmp esp" instruction that
    > should've been
    > at 0x42B0C9DC on this system would be found at 0x42B1C9DC so the
    > worm would
    > have been off target. The SQL Server running on this system, whilst still
    > being "vulnerable" to the buffer overflow vulnerability would have been
    > invulnerable to this worm. Sure - the SQL Server may have crashed - but it
    > would not have been compromised.
    >
    > It's like sickle cell. Someone born with the gene that causes sickle cell
    > anaemia, a blood disorder that affects many people of a West
    > African origin,
    > or carriers of the gene, sickle cell trait, do not suffer from the ill
    > affects of malaria, a disease caused by a parasite and most
    > commonly spread
    > by mosquitoes. Whilst someone with sickle cell trait can still catch
    > malaria, the gene mutates the haemoglobin in their blood in such
    > a way that
    > they are invulnerable to the debilitating side effects and syptoms of the
    > disease such as mental confusion, coma and death. There is an obvious
    > evolutionary advantage to sickle cell trait; remember that the
    > evolution of
    > the species cares not about how long a person lives, only that they live
    > long enough to pass on their genes. (Those with anaemia may suffer from
    > crises, periods of acute pain so the trade off is somewhat questionable.)
    >
    > In areas where malaria is a common cause of death, being a carrier of the
    > sick cell gene can help ensure that this person lives long enough to have
    > progeny. This is Darwinian natural selection in progress.
    >
    > Rebasing
    > *******
    > The problem with operating systems is that they all have pretty much the
    > same "genetic code" which makes each and every one of them vulnerable to a
    > new exploit. So we need to make them different and this can be achieved
    > through rebasing. Rebasing is the process of changing the Image Base of an
    > image file. By doing this the DLL/EXE is loaded into a different
    > location in
    > the virtual address space.
    >
    > Going back to Slammer, had I have rebased sqlsort.dll giving it a new base
    > of 0x41410000 my box would have been invulnerable to the worm. If another
    > worm were written, though, that used an address that contained a "jmp esp"
    > instruction in kernel32.dll then I would be vulnerable. So I rebase
    > kernel32.dll. But then another worm uses another DLL so I rebase that one,
    > too. Eventually I've rebased all of the DLLs used by SQL Server mutating
    > it's "genetic code", making it considerably different to any other SQL
    > Server install on the planet. In fact if I rebase every DLL on my
    > system and
    > every executable then I can make my box almost invulnerable to a given
    > exploit, past, present or future. It's not that my box is
    > invulnerable to a
    > buffer overflow vulnerability - it's just invulnerable to the exploits for
    > it. To gain control of a system protected in such a way
    > would require that the author of the exploit know the location of loaded
    > DLLs.
    >
    > So how easy is it to rebase DLLs and executables? Very. Microsoft have
    > provided a function to do this, ReBaseImage(), exported by
    > imagehlp.dll. If
    > you rebase an image the new base must be on a 64K boundary - i.e. if the
    > image base mod 64000 !=0 the base is not valid.
    >
    > The only other problem is Windows File Protection. Once you've rebased a
    > copy of the DLL you need to copy the new DLL over the old one but Windows
    > File Protection won't allow you to do this. To get around the problem use
    > the MoveFileEx and specifying the MOVEFILE_DELAY_UNTIL_REBOOT flag. Doing
    > this will add a registry value, "PendingFileRenameOperations" to
    > HKLM\System\CurrentControlSet\Control\Session Manager\. You then
    > need to add
    > another DWORD value "AllowProtectedRenames" and set it to 1. Then restart
    > the system. On reboot the new DLLs, with their new image bases, will be
    > loaded. For example - here is sample output of listdlls after kernel32.dll
    > and ws2_32.dll have been rebased.
    >
    >
    > Copyright (C) 1997-2000 Mark Russinovich
    > http://www.sysinternals.com
    >
    > ------------------------------------------------------------------
    > ----------
    > --
    > WINLOGON.EXE pid: 208
    > Command line: winlogon.exe
    >
    >   Base        Size      Version         Path
    >   0x01000000  0x2e000                   \??\C:\WINNT\system32\winlogon.exe
    >   0x77f80000  0x7b000   5.00.2195.5400  C:\WINNT\System32\ntdll.dll
    >   0x78000000  0x46000   6.01.9359.0000  C:\WINNT\system32\MSVCRT.dll
    >   0x4a4a0000  0xb1000   5.00.2195.6011  C:\WINNT\system32\KERNEL32.dll
    >   0x77db0000  0x5b000   5.00.2195.5992  C:\WINNT\system32\ADVAPI32.dll
    >   0x77d30000  0x71000   5.00.2195.5419  C:\WINNT\system32\RPCRT4.dll
    >   0x54530000  0x13000   5.00.2195.4874  C:\WINNT\system32\WS2_32.dll
    > ..
    > ..
    >
    > Now all the way through this I've been saying things like "almost
    > invulnerable" etc. Here's the reason. For some vulnerabilities it may be
    > sufficient to overwrite a saved return address, function pointer
    > or whatever
    > by only a few bytes. For example assume a saved return address is
    > 0x44784500
    > and at address 0x44784536 is a "jmp ebx" instruction and ebx points to our
    > code. Then we only need to overwrite the saved return address by 1 byte -
    > with 0x36. So knowledge of the DLL load address is not needed.
    > However, this
    > scenario is going to happen so infrequently (if ever) that it does not
    > detract from the idea of rebasing your system. There may other ways to
    > bypass this method.
    >
    > Some ideas to further help prevent exploits from working.
    >
    > Use addresses such as 0x**000000 or 0x00**0000 for the new image
    > base. With
    > there being a NULL in much of the image's address space this will help.
    > (This of course won't make a difference with unicode overflows)
    >
    > Ensure at least one (core) DLL has a base of 0x00119400 . This will ensure
    > that a common stack location 0x00120000 has been assigned forcing
    > the OS to
    > chose another location for the stack. You get the idea.
    >
    > Feel free to mail me/lists with comments.
    >
    > Cheers,
    > David Litchfield
    > NGSSoftware Ltd
    > http://www.ngssoftware.com/
    >
    >
    > MSDN Info
    > ReBaseImage()
    > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/d
    ebug/base/
    rebaseimage.asp
    MoveFileEx()
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base
    /movefileex.asp
    



    This archive was generated by hypermail 2b30 : Tue Feb 04 2003 - 17:26:18 PST