希望能更好地解释x86 call指令。我有点了解远方和远方。但是我不完全理解细分部分。对我的主要问题有一点了解,我正在研究IDA中的二进制文件,其起始代码为:

push 0xdeadbeef
call near 0xdeadbeef


评论

如果其中有Deadbeef,这是非常1337的代码;)

#1 楼

在现代二进制文件中,您将遇到的呼叫中有99%是near


呼叫near(操作码为E8)是相对于当前地址的呼叫,仅影响?IP。因此,它将操作数(字或双字)添加到下一个指令指针。它将操作数添加到?IP

调用far(操作码为9A)会跳转到绝对段并偏移。即就像一次设置CS?IP

内存实际上是按段组织的。在现代操作系统中,通常不会弄乱段(CS在用户模式和内核模式下具有固定值),因此您不会由于任何原因而更改它们。

段更改就像是反调试或与32 / 64b模式混为一谈

评论


它与setjmp / lngjmp C函数有关吗(请参阅本教程)?

–恐怖
13年5月3日在16:45



@perror:AFAIK不是直接的。

– 0xC0000022L♦
13年5月3日在18:45

不,“ longjmp”意义上的“ long”与跳远无关。

–彼得·弗里
13年5月5日,2:25

#2 楼

段是进入内存段的“窗口”。您可以将全部或部分内存映射到单个段,并且多个段可以具有相同内存的重叠视图。远距离呼叫或跳转允许您在这些窗口之间或之内移动。 Near调用或跳转仅允许您在当前窗口内移动。

调用和跳转之间的唯一区别是,调用将返回地址保存在堆栈中。对于远距离调用,返回选择器也保存在堆栈中。

但是,您的问题缺少要确切知道的详细信息。

评论


如何在操作码中指定呼叫存储段,例如E8 D2 12 00 00呼叫sub_402390 000012D2与402390有何关系?那就是我迷路的地方。

–the_endian
17年4月5日在23:47

指令结束后立即将12D2添加到内存地址,因此调用指令以4010BE + 12D2 = 402390结尾。

–彼得·弗里
17年4月11日在18:18