COM

U1S1这玩意学的特别痛苦=。=

经过好几天消化才搞懂了大概

有些地方写错了还请指正。

Component Object Model (COM) Internals

COM是微软的一种开发标准,遵循这种标准开发出来的组件叫做COM组件,无论是什么语言只要遵循这种标准就能调用该组件提供的接口。
COM出现的原因是为了IPC(进程间通信),这种IPC之前就有叫做OLE(Object Linking and Embedding),但这不是最早的,最早的是DDE(Dynamic Data Exchange),因为这种东西比较麻烦并难以理解,所以COM被微软开发出来让其使用更加方便更容易理解。

image-20210201145658375

It bridge the gap between different languages and processes。

所有COM都遵循IUnknown接口标准为了解决Casting Problem

image-20210202003324934

主要有俩个功能,一个是引用计数,因为被不同的语言调用,还有一个是GUID,这是解决Casting Problem,因为GUID都是唯一的,name不是。

image-20210202003928045

image-20210202003952630

注册的组件再注册表中有个CLSID

这边提一下GUID,CLSID,IID,UUID

UUID是一个算法

GUID标志COM组件

CLSID标志类

IID显而易见就是接口了

其实是一个东西的不同表示

image-20210202004402291

image-20210202004417253

这边解释了客户端如何得到接口

dll中导出函数DllGetClassObject,传入Class ID,如果dll知道会返回一个factory object然后就能CoCreateInstanceEx获取接口

STA 一个对象只能由一个线程访问(通过对象的接口指针调用其方法),其他线程不得访问这个对象,因此对于这个对象的所有调用都是同步了的,对象的状态(也就是对象的成员变量的值)肯定是正确变化的,不会出现线程访问冲突而导致对象状态错误。其他线程要访问这个对象,必须等待,直到那个唯一的线程空闲时才能调用对象。

image-20210202005758271

MTA 一个对象可以被多个线程访问,即这个对象的代码在自己的方法中实现了线程保护,保证可以正确改变自己的状态。这对于作为业务逻辑组件或干后台服务的组件非常适合。因为作为一个分布式的服务器,同一时间可能有几千条服务请求到达,如果排队进行调用,那么将是不能想像的。

image-20210202005743114

image-20210202102602291

上图代码可以dump出在你电脑上所有可交互的对象

image-20210202102807305

跨进程时与前面的很像,只不过把windows messaging换成了ALPC Channel

DCOM Activator是用来管理COM对象的初始化

image-20210202103048205

当客户端发送请求想要创建类,他会与System Activator交互

image-20210202103142612

如果需要的话RPCSS会创建新的进程,如果已经存在的话就会直接使用了

image-20210202103347139

image-20210202103359474

接着就会把接口封装后返回然后客户端就能链接

image-20210202103435942

System Activator主要有上面俩个函数一个用来和服务端一个用来和客户端交互

image-20210202104320925

processhacker看句柄表的时候很常见OLE开头的ALPC PORT,这是用来定位COM对象的RPC端口的

image-20210202105129205

image-20210202105135260

上面是类似COM中的DACL

后面有些没有搞懂。。。这边就不写了,过几天深入研究下

COM编写与调用

创建项目

image-20210201151820019

image-20210201151930768

新建项添加ATL简单对象

image-20210201153910686

image-20210201154031617

然后再temp.h中声明函数

image-20210201160333368

接着去cpp中实现

image-20210201160357186

然后定义接口

image-20210201160425102

直接编译,报错不需要管,进文件夹看到dll后管理员权限打开CMD输入以下命令

image-20210201160057792

image-20210201160259922

再打开工具就能看到我们注册的组件了

下面来调用我们的COM组件

首先设置属性允许跨平台语言

image-20210201184050218

接着添加引用,就是之前我们注册的dll

image-20210201184021092

接着确定namespace

查询Com组件命名空间,双击引用中需要的文件打开对象浏览器,点击带{}符号项,得到命名空间Namespace XXX,然后在按钮的点击事件对应代码所在的.cpp源文件中添加命名空间,如下

image-20210201184419769

在对象浏览器查询所需函数所在类名,然后在按钮点击事件对应代码中使用该类生成相应对象,即可调用所需函数。

image-20210201185354061

image-20210201185729445

成功

COM逆向

右击点create instance

image-20210201160741142

接着Operations->Marshal->View Properties

image-20210201160836639

这边已经可以看到pid了

点view,需要配置一下dll路径,这边自行下载SDK

image-20210201160944065

可以看到FUCOM+0x9CC0

image-20210201161156479

逆向开始

image-20210201161233668

还有一些要配合windbg使用因为没有符号

可以windbg附加上然后命令输入

1
dqs FUCOM+0x9CC0

类似这样

image-20210201161419253

把输出放到这,工具会自动帮你“融合”一波放到剪切板

然后就能还原了。

文章目录
  1. 1. Component Object Model (COM) Internals
  2. 2. COM编写与调用
  3. 3. COM逆向
|