call cs:CoCreateInstance
或
call WinSqmAddToStream
但是有时格式不使用函数名称。下面的示例包括导致该行的代码。第三行代码似乎“缺少”函数名称。 (评论是我自己的。)
mov rcx, [rsp+128h+var_D8] // reg CX gets the address at stack pointer+128h+var_D8 bytes
mov r8, [rcx] // the address at reg CX is stored to reg r8
call qword ptr [r8 + 18h] // at address rax+18h, call function defined by qword bytes
我的问题如下:
如何建立两者之间的联系
call qword ptr <address>
和反汇编中的函数?我知道IDA在这里不能使用函数名称,因为它不知道存储在寄存器R8中的值...那是什么原因呢?开发人员是否使用某种语法或约定?换句话说,开发人员是否以与
WinSqmAddToStream
处不同的方式调用函数[r8+18h]
?#1 楼
要将间接调用连接到其目标(如果知道),可以执行以下操作:1)添加自定义交叉引用-使用IDC / Python或“交叉引用”子视图。如果使用脚本,请不要忘记添加XREF_USER标志,以便IDA在重新分析时不会将其删除。
2)使用“ callee”插件(编辑->插件->更改被调用者地址) ,或Alt + F11)。这将自动在调用旁边添加一个交叉引用和注释。
为什么在二进制文件中不存在显式调用,可能有很多解释。您显示的代码片段看起来像一个虚拟函数调用,通常仅以这种方式完成,以解决方法在派生类中被覆盖的可能性。
评论
感谢你的回答。一旦我知道目标函数,这将非常有帮助。我仍然不知道如何确定正在调用的函数。我将编辑问题以表明我对该部分更感兴趣。
–克拉克
13年5月28日在14:22
@clark尝试在指令上放置一个断点,然后运行,然后进入/手动计算与可用寄存器的偏移量?还是必须是静态的?
–马丁
16-10-26在22:41
#2 楼
诀窍是找到对象的构造函数。让我们假设代码看起来像这样:a = new CFoo();
a->bar();
编译器(我假设是MSVC,32位)可能会产生以下内容:
push 12h ; size_t
call ??2@YXYXY@Z ; operator new(uint)
mov [ebp+var_8], eax
mov esi, eax
test esi, esi
jz loc_1
mov ecx, esi
call ??0CFoo@@AAAA@AA ; CFoo::CFoo(void)
mov [ebp+var_8], eax
jmp loc_2
loc_1:
mov [ebp+var_8], 0
loc_2:
...
...
...
mov eax, [ebp+var_8]
mov ecx, [eax]
mov ebx, ecx
mov ecx, [ebp+var_8]
call dword ptr [ebx+08h]
查看
??0CFoo@@AAAA@AA
,又称为CFoo::CFoo():
...
mov esi, ecx
mov dword ptr [esi], unk_12345
...
unk_12345
是CFoo
的虚拟表偏移量: /> 被称为
sub_45678
的是unk_12345+08h
处的CFoo::bar()
(在本例中为第3个条目)。
评论
例如,这些间接调用用于在C ++中实现虚拟功能(通过使用vtable)。也有像github.com/0xgalz/Virtuailor这样的插件可以自动执行这些任务。