I'm trying to keep some strings safe in memory and Installed the SecureString Nuget package in a UWP targeting 10240. Using it is pretty easy:
SecureString secureStr = new SecureString();
for (int i = 0; i < someString.Length; i++)
{
secureStr.AppendChar(someString[i]);
}
secureStr.MakeReadOnly();
But in order to access the content I have to use:
IntPtr stringPointer = Marshal.SecureStringToBSTR(secureStringObj);
string normalString = Marshal.PtrToStringBSTR(stringPointer);
Marshal.ZeroFreeBSTR(stringPointer);
But in UWP there is not such method in the Marshal class SecureStringToBSTR any other ways to read the content of a SecureString?
Thanks!
You should be able to use the SecureStringMarshal class to get a pointer, and then the regular Marshal.PtrToStringXXXX methods to read it as a string etc.
I am trying to use the python c-api from a c# project via dll import.
I am getting an ModuleNotFoundError when importing some modules, which I thought are builtin.
(Note: I compiled python myself)
I am a bit stuck right now, but my hope is to get some extra information when calling PyErr_Print() in the code below.
Code:
IntPtr modulePtr = NativeInterface.PyImport_ExecCodeModuleEx(moduleName,compiledModule, path);
if (modulePtr == IntPtr.Zero)
{
NativeInterface.PyErr_Print();
PythonException exception = PythonException.Query();
throw exception;
}
The docs for PyErr_Print state that it will populate sys.stderr with some error information.
What would be the easiest way to read this variable from my c# application?
This answer gives C code because I understand C and not C#, but I think it should be pretty transferable.
By default sys.stderr writes to some console somewhere and so you can't meaningfully try to read from it. However, it's perfectly possible to replace it to redirect the output. Two sensible options include writing to a file, and writing to a StringIO object that can later be queried.
The C code to run is basically equivalent to:
import sys
from io import StringIO # Python 3
sys.stderr = StringIO()
or in C:
int setup_stderr() {
PyObject *io = NULL, *stringio = NULL, *stringioinstance = NULL;
int success = 0;
io = PyImport_ImportModule("io");
if (!io) goto done;
stringio = PyObject_GetAttrString(io,"StringIO");
if (!stringio) goto done;
stringioinstance = PyObject_CallFunctionObjArgs(stringio,NULL);
if (!stringioinstance) goto done;
if (PySys_SetObject("stderr",stringioinstance)==-1) goto done;
success = 1;
done:
Py_XDECREF(stringioinstance);
Py_XDECREF(stringio);
Py_XDECREF(io);
return success;
}
You run this once at the start of your program.
To query the contents of sys.stderr you'd then do the equivalent of:
value = sys.stderr.getvalue()
encoded_value = value.encode() # or you could just handle the unicode output
In C:
char* get_stderr_text() {
PyObject* stderr = PySys_GetObject("stderr"); // borrowed reference
PyObject *value = NULL, *encoded = NULL;
char* result = NULL;
char* temp_result = NULL;
Py_ssize_t size = 0;
value = PyObject_CallMethod(stderr,"getvalue",NULL);
if (!value) goto done;
// ideally should get the preferred encoding
encoded = PyUnicode_AsEncodedString(value,"utf-8","strict");
if (!encoded) goto done;
if (PyBytes_AsStringAndSize(encoded,&temp_result,&size) == -1) goto done;
size += 1;
// copy so we own the memory
result = malloc(sizeof(char)*size);
for (int i = 0; i<size; ++i) {
result[i] = temp_result[i];
}
done:
Py_XDECREF(encoded);
Py_XDECREF(value);
return result;
}
There's a bit of effort spent copying the string. You might consider working directly with unicode and using PyUnicode_AsUCS4Copy.
You probably then want to look at clearing the string after you've written it, just done by replacing sys.stderr with a fresh StringIO object.
I could not find a way to acces sys.stderr via C-Api. But I realized that I can run python scripts via the c-api (See PyRun_String in the docs).
So I am debugging now by writing sys.path to a textfile.
import sys
file = open('log.txt','w')
for path in sys.path:
file.write(i+'\n')
I have an application that needs to have the user create a passphrase. As such, there are various rules that need to be tested against the passphrase as it's being entered.
These rules are pretty typical-- the value must be a certain length, have one upper, one lower, include some special characters, etc.
However, since this is a WPF application using a PasswordBox control, and the resulting value is very sensitive, how can I setup a complexity comparison system that dynamically checks the passphrase as the user is typing?
To be clear, I have a list of all requirements in a text label below the passphrase creation PasswordBox element. As the user types, a validator shows which requirements are met and which ones are still needed. I also have an entropy calculator which give a typical "OK, Good, Strong, Very Strong" indicator once requirements are met. This is why I need to find a way to securely validate the value as the user is typing.
How can I accomplish this without emitting insecure .Net strings?
You can subscribe to PasswordChanged but don't use Password property if you care about securely storing your sensetive value. Instead, do this:
private void OnPasswordChanged(object sender, RoutedEventArgs e) {
using (var pwd = ((PasswordBox) sender).SecurePassword) {
int length = pwd.Length;
if (length == 0) {
// string empty, do something
return;
}
bool hasSpecial = false;
bool hasUpper = false;
bool hasLower = false;
bool hasDigit = false;
// etc
// allocate unmanaged memory and copy string there
IntPtr ptr = Marshal.SecureStringToBSTR(pwd);
try {
// each char in that string is 2 bytes, not one (it's UTF-16 string)
for (int i = 0; i < length * 2; i += 2) {
// so use ReadInt16 and convert resulting "short" to char
var ch = Convert.ToChar(Marshal.ReadInt16(ptr + i));
// run your checks
hasSpecial |= IsSpecialChar(ch);
hasUpper |= Char.IsUpper(ch);
hasLower |= Char.IsLower(ch);
hasDigit |= Char.IsDigit(ch);
}
}
finally {
// don't forget to zero memory to remove password from it
Marshal.ZeroFreeBSTR(ptr);
}
}
}
That way you never build .NET string during your validation, and every trace of password is cleared from memory when you finish.
In proxy.exe I am creating a secure string the following way:
public SecureString GetSecureEncryptionKey()
{
string strPassword = "8charPwd";
SecureString secureStr = new SecureString();
if (strPassword.Length > 0)
{
foreach (var c in strPassword.ToCharArray()) secureStr.AppendChar(c);
}
return secureStr;
}
Then in main.exe I am decrypting it using this function:
public string convertToUNSecureString(SecureString secstrPassword)
{
IntPtr unmanagedString = IntPtr.Zero;
try
{
unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(secstrPassword);
return Marshal.PtrToStringUni(unmanagedString);
}
finally
{
Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
}
}
The issue is that the returned string is empty, unless I encrypt the initial string within main.exe, then the returned decrypted string is indeed "8charPwd". Why is this happening? Is SecureString encryption bound to the executable?
The purpose of SecureString is to keep strings safety inside your application memory(keep the string secure in RAM)
SecureString object is not a serialize-able.
You cannot transfer an instance between applications.
SecureString encrypt the string by using RtlEncryptMemory (WINAPI) with the flag:"0" (only the same process can decrypt the content). RtlEncryptMemory API
if you don't want to expose the password(at any time) in the RAM, you can create a simple obfuscation(or encryption) logic, and then transfer the content.
Edit:
I found 2 old questions that might be helpful for you:
When would I need a SecureString in .NET?
Wcf-Authentication and Logging
I would like to read some articles or books about how works windows clipboard inside, but I can't find at least one article that was deeper than standard API references or examples of using .
I'm working with windows clipboard over standart winapi and I obtain some strange results.
Case 1: I write to clipboard some unicode string and remember address of that string. Then I close clipboard, and repeat following procedure:
open clipboard, get address of my unicode string, close clipboard.
I think that I must receive same addresses of clipboard content but it isn't. Why?
//1.) Copying string to clipboard
if (WinAPI.OpenClipboard(owner))
{
WinAPI.EmptyClipboard();
IntPtr exampleStringPtr = Marshal.StringToHGlobalUni("Example");
Console.WriteLine("setting address: {0}", exampleStringPtr.ToInt32());
WinAPI.SetClipboardData(WinAPI.CF_UNICODETEXT, exampleStringPtr);
WinAPI.CloseClipboard();
}
//2.) Getting string from clipboard
for (int i = 0; i < 100; i++ )
if (WinAPI.OpenClipboard(owner))
{
IntPtr exampleStringPtr = WinAPI.GetClipboardData(WinAPI.CF_UNICODETEXT);
Console.WriteLine("getting address: {0}", exampleStringPtr.ToInt32());
WinAPI.GlobalLock(exampleStringPtr);
var s = Marshal.PtrToStringUni(exampleStringPtr);
WinAPI.GlobalUnlock(exampleStringPtr);
WinAPI.CloseClipboard();
}
case 2: I write to clipboard some string, close clipboard, change string (in unmanaged memory) and again open clipboard and read this string. To my surprise, I obtain SAME string address and my UNCHANGED string.
//1.) Copying string to clipboard
if (WinAPI.OpenClipboard(owner))
{
WinAPI.EmptyClipboard();
IntPtr exampleStringPtr = Marshal.StringToHGlobalUni("Loooooooooooonng String Example");
Console.WriteLine("setting address: {0}", exampleStringPtr.ToInt32());
WinAPI.SetClipboardData(WinAPI.CF_UNICODETEXT, exampleStringPtr);
WinAPI.CloseClipboard();
//2.) Change string - replace first 10 characters on one any symbol
for (int i = 0; i < 10; i++)
{
Marshal.WriteByte(exampleStringPtr + i, 50);
}
//3.) Obtain string and make sure that string was changed
Console.WriteLine("changed string: {0}", Marshal.PtrToStringUni(exampleStringPtr));
}
//2.) Getting string from clipboard
for (int i = 0; i < 100; i++)
if (WinAPI.OpenClipboard(owner))
{
IntPtr exampleStringPtr = WinAPI.GetClipboardData(WinAPI.CF_UNICODETEXT);
Console.WriteLine("getting address: {0}", exampleStringPtr.ToInt32());
WinAPI.GlobalLock(exampleStringPtr);
var s = Marshal.PtrToStringUni(exampleStringPtr);
Console.WriteLine("obtained string: {0}", s);
WinAPI.CloseClipboard();
}
Now I'm thinking that clipboard copy all memory block in SetClipboardData to other memory and source block can be copied several times. I can't understand, why I can't free my unmanaged memory for string immediately after SetClipboardData execution?
I have many questions and I think that some literature will make it clear
UPDATE:
to Raymond Chen, Jonathan Potter, Eric Brown: thank's for your answers, but I edited my second test that it would be more correct and now it shows following:
I change source string BEFORE clipboard was closed and I may think it is valid operation and it removes answers that I make it after clipboard was closed. Then I get this string and results shows that is changed, then I get this string by invoking GetClipboardData and results shows that string was changed and pointer is same. Then I close clipboard open it again and read string again. What I obtain now? string address is same as address of source string but string is UNCHANGED. Here's this code:
//1.) Copying string to clipboard
if (WinAPI.OpenClipboard(owner))
{
WinAPI.EmptyClipboard();
IntPtr exampleStringPtr = Marshal.StringToHGlobalUni("Loooooooooooonng String Example");
Console.WriteLine("setting address: {0}", exampleStringPtr.ToInt32());
WinAPI.SetClipboardData(WinAPI.CF_UNICODETEXT, exampleStringPtr);
//2.) Change string while clipboard isn't closed - replace first 10 characters on one any symbol
for (int i = 0; i < 10; i++)
{
Marshal.WriteByte(exampleStringPtr + i, 50);
}
//3.) Obtain string and make sure that string was changed
Console.WriteLine("changed string: {0}", Marshal.PtrToStringUni(exampleStringPtr));
//4.) Get this string from clipboard and make sure that clipboard was changed
exampleStringPtr = WinAPI.GetClipboardData(WinAPI.CF_UNICODETEXT);
Console.WriteLine("getting address of changed string: {0}", exampleStringPtr.ToInt32());
var lockedPtr = WinAPI.GlobalLock(exampleStringPtr);
var s = Marshal.PtrToStringUni(exampleStringPtr);
WinAPI.GlobalUnlock(lockedPtr);
Console.WriteLine("obtained string: {0}", s);
WinAPI.CloseClipboard();
}
Console.WriteLine("\n-------Close and open clipboard------------------\n");
//5.) Getting string from clipboard
for (int i = 0; i < 100; i++)
if (WinAPI.OpenClipboard(owner))
{
IntPtr exampleStringPtr = WinAPI.GetClipboardData(WinAPI.CF_UNICODETEXT);
Console.WriteLine("getting address: {0}", exampleStringPtr.ToInt32());
var lockedPtr = WinAPI.GlobalLock(exampleStringPtr);
var s = Marshal.PtrToStringUni(lockedPtr);
WinAPI.GlobalUnlock(lockedPtr);
Console.WriteLine("obtained string: {0}", s);
WinAPI.CloseClipboard();
}
I run program, paused it and analyzied memory by WinDbg. Then I make screenshot of results and provide for it you. http://postimg.org/image/are6um7yv/ So, my tests and screenshot shows that:
1.) We have several copies of one source object in memory
2.) If I change source memory given to SetClipboardData invoke before closing clipboard, after opening it again clipboard restore source object even on source address.
Isn't is? Can anyone explain, whether these clauses are true or not?
UPDATE 2: Ok.. I was rewriting my third test on C++. it's here:
#include "stdafx.h"
#include "windows.h"
#include "conio.h"
int main()
{
HWND owner = GetConsoleWindow();
//1.) Copying string to clipboard
if (OpenClipboard(owner))
{
EmptyClipboard();
//WCHAR *str = L"Loooong string example";
char *str = "Loooooooong string Example";
int cch = strlen(str);
char* strptr = (char*)GlobalAlloc(GMEM_MOVEABLE, (cch + 1));
printf("setting (segment??) address: %X \n", strptr);
LPVOID lockedPtr = GlobalLock(strptr);
printf("locked setting address: %X \n", lockedPtr);
// copy
memcpy(lockedPtr, str, cch);
GlobalUnlock(strptr);
// set to clipboard
SetClipboardData(CF_TEXT, strptr);
//2.) Change string while clipboard isn't closed - replace first 10 characters on one any symbol
lockedPtr = GlobalLock(strptr);
for (int i = 0; i < 10; i++)
{
((char*)lockedPtr)[i] = 50;
}
GlobalUnlock(strptr);
//3.) Obtain string and make sure that string was changed
lockedPtr = GlobalLock(strptr);
printf("changed string: %s \n", lockedPtr);
GlobalUnlock(strptr);
//4.) Get this string from clipboard and make sure that clipboard was changed
strptr = (char*)GetClipboardData(CF_TEXT);
printf("getting address: %X \n", strptr);
lockedPtr = GlobalLock(strptr);
printf("locked getting address: %X \n", lockedPtr);
printf("obtained string: %s \n", (char*)lockedPtr );
GlobalUnlock(strptr);
CloseClipboard();
}
printf("\n-------Close and open clipboard------------------\n");
//5.) Getting string from clipboard
for (int i = 0; i < 10; i++)
{
//Sleep(1000);
if (OpenClipboard(owner))
{
HANDLE exampleStringPtr = GetClipboardData(CF_TEXT);
printf("getting address: %X \n", exampleStringPtr);
char* lockedPtr = (char*)GlobalLock(exampleStringPtr);
printf("locked getting address: %X \n", lockedPtr);
printf("obtained string: %s \n", lockedPtr);
GlobalUnlock(exampleStringPtr);
CloseClipboard();
}
}
getch();
return 0;
}
Really, now when I invoke GetClipboardData then I obtain the same pointer to the data all the time. But sometimes it was different from locked pointer of first string that I putted to the clipboard.
But although I'm writing this test on C++, I still have same effect I was writeing early.
If I change source memory block after invoking SetClipboardData and then try to invoke GetClipboardData, I obtain my changed memory block. But when I close this clipboard and then open it again, my changed memory block was overriten with some info, I don't know, and when I invoke GetClipboardData, that memory block was restored to initial state as if I didn't change it.
From where clipboard "knows" how to restore this block if it hasn't its copies and I changed source block?
I recorded little screencast that shows in what moment memory restored http://screencast.com/t/5t3wc9LS
The docs for SetClipboardData() say quite clearly that it does not copy the data you provide - instead, the clipboard owns the data handle and although you can still read from it until the clipboard is closed, you must not write to or free the data once the SetClipboardData() call has succeeded.
Once you've closed the clipboard you no longer own the clipboard and the data object is not safe to use at all, even for reading, as another process may have changed the clipboard contents. Your tests at modifying the data after closing the clipboard worked by luck, not because they are supposed to.
If SetClipboardData succeeds, the system owns the object identified by
the hMem parameter. The application may not write to or free the data
once ownership has been transferred to the system, but it can lock and
read from the data until the CloseClipboard function is called. (The
memory must be unlocked before the Clipboard is closed.)
Edit: Because you seem to have trouble with the concept of resource ownership and undefined behaviour, maybe this analogy will help.
// allocate 1 byte of memory
char* ptr = malloc(sizeof(char));
// set the byte to the letter A
*ptr = 'A';
// free the memory
free(ptr);
// set the byte to B
*ptr = 'B';
// verify that the byte is set to B
printf("byte contains %c\n", *ptr);
// allocate another byte of memory
char* ptr2 = malloc(sizeof(char));
// are they the same byte? maybe
printf("byte contains %c - first was %lx, second is %lx\n", *ptr2, ptr, ptr2);
I hope you will see that this code is completely wrong. We allocate memory, write to it, free it, and then after that, we write to it and read from it again. And yet if you compile and run this code, there's a good chance it will work. There's also a good chance that the second allocation will return the same address as the first allocation. What's going on?
This is called undefined behaviour. The language doesn't define what happens in a situation like this. When you free memory, you no longer own it, and you must not write to it nor read from it. If it works, or appears to work, it's a coincidence, nothing more. There is no guarantee it will always work. There is no point continually performing tests to try to prove that somehow it does work - nothing alters the fact that the behaviour is undefined. It might work, it might not. Don't do it.
SetClipboardData copies the data in the given global handle. Once the clipboard is closed, the global handle should be freed (and not before). GetClipboardData returns the (internal) memory handle; you should treat this handle as a read-only buffer.