colombeen Posted June 15, 2017 Posted June 15, 2017 (edited) Hi guys, I was bored and somehow this idea just got stuck in my head to create a RunAs GUI with a credential manager that would run in the system tray which would let you start executable files (exe, msi, ...) by clicking on the tray icon and showing a user defined list of apps that would start directly if only one credential is provided, or would show you a list from which to choose the wanted credentials. the last 2 options from the list would be settings and exit ofcourse. the settings should bring up a GUI with 2 parts : the credential manager and the application list. for the applications i would use a FileOpenDialog popup to choose the wanted applications. I would add an optional command line switch(es) field for each app you add. Maybe the option to add apps to categories for better management? for the credentials i'm not completely sure how I will do it just yet. I was actually hoping to be able to use the windows stored credentials (but i'm not sure if this is possible) as well as adding manual credentials. Now what is all this about... I was hoping for some input from all you guys on best practices for something like this... - Would you use (an) ini file(s) to store the applications list and credentials, would you use the registry? - How do you think the GUI would have to look to be as user friendly as possible? - Any suggestions on other things to add? - ... - Has this already been done and would I be wasting my time? Let me know and I'll see what I can do (I will post the result on the forum) Greetz Colombeen ---------------------------------------------- Edit: This is what I have so far (just testing). The ini files are manually set ATM. Multiple credential support and the management GUI isn't created at this point. I still have to clean up the code, optimize, add more functions, ... But the first tests seem to work for me. All files have to be in the same directory at this point. c-RunAs.au3 expandcollapse popup#NoTrayIcon #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Icon=icon.ico #AutoIt3Wrapper_Outfile=c-RunAs.exe #AutoIt3Wrapper_Compression=4 #AutoIt3Wrapper_Res_Comment=RunAs GUI with a credential manager #AutoIt3Wrapper_Res_Description=RunAs GUI with a credential manager #AutoIt3Wrapper_Res_Fileversion=1.0.0.0 #AutoIt3Wrapper_Res_Fileversion_AutoIncrement=p #AutoIt3Wrapper_Res_ProductVersion=1.0 #AutoIt3Wrapper_Res_LegalCopyright=Jarno Colombeen #AutoIt3Wrapper_Res_Language=1033 #AutoIt3Wrapper_Res_requestedExecutionLevel=highestAvailable #AutoIt3Wrapper_AU3Check_Stop_OnWarning=Y #AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #cs Script: c-RunAs Author: Jarno Colombeen Copyright: colombeen.be Description: RunAs GUI with a credential manager Date: 2017/06/16 AutoIt Version: 3.3.14.2 #ce #Region General options Opt("GuiOnEventMode", 1) Opt("TrayMenuMode", 3) Opt("TrayOnEventMode", 1) #EndRegion #Region General variables Global $cRunAs_ini_creds = "c-Credentials.ini" Global $cRunAs_creds Global $cRunAs_ini_apps = "c-Apps.ini" Global $cRunAs_apps Global $cRunAs_cats ; - For the GUI Global $cRunAs_GUI Global $cRunAsTitle = "c-RunAs - RunAs GUI with credential manager" #EndRegion #Region Required files #include <Array.au3> #include <AutoItConstants.au3> #include <Crypt.au3> #include <TrayConstants.au3> #include <WinAPIDiag.au3> #EndRegion #Region Init App _cRunAs() Func _cRunAs() ; Load the credentials if there are any If FileExists($cRunAs_ini_creds) Then _cRunAsGetCredentials() ; Load the categories and apps If FileExists($cRunAs_ini_apps) Then _cRunAsGetApps() ; Load the tray app _cRunAsTray() ; First run ??? Show GUI If Not FileExists($cRunAs_ini_apps) Or Not FileExists($cRunAs_ini_creds) Then _cRunAsSettingsGUI() While 1 Sleep(100) WEnd EndFunc ; ==> _cRunAs() #EndRegion #Region Helper functions Func _cRunAsTray() ; Show correct icon during development If Not @Compiled Then TraySetIcon("icon.ico") ; Title TrayCreateItem("c-RunAs") TrayItemSetOnEvent(-1, "_cRunAsSettingsGUI") TrayItemSetState(-1, $TRAY_DEFAULT) ; Dynamically create the tray items If IsArray($cRunAs_cats) And UBound($cRunAs_cats) > 0 Then TrayCreateItem("") For $i = 0 To (UBound($cRunAs_cats)-1) Local $RunAsMenu = TrayCreateMenu($cRunAs_cats[$i]) For $j = 0 To (UBound($cRunAs_apps)-1) If $cRunAs_cats[$i] = $cRunAs_apps[$j][1] Then TrayCreateItem($cRunAs_apps[$j][0], $RunAsMenu) TrayItemSetOnEvent(-1, "_cRunAsExecute") EndIf Next Next EndIf ; Create the exit item TrayCreateItem("") TrayCreateItem("Exit") TrayItemSetOnEvent(-1, "_cRunAsExit") ; Set tray default ;TraySetOnEvent($TRAY_EVENT_PRIMARYDOUBLE, "_cRunAsSettingsGUI") TraySetClick(8) TraySetState($TRAY_ICONSTATE_SHOW) TraySetToolTip("c-RunAs") EndFunc ; ==> _cRunAsTray() Func _cRunAsExecute() Local $RunAsID = @TRAY_ID Local $RunAsName = TrayItemGetText($RunAsID) Local $RunAsAppID = _ArraySearch($cRunAs_apps, $RunAsName) Local $RunAsUser, $RunAsDomain, $RunAsPassword If $RunAsAppID >= 0 Then If UBound($cRunAs_creds) = 1 Then ; Only one credential found > Run as this user $RunAsUser = $cRunAs_creds[0][0] $RunAsDomain = $cRunAs_creds[0][1] $RunAsPassword = $cRunAs_creds[0][2] ElseIf UBound($cRunAs_creds) > 1 Then ; Multiple credentials found > Show list to choose from Else ; There are no credentials > Run as current user Run($cRunAs_apps[$RunAsAppID][2] & " " & $cRunAs_apps[$RunAsAppID][3], "") If @error Then TrayTip("c-RunAs", "Error starting " & $RunAsName & @CRLF & "Error: " & @error & @CRLF & "Extended error: " & @extended, 5) Else TrayTip("c-RunAs", "Starting " & $RunAsName & @CRLF & "as " & @LogonDomain & "\" & @UserName & @CRLF & "Reason: No other credentials found", 2) EndIf Return False Endif RunAs($RunAsUser, $RunAsDomain, $RunAsPassword, 1, $cRunAs_apps[$RunAsAppID][2] & " " & $cRunAs_apps[$RunAsAppID][3], "") If @error Then Local $error = @error Local $extended = @extended Local $description = _WinAPI_GetErrorMessage($extended) TrayTip("c-RunAs", "Error starting " & $RunAsName & @CRLF & @CRLF & $description & " (Error " & $error & " - " & $extended & ")", 5) Else TrayTip("c-RunAs", "Starting " & $RunAsName & @CRLF & "as " & $RunAsDomain & "\" & $RunAsUser, 2) EndIf Else MsgBox(16, $cRunAsTitle, "Couldn't find the app information") EndIf EndFunc ; ==> _cRunAsExecute() Func _cRunAsGetCredentials() Local $Credentials = IniReadSectionNames ($cRunAs_ini_creds) If Not @error Then $cRunAs_creds = 0 Global $cRunAs_creds[1][3] For $i = 1 To $Credentials[0] Local $Credential = IniReadSection($cRunAs_ini_creds, $Credentials[$i]) _ArrayDelete($Credential, 0) _ArrayColDelete($Credential, 0) _ArrayAdd($cRunAs_creds, $Credential[0][0] & "|" & $Credential[1][0] & "|" & _cRunAsEncryptDecrypt($Credential[2][0], True)) Next _ArrayDelete($cRunAs_creds, 0) EndIf EndFunc ; ==> _cRunAsGetCredentials() Func _cRunAsGetApps() Local $Apps = IniReadSectionNames ($cRunAs_ini_apps) If Not @error Then $cRunAs_apps = 0 $cRunAs_cats = 0 Global $cRunAs_apps[1][4] Global $cRunAs_cats[1] For $i = 1 To $Apps[0] Local $App = IniReadSection($cRunAs_ini_apps, $Apps[$i]) _ArrayDelete($App, 0) _ArrayColDelete($App, 0) If _ArraySearch($cRunAs_cats, $App[1][0]) = -1 Then _ArrayAdd($cRunAs_cats, $App[1][0]) _ArrayAdd($cRunAs_apps, $App[0][0] & "|" & $App[1][0] & "|" & $App[2][0] & "|" & $App[3][0]) Next _ArrayDelete($cRunAs_apps, 0) _ArrayDelete($cRunAs_cats, 0) EndIf EndFunc ; ==> _cRunAsGetApps() Func _cRunAsSettingsGUI() ; GUI HERE ConsoleWrite(@CRLF & "!> c-RunAs Settings GUI") EndFunc ; ==> _cRunAsSettingsGUI() Func _cRunAsExit() Exit EndFunc ; ==> _cRunAsExit() Func _cRunAsEncryptDecrypt($CryptString, $Decrypt = False) Local $CryptAlgorithm = $CALG_AES_256 Local $CryptKey = "cRunAs" & @ComputerName & "-3nCrÿPt!0n" _Crypt_Startup() If $Decrypt = False Then Return _Crypt_EncryptData($CryptString, $CryptKey, $CryptAlgorithm) ElseIf $Decrypt = True Then Return BinaryToString(_Crypt_DecryptData($CryptString, $CryptKey, $CryptAlgorithm)) Endif _Crypt_Shutdown() EndFunc #EndRegion c-Apps.ini [Active Directory] Name=Active Directory Category=Administrator Path="C:\Windows\System32\cmd.exe" CmdLine=/C START MMC C:\Windows\System32\dsa.msc [Computer Management] Name=Computer Management Category=Administrator Path="C:\Windows\System32\cmd.exe" CmdLine=/C START MMC C:\Windows\System32\compmgmt.msc [DFS Management] Name=DFS Management Category=Administrator Path="C:\Windows\System32\cmd.exe" CmdLine=/C START MMC C:\Windows\System32\dfsmgmt.msc [Total Commander] Name=Total Commander Category=File managers Path="C:\Program Files\TotalCommander\TOTALCMD64.EXE" CmdLine= c-Credentials.ini ; Replace MyUserName - MyDomain - $CALG_AES_256 encrypted MyPassword with the correct information [MyUserName] User=MyUserName Domain=MyDomain Password=MyPassword If you have any suggestions, let me know As it is now, the app uses 3mb memory and as good as nothing for CPU usage. Edited June 23, 2017 by colombeen Updated the script a bit
Starf0x Posted June 16, 2017 Posted June 16, 2017 Hi, I'm a big fan of portability, so all my programs contain ini files. I've written an app for my current customer which save s the password in the ini file (encrypted). Keep in mind, AutoIT can be decompiled, so the seed for encrypting the password can easily be read. Registry is not my forte, just because then the 'config' file of windows would be even bigger to read at startup. Have Fun.
colombeen Posted June 16, 2017 Author Posted June 16, 2017 (edited) Thx for the input Starf0x. I'm still trying to figure out what would be the best way to use ini files (separate files per category? can I do it all in one file? ... I haven't worked with my own custom ini files so far) Could you do something like : [General] {(Here the name),(Here the application path),(Command line switches)} {(Here the name),(Here the application path),(Command line switches)} {(Here the name),(Here the application path),(Command line switches)} {(Here the name),(Here the application path),(Command line switches)} {(Here the name),(Here the application path),(Command line switches)} [Scripting] {(Here the name),(Here the application path),(Command line switches)} {(Here the name),(Here the application path),(Command line switches)} [Bananas] {(Here the name),(Here the application path),(Command line switches)} {(Here the name),(Here the application path),(Command line switches)} {(Here the name),(Here the application path),(Command line switches)} I've been looking at documentation but it's not really clear on how to add multiple items in one section. I'm thinking about adding an option to choose if you'd like the creds only to be on the current device (in which case I would add something device specific to the encryption string) or adding them in the application folder EDIT: Aparently nested sections in ini files aren't really "done" but I found an article that states you should write it like : [General/Application1] Name=Application1 Path=ThePathToTheApp CmdLine=Switches here [General/Application2] Name=Application2 Path=ThePathToTheApp CmdLine=Switches here ... Does anyone have any experience with this? Any help would be awesome Edited June 16, 2017 by colombeen
colombeen Posted June 21, 2017 Author Posted June 21, 2017 Hi guys, it's been a few days... I haven't had alot of time... been mostly updating the script with improvements, not so much on the other features. Removed the categories ini file (I create an array with the categories from the apps ini file) Instead of constantly reading the ini files I load every ini file into an array at the start ... I updated the first post with the new code. thoughts, suggestions, bugs, ... are welcome!
colombeen Posted June 22, 2017 Author Posted June 22, 2017 Does anyone have any suggestions for the encryption? Would you encrypt the entire credential ini file or just the passwords? What encryption algorithm would you use? Suggestions for the ecryption key? thx
ViciousXUSMC Posted June 22, 2017 Posted June 22, 2017 I encrypted just the passwords & usernames when I used them in an INI. Use the Crypt.au3 functions. To help with security since the "seed" is in the file I try not to have a static seed so I use something like @LogonDNSDomain so it runs in the environment I wrote it for, but if somebody magically found my code in the wild they would have no idea what that was. You can get pretty creative with it, but no solution is perfect.
colombeen Posted June 22, 2017 Author Posted June 22, 2017 (edited) 14 minutes ago, ViciousXUSMC said: I encrypted just the passwords & usernames when I used them in an INI. Use the Crypt.au3 functions. To help with security since the "seed" is in the file I try not to have a static seed so I use something like @LogonDNSDomain so it runs in the environment I wrote it for, but if somebody magically found my code in the wild they would have no idea what that was. You can get pretty creative with it, but no solution is perfect. For testing purposes I'm using this: Func _cRunAsEncryptDecrypt($CryptString, $Decrypt = False) Local $CryptAlgorithm = $CALG_AES_256 Local $CryptKey = "cRunAs" & @ComputerName & "-3nCrÿPt!0n" _Crypt_Startup() If $Decrypt = False Then Return _Crypt_EncryptData($CryptString, $CryptKey, $CryptAlgorithm) ElseIf $Decrypt = True Then Return BinaryToString(_Crypt_DecryptData($CryptString, $CryptKey, $CryptAlgorithm)) Endif _Crypt_Shutdown() EndFunc In this case it would differ for each device because I'm using the @computername macro. I only encrypted the passwords at this point. What encryption algorithm would you suggest? Edited June 22, 2017 by colombeen
colombeen Posted June 23, 2017 Author Posted June 23, 2017 Updated my first post. Added password encryption Added _WinAPI_GetErrorMessage to show a readable error
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now