Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Playing Malware Injection with Exploit thoughts [CFG ver.]

229b1596ce57cd0935a2bacd410d87a0?s=47 adr
September 21, 2018
410

Playing Malware Injection with Exploit thoughts [CFG ver.]

In the past, when hackers did malicious program code injection, they used to adopt RunPE, AtomBombing, cross-process creation threads, and other approaches. They could forge their own execution program as any critical system service. However with increasing process of anti-virus techniques, these sensitive approaches have been gradually proactively killed. Therefore, hackers began to aim at another place, namely memory-level weakness, due to the breakages of critical system service itself.

This lecture will introduce a new memory injection technique that emerged after 2013, PowerLoadEx. Based on this concept, three new injection methods will be disclosed as well. These makes good use of the memory vulnerability in Windows to inject malicious behavior into system critical services. The content will cover Windows reverse analysis, memory weakness analysis, how to use and utilize, and so on. The relevant PoC will be released at the end of the lecture.

229b1596ce57cd0935a2bacd410d87a0?s=128

adr

September 21, 2018
Tweet

Transcript

  1. Playing Malware Injection with Exploit thoughts aaaddress1@chroot.org !1

  2. • Master degree at CSIE, NTUST • Security Researcher -

    chrO.ot, TDOHacker • Speaker - BlackHat, DEFCON, VXCON, HITCON >_cat ./Bio !2
  3. • Introduction • Challenge When we meet Anti-Virus • Interesting

    Case - PowerLoader since 2013 • New Vulnerability - 3 idea inspired by PowerLoader • CFG Patch by MicroSoft • Summary >_ls ./agenda !3
  4. aaaddress1@chroot.org Quick Review: What's Malware Injection? !4

  5. >_man inject (`_´)ゞ Used for bypassing whitelist checking, byassing anti-virus,

    privilege escalation, etc. e.g. • DLL Side-Loading + Digital Signature = Bypassing anti-virus • Remote Inject + whitelisted process = Bypassing whitelist • Inject explorer + DLL Side-Loading + Self-elevate Service
 = Bypassing Windows UAC (User Account Control) *Vista ~ Win8* !5
  6. >_man inject There're serval well-known techniques • Shellcode Inject or

    DLL Inject - OpenProcess, VirtualAllocExRWX, WriteProcessMemory, CreateRemoteThread
 • Process Hollowing (aka RunPE) - OpenProcess, CreateProcessASuspended, Mapping PE FileVirtualAllocEx + WriteProcessMemory, GetThreadContext, and ResumeThread to Execute exe file from memory
 • Thread Hijack or AtomBombing - QueueUserAPC, Inline Hook, or IAT Hijack
 • Memory Exploit (PowerLoaderEX) - SetWindowLong, SendNotifyMessage !6
  7. (ꐦ`•ω•´)!!! Here are the 4 primary challenges that you'll encounter

    during injection. >_man inject !7
  8. There are 4 primary challenges in injection: 1. What's target

    - choose a target to inject, and it should be meaningful. e.g. explorer, svchost
 2. Where to place - find memory for us to place RWX memory or ROPChain payload. e.g. VirtualAllocEx
 3. How to inject payload - any way for us to write payload into remote process memory
 4. How to run it - create a new thread to execute or hijack current thread of that process? >_man inject !8
  9. aaaddress1@chroot.org Interesting Case: Powerloader since 2013 !9

  10. Powerloader, aka Extra Window Vulnerability !10

  11. Explorer Process Memory Shell_TrayWnd +0 - 0xcafe (vtable) +4 -

    window hwnd ... vtable @ 0xcafe +0 - Interlocked (inc) +4 - message callback +8 - Interlocked (inc) Operating System 1) Send Window Message 2) Send Window Message 3) Invoke s_wndProc function 4) Invoke several function from vtable >_how it works !11
  12. Explorer Process Memory Shell_TrayWnd +0 - 0xcafe (vtable) +4 -

    window hwnd ... vtable @ 0xcafe +0 - Interlocked (inc) +4 - message callback +8 - Interlocked (inc) >_issue? GetWindowLong() !12
  13. Explorer Process Memory Shell_TrayWnd +0 - 0xbeef 0xcafe +4 -

    window hwnd ... >_issue? GetWindowLong() vtable @ 0xcafe +0 - Interlocked (inc) +4 - message callback +8 - Interlocked (inc) fake vtable @ 0xbeef +0 - shellcode addr +4 - shellcode ... SetWindowLong() !13
  14. Explorer Process Memory malicious Shell_TrayWnd >_issue? GetWindowLong() payload SetWindowLong() +0

    - fake vtable ($+4) fake vtable +4 - shellcode addr ($+8) +8 - shellcode pwn! !14
  15. >_abuse vtable !15

  16. aaaddress1@chroot.org Demo !16

  17. aaaddress1@chroot.org 3 more vulnerability: From Exploit to Inject !17

  18. aaaddress1@chroot.org #1 Ole32 DropEnter Event !18

  19. >_cat ./ole32_init !19

  20. >_cat ./reg_dropevent !20

  21. >_man LPDROPTARGET IDropTarget actually is a virtual method table :)

    !21
  22. >_issue? vtable addr is determined by GetProp() so... it's really

    easy for us to hijack vtable just by SetProp() This callback function is used to deal with dropping file to Start Button of Explorer.exe !22
  23. explorer Process Memory DropTarget @ 0xc0fee Prop Name Value OleDropTargetInterface

    0xbeef payload @ 0xbeef +0 - 0xbeef (this) +4 - don't care ... +8 - don't care +0C- shellcode addr it's easy for us to change the return value of GetPropW("OleDropTargetInterface") from 0xc0fee to 0xbeef (malicious payload). >_issue !23
  24. explorer Process Memory Operating System 1) Send Window Message (Drag

    & Drop) 2) GetPropW("OleDropTargetInterface") 3) Invoke drop file function from vtable, invoke shellcode addr = *(beef+0c) DropTarget @ 0xc0fee payload @ 0xbeef +0 - 0xbeef (this) +4 - don't care ... +8 - don't care +0C- shellcode addr Prop Name Value OleDropTargetInterface 0xbeef >_issue !24
  25. >_abuse vtable !25

  26. aaaddress1@chroot.org Demo !26

  27. aaaddress1@chroot.org #2 Comctl32 SubClass Event !27

  28. >_cat FastGetSubclsHdr !28

  29. >_cat MstSubclsProc !29

  30. >_cat EnterSubclsFram !30

  31. >_cat EntrSubclsCallbk !31

  32. >_cat CallNxtSubclsProc !32

  33. >_abuse vtable !33

  34. >_abuse vtable !34

  35. aaaddress1@chroot.org Demo !35

  36. aaaddress1@chroot.org #3 Thread Hijacking (win10+) !36

  37. 3) create first thread of this process, point register eax

    to AddressOfEntry, point ebx+8 (TIB base + 8) to image base, and point eip to ntdll!LdrInitializeThunk Process >_Process? Kernel (ring0) Application (ring3) 1) create process via CreateProcess() 2) mapping file into memory iexplorer.exe .data section .text section AddressOfEntry ntdll.dll kernel32.dll ... !37
  38. >_Process? Process iexplorer.exe ntdll.dll kernel32.dll ... Call Stack -------------- _LdrpSnapModule

    _LdrpMapAndSnapDependency _LdrpMapDllWithSectionHandle _LdrpLoadKnownDll _LdrpFindOrPrepareLoadingModule _LdrpLoadDllInternal _LdrpLoadDll _LdrLoadDll _LdrpInitializeProcess __LdrpInitialize _LdrInitializeThunk fix import address table, fix export directory, apply relocation, etc .text section ntdll!LdrInitializeThunk !38
  39. >_Process? ntdll!LdrInitializeThunk AddressOfEntry@.text Process iexplorer.exe .text section ntdll.dll kernel32.dll ...

    ntdll!RtlUserThreadStart RtlUserThreadStart is entry-point of every thread. We can hijack thread via write shellcode address into global variable ‘LdrDelegatedRtlUserThreadStart'. !39 *Pseudocode *Pseudocode
  40. 3) point 'LdrDelegatedRtlUserThreadStart' to shellcode address Process >_Abuse Malware 1)

    get privilege of target process via OpenProcess() 2) mapping shellcode into target process chrome.exe .data section .text section shellcode ... ntdll.dll LdrDelegatedRtlUserThreadStart 4) every new thread of target process can be hijack to invoke shellcode !40
  41. aaaddress1@chroot.org Demo !41

  42. However, if you try to use this PoC, you'll find

    it doesn't work at all. plz... don't look at me like this :( !42
  43. aaaddress1@chroot.org #3 Thread Hijacking (win10+) Sorry bro. We've patched CFG

    (Control-Flow-Guard) protection on ntdll.dll in August ;) So... What Happened? !43
  44. The interesting thing is, actually I don't know where's the

    patch MicroSoft updated (ntdll.dll file, patched version) You guys will say: It's located at C:\windows\system32. yah, it should be right there, but it's not. Moreover, if you try any tools or windows system API to fetch the ntdll.dll path loaded in active process. You'll still see the path point to C:\windows\system32. >_Ntdll.dll's Patch? !44
  45. Thus, I decide to use x64dbg to launch a debug

    mode process (and it should be protected by CFG), and dump the ntdll.dll module from process memory via Scylla. A blessing in disguise, ntdll.dll is designed to be loaded first, so there's no IAT (Import Address Table) we need to repair for the dump file. >_Dump Patch yah, we got the original ntdll.dll module & the patch now. !45
  46. >_Recall ntdll!LdrInitializeThunk AddressOfEntry@.text Process iexplorer.exe .text section ntdll.dll kernel32.dll ...

    ntdll!RtlUserThreadStart RtlUserThreadStart is entry-point of every thread. We can hijack thread via write shellcode address into global variable ‘LdrDelegatedRtlUserThreadStart'. !46 *Pseudocode *Pseudocode
  47. Orginal Patch !47 *Pseudocode *Pseudocode *Pseudocode

  48. >_guard_dispatch_icall_fptr !48 *Pseudocode

  49. >_how CFG works? • CFG protects all indirect call/jump during

    compiling, and bitmap memory is allocated dynamically. • ntdll!guard_dispatch_icall_fptr verifies every dest addresses by bitmap. With dest address >> 9 as index, fetch uint64_t as hash from bitmap, and check it. • CFG will directly jump into
 the dest address, if the hash
 matches. Process anyApp.exe ntdll.dll kernel32.dll .text section CFG Bitmap bitmap[0] 08 00 00 00 48 00 08 00 bitmap[1] 00 00 00 00 00 00 00 00 bitmap[2] 28 00 00 01 00 00 00 00 ... !49
  50. >_By & far (1/3) • A cool idea is modifying

    the CFG bitmap base address. However, the bitmap base buffer sadly is read-only. 
 
 It's necessary for you to use VirtualProtectEx(), but this API is too conspicuous for anti-virus to catch-up. !50
  51. >_By & far (2/3) • CFG bitmap memory is allocated

    dynamically, and this address is randomized. • If we don't change the CFG bitmap base address, we must leak the CFG bitmap base address by ReadProcessMemory. • Fortunately, the CFG bitmap is predictable. There're 2 processes created simultaneously, and they have the same CFG bitmap memory address. !51
  52. >_By & far (3/3) • Correct hash should be stored

    on following formula:
 p = cfgBitmap[dest >> 9] • if _bittest(p, dest >> 3) != null, $rip is hijacked • anothor cool idea is allocating a fake CFG field where stores a correct hash to cheat the CFG function, If we could predict the remote CFG bitmap address. • VirtualAllocEx doesn't allow you get a higher address than current CFG bitmap address, so ... !52
  53. Well done, CFG! !53

  54. Thanks for listening aaaddress1@chroot.org Slide Github @aaaddress1 Facebook !54