2010-11-22 4 views
3

ダンプファイルを開くときに、Windowsクラッシュダンプを調査していて、Visual Studioデバッガに「不正な命令0xC000001D」が表示されます。私は手動でデバッガのメモリウィンドウ内のいくつかの無効な値を持つ関数のコードが、クラッシュダンプを上書きすることにより、デバッガで上記の例を作成したWindows XPでは、通常のC++プログラムでコードセグメントを上書きすることはできますか?

void g(int x) { 
00401E80 push  ebp 
00401E81 mov   ebp,esp 
    if(x > 20) { 
00401E83 cmp   dword ptr [x],14h 
00401E87 jle   g+14h (401E94h) 
     x *= 4; 
>00401E89 db   0fh // illegal instruction here 
00401E8A db   0fh 
00401E8B xadd  eax,esp 
00401E8E add   cl,byte ptr [ecx+9EB0845h] 
     x += 42; 
00401E94 mov   ecx,dword ptr [x] 
... 

:それは、このエラーは、次の例に沿って分解をそれぞれ示すコード位置私は調査で同じdb 0fhのエントリを示していますが、明らかに無効な命令を示しています。このコードは、無効な命令より前の命令がすべて有効でソースコードと一致しているという点で、ダンプファイルに表示されるコードと似ています。台無しのコードセグメントにする(Windows XP上のVisual C++ 2005) - メモリページアクセス制限の周り混乱しないこと -

は今質問は、それがすべてで正常にコンパイルされたC++プログラム内で可能であるですプロセス?

コードから上記の例の関数アドレスに書き込もうとすると、コード違反のメモリページが書き込み保護されているように見えるアクセス違反が常に発生します。

{ 
    void* fnAddr = &g; // non-portable but OK in VC++ 
    unsigned int x = 0xDEADBEEF; 
    // Simulate memory corruption: Try to write something to the code segment: 
    memcpy((char*)fnAddr+4, &x, sizeof(x)); // generated 0xC0000005 Access Violation 
    g(42); // call messed up function - never get here 
} 

実際にコードセグメント内の何かを誤って上書きする可能性のある状況がありますか?

私は、実際のプログラムは多くの仮想関数、いくつかのメンバ関数ポインタなどを含んでいて、問題は悲しいかなか再現できないと付け加えるべきです。さもないと。 - しかし、ダンプファイルはコードセグメントに不正な命令を表示するので、コードセグメントを混乱させる可能性は考えられませんでした。

答えて

3

いいえ、コードを含むメモリページは書き込み禁止です。この種の損傷は、プロセスの初期化時にのみ発生する可能性があります。しかし、より多くの可能性のあるソースはソフトRAMエラーです。 RAMテストプログラムを実行するようお客様に依頼してください。ファイルの破損を考慮すると、エラーは繰り返し可能です。

+0

ファイルが問題ないようです。 RAMエラーは起こりそうもないようですが、テストします。たぶんダンプファイルは、私が私にそれを見せていると思うものを私に見せてくれないでしょう。 –

0

はい、アプリケーションによってコードセグメントの一部が書き込み可能になった場合(たとえば、Javaバイトコードがネイティブコードに変換されるJava JITなど)。

+1

答えは "いいえ"で始まっているはずです。問題は次のとおりです。*通常はコンパイルされたC++プログラムでは可能です - プロセスのコードセグメントを混乱させるようなメモリページのアクセス制限がありませんか? * –

0

デフォルトでは.textセクションのアクセス権はRXです。 Howererの場合、VirtualProtectを使用すると、これらのメモリページの書き込み剛性を得ることができます。

code:00401000 55        push ebp 
code:00401001 89 E5        mov  ebp, esp 
code:00401003 81 7D 08 14 00 00+    cmp  dword ptr [ebp+8], 14h 
code:0040100A 7E 0B        jle  short loc_401017 
code:0040100A     ; --------------------------------------------------------------------------- 
code:0040100C 0F        db 0Fh // here should be x += 10.5; ?? 
code:0040100D 0F        db 0Fh 
code:0040100E 0F        db 0Fh 
code:0040100F     ; --------------------------------------------------------------------------- 
code:0040100F C1 E0 02       shl  eax, 2 ; //x *= 4 
code:00401012 
code:00401012     loc_401012: 
code:00401012 89 45 08       mov  [ebp+8], eax // save x 
code:00401015 EB 09        jmp  short near ptr unk_401020 
code:00401017     ; --------------------------------------------------------------------------- 
code:00401017 
code:00401017     loc_401017:        ; CODE XREF: code:0040100Aj 
code:00401017 8B 4D 08       mov  ecx, [ebp+8] 

私はオペコードを推測した場合、その後、欠け部分は、EAXに10.5を追加するものではありませんする必要があります。しかし、私はこれがコードする必要がありますと仮定

。これを見てみましょうかなり可能。好奇心を作るためにあなたが試すことができ、それ

if (x > 20){ 
     x *= 4; 
     x += 40; 
}; 

あなたもそのASMのリストと一緒に全体g(int)機能を投稿することができますか? (可能であれば、私の例のようにバイナリのopcode値で)。

+0

ruslik - ここで紹介したオペコードは、私がデバッガのメモリビューでメモリを上書きして作成したものです。この記事の執筆時点では、元のダンプリスティングにアクセスできませんでしたので、私はテストプログラムを "手動で"メモリを混乱させて使用しました。 –

1

難しい原因は、ローカル変数(文字列など)がオーバーフローし、スタックフレームを上書きしたことが原因です。サブルーチンが終了すると、スタックからの戻りアドレスがポップアップし、そこで見つかった命令を実行し始めます。これは、バッファオーバーフロー攻撃で悪用されるメカニズムです。

+0

スタックオーバーフローはコードセクションを変更できません。そしてその関数に無効なオペコードがあります。 – ruslik

+1

x86は可変長命令を使用し、関数間にはパディングがあります。コードセグメントへのポインタが有効な命令を指すことは想定できません。 – MSalters

+0

上記の例のように、有効なアドレスになっているmem_addr(上記の例では00401E89、若干の0061FF ..)は、すべてのasm命令* faulty命令の* prior *が有効でした正確なソースコードの実際のオペコードは何ですか? –

関連する問題