How can I keep my application from a keyboard logger?
-
Tuesday, September 18, 2012 5:51 AM
My program needs some high security measures to keep it from any would-be attackers. So I got an idea:
when password textbox is focused, I used a background worker to send a lot of virtual keypress by either keybd_event or Sendkeys.Send. But soon I find out, though my application can tell actual keypress from the virtual one, the user input might be interrupted or lost. For example, user often use SHIFT key to type a single capital "A", but because of the virtual keypress, all of them appears as lower-case "a". (CapsLock doesn't seem to be affected)
Then I made some improvement: save the keyboard state by GetKeyboardState() and then restore it once codes are executed using SetKeyboardState(). It got better, but it's still fifty-fifty chance the SHIFT will be lost.
So here I wonder why? And is there any other solutions? I searched the Internet and found a lot of anti-keylogger software, but no articles about these.
I would really appreciate if you can help.
Does this unit have a soul?
All Replies
-
Tuesday, September 18, 2012 6:37 AM
When the password textbox has focus it loses the shift function from the keyboard? Do you capture the incoming keyboard keystroke and then pass it to the password textbox? And if so what code do you use to do that?
You've taught me everything I know but not everything you know.
-
Tuesday, September 18, 2012 7:47 AM
In this code I set the TextBox2 (password TextBox) property Read Only to true. And the GetAsyncKeyState will detect Caps Lock, Shift, Num Lock and Normal Keyboard operations. However I don't know how to make it backspace or delete in the TextBox so Button1 is used to clear the TextBox if the user entering the password needs to start over due to typing error or I suppose password mismatch unless password mismatch clears the password TextBox automatically.
Don't know if this is what you are looking for though. Also TextBox2.Backcolor is set to white.
Imports System.Runtime.InteropServices Public Class Form1 <DllImport("user32.dll")> Public Shared Function GetAsyncKeyState(ByVal vKey As Int32) As UShort End Function Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load TextBox2.ReadOnly = True KeyPreview = True End Sub Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown If (GetAsyncKeyState(&H6E) And My.Computer.Keyboard.NumLock) Then TextBox2.AppendText(".") ElseIf (GetAsyncKeyState(&H67) And My.Computer.Keyboard.NumLock) Then TextBox2.AppendText("7") ElseIf (GetAsyncKeyState(&H68) And My.Computer.Keyboard.NumLock) Then TextBox2.AppendText("8") ElseIf (GetAsyncKeyState(&H69) And My.Computer.Keyboard.NumLock) Then TextBox2.AppendText("9") ElseIf (GetAsyncKeyState(&H64) And My.Computer.Keyboard.NumLock) Then TextBox2.AppendText("4") ElseIf (GetAsyncKeyState(&H66) And My.Computer.Keyboard.NumLock) Then TextBox2.AppendText("6") ElseIf (GetAsyncKeyState(&H61) And My.Computer.Keyboard.NumLock) Then TextBox2.AppendText("1") ElseIf (GetAsyncKeyState(&H62) And My.Computer.Keyboard.NumLock) Then TextBox2.AppendText("2") ElseIf (GetAsyncKeyState(&H63) And My.Computer.Keyboard.NumLock) Then TextBox2.AppendText("3") ElseIf (GetAsyncKeyState(&H60) And My.Computer.Keyboard.NumLock) Then TextBox2.AppendText("0") ElseIf (GetAsyncKeyState(&H51) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("Q") ElseIf (GetAsyncKeyState(&H57) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("W") ElseIf (GetAsyncKeyState(&H45) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("E") ElseIf (GetAsyncKeyState(&H52) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("R") ElseIf (GetAsyncKeyState(&H54) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("T") ElseIf (GetAsyncKeyState(&H59) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("Y") ElseIf (GetAsyncKeyState(&H55) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("U") ElseIf (GetAsyncKeyState(&H49) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("I") ElseIf (GetAsyncKeyState(&H4F) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("O") ElseIf (GetAsyncKeyState(&H50) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("P") ElseIf (GetAsyncKeyState(&H41) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("A") ElseIf (GetAsyncKeyState(&H53) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("S") ElseIf (GetAsyncKeyState(&H44) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("D") ElseIf (GetAsyncKeyState(&H46) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("F") ElseIf (GetAsyncKeyState(&H47) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("G") ElseIf (GetAsyncKeyState(&H48) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("H") ElseIf (GetAsyncKeyState(&H4A) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("J") ElseIf (GetAsyncKeyState(&H4B) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("K") ElseIf (GetAsyncKeyState(&H4C) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("L") ElseIf (GetAsyncKeyState(&H5A) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("Z") ElseIf (GetAsyncKeyState(&H58) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("X") ElseIf (GetAsyncKeyState(&H43) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("C") ElseIf (GetAsyncKeyState(&H56) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("V") ElseIf (GetAsyncKeyState(&H42) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("B") ElseIf (GetAsyncKeyState(&H4E) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("N") ElseIf (GetAsyncKeyState(&H4D) And My.Computer.Keyboard.CapsLock) Then TextBox2.AppendText("M") ElseIf (GetAsyncKeyState(&HC0) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("`") ElseIf (GetAsyncKeyState(&H31) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("!") ElseIf (GetAsyncKeyState(&H32) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("@") ElseIf (GetAsyncKeyState(&H33) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("#") ElseIf (GetAsyncKeyState(&H34) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("$") ElseIf (GetAsyncKeyState(&H35) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("%") ElseIf (GetAsyncKeyState(&H36) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("^") ElseIf (GetAsyncKeyState(&H37) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("&") ElseIf (GetAsyncKeyState(&H38) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("*") ElseIf (GetAsyncKeyState(&H39) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("(") ElseIf (GetAsyncKeyState(&H30) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText(")") ElseIf (GetAsyncKeyState(&HBD) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("_") ElseIf (GetAsyncKeyState(&HBB) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("+") ElseIf (GetAsyncKeyState(&H51) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("Q") ElseIf (GetAsyncKeyState(&H57) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("W") ElseIf (GetAsyncKeyState(&H45) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("E") ElseIf (GetAsyncKeyState(&H52) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("R") ElseIf (GetAsyncKeyState(&H54) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("T") ElseIf (GetAsyncKeyState(&H59) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("Y") ElseIf (GetAsyncKeyState(&H55) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("U") ElseIf (GetAsyncKeyState(&H49) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("I") ElseIf (GetAsyncKeyState(&H4F) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("O") ElseIf (GetAsyncKeyState(&H50) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("P") ElseIf (GetAsyncKeyState(&HDB) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("{") ElseIf (GetAsyncKeyState(&HDD) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("}") ElseIf (GetAsyncKeyState(&HDC) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("|") ElseIf (GetAsyncKeyState(&H41) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("A") ElseIf (GetAsyncKeyState(&H53) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("S") ElseIf (GetAsyncKeyState(&H44) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("D") ElseIf (GetAsyncKeyState(&H46) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("F") ElseIf (GetAsyncKeyState(&H47) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("G") ElseIf (GetAsyncKeyState(&H48) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("H") ElseIf (GetAsyncKeyState(&H4A) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("J") ElseIf (GetAsyncKeyState(&H4B) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("K") ElseIf (GetAsyncKeyState(&H4C) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("L") ElseIf (GetAsyncKeyState(&HBA) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText(":") ElseIf (GetAsyncKeyState(&HDE) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("""") ElseIf (GetAsyncKeyState(&H5A) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("Z") ElseIf (GetAsyncKeyState(&H58) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("X") ElseIf (GetAsyncKeyState(&H43) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("C") ElseIf (GetAsyncKeyState(&H56) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("V") ElseIf (GetAsyncKeyState(&H42) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("B") ElseIf (GetAsyncKeyState(&H4E) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("N") ElseIf (GetAsyncKeyState(&H4D) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("M") ElseIf (GetAsyncKeyState(&HBC) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("<") ElseIf (GetAsyncKeyState(&HBE) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText(">") ElseIf (GetAsyncKeyState(&HBF) And My.Computer.Keyboard.ShiftKeyDown) Then TextBox2.AppendText("?") ElseIf GetAsyncKeyState(&HC0) Then TextBox2.AppendText("`") ElseIf GetAsyncKeyState(&H31) Then TextBox2.AppendText("1") ElseIf GetAsyncKeyState(&H32) Then TextBox2.AppendText("2") ElseIf GetAsyncKeyState(&H33) Then TextBox2.AppendText("3") ElseIf GetAsyncKeyState(&H34) Then TextBox2.AppendText("4") ElseIf GetAsyncKeyState(&H35) Then TextBox2.AppendText("5") ElseIf GetAsyncKeyState(&H36) Then TextBox2.AppendText("6") ElseIf GetAsyncKeyState(&H37) Then TextBox2.AppendText("7") ElseIf GetAsyncKeyState(&H38) Then TextBox2.AppendText("8") ElseIf GetAsyncKeyState(&H39) Then TextBox2.AppendText("9") ElseIf GetAsyncKeyState(&H30) Then TextBox2.AppendText("0") ElseIf GetAsyncKeyState(&HBD) Then TextBox2.AppendText("-") ElseIf GetAsyncKeyState(&HBB) Then TextBox2.AppendText("=") ElseIf GetAsyncKeyState(&H51) Then TextBox2.AppendText("q") ElseIf GetAsyncKeyState(&H57) Then TextBox2.AppendText("w") ElseIf GetAsyncKeyState(&H45) Then TextBox2.AppendText("e") ElseIf GetAsyncKeyState(&H52) Then TextBox2.AppendText("r") ElseIf GetAsyncKeyState(&H54) Then TextBox2.AppendText("t") ElseIf GetAsyncKeyState(&H59) Then TextBox2.AppendText("y") ElseIf GetAsyncKeyState(&H55) Then TextBox2.AppendText("u") ElseIf GetAsyncKeyState(&H49) Then TextBox2.AppendText("i") ElseIf GetAsyncKeyState(&H4F) Then TextBox2.AppendText("o") ElseIf GetAsyncKeyState(&H50) Then TextBox2.AppendText("p") ElseIf GetAsyncKeyState(&HDB) Then TextBox2.AppendText("[") ElseIf GetAsyncKeyState(&HDD) Then TextBox2.AppendText("]") ElseIf GetAsyncKeyState(&HDC) Then TextBox2.AppendText("\") ElseIf GetAsyncKeyState(&H41) Then TextBox2.AppendText("a") ElseIf GetAsyncKeyState(&H53) Then TextBox2.AppendText("s") ElseIf GetAsyncKeyState(&H44) Then TextBox2.AppendText("d") ElseIf GetAsyncKeyState(&H46) Then TextBox2.AppendText("f") ElseIf GetAsyncKeyState(&H47) Then TextBox2.AppendText("g") ElseIf GetAsyncKeyState(&H48) Then TextBox2.AppendText("h") ElseIf GetAsyncKeyState(&H4A) Then TextBox2.AppendText("j") ElseIf GetAsyncKeyState(&H4B) Then TextBox2.AppendText("k") ElseIf GetAsyncKeyState(&H4C) Then TextBox2.AppendText("l") ElseIf GetAsyncKeyState(&HBA) Then TextBox2.AppendText(";") ElseIf GetAsyncKeyState(&HDE) Then TextBox2.AppendText("'") ElseIf GetAsyncKeyState(&H5A) Then TextBox2.AppendText("z") ElseIf GetAsyncKeyState(&H58) Then TextBox2.AppendText("x") ElseIf GetAsyncKeyState(&H43) Then TextBox2.AppendText("c") ElseIf GetAsyncKeyState(&H56) Then TextBox2.AppendText("v") ElseIf GetAsyncKeyState(&H42) Then TextBox2.AppendText("b") ElseIf GetAsyncKeyState(&H4E) Then TextBox2.AppendText("n") ElseIf GetAsyncKeyState(&H4D) Then TextBox2.AppendText("m") ElseIf GetAsyncKeyState(&HBC) Then TextBox2.AppendText(",") ElseIf GetAsyncKeyState(&HBE) Then TextBox2.AppendText(".") ElseIf GetAsyncKeyState(&HBF) Then TextBox2.AppendText("/") ElseIf GetAsyncKeyState(&HA2) Then TextBox2.AppendText("^") ElseIf GetAsyncKeyState(&H12) Then TextBox2.AppendText("%") ElseIf GetAsyncKeyState(&HA3) Then TextBox2.AppendText("^") ElseIf GetAsyncKeyState(&H65) Then TextBox2.AppendText("5") End If End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click TextBox2.Text = "" End Sub End Class
You've taught me everything I know but not everything you know.
- Edited by Mr. MonkeyboyMicrosoft Community Contributor Tuesday, September 18, 2012 8:02 AM
-
Wednesday, September 19, 2012 3:36 AMModerator
Hi legion,
Thanks for you post.
I’d like to suggest you to use virtual keyboard instead.
You can add a button on the right of the password textbox, and let or force the users to using mouse click on the virtual keyboard to pass the data into the textbox. In this way, you can get rid of the keylogger software.
Here is a keyboard sample: Create a soft keyboard (VBSoftKeyboard): http://code.msdn.microsoft.com/windowsdesktop/VBSoftKeyboard-161d92d7
Hope this helps.
Mark Liu-lxf [MSFT]
MSDN Community Support | Feedback to us
-
Wednesday, September 19, 2012 5:34 AM
This is my codes.Dim PasswordText As New Security.SecurePassword() Friend WithEvents Disruptor As New System.ComponentModel.BackgroundWorker() Private Sub PasswordTextbox_GotFocus(sender As Object, e As EventArgs) Handles PasswordTextbox.GotFocus Disruptor.RunWorkerAsync() End Sub Private Sub PasswordTextbox_LostFocus(sender As Object, e As EventArgs) Handles PasswordTextbox.LostFocus Disruptor.CancelAsync() End Sub Private Sub PasswordTextbox_Keydown(sender As Object, e As KeyDownEventArgs) Handles PasswordTextbox.KeyDown If Not (AllowedInput.Contains(e.KeyCode)) Then e.SuppressKeyPress = True 'AllowedInput is an array of all valid key codes. 'Following lines of codes can suppress keypress send by my application. End Sub Private Sub PasswordTextbox_KeyPress(sender As Object, e As KeyPressEventArgs) Handles PasswordTextbox.KeyPress PasswordText.Append(e.KeyChar) PasswordTextbox.Text = Space(PasswordText.Length) End Sub Private Sub OK_Click(sender As Object, e As EventArgs) Handles OK.Click PasswordText.MakeReadOnly() 'Other login procedures End Sub Private Sub Disruptor_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles Disruptor.DoWork Do Dim a(255) As Byte GetKeyboardState(a) Dim b As New Random() For i = 0 to 3 Sendkeys.SendWait(Chr(a.Next(32,128))) Next SetKeyboardState(a) Threading.Thread.Sleep(10) Loop Until Disruptor.CancellationPending End Sub Private Sub Form_Load(sender As Object, e As EventArgs) Handles Me.Load Disruptor.WorkerSupportsCancellation = True End Sub
- Edited by Legion the Geth Wednesday, September 19, 2012 5:50 AM Add some comments in code
-
Wednesday, September 19, 2012 5:36 AM
Hello Legion the Gerth,
You simply cannot use VB to prevent key loggers are active.
They work on a machine to low level to be reachable for VB. Your have to use a program language like C++, C or Intel Assembler.
Or you should disconnect your keyboard completely like I assume the others suggest and use a keyboard on the screen done by the mouse.
Success
Cor -
Wednesday, September 19, 2012 5:39 AM
I know that, but then how can I get rid of screen capture spyware?
And also, it causes great inconvenience.
Does this unit have a soul?
-
Wednesday, September 19, 2012 5:46 AMSee my codes up there, I believe it can disrupt the keylogger(I've tested it). But the problem is, it also makes SHIFT key dysfunctional.
Does this unit have a soul?
-
Wednesday, September 19, 2012 6:00 AMModerator
I know that, but then how can I get rid of screen capture spyware?
And also, it causes great inconvenience.
Does this unit have a soul?
Hi Legion,
Personally, I think screen capture doesn't make sense. A mouse location will not be showed into the screenshot. You also can random the location of buttons in the Virtual keyboard (in every time click a letter into password) to rid of the screen capture spyware.
Hope this helps.
Mark Liu-lxf [MSFT]
MSDN Community Support | Feedback to us
- Edited by Mark Liu-lxfModerator Wednesday, September 19, 2012 6:03 AM
-
Thursday, September 20, 2012 5:36 AM
A mouse location will not be showed into the screenshot. You also can random the location of buttons in the Virtual keyboard (in every time click a letter into password) to rid of the screen capture spyware
1.Random the location of buttons, that's a lovely idea. Inconvenient for user, but more secure.
2.But I still believe that a screen-capture software can capture mouse location simultaneously. For example, if I hook the mouse click function, then get a screenshot while recording a mouse location with GetCursorPos() when mouse clicked, then I should be able to recover every letters ever typed.
Does this unit have a soul?
-
Thursday, September 20, 2012 12:37 PMModerator
Hi Legion,
Could you please send a simple example that can reproduce the issue(SHIFT missing)? If it is OK, please send it to alanyao@microsoft.com
However, I do agree vitrual keyboard with random buttons is a good idea if the security is the top concern for you.
Regards,
Alan Yao [MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.

- Edited by Alan_YaoMicrosoft Employee, Moderator Thursday, September 20, 2012 12:40 PM
-
Friday, September 21, 2012 5:47 AM
Thanks for your attention. I should be able to send it to you next Sunday. I'm at school right now while my source codes are at home.
I'm still not convinced with your opinions quite though. As I said above, if I use api to add some hooks in the system, I can intercept the mouse click events and then record the mouse coordinates. So with the snapshot, it will be rather easy to recover the password. So I don't think it's safe enough.
Please tell me if there is any mistake.
Does this unit have a soul?
-
Friday, September 21, 2012 9:09 AM
There's a function to stop screen capture I think. It is called SetWindowDisplayAffinity "This function and GetWindowDisplayAffinity are designed to support the window content protection feature that is new to Windows 7. This feature enables applications to protect their own onscreen window content from being captured or copied through a specific set of public operating system features and APIs. However, it works only when the Desktop Window Manager(DWM) is composing the desktop."
http://msdn.microsoft.com/en-us/library/windows/desktop/dd375340(v=vs.85).aspx
I have code to check if DWM is enabled prior to using SetWindowDisplayAffinity but I have no idea how to do the DLLImport or the Public Shared Function for SetWindowDisplayAffinity or use SetWindowDisplayAffinity even if I knew how to do the DllImport or Public Shared Function for it.
DWM is at this link http://msdn.microsoft.com/en-us/library/windows/desktop/aa969518(v=vs.85).aspx
The code for checking if DWM is enabled follows;
Imports System.Runtime.InteropServices Public Class Form1 'SetWindowDisplayAffinity - Don't know how to do that. <DllImport("dwmapi.dll", PreserveSig:=False)> _ Public Shared Function DwmIsCompositionEnabled() As Boolean End Function Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load If DwmIsCompositionEnabled() Then MessageBox.Show(DwmIsCompositionEnabled()) Else MessageBox.Show("False") End If End Sub End ClassYou've taught me everything I know but not everything you know.
-
Friday, September 21, 2012 5:24 PM
Fernando Soto gave me the information for using SetWindowsDisplayAffinity. When it is turned on in conjunction with DWMIsCompositionEnabled (true) then your applications form window is black when someone uses print screen on it.
Below is the code I used to check if DWMIsCompositionEnabled and to turn SetWindowsDisplayAffinity on and off. The buttons on the form are Button1 to Button3 left to right.
On another note SetWindowsDisplayAffinity is only supported on Windows 7 Clients minimum and Windows Server 2008 R2 minimum.
Below the code are two images of my application, the first image is with SetWindowsDisplayAffinity on and the second image is with it off.
Imports System.Runtime.InteropServices Public Class Form1 <DllImport("dwmapi.dll", PreserveSig:=False)> _ Public Shared Function DwmIsCompositionEnabled() As Boolean End Function Declare Auto Function SetWindowDisplayAffinity Lib "User32.dll" Alias "SetWindowDisplayAffinity" (ByVal hWnd As Integer, ByVal dwAffinity As Integer) As Boolean Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click MessageBox.Show(DwmIsCompositionEnabled()) End Sub Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click ' Get the window handle Dim hWnd As Integer = Me.Handle ' Then call the function as follows SetWindowDisplayAffinity(hWnd, 1) End Sub Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click ' Get the window handle Dim hWnd As Integer = Me.Handle ' Then call the function as follows SetWindowDisplayAffinity(hWnd, 0) End Sub End Class
You've taught me everything I know but not everything you know.
- Edited by Mr. MonkeyboyMicrosoft Community Contributor Saturday, September 22, 2012 10:50 AM
-
Friday, September 21, 2012 5:53 PMAlso you could run a timer to test for DwmIsCompositionEnabled enabled and if not re-enable it and reset SetWindowsDisplayAffinity to on. I don't know if Windows 8 or later supports this feature though. And there is some discernment as to whether this function is very security worthy. But I'd say it's better than nothing on a Win 7 or later (if supported) environment.
You've taught me everything I know but not everything you know.
-
Saturday, September 22, 2012 1:08 PM
Here's an update to the code that allows you to turn on and off Dwm. You could run a timer to test if someone disabled Dwm and then turn Dwm and SetWindowDisplayAffinity on again before they could do a screen capture.
Imports System.Runtime.InteropServices Public Class Form1 <DllImport("dwmapi.dll", PreserveSig:=False)> _ Public Shared Function DwmIsCompositionEnabled() As Boolean End Function <DllImport("dwmapi.dll", PreserveSig:=False)> _ Public Shared Sub DwmEnableComposition(bEnable As Boolean) End Sub Declare Auto Function SetWindowDisplayAffinity Lib "User32.dll" Alias "SetWindowDisplayAffinity" (ByVal hWnd As Integer, ByVal dwAffinity As Integer) As Boolean Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click MessageBox.Show(DwmIsCompositionEnabled()) End Sub Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click ' Get the window handle Dim hWnd As Integer = Me.Handle ' Then call the function as follows to turn SetWindowDisplayAffinity on. SetWindowDisplayAffinity(hWnd, 1) End Sub Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click ' Get the window handle Dim hWnd As Integer = Me.Handle ' Then call the function as follows to turn SetWindowDisplayAffinity off. SetWindowDisplayAffinity(hWnd, 0) End Sub Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click DwmEnableComposition(False) End Sub Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click DwmEnableComposition(True) End Sub End Class
You've taught me everything I know but not everything you know.
-
Monday, September 24, 2012 5:32 AM
Thanks for your solution, though I'm still hoping to find a way to type with keyboard.
So your solution solve half of the problem, I'm still hoping someone can solve the rest.
I've got my source code all here, so if you find the solution, please tell me.
<frmLogin.Designer.vb>
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _ <Global.System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1726")> _ Partial Class frmLogin Inherits System.Windows.Forms.Form 'Form overrides dispose to clean up the component list. <System.Diagnostics.DebuggerNonUserCode()> _ Protected Overrides Sub Dispose(ByVal disposing As Boolean) Try If disposing AndAlso components IsNot Nothing Then components.Dispose() End If Finally MyBase.Dispose(disposing) End Try End Sub Friend WithEvents LogoPictureBox As System.Windows.Forms.PictureBox Friend WithEvents UsernameLabel As System.Windows.Forms.Label Friend WithEvents PasswordLabel As System.Windows.Forms.Label Friend WithEvents UsernameTextBox As System.Windows.Forms.TextBox Friend WithEvents PasswordTextBox As System.Windows.Forms.TextBox Friend WithEvents OK As System.Windows.Forms.Button Friend WithEvents Register As System.Windows.Forms.Button 'Required by the Windows Form Designer Private components As System.ComponentModel.IContainer 'NOTE: The following procedure is required by the Windows Form Designer 'It can be modified using the Windows Form Designer. 'Do not modify it using the code editor. <System.Diagnostics.DebuggerStepThrough()> _ Private Sub InitializeComponent() Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(frmLogin)) Me.LogoPictureBox = New System.Windows.Forms.PictureBox() Me.UsernameLabel = New System.Windows.Forms.Label() Me.PasswordLabel = New System.Windows.Forms.Label() Me.UsernameTextBox = New System.Windows.Forms.TextBox() Me.PasswordTextBox = New System.Windows.Forms.TextBox() Me.OK = New System.Windows.Forms.Button() Me.Register = New System.Windows.Forms.Button() Me.CheckPasswordChar = New System.Windows.Forms.CheckBox() CType(Me.LogoPictureBox, System.ComponentModel.ISupportInitialize).BeginInit() Me.SuspendLayout() ' 'LogoPictureBox ' Me.LogoPictureBox.Image = CType(resources.GetObject("LogoPictureBox.Image"), System.Drawing.Image) Me.LogoPictureBox.Location = New System.Drawing.Point(0, 0) Me.LogoPictureBox.Name = "LogoPictureBox" Me.LogoPictureBox.Size = New System.Drawing.Size(165, 193) Me.LogoPictureBox.TabIndex = 0 Me.LogoPictureBox.TabStop = False ' 'UsernameLabel ' Me.UsernameLabel.Location = New System.Drawing.Point(172, 24) Me.UsernameLabel.Name = "UsernameLabel" Me.UsernameLabel.Size = New System.Drawing.Size(220, 23) Me.UsernameLabel.TabIndex = 0 Me.UsernameLabel.Text = "&User name" Me.UsernameLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft ' 'PasswordLabel ' Me.PasswordLabel.Location = New System.Drawing.Point(172, 81) Me.PasswordLabel.Name = "PasswordLabel" Me.PasswordLabel.Size = New System.Drawing.Size(220, 23) Me.PasswordLabel.TabIndex = 2 Me.PasswordLabel.Text = "&Password" Me.PasswordLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft ' 'UsernameTextBox ' Me.UsernameTextBox.Location = New System.Drawing.Point(174, 44) Me.UsernameTextBox.Name = "UsernameTextBox" Me.UsernameTextBox.Size = New System.Drawing.Size(220, 20) Me.UsernameTextBox.TabIndex = 1 ' 'PasswordTextBox ' Me.PasswordTextBox.ContextMenuStrip = New ContextMenuStrip() Me.PasswordTextBox.ImeMode = System.Windows.Forms.ImeMode.Disable Me.PasswordTextBox.Location = New System.Drawing.Point(174, 101) Me.PasswordTextBox.Name = "PasswordTextBox" Me.PasswordTextBox.Size = New System.Drawing.Size(220, 20) Me.PasswordTextBox.TabIndex = 3 Me.PasswordTextBox.UseSystemPasswordChar = True ' 'OK ' Me.OK.Location = New System.Drawing.Point(183, 158) Me.OK.Name = "OK" Me.OK.Size = New System.Drawing.Size(100, 23) Me.OK.TabIndex = 4 Me.OK.Text = "&OK" ' 'Register ' Me.Register.DialogResult = System.Windows.Forms.DialogResult.Cancel Me.Register.Location = New System.Drawing.Point(289, 158) Me.Register.Name = "Register" Me.Register.Size = New System.Drawing.Size(100, 23) Me.Register.TabIndex = 5 Me.Register.Text = "&Register" ' 'CheckPasswordChar ' Me.CheckPasswordChar.Appearance = System.Windows.Forms.Appearance.Button Me.CheckPasswordChar.AutoCheck = False Me.CheckPasswordChar.Font = New System.Drawing.Font("Microsoft Sans Serif", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte)) Me.CheckPasswordChar.Location = New System.Drawing.Point(289, 127) Me.CheckPasswordChar.Name = "CheckPasswordChar" Me.CheckPasswordChar.Size = New System.Drawing.Size(100, 25) Me.CheckPasswordChar.TabIndex = 7 Me.CheckPasswordChar.Text = "&Show Password" Me.CheckPasswordChar.TextAlign = System.Drawing.ContentAlignment.MiddleCenter Me.CheckPasswordChar.UseVisualStyleBackColor = True ' 'frmLogin ' Me.AcceptButton = Me.OK Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font Me.ClientSize = New System.Drawing.Size(401, 193) Me.Controls.Add(Me.CheckPasswordChar) Me.Controls.Add(Me.Register) Me.Controls.Add(Me.OK) Me.Controls.Add(Me.PasswordTextBox) Me.Controls.Add(Me.UsernameTextBox) Me.Controls.Add(Me.PasswordLabel) Me.Controls.Add(Me.UsernameLabel) Me.Controls.Add(Me.LogoPictureBox) Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle Me.MaximizeBox = False Me.MinimizeBox = False Me.Name = "frmLogin" Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent Me.Text = "Login" CType(Me.LogoPictureBox, System.ComponentModel.ISupportInitialize).EndInit() Me.ResumeLayout(False) Me.PerformLayout() End Sub Friend WithEvents CheckPasswordChar As System.Windows.Forms.CheckBox End Class<frmLogin.vb>
Public Class frmLogin ' TODO: Insert code to perform custom authentication using the provided username and password ' (See http://go.microsoft.com/fwlink/?LinkId=35339). ' The custom principal can then be attached to the current thread's principal as follows: ' My.User.CurrentPrincipal = CustomPrincipal ' where CustomPrincipal is the IPrincipal implementation used to perform authentication. ' Subsequently, My.User will return identity information encapsulated in the CustomPrincipal object ' such as the username, display name, etc. Private PasswordText As New Security.SecureString Private SuppressedKeys As Keys() = {Keys.Add, Keys.Alt, Keys.Apps, Keys.Attn, Keys.BrowserBack, Keys.BrowserFavorites, Keys.BrowserForward, Keys.BrowserHome, Keys.BrowserRefresh, Keys.BrowserSearch, Keys.BrowserStop, Keys.Cancel, Keys.Capital, Keys.Clear, Keys.Control, Keys.ControlKey, Keys.Crsel, Keys.Down, Keys.End, Keys.Enter, Keys.EraseEof, Keys.Escape, Keys.Execute, Keys.Exsel, Keys.F1, Keys.F2, Keys.F3, Keys.F4, Keys.F5, Keys.F6, Keys.F7, Keys.F8, Keys.F9, Keys.F10, Keys.F11, Keys.F12, Keys.F13, Keys.F14, Keys.F15, Keys.F16, Keys.F17, Keys.F18, Keys.F19, Keys.F20, Keys.F21, Keys.F22, Keys.F23, Keys.F24, Keys.FinalMode, Keys.HangulMode, Keys.HanjaMode, Keys.Help, Keys.Home, Keys.IMEAccept, Keys.IMEConvert, Keys.IMEModeChange, Keys.IMENonconvert, Keys.Insert, Keys.JunjaMode, Keys.KanaMode, Keys.KanjiMode, Keys.LaunchApplication1, Keys.LaunchApplication2, Keys.LaunchMail, Keys.LControlKey, Keys.Left, Keys.LineFeed, Keys.LMenu, Keys.LWin, Keys.MediaNextTrack, Keys.MediaPlayPause, Keys.MediaPreviousTrack, Keys.MediaStop, Keys.Menu, Keys.Next, Keys.NumLock, Keys.Oem102, Keys.Pa1, Keys.Packet, Keys.PageDown, Keys.PageUp, Keys.Pause, Keys.Play, Keys.Print, Keys.PrintScreen, Keys.Prior, Keys.ProcessKey, Keys.RControlKey, Keys.Return, Keys.Right, Keys.RMenu, Keys.RWin, Keys.Scroll, Keys.Select, Keys.SelectMedia, Keys.Sleep, Keys.Snapshot, Keys.Tab, Keys.Up, Keys.VolumeDown, Keys.VolumeMute, Keys.VolumeUp, Keys.Zoom} Public WithEvents Disruptor As New System.ComponentModel.BackgroundWorker Public Disrupting As Char Private Sub DisruptorDoWork(sender As Object, e As System.EventArgs) Handles PasswordTextBox.GotFocus Disruptor.RunWorkerAsync() End Sub Private Sub DisruptorCancel(sender As Object, e As System.EventArgs) Handles PasswordTextBox.LostFocus, Me.Deactivate Disruptor.CancelAsync() End Sub Private Sub PasswordTextBox_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles PasswordTextBox.KeyDown If SuppressedKeys.Contains(e.KeyCode) OrElse e.Control OrElse e.Alt Then e.Handled = True e.SuppressKeyPress = True ElseIf e.KeyCode = Keys.Back Then If (PasswordText.Length > 0) AndAlso (PasswordTextBox.SelectionStart > 0) Then PasswordText.RemoveAt(PasswordTextBox.SelectionStart - 1) Dim a As Integer = PasswordTextBox.SelectionStart PasswordTextBox.Text = Space(PasswordText.Length) PasswordTextBox.Select(a - 1, 0) End If e.Handled = True e.SuppressKeyPress = True ElseIf e.KeyCode = Keys.Delete Then If (PasswordText.Length > 0) AndAlso (PasswordTextBox.SelectionStart < PasswordText.Length) Then PasswordText.RemoveAt(PasswordTextBox.SelectionStart) Dim a As Integer = PasswordTextBox.SelectionStart PasswordTextBox.Text = Space(PasswordText.Length) PasswordTextBox.Select(a, 0) End If e.Handled = True e.SuppressKeyPress = True End If End Sub Private Sub PasswordTextBox_KeyPress(sender As Object, e As System.Windows.Forms.KeyPressEventArgs) Handles PasswordTextBox.KeyPress If (Asc(e.KeyChar) > 127) OrElse (Asc(e.KeyChar) < 0) Then e.Handled = True Exit Sub ElseIf e.KeyChar = Disrupting Then e.Handled = True Disrupting = Chr(255) Exit Sub End If If PasswordTextBox.SelectionStart = PasswordText.Length Then PasswordText.AppendChar(e.KeyChar) Else PasswordText.InsertAt(PasswordTextBox.SelectionStart, e.KeyChar) End If Dim a As Integer = PasswordTextBox.SelectionStart PasswordTextBox.Text = Space(PasswordText.Length) PasswordTextBox.Select(a + 1, 0) e.Handled = True End Sub Private Sub PasswordTextBox_Deselect(sender As Object, e As System.EventArgs) Handles PasswordTextBox.MouseDown, PasswordTextBox.MouseMove, PasswordTextBox.MouseUp, PasswordTextBox.TextChanged PasswordTextBox.DeselectAll() End Sub Private Sub CheckPasswordChar_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles CheckPasswordChar.MouseDown If e.Button = Windows.Forms.MouseButtons.Left Then Dim Cur As Integer = PasswordTextBox.SelectionStart PasswordTextBox.UseSystemPasswordChar = False Dim a As IntPtr = Runtime.InteropServices.Marshal.SecureStringToBSTR(PasswordText) PasswordTextBox.Text = Runtime.InteropServices.Marshal.PtrToStringBSTR(a) Runtime.InteropServices.Marshal.ZeroFreeBSTR(a) PasswordTextBox.SelectionStart = Cur PasswordTextBox.SelectionLength = 0 End If End Sub Private Sub CheckPasswordChar_MouseUp(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles CheckPasswordChar.MouseUp If e.Button = Windows.Forms.MouseButtons.Left Then Dim Cur As Integer = PasswordTextBox.SelectionStart PasswordTextBox.UseSystemPasswordChar = True Do Loop Until DisposeString(PasswordTextBox.Text) PasswordTextBox.Text = Space(PasswordText.Length) PasswordTextBox.SelectionStart = Cur PasswordTextBox.SelectionLength = 0 End If End Sub Private Sub TextBox_MouseEnter(sender As Object, e As System.EventArgs) Handles UsernameTextBox.MouseEnter, PasswordTextBox.MouseEnter CType(sender, TextBox).Focus() End Sub Public Function DisposeString(ByRef S As String) As Boolean If IsNothing(S) OrElse (S = "") Then Return True Try Dim OriginalByteCount As Integer = S.Length * 2 Dim c As IntPtr = Runtime.InteropServices.GCHandle.Alloc(S, Runtime.InteropServices.GCHandleType.Pinned).AddrOfPinnedObject Dim Counter As Integer = -1 For i = 0 To OriginalByteCount Counter = Counter + 1 Runtime.InteropServices.Marshal.WriteByte(c + Counter, 0) Next Catch ex As Exception Return False End Try Return True End Function Private Sub Disruptor_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles Disruptor.DoWork Disruptor.WorkerSupportsCancellation = True Do Until Disruptor.CancellationPending Dim a As New Random Disrupting = Chr(a.Next(128, 256)) Dim b(255) As Byte NativeUnsafeMethods.GetKeyState(Keys.None) 'Solve GetKeyboardState bug NativeUnsafeMethods.GetKeyboardState(b) SendKeys.SendWait("{" & Disrupting & "}") NativeUnsafeMethods.SetKeyboardState(b) Disrupting = Chr(255) Threading.Thread.Sleep(100) Loop Disrupting = Chr(255) End Sub End Class Public Class NativeUnsafeMethods Public Declare Function GetKeyState Lib "user32.dll" (nVirtKey As Integer) As Short Public Declare Function GetKeyboardState Lib "user32.dll" (lpKeyState As Byte()) As Boolean Public Declare Function SetKeyboardState Lib "user32.dll" (ByRef lpKeyState As Byte()) As Boolean End ClassDoes this unit have a soul?
-
Monday, September 24, 2012 5:35 AM
I've send you the code. And it is also posted on this thread. If you find a way to solve this problem apart from using screen keyboard, please let me know it.
Does this unit have a soul?
-
Monday, September 24, 2012 5:48 AMIf you are having difficulty finding a solution to your problem, you may wish to consider that the information you need to help defend against a keylogger is the same informtion that a keylogger would use to improve their chances of success. People might be concerned about discussing their solutions in public.
-
Thursday, September 27, 2012 5:37 AM
Thanks. I've already considered this when I post this thread.
But you know, I don't want a completely new solution. I just want to find out what is wrong with my solution, and to look for a way to solve it.
So please read my description about this question up there and my code.
A short version of my solution:
If a keylogger wants to log the password, it must hook the keyboard input. So I send virtual keypress generated randomly which can only be distinguished by my application. So the keylogger will log a lot of keypress but cannot find out which is the password.
Does this unit have a soul?
-
Wednesday, October 17, 2012 10:20 AM
There is little point trying to stop key loggers from capturing the keyboard. By the time they have the ability to capture key presses they are normally able to do anything an administrator would be able to do, including installing themselves as mouse, keyboard and video drivers. They can even install a root kit to make it hard for virus checkers to spot them. If they are really targeting you specifically they can change your application at a binary level to remove any security code you have put in. As a general rule of thumb you should always assume that anything on a client computer has been compromised.
A better way to prevent this kind of attack is to make your identity check depend on a token that changes over time or can only be used once. This is why banks all seem to be issuing hardware devices for either generating time dependant codes or using a chip and pin card to encrypt some kind of challenge response code. This way any login captured by a key logger will only be useable once and the criminal getting the information will not find it very useful as it will already have been used.
a

