0

catchsegvgdbvalgrindpmapなどのさまざまなユーティリティでデバッグする方法を学ぶために、意図的にコードに SIGSEGV を生成しました。mprotect() によって PROT_READ のフラグが設定されている mmap されたファイルに対して、意図的に memcpy() を使用しました。gdb でデバッグしているときに、アセンブリ出力から結論を出すことができません。組み立てに関してはかなりの初心者です。

詳細 -

メモリースタッフ:

    (gdb) x/35i 0x00002aaaaad55500
    0x2aaaaad55500 <memccpy+32>: jne    0x2aaaaad554e8 <memccpy+8>
    0x2aaaaad55502 <memccpy+34>: mov    %rdi,%rax
    0x2aaaaad55505 <memccpy+37>: retq
    0x2aaaaad55506 <memccpy+38>: nopw   %cs:0x0(%rax,%rax,1)
    0x2aaaaad55510 <memccpy+48>: xor    %eax,%eax
    0x2aaaaad55512 <memccpy+50>: retq
    0x2aaaaad55513:      nop
    0x2aaaaad55514:      nop
    0x2aaaaad55515:      nop
    0x2aaaaad55516:      nop
    0x2aaaaad55517:      nop
    0x2aaaaad55518:      nop
    0x2aaaaad55519:      nop
    0x2aaaaad5551a:      nop
    0x2aaaaad5551b:      nop
    0x2aaaaad5551c:      nop
    0x2aaaaad5551d:      nop
    0x2aaaaad5551e:      nop
    0x2aaaaad5551f:      nop
    0x2aaaaad55520 <__memcpy_chk>:       cmp    %rdx,%rcx
    0x2aaaaad55523 <__memcpy_chk+3>:     jb     0x2aaaaadcb590 <__chk_fail>
    0x2aaaaad55529:      nopl   0x0(%rax)
    0x2aaaaad55530 <memcpy>:     cmp    $0x20,%rdx
    0x2aaaaad55534 <memcpy+4>:   mov    %rdi,%rax
    0x2aaaaad55537 <memcpy+7>:   jae    0x2aaaaad555b0 <memcpy+128>
    0x2aaaaad55539 <memcpy+9>:   test   $0x1,%dl
    0x2aaaaad5553c <memcpy+12>:  je     0x2aaaaad55549 <memcpy+25>
    0x2aaaaad5553e <memcpy+14>:  movzbl (%rsi),%ecx
    => 0x2aaaaad55541 <memcpy+17>:  mov    %cl,(%rdi)
    0x2aaaaad55543 <memcpy+19>:  inc    %rsi
    0x2aaaaad55546 <memcpy+22>:  inc    %rdi
    0x2aaaaad55549 <memcpy+25>:  test   $0x2,%dl
    0x2aaaaad5554c <memcpy+28>:  je     0x2aaaaad55560 <memcpy+48>
    0x2aaaaad5554e <memcpy+30>:  movzwl (%rsi),%ecx
    0x2aaaaad55551 <memcpy+33>:  mov    %cx,(%rdi)

ご覧のとおり、SEGFAULT が命令 0x2aaaaad55541 で発生したことがわかります。これは、64 ビット命令ポインター レジスタ RIP にも示されています。

レジスター:

    (gdb) info registers
    rax            0x2aaaaaacf002   46912496267266
    rbx            0x40146a 4199530
    rcx            0x69     105
    rdx            0x1      1
    rsi            0x40146a 4199530
    rdi            0x2aaaaaacf002   46912496267266
    rbp            0x7      0x7
    rsp            0x7fffffffe468   0x7fffffffe468
    r8             0x40146a 4199530
    r9             0x53202c444145525f       5989836176067220063
    r10            0x7fffffffe1f0   140737488347632
    r11            0x2aaaaad55530   46912498914608
    r12            0x2aaaab05eac8   46912502098632
    r13            0x7fffffffe5a0   140737488348576
    r14            0x7fffffffe590   140737488348560
    r15            0x2aaaaaacf000   46912496267264
    rip            0x2aaaaad55541   0x2aaaaad55541 <memcpy+17>
    eflags         0x10202  [ IF RF ]
    cs             0x33     51
    ss             0x2b     43
    ds             0x0      0
    es             0x0      0
    fs             0x0      0
    gs             0x0      0

プロセス マッピング:

以下は、gdb 内の「info proc mappings」コマンドの出力です。

    [excerpt]
    0x2aaaaaacf000     0x2aaaaaad0000     0x1000          0             /tmp/dst_file
    [/excerpt]

/tmp/dst_file は mmap() を使用してメモリにマップされ、memcpy() 呼び出しの前に PROT_READ を使用して読み取り専用にされ、memcpy() はそれにコンテンツを書き込もうとするため、SEGFAULT が表示されます。

使用される Memcpy() 呼び出し:

    memcpy (mmap_start + myfilestat1.st_size, str1, strlen(str1))

mmap_start は開始アドレスで、myfilestat1.st_size は切り捨てられた新しいファイル サイズです。str1 は、ファイルに追加する文字列です。

これが私のソースコードの小さな流れです -

    1. Fstat original size of file 
    2. Set Offset of file to grow depending upon strlen() of string to append 
    3. Ftruncate() to grow file size 
    4. Fstat new file size. 
    5. Mmap the newly truncated file 
    6. If segmentation fault need to be generated, call mprotect() to convert to PROT_READ. 
    7. Memcpy() with Orignal fstat size to append contents to text file. 

質問 -

今、私が理解できないのは

    0x2aaaaad55541 <memcpy+17>:  mov    %cl,(%rdi)

この指示は正確に何をしますか?RDI レジスタには、書き込みを開始するようにマップされたファイルの終了アドレスが含まれていますが、RDI アドレスの値が CX レジスタに書き込まれているのはなぜですか?

どんな助けでも大歓迎です。さらに情報が必要な場合はお知らせください。

4

1 に答える 1

1

RDImemcpy宛先として渡される引数です。あなたの場合、マップされた領域のオフセット 2 のようです。memcpy使用した通話を提供していません。

CLソースメモリ領域の最初のバイトを保持します。これは、フォルトの直前の命令によってロードされています: movzbl (%rsi),%ecx. CLそれが の下位 8 ビットECX(つまり の下位 32 ビット) であることを知っていると思いますRCX

于 2013-10-03T12:18:40.520 に答える