为什么我不能使用x / 3x以$ eax或$ rax访问内存

时间:2018-02-16 07:23:35

标签: assembly memory x86 gdb

免责声明我是大会新成员,所以如果这是一个愚蠢的问题而我很抱歉,我的术语和一切都很糟糕。

我相信以下代码是链表的x86表示。我正在做“二元炸弹”项目,并一直在跟踪一个不同的炸弹,让我知道我应该采取的步骤。我可以使用命令 x / 3x $ rax 访问$ rax的信息。基于汇编代码和错误中给出的地址,我可以告诉它存储一个节点,该节点指向位于*($ rax + 8)的列表中的下一个节点。出于某种原因,当我尝试查看该位置时,我的终端告诉我它无法访问该位置的内存。为什么会这样?我做错了什么?

错误本身位于汇编代码的底部。不确定它是否可能从我给出的内容中推断出任何答案,但如果是,我想自己解决这个难题,所以请限制答案以解释为什么我无法访问给定位置的内存。 谢谢!

    0x00000000004010bc <+0>:    push   %r13
  0x00000000004010be <+2>:  push   %r12
       0x00000000004010c0 <+4>: push   %rbp
       0x00000000004010c1 <+5>: push   %rbx
       0x00000000004010c2 <+6>: sub    $0x58,%rsp
       0x00000000004010c6 <+10>:    lea    0x30(%rsp),%rsi
       0x00000000004010cb <+15>:    callq  0x401576 <read_six_numbers>
       0x00000000004010d0 <+20>:    lea    0x30(%rsp),%r12
       0x00000000004010d5 <+25>:    mov    $0x0,%r13d
       0x00000000004010db <+31>:    jmp    0x401103 <phase_6+71>
       0x00000000004010dd <+33>:    callq  0x401540 <explode_bomb>
       0x00000000004010e2 <+38>:    jmp    0x401112 <phase_6+86>
       0x00000000004010e4 <+40>:    add    $0x1,%ebx
       0x00000000004010e7 <+43>:    cmp    $0x5,%ebx
       0x00000000004010ea <+46>:    jg     0x4010ff <phase_6+67>
       0x00000000004010ec <+48>:    movslq %ebx,%rax
       0x00000000004010ef <+51>:    mov    0x30(%rsp,%rax,4),%eax
       0x00000000004010f3 <+55>:    cmp    %eax,0x0(%rbp)
       0x00000000004010f6 <+58>:    jne    0x4010e4 <phase_6+40>
       0x00000000004010f8 <+60>:    callq  0x401540 <explode_bomb>
       0x00000000004010fd <+65>:    jmp    0x4010e4 <phase_6+40>
       0x00000000004010ff <+67>:    add    $0x4,%r12
       0x0000000000401103 <+71>:    mov    %r12,%rbp
       0x0000000000401106 <+74>:    mov    (%r12),%eax
       0x000000000040110a <+78>:    sub    $0x1,%eax
       0x000000000040110d <+81>:    cmp    $0x5,%eax
       0x0000000000401110 <+84>:    ja     0x4010dd <phase_6+33>
       0x0000000000401112 <+86>:    add    $0x1,%r13d
    ---Type <return> to continue, or q <return> to quit---
       0x0000000000401116 <+90>:    cmp    $0x6,%r13d
       0x000000000040111a <+94>:    je     0x40114f <phase_6+147>
       0x000000000040111c <+96>:    mov    %r13d,%ebx
       0x000000000040111f <+99>:    jmp    0x4010ec <phase_6+48>
       0x0000000000401121 <+101>:   mov    0x8(%rdx),%rdx
       0x0000000000401125 <+105>:   add    $0x1,%eax
       0x0000000000401128 <+108>:   cmp    %ecx,%eax
       0x000000000040112a <+110>:   jne    0x401121 <phase_6+101>
       0x000000000040112c <+112>:   mov    %rdx,(%rsp,%rsi,8)
       0x0000000000401130 <+116>:   add    $0x1,%rsi
       0x0000000000401134 <+120>:   cmp    $0x6,%rsi
       0x0000000000401138 <+124>:   je     0x401156 <phase_6+154>
       0x000000000040113a <+126>:   mov    0x30(%rsp,%rsi,4),%ecx
       0x000000000040113e <+130>:   mov    $0x1,%eax
       0x0000000000401143 <+135>:   mov    $0x6042f0,%edx
       0x0000000000401148 <+140>:   cmp    $0x1,%ecx
       0x000000000040114b <+143>:   jg     0x401121 <phase_6+101>
       0x000000000040114d <+145>:   jmp    0x40112c <phase_6+112>
       0x000000000040114f <+147>:   mov    $0x0,%esi
       0x0000000000401154 <+152>:   jmp    0x40113a <phase_6+126>
       0x0000000000401156 <+154>:   mov    (%rsp),%rbx
       0x000000000040115a <+158>:   mov    0x8(%rsp),%rax
       0x000000000040115f <+163>:   mov    %rax,0x8(%rbx)
       0x0000000000401163 <+167>:   mov    0x10(%rsp),%rdx
       0x0000000000401168 <+172>:   mov    %rdx,0x8(%rax)
       0x000000000040116c <+176>:   mov    0x18(%rsp),%rax
       0x0000000000401171 <+181>:   mov    %rax,0x8(%rdx)
       0x0000000000401175 <+185>:   mov    0x20(%rsp),%rdx
       0x000000000040117a <+190>:   mov    %rdx,0x8(%rax)
    ---Type <return> to continue, or q <return> to quit---
       0x000000000040117e <+194>:   mov    0x28(%rsp),%rax
       0x0000000000401183 <+199>:   mov    %rax,0x8(%rdx)
       0x0000000000401187 <+203>:   movq   $0x0,0x8(%rax)
       0x000000000040118f <+211>:   mov    $0x5,%ebp
       0x0000000000401194 <+216>:   jmp    0x40119f <phase_6+227>
       0x0000000000401196 <+218>:   mov    0x8(%rbx),%rbx
       0x000000000040119a <+222>:   sub    $0x1,%ebp
       0x000000000040119d <+225>:   je     0x4011b0 <phase_6+244>
       0x000000000040119f <+227>:   mov    0x8(%rbx),%rax
       0x00000000004011a3 <+231>:   mov    (%rax),%eax
       0x00000000004011a5 <+233>:   cmp    %eax,(%rbx)
       0x00000000004011a7 <+235>:   jle    0x401196 <phase_6+218>
       0x00000000004011a9 <+237>:   callq  0x401540 <explode_bomb>
       0x00000000004011ae <+242>:   jmp    0x401196 <phase_6+218>
       0x00000000004011b0 <+244>:   add    $0x58,%rsp
       0x00000000004011b4 <+248>:   pop    %rbx
       0x00000000004011b5 <+249>:   pop    %rbp
       0x00000000004011b6 <+250>:   pop    %r12
       0x00000000004011b8 <+252>:   pop    %r13
       0x00000000004011ba <+254>:   retq   
    End of assembler dump.
    (gdb) x/3x $rax
    0x604950 <input_strings+400>:   0x20342036  0x20352031  0x00322033
    (gdb) x/3x *($rax+8)
    0x322033:   Cannot access memory at address 0x322033
    (gdb) x/3x *($rax + 8)
    0x322033:   Cannot access memory at address 0x322033

