最近在用IDA分析QuickTime.qts中代码的时候,发现其中很多函数(有2800多个吧
)都是由theQuickTimeDispatcher函数分发来实现调用的,比如在模块以下位置有两处函数调用:
.text:6688EDF0 loc_6688EDF0:
.text:6688EDF0 mov eax, [esp+124h+var_F0]
.text:6688EDF4 test eax, eax
.text:6688EDF6 jz short loc_6688EE01
.text:6688EDF8 push eax
.text:6688EDF9 call sub_668FE1B0
.text:6688EDFE add esp, 4
.text:6688EE01
.text:6688EE01 loc_6688EE01:
.text:6688EE01 cmp [esp+124h+var_104], 0
.text:6688EE06 jz short loc_6688EE15
.text:6688EE08 lea eax, [esp+124h+var_104]
.text:6688EE0C push eax
.text:6688EE0D call sub_668CE1D0
.text:6688EE12 add esp, 4
在IDA中跳转到sub_668FE1B0和sub_668CE1D0的入口处,都只能看到类似如下两条简单的指令:
mov eax,[分发函数序号]
jmp theQuickTimeDispatcher
在theQuickTimeDispatcher函数中会用EAX中保存的分发函数序号,从一函数指针数组中读取实际的功能函数入口地址:
.text:6684BA90 theQuickTimeDispatcher proc near
.text:6684BA90
.text:6684BA90 mov ecx, eax
.text:6684BA92 shr ecx, 10h
.text:6684BA95 and ecx, 0FFh
.text:6684BA9B and eax, 0FF00FFFFh
.text:6684BAA0 lea ecx, dword_67301A38[ecx*8] ;0x67301A38中为一函数指针数组基地值
.text:6684BAA7 cmp byte ptr [ecx], 0
.text:6684BAAA jz short loc_6684BAC1
.text:6684BAAC mov edx, [ecx+4]
.text:6684BAAF lea ecx, ds:0[eax*4]
.text:6684BAB6 lea ecx, [edx+ecx*4]
.text:6684BAB9 mov eax, [ecx] ;将实际的功能函数入口地址保存在EAX中
如果执行cmp byte ptr[ecx],0指令时,ECX所指向内存单元中为0,则跳转到子分发函数中执行:
.text:6684BAC1 jmp dword ptr [ecx+4]
QuickTime.qts模块中有多个子分发函数,这些函数的逻辑类似,即从不同的函数指针数组中读取功能函数地址:
movsx eax, ax
lea ecx, 函数指针数组基地值[eax*8]
mov eax, [ecx]
于是考虑编写一IDAPython脚本来通过模拟分发函数执行,获取实际功能函数地址,并且在函数调用位置添加注释信息,以便在静态分析的时候可以直接跳转到功能函数的入口处。达到下图这样的效果
没什么技术含量的东西,之所以要在此献丑,是希望这个脚本可以对一些研究QuickTime的人的工作起到帮助。代码参见附件qt_dispatcher.py.txt,哪位仁兄若有好的修改建议,也欢迎提出
[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。