x86 E8和FF通话,如何“动态”找到E8移位地址?基本的x86 ASM调用

时间:2012-05-30 14:56:33

标签: c assembly x86

我在这里使用二进制混淆,所以有一个填充了操作码的缓冲区,我正在使用linux,因此,所有函数调用都使用相同的调用者/被调用者约定,这里没有问题。 / p>

我的问题是关于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。它无论如何都没有用。

坦克引起了注意。

2 个答案:

答案 0 :(得分:1)

我解决了这个问题:

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

比我更换缓冲区上的调用,一切正常。所有坦克都告诉我,我正在为endianes和坦克进行错误的转换以获得帮助。

答案 1 :(得分:1)

near calljxx / near jmp指令中的相对地址等于您要转移控件的目标地址减去紧随call之后的指令地址或jump指示。相对地址相对于下一条指令的地址,而不是传输控制的地址。 IOW,如果calljump指令的地址操作数是相对的,则必须考虑它的长度。

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

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

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

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

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