gdbを使ってメモリをチェックするのは混乱していますか?

gdbを使ってメモリをチェックするのは混乱していますか?

私はHacking、The Art of Exploitationを読み始め、メモリチェックに関するいくつかの点について混乱しました。

メインを分解すると、個別の組み立て説明書があるメモリ全体の出力が出ますよね?各命令は必ずしもメモリアドレスを1ずつ増やす必要はないので、最後に<main + 1>と<main + 3>を追加できます。だからコマンドはこのスクリーンショットプログラムの最初の20命令を表示します。各メッセージには何バイトの情報が含まれていますか?

今混乱しています。 ir eipを使用するとき、このレジスタの位置は0x8048384です(それでmainの最初の命令として保存されますか?)。スクリーンショット。隣の値が保存する値ですがここで知りたいのですが0x00fc45c7を保存しますが、上記の出力にはこの命令はありませんか?私はそれがプログラムの次のコマンドを含むメモリを指すべきだと思います。

今最大の混乱が来ます。 $ eipが保存されているメモリを観察し、同時に複数のセルを観察できます。このスクリーンショット。しかし、x / 2xを使用したスクリーンショットを見ると、メモリに2つの値が格納されていますが、どちらもサイズが4バイトであることがわかります。その後、x / 12を使用すると、突然0x8048384に4つの単語があり、他の4つの単語0x8048394がありますか?

使用する単位によっては、メモリアドレスに格納されている値がどのように異なるのか理解できないようです。また、各メモリアドレスには1バイトの情報のみを含めるべきだと考えました。

質問の説明が必要な場合は投稿してください。英語は私の母国語ではなく、私の説明が正しいかどうかわかりません。

事前に助けてくれてありがとう。

答え1

各メッセージには何バイトの情報が含まれていますか?

1バイトから複数バイトまでの命令push %ebpには固定長がありません。たとえば、コマンドの出力は objdump -d a.outコマンドの長さをより明確にします(コマンドが何であるかを示すため、便利です)。

08048400 <main>:
 8048400:       55                      push   %ebp
 8048401:       89 e5                   mov    %esp,%ebp
 8048403:       83 ec 08                sub    $0x8,%esp
 8048406:       90                      nop
 8048407:       c7 45 fc 00 00 00 00    movl   $0x0,0xfffffffc(%ebp)
 804840e:       89 f6                   mov    %esi,%esi
 8048410:       83 7d fc 09             cmpl   $0x9,0xfffffffc(%ebp)

今混乱しています。 ir eipを使用すると、このレジスタの位置を知ることができます。

(gdb) disassemble main
Dump of assembler code for function main:
0x8048400 <main>:       push   %ebp
0x8048401 <main+1>:     mov    %esp,%ebp
0x8048403 <main+3>:     sub    $0x8,%esp
0x8048406 <main+6>:     nop
0x8048407 <main+7>:     movl   $0x0,0xfffffffc(%ebp)
0x804840e <main+14>:    mov    %esi,%esi
0x8048410 <main+16>:    cmpl   $0x9,0xfffffffc(%ebp)
...
(gdb) i r eip
eip            0x8048406        0x8048406

私のバージョンでは、プログラムがeipプログラムを停止するコマンドを指していますnopb maingdb

$eip今最大の混乱が来ます。メモリがどこに保存されているかを確認できます。

(gdb) x/10b $eip
0x8048406 <main+6>:     0x90    0xc7    0x45    0xfc    0x00    0x00    0x00    0x00
0x804840e <main+14>:    0x89    0xf6

上記の出力を覚えてくださいobjdump

 8048406:       90                      nop
 8048407:       c7 45 fc 00 00 00 00    movl   $0x0,0xfffffffc(%ebp)
 804840e:       89 f6                   mov    %esi,%esi

10バイトダンプには、$eip90、c7 45 fc 00 00 00 00、89 f6など、次の3つの命令が表示されます。

使用する単位によっては、メモリアドレスに格納されている値がどのように異なるのか理解できないようです。また、各メモリアドレスには1バイトの情報のみを含めるべきだと考えました。

gdbさまざまな幅または論理単位で確認できます。x/3iたとえば、次の3つのコマンドを表示するとします。

(gdb) x/3i $eip
0x8048406 <main+6>:     nop
0x8048407 <main+7>:     movl   $0x0,0xfffffffc(%ebp)
0x804840e <main+14>:    mov    %esi,%esi

使用する幅の最良の選択は状況によって異なります。 8ビットシステムではバイトを確認する必要があります。 64ビットシステムのメモリアドレスがgジャンボか8バイトかを確認する必要があります。選択範囲の幅を変更すると、表示されるgdb数字が変わる可能性があります。幅が異なるとビットパターンが変わり、数字も変わることがあるからです。さらに、CPUのエンディアンは状況を複雑にすることができます。

考慮する:

#include <stdio.h>
char *pointer = "test";
int main(void) {
        printf("%s\n", pointer);
}

チェックするときに異なる幅を選択すると、異なるpointerビットパターンから異なる数字が得られます。

(gdb) p pointer
$1 = 0x8048488 "test"
(gdb) x/4c pointer
0x8048488 <_IO_stdin_used+4>:   116 't' 101 'e' 115 's' 116 't'
(gdb) x/4t pointer
0x8048488 <_IO_stdin_used+4>:   01110100        01100101        01110011        01110100
(gdb) x/t (int *)pointer
0x8048488 <_IO_stdin_used+4>:   01110100011100110110010101110100

もう1つの問題は、Intelシステムがリトルエンディアンであることです(Intelではこれを問題と見なすことはできません)。したがって、詳細に見ると、これらの複雑さによってビットパターンがx/4tわずかに異なります。ビッグエンディアンモードに入るようにx/t (int *)指示できます。gdb

(gdb) set endian big
The target is assumed to be big endian
(gdb) x/t (int *)pointer
0x88840408:     Cannot access memory at address 0x88840408

しかし、今メモリアドレスを逆に入力する必要があります!このhtonl 関数呼び出しは、32ビットのリトルエンディアン値をビッグエンディアン値に変換します。

$ cfu 'printf("%d\n", htonl(0x88840408))'
134513800

その後、gdbそのアドレスを試すことができます。

(gdb) x/t (int *)134513800
0x8048488 <_IO_stdin_used+4>:   01110100011001010111001101110100

4桁のビットパターンがビッグエンディアン形式と一致します。これらの結果を表に表示すると便利です。

            --> big endian reads this way
              t        e        s        t
x/4t (char)   01110100 01100101 01110011 01110100
big endian    01110100 01100101 01110011 01110100
            <-- yaw siht sdaer naidne elttil dna
              t        s        e        t
little endian 01110100 01110011 01100101 01110100

test文字列のビットパターンを表示する3つの方法(いくつかの方法の1つ)があります gdb。入力を分割するために指定したビット数gdbとシステムのバイト順序に応じて、同じビットパターンに異なる数字が表示されます。

関連情報