Kernel mode rootkits
Kernel mode rootkits
Kernel-mode rootkits
Modifications to the operating system kernel that hide the
attacker and/or provide backdoor access
Kernel mode
Rootkits typically try to run at Ring 0
Intel x86 supports 4 rings
Ring 0 = highest-privilege (kernel code)
Access to all memory
Access to special processor instructions/registers that directly alter
CPU behavior
Ring 3 = lowest-privilege (user programs)
Windows/Linux do not use Ring 1 and 2 typically
Administrator programs running in Ring 3 will need to get Ring 0
privileges from the kernel to perform operations
Kernel mode rootkit targets
Process and thread control
• Process hiding
• Execution redirection
*snip*
open("/etc/passwd", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=2092, ...}) = 0
read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 2092
write(1, "root:x:0:0:root:/root:/bin/bash\n"..., 2092root:x:0:0:root:/root:/bin
*snip*
Windows kernel
User-mode processes make calls to Win32 subsystem DLLs
APIs for user programs to call the kernel
WIN32 Subsystem: csrss.exe, kernel32.dll, gdi32.dll, user32.dll
POSIX Subsystem: psxss.exe, psxdll.dll, posix.exe
Displaying information on screen, opening files, running programs
Must go through ntdll.dll to get to kernel
Windows kernel
NTdll.dll
Maps function calls for transition to the kernel.
System Service Dispatching (system call)
Interrupt 0x2E on x86 processors.
» Registers (call numbers) indicate location in dispatch table (SSDT)
Alternative SYSENTER/SYSCALL
» Fast system call for Pentium and beyond
» Pointer to syscall handler in model specific hardware register
Invokes kernel-level functionality called the Executive within
NTOSKRNL.EXE
Windows kernel
NTOSKRNL.EXE
Executive
Makes kernel function calls available to user-mode.
Virtual Memory Manager (VMM)
Security Reference Monitor (SRM)
I/O Manager
Object Manager
Process and Thread Manager
Kernel Services (Exception handling and runtime library)
LPC Manager (Local Procedure Call)
Windows kernel
Windows kernel (system calls)
Kernel-mode rootkit techniques
Kernel modules/drivers
Hooking kernel functions
Hooking kernal data (Direct kernel object modification)
Patching the kernel image
Running “underneath” kernel
Kernel modules/drivers
Kernel modules/drivers
Augment or replace kernel features (e.g. system calls)
In Linux: insmod
/proc/modules
root@morbo[892]$ lsmod
Module Size Used by Not tainted
cdrom 33728 0 (autoclean) [ide-cd]
soundcore 6500 0 (autoclean)
nfsd 80272 0 (autoclean)
autofs 13332 0 (autoclean) (unused)
iptable_filter 2412 0 (autoclean) (unused)
ip_tables 15096 1 [iptable_filter]
loop 12184 15 (autoclean)
mousedev 5588 1
keybdev 2976 0 (unused)
usbcore 78944 1 [hid usb-uhci]
eepro100 22740 1
ext3 70912 4
raid5 19080 2
Linux kernel modules
Example module: File redirections
1. Load kernel
2. Kernel starts init process
3. Modify init to load malicious
kernel module into kernel
4. When process opens init files,
malicious module captures
request
5. Malicious module lies about
contents so it is not revealed
6. File integrity checker thinks
everything is fine
Loadable device drivers
Modules easy to detect
Kernel rootkits often load themselves as device drivers instead
Runs in kernel mode with full access to privileged memory
Examples: Slanret (27KB device driver), Krei (27KB TCP backdoor)
Can be used in conjunction with user-mode code
Easier to debug and support functionality in user mode
Registers a name for access from user space (i.e. \\Device\\MyDevice)
Use ioctl/read/write to communicate to driver
Examples
Network drivers
Network driver establishes communication with remote attacker
while hiding it from applications above
Network driver redirects or suppresses client traffic (e.g. Drop
Windows Update DNS query)
File system drivers
Insertion within file system filter chains (see previous)
Can be made “stealthy”
Inject code into existing driver memory
NonPagedPool memory since driver memory should not be paged
out
Unload injecting driver afterwards so it can no longer be detected
Kernel driver only loaded long enough to apply patch
Hooking kernel functions
Hooking within kernel
Can be done directly or via device drivers and kernel
modules
More desirable than library hooks
Places you on equal footing with detection software (Ring 0)
Kernel memory 0x80000000 and above
Kernel hooks provide global scope
Attractive targets
Memory management
Exception processing
CPU registers that contain base addresses for many function
tables
Memory management
Page directory tables
Also instrumental for mapping addresses
CPU uses special register CR3 to point to an array of 1024 32-bit values
called the page directory
Each process has its own unique value of CR3 (its own page directory)
Threads of a process share CR3 value
Each 32-bit value specifies base address of a page table in physical memory
CPU handles memory access via table lookups
Rootkits tamper with tables to allow modification and hiding of code
pages
Interrupt processing
Interrupt descriptor tables
Used to find interrupt handlers
IDT register stores base of IDT
One IDTR per CPU
IDT contains array of 256 entries (one for each interrupt)
IDT entry can specify privilege level to run at (“interrupt gate”)
Useful in getting to kernel mode via interrupts (i.e. system calls
generate interrupts)
Hooking the IDT
Interrupt Descriptor Table
Numerous software and hardware interrupts
Page faults, timers, system calls, etc.
Hooking the IDT
Patch entries in IDT to point to common hook table
Easier than patching every interrupt service routine (ISRs)
Hook every IDT entry, but include unique jump details to call back
to original ISR
See code in Rootkit book
Hooking the IDT: Original IDT
IDT
0 ISR ptr
Original ISR 0
1 ISR ptr
Original ISR 1
i ISR ptr
Original ISR i
Hooking the IDT: IDT with jump templates
IDT Jump templates
0 ISR ptr Call rootkit with param 0 FAR JMP to ISR 0
Original ISR 0
1 ISR ptr
Call rootkit with param 1 FAR JMP to ISR 1
Original ISR 1
Rootkit
code
i ISR ptr
Call rootkit with param i FAR JMP to ISR i
Original ISR i
System call processing
System Service Dispatch Table
Kernel data structure that points to code which implements
system calls in Win32, POSIX, and OS/2 subsystems
Indexed by system call number
Two ways to call (int 0x2e or SYSENTER)
Two ways to hook
Previous IDT hook
» i.e. Hook int 2e handler by replacing its IDT entry with yours
» Store original int 2e function handler (KiSystemService) into
global DWORD
» Call original KiSystemService upon completion
Modern Windows uses faster SYSENTER instruction
» Must hook SSDT entries instead of IDT
» Require Ring 0 to modify (load rootkit as device driver)
» Replace SSDT entries to point to code in device driver instead
of Ntoskrnl.exe or Win32k.sys
Hooking the SSDT
Example: Hiding processes
Replace NTQuerySystemInformation function in SSDT
Hook calls original function and filters results to remove rootkit
entries from SystemInformationClass buffer that is returned
Must update execution time statistics across all processes in list
If CPU doesn’t add up to 100%, someone will be suspicious
I/O processing
Drivers typically organized in chains to avoid re-
implementing functions that can be shared
Example chain: keyboard drivers
Drivers organized as a chain to implement key remappings,
keyboard macros, etc.
Lowest-level driver deals with direct access to bus and hardware
device
Next level deals with data formatting and error codes
Each level intercepts data from lower level, modifies it, and
passes it on to higher level
Perfect for rootkits
Insert into chain to suppress events or eavesdrop on them
Keyboard chain example
IRP header
DKOM
Directly modify objects the kernel relies upon for its bookkeeping
and reporting
Normally, modifications to processes or tokens is done via Object
Manager in kernel
Performs protection checks
DKOM bypasses Object Manager and its checks
DKOM
Disadvantages
Must disassemble format of object
Must know how object is used so code doesn’t break after
modification
Must know how object changes between versions of OS
Works only for in-memory objects
Can not be used to hide files
Good for hiding processes, device drivers, ports
Good for elevating privilege levels
DKOM example: Process hiding
Process hiding from programs such as Taskmgr.exe
ZwQuerySystemInformation call lists running processes
Traverses doubly linked list in the EPROCESS structure of each process
FLINK = pointer to process in front
BLINK = pointer to process in back
Find a reference to EPROCESS of current process by calling
PsGetCurrentProcess
Traverse list and update FLINK and BLINK pointers to point around
process to be hidden
Must ensure that hidden process has valid FLINK and BLINK pointers
when hidden process exits via PspExitProcess
Have them point to itself
Jamie Butler’s FU Rootkit
See Greg Hoglund’s Rootkit book or BlackHat podcasts for details
DKOM example: Device Driver hiding
Device driver hiding from drivers.exe utility
Windows Device Manager
SeAccessCheck
SeAccessCheck
At runtime on Linux, /dev/kmem
Attack at run-time instead…
At runtime in Windows
Global Descriptor Table (GDP)
How memory is divided into segments
Allocated to user programs and kernel
Maps memory from 0x0000000 to 0xFFFFFFFF
Kernel memory between 0x80000000 - 0xC0000000
Crazylords extension
Uses Hoglund’s work and PhysMem by Mark Russinovich
Manipulates \Devices\PhysicalMemory
Allows attacker to view, search, and alter memory
Running “underneath” kernel
Running “underneath” kernel
Restart victim virtualized
Modify victim from below
Examples: VMWare, VirtualPC, Plex86, Bochs, BluePill
Issues
Complex implementation
Fooling Administrator at console is difficult
User Mode Linux
Runs a Linux kernel inside a normal user-mode processes
All UML instances run as guest operating systems
Each UML is independent of others
Similar to VMware or VirtualPC, but only for hosting Linux
Malware purpose!
In a cage you can’t see!
Like … the matrix
User Mode Linux
Kernel Mode Linux Project
Designed for software developer or administrator to run
user code in kernel mode
Installed in /trusted
Runs in ring 0 for better performance
Attacker could use KML for kernel-level attacks in previous
section
Hardware virtualized rootkits
Red Pill, Blue Pill
Place rootkit in hypervisor
See BlackHat 2006 talks Rutkowska, Dai Zovi
Anti-virus tools
Signature based detection
Good against the known
What about the unknown?
Prevention
Kernel patches and updates
System configuration hardening
Non-modular kernels
Do not export system call table (or randomize it)
Examples
Systrace
Tracks and limits system calls (Niels Provos)
SELinux
Enhanced security controls
Applied mandatory access controls to critical system components
and functionality (versus discretionary)
Response
Bring a CD-ROM with Forensic tools
Reinstall...
Tools
Microsoft Detours library
Library that provides routines for easy trampoline insertion
Tsearch
Automated in-memory resource finder/modifier
Winject
Automatic DLL injection and ejection
/proc/[pid]
Per-process information
Writing to /proc
May alter kernel configuration in real time via /proc
abstraction
root@morbo[1012]# cd /proc/sys/net/ipv4
root@morbo[1012]# cat ip_forward
0
root@morbo[1012]# echo 1 >ip_forward
root@morbo[1012]# cat ip_forward
1
Stealth techniques
Hiding processes/windows
Window list scanning (Randomize name of exe)
Hiding DLL injection
Removal from loaded module lists (MEM_ORDER_TYPE,
LOAD_ORDER_TYPE, INIT_ORDER_TYPE)
Hiding in kernel
Memory cloaking
modifying page tables and page mappings dynamically
Alternative Data Stream (ADS)
Use of : instead of \
C:\windows\system32:lzx32.sys
Hides the driver from easy detection
Windows Explorer and cmd.exe do not show ADS
Change memory to replace “:” (0x3a) to a “\” (0x5c)
Attach ADS to directory since ADS viewers do not show this
Hooking system call interrupts
Hybrid hooking
Use kernel to hook user process
Why?
Userland hooks are easier to implement functionality in
But, run at lower privilege level and can be detected by detection
software running at Ring 0
Most detection looks at inclusion method
Hook IAT without opening a handle to target process (which can
be detected)
Kernel-based inclusion using PSSetImageLoadNotifyRoutine
» Driver callback routine that is called every time an image is
loaded into memory
» OS sends notification when your target process or DLL is loaded
» Driver callback is executed when load happens
Use on kernel32.dll to be notified when all processes load
Modify IAT of processes in callback
Hybrid hooking
Memory space for hooks
Must allocate additional memory in remote process for hooks
New trick
User address 0x7ffe0000 and kernel address 0xffdf0000 map to
same physical page
» Kernel address writable, but user address is not
» Shared region is 4K, but kernel uses only 1K
» 3K available for rootkit on every process