如何用GDB访问内存地址值及分析汇编中(%rdi)的含义
关于x86-64汇编与GDB调试的问题
1. 对(%rdi)的理解是否正确?
我认为%rdi是寄存器,括号表示寄存器中存储的是内存地址,(%rdi)返回该地址指向的内存内容,这个理解是否正确?
2. 如何用GDB访问(%rdi)的值?
我尝试使用x $rdi命令时,提示Cannot access memory address at 0x0,应该输入什么命令才能正确访问该值?
3. 如何查找特定内存区域?
我需要找到一个内存地址,该地址存储0x6a,且下一个地址存储0x0,怎么在GDB中实现?
附上反汇编代码:
0x0000000000400f6d <+0>: push %rbx 0x0000000000400f6e <+1>: mov %rdi,%rbx 0x0000000000400f71 <+4>: cmpb $0x0,0x1(%rdi) 0x0000000000400f75 <+8>: jne 0x400f7e <phase_1+17> 0x0000000000400f77 <+10>: cmpb $0x6a,(%rbx) 0x0000000000400f7a <+13>: jne 0x400f85 <phase_1+24> 0x0000000000400f7c <+15>: pop %rbx 0x0000000000400f7d <+16>: ret 0x0000000000400f7e <+17>: call 0x4016ed <explode_bomb> 0x0000000000400f83 <+22>: jmp 0x400f77 <phase_1+10> 0x0000000000400f85 <+24>: call 0x4016ed <explode_bomb> 0x0000000000400f8a <+29>: jmp 0x400f7c <phase_1+15>
解答
1. 对(%rdi)的理解完全正确
在x86-64汇编中,%rdi是通用寄存器,(%rdi)属于间接寻址语法:以%rdi寄存器内存储的数值作为内存地址,读取该地址对应的1字节(因为你提供的代码中用的是cmpb字节比较指令)内存内容。
2. 正确访问(%rdi)的GDB命令
你用x $rdi报错,是因为执行该命令时%rdi寄存器里存的是0x0,而空指针地址通常属于不可访问的内存区域。要正确读取(%rdi)的内容,需先确保程序运行到%rdi被正确赋值的位置(比如phase_1函数中mov %rdi,%rbx指令执行之后),再使用以下命令:
- 按字节读取内存内容:
x/b $rdi(/b表示以字节为单位查看) - 先查看寄存器值再对应读内存:先用
info registers rdi获取%rdi存储的地址,再执行x/b <该地址>查看内存内容
3. 查找目标内存区域的方法
GDB没有直接遍历所有内存的命令,可通过以下两种方式缩小范围查找:
方法1:指定内存区域搜索
- 先用
info proc mappings查看进程的内存映射,确定堆、栈或数据段的地址范围 - 使用
find命令搜索连续的0x6a和0x0字节:
find <起始地址>, <结束地址>, 0x6a, 0x0
例如,若数据段范围是0x400000到0x500000,则执行:
find 0x400000, 0x500000, 0x6a, 0x0
该命令会返回所有连续两个字节为0x6a、0x0的内存地址。
方法2:结合程序逻辑快速定位
从反汇编代码可以看出,phase_1函数是在检查传入的参数(x86-64中%rdi是第一个函数参数,这里应为字符串指针):
- 先检查
0x1(%rdi)(字符串第二个字符)是否为0x0 - 再检查
(%rdi)(字符串第一个字符)是否为0x6a
你要找的其实是长度为1的字符串"j"(0x6a对应ASCII字符j),可以直接在程序输入中填入j,或在GDB中查看程序的输入缓冲区(比如栈上存储输入的位置)。
内容的提问来源于stack exchange,提问作者Annie
相关产品推荐
相关产品推荐

