日期:
来源:看雪学苑收集编辑:techliu
本文为看雪论坛优秀文章
看雪论坛作者ID:techliu
PS D:\rust\com-inject> .\target\release\com-inject.exe -hcom-inject (1.0) - REInjectA process injection tool via COMCommands:inject Inject special dll or shellcode to target processlist List interface instance in special or all processhelp Print this message or the help of the given subcommand(s)Options:-h, --help Print help-V, --version Print version#############################################################PS D:\rust\com-inject> .\target\release\com-inject.exe inject -hInject special dll or shellcode to target processUsage: com-inject.exe inject [OPTIONS] <PID>Arguments:<PID> Target process idOptions:-m, --method Use CoGetObject instead of CoUnmarshalInterface to establish channel-d, --dll <PATH> Inject DLL into target, specify full path-s, --shellcode <PATH> Inject shellcode into target process-h, --help Print help#############################################################PS D:\rust\com-inject> .\target\release\com-inject.exe list -hList interface instance in special or all processUsage: com-inject.exe list [OPTIONS] [PID]Arguments:[PID] Target process idOptions:-v, --verbose Dispaly all interface, default only IRundown-h, --help Print help
Tips:
DLL 和 Shellcode 文件路径使用绝对路径;
不论是 list 操作还是 inject 操作,都会尝试开启 DEBUG 权限;
避免对同一进程交替进行 DLL 注入和 shellcode 注入或者重复进行 DLL 注入,可能会报错 “被调用的对象已与其客户端断开连接。(0x80010108)”,貌似是多次调用后远程接口会被释放掉;
如果报错 “不支持此接口 (0x80004002)”,就多试几遍;
并不是任何进程都能注入,只能对 list 动作显示出来的进程进行注入
技术原理。
先说一下如何使用 Rust 对 COM 接口调用,调用过程可以分这几个步骤:
接口定义
调用 CoInitializeEx 初始化
调用 CoGetObject 或其他类似 API 获取接口指针
使用接口指针调用接口方法
调用 CoUninitialize 结束
const IIDIID_IRundown = {0x00000134,0x0000,0x0000,{0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};MIDL_INTERFACE("00000134-0000-0000-C000-000000000046")IRundown : public IUnknown {STDMETHOD(RemQueryInterface) ( REFIPID ripid,ULONG cRefs,USHORT cIids,IID *iids,REMQIRESULT **ppQIResults);STDMETHOD(RemAddRef) ( unsigned short cInterfaceRefs,REMINTERFACEREF InterfaceRefs[],HRESULT *pResults);STDMETHOD(RemRelease) ( USHORT cInterfaceRefs,REMINTERFACEREF InterfaceRefs[]);};
| 声明方式 | |
#[repr(transparent)]pub struct IUnknown(std::ptr::NonNull<std::ffi::c_void>);
pub DoCallback: unsafe extern "system" fn(this: *mut ::core::ffi::c_void, pParam: *mut XAptCallback) -> windows::core::HRESULT,#[repr(C)]#[derive(Clone, Copy)]pub struct tagXAptCallback {pub pfnCallback: PTRMEM, // what to execute. e.g. LoadLibraryA, EtwpCreateEtwThreadpub pParam: PTRMEM, // parameter to callback.pub pServerCtx: PTRMEM, // combase!g_pMTAEmptyCtxpub pUnk: PTRMEM, // Not requiredpub iid: windows::core::GUID, // Not requiredpub iMethod: i32, // Not requiredpub guidProcessSecret: windows::core::GUID // combase!CProcessSecret::s_guidOle32Secret}pub type XAptCallback = tagXAptCallback;
0:004> x /D /d combase!*CRemoteUnknown*A B C D E F G H I J K L M N O P Q R S T U V W X Y Z00007fff`637008c8 combase!CRemoteUnknown::`vftable' = <function> *[13]0:004> dx -r1 (*((combase!void (__cdecl*(*)[13])())0x7fff637008c8))(*((combase!void (__cdecl*(*)[13])())0x7fff637008c8)) [Type: void (__cdecl* [13])()][0] : 0x7fff6353e790 : combase!CRemoteUnknown::QueryInterface+0x0 [Type: void (__cdecl*)()][1] : 0x7fff635ae3b0 : [Type: void (__cdecl*)()][2] : 0x7fff635ae3b0 : [Type: void (__cdecl*)()][3] : 0x7fff63520600 : combase!CRemoteUnknown::RemQueryInterface+0x0 [Type: void (__cdecl*)()][4] : 0x7fff6351a390 : combase!CRemoteUnknown::RemAddRef+0x0 [Type: void (__cdecl*)()][5] : 0x7fff6352f2b0 : combase!CRemoteUnknown::RemRelease+0x0 [Type: void (__cdecl*)()][6] : 0x7fff6355ad50 : combase!CRemoteUnknown::RemQueryInterface2+0x0 [Type: void (__cdecl*)()][7] : 0x7fff6355afa0 : combase!CRemoteUnknown::AcknowledgeMarshalingSets+0x0 [Type: void (__cdecl*)()][8] : 0x7fff636765a0 : combase!CRemoteUnknown::RemChangeRef+0x0 [Type: void (__cdecl*)()][9] : 0x7fff6358ee90 : combase!CRemoteUnknown::DoCallback+0x0 [Type: void (__cdecl*)()][10] : 0x7fff6358ee80 : combase!CRemoteUnknown::DoNonreentrantCallback+0x0 [Type: void (__cdecl*)()][11] : 0x7fff634d29b0 : combase!CRemoteUnknown::GetInterfaceNameFromIPID+0x0 [Type: void (__cdecl*)()][12] : 0x7fff6355b140 : combase!CRemoteUnknown::RundownOid+0x0 [Type: void (__cdecl*)()]0:004> u 7fff6358ee90combase!CRemoteUnknown::DoCallback [onecore\com\combase\dcomrem\remoteu.cxx @ 1843]:00007fff`6358ee90 48895c2408 mov qword ptr [rsp+8],rbx00007fff`6358ee95 57 push rdi00007fff`6358ee96 4883ec40 sub rsp,40h00007fff`6358ee9a 0f104234 movups xmm0,xmmword ptr [rdx+34h]00007fff`6358ee9e 488bda mov rbx,rdx00007fff`6358eea1 488d542430 lea rdx,[rsp+30h]00007fff`6358eea6 f30f7f442430 movdqu xmmword ptr [rsp+30h],xmm000007fff`6358eeac e83b000000 call combase!CProcessSecret::VerifyMatchingSecret (00007fff`6358eeec)0:004> bp 7fff6358ee90
if (*cpage)._pgalloc._cPages <= 0 || (*cpage)._pgalloc._cEntries <= 0 {continue;}
let x: Vec<_> = entries.iter().filter(|x| x.ipid.tid > 0x0 && x.ipid.tid < 0xffff).collect();let y: Vec<_> = entries.iter().filter(|x| x.ipid.tid == 0x0).collect();if x.len() > 0 {(*rc).ipid = x[0].ipid;(*rc).oxid = x[0].oxid;(*rc).oid = x[0].oid;} else if y.len() > 0 {(*rc).ipid = y[0].ipid;(*rc).oxid = y[0].oxid;(*rc).oid = y[0].oid;} else {(*rc).ipid = entries[0].ipid;(*rc).oxid = entries[0].oxid;(*rc).oid = entries[0].oid;}
未解决的问题
每次注入都会消耗掉目标进程中的一个接口指针,不确定为什么会自动释放掉,当用完之后就会一直注入失败了;
对于 TID 为 0x0000 或 0xFFFF 时总是注入失败,怎么解决;
通用于 x86 和 x86_64 的 COM 进程。
看雪ID:techliu
https://bbs.kanxue.com/user-home-860174.htm
# 往期推荐
球分享
球点赞
球在看
点击阅读原文查看更多