User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer,...

41
User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs

Transcript of User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer,...

Page 1: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

User-Mode Driver Emulation:Buffered Code Execution (BCE)

Matt Conover

Principal Software Engineer, Symantec Research Labs

Page 2: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

2

Project Goal

• Develop a way to observe the interaction between a suspicious kernel driver and the kernel

• Use the observed interactions as the basis for detection

• This tool is used by anti-virus analysts to analyze and debug a rootkit driver

– A usual kernel debugger must debug the whole kernel

– Our tool can isolate the rootkit and analyze only the rootkit

Page 3: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

3

Project Implementation Strategies

• We will use a virtual machine (Windows guest in VMWare)

– In the virtual machine, we will use our tool to execute the rootkit driver and observe its behavior

• Our tool can record the rootkit’s interactions with the kernel, so we can learn the rootkit’s behavior

– Includes using kernel APIs, reading from kernel memory, writing to kernel memory, and using privileged instructions.

• How can this be accomplished?

– Emulation

– Debugging (single-step, breakpoints, etc.)

– Dynamic translation (rewriting code)

Page 4: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

4

Strategy #1: Emulation

• Utilizes user-mode emulation of the driver

– Privileged instructions and kernel-mode APIs are emulated

– Doesn’t interact with kernel

• Requires emulating the kernel-mode APIs

• Symantec has tried this approach

– RAID 2007, “A Forced Sampled Execution Approach to Kernel Rootkit Identification”

• Norman Sandbox uses this approach

• Too much work!

Page 5: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

5

Strategy #2: Debugger

• Use kernel-mode debugger (such as Microsoft’s WinDbg)

• Use breakpoints or single-stepping to control the rootkit

• This approach is not very reliable

• The rootkit and debugger are running at the same privilege level

• It’s easy for the rootkit to detect or disable the debugger (for example, check KdDebuggerPresent variable)

Page 6: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

6

Strategy #3: Dynamic Translation

• The rootkit can be run natively but using translated code.

– This is the technique used by VMWare and QEMU

• Rather than transfer control the driver’s entry point:

• We copy (translate) the instructions into our own code buffer

• Execute the code from the buffer, which will return control to our translator

• We repeat this process for each instruction/code block until the program finishes

Page 7: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

7

Strategy #3: Dynamic Translation

TranslateBuffer:

switch to “guest” context

InstructionToBeExecuted

save changes to “guest context”

RunProgram:

while (ProgramRunning):

if (VirtualizeInstruction(Guest.EIP)) continue

memcpy(TranslateBuffer.InstructionToBeExecuted,

Guest.EIP, get_ilen(Guest.EIP))

call TranslateBuffer

Page 8: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

8

Strategy #3: Dynamic Translation

• Certain instructions can be specially handled:

call GetEIP <- should push virtual return address

GetEIP: pop eax

– EAX should contain the original (virtual) address, not the translated code’s address

• We also need to prevent the rootkit from reading/writing certain addresses

– Don’t let it detect our code

– Don’t let it do some action that will cause us to lose control

Page 9: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

9

Strategy #3: Dynamic Translation

• This seems the best trade-off

– Although some instructions need to be specially handled,

– Execution can be native

– We can more easily hide our presence

– We can improve the performance using caching

Page 10: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

10

Questions?

Page 11: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

11

Our Approach: Buffered Code Execution (BCE)

• We use a form of dynamic translation

– That’s why we call this project “BCE”

• Run the rootkit at ring 3, but make the rootkit think it is ring 0

– We can keep control of the rootkit, while still observing its original behavior

– We don’t need to emulate instructions, we just need to handle faults

– In other words, we will need to handle privileged instructions and privileged memory access specially (proxy them to ring 0)

Page 12: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

12

Our Approach: Buffered Code Execution (BCE)

• How it works

– We make the rootkit’s own stack and code pages user-mode (ring 3) accessible We just directly execute all rootkit’s instructions.

– As long as it doesn’t interact with the kernel, the code runs without a problem

Page 13: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

13

Our Approach:Buffered Code Execution (BCE)

• If the rootkit tries to read/write/call a kernel-mode address…

– It will produce an access violation (since ring 3 code can’t access the kernel directly)

• When we catch this access violation

– We execute the faulting instruction at ring 0

– Then we continue execution at the next instruction at ring 3

• Result

– We can just let the code execute and wait for an access violation! Then we record the interesting event and continue execution

– We can easily observe the rootkits key behaviors without too much noise or effort

Page 14: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

14

Address Space View

Kernel Address Space

BCE Region:

Rootkit Driver Rootkit Stack

0xFFFFFFFF

0x80000000NTOSKRNL

BCE

Ring3 Accessible

BCE

Non-Executable Pages

BCEK

Code Buffer

Page 15: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

15

Address Space View

Kernel Address Space (shared)BCE Driver

Region

0xFFFFFFFF

0x80000000

A.exe

BCEK

BCE Driver Region

B.exe

BCEK

0x00000000

User Address Space (unique per process)

BCEK driver is always present in all processes

0x7FFFFFF

Page 16: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

16

Questions?

Page 17: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

17

BCE Version 1

• The first version of BCE was a user-mode process (BCE.exe) which ran the rootkit from user-mode:

– When the rootkit tries to access kernel-memory, it causes an access violation (ring 0 cannot access ring 3)

– Use Win32 Structured Exception Handling (SEH) to detect the faults

• How does it work?

– By recording these faults, we can detect when the rootkit is trying interacting with the kernel

– We will specially handle these faults, so that the rootkit works correctly

– This way, the rootkit will work correctly even though it’s running in user-mode

Page 18: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

18

BCE Version 1

• STATUS_ACCESS_VIOLATION

– Kernel rootkit tried to read or write to kernel memory

MOV EAX, DWORD PTR [KeServiceDescriptorTable]

– Kernel rootkit tried to call a kernel-mode API

CALL PsGetCurrentProcessId

• STATUS_PRIVILEGED_INSTRUCTION

– Kernel rootkit used a privileged instruction:

IN, OUT

LIDT, LGDT, LTR

RDMSR, WRMSR

MOV CRx, ...

Page 19: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

19

Hurdles to Overcome:

• The approach I have just mentioned, in fact, doesn’t work very well….

• What’s the problem?

• Kernel-mode callbacks…

• To fix this problem, we need to use a different architecture

• First, let’s discuss what a kernel-mode callback is

Page 20: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

20

Hurdles to Overcome: Kernel-Mode Callbacks

• What’s a callback? Any kind of function pointer…

– System call handler

– Interrupt handler

– PsCreateSystemThread, PsSetCreateProcessNotifyRoutine, etc.

Page 21: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

21

Hurdles to Overcome: Kernel-Mode Callbacks

• Callbacks are asynchronous, they can happen at any time

• Imagine the rootkit replaces an interrupt handler

• When the interrupt happens, if our user-mode process is not the current process, the result is unpredictable

Page 22: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

22

Callback Problem

RootKit.sys NTOSKRNL

IDT[0x03]

Set

IDT[0x03] =

0x404037

CPU

0x404037:

Int3Handler

Arbitrary.exe

_asm int 3

0x404037:

???

User-Mode Address = Process-Specific

3

4

21

Page 23: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

23

Hurdles to Overcome: Losing Control

• We must prevent the kernel from directly calling rootkit code, since it will run at ring 0 without protection.

• Example:

PsCreateSystemThread(…, RootkitFunc)

The kernel will call RootkitFunc directly, it will break our sandbox!

Page 24: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

24

Questions?

Page 25: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

25

Ring3 Emulation of an Instruction

Kernel Address Space

0xFFFFFFFF

0x80000000

BCE Buffer (ring 3)

Rootkit Stack

Rootkit Driver

ESP

EIP

Rootkit Context (ring3)

BCEK (ring0)#1 Read into BCE Buffer

#2 Jump to BCE Buffer

#3 BCE Buffer returns to BCEK

Page 26: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

26

Example

TID 3224 -> eax BB40E64E ebx 11111111 ecx BB40E64E edx 80549FA0

TID 3224 -> esi 00000000 edi 00000000

TID 3224 -> esp 81563070 ebp 81563070 eflags 00000246

TID 3224 <- FF809FCC mov <eax>, 0xFF801780

TID 3224 -> eax FF801780 ebx 11111111 ecx BB40E64E edx 80549FA0

TID 3224 -> esi 00000000 edi 00000000

TID 3224 -> esp 81563070 ebp 81563070 eflags 00000246

TID 3224 <- FF809FD1 shr eax, 0x08

TID 3224 -> eax 00FF8017 ebx 11111111 ecx BB40E64E edx 80549FA0

TID 3224 -> esi 00000000 edi 00000000

TID 3224 -> esp 81563070 ebp 81563070 eflags 00000207

TID 3224 <- FF809FD4 xor eax, dword ptr ds:[edx]

Page 27: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

27

Handling Kernel Function Calls:Calling a kernel API

Kernel Address Space

0xFFFFFFFF

0x80000000

Rootkit Stack

Rootkit Driver

BCEK

#1: Rootkit calls PsGetCurrentProcessId (caused a GPF)

GPF Handler

BCE Buffer (ring 3)

Page 28: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

28

Handling Kernel Function Calls: BCEK proxies the called kernel API

Kernel Address Space

0xFFFFFFFF

Rootkit Stack

Rootkit Driver

BCEK

0x80000000

GPF Handler

#2: GPF is handled by BCEK, “returns” to BCEK

BCE Buffer (ring 3)

Page 29: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

29

Handling Kernel Function Calls: Calling the actual kernel API

Kernel Address Space

0xFFFFFFFF

Rootkit Stack

Rootkit Driver

BCEK

0x80000000

GPF Handler

#3: BCEK calls API (ring0), API returns to BCEK, BCEK saves context

NTOSKRNL

BCE Buffer (ring 3)

Page 30: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

30

Handling Kernel Function Calls: Return to ring3 emulation

Kernel Address Space

0xFFFFFFFF

Rootkit Stack

Rootkit Driver

BCEK

0x80000000

GPF Handler

#4: Repeat the process on the next instruction

NTOSKRNL

BCE Buffer (ring 3)

Page 31: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

31

API Demo

[APIPROXY] TID 1704 API 0x8052702E (DbgPrint)

BCE Context 0x81D5A000:

host_prev_eip 0xFF80052C

host_prev_len 6

host_eip 0xFF800532

host_esp 0x81D7A068

Parameters: FF800540 FF6DE04C 00000000 8899AABB

Return address 0xFF8004A6

Page 32: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

32

BCE Solving Callback Problem:Kernel calls a rootkit function

Kernel Address Space

0xFFFFFFFF

0x80000000

Rootkit DriverNX Handler

Interrupt Handlers

NTOSKRNL

#1 Kernel makes call into rootkit driver

#2 Causes NX fault (rootkit driver code is non-executable)

Page 33: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

33

BCE Solving Callback Problem:Control passed to BCEK

Kernel Address Space

0xFFFFFFFF

0x80000000

Rootkit DriverNX Handler

Interrupt Handlers

NTOSKRNL

#3 NX handler saves caller information (NTOSKRNL)

BCE Buffer (ring 3)

BCEK (ring0)

ESP

EIP

#4 NX handler “returns” to BCEK callback handler

Page 34: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

34

BCE Solving Callback Problem:BCEK emulates the rootkit function

Kernel Address Space

0xFFFFFFFF

0x80000000

Rootkit DriverNX Handler

Interrupt Handlers

NTOSKRNL

#5 BCEK emulates the callback code

BCE Buffer (ring 3)

BCEK (ring0)

Page 35: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

35

BCE Solving Callback Problem:BCEK returns to kernel

Kernel Address Space

0xFFFFFFFF

0x80000000

Rootkit DriverNX Handler

Interrupt Handlers

NTOSKRNL

#6 BCEK reads in saved caller information

BCE Buffer (ring 3)

BCEK (ring0)

ESP

EIP

#7 BCEK returns to the original caller (NTOSKRNL)

Page 36: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

36

Callback Demo: Before

[APIPROXY] TID 420 API 0x805C5BF6 (PsCreateSystemThread)

BCE Context 0x81D54000:

host_prev_eip 0xFF809614

host_prev_len 6

host_eip 0xFF80961A

host_esp 0x81D74048

Parameters: 81D74068 10000000 00000000 00000000

Return address 0xFF80961A

Page 37: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

37

Callback Demo: After

[BCENX] IRQL 0, thread 0x81ECD2D8, FaultAddress 0xFF809290, ErrorCode 0x00000011, CS:EIP 0x08:0xFF809290

[HandleCallback] TID 224 @ 0xFF809290: callback (stack 0xF7872DB0)

eax 81ECD2D8 ebx 00000000 ecx 00000000 edx 821CC9FA

esi 81ECD2D8 edi 00000000 ebp F7872DDC

[bce_new_context] +R3 PDE 0xC0602080-0xC0602080

[bce_new_context] +R3 PTE 0xC0410910-0xC0410A10

[bce_run] Calling bce_thread_init 0xF702C7E8 (EIP FF809290, ESP 82142080)

Page 38: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

38

Future Direction

• Working!!!

• Detection

– Rootkits can detect our software because the rootkit runs more slowly than expected. Try to make our software harder to detect

• Performance

– No caching is implemented, instructions are translated one-by-one. We need to use caching to improve performance

Page 39: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

39

Conclusion

• We have a very effective and unique tool that can observe rootkit behavior

• The technology is lightweight

– It’s just a single driver and user-mode program

– It can run on any vanilla Windows machine

– It doesn’t require hardware virtualization (it just needs NX)

Page 40: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

40

Conclusion

• The rootkit cannot breakout of its sandbox

– Without the activity first being recorded

• The technology is can generic

– It can be used to run any kind of driver from ring 3

• We don’t prevent the rootkit from doing its behavior, we just make sure we can observe it

– That is, we don’t prevent it from doing something bad!

– Therefore, this should only be used from a virtual machine when using it with unknown, possibly malicious drivers

Page 41: User-Mode Driver Emulation: Buffered Code Execution (BCE) Matt Conover Principal Software Engineer, Symantec Research Labs.

41

Thank you!Final questions?

Email:[email protected]