我已经开始研究COM对象,最初是通过UAC绕过方法来实现的,但是我想我的问题很笼统。普遍的问题是:如何从注册表中的(提升的)CLSID调用COM接口中的函数?接下来说明我进行的研究以及我的具体问题。我将以IFileOperation COM(CLSID = 3AD05575-8857-4850-9277-11B85BDB8E09)和ICMLuaUtil COM(CLSID = 3E5FC7F9-9A51-4367-9063-A120244FBEC7)为例。

COM对象在HKEY_CLASSES_ROOT\CLSID下的注册表中列出。默认值具有COM名称和服务器DLL文件。

现在,为了列出与之关联的接口,我使用了oleview,对于IFileOperation,它显示了所有接口,而对于ICMLuaUtil,它仅显示了。

即使获得接口名称,也必须获得功能列表和签名,可以从idl文件中提取出这些信息。这里给出的一个很好的答案显示了如何通过检查示例代码并搜索与idl文件夹中的导入名称相同的sdk文件,从接口名称转换为其功能签名。我尝试对两个接口应用类似的方法,但部分成功。


对于IFileOperation,示例源中有4个都没有包含与sdk文件夹中的idl文件完全相同的文件。所以我在文件夹中搜索所有文件的内容,以查找单词IFileOperation,从而得到了所需的文件:shobjidl_core
不幸的是,由于我不知道接口名称,我无法对ICMLuaUtil做同样的事情,我尝试了几种名称变化,但一无所获。

我尝试过的其他方法是:


从注册表中找到的DLL中提取所有文件(没有)
COMViewer应该提供其他信息但是即使在兼容模式下,它也无法在Windows 10计算机上运行(无法启动)。

我的问题是如何从(有时是未记录的)COM对象到具体的接口定义,以便可以在代码中使用它? UACMe项目为ICMLuaUtil定义了接口的具体定义,因此必须有一种获取接口的方法。获得这些功能签名的准则和步骤是什么?

评论

嗨,欢迎来到RE.SE!我很困惑。句子之一像一样拖尾。而且,为什么您认为需要接口名称? IID / CLSID / GUID是COM永远关心的全部。一切都从IUnknown开始,文档(MSDN)和几本书都详细解释了如何实例化COM对象。但是,这些都是非RCE主题。是否存在接口定义(IDL或其他)仅取决于作者。毕竟,COM旨在允许黑匣子对象彼此交互。只有主叫方和被叫方才需要知道。

@ 0xC0000022L感谢您抽出宝贵的时间来理解问题。我确实意识到处理COM(CoCreateInstance,CoGetObject ..)的函数仅需要IID / CLSID。对于ICMLuaUtil,让我来缩小问题的范围,在这里我没有接口名称/ IDL文件,如何获得IID以及如何找出方法签名?它已经完成过,我希望学习如何重现结果(github.com/hfiref0x/UACME/blob/…)

@ Anton.P您是否具备C ++类,构造函数,析构函数,继承的基本知识?我想添加一些信息。

@Biswapriyo是的,我熟悉C ++(非常了解C ++,并且熟悉您列出的概念),并且很高兴获得更多信息

#1 楼

现在,不幸的是,这不是从A到Z的完整答案。但是对于COM来说,只有几步真正针对COM。

您链接的项目显然对接口进行了反向工程(elvint.h)。这首先意味着接口的名称不一定与Microsoft所说的名称相匹配(不过,在您的情况下,它们是匹配的)。但是,如果实现相应COM接口或其代理DLL的二进制文件是官方系统文件,则可以为其获取PDB文件,即使Microsoft严重削减了公共符号,这通常仍可以使您为功能/方法。

当然,链接项目的作者已经知道他们在寻找什么,而且似乎是“神奇地”能够以某种方式“神奇地”规避了典型UAC海拔提示的系统组件尽管应该让他们看到一个。

现在说他们发现Connection Manager配置(与RAS相关)包含了这样的功能,他们现在可以继续执行您期望的操作需要高程,但不需要。然后他们将查找加载到进程中的DLL,然后找到一个InProc服务器或将它们引导到OutProc服务器的代理。用于典型的COM导出功能束(最明显的是第一个):


br /> ...,然后检查版本信息资源。使用DllGetClassObject模块,这将成为一个简单的Python脚本工作。基本上,这是RCE始终要做的第一步:情报收集。它不是严格的RCE(例如进行筛选或操作反汇编),但它是我到目前为止完成的所有RCE作业的内在部分。

但是对于您而言,您已经使用过oleview.exe,因此知道了最重要的信息:



...这就是为什么我的评论令人困惑:


不幸的是,我无法使用DllCanUnloadNow做同一件事,因为我不知道接口名称,我尝试了几种名称变体,但没有得到

>

