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

Playing Malware Injection with Exploit thoughts [CFG ver.]

adr
September 21, 2018
500

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.

adr

September 21, 2018
Tweet

Transcript

  1. Playing Malware Injection
    with Exploit thoughts
    [email protected]rg
    !1

    View Slide

  2. • Master degree at CSIE, NTUST
    • Security Researcher - chrO.ot, TDOHacker
    • Speaker - BlackHat, DEFCON, VXCON, HITCON
    >_cat ./Bio
    !2

    View Slide

  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

    View Slide

  4. [email protected]
    Quick Review:
    What's Malware Injection?
    !4

    View Slide

  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

    View Slide

  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

    View Slide

  7. (ꐦ`•ω•´)!!!
    Here are the 4 primary challenges that
    you'll encounter during injection.
    >_man inject
    !7

    View Slide

  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

    View Slide

  9. [email protected]
    Interesting Case:
    Powerloader since 2013
    !9

    View Slide

  10. Powerloader,
    aka Extra Window Vulnerability
    !10

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  15. >_abuse vtable
    !15

    View Slide

  16. View Slide

  17. [email protected]
    3 more vulnerability:
    From Exploit to Inject
    !17

    View Slide

  18. [email protected]
    #1
    Ole32 DropEnter Event
    !18

    View Slide

  19. >_cat ./ole32_init
    !19

    View Slide

  20. >_cat ./reg_dropevent
    !20

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  25. >_abuse vtable
    !25

    View Slide

  26. View Slide

  27. [email protected]
    #2
    Comctl32 SubClass Event
    !27

    View Slide

  28. >_cat FastGetSubclsHdr
    !28

    View Slide

  29. >_cat MstSubclsProc
    !29

    View Slide

  30. >_cat EnterSubclsFram
    !30

    View Slide

  31. >_cat EntrSubclsCallbk
    !31

    View Slide

  32. >_cat CallNxtSubclsProc
    !32

    View Slide

  33. >_abuse vtable
    !33

    View Slide

  34. >_abuse vtable
    !34

    View Slide

  35. View Slide

  36. [email protected]
    #3
    Thread Hijacking (win10+)
    !36

    View Slide

  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

    View Slide

  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

    View Slide

  39. >_Process?
    ntdll!LdrInitializeThunk
    [email protected]
    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

    View Slide

  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

    View Slide

  41. View Slide

  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

    View Slide

  43. [email protected]
    #3
    Thread Hijacking (win10+)
    Sorry bro. We've patched CFG
    (Control-Flow-Guard) protection on
    ntdll.dll in August ;)
    So... What Happened?
    !43

    View Slide

  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

    View Slide

  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

    View Slide

  46. >_Recall
    ntdll!LdrInitializeThunk
    [email protected]
    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

    View Slide

  47. Orginal Patch
    !47
    *Pseudocode
    *Pseudocode *Pseudocode

    View Slide

  48. >_guard_dispatch_icall_fptr
    !48
    *Pseudocode

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  53. Well done, CFG!
    !53

    View Slide

  54. Thanks for listening
    [email protected]
    Slide
    Github @aaaddress1
    Facebook
    !54

    View Slide