Romanitho / Winget-AutoUpdate

WAU daily updates apps as system and notify connected users. (Allowlist and Blocklist support)
MIT License
1.09k stars 134 forks source link

[Feature Request]: replace invisible.vbs with run-hidden #465

Open andreasbrett opened 10 months ago

andreasbrett commented 10 months ago

The request

Microsoft officially announced last month that VBS will be deprecated in the future. No deadlines or time frames were mentioned. Nevertheless since invisible.vbs is merely used for spawning a powershell.exe process in a hidden fashion, it should be easy to migrate to another workaround before Microsoft decides to kill off VBS.

https://github.com/PowerShell/PowerShell/issues/3028 mentions a C++ implementation. You can find it here: https://github.com/stax76/run-hidden. It would be a great drop-in replacement. License allows deploying WAU with the run-hidden binary. Of course using an external binary might trigger some AV/EDR tools and is worse than using embedded OS tools. VirusTotal result is 1/72.

Background info on VBS deprecation: https://isvbscriptdead.com/ https://learn.microsoft.com/en-us/windows/whats-new/deprecated-features

Is your feature request related to a problem?

No response

Additional information

No response

Romanitho commented 10 months ago

Thanks for spotting that point. Indeed, we need to think about the replacement of this vbs.

KnifMelti commented 10 months ago

In my work I belong to an organization that has an exe replacement, but that I can't share - VirusTotal result is 0/72 (not at work now πŸ˜‰)

AndrewDemski-ad-gmail-com commented 10 months ago

We could write our own exe in C# that would be mind-dumbing class.

using System.Diagnostics;

namespace InvisiLauncher
{
  internal static class Program
  {
    [STAThread]
    static void Main(string[] args)
    {
      NotifyIcon icon = new NotifyIcon();
      icon.Icon = SystemIcons.Question;
      icon.Click += delegate { MessageBox.Show("Bye!","how about that?", MessageBoxButtons.OK, MessageBoxIcon.Question); icon.Visible = true; Application.Exit(); };
      icon.Visible = true;
      if (args.Length == 1)
      {
        var scriptArguments = "-ExecutionPolicy Bypass -File \"" + args[0] + "\"";
        var processStartInfo = new ProcessStartInfo("powershell.exe", scriptArguments);
        processStartInfo.RedirectStandardOutput = true;
        processStartInfo.RedirectStandardError = true;
        using var process = new Process();
        process.StartInfo = processStartInfo;
        process.Start();
        string output = process.StandardOutput.ReadToEnd();
        string error = process.StandardError.ReadToEnd();
      }
      Application.Run();
    }
  }
}

or.. we could tell PowerShell to hide own window.. but I would need some time digging up the old scripts repo.

AndrewDemski-ad-gmail-com commented 10 months ago

This PowerShell script hides own window

enum WindowStates {
              FORCEMINIMIZE = 11
              HIDE = 0
              MAXIMIZE = 3
              MINIMIZE = 6
              RESTORE = 9
              SHOW = 5
              SHOWDEFAULT = 10
              SHOWMAXIMIZED = 3
              SHOWMINIMIZED = 2
              SHOWMINNOACTIVE = 7
              SHOWNA = 8
              SHOWNOACTIVATE = 4
              SHOWNORMAL = 1
          }
$Win32ShowWindowAsync = Add-Type -MemberDefinition @'
[DllImport("user32.dll")]
public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
'@ -Name 'Win32ShowWindowAsync' -Namespace Win32Functions -PassThru

$process = [System.Diagnostics.Process]::GetCurrentProcess()
$id = $process.Id
$myHandle = $process.MainWindowHandle

$Win32ShowWindowAsync::ShowWindowAsync($myHandle, [WindowStates]::MINIMIZE) | Out-Null
Romanitho commented 10 months ago

Our own EXE would not be signed? If a full PS solution can be implement, I'd go for that. But I don't know πŸ˜…

AndrewDemski-ad-gmail-com commented 10 months ago

Very well.. then lets see how PowerShell deployment toolkit launcher operates. It is an exe with config file.


From: Romain @.> Sent: 18 November 2023 01:44 To: Romanitho/Winget-AutoUpdate @.> Cc: Andrzej Demski @.>; Comment @.> Subject: Re: [Romanitho/Winget-AutoUpdate] [Feature Request]: replace invisible.vbs with run-hidden (Issue #465)

Our own EXE would not be signed? If a full PS solution can be implement, I'd go for that. But I don't know πŸ˜…

β€” Reply to this email directly, view it on GitHubhttps://github.com/Romanitho/Winget-AutoUpdate/issues/465#issuecomment-1817292305, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ASAJCPQ2QZPDSZYEKZZL4O3YFAAG5AVCNFSM6AAAAAA62C45L6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQMJXGI4TEMZQGU. You are receiving this because you commented.Message ID: @.***>

Romanitho commented 9 months ago

It seems to be the top priority topic to work on...

AndrewDemski-ad-gmail-com commented 9 months ago

It seems to be the top priority topic to work on...

Very well. I'll check the latest release

AndrewDemski-ad-gmail-com commented 9 months ago

digging..

Already something useful came from that excavation operation.

Piece of code which could make User experience a bit less stressful.

UserNotificationState (MSDN) which will allow User-side deployments to wait for actual user if interaction of manual postpones will be necessary.

findings

Current version of PDT launcher (v.1.1.1.1) is basically a C# equivalent of current invisible.vbs script :) image

All paths are semi-hardcoded, if we allow CPU arch detection to let it be called a dynamic setting. Later is the same process invocation as in my previous example. image

The verdict

We do not need 3rd party binaries, we can write our own.

AndrewDemski-ad-gmail-com commented 9 months ago

There is a 3rd option, AutoHotkey. There are examples how to do that.. F.ex. AHK to run PowerShell command

In our case we would need to define powershell.exe with full path rather than letting the $env:path variable and binary search order picking something malicious with matching exe name from any path higher on the list.

AndrewDemski-ad-gmail-com commented 9 months ago

4th option would be calling PowerShell directly from C# using System.Management.Automation Namespace, no exe file paths would be required, all parameters could be fed from C# app command line.

docs examples

Romanitho commented 9 months ago

Your invest is really appreciated πŸ™‚ To be honest, I think we need something as simple as possible. I don't know what could be the best option.

KnifMelti commented 9 months ago

All of this because the flawed behavior of Powershell -WindowsStyle Hidden 😁with a brief flashing of a window... ...https://stackoverflow.com/questions/1802127/how-to-run-a-powershell-script-without-displaying-a-window image

[EDIT] Still flashes...

AndrewDemski-ad-gmail-com commented 9 months ago

All of this because the flawed behavior of Powershell -WindowsStyle Hidden 😁with a brief flashing of a window... [EDIT] Still flashes...

I'd love to see MS adding powershellw.exe similar to java.exe/javaw.exe But before that happens, I'd pick option #1(C# launcher via filepath) or #4(C# launcher via API) and use it for now.

How bad could it be if even Snyk says its OK? image

Romanitho commented 9 months ago

If you know what to do, let's try then... πŸ˜…

KnifMelti commented 9 months ago

The only thing left know is a coding certificate...

KnifMelti commented 9 months ago

The only thing left know is a coding certificate...

Ah, run-hidden!

Romanitho commented 9 months ago

run-hidden.exe seems to be a good option too

AndrewDemski-ad-gmail-com commented 9 months ago

Good evening. It's been a while and after some brain grinding I think that whoever cares about signing the exe/assembly/code probably has access to Active Directory Certificate Services in their company and could sign anything using their internal code signing certs. Same with AppLocker, all they would ever need is a checksum. Buying code signing cert is a waste of resource. Keeping even part of that info in a public github repo - pure nightmare. using self-signed code proves only that file was not modified in the transfer. I even considered option of sending "launcher.cs" file and using CSC.exe on the target machine to compile it :) image

TL;DR: The only issues related to "Custom PowerShell Startup in Window Mode" will only affect companies that are more than qualified to deal with this illusory problem.

This project is public, everyone can read what is inside, calling it unsafe only because someone did not configure AppLocker/WDAG or did not sign the code during on-boarding is both a rude jab at the supplier and an indirect confirmation that either the company's IT OPS processes are lame or their employees are not proactive.

AndrewDemski-ad-gmail-com commented 9 months ago

Word of caution, any C# based application which gets into contact with System.Management.Automation bypasses execution policies. IMHO If we create and decide to ship something like that with WAU, we should have a disclaimer added to the readme file.

AndrewDemski-ad-gmail-com commented 9 months ago

I'd pick option No.1(C# launcher via filepath)

@Romanitho, Guys, how to share that minute C# project with you? I set it to private and shared gave view perm to you, @Romanitho. here

Romanitho commented 9 months ago

it can be public, no ?

AndrewDemski-ad-gmail-com commented 9 months ago

it can be public, no ?

it could be, but i still feel like it is not "production ready". There is no compilation workflow in place etc.. I'll need some help with that.

Romanitho commented 9 months ago

That's why GitHub is made for, I guess 😜

AndrewDemski-ad-gmail-com commented 9 months ago

Stop teasing me :) I'd like to see that code at least once in the daylight. before I share it with the rest of this planet. I'll clean that up this week after the PI plannings are done.. and then change the repository visibility to public,