现在发现DllAddRef是实现我们感兴趣的(COM)对象的DLL,我们可以继续将其加载到IDA(或另一个反汇编程序)中,并且将提示您加载调试Microsoft的符号服务器中的符号。

加载符号后,我们将看到以下内容:
要获取IDL,您需要将DllRelease类的vtable与当要求该特定类时DLL返回的接口指针相匹配。查看pefile将使您能够找出IID。

现在从这里开始,这将是理解拆装(或伪代码,如果您能负担得起的话)的旧工作。 decompiler插件)。


现在,如果幸运的话,如果有问题的COM服务器(通常是DLL)包含TYPELIB资源(即已编译的版本),则可以节省大量时间IDL,因此是快速进入IDL的最佳起点。对于ICMLuaUtil,我们很不幸。

此外,如果您没有像Windows组件那样的符号,则必须深入研究从cmlua.dll开始的反汇编,CCMLuaUtil是众所周知的且有据可查,并且即使对于非专业人士而言也应该很容易理解。从那里开始,并具备以下知识:任何COM接口的前三个方法都是从DllGetClassObject继承的,然后您将尝试理解每个方法的实现(除了那些著名的前三个方法)并分配希望有意义的名称功能及其参数。也就是说:如果没有调试符号,整个任务将变得更加乏味,但并非根本不可能。

评论


我什至无法想象有比这个更好的答案。非常感谢。我尝试用IDA加载DLL,实际上在获得符号后我看到了签名。我需要解析,尝试和应用很多信息。谢谢!!

– Anton.P
18年11月23日在11:55

#2 楼

答案很好,这只是演示如何在命令行中使用windbg到达而已

dbh是windbg安装中的实用程序,可以加载任何二进制文件并提供大量静态信息
使用它和windbg cdb.exe的命令行版本可以在两个命令中获得方法(注意,方法名称已取消组合)

C:\>dbh c:\Windows\System32\cmlua.dll  "x CCM*" | grep -i vf
    11            1002d58 :   CCMLuaUtil::`vftable'

C:\>cdb -c "dps cmlua.dll+2d58" -z c:\Windows\System32\cmlua.dll

Microsoft (R) Windows Debugger Version 10.0.16299.15 X86
Loading Dump File [c:\Windows\System32\cmlua.dll]


cmlua!_DllMainCRTStartup:
100061e7 8bff            mov     edi,edi

0:000> cdb: Reading initial command 'dps cmlua.dll+2d58'

10002d58  100042ad cmlua!CCMLuaUtil::QueryInterface
10002d5c  10004e82 cmlua!CCMLuaUtil::AddRef
10002d60  10004279 cmlua!CCMLuaUtil::Release
10002d64  10004346 cmlua!CCMLuaUtil::SetRasCredentials
10002d68  10004401 cmlua!CCMLuaUtil::SetRasEntryProperties
10002d6c  100044dd cmlua!CCMLuaUtil::DeleteRasEntry
10002d70  10004573 cmlua!CCMLuaUtil::LaunchInfSection
10002d74  100045e1 cmlua!CCMLuaUtil::LaunchInfSectionEx
10002d78  10004630 cmlua!CCMLuaUtil::CreateLayerDirectory
10002d7c  1000466e cmlua!CCMLuaUtil::ShellExec
10002d80  10004690 cmlua!CCMLuaUtil::SetRegistryStringValue
10002d84  10004701 cmlua!CCMLuaUtil::DeleteRegistryStringValue
10002d88  100055da cmlua!CCMLuaUtil::DeleteRegKeysWithoutSubKeys
10002d8c  10004767 cmlua!CCMLuaUtil::DeleteRegTree
10002d90  100048cc cmlua!CCMLuaUtil::ExitWindowsFunc
10002d94  10005c72 cmlua!CCMLuaUtil::AllowAccessToTheWorld
10002d98  100048d9 cmlua!CCMLuaUtil::CreateFileAndClose
10002d9c  1000560f cmlua!CCMLuaUtil::DeleteHiddenCmProfileFiles
10002da0  1000492a cmlua!CCMLuaUtil::CallCustomActionDll
10002da4  10004b6c cmlua!CCMLuaUtil::RunCustomActionExe
10002da8  10004c2c cmlua!CCMLuaUtil::SetRasSubEntryProperties
10002dac  10004d0e cmlua!CCMLuaUtil::DeleteRasSubEntry
10002db0  10004da7 cmlua!CCMLuaUtil::SetCustomAuthData
10002db4  10005cdb cmlua!CCMLuaUtil::`vector deleting destructor'
10002db8  00000000
10002dbc  10009138 cmlua!hProxyDll+0x10
10002dc0  10009188 cmlua!hProxyDll+0x60
10002dc4  00000000
10002dc8  69727453
10002dcc  6343676e
10002dd0  706f4368
10002dd4  20784579
0:000>

