techahold / rustdeskinstall

Easy install Script for Rustdesk
MIT License
379 stars 114 forks source link

Windows GPO PowerShell script deployment #5

Closed michaelortnersanube closed 2 years ago

michaelortnersanube commented 2 years ago

Hello,

as i see there are multiple ps scripts for rustdesk. WindowsAgentAIOInstall.ps1 is for the configuration of rustdesk with the proxy right? Is clientinstall.ps1 for the installation only?

We have the problem, that we use the WindowsAgentAIOInstall.ps1 for deployment, but it doesn't work. The script will be execute, but no files will be created. I think the problem is, that this script have to be manually execute on the client notebook.

Is it possible to work with GPO and this script?

Has anyone test it?

Maybe someone can explain and help me.

dinger1986 commented 2 years ago

What does it do or not do?

Have you ran the linux server install script and used the generated WindowsAgentAIOInstall.ps1 from the small web server or are you trying to use the one directly from my repo? If you are trying to use it you will need to change the variables to your rustdesk server. It says at the top of the powershell file # Replace wanipreg and keyreg with the relevant info

I dont see any reason it wouldnt work with GPO, I have used it 100s of times on my rmm server.

michaelortnersanube commented 2 years ago

Hello Sir,

it take the WindowsAgentAIOInstall.ps1 from the small web server. The information is in the ps file.

So i have it now test with the clientinstall.ps1 - this work. But for the settings i need the other script.

On the WindowsAgentAIOInstall.ps1 what it doesn't do is to create the folder c:\temp and insert the data of rustdesk

Eventviewer say this, it seems like an error:

`Details zur Pipelineausführung für die Befehlszeile: Add-Type -ReferencedAssemblies $requiredAssembly -TypeDefinition $source -Language CSharp -ErrorAction SilentlyContinue .

Kontextinformationen: DetailSequence=1 DetailTotal=1

SequenceNumber=32

UserId=HOST\SYSTEM
HostName=ConsoleHost
HostVersion=5.1.19041.1682
HostId=30c44a8f-9a20-4ab9-a0ef-168a2d9996e9
HostApplication= -ExecutionPolicy ByPass -File \\thot\netlogon\rustdesk_deploy.ps1
EngineVersion=5.1.19041.1682
RunspaceId=750a5171-1e2a-4ce4-bcee-254da1e6174f
PipelineId=6
ScriptName=C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PSModule.psm1
CommandLine=        Add-Type -ReferencedAssemblies $requiredAssembly -TypeDefinition $source -Language CSharp -ErrorAction SilentlyContinue

Details: CommandInvocation(Add-Type): "Add-Type" ParameterBinding(Add-Type): Name="ReferencedAssemblies"; Wert="System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, ..." ParameterBinding(Add-Type): Name="TypeDefinition"; Wert="using System; using System.Net; using System.Management.Automation; using Microsoft.Win32.SafeHandles; using System.Security.Cryptography; using System.Runtime.InteropServices; using System.Runtime.ConstrainedExecution; using System.Runtime.Versioning; using System.Security;

namespace Microsoft.PowerShell.Commands.PowerShellGet { public static class Telemetry
{ public static void TraceMessageArtifactsNotFound(string[] artifactsNotFound, string operationName) { Microsoft.PowerShell.Telemetry.Internal.TelemetryAPI.TraceMessage(operationName, new { ArtifactsNotFound = artifactsNotFound }); }

    public static void TraceMessageNonPSGalleryRegistration(string sourceLocationType, string sourceLocationHash, string installationPolicy, string packageManagementProvider, string publishLocationHash, string scriptSourceLocationHash, string scriptPublishLocationHash, string operationName) 
    { 
        Microsoft.PowerShell.Telemetry.Internal.TelemetryAPI.TraceMessage(operationName, new { SourceLocationType = sourceLocationType, SourceLocationHash = sourceLocationHash, InstallationPolicy = installationPolicy, PackageManagementProvider = packageManagementProvider, PublishLocationHash = publishLocationHash, ScriptSourceLocationHash = scriptSourceLocationHash, ScriptPublishLocationHash = scriptPublishLocationHash });
    }         

}

/// <summary>
/// Used by Ping-Endpoint function to supply webproxy to HttpClient
/// We cannot use System.Net.WebProxy because this is not available on CoreClr
/// </summary>
public class InternalWebProxy : IWebProxy
{
    Uri _proxyUri;
    ICredentials _credentials;

    public InternalWebProxy(Uri uri, ICredentials credentials)
    {
        Credentials = credentials;
        _proxyUri = uri;
    }

    /// <summary>
    /// Credentials used by WebProxy
    /// </summary>
    public ICredentials Credentials
    {
        get
        {
            return _credentials;
        }
        set
        {
            _credentials = value;
        }
    }

    public Uri GetProxy(Uri destination)
    {
        return _proxyUri;
    }

    public bool IsBypassed(Uri host)
    {
        return false;
    }
} 

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct CERT_CHAIN_POLICY_PARA {
    public CERT_CHAIN_POLICY_PARA(int size) {
        cbSize = (uint) size;
        dwFlags = 0;
        pvExtraPolicyPara = IntPtr.Zero;
    }
    public uint   cbSize;
    public uint   dwFlags;
    public IntPtr pvExtraPolicyPara; 
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct CERT_CHAIN_POLICY_STATUS {
    public CERT_CHAIN_POLICY_STATUS(int size) {
        cbSize = (uint) size;
        dwError = 0;
        lChainIndex = IntPtr.Zero;
        lElementIndex = IntPtr.Zero;
        pvExtraPolicyStatus = IntPtr.Zero;
    }
    public uint   cbSize;
    public uint   dwError;
    public IntPtr lChainIndex;
    public IntPtr lElementIndex;
    public IntPtr pvExtraPolicyStatus; 
}

// Internal SafeHandleZeroOrMinusOneIsInvalid class to remove the dependency on .Net Framework 4.6.
public abstract class InternalSafeHandleZeroOrMinusOneIsInvalid : SafeHandle
{
    protected InternalSafeHandleZeroOrMinusOneIsInvalid(bool ownsHandle)
        : base(IntPtr.Zero, ownsHandle)
    {
    }

    public override bool IsInvalid
    {
        get
        {
            return handle == IntPtr.Zero || handle == new IntPtr(-1);
        }
    }
}

// Internal SafeX509ChainHandle class to remove the dependency on .Net Framework 4.6.
[SecurityCritical]
public sealed class InternalSafeX509ChainHandle : InternalSafeHandleZeroOrMinusOneIsInvalid { 
    private InternalSafeX509ChainHandle () : base(true) {}

    internal InternalSafeX509ChainHandle (IntPtr handle) : base (true) {
        SetHandle(handle); 
    }

    internal static InternalSafeX509ChainHandle InvalidHandle { 
        get { return new InternalSafeX509ChainHandle(IntPtr.Zero); }
    } 

    [SecurityCritical]
    override protected bool ReleaseHandle() 
    {
        CertFreeCertificateChain(handle);
        return true;
    } 

    [DllImport("Crypt32.dll", SetLastError=true)]

    [SuppressUnmanagedCodeSecurity,
     ResourceExposure(ResourceScope.None),
     ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]

    private static extern void CertFreeCertificateChain(IntPtr handle); 
}

public class Win32Helpers
{
    [DllImport("Crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
    public extern static 
    bool CertVerifyCertificateChainPolicy(
        [In]     IntPtr                       pszPolicyOID,
        [In]     SafeX509ChainHandle  pChainContext,
        [In]     ref CERT_CHAIN_POLICY_PARA   pPolicyPara,
        [In,Out] ref CERT_CHAIN_POLICY_STATUS pPolicyStatus);

    [DllImport("Crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]
    public static extern
    SafeX509ChainHandle CertDuplicateCertificateChain(
        [In]     IntPtr pChainContext);

    [DllImport("Crypt32.dll", CharSet=CharSet.Auto, SetLastError=true)]

    [ResourceExposure(ResourceScope.None)]

    public static extern
    SafeX509ChainHandle CertDuplicateCertificateChain(
        [In]     SafeX509ChainHandle pChainContext);

    public static bool IsMicrosoftCertificate([In] SafeX509ChainHandle pChainContext)
    {
        //-------------------------------------------------------------------------
        //  CERT_CHAIN_POLICY_MICROSOFT_ROOT  
        //  
        //  Checks if the last element of the first simple chain contains a  
        //  Microsoft root public key. If it doesn't contain a Microsoft root  
        //  public key, dwError is set to CERT_E_UNTRUSTEDROOT.  
        //  
        //  pPolicyPara is optional. However,  
        //  MICROSOFT_ROOT_CERT_CHAIN_POLICY_ENABLE_TEST_ROOT_FLAG can be set in  
        //  the dwFlags in pPolicyPara to also check for the Microsoft Test Roots.  
        //  
        //  MICROSOFT_ROOT_CERT_CHAIN_POLICY_CHECK_APPLICATION_ROOT_FLAG can be set  
        //  in the dwFlags in pPolicyPara to check for the Microsoft root for  
        //  application signing instead of the Microsoft product root. This flag  
        //  explicitly checks for the application root only and cannot be combined  
        //  with the test root flag.    
        //  
        //  MICROSOFT_ROOT_CERT_CHAIN_POLICY_DISABLE_FLIGHT_ROOT_FLAG can be set  
        //  in the dwFlags in pPolicyPara to always disable the Flight root.  
        //  
        //  pvExtraPolicyPara and pvExtraPolicyStatus aren't used and must be set  
        //  to NULL.  
        //--------------------------------------------------------------------------  
        const uint MICROSOFT_ROOT_CERT_CHAIN_POLICY_ENABLE_TEST_ROOT_FLAG       = 0x00010000;
        const uint MICROSOFT_ROOT_CERT_CHAIN_POLICY_CHECK_APPLICATION_ROOT_FLAG = 0x00020000;
        //const uint MICROSOFT_ROOT_CERT_CHAIN_POLICY_DISABLE_FLIGHT_ROOT_FLAG    = 0x00040000;

        CERT_CHAIN_POLICY_PARA PolicyPara = new CERT_CHAIN_POLICY_PARA(Marshal.SizeOf(typeof(CERT_CHAIN_POLICY_PARA)));
        CERT_CHAIN_POLICY_STATUS PolicyStatus = new CERT_CHAIN_POLICY_STATUS(Marshal.SizeOf(typeof(CERT_CHAIN_POLICY_STATUS)));
        int CERT_CHAIN_POLICY_MICROSOFT_ROOT = 7;

        PolicyPara.dwFlags = (uint) MICROSOFT_ROOT_CERT_CHAIN_POLICY_ENABLE_TEST_ROOT_FLAG;
        bool isMicrosoftRoot = false;

        if(CertVerifyCertificateChainPolicy(new IntPtr(CERT_CHAIN_POLICY_MICROSOFT_ROOT),
                                            pChainContext,
                                            ref PolicyPara,
                                            ref PolicyStatus))
        {
            isMicrosoftRoot = (PolicyStatus.dwError == 0);
        }

        // Also check for the Microsoft root for application signing if the Microsoft product root verification is unsuccessful.
        if(!isMicrosoftRoot)
        {
            // Some Microsoft modules can be signed with Microsoft Application Root instead of Microsoft Product Root,
            // So we need to use the MICROSOFT_ROOT_CERT_CHAIN_POLICY_CHECK_APPLICATION_ROOT_FLAG for the certificate verification.
            // MICROSOFT_ROOT_CERT_CHAIN_POLICY_CHECK_APPLICATION_ROOT_FLAG can not be used
            // with MICROSOFT_ROOT_CERT_CHAIN_POLICY_ENABLE_TEST_ROOT_FLAG,
            // so additional CertVerifyCertificateChainPolicy call is required to verify the given certificate is in Microsoft Application Root.
            //
            CERT_CHAIN_POLICY_PARA PolicyPara2 = new CERT_CHAIN_POLICY_PARA(Marshal.SizeOf(typeof(CERT_CHAIN_POLICY_PARA)));
            CERT_CHAIN_POLICY_STATUS PolicyStatus2 = new CERT_CHAIN_POLICY_STATUS(Marshal.SizeOf(typeof(CERT_CHAIN_POLICY_STATUS)));
            PolicyPara2.dwFlags = (uint) MICROSOFT_ROOT_CERT_CHAIN_POLICY_CHECK_APPLICATION_ROOT_FLAG;

            if(CertVerifyCertificateChainPolicy(new IntPtr(CERT_CHAIN_POLICY_MICROSOFT_ROOT),
                                                pChainContext,
                                                ref PolicyPara2,
                                                ref PolicyStatus2))
            {
                isMicrosoftRoot = (PolicyStatus2.dwError == 0);
            }
        }

        return isMicrosoftRoot;
    }
}

} " ParameterBinding(Add-Type): Name="Language"; Wert="CSharp" ParameterBinding(Add-Type): Name="ErrorAction"; Wert="SilentlyContinue" `

