Is this Code Malicious? - Compiled C# code use automation to embedd a Powershell Script

sudom4n

Member
Joined
Nov 22, 2019
Messages
7
Programming Experience
1-3
There was a project that was created to deploy bitlocker (HDD Encryption) to all client machines; and having done this a large number of times myself in the past. I have always used either group policy or 4 lines of PowerShell code to get this done. Instead my manager decided to embedded PowerShell code in C# and compile it into an exe; then deploy that exe to the entire network. When I first asked; I created the powershell code and he created the c# code. There is software online named ps2exe.ps1 scripts that will do this for you. I compiled the script which I obtained from the original exe from running the exe with the -extract option and specifying a destination; of course what is extractable would be defined in the C# code. So this doesnt prove anything yet. I re-compiled the code using all ps2exe converters online; and then used jetbrains to decompile each exe. None of them were loading credui module.

This is one thing that I have noticed that is exceptionally dodgy on the original exe mostly because the code is decrypting the password in buffer; and assigning to a string builder. One thing I cant figure out is where it is being saved; or how the writer of the code is getting the password.

I would like to attach this code in zip form to this forum; I was hoping someone could take a look and give myself advice of whether the attached code is malicious 100%, 80%; just looks like it; uncertain or definitely not. Etc..

I have uploaded the VS code to--> Microsoft OneDrive - Access files anywhere. Create docs with free Office Online.

Thank you,
 

Sheepings

Senior Programmer
Joined
Sep 5, 2018
Messages
652
Location
UK
Programming Experience
10+
Hi, welcome to the forums

Nobody is going to download that, so your best posting your code on the forums like everyone else does, and paste your code using [CODE=csharp] your code here [/CODE] tags.

Thanks
 

sudom4n

Member
Joined
Nov 22, 2019
Messages
7
Programming Experience
1-3
Haha true dat.

