Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 更改a';呼叫';内存中的地址?_C_Assembly_X86_Gdb_Stack - Fatal编程技术网

C 更改a';呼叫';内存中的地址?

C 更改a';呼叫';内存中的地址?,c,assembly,x86,gdb,stack,C,Assembly,X86,Gdb,Stack,这适用于64位x86英特尔处理器 在GDB中,我可以看到: 0x400500 <main+50>: call 0x400100 <somefunc> 0x400500:调用0x400100 然而,当我检查0x400500处的内存时,我看不到对“0x400100”的任何引用,也看不到附近寄存器中有任何明显的内容 它如何“知道”在哪里打电话。这似乎很简单,但我还没有找到答案 我正在尝试调用,例如,具有上述函数参数的系统,但只能有限地访问内存。请注意,这只是为了好玩,是挑战

这适用于64位x86英特尔处理器

在GDB中,我可以看到:

0x400500 <main+50>: call 0x400100 <somefunc>
0x400500:调用0x400100
然而,当我检查0x400500处的内存时,我看不到对“0x400100”的任何引用,也看不到附近寄存器中有任何明显的内容

它如何“知道”在哪里打电话。这似乎很简单,但我还没有找到答案

我正在尝试调用,例如,具有上述函数参数的系统,但只能有限地访问内存。请注意,这只是为了好玩,是挑战练习的一部分

它如何“知道”在哪里打电话

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

例如:

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
intfoo(){return 42;}
int main(){return foo();}
gcc-g t.c
gdb-q./a.out
(gdb)disas/r干管
主功能的汇编程序代码转储:
0x00000000004004f8:55推送%rbp
0x00000000004004f9:48 89 e5 mov%rsp,%rbp
0x000000000004004FC:b8 00 mov$0x0,%eax
0x0000000000400501:e8 e7 ff ff ff callq 0x4004ed
0x0000000000400506:5d pop%rbp
0x0000000000400507:c3 retq
汇编程序转储结束。
(gdb)宝富
$1=(整数(*)()0x4004ed
(gdb)p/x 0x4004ed-0x0000000000400506
$2=0xFFFFFF7

注意
e7 ff ff
字节,它们是
callq
的一部分。这是偏移量,用小尾端字母拼写。

普通调用指令编码为
调用rel32
,具有相对位移而不是绝对位移。一如既往,检查以了解指令是如何编码的

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


在GDB中,您不需要修改机器指令中编码的相对位移:您可以将
stepi
放入
调用中,然后使用
jump*0x1234567
GDB命令在其他地方继续执行
设置$pc=0x1234567
以更改EIP/RIP,而无需执行“继续”


所以你让call指令推送一个返回地址并跳转,然后跳转到其他地方,假装你一开始就跳转到了那里。只有在
调用
的原始目标可访问的情况下,这才可能起作用;我不确定x86是否只是因为将RIP设置为不可执行内存而出现故障,或者只有在尝试运行第一条指令时才会出现故障。

32b还是64b?为什么不发布,在
0x400500
中存储了哪些字节?在32b模式下,
call$
被组装到
e8 fb ff ff
call
操作码是
e8
,接下来的4个字节是与
eip
相对的32位偏移量(地址计算时指向下一条指令,即偏移量为-5,以便在无限循环中对自身进行
调用
). 从您的反汇编猜测操作码可能是
e8 fb ff
.64位,抱歉。将更新问题。打印出呼叫发生的地址,例如0xfffe66e8。不确定您发布了什么,但我在那里没有看到机器代码(
e8
call opcode),这就是您想要实现的地址?或者
调用
所在的位置?无论如何,从汇编程序的快速测试来看,即使在64b模式下,
调用imm32
的计算方法与32b相同,即当前
rip
的32位有符号偏移量(该偏移量超出
调用
,即+5)。啊,要更改调用地址,我需要更改针对eip的偏移量。这是有道理的,但在GDB中不容易发现。谢谢。现在粘贴正确的输出。谢谢您的回答。关于调用后的跳转,我不确定是否要看程序,但这取决于跳转指令是否可用,对吗?我只能更改8个字节。当它试图在非可执行内存中运行第一条指令时,它是SIGSEGVs。@GhostSparkles:不,我说的是用调试器修改程序状态,而不是修改指令。在断点/单步停止时,您可以直接将
RIP
设置为您想要的任何内容。