TA的每日心情 | 奋斗 2023-6-30 13:23 |
|---|
签到天数: 105 天 [LV.6]常住居民II
|
COMPROCESSINJECTIONRUST[url]http://www.yxfzedu.com/网络验证[/url]的相关知识也可以到网站具体了解一下,有专业的客服人员为您全面解读,相信会有一个好的合作![align=center]http://resources.yxfzedu.com/images/other_images/jing_video.png[/align]
项目地址:
PICOM(COM)IR::DC()
该技术由挖掘发现,在我对该技术进行深入研究过程中,将原项目使用了R重写,希望对使用R的安全人员在COM接口调用、进程注入等方面有所帮助。
对于此项注入技术原理的更保真的解释,还请参考,这里只记录一下工具用法和过程中遇到的一些问题和想法。
使用方法
1
2
3
4
5
6
7
8
9
PSD:\\
-
\\\
-
-
-
(
)
-
REI
ACOM
C:
I
L
P
()
O:
-
,
-
-
P
-
V,
-
-
P
#############################################################
PSD:\\
-
\\\
-
-
I
U:
-
[OPTIONS]PID
A:
PIDT
O:
-
,
-
-
UCGOCUI
-
,
-
-
PATHIDLL,
-
,
-
-
PATHI
-
,
-
-
P
#############################################################
PSD:\\
-
\\\
-
-
L
U:
-
[OPTIONS][PID]
A:
[PID]T
O:
-
,
-
-
D
,IR
-
,
-
-
P
T:
DLL和S文件路径使用绝对路径
不论是操作还是操作,都会尝试开启DEBUG权限
避免对同一进程交替进行DLL注入和注入或者重复进行DLL注入,可能会报错“被调用的对象已与其客户端断开连接。(0)”,貌似是多次调用后远程接口会被释放掉
如果报错“不支持此接口(000)”,就多试几遍
并不是任何进程都能注入,只能对动作显示出来的进程进行注入技术原理
先说一下如何使用R对COM接口调用,调用过程可以分这几个步骤:
接口定义
调用CIE初始化
调用CGO或其他类似API获取接口指针
使用接口指针调用接口方法
调用CU结束
重点在接口定义,后面几步都是API调用,对于一些有文档记录的接口一般都有对应的头文件或IDL,直接用就行,但是对于其他COM接口,调用之前先要定义一个包含方法虚表的结构体接口,这个虚表的内存偏移、方法顺序需要保证和接口现一致,后面拿到接口指针才能正确调用对应的方法,++里的接口定义示例:
1
2
3
4
5
6
7
8
9
IID
IID_IR
=
{
000
,
00000
,
00000
,
{
0C0
,
000
,
000
,
000
,
000
,
000
,
000
,
6
}};
MIDL_INTERFACE(
"00-0000-0000-C000-00000000"
)
IR:IU{
STDMETHOD(RQI)(REFIPID,
ULONGR,
USHORTI,
IID
*
,
REMQIRESULT
*
*
QIR);
STDMETHOD(RAR)(IR,
REMINTERFACEREFIR[],
HRESULT
*
R);
STDMETHOD(RR)(USHORTIR,
REMINTERFACEREFIR[]);
};
所有COM接口的祖先就是IU,大部分接口直接继承自IU,还有部分通过继承ID或其他接口间接的继承自IU。继承在内存布局上际上就是在父类的内存结构基础上进行新增,所以不继承直接将IU中的方法搬过来也行。
由于R里面接口、类全部都以的形式表达,并且和C++中的内存布局是有区别的,所以在定义接口虚表时,全部需要加上#[(C)],代表该结构体内存布局和C完全一致。C里面有IU,R里也不需要我们从IU开始现,际上在-和这两个中都有现,但是现方式上有所不同。主要体现在对“接口指针”的定义上,下面是使用C、、-各自如何声明一个接口指针变量:
声明方式
C
IU*=NULL;
:*IU=::_();
-
:IU;
可以看出来的接口定义方式更符合的接口调用风格,而-从声明上则看不出来是一个指针,指针被隐藏在了内部:
1
2
#[()]
IU(::::NN::::_);
可以理解为透传,相当于:IU=::::NN::::_,所以:IU等价于:::::NN::::_,这样才能看出来是个指针了。
对于这块暂时解释到这里,想更进一步理解具体怎么用R定义一个接口的话,可以借鉴我代码里对IR接口的现方式。
接下来理解COM接口方法的调用过程,COM际上可以理解为RPC的一种上层现,所以还是RPC,调用接口的程序称为客户端,真正处理执行调用请求的称为服务端。之前列出的调用过程步骤中的第3步,使用CGO、CCI、CGOC这些API获取接口指针,如果获取成功就相当于和服务端连接成功,当通过指针调用方法后,相当于发起一个请求到服务端了。
1
DC:
""
(:
*
::::::_,P:
*
XAC)
-
::::HRESULT,
XAC参数设置回调地址和参数地址:
1
2
3
4
5
6
7
8
9
#[(C)]
#[(C,C)]
XAC{
C:PTRMEM,
LLA,ECET
P:PTRMEM,
SC:PTRMEM,
!_MTAEC
U:PTRMEM,
N
:::::GUID,
N
M:32,
N
PS:::::GUID
!CPS::_O32S
}
XAC
=
XAC;
C为回调函数指针,P为参数指针。加上之前说的CS架构,接口调用请求际上是在服务端处理的,所以当服务端进程接收到执行回调的请求后,触发回调执行完成代码注入。
大致的技术利用原理就这些,其他的都是一些细节问题,比如如何获取到该接口指针、如何注入到任意进程中去,这两个际上是一个问题,前面说过成功获取接口指针即是连接到目标进程,所以对于此类问题的根本是“哪些进程属于这个接口的服务进程”。
好像目前仅有好用的查看COM进程信息的工具就是了,需要提前使用或者其他调试器把的符号下载到本地,然后配置到OVDN里,否则是查不到任何结果的:
然后在P-AP-BN打开COM进程列表,搜索IR:
相当于执行--。
这些进程中存在IR接口指针,由于IR接口的现者是,所以加载的进程都有可能。
里面可以直接按下面的方式找IR接口虚表:
1
2
3
4
5
6
7
8
9
0
:
0
D
!
*
CRU
*
ABCDEFGHIJKLMNOPQRSTUVWXYZ
000
`
637
!CRU::`'
=
*
[
]
0
:
0
-
1(
*
((!(__
*
(
*
)[
])())
637
))
(
*
((!(__
*
(
*
)[
])())
637
))[
T
:(__
*
[
])()]
[
0
]:
6353790
:!CRU::QI
+
00
[
T
:(__
*
)()]
[
1
]:
635
:[
T
:(__
*
)()]
[
2
]:
635
:[
T
:(__
*
)()]
[
3
]:
6350
:!CRU::RQI
+
00
[
T
:(__
*
)()]
[
4
]:
63590
:!CRU::RAR
+
00
[
T
:(__
*
)()]
[
5
]:
6352
:!CRU::RR
+
00
[
T
:(__
*
)()]
[
6
]:
635550
:!CRU::RQI2
+
00
[
T
:(__
*
)()]
[
7
]:
63550
:!CRU::AMS
+
00
[
T
:(__
*
)()]
[
8
]:
6367650
:!CRU::RCR
+
00
[
T
:(__
*
)()]
[
9
]:
635890
:!CRU::DC
+
00
[
T
:(__
*
)()]
[
]:
635880
:!CRU::DNC
+
00
[
T
:(__
*
)()]
[
]:
6340
:!CRU::GINFIPID
+
00
[
T
:(__
*
)()]
[
]:
63550
:!CRU::RO
+
00
[
T
:(__
*
)()]
0
:
0
7635890
!CRU::DC[\\\\@
43
]:
000
`
635890
48895
[
+
8
],
000
`
635895
57
000
`
635896
488340
,
40
000
`
63589
4
0,[
+
34
]
000
`
63589
488
,
000
`
63581
48854
,[
+
]
000
`
63586
344[
+
],0
000
`
6358
800000!CPS::VMS(
000
`
6358
)
0
:
0
7635890
其他细节或者挖掘思路直接看一下大佬的文章解惑吧。
已经解决的问题
原项目运行后可能会遇到一些问题,在重写时简单处理了一下,问题如下:
A、在获取目标进程IPID列表偏移时,判断条件不够导致后续步骤访问到错误地址导致崩溃
我在__中加了些条件,然后就没遇到过着个问题了:
1
2
3
(
*
)__P
=
0
||(
*
)__E
=
0
{
;
}
B、原项目默认取首个IPID进行交互,但是首个IPID对应的TID可能是00000或0FFFF,导致回调失败
IPID是一个GUID,是对接口指针的标识,具有一定的格式:----,的位置代表进程PID,的位置代表线程TID,如果线程ID效会导致获取的不正确,比较后虽然这个接口指针的状态虽然不是IPIDF_DISCONNECTED,但是比较终调用DC时依然返回错误:“被调用的对象已与其客户端断开连接。(0)”。
所以我在获取接口指针时,加了些过滤,先使用TID有效的IPID:
1
2
3
4
5
6
7
8
9
:V_
=
()
(||
00
0
)();
:V_
=
()
(||
=
=
00
)();
()
0
{
(
*
)
=
[
0
];
(
*
)
=
[
0
];
(
*
)
=
[
0
];
}
()
0
{
(
*
)
=
[
0
];
(
*
)
=
[
0
];
(
*
)
=
[
0
];
}
{
(
*
)
=
[
0
];
(
*
)
=
[
0
];
(
*
)
=
[
0
];
}
未解决的问题
每次注入都会消耗掉目标进程中的一个接口指针,不确定为什么会自动释放掉,当用完之后就会一直注入失败了
对于TID为00000或0FFFF时总是注入失败,怎么解决
通用于86和86_64的COM进程 |
|