C x86 E8和FF调用,如何查找E8移位地址';在飞行中';?基本x86 ASM调用
我在这里处理二进制模糊处理,所以a有一个缓冲区,里面填充了操作码,我使用Linux,所以所有函数调用都使用相同的调用方/被调用方约定,这里没有问题 我的问题是关于E8操作码,这个操作码使用相对地址进行近距离呼叫 我的问题是:我知道打电话的地址,我知道我必须打电话的地址,所以,我如何才能找到我必须在E8电话中输入的轮班地址?这是:C x86 E8和FF调用,如何查找E8移位地址';在飞行中';?基本x86 ASM调用,c,assembly,x86,machine-code,C,Assembly,X86,Machine Code,我在这里处理二进制模糊处理,所以a有一个缓冲区,里面填充了操作码,我使用Linux,所以所有函数调用都使用相同的调用方/被调用方约定,这里没有问题 我的问题是关于E8操作码,这个操作码使用相对地址进行近距离呼叫 我的问题是:我知道打电话的地址,我知道我必须打电话的地址,所以,我如何才能找到我必须在E8电话中输入的轮班地址?这是: signed long src = (signed long)buffer + shift; //get the position where E8 instructi
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 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);
inline void endian_交换(long&x){
x=(x>>24)|
((x8)和0x0000FF00)|
(x我通过以下方法解决了这个问题:
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);
然后,我替换了缓冲区上的调用,一切都正常。我通过执行以下操作解决了此问题:
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);
然后我替换了对缓冲区的调用,一切正常。在近调用
和jxx
/近jmp
指令中的相对地址等于要转移控制的目标地址减去调用
或跳转
后的指令地址指令。相对地址是相对于下一条指令的地址,而不是转移控制权的指令。因此,如果指令的地址操作数是相对的,则必须考虑调用
或跳转
指令的长度
一般来说,没有与5字节或更短的调用
或跳转
指令等效的指令
您可以将jmp
模拟为push目标地址
+ret
,但在32位模式下,对于任意目标地址,这两条指令至少会得到1+4+1=6字节。您可以用相同的方式模拟调用
,但您必须添加另一条push
或调用
指令来放置re打开堆栈上的地址。因此,在这6个字节中再添加5个
有一种“绝对”版本的“jmp”(以及IIRC“call”),它将地址操作数作为由目标偏移量和目标段组成的立即数。这种指令的长度至少为1+4+2=7字节(偏移量为4字节,段选择器为2字节)
如果使用从指定内存位置获取目标地址的call
或jmp
变体(例如call[ebx]
),则该指令的长度至少为1+1=2字节(操作码+ModR/M字节),但您必须加载一个包含目标地址的内存位置地址的寄存器,这将花费您另外一些1+4=5字节,给您至少7个字节。还有一个变体允许您在寄存器中指定目标地址(例如jmp ebx
),但同样,由于必须加载寄存器,您至少会输出7个字节
使调用
/跳转
指令变短的唯一方法是当目标地址非常接近该指令的地址时(在这种情况下,您可以使用rel16
形式(使用适当的操作数或地址(我不记得是哪一个)重写前缀)或rel8
表单(如果可用)或目标地址较小时(在这种情况下,推送目标地址可以是较短的推送Ib
或较短的操作数大小前缀+推送Iw
).在近调用
和jxx
/近jmp
指令中的相对地址等于要转移控制权的目标地址减去紧跟在调用
或跳转
指令之后的指令地址。相对地址与ext指令,而不是传输控制的指令。注意,如果地址操作数是相对的,则必须考虑调用
或跳转
指令的长度
一般来说,没有与5字节或更短的调用
或跳转
指令等效的指令
您可以将jmp
模拟为push目标地址
+ret
,但在32位模式下,对于任意目标地址,这两条指令至少会得到1+4+1=6字节。您可以用相同的方式模拟调用
,但您必须添加另一条push
或调用
指令来放置re打开堆栈上的地址。因此,在这6个字节中再添加5个
有一种“绝对”版本的“jmp”(以及IIRC“call”),它将地址操作数作为由目标偏移量和目标段组成的立即数。这种指令的长度至少为1+4+2=7字节(偏移量为4字节,段选择器为2字节)
如果您使用从指定内存位置获取目标地址的call
或jmp
变体(例如call[ebx]
),则该指令的长度至少为1+1=2字节(操作码+ModR/M字节),但您必须用t加载寄存器