web-dev-qa-db-ja.com

システムメモリダンプはどのように機能しますか?

そのため、システムでメモリダンプを実行するペンテストツールは非常に多くあります。それらはどのように正確に機能しますか?正確には何が起こりますか?

10
Legolas

システム全体または単一の実行可能ファイルの コアダンプ は、そのプロセスのメモリの内容全体、またはシステムの場合はすべてのメモリがファイルに書き込まれます。そのようなダンプには多くのデータが含まれる可能性があります-これは、現在実行中のgvimのメモリ空間の省略形です。

pmap 19133
19133:   gvim fsstate.py
0000000000400000   2184K r-x--  /usr/bin/gvim    ; program code
0000000000821000    100K rw---  /usr/bin/gvim    ; program code again
000000000083a000     52K rw---    [ anon ]
0000000000a39000     56K rw---  /usr/bin/gvim    ; more program code
0000000002469000   3592K rw---    [ anon ]
0000003d53c00000     16K r-x--  /lib64/libuuid.so.1.3.0 ; shared object
0000003d53c04000   2044K -----  /lib64/libuuid.so.1.3.0
0000003d53e03000      4K rw---  /lib64/libuuid.so.1.3.0
0000003d55000000     28K r-x--  /usr/lib64/libSM.so.6.0.1
0000003d55007000   2044K -----  /usr/lib64/libSM.so.6.0.1
...
00007f46d66c7000     20K r----  /usr/share/locale/en_GB/LC_MESSAGES/gdk-pixbuf.mo
00007f46d66cc000      4K r----  /usr/share/locale/en_GB/LC_MESSAGES/libc.mo
00007f46d66cd000     56K r----  /usr/share/locale/en_GB/LC_MESSAGES/gtk20.mo
00007f46d66db000     28K r--s-  /usr/lib64/gconv/gconv-modules.cache
00007f46d66e5000      4K rw---    [ anon ]
00007fffc9ed9000    132K rw---    [ stack ]    ; stack!
00007fffc9f9b000      4K r-x--    [ anon ]
ffffffffff600000      4K r-x--    [ anon ]

そのアドレス空間からは、共有オブジェクトはダンプされませんが、スタック、ヒープなど、その他はすべてダンプされます。アドレスは、共有オブジェクトの特定のバージョンに関連しており、ASLRを使用すると、プロセス間で整列されない可能性があります。カーネルダンプは、小さなダンプからすべてのものまで、さまざまな量の情報を含むように構成できます。

これは何を教えてくれますか?ダンプされたときのシステムまたはプログラムの正確な状態-スタック上にあるもの(そしておそらくそれがどの関数にあるか)。ほとんどのコアダンプには、ダンプ時にプロセッサのレジスタに何があるかなど、他の有用な情報も含まれています。

何が起こっているのかをどのように解決するかに関して、x86(x64)のEIPまたはRIPは、プロセスが実行していたメモリアドレスを正確に示します。 rbpまたはebpは、関数が動作しているスタックの場所を教えてくれます。そこではローカル変数が見つかると思います。また、コアダンプで行われたすべてのシステムコールとその引数を検索することもできます。

これらのすべては、その特定の時点でのプロセスで何が起こっているかを伝えるのに役立ちます。ペンをテストするための単なるツールではありません。特に、デバッガーの実行が困難または不可能な場合、コアダンプをデバッグアプリケーションの形式として分析することができます。たとえば、カーネルコアダンプを分析して、デバッガーを接続して再試行するのではなく、カーネルがクラッシュした理由(パニックになったときはどうなったのか)を調べます。これにより、他の人が分析のためにダンプを送信することもできます。

これはペンのテストにどのように役立ちますか?同じようにデバッグはペンのテストに役立ちます。メモリに何がロードされているか、現在の状態は何かを確認できます。ダンプをとったときにプロセスが何をしているかを調べることができ、おそらく最も重要なことには、メモリ内の実行可能ファイル(ヒープ、スタックなど)に格納されているデータも、メモリにプレーンテキストとして格納されているパスワードを含めて、コアダンプに含まれます。 。

分析ツールは何をしますか?潜在的なエクスプロイト(またはデバッグ後の場合はエラー)を示すパターンと構造を探します。その完全な説明はおそらくこのボックスの範囲を超えています-メモリダンプを分析するためのテクニックを専門に扱った本はたくさんあります。これの多くは、システムとアーキテクチャにも依存しています。 Windows x86のテクニックは、Linux on MIPSのテクニックとは異なります。

エラーを示す可能性があるものの例として、AviDが実際に理解できる例を次に示します。

