-
Notifications
You must be signed in to change notification settings - Fork 54
Expand file tree
/
Copy pathComUtils.cpp
More file actions
154 lines (134 loc) · 5.38 KB
/
ComUtils.cpp
File metadata and controls
154 lines (134 loc) · 5.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include "ComUtils.h"
void ComUtils::InitAuthStructs(COAUTHIDENTITY* pAuthId, COAUTHINFO* pAuthInfo, std::wstring& w_domain, std::wstring& w_username, std::wstring& w_password)
{
if (!w_domain.empty()) {
pAuthId->Domain = (unsigned short*)w_domain.c_str();
pAuthId->DomainLength = wcslen(w_domain.c_str());
}
if (!w_password.empty()) {
pAuthId->Password = (unsigned short*)w_password.c_str();
pAuthId->PasswordLength = wcslen(w_password.c_str());
}
if (!w_username.empty()) {
pAuthId->User = (unsigned short*)w_username.c_str();
pAuthId->UserLength = wcslen(w_username.c_str());
}
pAuthInfo->dwAuthnLevel = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY ;
pAuthInfo->dwAuthnSvc = RPC_C_AUTHN_WINNT;
pAuthInfo->dwAuthzSvc = RPC_C_AUTHZ_NONE;
pAuthInfo->dwCapabilities = EOAC_NONE;
pAuthInfo->dwImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE;
// setup identity details if existing
if (!w_username.empty() || !w_password.empty() || !w_domain.empty())
{
pAuthId->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
pAuthInfo->pAuthIdentityData = pAuthId;
}
else
{
pAuthInfo->pAuthIdentityData = nullptr;
}
}
IUnknown* ComUtils::CreateObject(CLSID clsid, IID iid, DWORD ctx, std::wstring& w_address, COAUTHINFO* pAuthInfo)
{
HRESULT hr = NULL;
// Initialize COM
if(!gComInited)
{
hr = CoInitialize(NULL);
if(FAILED(hr))
{
std::cout << "[-] Failed CoInitialize: " << std::hex << hr << '\n';
return nullptr;
}
}
COSERVERINFO coserverinfo = {};
// setup network info if we are directed to a remote address
if (!w_address.empty())
coserverinfo.pwszName = w_address.data();
coserverinfo.pAuthInfo = pAuthInfo;
MULTI_QI qi ={};
qi.pIID = &iid; // the interface we aim to get
qi.pItf = NULL;
qi.hr = 0;
SOLE_AUTHENTICATION_INFO sni = {};
sni.dwAuthnSvc = pAuthInfo->dwAuthnSvc;
sni.dwAuthzSvc = pAuthInfo->dwAuthzSvc;
sni.pAuthInfo = pAuthInfo->pAuthIdentityData;
SOLE_AUTHENTICATION_LIST sal = {};
sal.cAuthInfo = 1;
sal.aAuthInfo = &sni;
// initialize security
hr = CoInitializeSecurity(nullptr, -1, NULL, NULL, pAuthInfo->dwAuthnLevel, pAuthInfo->dwImpersonationLevel, &sal, EOAC_NONE, NULL);
if (FAILED(hr)) {
std::cout << "[-] Failed CoInitializeSecurity: " << std::hex << hr << '\n';
return nullptr;
}
hr = CoCreateInstanceEx(clsid, NULL, ctx, &coserverinfo, 1, &qi);
if (FAILED(hr)) {
std::cout << "[-] Failed CoCreateInstanceEx: " << std::hex << hr << '\n';
}
return qi.pItf;
}
IUnknown* ComUtils::CreateObjectFromDllFactory(HMODULE hdll, CLSID clsidFactory)
{
IClassFactory* fact;
IUnknown* requestedObject = nullptr;
DllGetClassObjectFunc DllGetClassObject = (DllGetClassObjectFunc)GetProcAddress(hdll, "DllGetClassObject");
if(!DllGetClassObject)
{
std::cout << "[-] Failed locating DllGetClassObject on hdll: " << std::hex << GetLastError() << '\n';
return nullptr;
}
HRESULT hr = DllGetClassObject(clsidFactory, IID_IClassFactory, (PVOID*)&fact);
if(FAILED(hr))
{
std::cout << "[-] Failed DllGetClassObject on hdll: " << std::hex << GetLastError() << '\n';
return nullptr;
}
hr = fact->CreateInstance(NULL, clsidFactory, (PVOID*)&requestedObject);
if (FAILED(hr))
{
std::cout << "[-] Failed CreateInstance on hdll: " << std::hex << GetLastError() << '\n';
}
return requestedObject;
}
HRESULT ComUtils::SetupInterfaceAuth(IUnknown* iface, COAUTHINFO* pAuthInfo)
{
OLECHAR* pServerPrincName = nullptr;
std::wstring principleName;
if (pAuthInfo->pAuthIdentityData)
{
principleName = std::format(L"{}\\{}", (WCHAR*)pAuthInfo->pAuthIdentityData->Domain, (WCHAR*)pAuthInfo->pAuthIdentityData->User);
pServerPrincName = principleName.data();
}
HRESULT hr = CoSetProxyBlanket(iface, pAuthInfo->dwAuthnSvc, pAuthInfo->dwAuthzSvc, pServerPrincName, pAuthInfo->dwAuthnLevel,
pAuthInfo->dwImpersonationLevel, pAuthInfo->pAuthIdentityData, EOAC_DEFAULT);
if (FAILED(hr)) {
std::cout << "[-] Failed CoSetProxyBlanket: " << std::hex << hr << '\n';
}
return hr;
}
/*
* Setup auth on interfaces the correct way. We must apply auth to the underlying IID_IUnknown
* else QueryInterface will fail with access denied when attempting to query the derived interface.
* read more: "https://learn.microsoft.com/en-us/windows/win32/wmisdk/setting-authentication-using-c-"
*/
HRESULT ComUtils::SetupAuthOnParentIUnknownCastToIID(IUnknown* pAnyIface, COAUTHINFO* pAuthInfo, IUnknown** ppCastedOutput, const IID& riid)
{
IUnknown* pUnknown = nullptr;
SetupInterfaceAuth(pAnyIface, pAuthInfo);
HRESULT hr = pAnyIface->QueryInterface(IID_IUnknown, reinterpret_cast<void**>(&pUnknown));
if (FAILED(hr)) {
pAnyIface->Release();
std::cout << "[-] Failed QueryInterface to underlying IUnknown: " << std::hex << hr << '\n';
}
SetupInterfaceAuth(pUnknown, pAuthInfo);
hr = pUnknown->QueryInterface(riid, reinterpret_cast<void**>(ppCastedOutput));
if (FAILED(hr)) {
pUnknown->Release();
pAnyIface->Release();
std::cout << "[-] Failed QueryInterface to cast back from IUnknown: " << std::hex << hr << '\n';
}
return SetupInterfaceAuth(*ppCastedOutput, pAuthInfo);
}