KnifMelti commented 9 months ago

@AndrewDemski-ad-gmail-com We have another function using WScript.Shell Sources/WAU/Winget-AutoUpdate/functions/Add-Shortcut.ps1

If that falls under the same category, could you consider building a simular function into your release too?

AndrewDemski-ad-gmail-com commented 9 months ago

@AndrewDemski-ad-gmail-com We have another function using WScript.Shell Sources/WAU/Winget-AutoUpdate/functions/Add-Shortcut.ps1

If that falls under the same category, could you consider building a simular function into your release too?

I am not sure it hat shortcut would ever re-emerge as a problem. If we could just use the built-in cmdlet new-item which has been expanded in PS5.0 with option to create symlinks.

windowless launcher is capable of launching processes with custom args. That means the only difference between LNK and symlink functionalities are eliminated (from our POV/needs)

All it needs is some polishing over this weekend.

KnifMelti commented 9 months ago

That Function in WAU is used to create shortcuts for:

        #Create Shortcuts
        if ($StartMenuShortcut) {
            if (!(Test-Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)")) {
                New-Item -ItemType Directory -Force -Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)" | Out-Null
            }
            Add-Shortcut "wscript.exe" "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)\WAU - Check for updated Apps.lnk" "`"$($WAUinstallPath)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WAUinstallPath)\user-run.ps1`"`"" "${env:SystemRoot}\System32\shell32.dll,-16739" "Manual start of Winget-AutoUpdate (WAU)..."
            Add-Shortcut "wscript.exe" "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)\WAU - Open logs.lnk" "`"$($WAUinstallPath)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WAUinstallPath)\user-run.ps1`" -Logs`"" "${env:SystemRoot}\System32\shell32.dll,-16763" "Open existing WAU logs..."
            Add-Shortcut "wscript.exe" "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)\WAU - Web Help.lnk" "`"$($WAUinstallPath)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WAUinstallPath)\user-run.ps1`" -Help`"" "${env:SystemRoot}\System32\shell32.dll,-24" "Help for WAU..."
        }

        if ($DesktopShortcut) {
            Add-Shortcut "wscript.exe" "${env:Public}\Desktop\WAU - Check for updated Apps.lnk" "`"$($WAUinstallPath)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WAUinstallPath)\user-run.ps1`"`"" "${env:SystemRoot}\System32\shell32.dll,-16739" "Manual start of Winget-AutoUpdate (WAU)..."
        }

