Upload
guest3e5046
View
1.696
Download
0
Tags:
Embed Size (px)
Citation preview
injectso
Modifying and Spying on running processes under
Linux and SolarisShaun Clowes – [email protected]
Overview – Part 1A study of InjLibIntroduction to injectsoAll about ELFProgram/process modification techniques under Unix
Overview – Part 2injectso vs InjLibHow injectso worksIntercepting dynamic function callsDefending against injectsoFuture
Introduction to InjLibWindows System Journal 1994Jeffrey RichterInject a DLL into another processInjection has no effect on processDLL can be passed information about the target process
InjLibInjLib process is trivial
Entire process complete < 50 lines of codeStill impressive
Technique very widely used:Pwdump (2 and 3)GetAdminFport Virtually every ‘Spy’ application
InjLib – Basic Process 1. Find address of system function used
to open libraries2. Attach to process3. Allocate memory in process4. Copy DLL loading function into process5. Create thread in process at injected
function6. Function loads DLL
InjLib – Step 1Copied function needs to know how to get a DLL loadedDLLs dynamically loaded with “LoadLibraryA”Copied function needs to know address of this LoadLibraryA Copied function cannot rely on normal IAT processing since it is in different process
InjLib – Step 1‘LoadLibraryA’ is in kernel32.dllAll Windows applications have kernel32.dll mappedSafe to assume DLL mapped at same address in all processes on a machine
InjLib – Step 1Load reference to kernel32.dllhDll = LoadLibrary ("Kernel32");
Get address of LoadLibraryApLoadLib = GetProcAddress(hDll, “LoadLibraryA”);
InjLib – Step 2Attach to process (as a debugger)In code:hProc = OpenProcess (PROCESS_ALL_ACCESS, FALSE,
dwPid)
Need SE_DEBUG privilege to open processes owned by other users
InjLib – Step 3Allocate memory in remote process to store
Copied functionArguments to copied function
In code:pMem = VirtualAllocEx (hProc, NULL, dwBytesToAlloc,
MEM_COMMIT, PAGE_EXECUTE_READWRITE);
InjLib – Step 4Copy function and arguments into process.In code:WriteProcessMemory (hProc, pAddr, pToCopy,
dwAmtToCopy, &dwWritten);
To copy function just copy everything from function address to immediately following function address
InjLib – Step 5Create a new thread in remote process, Start it at address of injected functionPass address of structure in process containing information about location of ‘LoadLibraryA’ and DLL nameIn Code:hThread = CreateRemoteThread(hProc, NULL, 0,
pInjectedFunction, pArgs, 0, NULL);
InjLib – Step 6Injected function now runsCall ‘LoadLibraryA’ using function pointer and DLL name arguments
InjLib – ResultInjLib process for injecting a DLL is
EasyShortSafe
InjLib – What next?Up to application
Tinker with internal memory structuresChange window appearance/layoutCall API routines from inside processUse IPC channels in processPatch program functionsEndless possibilities
Introduction to injectsoinjectso is like InjLib for Linux and SolarisInject shared libraries into remote processesProvides some support code to help in dynamic function patching/interceptionMuch more detail later
Modifying Programs/Processes
The ability to modify behavior of programs/processes has obvious security ramifications
Patching vulnerabilitiesRun timeStatically
Subverting applicationsBackdoorsViruses
Modifying Programs/Processes under
UnixA few techniques:
Binary PatchingDynamic Loader EnvironmentIn Core Patching
Breakdown of ELFNeed understanding of internal structure of executablesELF = Executable and Linkable FormatOriginally by Unix System Labs (USL)Adopted by Tool Interface Standards committee (TIS)Used in virtually every recent Unix
Breakdown of ELFThree main types of ELF files
Relocatable file – object file ready to be linked with othersExecutable Shared Object (Library)
Only last two relevantConcentrate on Executables
ELF ‘Views’ELF describes two separate ‘views’ of an executable, a linking view and a loading viewLinking view is used at static link time to combine relocatable filesLoading view is used at run time to load and execute program
ELF ‘Views’ – Split
ELF Linking ViewDivides executable into many meaningful ‘Sections’Sections have:
A name and type Requested memory location at run timePermissions (writeable/executable)
.interp
.text
.rel.plt
.dynstr
.dynsym
.dynamic
ELF Linking View – Important Sections
.interp Requested Dynamic linker
.dynamic Dynamic linking information
.symtab, .dynsym
Symbols (static/dynamic)
.strtab, .dynstr String tables
.plt Procedure linkage table
.rel.<x> Relocations for section x
.text Code
ELF Linking ViewNot all sections loaded at run time
Information used for linkingDebugging information
Difference between link time and run time
ELF Loading ViewMuch simpler view, divides executable into ‘Segments’Only includes data to be loaded into memory at runtimeSegments have:
A simple typeRequested memory location at run timePermissions (readable/writeable/executable)
ELF Loading View – Segment Types
INTERP Dynamic linker for this executable
DYNAMIC
Dynamic linking information
LOAD Segment loaded into memory
ELF ‘Views’ - Linking to Loading
ELF Loading ViewSemantics of section table (Linking View) are irrelevant in Loading ViewSection information can be removed from executable
Loading and Executing an ELF Executable
1. File opened2. File descriptor passed to dynamic
linker specified in INTERP segment3. Linker reads file segments and loads
them at requested addresses4. Linker finds and processes the
dynamic segment
The Dynamic Section/Segment
A table with records containing data critical to dynamic loading/linkingAllows dynamic linker to quickly find out information about the executable
No need for section table etc
Each record consists of:A type (tag)Value (or pointer)
Dynamic Segment Record Tags
DT_NEEDED
Name of a required shared library
DT_JMPREL Address of relocation entries associated with the PLT
DT_DEBUG Pointer to debugging information from dynamic linker
Loading and Executing an ELF Executable
5. Map in shared libraries corresponding to DT_NEEDED entries
6. Add libraries to link map stored in debug struct referenced by DT_DEBUG entry
7. Perform Global Offset Table (GOT) relocations
8. Perform Procedure Linkage Table (PLT) relocations (usually lazily)
The Procedure Linkage Table
Stored in the .plt sectionAllows executables to call functions that aren’t present at compile time
Shared library functionsprintf() etc.
Set of function stubs
The Procedure Linkage Table
The Procedure Linkage Table
Redirection through PLT to real printf() determined by Dynamic LinkerUsually done ‘Lazily’
Dynamic Symbols/Relocations
In .rel.plt and .dynsym sectionsTell Dynamic Linker what it needs to resolve where (PLT)More on PLT/Dynamic relocations later
The Global Offset TableLike PLT but for non function symbols
‘stderr’, ‘errno’ etc
Referenced by PLT on IA32But NOT Sparc
Both PLT and GOT targeted for attack in format string vulnerabilities
DT_DEBUG RecordPointer to a structure provided by the Dynamic Linker (at run time)Normally examined by DebuggersShows memory layout of process
Which object files are loadedBase address at which they are loaded
Binary PatchingStatically modify code in fileNeed to:
Insert additional codeLink existing code to added code
Binary Patching – Inserting Code
Code in assembler (sometimes C)Where to put additional code?
Overwrite existing unused codeHard to identify
Section paddingNot much spaceNeed section in executable segment (on non IA32 targets)
Binary Patching – Inserting Code
Add a segmentHave as much space as needed
Other methodsUnix viruses
Our example will add a new segment
Can reuse existing but unneeded segment entry (e.g PT_PHDR)Create our own program headers
Binary Patching – Adding a Segment
Binary Patching – Patch what?
What to modify?Anything!Function prologues
Redirect internal function calls
General codeInsert new/remove old code
How to modify old codeJump to new code, then jump back
Binary Patching - Demo
Demo
Binary Patching - Advantages
Very flexibleCan modify almost everything
PermanentLittle performance impact
Binary Patching - Disadvantages
Complex, error prone, time consuming work
Particularly any asm code/disassembly
Hard to intercept dynamic functions (can’t simply overwrite PLT entries statically)Program must be restarted
Bad if it’s a critical service
Binary Patching - Disadvantages
Program executable must be modifiedEntire code must usually be relocatable
Can’t easily import functionsDirect syscalls
In Core PatchingModify the in core image of the process while it runsCan modify the remote process memory using ptrace() or procfs
In Core PatchingAs with static patching need to:
Insert additional codeLink existing code to new code
In Core PatchingWhere to put additional code?
Need executable memory spaceOverwrite existing unused code
Hard to identify
Use segment paddingMuch more significant at run timePage padded
Overwrite Program HeadersNot needed at execution time
In Core PatchingLinking in additional code:
Exactly as with file patching
In Core Patching - Demo
Demo
In Core Patching - Advantages
Very flexibleCan modify almost everything Non permanentCan be performed on running process
In Core Patching - Disadvantages
Complex, error prone, time consuming work
Particularly any asm code/disassembly
Can easily kill running programParticularly if not stopped at patch time
Dynamic Loader Environment
Dynamic loader resolves at run time all external symbols (dynamic relocations)
GOT – Data relocationsPLT – Function relocations
How?
Dynamic Loader TricksReads DT_NEEDED entries in PT_DYNAMIC segmentLoads files and adds them to link mapThen goes on to process relocations
Dynamic Loader Tricks – Process View
Dynamic Linker Tricks - Resolution
When processing relocations dynamic linker looks through map and
Searches each libraries exported symbolsTries to find matching symbol nameLooks for non ‘weak’ function
First match is the winner
Dynamic Linker – Function Call Interception
Trick is to get your library loaded firstIt will be the match (winner) for all its exported symbols
Can intercept any dynamic function call (libc etc)
Dynamic Linker – Getting in First
Modify DT_NEEDED recordsOverwrite other library entry
Open it in your library with linker routinesSubstitute library depends on old libraryRequires lazy binding!
Move DYNAMIC segment and recreate
Dynamic Linker – Getting in First
Use Linker environmentLD_PRELOAD specifies libraries to be loaded immediatelyVery common technique
Dynamic Linker – Calling Real Function
Intercepting function usually needs to call old functionDynamic linker provides interface (through libdl.so):
dlopen – Open a librarydlsym – Get address of symbol, RTLD_NEXT flag specifies libraries after current one
Dynamic Linker Tricks - Demo
Demo
Dynamic Linker Tricks - Advantages
EasyAll interception code can be done in C
SimpleSafe
Provided interception routines are sound
LD_PRELOAD non permanent
Dynamic Linker Tricks - Disadvantages
LD_PRELOAD not permanentDT_NEEDED approach requires executable modification
And library in place at all times
Program must be restartedAgain, bad for a critical service
injectso - End Part 1
Questions?
injectso - Part 2
Re-Overview – Part 2injectso vs InjLibHow injectso worksIntercepting dynamic function callsDefending against injectsoFuture
injectso TeaserSince we’re doing all these demosQuick demo of library injection using injectsoReal demos to follow internal details
injectso – Simple Demo
Demo
injectso Vs InjLibinjectso is basically the same as Injlib, but for Unix (Linux/Solaris)Much harder on Unix than on windows
Operating system provides minimal support
injectso Vs InjlibLoadLibraryA
Close equivalent under Unix
OpenProcessClose equivalent under Unix
VirtualAllocExNo Unix equivalentNo way to modify remote processes’ page protection
injectso Vs InjlibWriteProcessMemory
Close equivalent under Unix
CreateRemoteThreadNo Unix EquivalentUnix and Threads not best of friends
In summary, the two most important functions for InjLib have no Unix equivalent
injectso – Conceptual Steps
Break down library injection into conceptual steps
Then find ways to implement them under Unix
injectso – Conceptual Steps
Steps:1.Open process2.Find function in process to load a
library3.Get process to call that function to
load specified library4.(Bonus Points) Help injected library do
something useful
Step 1. Attaching to Process
No problemInjLib uses OpenProcess to get debugger connectionAlmost equivalent functions:
ptrace() – Linuxprocfs - Solaris
Step 1. Attaching to Process
Abilities gained:Read and write to arbitrary process memory
Page permissions do not apply
Modify process registersOther funky stuff under Solaris (but ptrace() support is nice)
Step 2. Library Open Functions
The function dlopen() can be used to open a dynamic library
And have it mapped in as normal
In Windows LoadLibraryA is in Kernel32.dll
Therefore in all programs
Step 2. Library Open Functions
Under Unix dlopen() exists in libdl.so
Dynamic linker related routines
How to use functions that aren’t loaded?
Step 2. Library Open Functions
Functions in libdl.so are stubsPerform error processing (under Linux)Real functions are located in
glibc (Linux)ld.so.1 (Solaris)
Makes senseDynamic linker must have access to the functionality to work
Step 2. Library Open Functions
Thus all (dynamically linked) processes have access to dlopen() functionality at all times
Step 2. Locating Library Functions
InjLib:Open kernel32.dllFind function addressAssume same in remote process
injectso can do the same using dlopen() and dlsym()
Does the address assumption hold?
Step 2. Locating Library Functions
No!Patches such as PaX, OpenWall etc deliberately randomly map shared librariesLocation of library in one process not the same in another
Step 2. Locating Library Functions
Duplicate actions of dynamic linker (by reading process memory):
Loop through link mapLoop through each objects dynamic symbolsFind matching symbolDetermine symbols absolute address (we have the base address)
Step 2. Locating Library Functions
Step 3. Calling the Loader Routine
Much harder under UnixNeed to force main process to jump to other code
Can’t just create a thread and copy function
Step 3. Calling the Loader Routine
Issues:Restoring process after
Syscall interruption
Constructing arguments to routineActually forcing call to routine
Step 3a. Syscall Interruption
A lot of code spends majority of time in syscalls
select(), read(), connect(), write() etc.
Redirecting process to other code will break the syscall
Breaking syscalls is not fun
Step 3a. Syscall Interruption
Syscall arguments stored in registersIA32 Linux - %eax, %ebx, %ecx, %edx …Sparc Linux - %o1, %o2, %o3, …Sparc Solaris - %g1, %o0, %o1, …
When syscall is interrupted the syscall returns an error into:
IA32 Linux - %eaxSparc Linux - %o1Sparc Solaris - %g1
Step 3a. Syscall Interruption
Value isn’t errno, I.e EINTREven if it were most code can’t handle it and dies
Need to prevent adverse affectsRestart syscall But the first argument is gone?!
Step 3a. Syscall Interruption
Finding old parameter:IA32 Linux – Stored in debugger structureSparc Solaris – Debugger connection doesn’t break syscall, take it before breakSparc Linux – Hell!
Step 3a. Syscall Interruption
Save old registers before modifying processRestore old syscall (and set instruction pointer) in saved registersWhen complete restore and start
Step 3b. Calling FunctionNeed to construct arguments and call functionInjLib copies in a function (and sets it executable)Doesn’t work on Unix:
Can’t malloc remote memoryCan’t set remote memory executable
Step 3b. Calling FunctionObvious solution – Trampolines
As used in gdbCopy code onto process stack to call function
Well and truly broken by PaX, OpenWall etc
Step 3b. Calling Functioninjectso steps:
1. Copy string arguments onto remote process stack (removed on register restore)
2. Set arguments in registers as required
3. Set saved PC/EIP to be an invalid page (0x41414140)
4. Set PC/EIP to function
Step 3b. Calling Function5. Allow process to execute6. Catch SegFault on return (invalid
page)7. Continue processing
No executable code injected at allNo permissions issues
injectso - SuccessIf done right library is loaded into remote process, care of dynamic linker
_init() is called as normal
Process continues on as normal
injectso - Demo
Demo
injectso – IssuesSignals
Signals generated during injection (e.g SIGALRM, SIGCHLD, SIGURG etc)Need to be replayed
Dangerous by definitionEspecially with unsafe syscall restartBut generally reliable with injectso
injectso – What next?Library can do whatever it wishesHowever useful to be able to override dynamic function calls
Most holes can be fixed this wayMost processes can be subverted this way
injectso – User Function Call
injectso can call a user specified function after injection
Provides address of program PT_DYNAMIC segment
Utility object called Intercept.o makes use of this
Compile it into libraryEasily intercept dynamic functions
Intercept.o – Intercepting Function Calls
User code provides list of functions to overrideIntercept.o function intercept_begin() called by injectsoFinds functions in PLT and patches them to refer to replacement versionsProvides pointer to old function to library
Intercept.o – Intercepting Function Calls
Intercept.o – Intercepting Function Calls
Needs to reapply after every call to original
Lazy Binding
A little harder on Sparc
injectso – Demo - Interception
Demo
injectso – Protecting Applications
Protect running servicesKill bad input data as it comes inIntercept input functions and purify
injectso – Demo - Protection
Demo
injectso – Subverting Applications
Backdoor running programsPop magic shell on certain inputLog input and output to critical service
injectso – Demo - Subversion
Demo
injectso - AdvantagesSimpleFlexible
Library can do anything it wishes
No modifications to binaryNo disk files
Library may be deleted after injection
injectso – AdvantagesService does not need to be restartedCode normally in CCode gets relocations freeMostly safe
injectso - DisadvantagesNot permanentComplex to use for non dynamic function interception
Protecting against injectsoinjectso is not a new attack
As demonstrated via three other methods
Modifying processes/binaries only possible after intrusionProtect machine
injectso – The FutureModify relocations
Prevents PLT patching problems for unbound functionsNeed executable space (on Sparc)
Hard to find with PaX aroundOverwrite library code segment?
Other PlatformsAdditional helpers (Prologue interception etc)
Thank you for listening!Questions?SecureReality Web Site:http://www.securereality.com.au
Email:[email protected]