前言
摘抄 恶意代码分析实战 书中的易遗忘部份,以便以后参考
微软组件对象模型 COM 是一个接口标准,它使得不同软件在不知道其他组件代码的规范时,相互之间可以进行调用。分析使用COM 的恶意代码时,你需要判断那段代码会被作为一个COM 函数进行调用。
COM 可以支持任何编程语言,并且被设计成一种可复用的软件组件,并可以被所有程序所利用。COM 使用了一个对象结构,在与面向对象的编程语言中可以很好配合使用,COM 也并不排斥非面向对象的编程语言。
由于COM 如此多能。COM 常被实现成一个酷虎-服务器框架。客户端是那些使用COM 对象的程序,服务器是那些可复用的原件组件——也就是COM对象本身。微软提供了很多COM 对象给程序使用。
使用
每一个使用COM 的线程,必须在调用任何其他COM 库函数之前,至少调用一次OleInitialize
或CoInitializeEx
函数。所以可以以此来判断一个程序是否使用了COM 功能,然而COM 对象繁杂且广泛,知道片段的使用COM 对象代码并没有提供很多消息,因为COM 对象是繁杂且广泛的,你需要进一步找到被使用对象的标识符来继续分析行为。
CLSD、IID,以及COM 对象的使用
COM 对象通过他们的全局唯一标识符(GUID),分为类型标识符(CLSID)以及接口标识符(IID),来进行访问。
CoCreateInstance 函数用来获取对COM 功能的访问。恶意代码使用的一个常用函数是 Navigate,它允许一个程序启动 Internet Explorer,并访问一个 Web 地址。Navigate函数是 IWebBrowser2组件接口的一部分,这个接口制定了一个必须被实现的函数列表,但是它没有指定哪一个程序会提供这个功能。提供这个程序是实现了IWebBrowse2接口的COM类。在多数例子中,IWeBrowser2 接口被 Internet Explorer实现。接口通过一个叫做 IID 的 GUID 来标识,而COM类通过一个叫 CLSID 的 GUID 来标识。
lea eax,[esp+18h+ PointerToComObject]
push eax;PPV
push offset IID_IWebBrowser2;rIID
push 4;dwClsContext
push offset stru_40311c;rCLSID
call CoCreateInstance
这段代码,就是很明显的API 调用,但是为了搞清楚行为,需要知道IID 和CLSID 的结构里面是什么。
IID : D30C1661-CDAF-11D0-8A3E-00C04FC9E26E
CLSID: 0002DF01-0000-0000-C000-000000000046
IID 的值标识这是IWebBrowser2接口,CLSID 的值 是标识 InternetExplorer。
CLSID 代表的含义,可以分别到
HKLM\SOFTWARE\Classes\CLSID
和HKCU\SOFTWARE\Classes\CLSID
查看对应ID键下的值 , 这些值带着标着哪些代码执行这个COM的信息。注意: 在这些ID键下面还会有子健,真正的值存在于子健中
- 子健 若是 LocalServer32 则表示这COM对象被安装作为EXE加载 ;
- 子健 若是 InprocServer32 则表示 这个COM对象被安装作为DLL加载。
IID 标识着一个个功能接口。详情参见https://docs.microsoft.com/en-us/office/client-developer/outlook/mapi/iid
调用一个COM函数
一旦结构体CoCreateInstance调用返回,COM客户端对于这个结构体中某个偏移处的一个函数。代码清单7-12显示了这个调用。对这个COM 对象的引用保存在栈上,然后被移动到EAX中。这个结构体的第一个值指向一个函数指针表。这个前面的代码返回的 结构中的第一个值的0x2c处调用的Navigate函数。
下面的代码调用Navigate函数:
push ecx
push ecx
push ecx
mov esi,eax
mov eax,[esp + 24h +PointerToComObject]
mov edx,[eax]
mov edx,[edx + 2ch]; 2c 偏移量 即是函数指针表 中 Navigate函数
push ecx
push esi
push eax
push eax
call edx
为了标识当恶意代码调用一个COM函数时正在做什么,恶意代码分析师确定一个函数被保存在哪个偏移,这其中需要一些技巧。IDA pro为常用的接口保存了偏移 和结构体,他们通过结构子视图来查看。按INSERT键来添加一个结构,然后单击Add Standard Structure.要添加的结构体名字时InterfaceNameVtbl。在我们的Navigate
扩展:
1 注册一个CLISD 的时候,ThreadModel 的意义?
在COM /ActiveX 编程中,尤其VB 开发者对线程是恐惧的(没有线程这个概念);事实上,没法保证在VB/JS 程序中的线程安全,这些语言没有线程的概念,所以COM开发者需要设计一个架构允许支撑单线程对象托管在多线程程序中。
他们提出了一个解决方案 “apartments”, 本质上每个有COM对象的程序都需要包含一个或多个“apartments”。有两种不同的“apartments”:
Single Threaded Apartments (STAs)
Multi Threaded Apartments(MTAs)
在给定的程序中,可能有多个 STAs 但是 只能有一个 MTAs
(当在一个线程调用CCoInitializeEx(or CoInitialize) ,线程会给出准备好的一种类型。比如: 为了表明该线程应该驻留在MTA中,可以将COINIT_MULTITHREAD标志传递给CoInitializeEx)
COM对象怎么通知以哪种模式呢?
-
当一个 in-proc COM对象注册的时候,创建如下注册表键:
HKCR\CLSID\{<Object class ID>}\InprocServer32
-
InprocServer32 的默认值告诉COM 对象是哪个dll文件托管这个对象,并且通过ThreadingModelvalue 告诉COM对象其
threading model
。这里有4种 合法的threadingmodel值:
-
Apartment
当 COM对象被标识成 “Apartment”模式的时候,意味着这是STA
-
Free
预示着这是 MTA模式
-
Both
this is 一个尝试 用来提供最好的方式
-
Neutral
With COM+ ,COM 增加了 Neutral的概念,“Neutral”threading model 是一个对调用者完全忽略threading model 的模式
-
-