dbh有一个-d开关,它将输出错误的名称,并且您可以利用该开关将参数打印到方法上

C:\>echo off

for /F %i in ('dbh -d c:\Windows\System32\cmlua.dll  "x *CCM*"  ^| awk "{print }"') do  dbh c:\windows\system32\cmlua.
dll undec %i

?Release@CCMLuaUtil@@UAGKXZ =
public: virtual unsigned long __stdcall CCMLuaUtil::Release(void)

??_ECCMLuaUtil@@UAEPAXI@Z =
public: virtual void * __thiscall CCMLuaUtil::`vector deleting destructor'(unsigned int)

??0CCMLuaUtil@@QAE@XZ =
public: __thiscall CCMLuaUtil::CCMLuaUtil(void)

?AddRef@CCMLuaUtil@@UAGKXZ =
public: virtual unsigned long __stdcall CCMLuaUtil::AddRef(void)

?CreateFileAndClose@CCMLuaUtil@@UAGJPBGKKKK@Z =
public: virtual long __stdcall CCMLuaUtil::CreateFileAndClose(unsigned short const *,unsigned long,unsigned long,unsigne
d long,unsigned long)

?DeleteHiddenCmProfileFiles@CCMLuaUtil@@UAGJPBG@Z =
public: virtual long __stdcall CCMLuaUtil::DeleteHiddenCmProfileFiles(unsigned short const *)

??_GCCMLuaUtil@@UAEPAXI@Z =
public: virtual void * __thiscall CCMLuaUtil::`scalar deleting destructor'(unsigned int)

?SetRasSubEntryProperties@CCMLuaUtil@@UAGJPBG0KPAPAGK@Z =
public: virtual long __stdcall CCMLuaUtil::SetRasSubEntryProperties(unsigned short const *,unsigned short const *,unsign
ed long,unsigned short * *,unsigned long)

?QueryInterface@CCMLuaUtil@@UAGJABU_GUID@@PAPAX@Z =
public: virtual long __stdcall CCMLuaUtil::QueryInterface(struct _GUID const &,void * *)

?CCMLuaUtil_CreateInstance@@YGJABU_GUID@@PAPAX@Z =
long __stdcall CCMLuaUtil_CreateInstance(struct _GUID const &,void * *)

?ExitWindowsFunc@CCMLuaUtil@@UAGJXZ =
public: virtual long __stdcall CCMLuaUtil::ExitWindowsFunc(void)

?CreateLayerDirectory@CCMLuaUtil@@UAGJPBG@Z =
public: virtual long __stdcall CCMLuaUtil::CreateLayerDirectory(unsigned short const *)

?LaunchInfSectionEx@CCMLuaUtil@@UAGJPBG0K@Z =
public: virtual long __stdcall CCMLuaUtil::LaunchInfSectionEx(unsigned short const *,unsigned short const *,unsigned lon
g)

?ShellExec@CCMLuaUtil@@UAGJPBG00KK@Z =
public: virtual long __stdcall CCMLuaUtil::ShellExec(unsigned short const *,unsigned short const *,unsigned short const
*,unsigned long,unsigned long)

?DeleteRasEntry@CCMLuaUtil@@UAGJPBG0@Z =
public: virtual long __stdcall CCMLuaUtil::DeleteRasEntry(unsigned short const *,unsigned short const *)

?DeleteRegistryStringValue@CCMLuaUtil@@UAGJHPBG0@Z =
public: virtual long __stdcall CCMLuaUtil::DeleteRegistryStringValue(int,unsigned short const *,unsigned short const *)