And the created shortcuts are in fact calling wscript.exe

A New-Item with -ItemType SymbolicLink can't handle (what I know of) all of the $Target, $Shortcut, $Arguments, $Icon, $Description

So, if you could also add the possibility to pass $Icon, $Description to your solution (and save it as a shortcut) we would be all good

[EDIT] But, if $WScriptShell = New-Object -ComObject WScript.Shell from PowerShell isn't removed we could just use your solution to replace wscript.exe in the shortcuts!

KnifMelti commented 9 months ago

All it needs is some polishing over this weekend.

Hello (tried to answer in your invitation but your mail account seems to be flooded)! As I interpret the code it isn't restricted to just running PS silent. . By editing the config file it can call and run anything silent! Great πŸ‘

AndrewDemski-ad-gmail-com commented 9 months ago

By editing the config file it can call and run anything silent!

That was precisely my point, with all configuration pushed outside of LNK, functional differences between SymLink and ms-shllink will be negligible.

I made that repository public. I will finish the code after Xmass

AndrewDemski-ad-gmail-com commented 8 months ago

not-stale-yet.

Functionality is there, but part where github does the compilation for PR is still missing.

AndrewDemski-ad-gmail-com commented 8 months ago

image

With great please I'd like to announce that launcher is ready :)

Releases are automated, more details there and there:

github-actions[bot] commented 7 months ago

This issue is stale because it has been open for 30 days with no activity.

Romanitho commented 7 months ago

up

github-actions[bot] commented 6 months ago

This issue is stale because it has been open for 30 days with no activity.

andreasbrett commented 5 months ago

How do we proceed from here? We'd need a way to configure an alternative to invisible.vbs

KnifMelti commented 5 months ago

https://github.com/Romanitho/Winget-AutoUpdate/issues/465#issuecomment-1896431001

andreasbrett commented 5 months ago

#465 (comment)

Invisible.vbs usage is still fixed in WAU. I can not simply replace Invisible.vbs with the binary provided by @AndrewDemski-ad-gmail-com. That's why I ask if WAU will get the necessary changes to use alternatives to Invisible.vbs

KnifMelti commented 5 months ago

I meant that that must be imolemented in WAU @Romanitho

AndrewDemski-ad-gmail-com commented 5 months ago

Sorry for being absent from this discussion for so long (I was moving to a new place).

It would be possible to use either job action with wget to pull the zip with latest binary which is being compiled by github. The last remaining step would be saving the XML config file to save the whole command line currently invoked by VBScript.

Romanitho commented 5 months ago

yes. We need to work on that part. But I'm a bit like @andreasbrett πŸ˜…

colourofsound commented 4 months ago

Just another a bump on this - I have Applocker in place in my environment and it really doesn't like VBS scripts running from ProgramData (even if I whitelist that path)

AndrewDemski-ad-gmail-com commented 4 months ago

@colourofsound, Please do not whitelist paths, use file hashes. that way AppLocker will block any modified scripts. Someone may replace content of your whitelisted script with something more sinister and there will be..

..trouble!

github-actions[bot] commented 3 months ago

This issue is stale because it has been open for 30 days with no activity.

soredake commented 3 months ago

https://techcommunity.microsoft.com/t5/windows-it-pro-blog/vbscript-deprecation-timelines-and-next-steps/ba-p/4148301

Romanitho commented 3 months ago

high priority

github-actions[bot] commented 2 months ago

This issue is stale because it has been open for 30 days with no activity.

soredake commented 2 months ago

Not stale.

github-actions[bot] commented 1 month ago

This issue is stale because it has been open for 30 days with no activity.

andreasbrett commented 1 month ago

Not stale