259 lines
15 KiB
C#
259 lines
15 KiB
C#
using System;
|
|
using System.Runtime.ConstrainedExecution;
|
|
using System.Runtime.InteropServices;
|
|
using System.Security.AccessControl;
|
|
using System.Security.Principal;
|
|
using System.Text;
|
|
using winPEAS.Helpers.CredentialManager;
|
|
using winPEAS.Info.NetworkInfo;
|
|
using winPEAS.Native.Classes;
|
|
using winPEAS.Native.Enums;
|
|
using winPEAS.Native.Structs;
|
|
|
|
namespace winPEAS.Native
|
|
{
|
|
internal class Advapi32
|
|
{
|
|
/// <summary>
|
|
/// The CredRead function reads a credential from the user's credential set.
|
|
/// The credential set used is the one associated with the logon session of the current token.
|
|
/// The token must not have the user's SID disabled.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// If the value of the Type member of the CREDENTIAL structure specified by the Credential parameter is
|
|
/// CRED_TYPE_DOMAIN_EXTENDED, a namespace must be specified in the target name. This function can return only one
|
|
/// credential of the specified type.
|
|
/// </remarks>
|
|
/// <param name="target">Pointer to a null-terminated string that contains the name of the credential to read.</param>
|
|
/// <param name="type">Type of the credential to read. Type must be one of the CRED_TYPE_* defined types.</param>
|
|
/// <param name="reservedFlag">Currently reserved and must be zero.</param>
|
|
/// <param name="credentialPtr">
|
|
/// Pointer to a single allocated block buffer to return the credential.
|
|
/// Any pointers contained within the buffer are pointers to locations within this single allocated block.
|
|
/// The single returned buffer must be freed by calling CredFree.
|
|
/// </param>
|
|
/// <returns>The function returns TRUE on success and FALSE on failure.</returns>
|
|
[DllImport("Advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)]
|
|
internal static extern bool CredRead(string target, CredentialType type, int reservedFlag, out IntPtr credentialPtr);
|
|
|
|
/// <summary>
|
|
/// The CredWrite function creates a new credential or modifies an existing credential in the user's credential set.
|
|
/// The new credential is associated with the logon session of the current token.
|
|
/// The token must not have the user's security identifier (SID) disabled.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This function creates a credential if a credential with the specified TargetName and Type does not exist. If a
|
|
/// credential with the specified TargetName and Type exists, the new specified credential replaces the existing one.
|
|
/// When this function writes a CRED_TYPE_CERTIFICATE credential, the Credential->CredentialBlob member specifies the
|
|
/// PIN protecting the private key of the certificate specified by the Credential->UserName member. The credential
|
|
/// manager does not maintain the PIN. Rather, the PIN is passed to the cryptographic service provider (CSP) indicated
|
|
/// on the certificate for later use by the CSP and the authentication packages. The CSP defines the lifetime of the
|
|
/// PIN. Most CSPs flush the PIN when the smart card removal from the smart card reader.
|
|
/// If the value of the Type member of the CREDENTIAL structure specified by the Credential parameter is
|
|
/// CRED_TYPE_DOMAIN_EXTENDED, a namespace must be specified in the target name. This function does not support writing
|
|
/// to target names that contain wildcards.
|
|
/// </remarks>
|
|
/// <param name="userCredential">A pointer to the CREDENTIAL structure to be written.</param>
|
|
/// <param name="flags">Flags that control the function's operation. The following flag is defined.</param>
|
|
/// <returns>If the function succeeds, the function returns TRUE, if the function fails, it returns FALSE. </returns>
|
|
[DllImport("Advapi32.dll", EntryPoint = "CredWriteW", CharSet = CharSet.Unicode, SetLastError = true)]
|
|
internal static extern bool CredWrite([In] ref NativeMethods.CREDENTIAL userCredential, [In] UInt32 flags);
|
|
|
|
/// <summary>
|
|
/// The CredFree function frees a buffer returned by any of the credentials management functions.
|
|
/// </summary>
|
|
/// <param name="cred">Pointer to the buffer to be freed.</param>
|
|
[DllImport("Advapi32.dll", EntryPoint = "CredFree", SetLastError = true)]
|
|
internal static extern void CredFree([In] IntPtr cred);
|
|
|
|
/// <summary>
|
|
/// The CredDelete function deletes a credential from the user's credential set.
|
|
/// The credential set used is the one associated with the logon session of the current token.
|
|
/// The token must not have the user's SID disabled.
|
|
/// </summary>
|
|
/// <param name="target">Pointer to a null-terminated string that contains the name of the credential to delete.</param>
|
|
/// <param name="type">
|
|
/// Type of the credential to delete. Must be one of the CRED_TYPE_* defined types.
|
|
/// For a list of the defined types, see the Type member of the CREDENTIAL structure.
|
|
/// If the value of this parameter is CRED_TYPE_DOMAIN_EXTENDED,
|
|
/// this function can delete a credential that specifies a user name when there are multiple credentials for the same
|
|
/// target. The value of the TargetName parameter must specify the user name as Target|UserName.
|
|
/// </param>
|
|
/// <param name="flags">Reserved and must be zero.</param>
|
|
/// <returns>The function returns TRUE on success and FALSE on failure.</returns>
|
|
[DllImport("Advapi32.dll", EntryPoint = "CredDeleteW", CharSet = CharSet.Unicode)]
|
|
internal static extern bool CredDelete(StringBuilder target, CredentialType type, int flags);
|
|
|
|
/// <summary>
|
|
/// Enumerate credentials in the credential store
|
|
/// signature: BOOL CredEnumerate (
|
|
/// _In_ LPCTSTR Filter,
|
|
/// _In_ DWORD Flags,
|
|
/// _Out_ DWORD *Count,
|
|
/// _Out_ PCREDENTIAL **Credentials
|
|
///);
|
|
/// <param name="filter">[in]
|
|
/// Pointer to a null-terminated string that contains the filter for the returned credentials.Only credentials with a TargetName matching the filter will be returned.The filter specifies a name prefix followed by an asterisk.For instance, the filter "FRED*" will return all credentials with a TargetName beginning with the string "FRED".
|
|
/// If NULL is specified, all credentials will be returned.</param>
|
|
/// <param name="flag">[in]
|
|
/// The value of this parameter can be zero or more of the following values combined with a bitwise-OR operation.
|
|
/// Value Meaning
|
|
/// CRED_ENUMERATE_ALL_CREDENTIALS 0x1
|
|
/// This function enumerates all of the credentials in the user's credential set. The target name of each credential is returned in the "namespace:attribute=target" format. If this flag is set and the Filter parameter is not NULL, the function fails and returns ERROR_INVALID_FLAGS.
|
|
/// Windows Server 2003 and Windows XP: This flag is not supported.
|
|
///</param>
|
|
/// <param name="count">[out] Count of the credentials returned in the Credentials array.</param>
|
|
/// <param name="pCredentials"> [out]
|
|
/// Pointer to an array of pointers to credentials.The returned credential is a single allocated block. Any pointers contained within the buffer are pointers to locations within this single allocated block.The single returned buffer must be freed by calling CredFree.
|
|
/// Return value
|
|
/// </param>
|
|
/// <returns>
|
|
/// The function returns TRUE on success and FALSE on failure. The GetLastError function can be called to get a more specific status code.The following status codes can be returned.
|
|
/// Return code/value Description
|
|
/// ERROR_NOT_FOUND
|
|
/// 1168 (0x490)
|
|
/// No credential exists matching the specified Filter.
|
|
/// ERROR_NO_SUCH_LOGON_SESSION
|
|
/// 1312 (0x520)
|
|
/// The logon session does not exist or there is no credential set associated with this logon session. Network logon sessions do not have an associated credential set.
|
|
/// ERROR_INVALID_FLAGS
|
|
/// 1004 (0x3EC)
|
|
/// A flag that is not valid was specified for the Flags parameter, or CRED_ENUMERATE_ALL_CREDENTIALS is specified for the Flags parameter and the Filter parameter is not NULL.
|
|
/// </returns>
|
|
/// </summary>
|
|
[DllImport("Advapi32.dll", EntryPoint = "CredEnumerate", SetLastError = true, CharSet = CharSet.Unicode)]
|
|
internal static extern bool CredEnumerate(string filter, int flag, out int count, out IntPtr pCredentials);
|
|
|
|
[DllImport("advapi32.dll", SetLastError = true)]
|
|
internal static extern bool OpenProcessToken(IntPtr ProcessHandle, uint DesiredAccess, out IntPtr TokenHandle);
|
|
|
|
//////////////////////////////////////////
|
|
/////// Find Modifiable Services ////////
|
|
//////////////////////////////////////////
|
|
|
|
/// Find services that you can modify using PS os sc for example
|
|
[DllImport("advapi32.dll", SetLastError = true)]
|
|
internal static extern bool QueryServiceObjectSecurity(
|
|
IntPtr serviceHandle,
|
|
SecurityInfos secInfo,
|
|
byte[] lpSecDesrBuf,
|
|
uint bufSize,
|
|
out uint bufSizeNeeded);
|
|
|
|
[DllImport("advapi32.dll", EntryPoint = "GetNamedSecurityInfoW", CharSet = CharSet.Unicode)]
|
|
internal static extern int GetNamedSecurityInfo(
|
|
string objectName,
|
|
SE_OBJECT_TYPE objectType,
|
|
SecurityInfos securityInfo,
|
|
out IntPtr sidOwner,
|
|
out IntPtr sidGroup,
|
|
out IntPtr dacl,
|
|
out IntPtr sacl,
|
|
out IntPtr securityDescriptor);
|
|
|
|
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
|
internal static extern bool ConvertSecurityDescriptorToStringSecurityDescriptor(
|
|
IntPtr SecurityDescriptor,
|
|
uint StringSDRevision,
|
|
SecurityInfos SecurityInformation,
|
|
out IntPtr StringSecurityDescriptor,
|
|
out int StringSecurityDescriptorSize);
|
|
|
|
[DllImport("advapi32.dll", SetLastError = true)]
|
|
internal static extern bool GetTokenInformation(
|
|
IntPtr TokenHandle,
|
|
TOKEN_INFORMATION_CLASS TokenInformationClass,
|
|
IntPtr TokenInformation,
|
|
int TokenInformationLength,
|
|
out int ReturnLength);
|
|
|
|
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static extern bool LookupPrivilegeName(
|
|
string lpSystemName,
|
|
IntPtr lpLuid,
|
|
StringBuilder lpName,
|
|
ref int cchName);
|
|
|
|
[DllImport("advapi32.dll")]
|
|
internal static extern bool
|
|
DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);
|
|
|
|
[DllImport("advapi32.dll", SetLastError = true)]
|
|
internal static extern bool ImpersonateLoggedOnUser(IntPtr hToken);
|
|
|
|
[DllImport("advapi32.dll", SetLastError = true)]
|
|
internal static extern bool RevertToSelf();
|
|
|
|
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail), DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static extern bool DuplicateTokenEx([In] SafeTokenHandle ExistingTokenHandle, [In] AccessTypes DesiredAccess, [In] IntPtr TokenAttributes, [In] SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, [In] TokenType TokenType, [In, Out] ref SafeTokenHandle DuplicateTokenHandle);
|
|
|
|
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static extern bool GetTokenInformation(SafeTokenHandle hToken, TOKEN_INFORMATION_CLASS tokenInfoClass, IntPtr pTokenInfo, Int32 tokenInfoLength, out Int32 returnLength);
|
|
|
|
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
|
internal static extern int LogonUser(string lpszUserName, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
|
|
|
|
[DllImport("advapi32.dll", SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static extern bool LookupPrivilegeValue(string systemName, string name, out LUID luid);
|
|
|
|
[DllImport("advapi32.dll", SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static extern bool OpenProcessToken(IntPtr ProcessHandle, AccessTypes DesiredAccess, out SafeTokenHandle TokenHandle);
|
|
|
|
[DllImport("advapi32.dll", SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static extern bool OpenThreadToken(IntPtr ThreadHandle, AccessTypes DesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool OpenAsSelf, out SafeTokenHandle TokenHandle);
|
|
|
|
[DllImport("advapi32.dll", SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static extern bool SetThreadToken(IntPtr ThreadHandle, SafeTokenHandle TokenHandle);
|
|
|
|
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
|
internal static extern bool LookupAccountSid(
|
|
string? lpSystemName,
|
|
[MarshalAs(UnmanagedType.LPArray)] byte[] Sid,
|
|
StringBuilder lpName,
|
|
ref uint cchName,
|
|
StringBuilder ReferencedDomainName,
|
|
ref uint cchReferencedDomainName,
|
|
out SID_NAME_USE peUse);
|
|
|
|
public static string TranslateSid(string sid)
|
|
{
|
|
// adapted from http://www.pinvoke.net/default.aspx/advapi32.LookupAccountSid
|
|
var accountSid = new SecurityIdentifier(sid);
|
|
var accountSidByes = new byte[accountSid.BinaryLength];
|
|
accountSid.GetBinaryForm(accountSidByes, 0);
|
|
|
|
var name = new StringBuilder();
|
|
var cchName = (uint)name.Capacity;
|
|
var referencedDomainName = new StringBuilder();
|
|
var cchReferencedDomainName = (uint)referencedDomainName.Capacity;
|
|
|
|
var err = 0;
|
|
if (!LookupAccountSid(null, accountSidByes, name, ref cchName, referencedDomainName, ref cchReferencedDomainName, out var sidUse))
|
|
{
|
|
err = Marshal.GetLastWin32Error();
|
|
|
|
if (err == Win32Error.InsufficientBuffer)
|
|
{
|
|
name.EnsureCapacity((int)cchName);
|
|
referencedDomainName.EnsureCapacity((int)cchReferencedDomainName);
|
|
err = 0;
|
|
if (!LookupAccountSid(null, accountSidByes, name, ref cchName, referencedDomainName,
|
|
ref cchReferencedDomainName, out sidUse))
|
|
{
|
|
err = Marshal.GetLastWin32Error();
|
|
}
|
|
}
|
|
}
|
|
|
|
return err == 0 ? $"{referencedDomainName}\\{name}" : "";
|
|
}
|
|
}
|
|
}
|