在mmap()中的PROT_READ上进行memcpy()分段错误调试练习

时间:2013-10-03 11:57:37

标签: assembly gdb segmentation-fault mmap memcpy

我有意在我的代码中生成了SIGSEGV以学习在各种实用程序下调试它,例如 catchsegv gdb valgrind & PMAP 。我故意在mmap'ed文件上使用memcpy(),该文件具有由mprotect()设置的PROT_READ标志。现在,当我在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()调用&amp;之前使用PROT_READ进行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寄存器中写入?

感谢任何帮助。如果需要更多信息,请告诉我。

1 个答案:

答案 0 :(得分:0)

RDI是作为目的地传递给memcpy的参数。在您的情况下,似乎在映射区域中偏移2。您没有提供您使用的memcpy电话。

CL保存源内存区域的第一个字节,它已由故障前面的指令加载:movzbl (%rsi),%ecx。我假设您知道CLECX的低8位(而RCX的低32位)。