1

我在这里使用二进制混淆,所以有一个充满操作码的缓冲区,而且我使用的是 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[] = "[....]\xE8\xFF\xFA\xFE\x54[.....]"; //example

我需要用一个有效的指向 srand 的指针替换,我怎样才能从我拥有的东西中获取相对地址?

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

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

(在询问之前,我尝试将 FF XX 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 呼叫。无论如何它都没有用。

4

2 回答 2

3

near calland jxx/指令中的相对地址near jmp等于您要转移控制的目标地址减去紧跟callorjump指令之后的指令地址。相对地址是相对于下一条指令的地址,而不是转移控制的地址。IOW,如果它的地址操作数是相对的,你必须考虑你的callor指令的长度。jump

通常没有相当于5 个字节或更短的callor指令。jump

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

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

如果您使用callorjmp从指定内存位置获取目标地址的变体(例如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)。

于 2012-05-31T14:15:22.503 回答
2

我通过这样做解决了它:

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);

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

于 2012-05-31T13:54:40.577 回答