LaunchDaemon and Microsoft Defender ATP

tkuhn
New Contributor

Hello,

We have recently started testing and deploying MDATP to select people in our org. Right now I am trying to schedule Quick Scans to occur every day at 12:30pm but am having a bit of an issue. I am pretty green to the LaunchDaemons work but I have checked existing ones we utilize and even had one generated to verify i wasn't making a syntax error. Perhaps I am missing something simple someone could point out.

plist file in /Library/LaunchDaemons

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.org.mdatpquickscan</string> <key>ProgramArguments</key> <array> <string>sh</string> <string>/Library/path/script.sh</string> </array> <key>StartCalendarInterval</key> <dict> <key>Hour</key> <integer>12</integer> <key>Minute</key> <integer>30</integer> </dict> </dict> </plist>

Script:
mdatp --scan --quick

So I do a sudo launchctl list and find that the PID is "-" and the Status is "0" which sounds like it was executed successfully.

sudo launchctl list com.org.mdatpquickscan shows LastExitStatus = 0 as well but day in and day out the quick scan does not run at 12:30pm as I would like. Any help is appreciated!

14 REPLIES 14

dlondon
Valued Contributor

I'm just editing this post as I found a couple of issues with the plists I shared

There's an example here: https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/mac-schedule-scan-atp

I made this one called com.microsoft.wdav.schedquickscan.plist and placed it in /Library/LaunchDaemons with the correct permissions - 644 and ownership root:wheel. It does a quick scan at 3pm (1500) daily.

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.microsoft.wdav.schedquickscan</string> <key>ProgramArguments</key> <array> <string>sh</string> <string>-c</string> <string>/usr/local/bin/mdatp --scan --quick</string> </array> <key>StartCalendarInterval</key> <dict> <key>Hour</key> <integer>15</integer> <key>Minute</key> <integer>0</integer> </dict> <key>WorkingDirectory</key> <string>/usr/local/bin/</string> </dict> </plist>

That's working like a champ. A similar one to do a full scan once a week com.microsoft.wdav.schedfullscan.plist is below

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.microsoft.wdav.schedfullscan</string> <key>ProgramArguments</key> <array> <string>sh</string> <string>-c</string> <string>/usr/local/bin/mdatp --scan --full</string> </array> <key>StartCalendarInterval</key> <dict> <key>Weekday</key> <integer>4</integer> <key>Hour</key> <integer>12</integer> <key>Minute</key> <integer>0</integer> </dict> <key>WorkingDirectory</key> <string>/usr/local/bin/</string> </dict> </plist>

You can check that they are loaded in the command line by typing

sudo launchctl list | grep com.microsoft.wdav

Check the man page for other commands for launchctl such as load, unload, start, stop etc

k0bject
New Contributor

How did you guys deploy this with JamF?

dvasquez
Valued Contributor

kiltedtenor
New Contributor III

Not to resurrect an old thread, I agree with k0bject, Microsoft's doc on this assumes a lot of knowledge about launchd work that I don't have. Can either of you guys speak to how you actually got this deployed via Jamf?

pramodmac
New Contributor III

I have recently followed Microsoft's doc, & setup all config profiles but stumbled at this same place, I'm also following this thread to learn, thank you for resurrecting the thread @tdudley

dlondon
Valued Contributor

The way you can package things that are on a hard drive easily is to use Jamf Composer. That is available as part of your subscription. One way to use it is to do a before and after snapshot. However if you cancel out of the snapshot mode you can use it a different way. So get Composer to its main screen after cancelling the snapshot screen.

Then open finder and drill down to /Library/LaunchDaemons and locate the LaunchDaemon you want to deploy. Drag it to the left sidebar in Composer. You should see a new object created with the name of the LaunchDaemon on the left and in the right pane you should see the directory structure /Library/LaunchDaemons/yourdaemon

Rename the object to suit your purposes and select the object and make a DMG from it. Up load the DMG to your Jamf Pro Server. Deploy the Launch Daemon at the beginning of your Defender installation. Remember to deploy all the necessary Configuration Profiles before deploying Defender

