This document discusses various techniques for injecting code into other processes on Windows systems. It begins with an overview of code injection basics and user mode injection techniques using the Windows API. It then covers more advanced techniques like injecting DLLs, avoiding disk access requirements, and kernel mode injection by directly modifying process memory and thread contexts. The document aims to provide a technical understanding of how real-world malware may implement code injection capabilities.
This document discusses various techniques for injecting code into other processes on Windows systems. It begins with an overview of code injection basics and user mode injection techniques using the Windows API. It then covers more advanced techniques like injecting DLLs, avoiding disk access requirements, and kernel mode injection by directly modifying process memory and thread contexts. The document aims to provide a technical understanding of how real-world malware may implement code injection capabilities.
This document discusses various techniques for injecting code into other processes on Windows systems. It begins with an overview of code injection basics and user mode injection techniques using the Windows API. It then covers more advanced techniques like injecting DLLs, avoiding disk access requirements, and kernel mode injection by directly modifying process memory and thread contexts. The document aims to provide a technical understanding of how real-world malware may implement code injection capabilities.
This document discusses various techniques for injecting code into other processes on Windows systems. It begins with an overview of code injection basics and user mode injection techniques using the Windows API. It then covers more advanced techniques like injecting DLLs, avoiding disk access requirements, and kernel mode injection by directly modifying process memory and thread contexts. The document aims to provide a technical understanding of how real-world malware may implement code injection capabilities.
1-2 Outline Code Injection Basics User Mode Injection Techniques Example Malware Implementations Kernel Mode Injection Techniques Advanced Code Injection Detection via Raw Memory Analysis 1-3 Code Injection Basics Code Injectionrefers to techniques used to run code in the context of an existing process Motivation: Evasion: Hiding from automated or human detection of malicious code IR personnel hunt for malicious processes Impersonation: Bypassing restrictions enforced on a process level Windows Firewall, etc Pwdump, Sam J uicer 1-4 User Mode Injection Techniques Techniques Windows API AppInit_Dll Detours 1-5 Injecting code via the Windows API Somewhat surprisingly, the Windows API provides everything you need for process injection Functions: Vi r t ual Al l ocEx( ) Wr i t ePr ocessMemor y( ) Cr eat eRemot eThr ead( ) Get Thr eadCont ext ( ) / Set Thr eadCont ext ( ) Set Wi ndowsHookEx( ) 1-6 1. OpenProcess evil.exe (pid = 2222) Kernel (via kernel32) iexplore.exe (pid = 3333) 1 OpenProcess(3333) 2 Handle =400 hProc = 400 payload = 0xCC 3 1-7 2. VirtualAllocEx evil.exe (pid = 2222) hProc = 400 Kernel (via kernel32) iexplore.exe (pid = 3333) 1 VirtualAllocEx( hProc, 0x4000, 256, . . .) 4 base =0x4000 base = 0x4000 2 New section Base address =0x4000 Size =256 bytes payload = 0xCC 5 3 1-8 3. WriteProcessMemory evil.exe (pid = 2222) hProc = 400 Kernel (via kernel32) iexplore.exe (pid = 3333) 1 WriteProcessMemory( hProc, base, payload, 1, ) base = 0x4000 2 New section Base address =0x4000 Size =256 bytes payload = 0xCC 3 0xCC 1-9 4. CreateRemoteThread evil.exe (pid = 2222) hProc = 400 Kernel (via kernel32) iexplore.exe (pid = 3333) 1 CreateRemoteThread( hProc, SecAttribs =NULL, StackSize =1024, 0x4000 ) base = 0x4000 2 New section Base address =0x4000 Size =256 bytes payload = 0xCC 3 0xCC 4 ThreadId =11 New Thread Id =11 Start Address =0x4000 ThreadId = 11 5 10 #I nj ect an i nf i ni t e l oop i nt o a r unni ng pr ocess i mpor t pydbg k32 = pydbg. ker nel 32 payl oad = \ xEB\ xFE pi d = i nt ( ar gs[ 0] ) . . . h = k32. OpenPr ocess( PROCESS_ALL_ACCESS, \ Fal se, pi d) m= k32. Vi r t ual Al l ocEx( h, None, 1024, \ MEM_COMMI T, \ PAGE_EXECUTE_READWRI TE) k32. Wr i t ePr ocessMemor y( h, m, payl oad, \ l en( payl oad) , None) k32. Cr eat eRemot eThr ead( h, None, 1024000, m, None, 0, None) 1-11 Better Payloads Breakpoints and Loops are fun, but what about real payloads? If we directly inject code it must be position independent Any addresses that were pre-calculated at compile time would be wrong in the context of a new process 1-12 Better Payloads Building large position independent payloads is possible, but not trivial However, DLL injection is much simpler DLLs are designed to be loaded in a variety of processes, addresses are automatically fixed up when the DLL is loaded 1-13 DLL Injection Use the basic process we just described DLLs are loaded using kernel32!LoadLibrary kernel32 is at the same address in every process we know its address in the remote process (ignoring ASLR) Allocate space for the name of the DLL to be loaded, then create a thread with a start address that points to LoadLibrary 14 #DLL I nj ect i on Excer pt i mpor t pydbg k32 = pydbg. ker nel 32 pi d = i nt ( ar gs[ 0] ) dl l name = ar gs[ 1] . . . h = k32. OpenPr ocess( PROCESS_ALL_ACCESS, \ Fal se, pi d) m= k32. Vi r t ual Al l ocEx( h, None, 1024, \ MEM_COMMI T, \ PAGE_EXECUTE_READWRI TE) k32. Wr i t ePr ocessMemor y( h, m, dl l name, \ l en( dl l name) , None) k32. Cr eat eRemot eThr ead( h, None, 1024, k32. LoadLi br ar y, m, 0, None) 1-15 User Mode API Variants Rather than create a new remote thread, we can hijack an existing thread using Get Thr eadCont ext , Set Thr eadCont ext Set Wi ndowsHookEx can also be used to inject a DLL into a single remote process, or every process running on the current Desktop 1-16 SetWindowsHookEx SetWindowsHookEx defines a hook procedure within a DLL that will be called in response to specific events Example events: WH_KEYBOARD, WH_MOUSE, WH_CALLWNDPROC, WH_CBT Whenever the hooked event is first fired in a hooked thread, the specified DLL is be loaded 1-17 Permissions and Security To open a process opened by another user (including SYSTEM), you must hold the SE_DEBUG privilege Normally SE_DEBUG is only granted to member of the Administrator group However, even if you are running as a normal user, malware can still inject into another process that you own 1-18 Injecting code via AppInit_DLLs The AppInit_DLLs registry value provides another convenient method of DLL injection 1-19 Injecting code via Detours Detours is a library developed by Microsoft Research in 1999 The library uses the same techniques already described, wrapped up in slick package 1-20 Detours Features Function hooking in running processes Import table modification Attaching a DLL to an existing program file Detours comes with great sample programs: Withdll Injdll Setdll Traceapi 1-21 Setdll Detours can add a new DLL to an existing binary on disk. How? Detours creates a section named .detoursbetween the export table and debug symbols The .detours section contains the original PE header, and a new IAT Detours modifies the PE header to point at the new IAT (reversible) 1-22 Setdll Demo 1-23 Setdll Demo 1-24 Avoiding the Disk When we perform DLL injection, LoadLi br ar y expects the DLL to be on the disk (or at least an SMB share) The Metasploit project eliminates this requirement using a clever hooking strategy By hooking functions that are involved in reading the file from disk, they fool Windows into thinking the DLL is on disk 1-25 Meterpreter Hook Call LoadLibrary Unhook Hooked functions: NtMapViewOfSection NtQueryAttributesFile NtOpenFile NtCreateSection NtOpenSection See remote_dispatch.c and libloader.c in MSF 3.0 1-26 Meterpreter Demo 1-27 Poison Ivy RAT Tons of malware uses Code Injection Well quickly dig into the details of one example 1-28 Poison Ivy Capabilities 1-29 Step 1: Inject to Explorer Poison Ivy client immediately injects to Explorer and then exits Output from WinApiOverride32 for pi.exe 1-30 Step 2: Inject again to msnmsgr.exe Explorer.exe injected code then injects again Interestingly, PI does not grab the SE_DEBUG privilege, so we cant inject in many existing processes Output from WinApiOverride32 for explorer.exe 1-31 Did it Work? 1-32 Where is the evil? 1-33 Kernel Process Injection 1-34 Two Halves of the Process User land processes are comprised of two parts Kernel Portion EPROCESS and KPROCESS ETHREAD and KTHREAD Token Handle Table Page Tables Etc. 1-35 Two Halves of the Process User land Portion Process Environment Block (PEB) Thread Environment Block (TEB) Windows subsystem (CSRSS.EXE) Etc. 1-36 Kernel Process Injection Steps Must find suitable target Has a user land portion Has kernel32.dll and/or ntdll.dll loaded in its address space Has an alterable thread (unless hijacking an existing thread) Allocate memory in target process Write the equivalent of shellcodethat calls LoadLibrary Cause a thread in the parent to execute newly allocated code Hijack an existing thread Create an APC 1-37 Allocate memory in parent process Change virtual memory context to that of the target KeAttachProcess/KeStackAttachProcess ZwAllocateVirtualMemory (HANDLE) -1 means current process MEM_COMMIT PAGE_EXECUTE_READWRITE 1-38 Creating the Shellcode shellcodethat calls LoadLibrary Copy function parameters into address space Pass the address of function parameters to calls Can use the FS register FS contains the address of the TEB TEB has a pointer to the PEB PEB has a pointer to the PEB_LDR_DATA PEB_LDR_DATA contains all the loaded DLLs 1-39 Creating the Shellcode As an alternative to using the FS register Find the address of ntdll.dll from the driver Parse its exports section Does not work with all DLLs Only address of ntdll.dll returned by ZwQuerySystemInformation 1-40 Thread Hijacking Cause a thread in the parent to execute newly allocated code - Hijack an existing thread Locate a thread within the parent process Change its Context record Change Context record back when done Problems: Low priority threads Blocked threads Changing Context back 1-41 Thread Context Hijacking Hijack and Context records lkd>dt nt!_CONTEXT +0x000 ContextFlags : Uint4B +0x004 Dr0 : Uint4B +0x008 Dr1 : Uint4B +0x00c Dr2 : Uint4B +0x010 Dr3 : Uint4B +0x014 Dr6 : Uint4B +0x018 Dr7 : Uint4B +0x01c FloatSave : _FLOATING_SAVE_AREA +0x08c SegGs : Uint4B +0x090 SegFs : Uint4B +0x094 SegEs : Uint4B +0x098 SegDs : Uint4B +0x09c Edi : Uint4B +0x0a0 Esi : Uint4B +0x0a4 Ebx : Uint4B +0x0a8 Edx : Uint4B +0x0ac Ecx : Uint4B +0x0b0 Eax : Uint4B +0x0b4 Ebp : Uint4B +0x0b8 Eip : Uint4B +0x0bc SegCs : Uint4B +0x0c0 EFlags : Uint4B +0x0c4 Esp : Uint4B +0x0c8 SegSs : Uint4B +0x0cc ExtendedRegisters : [512] UChar 1-42 Alternative Method: APC Cause a thread in the parent to execute newly allocated code - Create an APC Threads can be notified to run an Asynchronous Procedure Call (APC) APC has a pointer to code to execute To be notified, thread should be Alertable 1-43 Alertable Threads and APCs MSDN 1-44 Finding an Alertable Thread PETHREAD FindAlertableThread(PEPROCESS eproc) { PETHREAD start, walk; if (eproc ==NULL) return NULL; start = *(PETHREAD *)((DWORD)eproc + THREADOFFSET); start = (PETHREAD)((DWORD)start - THREADFLINK); walk =start; do { DbgPrint("Looking at thread 0x%x\n",walk); if (*(PUCHAR)((DWORD)walk + ALERTOFFSET) == 0x01) return walk; walk =*(PETHREAD *)((DWORD)walk + THREADFLINK); walk = (PETHREAD)((DWORD)walk - THREADFLINK); }while (walk !=start); return NULL; } 1-45 Kernel Process Injection Demo 1-46 Memory Analysis Motivation APIs lie. The operating system can be subverted. Example: Unlink injected DLLs from the PEB_LDR_DATA in the PEB. Example: Hooking the Virtual Memory Manager and diverting address translation. APIs are not available to classic forensic investigations offline analysis 1-47 Memory Analysis Requirements No use of APIs to gather data. Ability to use any analysis solution on both live memory and offline memory image dumps. (Implies the ability to do all memory translation independently.) Do not require PDB symbols or any other operating specific information. 1-48 Steps to Memory Analysis Ability to access physical memory Derive the version of the OS important to know how to interpret raw memory Find all Processes and/or Threads Enumerate File Handles, DLLs, Ports, etc. 1-49 Steps to Memory Analysis Virtual to Physical Address Translation Determine if the host uses PAE or non-PAE Find the Page Directory Table process specific Translate prototype PTEs Use the paging file 1-50 Derive the version of the OS Find the System Process Allows the derivation of: The major operating system version in question The System Page Directory Table Base HandleTableListHead Virtual address of PsInitialSystemProcess PsActiveProcessHead PsProcessType Patent Pending 1-51 Operating System Version Find the System image name Walk backwards to identify the Process Block The spatial difference between major versions of the OS is enough to begin to tell us about the operating system version Patent Pending 1-52 Operating System Version Drawback: Ghosts There can be more than one System Process Open a memory crash dump in Windbg Run a Windows operating system in VMWare Solution: Non-paged kernel addresses are global We know the virtual address of PsActiveProcessHead PsActiveProcessHead and other kernel addresses should be valid and present (translatable) in both live or dead memory Patent Pending 1-53 Memory Translation PAE vs non-PAE Different ways to interpret the address tables The sixth bit in the CR4 CPU register determines if PAE is enabled Problem: We do not have access to CPU registers in memory analysis Solution? Kernel Processor Control Region -> KPCRB -> KPROCESSOR_STATE -> KSPECIAL_REGISTERS -> CR4 1-54 Memory Translation CR4 Heuristic Page Directory Table Base and the Page Directory Table Pointer Base look very different. CR3 is updated in the KPCR This can be used to identify a valid Page Directory Table The Page Directory can be used to validate the PsActiveProcessHead Patent Pending 1-55 Enumerating Injected DLLs Problem: APIs lie. Malware can unlink from the PEB_LDR_DATA lists of DLLs Solution: Virtual Address Descriptors (VADs) Patent Pending 1-56 VADs Self balancing binary tree [1] Contains: Virtual address range Parent Left Child and Right Child Flags is the memory executable Control Area 1. Russinovich, Mark and Solomon, Dave, Microsoft Windows Internals, Microsoft Press 2005 1-57 A Memory Map to a Name VAD contains a CONTROL_AREA CONTROL_AREA contains a FILE_OBJ ECT A FILE_OBJ ECT contains a UNICODE_STRING with the filename We now have the DLL name Patent Pending 1-58 Demo 1-59 Conclusion 1-60 Questions? Email: jamie.butler AT mandiant.com