near call and far call in Assembly
2023年12月16日以下是x64dbg调试某一程序的界面。
00E33FCB | E8 10D3D3FF | call <v2game.sub_B712E0> 00E33FD0 | C645 FC 32 | mov byte ptr ss:[ebp-4],32 00E33FD4 | 8D8D 4CF8FFFF | lea ecx,dword ptr ss:[ebp-7B4] 00E33FDA | E8 F14AD4FF | call <v2game.sub_B78AD0> 00E33FDF | 8D95 30F8FFFF | lea edx,dword ptr ss:[ebp-7D0] 00E33FE5 | 52 | push edx 00E33FE6 | 8B85 A4FEFFFF | mov eax,dword ptr ss:[ebp-15C] 00E33FEC | 8B10 | mov edx,dword ptr ds:[eax] 00E33FEE | 8B8D A4FEFFFF | mov ecx,dword ptr ss:[ebp-15C] 00E33FF4 | 8B82 90000000 | mov eax,dword ptr ds:[edx+90] 00E33FFA | FFD0 | call eax 00E33FFC | 8985 28E9FFFF | mov dword ptr ss:[ebp-16D8],eax 00E34002 | 8B8D 28E9FFFF | mov ecx,dword ptr ss:[ebp-16D8] 00E34008 | 898D 24E9FFFF | mov dword ptr ss:[ebp-16DC],ecx 00E3400E | C645 FC 34 | mov byte ptr ss:[ebp-4],34 00E34012 | 8B85 24E9FFFF | mov eax,dword ptr ss:[ebp-16DC] 00E34018 | 8D4D A4 | lea ecx,dword ptr ss:[ebp-5C] 00E3401B | E8 C0D2D3FF | call <v2game.sub_B712E0> 00E34020 | C645 FC 32 | mov byte ptr ss:[ebp-4],32
第一行(00E33FCB)是call sub_B712E0,倒数第二行(00E3401B)也是call sub_B712E0。但它们的二进制代码不一样,为什么?
原来,在x86指令集里,call(E8)命令是相对的,也叫做near call。[1]
v2game.sub_B712E0的目标地址为00E33FD0+FFD3D310=00E34020+FFD3D2C0=100B712E0。注意要采用little endian。[2]
最后,在32位系统中,地址是4字节,所以最开头的1被舍弃,所以v2game.sub_B712E0所在的地址为00B712E0。
call能不能调用一个绝对地址?
一个方法是转换为上面一样的相对地址,另一个方法是far call。
参考资料
- Ange. Better explanation of different x86 CALL variations. . 2013-05-03 [2023-12-16].↑
- Joachim Isaksson. X86 encode near call relative offset. . 2013-10-14 [2023-12-16].↑