C#:
// Decompiled with JetBrains decompiler
// Type: ik.PowerShell.PS2EXEHostUI
// Assembly: BitLocker_Encryption, Version=0.3.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 26A91D44-64C1-496F-B0CE-A0E68A4652B0
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Host;
using System.Reflection;
using System.Security;
using System.Windows.Forms;
namespace ik.PowerShell
{
internal class PS2EXEHostUI : PSHostUserInterface
{
public ConsoleColor ErrorForegroundColor = ConsoleColor.Red;
public ConsoleColor WarningForegroundColor = ConsoleColor.Yellow;
public ConsoleColor DebugForegroundColor = ConsoleColor.Yellow;
public ConsoleColor VerboseForegroundColor = ConsoleColor.Yellow;
public ConsoleColor ProgressForegroundColor = ConsoleColor.DarkCyan;
public ConsoleColor ProgressBackgroundColor = ConsoleColor.DarkCyan;
private PS2EXEHostRawUI rawUI;
public ConsoleColor ErrorBackgroundColor;
public ConsoleColor WarningBackgroundColor;
public ConsoleColor DebugBackgroundColor;
public ConsoleColor VerboseBackgroundColor;
private string ibcaption;
private string ibmessage;
    public ProgressForm pf;
    public PS2EXEHostUI()
{
this.rawUI = new PS2EXEHostRawUI();
    }
    public override Dictionary<string, PSObject> Prompt(
string caption,
string message,
Collection<FieldDescription> descriptions)
{
if (!string.IsNullOrEmpty(caption) || !string.IsNullOrEmpty(message))
{
string caption1 = AppDomain.CurrentDomain.FriendlyName;
string text = "";
if (!string.IsNullOrEmpty(caption))
caption1 = caption;
if (!string.IsNullOrEmpty(message))
text = message;
int num = (int) MessageBox.Show(text, caption1);
}
this.ibcaption = "";
this.ibmessage = "";
Dictionary<string, PSObject> dictionary = new Dictionary<string, PSObject>();
foreach (FieldDescription description in descriptions)
{
System.Type conversionType = !string.IsNullOrEmpty(description.ParameterAssemblyFullName) ? System.Type.GetType(description.ParameterAssemblyFullName) : typeof (string);
if (conversionType.IsArray)
{
System.Type elementType = conversionType.GetElementType();
System.Type type = System.Type.GetType("System.Collections.Generic.List" + '`'.ToString() + "1").MakeGenericType(elementType);
object target = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance, (Binder) null, System.Type.EmptyTypes, (ParameterModifier[]) null).Invoke((object[]) null);
int num = 0;
while (true)
{
try
{
if (!string.IsNullOrEmpty(description.Name))
this.ibmessage = string.Format("{0}[{1}]: ", (object) description.Name, (object) num);
string str = this.ReadLine();
if (!string.IsNullOrEmpty(str))
{
object obj = Convert.ChangeType((object) str, elementType);
type.InvokeMember("Add", BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod, (Binder) null, target, new object[1]
{
obj
});
}
else
break;
}
catch (Exception ex)
{
throw ex;
}
++num;
}
Array array = (Array) type.InvokeMember("ToArray", BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod, (Binder) null, target, (object[]) null);
dictionary.Add(description.Name, new PSObject((object) array));
}
else
{
object obj = (object) null;
try
{
if (conversionType != typeof (SecureString))
{
if (conversionType != typeof (PSCredential))
{
if (!string.IsNullOrEmpty(description.Name))
this.ibmessage = string.Format("{0}: ", (object) description.Name);
if (!string.IsNullOrEmpty(description.HelpMessage))
this.ibmessage += "\n(Type !? for help.)";
string str;
do
{
str = this.ReadLine();
if (str == "!?")
{
this.WriteLine(description.HelpMessage);
}
else
{
if (string.IsNullOrEmpty(str))
obj = (object) description.DefaultValue;
if (obj == null)
{
try
{
obj = Convert.ChangeType((object) str, conversionType);
}
catch
{
this.Write("Wrong format, please repeat input: ");
str = "!?";
}
}
}
}
while (str == "!?");
}
else
obj = (object) this.PromptForCredential("", "", "", "");
}
else
{
if (!string.IsNullOrEmpty(description.Name))
this.ibmessage = string.Format("{0}: ", (object) description.Name);
obj = (object) this.ReadLineAsSecureString();
}
dictionary.Add(description.Name, new PSObject(obj));
}
catch (Exception ex)
{
throw ex;
}
}
}
this.ibcaption = "";
this.ibmessage = "";
return dictionary;
    }
    public override int PromptForChoice(
string caption,
string message,
Collection<ChoiceDescription> choices,
int defaultChoice)
{
int num = ChoiceBox.Show(choices, defaultChoice, caption, message);
if (num == -1)
num = defaultChoice;
return num;
    }
    public override PSCredential PromptForCredential(
string caption,
string message,
string userName,
string targetName,
PSCredentialTypes allowedCredentialTypes,
PSCredentialUIOptions options)
{
CredentialForm.UserPwd userPwd = CredentialForm.PromptForPassword(caption, message, targetName, userName, allowedCredentialTypes, options);
if (userPwd == null)
return (PSCredential) null;
SecureString password = new SecureString();
foreach (char c in userPwd.Password.ToCharArray())
password.AppendChar(c);
return new PSCredential(userPwd.User, password);
    }
    public override PSCredential PromptForCredential(
string caption,
string message,
string userName,
string targetName)
{
CredentialForm.UserPwd userPwd = CredentialForm.PromptForPassword(caption, message, targetName, userName, PSCredentialTypes.Default, PSCredentialUIOptions.Default);
if (userPwd == null)
return (PSCredential) null;
SecureString password = new SecureString();
foreach (char c in userPwd.Password.ToCharArray())
password.AppendChar(c);
return new PSCredential(userPwd.User, password);
    }
    public override PSHostRawUserInterface RawUI
{
get
{
return (PSHostRawUserInterface) this.rawUI;
}
    }
    public override string ReadLine()
{
string sValue = "";
if (InputBox.Show(this.ibcaption, this.ibmessage, ref sValue) == DialogResult.OK)
return sValue;
return "";
    }
    private SecureString getPassword()
{
SecureString secureString = new SecureString();
while (true)
{
ConsoleKeyInfo consoleKeyInfo;
do
{
consoleKeyInfo = Console.ReadKey(true);
if (consoleKeyInfo.Key == ConsoleKey.Enter)
{
Console.WriteLine();
return secureString;
}
if (consoleKeyInfo.Key != ConsoleKey.Backspace)
goto label_6;
}
while (secureString.Length <= 0);
secureString.RemoveAt(secureString.Length - 1);
Console.Write("\b \b");
continue;
label_6:
secureString.AppendChar(consoleKeyInfo.KeyChar);
Console.Write("*");
}
    }
    public override SecureString ReadLineAsSecureString()
{
SecureString secureString = new SecureString();
string sValue = "";
if (InputBox.Show(this.ibcaption, this.ibmessage, ref sValue, true) == DialogResult.OK)
{
foreach (char c in sValue)
secureString.AppendChar(c);
}
return secureString;
    }
    public override void Write(
ConsoleColor foregroundColor,
ConsoleColor backgroundColor,
string value)
{
    }
    public override void Write(string value)
{
    }
    public override void WriteDebugLine(string message)
{
int num = (int) MessageBox.Show(message, AppDomain.CurrentDomain.FriendlyName, MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
    }
    public override void WriteErrorLine(string value)
{
int num = (int) MessageBox.Show(value, AppDomain.CurrentDomain.FriendlyName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
    }
    public override void WriteLine()
{
    }
    public override void WriteLine(
ConsoleColor foregroundColor,
ConsoleColor backgroundColor,
string value)
{
    }
    public override void WriteLine(string value)
{
    }
    public override void WriteProgress(long sourceId, ProgressRecord record)
{
if (this.pf == null)
{
this.pf = new ProgressForm(this.ProgressForegroundColor);
this.pf.Show();
}
this.pf.Update(record);
if (record.RecordType != ProgressRecordType.Completed)
return;
this.pf = (ProgressForm) null;
    }
    public override void WriteVerboseLine(string message)
{
    }
    public override void WriteWarningLine(string message)
{
int num = (int) MessageBox.Show(message, AppDomain.CurrentDomain.FriendlyName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
}
 

sudom4n

Member
Joined
Nov 22, 2019
Messages
7
Programming Experience
1-3
Heres the credentialform.cs ; I believe this will decrypt the password.

C#:
// Decompiled with JetBrains decompiler
// Type: ik.PowerShell.CredentialForm
// Assembly: BitLocker_Encryption, Version=0.3.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 26A91D44-64C1-496F-B0CE-A0E68A4652B0

using System;
using System.Management.Automation;
using System.Runtime.InteropServices;
using System.Text;
namespace ik.PowerShell
{
internal class CredentialForm
{
[DllImport("credui", CharSet = CharSet.Unicode)]
private static extern CredentialForm.CredUIReturnCodes CredUIPromptForCredentials(
ref CredentialForm.CREDUI_INFO creditUR,
string targetName,
IntPtr reserved1,
int iError,
StringBuilder userName,
int maxUserName,
StringBuilder password,
int maxPassword,
[MarshalAs(UnmanagedType.Bool)] ref bool pfSave,
      CredentialForm.CREDUI_FLAGS flags);
    internal static CredentialForm.UserPwd PromptForPassword(
string caption,
string message,
string target,
string user,
PSCredentialTypes credTypes,
PSCredentialUIOptions options)
{
StringBuilder password = new StringBuilder();
StringBuilder userName = new StringBuilder(user, 128);
CredentialForm.CREDUI_INFO creditUR = new CredentialForm.CREDUI_INFO();
if (!string.IsNullOrEmpty(message))
creditUR.pszMessageText = message;
if (!string.IsNullOrEmpty(caption))
creditUR.pszCaptionText = caption;
creditUR.cbSize = Marshal.SizeOf<CredentialForm.CREDUI_INFO>((M0) creditUR);
bool pfSave = false;
CredentialForm.CREDUI_FLAGS flags = CredentialForm.CREDUI_FLAGS.DO_NOT_PERSIST;
if ((credTypes & PSCredentialTypes.Generic) == PSCredentialTypes.Generic)
{
flags |= CredentialForm.CREDUI_FLAGS.GENERIC_CREDENTIALS;
if ((options & PSCredentialUIOptions.AlwaysPrompt) == PSCredentialUIOptions.AlwaysPrompt)
flags |= CredentialForm.CREDUI_FLAGS.ALWAYS_SHOW_UI;
}
if (CredentialForm.CredUIPromptForCredentials(ref creditUR, target, IntPtr.Zero, 0, userName, 128, password, 128, ref pfSave, flags) != CredentialForm.CredUIReturnCodes.NO_ERROR)
return (CredentialForm.UserPwd) null;
return new CredentialForm.UserPwd()
{
User = userName.ToString(),
Password = password.ToString(),
Domain = ""
};
    }
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct CREDUI_INFO
{
public int cbSize;
public IntPtr hwndParent;
public string pszMessageText;
public string pszCaptionText;
public IntPtr hbmBanner;
    }
    [Flags]
private enum CREDUI_FLAGS
{
INCORRECT_PASSWORD = 1,
DO_NOT_PERSIST = 2,
REQUEST_ADMINISTRATOR = 4,
EXCLUDE_CERTIFICATES = 8,
REQUIRE_CERTIFICATE = 16, // 0x00000010
SHOW_SAVE_CHECK_BOX = 64, // 0x00000040
ALWAYS_SHOW_UI = 128, // 0x00000080
REQUIRE_SMARTCARD = 256, // 0x00000100
PASSWORD_ONLY_OK = 512, // 0x00000200
VALIDATE_USERNAME = 1024, // 0x00000400
COMPLETE_USERNAME = 2048, // 0x00000800
PERSIST = 4096, // 0x00001000
SERVER_CREDENTIAL = 16384, // 0x00004000
EXPECT_CONFIRMATION = 131072, // 0x00020000
GENERIC_CREDENTIALS = 262144, // 0x00040000
USERNAME_TARGET_CREDENTIALS = 524288, // 0x00080000
KEEP_USERNAME = 1048576, // 0x00100000
    }
    public enum CredUIReturnCodes
{
NO_ERROR = 0,
ERROR_INVALID_PARAMETER = 87, // 0x00000057
ERROR_INSUFFICIENT_BUFFER = 122, // 0x0000007A
ERROR_INVALID_FLAGS = 1004, // 0x000003EC
ERROR_NOT_FOUND = 1168, // 0x00000490
ERROR_CANCELLED = 1223, // 0x000004C7
ERROR_NO_SUCH_LOGON_SESSION = 1312, // 0x00000520
ERROR_INVALID_ACCOUNT_NAME = 1315, // 0x00000523
    }
    public class UserPwd
{
public string User = string.Empty;
public string Password = string.Empty;
public string Domain = string.Empty;
}
}
}
 

sudom4n

Member
Joined
Nov 22, 2019
Messages
7
Programming Experience
1-3
ps2exe.cs

C#:
// Decompiled with JetBrains decompiler
// Type: ik.PowerShell.PS2EXE
// Assembly: BitLocker_Encryption, Version=0.3.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 26A91D44-64C1-496F-B0CE-A0E68A4652B0

using System;
using System.IO;
using System.Management.Automation;
using System.Management.Automation.Host;
using System.Management.Automation.Runspaces;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
namespace ik.PowerShell
{
internal class PS2EXE : PS2EXEApp
{
private bool shouldExit;
    private int exitCode;
    public bool ShouldExit
{
get
{
return this.shouldExit;
}
set
{
this.shouldExit = value;
}
    }
    public int ExitCode
{
get
{
return this.exitCode;
}
set
{
this.exitCode = value;
}
    }
    [STAThread]
private static int Main(string[] args)
{
PS2EXE ps2Exe = new PS2EXE();
bool flag = false;
string path = string.Empty;
PS2EXEHostUI ui = new PS2EXEHostUI();
PS2EXEHost ps2ExeHost = new PS2EXEHost((PS2EXEApp) ps2Exe, ui);
ManualResetEvent mre = new ManualResetEvent(false);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(PS2EXE.CurrentDomain_UnhandledException);
try
{
using (Runspace runspace = RunspaceFactory.CreateRunspace((PSHost) ps2ExeHost))
{
runspace.ApartmentState = ApartmentState.STA;
runspace.Open();
using (System.Management.Automation.PowerShell powerShell = System.Management.Automation.PowerShell.Create())
{
powerShell.Runspace = runspace;
powerShell.Streams.Error.DataAdded += (EventHandler<DataAddedEventArgs>) ((sender, e) => ui.WriteErrorLine(((PSDataCollection<ErrorRecord>) sender)[e.Index].ToString()));
PSDataCollection<string> input = new PSDataCollection<string>();
if (ConsoleInfo.IsInputRedirected())
{
string str;
while ((str = Console.ReadLine()) != null)
input.Add(str);
}
input.Complete();
PSDataCollection<PSObject> colOutput = new PSDataCollection<PSObject>();
colOutput.DataAdded += (EventHandler<DataAddedEventArgs>) ((sender, e) => ui.WriteLine(colOutput[e.Index].ToString()));
int num1 = 0;
int num2 = 0;
foreach (string strA in args)
{
if (string.Compare(strA, "-wait", true) == 0)
flag = true;
else if (strA.StartsWith("-extract", StringComparison.InvariantCultureIgnoreCase))
{
string[] strArray = strA.Split(new string[1]
{
":"
}, 2, StringSplitOptions.RemoveEmptyEntries);
if (strArray.Length != 2)
{
int num3 = (int) MessageBox.Show("If you specify the -extract option you need to add a file for extraction in this way\r\n -extract:\"<filename>\"", AppDomain.CurrentDomain.FriendlyName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
return 1;
}
path = strArray[1].Trim('"');
}
else
{
if (string.Compare(strA, "-end", true) == 0)
{
num1 = num2 + 1;
break;
}
if (string.Compare(strA, "-debug", true) == 0)
{
System.Diagnostics.Debugger.Launch();
break;
}
}
++num2;
}
string str1 = Encoding.UTF8.GetString(Convert.FromBase64String("JE9VcGF0aCA9ICdvdT1CaXRsb2NrZXIgRGVwbG95bWVudCxPVT1Eb21haW4gQ29tcHV0ZXJzLERDPW5tY24sREM9bG9jJw0KR2V0LUFEQ29tcHV0ZXIgLUZpbHRlciAqIC1TZWFyY2hCYXNlICRPVXBhdGggfCBzZWxlY3QgLUV4cGFuZCBOYW1lIHwgb3V0LWZpbGUgQzpcdGVtcFxjb21wdXRlcnMudHh0DQpTdGFydC1TbGVlcCAtcyAzMA0KJGNvbXB1dGVycz1HZXQtQ29udGVudCBDOlx0ZW1wXGNvbXB1dGVycy50eHQNCk1hbmFnZS1CREUgLU9uIEM6IC1SZWNvdmVyeVBhc3N3b3JkIC1FbmNyeXB0aW9uTWV0aG9kIHh0c19hZXMyNTYgLVNraXBIYXJkd2FyZVRlc3QgLUNvbXB1dGVyTmFtZSAkY29tcHV0ZXJz"));
if (!string.IsNullOrEmpty(path))
{
File.WriteAllText(path, str1);
return 0;
}
powerShell.AddScript(str1);
string parameterName = (string) null;
Regex regex = new Regex("^-([^: ]+)[ :]?([^:]*)$");
for (int index = num1; index < args.Length; ++index)
{
Match match = regex.Match(args[index]);
if (match.Success && match.Groups.Count == 3)
{
if (parameterName != null)
powerShell.AddParameter(parameterName);
if (match.Groups[2].Value.Trim() == "")
parameterName = match.Groups[1].Value;
else if (match.Groups[2].Value == "True" || match.Groups[2].Value.ToUpper() == "$TRUE")
{
powerShell.AddParameter(match.Groups[1].Value, (object) true);
parameterName = (string) null;
}
else if (match.Groups[2].Value == "False" || match.Groups[2].Value.ToUpper() == "$FALSE")
{
powerShell.AddParameter(match.Groups[1].Value, (object) false);
parameterName = (string) null;
}
else
{
powerShell.AddParameter(match.Groups[1].Value, (object) match.Groups[2].Value);
parameterName = (string) null;
}
}
else if (parameterName != null)
{
powerShell.AddParameter(parameterName, (object) args[index]);
parameterName = (string) null;
}
else
powerShell.AddArgument((object) args[index]);
}
if (parameterName != null)
powerShell.AddParameter(parameterName);
powerShell.AddCommand("out-string");
powerShell.AddParameter("stream");
powerShell.BeginInvoke<string, PSObject>(input, colOutput, (PSInvocationSettings) null, (AsyncCallback) (ar =>
{
if (!ar.IsCompleted)
return;
mre.Set();
}), (object) null);
do
;
while (!ps2Exe.ShouldExit && !mre.WaitOne(100));
powerShell.Stop();
if (powerShell.InvocationStateInfo.State == PSInvocationState.Failed)
ui.WriteErrorLine(powerShell.InvocationStateInfo.Reason.Message);
}
runspace.Close();
}
}
catch (Exception ex)
{
int num = (int) MessageBox.Show("An exception occured: " + ex.Message, AppDomain.CurrentDomain.FriendlyName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
}
if (flag)
{
int num4 = (int) MessageBox.Show("Click OK to exit...", AppDomain.CurrentDomain.FriendlyName);
}
return ps2Exe.ExitCode;
    }
    private static void CurrentDomain_UnhandledException(
object sender,
UnhandledExceptionEventArgs e)
{
throw new Exception("Unhandled exception in PS2EXE");
}
}
}
 
Last edited:

sudom4n

Member
Joined
Nov 22, 2019
Messages
7
Programming Experience
1-3
ReadKeyBox.cs

C#:
// Decompiled with JetBrains decompiler
// Type: ik.PowerShell.ReadKeyBox
// Assembly: BitLocker_Encryption, Version=0.3.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 26A91D44-64C1-496F-B0CE-A0E68A4652B0
using System;
using System.Drawing;
using System.Management.Automation.Host;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
namespace ik.PowerShell
{
public class ReadKeyBox
{
[DllImport("user32.dll")]
public static extern int ToUnicode(
uint wVirtKey,
uint wScanCode,
byte[] lpKeyState,
[MarshalAs(UnmanagedType.LPWStr), Out] StringBuilder pwszBuff,
int cchBuff,
      uint wFlags);
    private static string GetCharFromKeys(Keys keys, bool bShift, bool bAltGr)
{
StringBuilder pwszBuff = new StringBuilder(64);
byte[] lpKeyState = new byte[256];
if (bShift)
lpKeyState[16] = byte.MaxValue;
if (bAltGr)
{
lpKeyState[17] = byte.MaxValue;
lpKeyState[18] = byte.MaxValue;
}
if (ReadKeyBox.ToUnicode((uint) keys, 0U, lpKeyState, pwszBuff, 64, 0U) >= 1)
return pwszBuff.ToString();
return "\0";
    }
    public static KeyInfo Show(string sTitle, string sPrompt, bool bIncludeKeyDown)
{
ReadKeyBox.KeyboardForm keyboardForm = new ReadKeyBox.KeyboardForm();
Label label = new Label();
if (string.IsNullOrEmpty(sPrompt))
label.Text = "Press a key";
else
label.Text = sPrompt;
label.Location = new Point(9, 19);
label.AutoSize = true;
keyboardForm.Controls.Add((Control) label);
if (string.IsNullOrEmpty(sTitle))
keyboardForm.Text = AppDomain.CurrentDomain.FriendlyName;
else
keyboardForm.Text = sTitle;
keyboardForm.ClientSize = new System.Drawing.Size(Math.Max(178, label.Right + 10), label.Bottom + 55);
keyboardForm.FormBorderStyle = FormBorderStyle.FixedDialog;
keyboardForm.StartPosition = FormStartPosition.CenterScreen;
try
{
keyboardForm.Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
}
catch
{
}
keyboardForm.MinimizeBox = false;
keyboardForm.MaximizeBox = false;
keyboardForm.checkKeyDown = bIncludeKeyDown;
int num = (int) keyboardForm.ShowDialog();
return keyboardForm.keyinfo;
    }
    private class KeyboardForm : Form
{
public bool checkKeyDown = true;
      public KeyInfo keyinfo;
      public KeyboardForm()
{
this.KeyDown += new KeyEventHandler(this.KeyboardForm_KeyDown);
this.KeyUp += new KeyEventHandler(this.KeyboardForm_KeyUp);
      }
      private void KeyboardForm_KeyDown(object sender, KeyEventArgs e)
{
if (!this.checkKeyDown)
return;
this.keyinfo.VirtualKeyCode = e.KeyValue;
this.keyinfo.Character = ReadKeyBox.GetCharFromKeys(e.KeyCode, e.Shift, e.Alt & e.Control)[0];
this.keyinfo.KeyDown = false;
this.keyinfo.ControlKeyState = (ControlKeyStates) 0;
if (e.Alt)
this.keyinfo.ControlKeyState = ControlKeyStates.RightAltPressed | ControlKeyStates.LeftAltPressed;
if (e.Control)
{
this.keyinfo.ControlKeyState |= ControlKeyStates.RightCtrlPressed | ControlKeyStates.LeftCtrlPressed;
if (!e.Alt && e.KeyValue > 64 && e.KeyValue < 96)
this.keyinfo.Character = (char) (e.KeyValue - 64);
}
if (e.Shift)
this.keyinfo.ControlKeyState |= ControlKeyStates.ShiftPressed;
if ((e.Modifiers & Keys.Capital) > Keys.None)
this.keyinfo.ControlKeyState |= ControlKeyStates.CapsLockOn;
if ((e.Modifiers & Keys.NumLock) > Keys.None)
this.keyinfo.ControlKeyState |= ControlKeyStates.NumLockOn;
this.Close();
      }
      private void KeyboardForm_KeyUp(object sender, KeyEventArgs e)
{
if (this.checkKeyDown)
return;
this.keyinfo.VirtualKeyCode = e.KeyValue;
this.keyinfo.Character = ReadKeyBox.GetCharFromKeys(e.KeyCode, e.Shift, e.Alt & e.Control)[0];
this.keyinfo.KeyDown = true;
this.keyinfo.ControlKeyState = (ControlKeyStates) 0;
if (e.Alt)
this.keyinfo.ControlKeyState = ControlKeyStates.RightAltPressed | ControlKeyStates.LeftAltPressed;
if (e.Control)
{
this.keyinfo.ControlKeyState |= ControlKeyStates.RightCtrlPressed | ControlKeyStates.LeftCtrlPressed;
if (!e.Alt && e.KeyValue > 64 && e.KeyValue < 96)
this.keyinfo.Character = (char) (e.KeyValue - 64);
}
if (e.Shift)
this.keyinfo.ControlKeyState |= ControlKeyStates.ShiftPressed;
if ((e.Modifiers & Keys.Capital) > Keys.None)
this.keyinfo.ControlKeyState |= ControlKeyStates.CapsLockOn;
if ((e.Modifiers & Keys.NumLock) > Keys.None)
this.keyinfo.ControlKeyState |= ControlKeyStates.NumLockOn;
this.Close();
}
}
}
}
 

sudom4n

Member
Joined
Nov 22, 2019
Messages
7
Programming Experience
1-3
Theres some other cs forms that I haven't posted. Let myself know if they needed to take a look. I have posted what I believe to be suspicious,
However they are other forms named: (Please request if required)

PS2EXEHostUI
PS2EXEHost.cs
PS2EXEApp.cs
PS2EXE.cs
ConsoleInfo.CS
InputBox.cs
ProgressForm.CS
AssemblyInfo.CS
ChoiceBox.cs
 

sudom4n

Member
Joined
Nov 22, 2019
Messages
7
Programming Experience
1-3
For info Bitlocker Drive Encryption does not use the users credentials. Rather TPM, TPM+ Pin, or TPM + Pin + PendDrive(RecoveryKey) is used. Unless there is something I am missing on this.

I'm not sure how the password would be catched; once its been decrypted that's what I've been stuck on. This could be completely valid. Unfortunately I have trouble trusting anything that is compiled beyond the requirements to do so. (IE protecting company IP etc..)
 

Sheepings

Senior Programmer
Joined
Sep 5, 2018
Messages
652
Location
UK
Programming Experience
10+
That's a lot of code to cipher through. Anyway, Look on line 188 in your fist snipped where the password array is.

Start reading though the source for : userPwd.Password

Somewhere in the rest of the code you will find that line, so look for how the data is stored, if you find it, post back, and If I got time, I will take another look.

At a further glance, It looks like he is requesting it VIA prompt, similar to the way the opera browser does when you try to access stored passwords in the browser. Your windows password is required for viewing other passwords. See : pinvoke.net: CredUIPromptForWindowsCredentials (credui)

I should also point out, that decompiling applications is also illegal, despite this being code your manager acquired from an executable, and said compiled code running on your network; doesn't give you the rights to reverse engineer it even from a security standpoint. I have notified the mods to review the topic, as topics of this nature are generally prohibited across most forums. But if they are happy to leave it open, maybe you could link to the resource you used since there are a few different authors offering up the same script. From there I can do my own research.
 

Sheepings

Senior Programmer
Joined
Sep 5, 2018
Messages
652
Location
UK
Programming Experience
10+
I was running short on time earlier, so I Just want to be clear where I stand on this. Moderators have been online since reporting this. I am guessing they approve of this type of topic which is cool with me. As It's their decisions that decide how the board is run.

However, I won't be helping you or any other member with reverse engineering software related questions unless I know where the product came from. Because the information shared in these type of topics are often used by silly kids to do malicious things to legitimate commercial software. And I believe there is a certain liability of responsibility for any forum or ask board who allow such discussions to take place.

But I am happy to assist you with code related questions which do not pertain to further reverse engineering or questions about reverse engineering this executable, if it's non-compiled code is not public information. Since you decompiled this yourself without any help from anyone here, it will be you who will be sued if the author of the code is looking to open up a lawsuit if you've breached the licence agreement of the his/her product, and for putting their source code in the public domain if its not meant to be there.

On that note, if your manager used software which has already publicly shared its source code online, then I don't mind assisting you with code related questions. But if the decompiled code was already available, I don't think you would have gone through the hassle of decompiling it, in which case I won't be helping further. Hope you understand why. :)
 

Skydiver

Well-known member
Joined
Apr 6, 2019
Messages
644
Location
Virginia Beach, VA
Programming Experience
10+

Skydiver

Well-known member
Joined
Apr 6, 2019
Messages
644
Location
Virginia Beach, VA
Programming Experience
10+
Instead my manager decided to embedded PowerShell code in C# and compile it into an exe
So first off all, this is a fallacy. The PowerShell script is not actually being embedded into C#. Here's what Ingo wrote about his tool originally:
It does not convert the PowerShell script to an other language! It encapsulates the script with a lightweight PowerShell host written in C# and compiles the dynamically generated C# source code in memory to an EXE file. The resulting EXE is an .NET assembly that contains the source script encoded in Base64. The EXE includes all stuff that is needed to execute an PowerShell through the .NET object model. It is based on classes in the namespace System.Management.Automation that reperents the PowerShell engine. – Therefore the EXE file is not a real “standalone” EXE file. It needs PowerShell to be installed!!! And – of course – it needs .NET Framework v2.0. Furthermore “script execution” have to be allowed (see cmdlet: set-execultionpolicy). – The resulting EXE is “MSIL” and is able to execute as x64 or x86.
 

Skydiver

Well-known member
Joined
Apr 6, 2019
Messages
644
Location
Virginia Beach, VA
Programming Experience
10+
None of them were loading credui module.
Actually that really depends on what flags you were passing to the tool. If the -noConsole or the -credentialGUI flag is used with the MScholtes version, or the -noConsole flag is used with Ingo's original version, then the CredUI module would be imported by virtue of the P/Invoke calls to CredUI within the generated code.
 

Skydiver

Well-known member
Joined
Apr 6, 2019
Messages
644
Location
Virginia Beach, VA
Programming Experience
10+
This is one thing that I have noticed that is exceptionally dodgy on the original exe mostly because the code is decrypting the password in buffer; and assigning to a string builder. One thing I cant figure out is where it is being saved; or how the writer of the code is getting the password.
Where are you seeing this decryption?

I'm really burnt out after 5 days on call with 2 more days to go, but from what I am seeing, there is a call to CredUIPromptForWindowsCredentials() to prompt the user for a password. The StringBuilders that you see are to satisfy the requirements of P/Invoke marshaling of character buffers (as opposed to strings). Unfortunately, that password is returned by the P/Invoke call is in clear text and stored into the UserPwd class. The author then copies that password from that class into a SecureString because that is what the PowerShell PSCredential needs. PSCredential is the ubiquitous way of passing around credentials in PowerShell.

So in conclusion, the author tries to be as careful with password as possible, but doesn't go overboard by doing the older .NET 2.0 recommendations of overwriting the memory where the clear text password used to be.

In truth, even the .NET Core is recommending avoiding using SecureString:
Important

We don't recommend that you use the SecureString class for new development. For more information, see SecureString shouldn't be used on GitHub.
 
Top Bottom