Guided hunting notebook: Use Jupyter notebooks with m365 defender

Microsoft 365 Defender has a feature that is called ‘Advanced Hunting’, which is a query based hunting tool that allows you to explore up to 30 days of raw data. This allows threat hunters to analyze data across different domains such as, identities, endpoints, cloud apps, email and documents. While using the Advanced Hunting feature in the portal is great. There are some limitations around it, because you can only run, one query each time. To solve this problem, we can use Jupyter Notebooks to makes it easier to run queries, while also document each query that we ran. Making it reproducible for other threat hunters as well. This sample notebook can be accessed here and will be explained more in detail in this blog post.


Many organizations are using Microsoft 365 Defender and it provides an out-of-the-box hunting tool to explore raw data. However, the tool itself is a nice idea. We can extend it’s capabilities to make it more useful. This Guided Hunting Notebook was created to help threat hunters to expand their hunting capabilities and go beyond using the M365 portal.

M365 – Advanced Hunting (Portal)

App Registration

Before we can use Jupyter Notebooks. We have to register an application in Azure AD and give it the right permissions to be able, to query all the data in Microsoft 365 Defender.

In order to create a new application, you have to do the following:

  • Go to the Azure Portal 
  • Search for “App registrations” in the search bar and press enter
  • Click “New registration”
  • Give your app a name and click on “register”

Once you have followed the steps above, you can start assigning the API permissions.

  • Click “API permissions”
  • Click “Add a permission”
  • Click “APIs my organization uses”
  • Search for “Microsoft Threat Protection” in the search bar and press enter
  • Select “Application permissions”
  • Assign the permissions to the application

Make sure that you don’t forget to grant admin consent when you have assigned the permissions.

Creating Client Secret

A client secret is a secret known only to your application to prove it’s identity when requesting a token. It protects your resource by only granting an access token to the authorized persons that have access to the secret. This client secret needs to be stored somewhere in a safe place, such as an Azure Key Vault, and monitored when users are making a request to it.

Create a client secret and store it’s credentials in a safe place. We will need to use this client secret to get an access token for the Microsoft 365 Defender service, so don’t lose it!

Setting Up Jupyter Notebooks

There are different ways to run notebooks, whether it’s via Azure or locally. However, we are going to run it locally on our machine, so the first thing we have to do is download Visual Studio Code, and once we have downloaded it. We need to download Python. It’s always recommended to install the latest versions of course.

Now when we open Visual Studio Code, we have to install the “Jupyter” extension.

Once this extension has been installed. We need to install the “Python” extension.

Now when we press “Ctrl + Shift + P” it will open a new Jupyter Notebook.

Select a Python interpreter.

Configuring the Notebook

Once you have set up your Notebook environment, open up the Guided Hunting Notebook – Hunting suspicious LDAP reconnaissance activities

Running the first two cells in the notebook will install all the libraries and you will obtain an access token as we have discussed previously. Make sure that the client secret is correct, because otherwise you won’t be able to authenticate.

Get LDAP Search Filters

Here we are running a cell that is a KQL query and it will return a Pandas data frame that you can explore further. It is similar to what you would see, when you run a query in Log Analytics for instance.

The KQL query uses the parse_json function to parse all the values that are stored in the ‘AdditionalFields’ column, which is necessary to do, because it would provide more data that we could use to optimize our query.

Run LDAP queries

We need to generate logs in Microsoft Defender for Endpoint, so in every cell. There is a short description included that will help you to run a LDAP query to generate logs, but also contains a KQL query to hunt for it.

LDAP queries can be ran by every domain user and doesn’t require any additional privileges to do so. Unfortunately, Jupyter Notebooks removes all the square brackets in the description, so when you want to run a LDAP query. Make sure that you include the square brackets [] at ‘adsisearcher’.



Sample of Notebook


Jupyter Notebooks provides much more efficiency, because it allows you to document each step in your hunting engagement, which you can’t do within the M365 portal. What makes it great as well is, the fact that you can share it with others, so they can reproduce all the steps or edit it.

This sample notebook covers details about hunting in LDAP data and provides a simple way to run LDAP queries that are considered ‘suspicious’. It provides a few examples on different LDAP search filters that might be worth to look at in order discover potential reconnaissance activities.

If you have any ideas or you want to change certain things in the notebook. Please feel free to do so, and share it with the rest of the community.

Happy hunting!


Microsoft Threat Protection ‘Jupyter notebook’ #AdvancedHunting sample

Hunting for reconnaissance activities using LDAP search filters


  • great post! Have you experienced queries taken a long time to execute when using the API? Mine take forever 70% of the time


    • Yes, however that really depends on the query you run. Like when using the API. I always try to remind myself to make my KQL query ‘efficient’, so it won’t load that long.


Leave a Reply to m365guy Cancel reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s