dlondon
Valued Contributor

Actually I looked at my current workflow and it's all done with scripts. Here's the LaunchDaemon script:

#!/bin/bash
# 2020-12-08 David London
# Defender-CreateScheduledScanLaunchDaemons.bash
# Create the Defender scheduled scan Launch Daemons using a script 


echo "Creating Weekly Full Scan plist /Library/LaunchDaemons/com.microsoft.wdav.schedfullscan.plist" 
# Weekly Full Scan 
echo '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.microsoft.wdav.schedfullscan</string>
    <key>ProgramArguments</key>
    <array>
        <string>sh</string>
        <string>-c</string>
        <string>/usr/local/bin/mdatp --scan --full</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Weekday</key>
        <integer>2</integer>
        <key>Hour</key>
        <integer>12</integer>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
    <key>WorkingDirectory</key>
    <string>/usr/local/bin/</string>
</dict>
</plist>' > /Library/LaunchDaemons/com.microsoft.wdav.schedfullscan.plist


echo "Creating Daily Quick Scan plist /Library/LaunchDaemons/com.microsoft.wdav.schedquickscan.plist"
# Daily Quick Scan
echo '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.microsoft.wdav.schedquickscan</string>
    <key>ProgramArguments</key>
    <array>
        <string>sh</string>
        <string>-c</string>
        <string>/usr/local/bin/mdatp --scan --quick</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>15</integer>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
    <key>WorkingDirectory</key>
    <string>/usr/local/bin/</string>
</dict>
</plist>' > /Library/LaunchDaemons/com.microsoft.wdav.schedquickscan.plist


exit 0

dlondon
Valued Contributor

Corrected script with all the other input:

 

 

#!/bin/bash
# 2020-12-08 David London
# Defender-CreateScheduledScanLaunchDaemons.bash
# Create the Defender scheduled scan Launch Daemons using a script so that we can target machines that are on Unifi as they can't access the UWA DP


echo "Creating Weekly Full Scan plist /Library/LaunchDaemons/com.microsoft.wdav.schedfullscan.plist" 
# Weekly Full Scan 
echo '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.microsoft.wdav.schedfullscan</string>
    <key>ProgramArguments</key>
    <array>
        <string>sh</string>
        <string>-c</string>
        <string>/usr/local/bin/mdatp scan full</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Weekday</key>
        <integer>2</integer>
        <key>Hour</key>
        <integer>12</integer>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
    <key>WorkingDirectory</key>
    <string>/usr/local/bin/</string>
</dict>
</plist>' > /Library/LaunchDaemons/com.microsoft.wdav.schedfullscan.plist


echo "Creating Daily Quick Scan plist /Library/LaunchDaemons/com.microsoft.wdav.schedquickscan.plist"
# Daily Quick Scan
echo '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.microsoft.wdav.schedquickscan</string>
    <key>ProgramArguments</key>
    <array>
        <string>sh</string>
        <string>-c</string>
        <string>/usr/local/bin/mdatp scan quick</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>15</integer>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
    <key>WorkingDirectory</key>
    <string>/usr/local/bin/</string>
</dict>
</plist>' > /Library/LaunchDaemons/com.microsoft.wdav.schedquickscan.plist

# Set the permissions and ownership
/usr/sbin/chown root:wheel "/Library/LaunchDaemons/com.microsoft.wdav.schedfullscan.plist"
/bin/chmod 644 "/Library/LaunchDaemons/com.microsoft.wdav.schedfullscan.plist"

/usr/sbin/chown root:wheel "/Library/LaunchDaemons/com.microsoft.wdav.schedquickscan.plist"
/bin/chmod 644 "/Library/LaunchDaemons/com.microsoft.wdav.schedquickscan.plist"

# Load the launchdaemons
/bin/launchctl load -w  /Library/LaunchDaemons/com.microsoft.wdav.schedquickscan.plist
/bin/launchctl load -w  /Library/LaunchDaemons/com.microsoft.wdav.schedfullscan.plist
exit 0

 

 

pramodmac
New Contributor III

Thank you @dlondon
I Will go through, and will get back here if I need help,
much appreciated.

