c-x86 E8和FF调用,如何"即时"找到E8移位地址?基本 x86 ASM 调用



我在这里使用二进制混淆,所以有一个充满操作码的缓冲区,我使用的是 Linux,所以,所有函数调用都使用相同的调用方/被调用方约定,这里没有问题。

我的问题是关于 E8 操作码,该操作码使用相对地址接收近似调用。

我的问题是:我知道呼叫来自的地址,我知道我必须呼叫的地址,

那么,我如何找到必须在E8呼叫中输入的班次地址?这是:

signed long src = (signed long)buffer + shift; //get the position where E8 instruction is
signed long dst = (signed long)srand;          //get the destination position where i want to call (yes, srand(long) function in this case.)

所以在我的缓冲区中,我有:

buffer[] = "[....]xE8xFFxFAxFEx54[.....]"; //example

我需要替换为指向 srand 的有效指针,如何从我所拥有的中获取相对地址?

我只是想我可以使用FF指令直接调用,但是我不知道该怎么做。我无法将地址复制到(说)$eax因为我不能在替换中输入超过 5 个操作码(它会让上面的所有 jmp 调用都变成香蕉),而且我不明白是否有办法在 5 字节内直接调用。

因此,如果有人知道如何获得正确的值来替换 E8 相对移位地址,或者是否有一种方法可以进行某种直接调用,保持与 E8 调用相同的功能属性并且仅使用 5 个字节......

(在询问之前,我试图将 FF XX XX XX 作为 XX 作为真实地址,但它不起作用,x86 看起来不像一个电话,它解释为 INC(???)和一些随机的东西之后。我尝试以这种方式替换:

inline void endian_swap(long& x) {
      x = (x>>24) |
          ((x<<8) & 0x00FF0000) |
          ((x>>8) & 0x0000FF00) |
          (x<<24);
}
endian_swap(dst);
endian_swap(src);
unsigned int p = dst - src;
endian_swap(p);

并将我找到的地址输入E8呼叫。反正没用。

near calljxx/near jmp指令中的相对地址等于您要转移控制权的目标地址减去紧跟在calljump指令之后的指令地址。相对地址相对于下一条指令的地址,而不是转移控制权的地址。IOW,您必须考虑calljump指令的长度(如果其地址操作数是相对的)。

通常,没有等效于 5 个字节或更短的 calljump 指令。

您可以将jmp模拟为 push target address + ret ,但在具有任意目标地址的 32 位模式下,这 2 条指令至少获得 1+4+1=6 个字节。您可以以相同的方式模拟call,但您将添加另一个pushcall指令以将返回地址放置在堆栈上。因此,在这 6 个字节中,您再添加 5 个字节。

有一个"绝对"版本的"jmp"(以及IIRC"call"),它将地址操作数作为由目标偏移量和目标段组成的直接操作数。这样的指令长度至少为 1+4+2=7 字节(偏移量为 4 字节,段选择器为 2 字节)。

如果您使用 calljmp 的变体从指定的内存位置获取目标地址(例如 call [ebx] ),该指令的长度至少为 1+1=2 字节(操作码 + ModR/M 字节),但您必须加载一个寄存器,其中包含包含目标地址的该内存位置的地址,这将花费您其他一些 1+4=5 字节,至少给你 7 个字节。还有一个变体允许您在寄存器中指定目标地址(例如 jmp ebx ),但同样,由于必须加载寄存器,您至少需要 7 个字节。

使call/jump指令更短的唯一方法是当目标地址非常接近该指令的地址时(在这种情况下,您可以使用rel16形式(具有适当的操作数或地址(我不记得是哪一个)覆盖前缀)或rel8形式(如果可用))或目标地址较小(在这种情况下push target address可以是较短的 push Ib或较短的operand size prefix + push Iw)。

我通过以下方式解决了它:

long dst = (long)srand;
long src = ((long)buffer) + shift + 5; //begin of buffer + actual position + this instruction size
long p = dst - src;
p = htonl(p);

比我替换缓冲区上的调用,一切正常。

最新更新