I am writing a program that traverses the registry. When encountering the HKEY_CLASSES_ROOT\VirtualStore\MACHINE\SOFTWARE\Wow6432Node-Key, the program stops because
var openedKey = key.OpenSubKey(/* any name of the present (!) subkeys*/);
// where "key" is "HKEY_CLASSES_ROOT\VirtualStore\MACHINE\SOFTWARE\Wow6432Node"
yields null.
Therefore, I tried to find this key using regedit.exe and reg.exe and the result was that there are indeed subkeys that can be seen using this methods. Furthermore,
key.GetSubKeyNames()
returns the exact same values for the names.
I tried compiling for 64- and 32-bit CPUs and passed both RegistryView.Registry32 and RegistryView.Registry64 to the first
RegistryKey.OpenBaseKey(hive, view)
call.
This did not solve the problem.
Why are the returned keys null?
Related
I'm writing code that sets a value in the Windows registry. when I set that value manually, it works as expected; when I want to set the value programmatically, however, it gives an error. The value I want to define is a DWORD value type that is "4294967295". When I define that in the script, though, it says that DWORD does not support this value. And, yet, I can assign that exact value via the program I am using to manually update the registry.
Here's my code:
RegistryKey key = Registry.CurrentUser.OpenSubKey(#"Software\Lost in Days Studio\NO TIME", true);
key.SetValue("Current", 4294967295, RegistryValueKind.DWord);
key.Close();
As you likely know, a DWORD is stored as a 32 bit binary number. What may not be immediately obvious, though, is that it's unsigned—and, thus, a UInt32 (uint). Otherwise, you wouldn't be able to store a value of 4294967295, since the maximum value for a signed integer (int) is 2,147,483,647.
There's a catch, however! As #Jimi noted in the comments, SetValue() will attempt to do a Convert.ToInt32(), which will cause an overflow with any value above Int32.MaxValue—thus the error you are receiving. One would expect it to use Convert.ToUInt32() but, as #Jimi also discovered, that is a known bug in the method, which Microsoft is unable to fix due to backward compatibility concerns.
Instead, the SetValue() method converts a signed Int32 (int) into an unsigned 32 bit binary number, with values of 0…2147483647 remaining as is, but values of -2147483647…-1 getting saved to the 2147483648…4294967295 range.
That binary conversion is a bit convoluted if you're thinking about this as a signed integer. But, fortunately, you can use C#’s built-in unchecked() keyword to permit the overflow and effectively treat your uint as a signed int within those ranges:
key.SetValue("Current", unchecked((int)4294967295), RegistryValueKind.DWord);
This is really handy because it allows for you to continue to work with a standard UInt32 (uint) range of 0…4294967295, exactly like you would via e.g. RegEdit, without having to think about how the binary conversion is being handled.
BACKGROUND:
I am writing a 32 bit WPF (C#) application which functions as an on-screen keyboard. It publishes the selected key strokes to the focused window as if physical keys had been pressed, exactly as the Microsoft On-Screen Keyboard, OSK.exe behaves.
PROBLEM:
I was using the InputSimulator library with some success (code here: InputSimulator class which builds the INPUT array), but found that certain key strokes were not being recognised by Notepad as expected, e.g. the arrow keys were behaving as if CTRL was being held down. Similarly, the WIN key was not working as expected, which could also be explained if Windows was treating the input as Ctrl+Win.
ATTEMPTED SOLUTION:
I ported the InputSimulator source into my project and made some modifications to how keystrokes are sent to SendInput, based on the calls to SendInput that OSK.exe sends (captured using API Monitor). The key differences I observed (and replicated in my code) for a KeyDown/KeyUp are:
InputSimulator passes a Keycode, and an ExtendedKey flag (if the key is extended), plus the KeyUp flag when releasing the key.
OSK adds the key's Scancode, and the ScanCode flag for the majority of keys.
OSK also has some other differences; individual keys where the KeyCode is not passed at all, where the ScanCode is not passed at all, and differences in which keys require the ExtendedKey flag.
The result of my changing the code to replicate how OSK calls SendInput was that even more keys now behave as if CTRL is being detected by my target/focussed application (typically Notepad or Wordpad). However, from direct comparison of my app and OSK in API Monitor I believe that my calls to SendInput are identical to OSK's calls.
N.B. OSK works flawlessly on my Windows 8.1 (64 bit) laptop.
ISOLATED PROBLEM SPACE:
To minimise the problem space I simulated a single key down/key up combination of the 'S' key from my application on a newly restarted PC (so that I can be sure the key down states were not contaminated from previous runs or physical key strokes). The target was Notepad and then WordPad - both reacted by opening the 'Save As' dialog, suggesting that they had interpreted my keystrokes as CTRL+S. API Monitor detected only 2 calls to SendInput (the KeyDown and then KeyUp), and these calls matched the same experiment using OSK. Here is the log;
2014-12-10 21:29:54,650 Calling native method SendInput with params:
nInputs:1
pInputs[0]:
Type:1(Keyboard)
Data:
MOUSEINPUT:
X:2031699
Y:8
MouseData:0
Flags:0 ()
Time:0
KEYBDINPUT:
KeyCode:83(VK_S)
Scan:31
Flags:8 (KEYEVENTF_SCANCODE)
Time:0
ExtraInfo:0
HARDWAREINPUT:
Msg:2031699
ParamL:8
ParamH:0
cbSize:28
2014-12-10 21:29:54,651 Calling native method SendInput with params:
nInputs:1
pInputs[0]:
Type:1(Keyboard)
Data:
MOUSEINPUT:
X:2031699
Y:10
MouseData:0
Flags:0 ()
Time:0
KEYBDINPUT:
KeyCode:83(VK_S)
Scan:31
Flags:10 (KEYEVENTF_KEYUP | KEYEVENTF_SCANCODE)
Time:0
ExtraInfo:0
HARDWAREINPUT:
Msg:2031699
ParamL:10
ParamH:0
cbSize:28
The only noticeable difference is that OSK passes the cbSize param as 40, which I cannot fake (the call fails if I manually pass 40). My size is 28, which I get by passing the below. I have no idea why the sizes differ as my structure definitions match the MSDN documentation (I have not modified these from the original InputSimulator code).
var cbSize = Marshal.SizeOf(typeof (INPUT));
OTHER ATTEMPTED FIXES:
I have tried leaving the VirtualCode param blank (0) when a ScanCode (and ScanCode flag) are specified, but this does not change the result. Idea from here: SO question
I have tried adding a trailing call to keybd_event, but this does not change the result. Idea from here: MSDN thread
(keybd_event(0x41, 0, 0, 0);)
I have tried adding a thread sleep between each call to SendInput, i.e. a delay between the KeyDown and KeyUp calls.
I have modified my structs and winapi function definitions to match PINVOKE.net
I have recompiled my application as 64 bit (on my 64 bit machine) - this corrected the cbSize to 40, but did not change the behaviour.
Any help would be GREATLY appreciated. Also any suggestions regarding other debugging tools I could use? I have attempted to debug all Keyboard functions which OSK may be calling (to detect other calls to keybd_event, for example), but none are logged besides the calls to SendInput.
Right, so the issue was PEBCAK.
I missed the most obvious thing imaginable - the trigger signal that I have been using while testing (i.e. the signal to say that I want to press the currently focused an on-screen key) is the left CTRL key. I've been pressing the CTRL key and then wondering why Windows thinks the CTRL key is pressed. Shoot me now.
I've been using it for so long, and have been so focused on the details of the potentially misbehaving WinAPI calls that I missed the most obvious cause.
I will leave this here to remind myself to use Occam's Razor.
Some of the debugging journey above may be useful to someone; my altered version of the InputSimulator code works fine, as does the original, unaltered code.
I have observed a strange behaviour when comparing two strings with ==.
A little bit of context: The following code is from an application which should act as server and it should validate the thumbprint of the clientcertificate.
I have a client application with a certificate with the following thumbprint: "2074529C99D93D5955FEECA859AEAC6092741205". When I call the server this method returns Valid:
static CertificateValidationResult ValidateClientCertificate(X509Certificate2 clientcertificate)
{
return clientcertificate.Thumbprint == "2074529C99D93D5955FEECA859AEAC6092741205"
? CertificateValidationResult.Valid
: CertificateValidationResult.Rejected;
}
After I changed to a clientcertificate with the thumbprint "F9A021D2EFDCD3BD13671CE1D25CFE51BA5BA38E" and changed the server code the following method returns Rejected:
static CertificateValidationResult ValidateClientCertificate(X509Certificate2 clientcertificate)
{
return clientcertificate.Thumbprint == "F9A021D2EFDCD3BD13671CE1D25CFE51BA5BA38E"
? CertificateValidationResult.Valid
: CertificateValidationResult.Rejected;
}
In each case the strings are exactly the same, but only the first one returned Valid. Why is this happening?
If you copied / pasted the Thumbprint you may have accidentally copied a hidden character / symbol. Often these don't appear in the Visual Studio IDE even if you enable "Show Whitespace". This can cause all sorts of strange side-effects as you have witnessed.
The best approach is to manually type out the thumbprint into Visual Studio which will ensure no funny characters have slipped in. This can be a bit of a pain but the only way of guaranteeing you are actually comparing like for like.
I need to pass secure information to an executable in my application. In other words I have the line:
Process.Start("someExecutable.exe","MyUsername, myPassword");
I want to prevent people from seeing those parameters. (The username and password are specified by the user at run time so I do not have to worry about those parameters).
Now a problem that I have now is: If someone replaces someExecutable.exe with their own program they will be able to see the credentials!
For future reference I refere to someExecutable.exe (program I am sending the credientials as arguments as ) A and I will refere to the executable created by this program as B
I will like to prevent that problem here are some solutions I have think of:
Compute the hash of A and check it before executing it.
static bool? VerifyThatExeIsReliable(string pathOfExe)
{
if (System.IO.File.Exists(pathOfExe) == false)
return null;
var bytes = System.IO.File.ReadAllBytes(pathOfExe);
using (SHA1Managed a = new SHA1Managed())
{
var hash = a.ComputeHash(bytes);
StringBuilder formatted = new StringBuilder(2 * hash.Length);
foreach (byte b in hash)
formatted.AppendFormat("{0:X2}", b);
var code = formatted.ToString();
if (code == "4835658749AF89A65C5F4835658749AF89A65C5F")
return true;
}
return false;
}
the problem with this approach is that the hash 4835658749AF89A65C5F4835658749AF89A65C5F will be stored in the executable A and if someone opens this program with a hex editor he is going to be able to find the hash and modify it. In other words they will calculate the sha1 hash of the program they write and place that hash instead of 4835658749AF89A65C5F4835658749AF89A65C5F
Use a the file Watcher class to detect when the file has been modified. If my program is not running I will not be able to detect this
make sure that the user is not able to see the command line arguments passed to that executable: See command line arguments being passed to a program
To solve the problems with option #1, Use asymmetric encryption on the hash, that way your program (and the user) will only be able to decrypt the hash, not encrypt a different one. Of course if they can edit compiled C# code then you can't stop them from altering it to not decrypt the hash, but that requires a lot more time and expertise.
To solve problem #2, store a hash of executable A in your program, and verify that executable A matches the hash before starting it.
As for #3, as far as I am aware there is no way to resolve the problem. However, if you are able to modify the target program you could send the username and password via an encrypted network socket, for example.
Note also that it is possible to reverse engineer .NET applications, and that you should possibly consider running some kind of obfuscation tool on your executable if security is important to you. Ultimately its not about making the program 100% tamper-proof, because that is impossible. Its about making it not worth the bother to anyone who would have a reason to do so.
I'm reading the value of a registry key:
Microsoft.Win32.RegistryKey key;
key = *someLongPathHere*;
and displaying the value to a label:
string a = (string)key.GetValue("");//a default value
label1.Text = a;
It displays:
{F241C880-6982-4CE5-8CF7-7085BA96DA5A}
which is mostly correct, except for the first underscore, which exists in the original value:
{_F241C880-6982-4CE5-8CF7-7085BA96DA5A}
Why does it happen? i.e the missing underscore?
Also, after reading the key, do I have to close the key or anything? How can I do it?
It's easy enough to test whether or not there is a systematic problem with string values containing underscores. You can simply create such a value in the registry editor and then read it into your C# program with GetValue(). When you do so you'll discover that the C# registry code doesn't lose underscores. So, there must be some other explanation for your problem.
My best guess is that your label component does not display the underscore. I'm not very familiar with the C# UI frameworks but that seems plausible. Try looking at the value of a under the debugger rather than in a label caption on your UI.
The other thing that comes to mind is that you have registry redirection because you have an x86 process running on x64, and your key is under a redirected key, HKLM\Software, for example. Perhaps if you look under the Wow6432Node you will see the underscore discrepancy.
As for managing the life of the key, the key is backed by an unmanged resource. Namely a Windows HKEY. The RegistryKey class implements IDisposable and so you should wrap your keys in a using statement.