skywada
New Contributor II

Hello all! I am also struggling with this.

I used @dlondon 's script which works great at placing the plist files in the LaunchDaemon folder but the scheduled scans still don't work. I noticed that if I copy and paste the plist to my desktop then copy and paste it back into the LaunchDaemons folder (without making other changes except for the time) the plist takes effect and the permissions change. I think I need to adjust something either in the script or somewhere in my policy to make sure the correct permissions are inherited, but I am not exactly sure where. Any advice?
535d2b3c11f7445b960493a516e1e2d9

sdagley
Esteemed Contributor II

@skawada The script @dlondon posted doesn't set the ownership and permissions required for a LaunchDaemon. Add the following to the end of the script:

/usr/sbin/chown root:wheel "/Library/LaunchDaemons/com.microsoft.wdav.schedfullscan.plist"
/bin/chmod 644 "/Library/LaunchDaemons/com.microsoft.wdav.schedfullscan.plist"

/usr/sbin/chown root:wheel "/Library/LaunchDaemons/com.microsoft.wdav.schedquickscan.plist"
/bin/chmod 644 "/Library/LaunchDaemons/com.microsoft.wdav.schedquickscan.plist"

That will allow the LaunchDaemons to load the next time the Mac is restarted. If you want to load them immediately also add the following lines:

/bin/launchctl bootstrap system "/Library/LaunchDaemons/com.microsoft.wdav.schedfullscan.plist"
/bin/launchctl bootstrap system "/Library/LaunchDaemons/com.microsoft.wdav.schedquickscan.plist"

SBod
New Contributor II

Alongside what is mentioned with regards to the correct permissions, test removing the dash from the string in the script - <string>/usr/local/bin/mdatp --scan --quick</string>.

Microsoft Documentation has it set as the following as an example: <string>/usr/local/bin/mdatp scan quick</string>

Then to test without restarting the device, set your new timings/schedule that you want to use and unload and reload the Daemon:

launchctl unload /Library/LaunchDaemons/com.microsoft.wdav.schedquickscan.plist
launchctl load /Library/LaunchDaemons/com.microsoft.wdav.schedquickscan.plist

Alternatively set your timings in the script. Execute script and restart the device.
Open Defender App, you should see the quickscan trigger at the schedule you set.

It appears you can also set schedule daily or weekly scan via jamf policy > Files and processes command:

mdatp scan quick
mdatp scan full

Then set to run at daily, weekly recurring check etc, use the client side limitations to limit to time of day if required.

I guess it depends if you prefer the overhead to be client side rather then Jamf server side.

skywada
New Contributor II

@sdagley Thank you so much for that. That seemed to fix my script! It is working beautifully now.

@SBod Thank you for your input. I noticed that about the original string too and made changes accordingly. It hadn't occurred to me to use the files and processes command, that is a much simpler way of scheduling the scans. However, some of these devices will not consistently be enrolled in jamf, in which case, I wouldn't be able to use the command, but for devices we actively maintain I will be sure to keep that in mind!

I really appreciate this community so much, thank you all for your expertise!

GregE
Contributor

Any tips on why it doesn't seem to be loading correctly for me? I've tried launchctl unload/load and a reboot, and have done the above chmod and bootstrap options when deploying it.
edit: launchctl error bootstrap 2 returns os/kern protection failure. I am using the System Extensions config profile to pre-approve com.microsoft.wdav.netext and com.microsoft.wdav.epsext
edit 2: Seems I needed to add the start command to my deployment script launchctl start /Library/LaunchDaemons/com.microsoft.wdav.schedquickscan.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.microsoft.wdav.schedquickscan</string>
    <key>ProgramArguments</key>
    <array>
        <string>sh</string>
        <string>-c</string>
        <string>/usr/local/bin/mdatp --scan --quick</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>12</integer>
        <key>Minute</key>
        <integer>00</integer>
    </dict>
    <key>WorkingDirectory</key>
    <string>/usr/local/bin/</string>
</dict>
</plist>

bb709642051f4930a9c1079f4514ccbb