1 个答案:

答案 0 :(得分:3)

您正在使用rax访问x/3x $rax指向的内存。 (所以你的问题标题是错误的。)

x/3x *($rax+8)有2个问题:

  1. RAX指向的内存看起来像ASCII字符。 (尝试x /16c $raxp (char*)$rax。)不会看起来像一个有效的地址。 (您可以查看less /proc/$(pidof my_bomb)/maps以查找目标进程已映射的虚拟地址范围。)

  2. 您只使用32位数据作为地址。 GDB一般没有asm或寄存器的类型信息,通常默认为intint*。在这种情况下,$rax+8被视为int*中的*($rax+8),因此您要求GDB将4个字节的内存作为x命令的参数

  3. x86-64指针长64位,所以你应该使用x /3xg转储3 x86 qwords(GDB调用&#34; g iant&#34;而不是默认值32 -bit GDB w ord。请注意,即使在调试x86目标时,GDB的术语也与典型的32位RISC机器匹配,而不是x86术语。

    0x00322033不太可能是有效地址的低32位,你在编译器生成的代码中找到另一个指针,因为它是奇数。默认情况下,x86-64 System V ABI将64位指针/整数与64位对齐,因此包含指针的结构的起点将位于可被8整除的地址(以8结尾或十六进制中的0

    但是如果$rax+8是一个8字节的指针,在上面的32中有一些非零值,你可以x /3xg *(void **)($rax+8)或者其他什么,所以表达你&#39 ;重新引用具有指针指针类型,因此将加载整个指针的数据。

    或者,您可以复制/粘贴先前x命令中的地址。或者您可以使用print命令。例如,在流程中的_start处(rsp+8argv[0]):

    (gdb) p $rsp
    $1 = (void *) 0x7fffffffe690
    (gdb) p *(void**)($rsp+8)
    $4 = (void *) 0x7fffffffe9c5
    
    (gdb) p **(void**)($rsp+8)       # oops, always need at least one more * in the type and in the deref
    Attempt to dereference a generic pointer.
    
    (gdb) p **(long**)($rsp+8)
    $5 = 7955998172649846063
    (gdb) p /x **(long**)($rsp+8)   # same value, different format (/x isn't default because it's an integer type, not a pointer)
    $6 = 0x6e69622f7273752f
    
    (gdb) p  **(void*****)($rsp+8)     # you can use a zillion *s in the type :P
    
    $7 = (void ***) 0x6e69622f7273752f      # this wasn't a linked list!
    (gdb) p  ***(void*****)($rsp+8)
    Cannot access memory at address 0x6e69622f7273752f   # ASCII data as a pointer is bogus