更改电话'记忆中的地址?

时间:2017-10-15 14:47:24

标签: c assembly x86 gdb stack

这适用于64位x86 Intel处理器。

在GDB中我可以看到:

0x400500 <main+50>: call 0x400100 <somefunc>

然而,当我在0x400500处检查内存时,我看不到任何对“0x400100”的引用,附近的寄存器中也没有任何明显的内容。

它如何知道&#39;在哪里打电话。看起来很简单,但我还没有找到答案。

我试图打电话,例如系统具有上述功能的参数,只能有限地访问内存。请注意,这只是为了娱乐,是挑战练习的一部分。

2 个答案:

答案 0 :(得分:4)

  

它如何'知道'在哪里打电话。

要调用的地址是调用后指令的偏移量。

示例:

int foo() { return 42; }
int main() { return foo(); }

gcc -g t.c
gdb -q ./a.out

(gdb) disas/r main
Dump of assembler code for function main:
   0x00000000004004f8 <+0>: 55  push   %rbp
   0x00000000004004f9 <+1>: 48 89 e5    mov    %rsp,%rbp
   0x00000000004004fc <+4>: b8 00 00 00 00  mov    $0x0,%eax
   0x0000000000400501 <+9>: e8 e7 ff ff ff  callq  0x4004ed <foo>
   0x0000000000400506 <+14>:    5d  pop    %rbp
   0x0000000000400507 <+15>:    c3  retq
End of assembler dump.

(gdb) p &foo
$1 = (int (*)()) 0x4004ed <foo>

(gdb) p/x 0x4004ed - 0x0000000000400506
$2 = 0xffffffe7

请注意属于e7 ff ff ff的{​​{1}}个字节。这是偏移量,用小端拼写。

答案 1 :(得分:2)

普通呼叫指令编码为call rel32,具有相对位移而不是绝对位移。与往常一样,请检查the instruction-set reference manual entry以了解指令的编码方式。

要使GDB的内置反汇编包含原始机器代码字节,请使用disas /r。 (不确定如何在layout asm / layout reg中为asm窗口获取该行为。)objdump默认包含机器代码(十六进制)。我在.bashrc中使用alias disas='objdump -drwC -Mintel'

在GDB 中,您无需修改​​机器指令中编码的相对位移:您可以stepi进入call并使用jump *0x1234567 1}} GDB命令继续在其他地方执行。 set $pc = 0x1234567更改EIP / RIP而不进行“继续”

请参阅Is it possible to "jump"/"skip" in GDB debugger?

所以你让调用指令按下一个返回地址然后跳转,然后跳到其他地方,假装你首先跳到那里。这可能仅在call的原始目标可访问时才有效;我不确定x86是否只是将RIP设置为非可执行内存,或者在尝试运行第一条指令之前不会出错。