??_7CCMLuaUtil@@6B@ =
const CCMLuaUtil::`vftable'

?LaunchInfSection@CCMLuaUtil@@UAGJPBG00H@Z =
public: virtual long __stdcall CCMLuaUtil::LaunchInfSection(unsigned short const *,unsigned short const *,unsigned short
 const *,int)

?SetCustomAuthData@CCMLuaUtil@@UAGJPBG00K@Z =
public: virtual long __stdcall CCMLuaUtil::SetCustomAuthData(unsigned short const *,unsigned short const *,unsigned shor
t const *,unsigned long)

?DeleteRasSubEntry@CCMLuaUtil@@UAGJPBG0K@Z =
public: virtual long __stdcall CCMLuaUtil::DeleteRasSubEntry(unsigned short const *,unsigned short const *,unsigned long
)

?DeleteRegTree@CCMLuaUtil@@UAGJHPBG@Z =
public: virtual long __stdcall CCMLuaUtil::DeleteRegTree(int,unsigned short const *)

?DeleteRegKeysWithoutSubKeys@CCMLuaUtil@@UAGJHPBGH@Z =
public: virtual long __stdcall CCMLuaUtil::DeleteRegKeysWithoutSubKeys(int,unsigned short const *,int)

?CallCustomActionDll@CCMLuaUtil@@UAGJPBG000PAK@Z =
public: virtual long __stdcall CCMLuaUtil::CallCustomActionDll(unsigned short const *,unsigned short const *,unsigned sh
ort const *,unsigned short const *,unsigned long *)

?SetRegistryStringValue@CCMLuaUtil@@UAGJHPBG00@Z =
public: virtual long __stdcall CCMLuaUtil::SetRegistryStringValue(int,unsigned short const *,unsigned short const *,unsi
gned short const *)

?SetRasCredentials@CCMLuaUtil@@UAGJPBG00H@Z =
public: virtual long __stdcall CCMLuaUtil::SetRasCredentials(unsigned short const *,unsigned short const *,unsigned shor
t const *,int)

?SetRasEntryProperties@CCMLuaUtil@@UAGJPBG0PAPAGK@Z =
public: virtual long __stdcall CCMLuaUtil::SetRasEntryProperties(unsigned short const *,unsigned short const *,unsigned
short * *,unsigned long)

?AllowAccessToTheWorld@CCMLuaUtil@@UAGJPBG@Z =
public: virtual long __stdcall CCMLuaUtil::AllowAccessToTheWorld(unsigned short const *)

?RunCustomActionExe@CCMLuaUtil@@UAGJPBG0PAPAG@Z =
public: virtual long __stdcall CCMLuaUtil::RunCustomActionExe(unsigned short const *,unsigned short const *,unsigned sho
rt * *)


#3 楼

这只是@ 0xC0000022L答案的扩展。对于这个问题,我将在下面解释ICMLuaUtil COM接口,因为IFileOperation COM接口在shell32.dll中,太大;)

您提到了错误的CLSID。在这里,我提供了它们的列表:



GUID CLSID_CmstpLua = {3E5FC7F9-9A51-4367-9063-A120244FBEC7}
GUID IID_ICmstpLua = {6EF07F29-F9B8-4DA4-B59E-13DEA060AD60}
GUID IID_ICmstpLua2 = {AE8AFD54-5B57-4961-8A9B-12ADF23B696A}

GUID CLSID_CMLuaUtil = {3E000D72-A845-4CD9-BD83-80C07C3B881F}
GUID IID_ICMLuaUtil = {6EDD6D74-C007-4E75-B76A-E5740995E24C}




如何从CLSID查找DLL文件路径不使用任何第三方程序?在RegEdit中打开此注册表路径HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{CLSID}。对于这种情况,请尝试以下命令:



REG Query "HKLM\SOFTWARE\Classes\CLSID\{3E000D72-A845-4CD9-BD83-80C07C3B881F}\InprocServer32" /VE
REG Query "HKLM\SOFTWARE\Classes\Interface\{6EDD6D74-C007-4E75-B76A-E5740995E24C}" /VE




路径为%SystemRoot%\System32\cmlua.dll。在IDA(或任何反汇编程序/反编译器)中将其打开,然后加载PDB符号文件。使用Shift + F3转到函数窗口,然后在该窗口中键入这些单词来搜索构造函数或析构函数。在装配视图中打开该功能。必须有一个像const CCMLuaUtil::vftable这样的变量,因为您知道为什么。双击它,您将在程序集视图中看到该COM类的布局。



组装视图有很多优点。在程序集视图中,该类中的所有方法均按实际顺序放置,但功能窗口可能未放置(根据设置)。这些方法实际上是作为函数指针放置的。对于64位二进制文​​件,在每种方法之前(在上面的屏幕截图中),将存在dq(qword 8字节)。前三个方法是从IUnknown接口继承的。如果要用C编写该类(作为结构体),则必须包括这三个类。可以在我的GitHub仓库WslReverse中看到这种方法的真实示例,在其中显示了LxssManager.DLL的隐藏COM接口。也是有关实用C ++反编译的视频|侦察2011 |伊戈尔·斯科钦斯基(Igor Skochinsky)对我有很大帮助。

评论


对于额外的信息,我当然也会介绍,但是我有一个初步的问题,您如何知道哪个接口与哪个CLSID相关?在oleview中,CMLuaUtil没有任何与之关联的接口

– Anton.P
18年11月26日在12:04

我的问题是,您如何理解IID_ICMLuaUtil与CLSID_CMLuaUtil相关? (当然不是必须的名称,例如在IFileOperation COM中,某些受支持的接口不共享其名称)。这些命令确实揭示了DLL,但我无法理解完善它们之间链接的一般方法。

– Anton.P
18年11月26日在18:20

@ Anton.P这可能是过于简化的答案:i.stack.imgur.com/ZpIRF.png

– Biswapriyo
18年11月26日在18:40