The string in the managed code is a special type of object, which cannot be changed. when one of the methods in the string class or when performing operations (such as value assignment and concatenation), You must create a new String object in the memory, that is, allocate new space for the new object. This brings about two problems:
1: Is the original string still in memory?
2: How can we store confidential data (such as passwords) in the memory to ensure security?
Let's take a look at the first question:
Code
Publicclass Program
{
Staticvoid main (string [] ARGs)
{
Method1 (); // place a breakpoint here
Console. readkey ();
}
Staticvoid Method1 ()
{
String STR = "luminji ";
Console. writeline (STR );
}
}
Place a breakpoint at Method1 and let vs execute it here. In the real-time window, run the commands:. Load SOS. dll and! DSO, as follows:
Open the memory display window in debugging and go to 019db820 (! DSO ). As Method1 is not entered yet, the memory does not contain the string "luminji ". Then let the program run into the method. We can see that there is already "luminji" in the memory.
Then let the program continue running and exit Method1, and find that "luminji" remains in the memory.
This poses a problem. If a malicious person scans your memory, the confidential information stored in your program will be nowhere to escape. Fortunately, system. Security. securestring is provided in FCL. securestring indicates the text to be kept confidential and is encrypted during initialization.
Code
Publicclass Program
{
Static system. Security. securestring = new system. Security. securestring ();
Staticvoid main (string [] ARGs)
{
Method2 (); // place a breakpoint here
Console. readkey ();
}
Staticvoid method2 ()
{
Securestring. appendchar ('l ');
Securestring. appendchar ('U ');
Securestring. appendchar ('M ');
Securestring. appendchar ('I ');
Securestring. appendchar ('n ');
Securestring. appendchar ('J ');
Securestring. appendchar ('I ');
}
}
After entering method2, you can find that the corresponding string is no longer found. However, the problem arises, and the problem of saving the core data has been solved, but the text is always to be extracted and used. Will it be discovered if it is obtained. Yes, this problem cannot be avoided, but we can release the text once it is used up.
See the following code:
Code
Staticvoid method3 ()
{
Securestring. appendchar ('l ');
Securestring. appendchar ('U ');
Securestring. appendchar ('M ');
Securestring. appendchar ('I ');
Securestring. appendchar ('n ');
Securestring. appendchar ('J ');
Securestring. appendchar ('I ');
Intptr ADDR = marshal. securestringtobstr (securestring );
String temp = marshal. ptrtostringbstr (ADDR );
// Use the confidential text do something
/// ======== Start to clean up the memory
// Clear the memory value corresponding to the unmanaged code
Marshal. zerofreebstr (ADDR );
// Clear the memory value corresponding to the managed code (using the rewrite method)
Int id = getprocessid ();
Byte [] writebytes = encoding. Unicode. getbytes ("xxxxxx ");
Intptr = open (ID );
Unsafe
{
Fixed (char * c = temp)
{
Writememory (intptr) C, writebytes, writebytes. Length );
}
}
/// ======= The cleaning is complete
}
Check the code above:
Intptr ADDR = marshal. securestringtobstr (securestring );
String temp = marshal. ptrtostringbstr (ADDR );
The two lines of code indicate that the confidential text is obtained from securestring, and the temporary value is assigned to the string temp. There are two problems. The first line of actually called unmanaged code also stores a "luminji" in the memory ", the second line of code stores a "luminji" in the managed memory ". The release methods of these two texts are different. The former can be used:
Marshal. zerofreebstr (ADDR );
Release. The text in the managed memory can only be rewritten (as mentioned above, it is rewritten as meaningless "xxxxxx ").
The preceding Code involves the following methods:
Code
Publicstaticint getprocessid ()
{
PROCESS p = process. getcurrentprocess ();
Return P. ID;
}
Publicstatic intptr open (INT processid)
{
Intptr hprocess = intptr. zero;
Hprocess = processapihelper. OpenProcess (processaccessflags. All, false, processid );
If (hprocess = intptr. Zero)
Thrownew exception ("OpenProcess failed ");
Processinfo. hprocess = hprocess;
Processinfo. dwprocessid = processid;
Return hprocess;
}
Publicstaticint writememory (intptr addressbase, byte [] writebytes, int writelength)
{
Int reallywritelength = 0;
If (! Processapihelper. writeprocessmemory (processinfo. hprocess, addressbase, writebytes, writelength, out reallywritelength ))
{
// Throw new exception ();
}
Return reallywritelength;
}
[Structlayout (layoutkind. Sequential)]
Internalstruct process_information
{
Public intptr hprocess;
Public intptr hthread;
Publicint dwprocessid;
Publicint dwthreadid;
}
[Flags]
Enum processaccessflags: uint
{
All = 0x001f0fff,
Terminate = 0x00000001,
Createthread = 0x00000002,
Vmoperation = 0x00000008,
Vmread = 0x00000010,
Vmwrite = 0x00000020,
Duphandroid = 0x00000040,
Setinformation = 0x00000200,
Queryinformation = 0x00000400,
Synchronize = 0x00100000
}
Staticclass processapihelper
{
[Dllimport ("kernel32.dll")]
Publicstaticextern intptr OpenProcess (processaccessflags dwdesiredaccess, [financialas (unmanagedtype. bool)] bool binherithandle, int dwprocessid );
[Dllimport ("kernel32.dll", setlasterror = true)]
Publicstaticexternbool writeprocessmemory (intptr hprocess, intptr lpbaseaddress, byte [] lpbuffer, int nsize, outint lpnumberofbyteswritten );
[Dllimport ("kernel32.dll", setlasterror = true)]
Publicstaticexternbool readprocessmemory (
Intptr hprocess,
Intptr lpbaseaddress,
[Out] Byte [] lpbuffer,
Int dwsize,
Outuint lpnumberofbytesread
);
[Dllimport ("kernel32.dll", setlasterror = true)]
[Return: financialas (unmanagedtype. bool)]
Publicstaticexternbool closehandle (intptr hobject );
}
Summary:
1. Use system. Security. securestring to save confidential text;
2: After system. Security. securestring is released, use marshal. zerofreebstr to clear traces in the memory;
3: The hosted string can only be cleared using the overwrite memory;
For debugging unmanaged code with SOS. dll, view http://www.cnblogs.com/luminji/archive/2011/01/27/1946217.html