Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save 0xa-saline/082b9f32a526f6adc54208f400015a94 to your computer and use it in GitHub Desktop.
Save 0xa-saline/082b9f32a526f6adc54208f400015a94 to your computer and use it in GitHub Desktop.
GetAadJoinInformation C# Module
using System;
using System.Collections.Generic;
using System.Management;
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
using System.Text;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Collections;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Reflection;
namespace Core.ActiveDirectory
{
public class NetAPI32
{
public const int ErrorSuccess = 0;
[DllImport("Netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int NetGetJoinInformation(string server, out IntPtr domain, out NetJoinStatus status);
[DllImport("Netapi32.dll")]
public static extern int NetApiBufferFree(IntPtr Buffer);
public enum NetJoinStatus
{
NetSetupUnknownStatus = 0,
NetSetupUnjoined,
NetSetupWorkgroupName,
NetSetupDomainName
}
public enum DSREG_JOIN_TYPE
{
DSREG_UNKNOWN_JOIN,
DSREG_DEVICE_JOIN,
DSREG_WORKPLACE_JOIN
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct DSREG_USER_INFO
{
[MarshalAs(UnmanagedType.LPWStr)] public string UserEmail;
[MarshalAs(UnmanagedType.LPWStr)] public string UserKeyId;
[MarshalAs(UnmanagedType.LPWStr)] public string UserKeyName;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct CERT_CONTEX
{
public uint dwCertEncodingType;
public byte pbCertEncoded;
public uint cbCertEncoded;
public IntPtr pCertInfo;
public IntPtr hCertStore;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct DSREG_JOIN_INFO
{
public int joinType;
public IntPtr pJoinCertificate;
[MarshalAs(UnmanagedType.LPWStr)] public string DeviceId;
[MarshalAs(UnmanagedType.LPWStr)] public string IdpDomain;
[MarshalAs(UnmanagedType.LPWStr)] public string TenantId;
[MarshalAs(UnmanagedType.LPWStr)] public string JoinUserEmail;
[MarshalAs(UnmanagedType.LPWStr)] public string TenantDisplayName;
[MarshalAs(UnmanagedType.LPWStr)] public string MdmEnrollmentUrl;
[MarshalAs(UnmanagedType.LPWStr)] public string MdmTermsOfUseUrl;
[MarshalAs(UnmanagedType.LPWStr)] public string MdmComplianceUrl;
[MarshalAs(UnmanagedType.LPWStr)] public string UserSettingSyncUrl;
public IntPtr pUserInfo;
}
[DllImport("netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern void NetFreeAadJoinInformation(
IntPtr pJoinInfo);
[DllImport("netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int NetGetAadJoinInformation(
string pcszTenantId,
out IntPtr ppJoinInfo);
}
class AD
{
// https://stackoverflow.com/questions/926227/how-to-detect-if-machine-is-joined-to-domain
public static bool IsInDomain()
{
NetAPI32.NetJoinStatus status = NetAPI32.NetJoinStatus.NetSetupUnknownStatus;
IntPtr pDomain = IntPtr.Zero;
int result = NetAPI32.NetGetJoinInformation(null, out pDomain, out status);
if (pDomain != IntPtr.Zero)
{
NetAPI32.NetApiBufferFree(pDomain);
}
if (result == NetAPI32.ErrorSuccess)
{
return status == NetAPI32.NetJoinStatus.NetSetupDomainName;
}
else
{
throw new Exception("Domain Info Get Failed", new Win32Exception());
}
}
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/18d8fbe8-a967-4f1c-ae50-99ca8e491d2d
// https://docs.microsoft.com/en-us/windows/win32/api/lmjoin/nf-lmjoin-netgetaadjoininformation
// https://support.microsoft.com/en-us/help/2909958/exceptions-in-windows-powershell-other-dynamic-languages-and-dynamical
// https://deploywindows.com/2020/09/16/dont-wrap-dsregcmd-with-powershell-use-this-to-get-azure-ad-information-from-the-local-computer/
public static void getaadjoininformation()
{
string pcszTenantId = null;
var ptrJoinInfo = IntPtr.Zero;
var ptrUserInfo = IntPtr.Zero;
var ptrJoinCertificate = IntPtr.Zero;
NetAPI32.DSREG_JOIN_INFO joinInfo = new NetAPI32.DSREG_JOIN_INFO();
NetAPI32.NetFreeAadJoinInformation(IntPtr.Zero);
var retValue = NetAPI32.NetGetAadJoinInformation(pcszTenantId, out ptrJoinInfo);
if (retValue == 0)
{
Console.WriteLine($"[+] Starting Aad Enum:");
try
{
NetAPI32.DSREG_JOIN_INFO ptrJoinInfoObject = new NetAPI32.DSREG_JOIN_INFO();
joinInfo = (NetAPI32.DSREG_JOIN_INFO)System.Runtime.InteropServices.Marshal.PtrToStructure(ptrJoinInfo, (System.Type)ptrJoinInfoObject.GetType());
FieldInfo[] fi = typeof(NetAPI32.DSREG_JOIN_INFO).GetFields(BindingFlags.Public | BindingFlags.Instance);
foreach (FieldInfo info in fi)
{
var x = info.GetValue(joinInfo);
Console.WriteLine($" > {info.Name} : {x}");
}
}
catch (Exception e)
{
Console.WriteLine($"[-] Error running Aad Enum: {e.Message}");
}
try
{
Console.WriteLine($"\n[+] Starting UserInfo Enum:");
ptrUserInfo = joinInfo.pUserInfo;
NetAPI32.DSREG_USER_INFO ptrUserInfoObject = new NetAPI32.DSREG_USER_INFO();
NetAPI32.DSREG_USER_INFO userInfo = (NetAPI32.DSREG_USER_INFO)System.Runtime.InteropServices.Marshal.PtrToStructure(ptrUserInfo, (System.Type)ptrUserInfoObject.GetType());
FieldInfo[] fi = typeof(NetAPI32.DSREG_USER_INFO).GetFields(BindingFlags.Public | BindingFlags.Instance);
foreach (FieldInfo info in fi)
{
var x = info.GetValue(userInfo);
Console.WriteLine($" > {info.Name} : {x}");
}
}
catch (Exception e)
{
Console.WriteLine($"[-] Error running UserInfo Enum: {e.Message}");
}
try
{
Console.WriteLine($"\n[+] Starting JoinCertificate Enum:");
ptrJoinCertificate = joinInfo.pJoinCertificate;
NetAPI32.CERT_CONTEX ptrJoinCertificateObject = new NetAPI32.CERT_CONTEX();
var joinCertificate = Marshal.PtrToStructure(ptrJoinCertificate, (System.Type)ptrJoinCertificateObject.GetType());
FieldInfo[] fi = typeof(NetAPI32.CERT_CONTEX).GetFields(BindingFlags.Public | BindingFlags.Instance);
foreach (FieldInfo info in fi)
{
var x = info.GetValue(joinCertificate);
Console.WriteLine($" > {info.Name} : {x}");
}
}
catch (Exception e)
{
Console.WriteLine($"[-] Error running JoinCertificate Enum: {e.Message}");
}
Console.WriteLine($"\n[+] Starting Connect Enum:");
try
{
if (IsInDomain())
{
Console.WriteLine($" > DomainJoined : true");
}
else
{
Console.WriteLine($" > DomainJoined : false");
}
}
catch (Exception e)
{
Console.WriteLine($"[-] Error running Domain Join Check Enum: {e.Message}");
}
switch ((NetAPI32.DSREG_JOIN_TYPE)joinInfo.joinType)
{
case (NetAPI32.DSREG_JOIN_TYPE.DSREG_DEVICE_JOIN): { Console.WriteLine(" > AzureAD Joined : true"); break; }
case (NetAPI32.DSREG_JOIN_TYPE.DSREG_UNKNOWN_JOIN): { Console.WriteLine(" > Device is not joined"); break; }
case (NetAPI32.DSREG_JOIN_TYPE.DSREG_WORKPLACE_JOIN): { Console.WriteLine(" > Workplace Joined : true"); break; }
}
try
{
if (ptrJoinInfo != IntPtr.Zero)
{
Marshal.Release(ptrJoinInfo);
}
if (ptrUserInfo != IntPtr.Zero)
{
Marshal.Release(ptrUserInfo);
}
if (ptrJoinCertificate != IntPtr.Zero)
{
Marshal.Release(ptrJoinCertificate);
}
}
catch (Exception e)
{
Console.WriteLine($"\n[-] Error Releasing PTRs: {e.Message}");
}
}
else
{
Console.WriteLine("[-] No NetGetAadJoinInformation Info");
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment