どのように増加していメモリセイ?
-
22-08-2019 - |
質問
ができる"ふく"文字列のイン?を説明しましょう:
皆様にお伝えしたくて書き込みアプリケーションに対するには、DLLを唱えます。で読み込んで暗号化されたファイルをXML DOM情報を使用すが、その後リリースは、DOM.
この暗号化XMLは未だに座って、メモリ、DLL、およびそのために脆弱な検討します。ってるつもりはありませんに無理を保護することは、ユーザーを他のDLLが、このような基本ステップを防止ユーザーの名前から座ってメモリーます。しかし、思えるのではないかと思ってい簡単に拭き取り、メモリからの参照です。さんトラバースマド(TNativeXML級べての文字列インスタンスは、そのような"○"、それでは実際に割り当て、新たな文字列へのポインタDOMを参照しての古い文字列に座ってメモリを待って再分配?があるので、必ず私が殺しにや独自のコピー?
やはりD2007を教えても拭き取り時点で全額が未使用設定メモリからのヒープ?このリリースは、DOMをお伝えで乾拭きして下さい。
やんか次回のこのタスクをお忘れですからプライベートビーチがありゃ.
解決
私は、ユーザーがDLLを使用して、プロセスのメモリを読み取ることができる場合は、同じユーザーが任意の時点で実行を停止することができますので、それは、と悩ま価値があるとは思いません。まだユーザーに暗号化されていないデータへのフルアクセスを与える拭いているメモリの前に実行を停止します。
IMO十分に興味を持って、あなたが記述するものを行うことができるすべてのユーザーが真剣にメモリを拭くあなたのDLLによって不便されることはありません。
他のヒント
この約2つの一般的なポイント:
まず、これは、これらの分野の一つである「あなたが聞いている場合、あなたはおそらくこれを行うべきではありません。」その間違った方法を取ることはしないでください。私はあなたのプログラミングのスキルへの無礼を意味しません。それは、安全な、暗号的に強いソフトウェアを書くことは、あなたがのエキスパートだかそうでないのいずれか何かであることだけです。 「空手の少しを」知っているのと同じように非常にはるかに多くの危険は全く空手を知らないよりもあります。利用できる専門的なサポートを持って、Delphiで安全なソフトウェアを書くためのサードパーティのツールがいくつかあります。私は強く、Windowsの暗号化サービス、暗号の数学的基礎、代わりにしようとのそれらを使用するサイドチャネル攻撃を破った経験の深い知識がなくても誰でも励ます「自分自身をロールバックします。」
WindowsのAPIは役に立つ機能の数を持っている、そのような<のhref = "http://msdn.microsoft.com/en-us/library/aa380262(VS.85)のように:あなたの特定の質問に答えるために.aspxの」REL = "nofollowをnoreferrer"> CryptProtectMemory を。あなたのメモリを暗号化しますが、システムの他の場所に穴を持っている、またはサイドチャネルを公開する場合は、これは誤った安心感をもたらすでしょう。それはあなたのドアにロックをかけるが、開いているウィンドウを残すようにすることができます。
どのようにこのようなものでしょうか?
procedure WipeString(const str: String);
var
i:Integer;
iSize:Integer;
pData:PChar;
begin
iSize := Length(str);
pData := PChar(str);
for i := 0 to 7 do
begin
ZeroMemory(pData, iSize);
FillMemory(pData, iSize, $FF); // 1111 1111
FillMemory(pData, iSize, $AA); // 1010 1010
FillMemory(pData, iSize, $55); // 0101 0101
ZeroMemory(pData, iSize);
end;
end;
のDLLは、割り当てられたメモリを所有していない、プロセスが行います。プロセスが終了したら、あなたの特定のプロセスによって割り当てられたメモリは、DLLの周りハング(それは別のプロセスで使用されているため)かどうか、破棄されます。
どのようにあなたの検証を行うためにSAXプロセッサの代わりに、XMLのDOMを使用して、ストリームにファイルを復号化し、それを解放する前に復号化されたストリームを上書きについてはどうですか?
、その後、あなたはそれが解放されているときにメモリを上書きすることを強制することができます。
通常、その挙動は野生のポインタを検出するために使用されるが、それはまた、どのようなご希望に使用することができます。
一方で、あなたはクレイグStuntzの書き込みを理解してください:。可能な限り、自分は、基礎となるオペレーティング・システムを使用して、この認証および承認のものを書いていない。
ところで:Hallvard VassbotnはFastMMについての素敵なブログを書きました: http://hallvards.blogspot.com/2007/ 05 /ユースフルfastmm-考える-donating.htmlする
よろしく、
のJeroen Pluimers
メッシーしかし、あなたはそれがGetMemはあなたにまたがる大規模なチャンクを割り当てるか解放された後、機密データで埋めヒープを持っている間、あなたが使用したヒープサイズのノートを作ることができる(例えば)200%その。そのチャンクの塗りつぶしを行うと、任意の断片化は、審査官に多くの使用であることがunlinkelyであるという仮定を作ります。 BRI
どのようにXMLでハッシュ値としてパスワードを維持について、あなたのXMLでハッシュされたパスワードを使用して、入力されたパスワードのハッシュを比較して検証します。
編集:あなたは、暗号化されたすべての機密データを保持し、最後の可能な瞬間でのみ復号化できます。
。charまたはバイトの配列ではなく文字列に復号化されたXMLをロードすることは可能でしょうか?そして、そこにはコピー・オン・ライトハンドリングないだろう、あなたは解放する前に、#0の持つメモリを埋め戻すことができるだろう?
Delphiは[1..x] CHARの伝統的なパック配列との互換性のためにここにいくつかのスマートなハンドリングを持っているとして、、文字列にcharの配列を割り当てる場合は注意が必要です。
また、あなたがShortStringはを使用することができます?
あなたが危険にさらされたパスワード、あなたのパッティングユーザーを保存するために、XML、でも暗号化を使用している場合。より良いアプローチではなく、パスワードのハッシュ値を格納することで、その後、入力されたパスワードに対してハッシュを比較します。このアプローチの利点は、さらにハッシュ値を知ることで、あなたはハッシュを作るパスワードを知らないということです。 (無効なパスワードの試行をカウントし、一定数の後にアカウントをロック)ブルートフォース識別子を追加すると、さらにセキュリティを強化します。
あなたは、文字列のハッシュを作成するために使用できるいくつかの方法があります。良い出発点は、私は信じている、ターボパワーのオープンソースプロジェクト「 LockBoxしばらくする」を見てだろうそれは一方向ハッシュキーを作成するためのいくつかの例があります。
編集
その一つの方法のヘルプ場合は、しかし、どのようにハッシュ値を知っていますか?あなたは本当に被害妄想ならば、あなただけが知っているだろうとprediticable何かにハッシュ値を変更することができます...と言う、特定のシード値を加えた日付を使用して乱数。あなたは比較のための出発点としてそれを使用することができますので、あなたは、あなたのXMLでハッシュのに十分なだけを格納することができます。擬似乱数発生器の良いところは、彼らが常に同じシードを与えられた「ランダム」番号の同じシリーズを生成することです。
注意機能として扱う文字列としてポインタを使用 FillChar
または ZeroMemory
拭きる文字列です。
- この両方の違い(文字列は共有;ばねじの方の現在の文字列)
- を引き起こすということが判明アクセス違反の場合は文字列を起こして一定であった読み取りデータが書いてあるページのアドレス;う書き込みはアクセス違反
procedure BurnString(var s: UnicodeString);
begin
{
If the string is actually constant (reference count of -1), then any attempt to burn it will be
an access violation; as the memory is sitting in a read-only data page.
But Delphi provides no supported way to get the reference count of a string.
It's also an issue if someone else is currently using the string (i.e. Reference Count > 1).
If the string were only referenced by the caller (with a reference count of 1), then
our function here, which received the string through a var reference would also have the string with
a reference count of one.
Either way, we can only burn the string if there's no other reference.
The use of UniqueString, while counter-intuitiave, is the best approach.
If you pass an unencrypted password to BurnString as a var parameter, and there were another reference,
the string would still contain the password on exit. You can argue that what's the point of making a *copy*
of a string only to burn the copy. Two things:
- if you're debugging it, the string you passed will now be burned (i.e. your local variable will be empty)
- most of the time the RefCount will be 1. When RefCount is one, UniqueString does nothing, so we *are* burning
the only string
}
if Length(s) > 0 then
begin
System.UniqueString(s); //ensure the passed in string has a reference count of one
ZeroMemory(Pointer(s), System.Length(s)*SizeOf(WideChar));
{
By not calling UniqueString, we only save on a memory allocation and wipe if RefCnt <> 1
It's an unsafe micro-optimization because we're using undocumented offsets to reference counts.
And i'm really uncomfortable using it because it really is undocumented.
It is absolutely a given that it won't change. And we'd have stopping using Delphi long before
it changes. But i just can't do it.
}
//if PLongInt(PByte(S) - 8)^ = 1 then //RefCnt=1
// ZeroMemory(Pointer(s), System.Length(s)*SizeOf(WideChar));
s := ''; //We want the callee to see their passed string come back as empty (even if it was shared with other variables)
end;
end;
一度、 UnicodeString
版を作成することができ AnsiString
や WideString
バージョン:
procedure BurnString(var s: AnsiString); overload;
begin
if Length(s) > 0 then
begin
System.UniqueString(s);
ZeroMemory(Pointer(s), System.Length(s)*SizeOf(AnsiChar));
//if PLongInt(PByte(S) - 8)^ = 1 then //RefCount=1
// ZeroMemory(Pointer(s), System.Length(s)*SizeOf(AnsiChar));
s := '';
end;
end;
procedure BurnString(var s: WideString);
begin
//WideStrings (i.e. COM BSTRs) are not reference counted, but they are modifiable
if Length(s) > 0 then
begin
ZeroMemory(Pointer(s), System.Length(s)*SizeOf(WideChar));
//if PLongInt(PByte(S) - 8)^ = 1 then //RefCount=1
// ZeroMemory(Pointer(s), System.Length(s)*SizeOf(AnsiChar));
s := '';
end;
end;