Revealing Stealth Malware UMD CMSC 389 M Xeno








































- Slides: 40
Revealing Stealth Malware UMD CMSC 389 M Xeno Kovah – Jan. 2013 xkovah at gmail Subject line starting with "UMD: " 1
All materials is licensed under a Creative Commons “Share Alike” license. • http: //creativecommons. org/licenses/by-sa/3. 0/ 2
Outline • Newz u can uze • How "system calls" work on Windows 3
Awww yiss! GMER 2. 0 released! Supports Win 7/8 x 64! 4
System Calls • They're how userspace asks the kernel to do stuff for it • Implemented fairly similarly across OSes, usually a table of exported functions in kernel and userspace code just puts the function parameters in some place defined by that OS's own internal convention, and then they just say "dear kernel, I'd like to call the function at index <#> in the system call table please", and off the kernel goes • You need to see the full path, and know that attackers can hook basically everywhere along the path. 5
SSDT Hook 6 From: http: //www. blackhat. com/presentations/bh-europe-06/bh-eu-06 -Silberman-Butler. pdf
SSDT Hook hehehe 7 From: http: //www. blackhat. com/presentations/bh-europe-06/bh-eu-06 -Silberman-Butler. pdf
Conceptual Separation of Duties Hardware Read. Sector(123) Data Kernel Open. File(Pv. Z. exe) Memory Mapped File Userspace Open Vid-yo-game! User 8
Conceptual Separation of Duties Hardware Read. Sector(423) Data Kernel Read. Key(HKLMBla) Registry Information Userspace Open Vid-yo-game! User 9
Conceptual System Call Interface Kernel Nt. Read. Key() Nt. Write. File() Nt. Shutdown. System() Nt. Open. Semaphore() Userspace Read. Key() Write. File() Shutdown. System() Open. Semaphore() Yay Comp-u-tors! User 10
"Native API" • The Native API refers to the way that Microsoft Windows' libraries are able to call from userspace to the kernel • This API is mostly undocumented, though people have long ago reverse engineered a lot of it. • Native API calls will start with the prefix Nt or Zw, with the Nt* versions being the ones which are preferred to be called from userspace, and the Zw* versions being preferred to be called from kernel. 11
Slightly More Accurate System Call Interface Kernel Nt. Read. Key() Nt. Write. File() Nt. Shutdown. System() Nt. Open. Semaphore() Ki. Fast. Call. Entry() or Ki. System. Service() Native API calling interface ntdll. dll Read. Key() Write. File() Shutdown. System() Open. Semaphore() Yay Comp-u-tors! User 12
Kernel User Ntdll. dll Nt. Write. File(){ mov eax, 0 x 112 int 0 x 2 E OR sysenter } Kernel 32. dll Write. File(){ Call [IAT: Nt. Write. File] } Start Here Example from Win XP My. App. exe … Call [IAT: Write. File] … Hook inline at target (seen it) Hook IAT (seen it) 13
Let's dig back into cmd. exe file listing for a sec… Somewhere deep in the belly of KERNELBASE!Find. First. File. Ex. W… What the heck is a "syscall" instruction? 14
But wait a sec…remember when we were trying to use Proc. Mon to get a better idea of what functions were used by cmd. exe to list files, but nothing Find*File-y was coming up? . . . And now you're telling me that behind the scenes, even though we got our first break on the Find. First. File. Ex. W() function, that it eventually calls to this Nt. Query. Directory. File() Native API system call? 15
Kernel User Ntdll. dll Nt. Query. Directory. File(){ mov eax, 0 x 32 syscall } kernelbase. dll Find. First. File. Ex. W(){ call [IAT: Nt. Query. Directory. File] } kernel 32. dll Find. First. File. Ex. W(){ jmp [IAT: Find. First. File. Ex. W] } Start Here Example from Win 7 x 64 cmd. Exe Find. First(){ Call [IAT: Find. First. File. Ex. W] } 16
The INT 0 x 2 E path is the Win 2 k path ntoskrnl. exe … Ki. System. Service(){ } IDT From userspace INT 0 x 2 E Kernel User Ki. System. Service Hook IDT new (prob going to be out of scope for class 17
The sysenter path is the more common Win XP path ntoskrnl. exe … Ki. Fast. Call. Entry(){ Ki. Fast. Call. Entry != Ki. System. Service } From userspace sysenter Kernel User Hook sysenter (IA 32_SYSENTER_EIP MSR) new 18
The syscall path is the more common Win * x 64 path ntoskrnl. exe … Ki. Fast. Call. Entry(){ Ki. Fast. Call. Entry != Ki. System. Service } From userspace syscall Kernel User Hook syscall (IA 32_LSTAR MSR) new 19
Sysenter vs. syscall? • AMD came up with syscall first. • Intel wanted to go their own way, and made up sysenter to do basically the same thing. – Interesting confessional from the guy who designed sysenter in the notes • Eventually they relented and licensed syscall from AMD • And they all lived happily ever after • The End 20
unused IIS spud. sys (if installed and running) unused Win 32 k. sys API Native API Ke. Service. Descriptor. Table. Shadow ntoskrnl. exe … Ki. System. Service() or Ki. Fast. Call. Entry(){ * Consult Thread Info * Extract address of System Service Descriptor Table (SSDT) which is Ke. Service. Descriptor. Table normally or Ke. Service. Descriptor. Table. Shadow if the process has used any graphical (GDI) routines * Parse eax for specific table entry } Kernel User 21
unused IIS spud. sys (if installed and running) unused Native API struct System. Service. Descriptor. Table{ PULONG_PTR Service. Table. Base; PULONG Service. Counter. Table. Base; ULONG Number. Of. Services; PUCHAR Param. Table. Base; }; Index to function mappings change between releases to discourage assumptions and SSDT hooking … 0 x 112 - nt!Nt. Write. File … 1 - nt!Nt. Access. Check 0 - nt!Nt. Accept. Connect. Port Ke. Service. Descriptor. Table service number = eax = 0 x 112 0000010010 2 bits table index Kernel User 12 bits service index 22
… 0 x 112 - nt!Nt. Write. File … 1 - nt!Nt. Access. Check Hook SSDT (new) ntoskrnl. exe … Nt. Write. File(){ } Hook inline at target 0 - nt!Nt. Accept. Connect. Port 23
Kernel User GDI 32. dll Nt. Gdi. Update. Colors(){ mov eax, 0 x 112 E int 0 x 2 E OR sysenter } Update. Colors(){ Call IAT: Nt. Gdi. Update. Colors () } Start Here My. App. exe … Call IAT: Update. Colors() … Hook inline at target (seen it) Hook IAT (seen it) 24
unused IIS spud. sys (if installed and running) unused Win 32 k. sys API Native API Ke. Service. Descriptor. Table. Shadow ntoskrnl. exe … Ki. System. Service() or Ki. Fast. Call. Entry(){ * Consult Thread Info * Extract address of System Service Descriptor Table (SSDT) which is Ke. Service. Descriptor. Table normally or Ke. Service. Descriptor. Table. Shadow if the process has used any graphical (GDI) routines * Parse eax for specific table entry } Kernel User 25
unused IIS spud. sys (if installed and running) Win 32 k. sys API struct System. Service. Descriptor. Table{ PULONG_PTR Service. Table. Base; PULONG Service. Counter. Table. Base; ULONG Number. Of. Services; PUCHAR Param. Table. Base; }; Index to function mappings change between releases to discourage assumptions and SSDT hooking … 0 x 12 E - win 32 k!Nt. Gdi. Update. Colors … 1 - win 32 k!Nt. Gdi. Abort. Path 0 - win 32 k!Nt. Gdi. Abort. Doc Native API Ke. Service. Descriptor. Table. Shadow service number = eax = 0 x 112 E 0100101110 2 bits table index Kernel User 12 bits service index 26
Hook SSDT (new) … 0 x 12 E - win 32 k!Nt. Gdi. Update. Colors … 1 - win 32 k!Nt. Gdi. Abort. Path win 32 k. sys … Nt. Gdi. Update. Colors(){ } Hook inline at target 0 - win 32 k!Nt. Gdi. Abort. Doc 27
Big Picture … … Ke. Service. Descriptor. Table win 32 k Ke. Service. Descriptor. Table. Shadow nt … 2 e kernel user IDT Ki. System. Service … Ki. Fast. Call. Entry INT 2 e (depending on Windows/HW version) Ntdll. dll Kernel 32. dll My. App. exe sysenter/syscall (depending on WindowsHW version) 28
ZO. M. G. it's Yoshi!!! … (and Mario is doing the splits) … Ke. Service. Descriptor. Table win 32 k Ke. Service. Descriptor. Table. Shadow nt … kernel user Ki. System. Service … Ki. Fast. Call. Entry INT 2 e Ntdll. dll sysenter Kernel 32. dll My. App. exe 29
SSDT Hook 30 From: http: //www. blackhat. com/presentations/bh-europe-06/bh-eu-06 -Silberman-Butler. pdf
SSDT Hook hehehe 31 From: http: //www. blackhat. com/presentations/bh-europe-06/bh-eu-06 -Silberman-Butler. pdf
Nu 2 U - sysenter • We never talked about the sysenter instruction in Intermediate x 86, due to lack of time, even though it would work well in that class. • Sort of as a background notion when we were talking about interrupts that they were 1) a way for hardware to get the CPU's attention, and 2) a way to get some kernel code to execute (Break. On. Thru. To. The. Other. Side lab, discussion of interrupts underlying debugging. ) • So "back in the day" systems would implement the "system call table"(*nix) or "system service descriptor table" (Windows) as a way for userspace code to ask the kernel to do specific actions for it. E. g. open a file, allocate some memory, • This was achieved by putting a system call number in some register and then calling int 0 x 80 (linux), or int 0 x 2 e (Windows). The code on the kernel side would then just check the designated register(s) which were input parameters and call the appropriate kernel library function. 32
Out with the old, in with the Nu 2 U • Intel and AMD introduced a specific instruction for achieving this same sort of system call table capability for kernels, but doing it more efficiently. • The instructions for doing this are syscall/sysret on AMD and sysenter/sysexit on Intel. • Linux used int 0 x 80 <= 2. 4, and sys* >= 2. 5, Windows used int 0 x 2 e <= Win 2 k, sys* >= XP 33
Mi. Se. Rly Mi. Se. Ry Mi. Santh. Ropy • The syscall/sysenter instructions basically just jump to a predefined location in the kernel ala an interrupt. That location is predefined by using a "Model Specific Register" (MSR) • MSRs are special registers which exist on specific models and have specific purposes (not a "general purpose" register like eax, ebx, etc. ) • You read and write MSRs with "rdmsr" (read msr) and "wrmsr“ (write MSR) • IA 32_SYSENTER_EIP = 0 x 176 34
Mi. Se. Rly Mi. Se. Ry Mi. Santh. Ropy • IA 32_SYSENTER_EIP = 0 x 176 • Reading from the MSR – mov ecx, 0 x 176 – rdmsr – (eax now contains value that was in the MSR) • Writing a MSR – – mov eax, 0 xdeadbeef mov ecx, 0 x 176 wrmsr (IA 32_SYSENTER_EIP now holds the value 0 xdeadbeef) 35
More about system calls • For more into on int vs sys*, as well as how interrupts work and worked on Windows: – How Do Windows NT System Calls REALLY Work? - http: //www. codeguru. com/Cpp/WP/system/devicedriverdevelopment/article. php/c 8 035/ – System Call Optimization with the SYSENTER Instruction - http: //www. codeguru. com/cpp/wp/system/devicedriverdevelopment/print. php/c 822 3 • It would have made a whole lot more sense if you had already taken Intermediate x 86 : -/ 36
Noo. Too. Yoo - SSDT • Win. Dbg command to print tables: • !for_each_thread ". echo Thread: @#Thread; dt nt!_kthread Service. Table @#Thread" • (from http: //www. securabit. com/wpcontent/uploads/2010/03/Rootkit-Analysis. Hiding-SSDT-Hooks 1. pdf) 37
SSDT Hook 38 From: http: //www. blackhat. com/presentations/bh-europe-06/bh-eu-06 -Silberman-Butler. pdf
SSDT Hook hehehe 39 From: http: //www. blackhat. com/presentations/bh-europe-06/bh-eu-06 -Silberman-Butler. pdf
SSDT False Positives (go look at the overall SSDT results again at this point) How you could determine these are due to symantec is out of scope for this class 40