Push    rbp
mov rbp, rsp
sub rsp, 32
mov QWORD PTR [rbp-24], rdi  ; this is a char* argument stored on stack
mov rdx, QWORD PTR [rbp-24]  ; and this is a pointer loading it into a register
lea rax, [rbp-16]            ; this is only 8 bytes further down
mov rcx, QWORD PTR [rdx]     ; load contents of rdx into rcx
mov QWORD PTR [rax], rcx     ; put those 8 bytes to rbp-16
mov rcx, QWORD PTR [rdx+8]   ; load next 8 butes
mov QWORD PTR [rax+8], rcx   ; write to rbp-8   
mov rcx, QWORD PTR [rdx+16]
mov QWORD PTR [rax+16], rcx  ; write to rbp     
mov rcx, QWORD PTR [rdx+24]
mov QWORD PTR [rax+24], rcx  ; write to rbp+8   
mov rcx, QWORD PTR [rdx+32]
mov QWORD PTR [rax+32], rcx  ; write to rbp+16  
mov rcx, QWORD PTR [rdx+40]
mov QWORD PTR [rax+40], rcx  ; write to rbp+24  
mov rcx, QWORD PTR [rdx+48]
mov QWORD PTR [rax+48], rcx  ; write to rbp+32
mov rdx, QWORD PTR [rdx+56]
mov QWORD PTR [rax+56], rdx  ; write to rbp+40
lea rax, [rbp-16]

ご覧のとおり、この関数がスタック上でローカル変数に使用できる最初のスペースはrbp-16以下。その上で、スタックフレームにデータの山全体が含まれているので、プログラムがクラッシュする可能性があります。ただし、このコードは悪用の可能性を示している可能性があります。クラッシュダンプでそのようなパターンを探すことは、それらを有用にするものであり、さらに、この場合のripは、問題の原因となった命令を指し示すため、どのメモリアクセスが問題を引き起こしたかを正確に示します(理論的には) 。

ご参考までに、問題のコードは、境界のないバッファーからはるかに小さなターゲットスペースへのmemcpyでした。 memcpyへの関数呼び出しが最適化されました。

12
user2213

まず第一に、セキュリティにおけるメモリダンプの2つの主要なユーザー-フォレンジックと悪用を書く人です。ペンテスター、それほどではない-もちろんそれはペンテストに依存する;)

メモリ作業をダンプする通常の方法は、メモリ疑似デバイスを開いて、すべての内容をファイルに読み込むことです。

たとえば、ウィンドウでddを使用すると、dd if=\\.\Device\PhysicalMemory of=memory.bin bs=4096(win 2003より前、その後にはカーネルドライバーが必要です)

同じことがLinuxにも当てはまります。 dd if=/dev/mem of=/home/john/mem.bin bs=1024

もちろんこれが最も簡単な方法です。メモリを取得する他の方法は、Ninefingersが言及するクラッシュダンプ、LiveKdダンプを使用すること、VMについて話している場合はハイパーバイザーを介してメモリを取得する、存在する場合は休止ファイルを取得する、またはファイアウェアまたは別のメモリを介してメモリを取得するDMAインターフェース。もちろん、コールドブート攻撃もあります。

ファイルにメモリを持たせることで、目的に応じてさまざまなことができます。一般的なのは、文字列を検索することです。パスワードトークン、秘密キー、その他は、最も簡単なものです。

それ以上のことをしたい場合は、通常、さらに多くの作業が必要ですが、商用ツールまたはオープンソースツールを使用してさまざまな度合いで自動化されます。主なアイデアは、ダンプ内の物理メモリがページに分散されるということです。それを理解するには、ページテーブルをヒューリスティック検索で見つけ、メモリの論理ビューを再構築してみます。それが終わったら、他の検索を実行して、さまざまな実行中のプロセス、開いているファイル、ネットワーク接続などの構造を見つけることができます。これは、実際の目標に依存します。

8
john

全体のメモリと特定の領域など、違いがあるため、どのツールを一覧表示すると役立ちます。私が定期的に使用する、メモリをダンプする攻撃ツールは考えられません。

しかし、単純に、メモリのダンプを取ることで、アプリケーションコードだけでなく、変数値も確認できます。

メモリは、通常の使用でメモリページがディスクにスワップされる方法と同様に、ディスクにコピーされるか、ツールがメモリを直接読み取ります。

0
Rory Alsop

Windowsを使用している場合は、Sysinternals SuiteのProcess Explorerを使用してください。プロセスを右クリックして、そのプロセスのメモリをダンプすることを選択します。

http://technet.Microsoft.com/en-us/sysinternals/bb89665

0
Daniel Miessler