dinger1986 commented 2 years ago

Please test running manually, if it works manually then it's got to be something involving troubleshooting issues unique to your environment either due to gpo or some other policys, also looks like you are maybe running web proxys?

michaelortnersanube commented 2 years ago

Hello Sir,

i can send you the policy, maybe you see something, what i have make wrong :)

I don't think we running web proxys, where you see this?

Here is a picture of the Delegation of the Policy:

image

I have see, that there is a Policy for PowerShell on the User Configuration but i think this doesn't make this work :)

dinger1986 commented 2 years ago

Are all your users admins?

michaelortnersanube commented 2 years ago

No, local admins not if you mean this. I am domain admin, but if you want i can try it with a testuser.

michaelortnersanube commented 2 years ago

And Domain users are not admins, only me and one other.

dinger1986 commented 2 years ago

I think with the way you have setup your gpo they would need to be.

You could look at a deployment tool like pdq deploy or setup Tactical RMM (opensource RMM) and deploy using that.

michaelortnersanube commented 2 years ago

Oh thanks for the tipp with tactical rmm. This looks good, i will test it and say you if it works :)

dinger1986 commented 2 years ago

No problems, it will still need deployed but should be easy enough done.

Best place for support for both is discord 👍,can try and help on both.

Please close this if you are happy.