Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing...

59
Rootkit detection via Kernel Code Tunneling Mihai Chiriac BitDefender

Transcript of Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing...

Page 1: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Rootkit detection via Kernel Code Tunneling

Mihai Chiriac BitDefender

Page 2: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Talk outline

•   Introduction •   DBI – user mode •   DBI – kernel mode •   Analysis – rootkit detection •   Analysis - cleaning! •   Conclusions

Page 3: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

“Rootkits are sophisticated tools that allow pieces of malware to stay hidden, once they

are installed on a system, by subverting standard operating system functionality”

Page 4: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic
Page 5: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

File System

Page 6: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Storage Stack

Page 7: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Detection methods

•   “Bounds” check -IDT, MSRs, SDT entries, etc normally point inside ntoskrnl.exe - IRP_MJ_* functions point inside the driver

Page 8: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Detection methods

•   “Branch” check

Page 9: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Problems

•   “Trampoline attack” –  small piece of code (few instructions) –  stored in module’s unused areas –  difficult to analyze statically

Page 10: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Detection methods

•   Cross-view

Page 11: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Problems

•   Needs an untainted “low level” view –  difficult to obtain (miniport!)

•   Signature attack –   turn off filtering during RK scan

•   Other attacks –  piggyback an existing process –  use a custom file system

Page 12: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

A solution…

•   Single-step through the code flow •   Done by J. K. Rutkowski

–   “Execution path analysis”, 2003 –   Uses TF, hooks int1, counts instructions

•   However…. –   Instruction count varies widely –   Rootkits can easily interfere with the tracing

process

Page 13: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Dynamic Binary Instrumentation

Page 14: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Code Generation

•   Translates entire Basic Blocks •   Most instructions are copied 1:1 •   Offensive instructions are logged

–  We can remove or replace them… •   “Garbage” instructions are logged

–  Needed during analysis… •   How about branches?

Page 15: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Code Generation •   .4017F7 43 inc ebx •   .4017F8 83 7D CC 00 cmp byte ptr [ebp-34], 00

•   .4017FC 89 5D B8 mov dword ptr [ebp-48], ebx

•   .4017FF 0F 8C E0 07 00 00 jl 401FE5

•   .401805

•  

•   .3370000 43 inc ebx

•   .3370001 83 7D CC 00 cmp byte ptr [ebp-34], 00

•   .3370005 89 5D B8 mov dword ptr [ebp-48], ebx

•   .3370008 0F 8C ?? ?? ?? ?? jl __branch_taken

•   __fall_through:

•   JUMP_TO_VM (401805)

•   __branch_taken:

•   JUMP_TO_VM (401FE5) •  

Page 16: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Code Generation

•   JUMP_TO_VM (new EIP) –  Has to save environment –  Cannot push data unto the stack (stack

pollution) –  Has to find the successor (or translate it!) –  Has to restore the environment –  Has to jump to the new EIP

Page 17: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Code Generation •   .3370000 43 inc ebx •   .3370001 83 7D CC 00 cmp byte ptr [ebp-34], 00

•   .3370005 89 5D B8 mov dword ptr [ebp-48], ebx

•   .3370008 0F 8C ?? ?? ?? ?? jl __branch_taken

•   __fall_through:

•   xchg esp, dword ptr [__shadow_stack]

•   pushf

•   pushad

•   COMPUTE_JUMP (401805)

•   popad

•   popfd

•   xchg esp, dword ptr [__shadow_stack]

•   jmp dword ptr [__shadow_eip]

•   __branch_taken:

•   […] •  

Page 18: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Code Generation

•   COMPUTE_JUMP (new EIP) –  Expensive operation –  Saves and restores gen-purpose registers

and flags for every control transfer… –  Finds the successor, or even translates it –  Cache the results = direct link!

Page 19: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Code Generation

•   .3370000 43 inc ebx

•   .3370001 83 7D CC 00 cmp byte ptr [ebp-34], 00

•   .3370005 89 5D B8 mov dword ptr [ebp-48], ebx

•   .3370008 0F 8C ?? ?? ?? ?? jl __branch_taken

•   __fall_through:

•   jmp dword ptr [_BB.cache_fall_through]

•   __branch_taken:

•   jmp dword ptr [_BB.cache_branch_taken]

Page 20: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Code Generation

•   Indirect control transfer –  Cannot compute “target” at translation time –  Cannot link directly –  Have to generate special linking code… –  Very expensive L

.405B17 FF 24 95 20 5B 40 00 jmp dword ptr [405B20+edx*4]

Page 21: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Code Generation •   SPILL_EAX •   SPILL_ECX •   mov eax, dword ptr [405B20+edx*4] •   lea ecx, dword ptr [eax - _real_address_1] •   jecxz _1 •   […] •   // no match, so COMPUTE_JUMP (eax) •   _1: •   RESTORE_EAX •   RESTORE_ECX •   jmp _translated_address_1 •   […]

Page 22: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Asynchronous Tasks

•   Exceptions - 1 –  Common anti-debug technique –  Sometimes used as a covert control

transfer method – evades analysis –  Need to be properly handled

Page 23: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Asynchronous Tasks

•   Exceptions - 2 –  Monitor KiUserExceptionDispatcher,

enforce monitoring –   Inspect CONTEXT.Eip,

EXCEPTION_RECORD.ExceptionAddress

Page 24: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Asynchronous Tasks

•   Exceptions – 3

•   if (ExceptionAddress in Code Cache) { ExceptionAddress := FindRealAddress() return CONTINUE;

}

•   if (Eip in Code Cache) { Eip := FindRealAddress()

return CONTINUE; }

Page 25: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Asynchronous Tasks

•   APCs –  Hook KiUserAPCDispatcher

•   GUI related callbacks –  Hook KeUserModeCallback

•   Inspect and “fix” parameters –  The app will never know

Page 26: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Self Modifying Code

•   Enforce W^X at translation time… •   If executing from a RW page, make it

RO, but remember its original flags •   Extend KiUserExceptionDispatcher

monitoring •   Hook NtProtectVirtualMemory and

NtQueryVirtualMemory

Page 27: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Self Modifying Code

•   if (ExceptionCode = Write to RO Memory) {

•   // SMC? •   DeleteBlocksFromPage(); •   RemoveProtection(); •   Return HANDLED; •   }

Page 28: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

DEMO User-mode instrumentation

Page 29: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Kernel Mode DBI

•   Has to run at any IRQL –  Design a custom memory manager –  Remove all concurrent access control –  New engine instance, if we want to

instrument multiple threads –  Code generation engine should NOT crash J

Page 30: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Kernel Mode DBI

•   Detecting abnormal execution flow •   Exceptions? DRx ?

–  Hook the IDT ? –  We’re exposing ourselves L –  Compatibility problems with 64-bit

machines

Page 31: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Kernel Mode DBI

•   Detecting Self Modifying Code –  Normal method is very complex –  A rootkit may directly modify page

attributes… –  Or modify the WP bit in CR0 ! –  Hey, aren’t these offensive instructions? J

Page 32: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Kernel Mode DBI

•   Detecting Self Modifying Code –  Remove direct block linking –  Make sure everything goes through a

“basic block integrity checker” –  Simple CRC –  Obviously slower L

Page 33: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Kernel Mode DBI

•   Detecting Self Modifying Code –  Problems with basic blocks that modify

themselves –  Have to modify beyond the pre-fetch queue –  Hard to detect this behavior at translation

time

Page 34: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Analysis session

•   Let’s read the MBR J

•   void ReadMBR0() •   { •   li.LowPart = 0;

•   li.HighPart = 0;

•   dwStatus = ZwReadFile (hDisk, NULL, NULL, NULL, &ioBlock, pBuf, 512, &li, NULL);

•   }

Page 35: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Analysis session

•   Let’s read the MBR J

•   DWORD __declspec(noinline) _cdecl_0 (void *f) •   { •   Stopper (_ReturnAddress());

•   AddBlock (Translate (f));

•   ret = ((_fn_cdecl_0) (pBlock->pCode)) ();

•   return ret;

•   }

Page 36: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Analysis session

•   A normal disk operation… –  File system filter drivers –  File system driver –  Volume, Partition managers –  Class driver –  Port, Miniport, Hardware

Page 37: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

A clean system

•   A normal disk operation… - entire log in the whitepaper appendix!

•   82A4CEE8 | ntkrnlpa.exe ZwReadFile •   82C2F105 | ntkrnlpa.exe ObReferenceObjectByHandle •   82ABE05A | ntkrnlpa.exe IoGetRelatedDeviceObject •   82A9CD9A | ntkrnlpa.exe IoGetAttachedDevice •   82AC1ABB | ntkrnlpa.exe IoAllocateIrp •   82A47458 | ntkrnlpa.exe IofCallDriver •   8AA06306 | fltmgr.sys (8AA00000)+00006306

•   8ABE06DA | fileinfo.sys (8ABD9000)+000076DA

Page 38: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

A clean system 8AD2B222 | partmgr.sys (8AD2A000)+00001222 8AFAB39F | CLASSPNP.SYS (8AFA7000)+0000439F

8B1E75C2 | disk.sys (8B1E6000)+000015C2

8AFAB4A1 | CLASSPNP.SYS (8AFA7000)+000044A1

8ACA54AA | ACPI.sys (8AC9C000)+000094AA

8ABBC44E | ataport.SYS (8ABB6000)+0000644E

8ADAA006 | intelide.sys (8ADA9000)+00001006

8ABC4B0A | ataport.SYS (8ABB6000)+0000EB0A

8ADB115C | PCIIDEX.SYS (8ADB0000)+0000115C 82E1F874 | halmacpi.dll (82E1B000)+00004874

8ADB1056 | PCIIDEX.SYS (8ADB0000)+00001056

Page 39: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

A clean system 8ABC008C | ataport.SYS (8ABB6000)+0000A08C 8ADED438 | atapi.sys (8ADEC000)+00001438

8ACA53B8 | ACPI.sys (8AC9C000)+000093B8

8AFAB5A4 | CLASSPNP.SYS (8AFA7000)+000045A4

8AD2B230 | partmgr.sys (8AD2A000)+00001230

8AA0620C | fltmgr.sys (8AA00000)+0000620C

82A4E487 | ntkrnlpa.exe (82A0B000)+00043487

82A4CEF9 | ntkrnlpa.exe (82A0B000)+00041EF9

B1C36492 | KLUP.sys (B1C35000)+00001492

Page 40: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

A clean system

•   We have the entire execution path •   We’ve logged all instructions…

–  No suspicious control transfers –  No suspicious basic blocks –  No “garbage” or “offensive” instructions –  All basic blocks belong to legally loaded

modules

Page 41: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Infected system •   86BDE574 | CLASSPNP.SYS (86BDA000)+00004574 •   831B3EB6 | lsi_scsi.sys (8319F000)+00014EB6(T) •   855A2F61 | ??? (00000000)+855A2F61

•   855A2FD9 | ??? (00000000)+855A2FD9

•   855A2FED | ??? (00000000)+855A2FED

•   855A30D8 | ??? (00000000)+855A30D8

•   855A310A | ??? (00000000)+855A310A

•   855A3150 | ??? (00000000)+855A3150

•   […] •   831C14B1 | storport.sys (831B9000)+000084B1

Page 42: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Infected system

•   Infection “hints” –  Executing code outside of the code section

(s) –  Mismatch between the in-memory and on-

disk images of lsi_scsi.sys –  Execution of orphaned code – code that

does not belong to a legally loaded module

Page 43: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Detection

•   Select APIs to instrument –  Try to cover as much code as possible –  ~10 functions are enough! –  Registry –  Storage –  Processes / Threads –  Network

Page 44: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Detection

•   Registry –  ZwEnumerateKey –  ZwEnumerateValueKey –  ZwCreateKey –  …?

Page 45: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Detection

•   Storage system –  ZwCreateFile –  ZwReadFile –  ZwWriteFile –  ZwQueryDirectoryFile –  … ?

Page 46: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Detection

•   Processes / threads –  ZwQuerySystemInformation –  ZwQueryInformationProcess –  ZwQueryInformationThread –  …?

Page 47: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Detection

•   Network operations –  Not tested yet –  Probably use Windows Sockets Kernel? –   Instrument ZwDeviceIoControlFile on

\Device\Afd ? –  On our TODO list

Page 48: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

System disinfection

•   Booting from a clean disk is the safe way to go

•   But in some cases, live system disinfection may be valuable –  High availability environments?

•   Rebooting is a nuisance for most users

Page 49: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

System disinfection

•   A typical hook…

int Hook (QWORD Sector, BYTE *pData)

{ if (Sector == Rootkit_Sector)

{

memset (pData, 0, 512);

return 1;

} return OriginalFunction (Sector, pData);

}

Page 50: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

System disinfection

•   A typical hook (disarmed)

int Hook (QWORD Sector, BYTE *pData)

{ if (Sector == Rootkit_Sector)

{

NOP }

return OriginalFunction (Sector, pData);

}

Page 51: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

System disinfection

•   We could just patch the code, BUT… –  TDL3 checks its own code for patches,

using a second thread –  Not very elegant – it’s a last resort –  Prone to race conditions –  Need to find atomic operations to “disarm”

the hook –  After all, we’re patching live code J

Page 52: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

System disinfection

•   Pairs of signatures –   “original” malware code –   “disarmed” malware code

•   And during code generation… –  When encountering “original” code… –  …translate the “disarmed” code! –  We’ll then execute the “disarmed” path!

Page 53: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

System disinfection

•   Virus body is never modified –  But our translated copy is disarmed

•   We can use the full range of detection and remediation technologies

Page 54: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

DEMO Kernel-mode instrumentation

Page 55: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Conclusions

•   Strong detection technique –  Need to cover as many code paths as

possible •   Interesting disinfection capabilities

–  Rootkit binaries change many times/week –  Hook code changes much less often –  Signatures may live much longer

Page 56: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Conclusions

•   Interesting way of detecting ROP-based rootkits?

•   Rootkits have to modify control flow –  Detect DKOM-based malware using other

techniques –  Same for virtualization-based rootkits L

Page 57: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Conclusions

•   “Shadow Walker” –  BH 2005, by Sherri Sparks & Jamie Butler –   ITLB / DTLB de-synchronization

•   We’ll execute the clean code path! –  as read by the Code Generator (via the

DTLB) –  No infection “hints”, but we can use any

“classic” detection technology

Page 58: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Future work

•   64 bit code instrumentation –  An absolute must, considering 64-bit TDL4,

and it’s just the beginning! •   Network code analysis

–  Still in development –  Probably with WSK

Page 59: Rootkit detection via Kernel Code Tunneling...– Rootkits can easily interfere with the tracing process Dynamic Binary! Instrumentation! Code Generation • Translates entire Basic

Q&A [email protected]