Let us go back to the simple Delphi VCL application created in Part 1 of this blog post, and update it. This time, we will be using ISecureString at our earliest convenience:
uses
// Delphi
System.StrUtils,
// Project
PASSWORD,
SecureString;procedure TForm1.Button1Click(Sender: TObject);
var
S: ISecureString;
begin
with TPasswordDlg.Create(Self) do
try
if ShowModal <> mrOk then
EXIT;
S := NewSecureString(Password.Text);
Password.Clear;
ShowMessage(ReverseString(S.Data));
finally
Free;
end;
end;
Now let us try Mark Russinovich’ excellent Strings again:
- Start your application
- Enter this password: MyStupidPass123, and then dismiss the dialog
- Open Task Manager (Ctrl+Shift+Esc)
- Right-click on: Project1.exe (32 bit)
- Click on: Create dump file
- Open command prompt in %temp%
- Assuming the dump file is named Project1.DMP, enter this:
strings "Project1.DMP" | findstr /i MyStupidPass123
Success! MyStupidPass123 is not to be found in memory.
Where to go from here
ISecureString and TSecureString are not complete. But they are a great starting point. You could, for example, encrypt the boxed string. But here are a few things to remember and look out for:
- Decrypting the boxed string will result in the Delphi RTL to create a new plain-text string, hereby introducing a new vulnerability because you now have a new copy of a plain-text string that is not zero’ed out. As a general rule, your code should work with ISecureString throughout your entire project — not string.
- When you’re encrypting the boxed string, then you will probably use symmetric encryption and your encryption key is somewhere in memory (or worse, a constant in your binary). While this will protect your application against amateurs, a hacker will find your encryption key.
- Obscuring your encryption key will slow your attacker down at best — not stop him.
Here is something else you can do. Compile your application with ASLR turned on. ASLR ensures that your application isn’t using a predictable address space in memory that malware could attack. Add this to your (.dpr or .dpk) project source file:
{$SETPEOPTFLAGS $140}
Final thoughts
As developers, we rely on the operating system to forbid processes from accessing each other’s allocated memory and hope for the best. We must trust the operating system for not giving it away to third parties. The operating system is our friend, because if the operating system is an enemy then we have bigger problems to worry about.
The bottom-line is that passwords in memory are no safer than what the operating system allows. If you’re super concerned about this, then my advice is…
- Encrypt your harddrive. For example: use TrueCrypt or VeraCrypt. This avoids memory leaks through hibernation (when the whole RAM is written to disk).
- Do not use personal computers. PCs are designed to run several processes (on the same CPU, sharing resources, including cache memory) which are hostile to each other. Use dedicated hardware that is designed for perfect peace and isolation.