rootkit detection via kernel code tunneling...– rootkits can easily interfere with the tracing...

59
Rootkit detection via Kernel Code Tunneling Mihai Chiriac BitDefender

Upload: others

Post on 05-Aug-2020

3 views

Category:

Documents


0 download

TRANSCRIPT

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]