Skip to content

Instantly share code, notes, and snippets.

@kappa7194
Created December 5, 2017 17:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kappa7194/30473a6261e34a518bf5433702bde041 to your computer and use it in GitHub Desktop.
Save kappa7194/30473a6261e34a518bf5433702bde041 to your computer and use it in GitHub Desktop.
An example on how to decode Active Directory's User-Parameters attribute
namespace UserParametersParser
{
using System;
using System.DirectoryServices.Protocols;
using System.IO;
using System.Net;
using System.Text;
public static class Program
{
public static void Main(string[] args)
{
LdapDirectoryIdentifier ldapDirectoryIdentifier = new LdapDirectoryIdentifier(SERVER_NAME, 389, true, false);
NetworkCredential networkCredential = new NetworkCredential(USER_NAME, USER_PASSWORD, USER_DOMAIN);
LdapConnection ldapConnection = new LdapConnection(ldapDirectoryIdentifier, networkCredential, AuthType.Kerberos);
SearchRequest searchRequest = new SearchRequest(SEARCH_ROOT, SEARCH_FILTER, SearchScope.Subtree, "userParameters");
SearchResponse searchResponse = (SearchResponse) ldapConnection.SendRequest(searchRequest);
foreach (SearchResultEntry searchResultEntry in searchResponse.Entries)
{
// REMEMBER
// This WILL throw an exception if you read an object without the attribute.
// Do check if the attribute exists before accessing it.
var directoryAttribute = searchResultEntry.Attributes["userParameters"];
var userParametersAttribute = (string) directoryAttribute[0];
UserParameters userParameters = GetUserParameters(userParametersAttribute);
}
}
private static UserParameters GetUserParameters(string attributeValue)
{
UserParameters userParameters = new UserParameters();
byte[] bytes = Encoding.Unicode.GetBytes(attributeValue);
using (MemoryStream memoryStream = new MemoryStream(bytes))
{
using (BinaryReader binaryReader = new BinaryReader(memoryStream, Encoding.Unicode, true))
{
byte[] reservedData = binaryReader.ReadBytes(96);
byte[] signature = binaryReader.ReadBytes(2);
byte[] tsPropertyCount = binaryReader.ReadBytes(2);
string signatureValue = Encoding.Unicode.GetString(signature);
ushort tsPropertyCountValue = BitConverter.ToUInt16(tsPropertyCount, 0);
for (int i = 0; i < tsPropertyCountValue; i++)
{
byte[] nameLength = binaryReader.ReadBytes(2);
byte[] valueLength = binaryReader.ReadBytes(2);
byte[] type = binaryReader.ReadBytes(2);
ushort nameLengthValue = BitConverter.ToUInt16(nameLength, 0);
ushort valueLengthValue = BitConverter.ToUInt16(valueLength, 0);
ushort typeValue = BitConverter.ToUInt16(type, 0);
byte[] propName = binaryReader.ReadBytes(nameLengthValue);
byte[] propValue = binaryReader.ReadBytes(valueLengthValue);
string propNameValue = Encoding.Unicode.GetString(propName);
byte[] propValueValue = GetPropValueValue(propValue);
if (string.Equals(propNameValue, nameof(UserParameters.CtxCfgPresent), StringComparison.OrdinalIgnoreCase))
{
userParameters.CtxCfgPresent = BitConverter.ToUInt32(propValueValue, 0);
}
else if (string.Equals(propNameValue, nameof(UserParameters.CtxCfgFlags1), StringComparison.OrdinalIgnoreCase))
{
userParameters.CtxCfgFlags1 = (CtxCfgFlags1) BitConverter.ToUInt32(propValueValue, 0);
}
else if (string.Equals(propNameValue, nameof(UserParameters.CtxCallBack), StringComparison.OrdinalIgnoreCase))
{
userParameters.CtxCallBack = BitConverter.ToUInt32(propValueValue, 0);
}
else if (string.Equals(propNameValue, nameof(UserParameters.CtxKeyboardLayout), StringComparison.OrdinalIgnoreCase))
{
userParameters.CtxKeyboardLayout = BitConverter.ToUInt32(propValueValue, 0);
}
else if (string.Equals(propNameValue, nameof(UserParameters.CtxNwLogonServer), StringComparison.OrdinalIgnoreCase))
{
userParameters.CtxNwLogonServer = BitConverter.ToUInt32(propValueValue, 0);
}
else if (string.Equals(propNameValue, nameof(UserParameters.CtxMaxConnectionTime), StringComparison.OrdinalIgnoreCase))
{
userParameters.CtxMaxConnectionTime = BitConverter.ToUInt32(propValueValue, 0);
}
else if (string.Equals(propNameValue, nameof(UserParameters.CtxMaxDisconnectionTime), StringComparison.OrdinalIgnoreCase))
{
userParameters.CtxMaxDisconnectionTime = BitConverter.ToUInt32(propValueValue, 0);
}
else if (string.Equals(propNameValue, nameof(UserParameters.CtxMaxIdleTime), StringComparison.OrdinalIgnoreCase))
{
userParameters.CtxMaxIdleTime = BitConverter.ToUInt32(propValueValue, 0);
}
else if (string.Equals(propNameValue, nameof(UserParameters.CtxShadow), StringComparison.OrdinalIgnoreCase))
{
userParameters.CtxShadow = (CtxShadow) BitConverter.ToUInt32(propValueValue, 0);
}
else if (string.Equals(propNameValue, nameof(UserParameters.CtxMinEncryptionLevel), StringComparison.OrdinalIgnoreCase))
{
userParameters.CtxMinEncryptionLevel = propValueValue[0];
}
else if (string.Equals(propNameValue, nameof(UserParameters.CtxWfHomeDir), StringComparison.OrdinalIgnoreCase))
{
userParameters.CtxWfHomeDir = Encoding.ASCII.GetString(propValueValue, 0, propValueValue.Length - 1);
}
else if (string.Equals(propNameValue, nameof(UserParameters.CtxWfHomeDirDrive), StringComparison.OrdinalIgnoreCase))
{
userParameters.CtxWfHomeDirDrive = Encoding.ASCII.GetString(propValueValue, 0, propValueValue.Length - 1);
}
else if (string.Equals(propNameValue, nameof(UserParameters.CtxInitialProgram), StringComparison.OrdinalIgnoreCase))
{
userParameters.CtxInitialProgram = Encoding.ASCII.GetString(propValueValue, 0, propValueValue.Length - 1);
}
else if (string.Equals(propNameValue, nameof(UserParameters.CtxWfProfilePath), StringComparison.OrdinalIgnoreCase))
{
userParameters.CtxWfProfilePath = Encoding.ASCII.GetString(propValueValue, 0, propValueValue.Length - 1);
}
else if (string.Equals(propNameValue, nameof(UserParameters.CtxWorkDirectory), StringComparison.OrdinalIgnoreCase))
{
userParameters.CtxWorkDirectory = Encoding.ASCII.GetString(propValueValue, 0, propValueValue.Length - 1);
}
else if (string.Equals(propNameValue, nameof(UserParameters.CtxCallbackNumber), StringComparison.OrdinalIgnoreCase))
{
userParameters.CtxCallbackNumber = Encoding.ASCII.GetString(propValueValue, 0, propValueValue.Length - 1);
}
else
{
throw new Exception("Unsupported property.");
}
}
}
}
return userParameters;
}
private static byte[] GetPropValueValue(byte[] propValue)
{
byte[] propValueValue = new byte[propValue.Length / 2];
for (int j = 0; j < propValue.Length; j = j + 2)
{
int highNibble = HexToInt(propValue[j]);
int lowNibble = HexToInt(propValue[j + 1]);
propValueValue[j / 2] = (byte) (highNibble << 4 | lowNibble);
}
return propValueValue;
}
private static int HexToInt(byte value)
{
if ('0' <= value && value <= '9')
{
return value - '0';
}
if ('a' <= value && value <= 'f')
{
return value - 'a' + 10;
}
if ('A' <= value && value <= 'F')
{
return value - 'A' + 10;
}
throw new Exception("Invalid character.");
}
}
public class UserParameters
{
public uint? CtxCfgPresent { get; set; }
public CtxCfgFlags1? CtxCfgFlags1 { get; set; }
public uint? CtxCallBack { get; set; }
public uint? CtxKeyboardLayout { get; set; }
public byte? CtxMinEncryptionLevel { get; set; }
public uint? CtxNwLogonServer { get; set; }
public string CtxWfHomeDir { get; set; }
public string CtxWfHomeDirDrive { get; set; }
public string CtxInitialProgram { get; set; }
public uint? CtxMaxConnectionTime { get; set; }
public uint? CtxMaxDisconnectionTime { get; set; }
public uint? CtxMaxIdleTime { get; set; }
public string CtxWfProfilePath { get; set; }
public CtxShadow? CtxShadow { get; set; }
public string CtxWorkDirectory { get; set; }
public string CtxCallbackNumber { get; set; }
}
[Flags]
public enum CtxCfgFlags1 : uint
{
Undefined1 = 0x00000000,
Undefined2 = 0x00000001,
Undefined3 = 0x00000002,
DisableCam = 0x00000004,
WallpaperDisabled = 0x00000008,
DisableExe = 0x00000010,
DisableClip = 0x00000020,
DisableLpt = 0x00000040,
DisableCcm = 0x00000080,
DisableCdm = 0x00000100,
DisableCpm = 0x00000200,
UseDefaultGina = 0x00000400,
HomeDirectoryMapRoot = 0x00000800,
DisableEncryption = 0x00001000,
ForceClientLptDef = 0x00002000,
AutoClientLpts = 0x00004000,
AutoClientDrives = 0x00008000,
LogonDisabled = 0x00010000,
ReconnectSame = 0x00020000,
ResetBroken = 0x00040000,
PromptForPassword = 0x00080000,
InheritSecurity = 0x00100000,
InheritAutoClient = 0x00200000,
InheritMaxIdleTime = 0x00400000,
InheritMaxdisconnectionTime = 0x00800000,
InheritMaxsessionTime = 0x01000000,
InheritShadow = 0x02000000,
InheritCallbackNumber = 0x04000000,
InheritCallback = 0x08000000,
Undefined4 = 0x10000000,
Undefined5 = 0x20000000,
Undefined6 = 0x40000000,
Undefined7 = 0x80000000
}
public enum CtxShadow : uint
{
Disable = 0x00000000,
EnableInputNotify = 0x00000001,
EnableInputNoNotify = 0x00000002,
EnableNoInputNotify = 0x00000003,
EnableNoInputNoNotify = 0x00000004
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment