├── .gitignore
├── ConsoleApp1
├── App.config
├── AssemblyLoader.csproj
├── Program.cs
└── Properties
│ └── AssemblyInfo.cs
├── DemoAssembly
├── DemoAssembly.csproj
├── DemoClass.cs
└── Properties
│ └── AssemblyInfo.cs
├── DotNetGargoyle.sln
├── EnumerateDotNetTimers
├── App.config
├── EnumerateDotNetTimers.csproj
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
├── Timers.cs
└── packages.config
├── NativeDll
├── NativeDll.vcxproj
├── NativeDll.vcxproj.filters
└── dll.cpp
├── NativeMainApp
├── NativeMainApp.cpp
├── NativeMainApp.vcxproj
├── NativeMainApp.vcxproj.filters
├── stdafx.cpp
├── stdafx.h
└── targetver.h
└── README.md
/.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/master/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 | # Build results
17 | [Dd]ebug/
18 | [Dd]ebugPublic/
19 | [Rr]elease/
20 | [Rr]eleases/
21 | x64/
22 | x86/
23 | [Aa][Rr][Mm]/
24 | [Aa][Rr][Mm]64/
25 | bld/
26 | [Bb]in/
27 | [Oo]bj/
28 | [Ll]og/
29 |
30 | # Visual Studio 2015/2017 cache/options directory
31 | .vs/
32 | # Uncomment if you have tasks that create the project's static files in wwwroot
33 | #wwwroot/
34 |
35 | # Visual Studio 2017 auto generated files
36 | Generated\ Files/
37 |
38 | # MSTest test Results
39 | [Tt]est[Rr]esult*/
40 | [Bb]uild[Ll]og.*
41 |
42 | # NUNIT
43 | *.VisualState.xml
44 | TestResult.xml
45 |
46 | # Build Results of an ATL Project
47 | [Dd]ebugPS/
48 | [Rr]eleasePS/
49 | dlldata.c
50 |
51 | # Benchmark Results
52 | BenchmarkDotNet.Artifacts/
53 |
54 | # .NET Core
55 | project.lock.json
56 | project.fragment.lock.json
57 | artifacts/
58 |
59 | # StyleCop
60 | StyleCopReport.xml
61 |
62 | # Files built by Visual Studio
63 | *_i.c
64 | *_p.c
65 | *_h.h
66 | *.ilk
67 | *.meta
68 | *.obj
69 | *.iobj
70 | *.pch
71 | *.pdb
72 | *.ipdb
73 | *.pgc
74 | *.pgd
75 | *.rsp
76 | *.sbr
77 | *.tlb
78 | *.tli
79 | *.tlh
80 | *.tmp
81 | *.tmp_proj
82 | *_wpftmp.csproj
83 | *.log
84 | *.vspscc
85 | *.vssscc
86 | .builds
87 | *.pidb
88 | *.svclog
89 | *.scc
90 |
91 | # Chutzpah Test files
92 | _Chutzpah*
93 |
94 | # Visual C++ cache files
95 | ipch/
96 | *.aps
97 | *.ncb
98 | *.opendb
99 | *.opensdf
100 | *.sdf
101 | *.cachefile
102 | *.VC.db
103 | *.VC.VC.opendb
104 |
105 | # Visual Studio profiler
106 | *.psess
107 | *.vsp
108 | *.vspx
109 | *.sap
110 |
111 | # Visual Studio Trace Files
112 | *.e2e
113 |
114 | # TFS 2012 Local Workspace
115 | $tf/
116 |
117 | # Guidance Automation Toolkit
118 | *.gpState
119 |
120 | # ReSharper is a .NET coding add-in
121 | _ReSharper*/
122 | *.[Rr]e[Ss]harper
123 | *.DotSettings.user
124 |
125 | # JustCode is a .NET coding add-in
126 | .JustCode
127 |
128 | # TeamCity is a build add-in
129 | _TeamCity*
130 |
131 | # DotCover is a Code Coverage Tool
132 | *.dotCover
133 |
134 | # AxoCover is a Code Coverage Tool
135 | .axoCover/*
136 | !.axoCover/settings.json
137 |
138 | # Visual Studio code coverage results
139 | *.coverage
140 | *.coveragexml
141 |
142 | # NCrunch
143 | _NCrunch_*
144 | .*crunch*.local.xml
145 | nCrunchTemp_*
146 |
147 | # MightyMoose
148 | *.mm.*
149 | AutoTest.Net/
150 |
151 | # Web workbench (sass)
152 | .sass-cache/
153 |
154 | # Installshield output folder
155 | [Ee]xpress/
156 |
157 | # DocProject is a documentation generator add-in
158 | DocProject/buildhelp/
159 | DocProject/Help/*.HxT
160 | DocProject/Help/*.HxC
161 | DocProject/Help/*.hhc
162 | DocProject/Help/*.hhk
163 | DocProject/Help/*.hhp
164 | DocProject/Help/Html2
165 | DocProject/Help/html
166 |
167 | # Click-Once directory
168 | publish/
169 |
170 | # Publish Web Output
171 | *.[Pp]ublish.xml
172 | *.azurePubxml
173 | # Note: Comment the next line if you want to checkin your web deploy settings,
174 | # but database connection strings (with potential passwords) will be unencrypted
175 | *.pubxml
176 | *.publishproj
177 |
178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
179 | # checkin your Azure Web App publish settings, but sensitive information contained
180 | # in these scripts will be unencrypted
181 | PublishScripts/
182 |
183 | # NuGet Packages
184 | *.nupkg
185 | # The packages folder can be ignored because of Package Restore
186 | **/[Pp]ackages/*
187 | # except build/, which is used as an MSBuild target.
188 | !**/[Pp]ackages/build/
189 | # Uncomment if necessary however generally it will be regenerated when needed
190 | #!**/[Pp]ackages/repositories.config
191 | # NuGet v3's project.json files produces more ignorable files
192 | *.nuget.props
193 | *.nuget.targets
194 |
195 | # Microsoft Azure Build Output
196 | csx/
197 | *.build.csdef
198 |
199 | # Microsoft Azure Emulator
200 | ecf/
201 | rcf/
202 |
203 | # Windows Store app package directories and files
204 | AppPackages/
205 | BundleArtifacts/
206 | Package.StoreAssociation.xml
207 | _pkginfo.txt
208 | *.appx
209 |
210 | # Visual Studio cache files
211 | # files ending in .cache can be ignored
212 | *.[Cc]ache
213 | # but keep track of directories ending in .cache
214 | !*.[Cc]ache/
215 |
216 | # Others
217 | ClientBin/
218 | ~$*
219 | *~
220 | *.dbmdl
221 | *.dbproj.schemaview
222 | *.jfm
223 | *.pfx
224 | *.publishsettings
225 | orleans.codegen.cs
226 |
227 | # Including strong name files can present a security risk
228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
229 | #*.snk
230 |
231 | # Since there are multiple workflows, uncomment next line to ignore bower_components
232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
233 | #bower_components/
234 | # ASP.NET Core default setup: bower directory is configured as wwwroot/lib/ and bower restore is true
235 | **/wwwroot/lib/
236 |
237 | # RIA/Silverlight projects
238 | Generated_Code/
239 |
240 | # Backup & report files from converting an old project file
241 | # to a newer Visual Studio version. Backup files are not needed,
242 | # because we have git ;-)
243 | _UpgradeReport_Files/
244 | Backup*/
245 | UpgradeLog*.XML
246 | UpgradeLog*.htm
247 | ServiceFabricBackup/
248 | *.rptproj.bak
249 |
250 | # SQL Server files
251 | *.mdf
252 | *.ldf
253 | *.ndf
254 |
255 | # Business Intelligence projects
256 | *.rdl.data
257 | *.bim.layout
258 | *.bim_*.settings
259 | *.rptproj.rsuser
260 |
261 | # Microsoft Fakes
262 | FakesAssemblies/
263 |
264 | # GhostDoc plugin setting file
265 | *.GhostDoc.xml
266 |
267 | # Node.js Tools for Visual Studio
268 | .ntvs_analysis.dat
269 | node_modules/
270 |
271 | # Visual Studio 6 build log
272 | *.plg
273 |
274 | # Visual Studio 6 workspace options file
275 | *.opt
276 |
277 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
278 | *.vbw
279 |
280 | # Visual Studio LightSwitch build output
281 | **/*.HTMLClient/GeneratedArtifacts
282 | **/*.DesktopClient/GeneratedArtifacts
283 | **/*.DesktopClient/ModelManifest.xml
284 | **/*.Server/GeneratedArtifacts
285 | **/*.Server/ModelManifest.xml
286 | _Pvt_Extensions
287 |
288 | # Paket dependency manager
289 | .paket/paket.exe
290 | paket-files/
291 |
292 | # FAKE - F# Make
293 | .fake/
294 |
295 | # JetBrains Rider
296 | .idea/
297 | *.sln.iml
298 |
299 | # CodeRush personal settings
300 | .cr/personal
301 |
302 | # Python Tools for Visual Studio (PTVS)
303 | __pycache__/
304 | *.pyc
305 |
306 | # Cake - Uncomment if you are using it
307 | # tools/**
308 | # !tools/packages.config
309 |
310 | # Tabs Studio
311 | *.tss
312 |
313 | # Telerik's JustMock configuration file
314 | *.jmconfig
315 |
316 | # BizTalk build output
317 | *.btp.cs
318 | *.btm.cs
319 | *.odx.cs
320 | *.xsd.cs
321 |
322 | # OpenCover UI analysis results
323 | OpenCover/
324 |
325 | # Azure Stream Analytics local run output
326 | ASALocalRun/
327 |
328 | # MSBuild Binary and Structured Log
329 | *.binlog
330 |
331 | # NVidia Nsight GPU debugger configuration file
332 | *.nvuser
333 |
334 | # MFractors (Xamarin productivity tool) working folder
335 | .mfractor/
336 |
337 | # Local History for Visual Studio
338 | .localhistory/
--------------------------------------------------------------------------------
/ConsoleApp1/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/ConsoleApp1/AssemblyLoader.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {76435F79-F8AF-4D74-8DF5-D598A551B895}
8 | Library
9 | AssemblyLoader
10 | AssemblyLoader
11 | v4.6.1
12 | 512
13 | true
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 | true
39 | bin\x64\Debug\
40 | DEBUG;TRACE
41 | full
42 | x64
43 | prompt
44 | MinimumRecommendedRules.ruleset
45 |
46 |
47 | bin\x64\Release\
48 | TRACE
49 | true
50 | pdbonly
51 | x64
52 | prompt
53 | MinimumRecommendedRules.ruleset
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/ConsoleApp1/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using System.IO;
4 | using System.Reflection;
5 |
6 | public class AssemblyLoader
7 | {
8 | public interface IAssemblyLoader
9 | {
10 | void Load(byte[] bytes);
11 | }
12 |
13 | public class AssemblyLoaderProxy : MarshalByRefObject, IAssemblyLoader
14 | {
15 | public void Load(byte[] bytes)
16 | {
17 | var assembly = AppDomain.CurrentDomain.Load(bytes);
18 | var type = assembly.GetType("DemoAssembly.DemoClass");
19 | var method = type.GetMethod("HelloWorld");
20 | var instance = Activator.CreateInstance(type, null);
21 | Console.WriteLine("--- Executed from {0}: {1}", AppDomain.CurrentDomain.FriendlyName, method.Invoke(instance, null));
22 | }
23 | }
24 |
25 | public static int StartTimer(string gargoyleDllContentsInBase64)
26 | {
27 | Console.WriteLine("Start timer function called");
28 | byte[] dllByteArray = Convert.FromBase64String(gargoyleDllContentsInBase64);
29 | Timer t = new Timer(new TimerCallback(TimerProcAssemblyLoad), dllByteArray, 0, 0);
30 | return 0;
31 | }
32 |
33 | private static void TimerProcAssemblyLoad(object state)
34 | {
35 | AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
36 | Console.WriteLine("Hello from timer!");
37 |
38 | String appDomainName = "TemporaryApplicationDomain";
39 | AppDomain applicationDomain = System.AppDomain.CreateDomain(appDomainName);
40 | var assmblyLoaderType = typeof(AssemblyLoaderProxy);
41 | var assemblyLoader = (IAssemblyLoader)applicationDomain.CreateInstanceFromAndUnwrap(assmblyLoaderType.Assembly.Location, assmblyLoaderType.FullName);
42 | assemblyLoader.Load((byte[])state);
43 | Console.WriteLine("Dynamic assembly has been loaded in new AppDomain " + appDomainName);
44 |
45 | AppDomain.Unload(applicationDomain);
46 | Console.WriteLine("New AppDomain has been unloaded");
47 |
48 | Timer t = new Timer(new TimerCallback(TimerProcAssemblyLoad), state, 1000, 0);
49 | }
50 |
51 | private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
52 | {
53 | try
54 | {
55 | Assembly assembly = System.Reflection.Assembly.Load(args.Name);
56 | if (assembly != null)
57 | return assembly;
58 | }
59 | catch
60 | { // ignore load error }
61 |
62 | // *** Try to load by filename - split out the filename of the full assembly name
63 | // *** and append the base path of the original assembly (ie. look in the same dir)
64 | // *** NOTE: this doesn't account for special search paths but then that never
65 | // worked before either.
66 | string[] Parts = args.Name.Split(',');
67 | string File = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\" + Parts[0].Trim() + ".dll";
68 |
69 | return System.Reflection.Assembly.LoadFrom(File);
70 | }
71 | return null;
72 | }
73 | }
--------------------------------------------------------------------------------
/ConsoleApp1/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("ConsoleApp1")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ConsoleApp1")]
13 | [assembly: AssemblyCopyright("Copyright © 2018")]
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("76435f79-f8af-4d74-8df5-d598a551b895")]
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 |
--------------------------------------------------------------------------------
/DemoAssembly/DemoAssembly.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {6F0BBB2A-E200-4D76-B8FA-F93C801AC220}
8 | Library
9 | Properties
10 | DemoAssembly
11 | DemoAssembly
12 | v4.6.1
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 | true
34 | bin\x64\Debug\
35 | DEBUG;TRACE
36 | full
37 | x64
38 | prompt
39 | MinimumRecommendedRules.ruleset
40 |
41 |
42 | bin\x64\Release\
43 | TRACE
44 | true
45 | pdbonly
46 | x64
47 | prompt
48 | MinimumRecommendedRules.ruleset
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/DemoAssembly/DemoClass.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace DemoAssembly
8 | {
9 | public class DemoClass
10 | {
11 | public static string HelloWorld()
12 | {
13 | return "Hello World from DemoAssembly!";
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/DemoAssembly/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("DemoAssembly")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("DemoAssembly")]
13 | [assembly: AssemblyCopyright("Copyright © 2018")]
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("6f0bbb2a-e200-4d76-b8fa-f93c801ac220")]
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 |
--------------------------------------------------------------------------------
/DotNetGargoyle.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27703.2035
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssemblyLoader", "ConsoleApp1\AssemblyLoader.csproj", "{76435F79-F8AF-4D74-8DF5-D598A551B895}"
7 | EndProject
8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NativeMainApp", "NativeMainApp\NativeMainApp.vcxproj", "{4BBB15A7-F6E7-492F-92CA-10CA66F0EE1B}"
9 | EndProject
10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NativeDll", "NativeDll\NativeDll.vcxproj", "{C08A1ED9-4989-423A-A356-28A24DFAC703}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DemoAssembly", "DemoAssembly\DemoAssembly.csproj", "{6F0BBB2A-E200-4D76-B8FA-F93C801AC220}"
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnumerateDotNetTimers", "EnumerateDotNetTimers\EnumerateDotNetTimers.csproj", "{5A3FC840-5432-4925-B5BC-ABC536429CB5}"
15 | EndProject
16 | Global
17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
18 | Debug|Any CPU = Debug|Any CPU
19 | Debug|x64 = Debug|x64
20 | Debug|x86 = Debug|x86
21 | Release|Any CPU = Release|Any CPU
22 | Release|x64 = Release|x64
23 | Release|x86 = Release|x86
24 | EndGlobalSection
25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
26 | {76435F79-F8AF-4D74-8DF5-D598A551B895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {76435F79-F8AF-4D74-8DF5-D598A551B895}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {76435F79-F8AF-4D74-8DF5-D598A551B895}.Debug|x64.ActiveCfg = Debug|x64
29 | {76435F79-F8AF-4D74-8DF5-D598A551B895}.Debug|x64.Build.0 = Debug|x64
30 | {76435F79-F8AF-4D74-8DF5-D598A551B895}.Debug|x86.ActiveCfg = Debug|Any CPU
31 | {76435F79-F8AF-4D74-8DF5-D598A551B895}.Debug|x86.Build.0 = Debug|Any CPU
32 | {76435F79-F8AF-4D74-8DF5-D598A551B895}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {76435F79-F8AF-4D74-8DF5-D598A551B895}.Release|Any CPU.Build.0 = Release|Any CPU
34 | {76435F79-F8AF-4D74-8DF5-D598A551B895}.Release|x64.ActiveCfg = Release|Any CPU
35 | {76435F79-F8AF-4D74-8DF5-D598A551B895}.Release|x64.Build.0 = Release|Any CPU
36 | {76435F79-F8AF-4D74-8DF5-D598A551B895}.Release|x86.ActiveCfg = Release|Any CPU
37 | {76435F79-F8AF-4D74-8DF5-D598A551B895}.Release|x86.Build.0 = Release|Any CPU
38 | {4BBB15A7-F6E7-492F-92CA-10CA66F0EE1B}.Debug|Any CPU.ActiveCfg = Debug|Win32
39 | {4BBB15A7-F6E7-492F-92CA-10CA66F0EE1B}.Debug|Any CPU.Build.0 = Debug|Win32
40 | {4BBB15A7-F6E7-492F-92CA-10CA66F0EE1B}.Debug|x64.ActiveCfg = Debug|x64
41 | {4BBB15A7-F6E7-492F-92CA-10CA66F0EE1B}.Debug|x64.Build.0 = Debug|x64
42 | {4BBB15A7-F6E7-492F-92CA-10CA66F0EE1B}.Debug|x86.ActiveCfg = Debug|Win32
43 | {4BBB15A7-F6E7-492F-92CA-10CA66F0EE1B}.Debug|x86.Build.0 = Debug|Win32
44 | {4BBB15A7-F6E7-492F-92CA-10CA66F0EE1B}.Release|Any CPU.ActiveCfg = Release|Win32
45 | {4BBB15A7-F6E7-492F-92CA-10CA66F0EE1B}.Release|x64.ActiveCfg = Release|x64
46 | {4BBB15A7-F6E7-492F-92CA-10CA66F0EE1B}.Release|x64.Build.0 = Release|x64
47 | {4BBB15A7-F6E7-492F-92CA-10CA66F0EE1B}.Release|x86.ActiveCfg = Release|Win32
48 | {4BBB15A7-F6E7-492F-92CA-10CA66F0EE1B}.Release|x86.Build.0 = Release|Win32
49 | {C08A1ED9-4989-423A-A356-28A24DFAC703}.Debug|Any CPU.ActiveCfg = Debug|Win32
50 | {C08A1ED9-4989-423A-A356-28A24DFAC703}.Debug|Any CPU.Build.0 = Debug|Win32
51 | {C08A1ED9-4989-423A-A356-28A24DFAC703}.Debug|x64.ActiveCfg = Debug|x64
52 | {C08A1ED9-4989-423A-A356-28A24DFAC703}.Debug|x64.Build.0 = Debug|x64
53 | {C08A1ED9-4989-423A-A356-28A24DFAC703}.Debug|x86.ActiveCfg = Debug|Win32
54 | {C08A1ED9-4989-423A-A356-28A24DFAC703}.Debug|x86.Build.0 = Debug|Win32
55 | {C08A1ED9-4989-423A-A356-28A24DFAC703}.Release|Any CPU.ActiveCfg = Release|Win32
56 | {C08A1ED9-4989-423A-A356-28A24DFAC703}.Release|x64.ActiveCfg = Release|x64
57 | {C08A1ED9-4989-423A-A356-28A24DFAC703}.Release|x64.Build.0 = Release|x64
58 | {C08A1ED9-4989-423A-A356-28A24DFAC703}.Release|x86.ActiveCfg = Release|Win32
59 | {C08A1ED9-4989-423A-A356-28A24DFAC703}.Release|x86.Build.0 = Release|Win32
60 | {6F0BBB2A-E200-4D76-B8FA-F93C801AC220}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
61 | {6F0BBB2A-E200-4D76-B8FA-F93C801AC220}.Debug|Any CPU.Build.0 = Debug|Any CPU
62 | {6F0BBB2A-E200-4D76-B8FA-F93C801AC220}.Debug|x64.ActiveCfg = Debug|x64
63 | {6F0BBB2A-E200-4D76-B8FA-F93C801AC220}.Debug|x64.Build.0 = Debug|x64
64 | {6F0BBB2A-E200-4D76-B8FA-F93C801AC220}.Debug|x86.ActiveCfg = Debug|Any CPU
65 | {6F0BBB2A-E200-4D76-B8FA-F93C801AC220}.Debug|x86.Build.0 = Debug|Any CPU
66 | {6F0BBB2A-E200-4D76-B8FA-F93C801AC220}.Release|Any CPU.ActiveCfg = Release|Any CPU
67 | {6F0BBB2A-E200-4D76-B8FA-F93C801AC220}.Release|Any CPU.Build.0 = Release|Any CPU
68 | {6F0BBB2A-E200-4D76-B8FA-F93C801AC220}.Release|x64.ActiveCfg = Release|Any CPU
69 | {6F0BBB2A-E200-4D76-B8FA-F93C801AC220}.Release|x64.Build.0 = Release|Any CPU
70 | {6F0BBB2A-E200-4D76-B8FA-F93C801AC220}.Release|x86.ActiveCfg = Release|Any CPU
71 | {6F0BBB2A-E200-4D76-B8FA-F93C801AC220}.Release|x86.Build.0 = Release|Any CPU
72 | {5A3FC840-5432-4925-B5BC-ABC536429CB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
73 | {5A3FC840-5432-4925-B5BC-ABC536429CB5}.Debug|Any CPU.Build.0 = Debug|Any CPU
74 | {5A3FC840-5432-4925-B5BC-ABC536429CB5}.Debug|x64.ActiveCfg = Debug|x64
75 | {5A3FC840-5432-4925-B5BC-ABC536429CB5}.Debug|x64.Build.0 = Debug|x64
76 | {5A3FC840-5432-4925-B5BC-ABC536429CB5}.Debug|x86.ActiveCfg = Debug|Any CPU
77 | {5A3FC840-5432-4925-B5BC-ABC536429CB5}.Debug|x86.Build.0 = Debug|Any CPU
78 | {5A3FC840-5432-4925-B5BC-ABC536429CB5}.Release|Any CPU.ActiveCfg = Release|Any CPU
79 | {5A3FC840-5432-4925-B5BC-ABC536429CB5}.Release|Any CPU.Build.0 = Release|Any CPU
80 | {5A3FC840-5432-4925-B5BC-ABC536429CB5}.Release|x64.ActiveCfg = Release|Any CPU
81 | {5A3FC840-5432-4925-B5BC-ABC536429CB5}.Release|x64.Build.0 = Release|Any CPU
82 | {5A3FC840-5432-4925-B5BC-ABC536429CB5}.Release|x86.ActiveCfg = Release|Any CPU
83 | {5A3FC840-5432-4925-B5BC-ABC536429CB5}.Release|x86.Build.0 = Release|Any CPU
84 | EndGlobalSection
85 | GlobalSection(SolutionProperties) = preSolution
86 | HideSolutionNode = FALSE
87 | EndGlobalSection
88 | GlobalSection(ExtensibilityGlobals) = postSolution
89 | SolutionGuid = {1D5A20DE-3455-44EF-9350-13B4B3E946FB}
90 | EndGlobalSection
91 | EndGlobal
92 |
--------------------------------------------------------------------------------
/EnumerateDotNetTimers/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/EnumerateDotNetTimers/EnumerateDotNetTimers.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {5A3FC840-5432-4925-B5BC-ABC536429CB5}
8 | Exe
9 | EnumerateDotNetTimers
10 | EnumerateDotNetTimers
11 | v4.6.1
12 | 512
13 | true
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 | true
36 | bin\x64\Debug\
37 | DEBUG;TRACE
38 | full
39 | x64
40 | prompt
41 | MinimumRecommendedRules.ruleset
42 | true
43 |
44 |
45 | bin\x64\Release\
46 | TRACE
47 | true
48 | pdbonly
49 | x64
50 | prompt
51 | MinimumRecommendedRules.ruleset
52 | true
53 |
54 |
55 |
56 | ..\packages\Microsoft.Diagnostics.Runtime.0.9.180305.01\lib\net40\Microsoft.Diagnostics.Runtime.dll
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/EnumerateDotNetTimers/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Microsoft.Diagnostics.Runtime;
7 | using System.Diagnostics;
8 |
9 |
10 | namespace ClrMdHarness
11 | {
12 | class Program
13 | {
14 | static void Usage()
15 | {
16 | Console.WriteLine("ERROR - Invalid args");
17 | Console.WriteLine();
18 | Console.WriteLine("EnumerateDotNetTimers.exe --all | --non-microsoft-only");
19 | Console.WriteLine();
20 | Console.WriteLine("--all\t\t\tEnumerate all timers");
21 | Console.WriteLine("--non-microsoft-only\tEnumerate only timers with non-System and non-Microsoft namespaces");
22 | }
23 | static void Main(string[] args)
24 | {
25 | bool enumerateAll = true;
26 |
27 | if (args.Length < 1)
28 | {
29 | Usage();
30 | return;
31 | }
32 | else if (args[0] == "--all")
33 | {
34 | enumerateAll = true;
35 | }
36 | else if (args[0] == "--non-microsoft-only")
37 | {
38 | enumerateAll = false;
39 | }
40 | else
41 | {
42 | Usage();
43 | return;
44 | }
45 |
46 | Console.WriteLine("Timers\n============");
47 |
48 | foreach (var process in Process.GetProcesses())
49 | {
50 | try
51 | {
52 | using (DataTarget target = DataTarget.AttachToProcess(process.Id, 1000, AttachFlag.Passive))
53 | {
54 | // First, loop through each Clr in the process (there may be multiple in the side-by-side scenario).
55 | foreach (ClrInfo clrVersion in target.ClrVersions)
56 | {
57 | ClrRuntime runtime = clrVersion.CreateRuntime();
58 | Timers t = new Timers();
59 | var timers = t.EnumerateTimers(runtime);
60 | foreach (var timer in timers)
61 | {
62 | if (!timer.MethodName.StartsWith("System") && !timer.MethodName.StartsWith("Microsoft"))
63 | {
64 | Console.WriteLine("[NON-MICROSOFT] - {0}:{1} - {2}, {3}, {4:X}, {5:X}, {6}", process.ProcessName, process.Id, timer.DueTime.ToString(), timer.StateTypeName, timer.ThisAddress, timer.MethodAddress, timer.MethodName);
65 | }
66 | else if (enumerateAll)
67 | {
68 | Console.WriteLine("[MICROSOFT] - {0}:{1} - {2}, {3}, {4:X}, {5:X}, {6}", process.ProcessName, process.Id, timer.DueTime.ToString(), timer.StateTypeName, timer.ThisAddress, timer.MethodAddress, timer.MethodName);
69 | }
70 | }
71 | }
72 | }
73 | }
74 | catch (Exception e)
75 | {
76 | // Console.WriteLine(e);
77 | }
78 | }
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/EnumerateDotNetTimers/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("EnumerateDotNetTimers")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("EnumerateDotNetTimers")]
13 | [assembly: AssemblyCopyright("Copyright © 2018")]
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("5a3fc840-5432-4925-b5bc-abc536429cb5")]
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 |
--------------------------------------------------------------------------------
/EnumerateDotNetTimers/Timers.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Microsoft.Diagnostics.Runtime;
7 |
8 |
9 | namespace ClrMdHarness
10 | {
11 | class Timers
12 | {
13 | public class TimerInfo
14 | {
15 | public ulong TimerQueueTimerAddress { get; set; }
16 | public uint DueTime { get; set; }
17 | public uint Period { get; set; }
18 | public bool Cancelled { get; set; }
19 | public ulong StateAddress { get; set; }
20 | public string StateTypeName { get; set; }
21 | public ulong ThisAddress { get; set; }
22 | public string MethodName { get; set; }
23 | public ulong MethodAddress { get; set; }
24 | }
25 |
26 | // from threadpool.cs in https://github.com/Microsoft/clrmd/tree/master/src/Microsoft.Diagnostics.Runtime/Desktop
27 | public ClrModule GetMscorlib(ClrRuntime runtime)
28 | {
29 | foreach (ClrModule module in runtime.Modules)
30 | if (module.AssemblyName.Contains("mscorlib.dll"))
31 | return module;
32 |
33 | // Uh oh, this shouldn't have happened. Let's look more carefully (slowly).
34 | foreach (ClrModule module in runtime.Modules)
35 | if (module.AssemblyName.ToLower().Contains("mscorlib"))
36 | return module;
37 |
38 | // Ok...not sure why we couldn't find it.
39 | return null;
40 | }
41 |
42 | private object GetFieldValue(ClrHeap heap, ulong address, string fieldName)
43 | {
44 | var type = heap.GetObjectType(address);
45 | ClrInstanceField field = type.GetFieldByName(fieldName);
46 | if (field == null)
47 | return null;
48 |
49 | return field.GetValue(address);
50 | }
51 |
52 | private string BuildTimerCallbackMethodName(ClrRuntime runtime, ulong timerCallbackRef, string methodPtrString)
53 | {
54 | var heap = runtime.Heap;
55 | var methodPtr = GetFieldValue(heap, timerCallbackRef, methodPtrString);
56 | if (methodPtr != null)
57 | {
58 | ClrMethod method = runtime.GetMethodByAddress((ulong)(long)methodPtr);
59 | if (method != null)
60 | {
61 | // look for "this" to figure out the real callback implementor type
62 | string thisTypeName = "?";
63 | var thisPtr = GetFieldValue(heap, timerCallbackRef, "_target");
64 | if ((thisPtr != null) && ((ulong)thisPtr) != 0)
65 | {
66 | ulong thisRef = (ulong)thisPtr;
67 | var thisType = heap.GetObjectType(thisRef);
68 | if (thisType != null)
69 | {
70 | thisTypeName = thisType.Name;
71 | }
72 | }
73 | else
74 | {
75 | thisTypeName = (method.Type != null) ? method.Type.Name : "?";
76 | }
77 | return method.GetFullSignature();
78 | return string.Format("{0}.{1}", thisTypeName, method.Name);
79 | }
80 | else
81 | {
82 | return "";
83 | }
84 | }
85 | else
86 | {
87 | return "";
88 | }
89 | }
90 |
91 | public IEnumerable EnumerateTimers(ClrRuntime runtime)
92 | {
93 | ClrHeap heap = runtime.Heap;
94 | if (!heap.CanWalkHeap)
95 | yield break;
96 |
97 | var timerQueueType = GetMscorlib(runtime).GetTypeByName("System.Threading.TimerQueue");
98 | if (timerQueueType == null)
99 | yield break;
100 |
101 | ClrStaticField staticField = timerQueueType.GetStaticFieldByName("s_queue");
102 | if (staticField == null)
103 | yield break;
104 |
105 | foreach (ClrAppDomain domain in runtime.AppDomains)
106 | {
107 | ulong? timerQueue = (ulong?)staticField.GetValue(domain);
108 | if (!timerQueue.HasValue || timerQueue.Value == 0)
109 | continue;
110 |
111 | // m_timers is the start of the list of TimerQueueTimer
112 | var currentPointer = GetFieldValue(heap, timerQueue.Value, "m_timers");
113 |
114 | while ((currentPointer != null) && (((ulong)currentPointer) != 0))
115 | {
116 | // currentPointer points to a TimerQueueTimer instance
117 | ulong currentTimerQueueTimerRef = (ulong)currentPointer;
118 |
119 | TimerInfo ti = new TimerInfo()
120 | {
121 | TimerQueueTimerAddress = currentTimerQueueTimerRef
122 | };
123 |
124 | var val = GetFieldValue(heap, currentTimerQueueTimerRef, "m_dueTime");
125 | ti.DueTime = (uint)val;
126 | val = GetFieldValue(heap, currentTimerQueueTimerRef, "m_period");
127 | ti.Period = (uint)val;
128 | val = GetFieldValue(heap, currentTimerQueueTimerRef, "m_canceled");
129 | ti.Cancelled = (bool)val;
130 | val = GetFieldValue(heap, currentTimerQueueTimerRef, "m_state");
131 | ti.StateTypeName = "";
132 | if (val == null)
133 | {
134 | ti.StateAddress = 0;
135 | }
136 | else
137 | {
138 | ti.StateAddress = (ulong)val;
139 | var stateType = heap.GetObjectType(ti.StateAddress);
140 | if (stateType != null)
141 | {
142 | ti.StateTypeName = stateType.Name;
143 | }
144 | }
145 |
146 | // decypher the callback details
147 | val = GetFieldValue(heap, currentTimerQueueTimerRef, "m_timerCallback");
148 | if (val != null)
149 | {
150 | ulong elementAddress = (ulong)val;
151 | if (elementAddress == 0)
152 | continue;
153 |
154 | var elementType = heap.GetObjectType(elementAddress);
155 | if (elementType != null)
156 | {
157 | if (elementType.Name == "System.Threading.TimerCallback")
158 | {
159 | ti.MethodAddress = (ulong)(long)GetFieldValue(heap, elementAddress, "_methodPtr");
160 | ti.MethodName = BuildTimerCallbackMethodName(runtime, elementAddress, "_methodPtr");
161 | if (ti.MethodName == "")
162 | {
163 | ti.MethodAddress = (ulong)(long)GetFieldValue(heap, elementAddress, "_methodPtrAux");
164 | ti.MethodName = BuildTimerCallbackMethodName(runtime, elementAddress, "_methodPtrAux");
165 | }
166 | }
167 | else
168 | {
169 | ti.MethodName = "<" + elementType.Name + ">";
170 | }
171 | }
172 | else
173 | {
174 | ti.MethodName = "{no callback type?}";
175 | }
176 | }
177 | else
178 | {
179 | ti.MethodName = "???";
180 | }
181 |
182 | yield return ti;
183 |
184 | currentPointer = GetFieldValue(heap, currentTimerQueueTimerRef, "m_next");
185 | }
186 | }
187 | }
188 | }
189 | }
190 |
--------------------------------------------------------------------------------
/EnumerateDotNetTimers/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/NativeDll/NativeDll.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 | 15.0
23 | {C08A1ED9-4989-423A-A356-28A24DFAC703}
24 | NativeDll
25 | 10.0.17134.0
26 |
27 |
28 |
29 | DynamicLibrary
30 | true
31 | v141
32 | MultiByte
33 |
34 |
35 | Application
36 | false
37 | v141
38 | true
39 | MultiByte
40 |
41 |
42 | Application
43 | true
44 | v141
45 | MultiByte
46 |
47 |
48 | Application
49 | false
50 | v141
51 | true
52 | MultiByte
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | Level3
76 | Disabled
77 | true
78 | true
79 |
80 |
81 |
82 |
83 | Level3
84 | Disabled
85 | true
86 | true
87 |
88 |
89 |
90 |
91 | Level3
92 | MaxSpeed
93 | true
94 | true
95 | true
96 | true
97 |
98 |
99 | true
100 | true
101 |
102 |
103 |
104 |
105 | Level3
106 | MaxSpeed
107 | true
108 | true
109 | true
110 | true
111 |
112 |
113 | true
114 | true
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 | {76435f79-f8af-4d74-8df5-d598a551b895}
123 |
124 |
125 | {6f0bbb2a-e200-4d76-b8fa-f93c801ac220}
126 |
127 |
128 |
129 |
130 |
131 |
--------------------------------------------------------------------------------
/NativeDll/NativeDll.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;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 |
--------------------------------------------------------------------------------
/NativeDll/dll.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #pragma comment(lib, "mscoree.lib")
8 |
9 |
10 | static char encoding_table[] = {
11 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
12 | 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
13 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
14 | 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
15 | 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
16 | 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
17 | 'w', 'x', 'y', 'z', '0', '1', '2', '3',
18 | '4', '5', '6', '7', '8', '9', '+', '/' };
19 | static char *decoding_table = NULL;
20 | static int mod_table[] = { 0, 2, 1 };
21 |
22 |
23 | char *base64_encode(const unsigned char *data,
24 | size_t input_length,
25 | size_t *output_length) {
26 |
27 | *output_length = 4 * ((input_length + 2) / 3);
28 |
29 | char *encoded_data = (char*)calloc(*output_length, sizeof(char));
30 | if (encoded_data == NULL) return NULL;
31 |
32 | for (unsigned int i = 0, j = 0; i < input_length;) {
33 |
34 | uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
35 | uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
36 | uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;
37 |
38 | uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
39 |
40 | encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
41 | encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
42 | encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
43 | encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
44 | }
45 |
46 | for (int i = 0; i < mod_table[input_length % 3]; i++)
47 | encoded_data[*output_length - 1 - i] = '=';
48 |
49 | encoded_data[*output_length] = '\0';
50 |
51 | return encoded_data;
52 | }
53 |
54 |
55 | DWORD WINAPI RunDotNet(LPVOID lpvParam)
56 | {
57 | HRESULT hr;
58 | ICLRMetaHost *pMetaHost = NULL;
59 | ICLRRuntimeInfo *pRuntimeInfo = NULL;
60 | ICLRRuntimeHost *pClrRuntimeHost = NULL;
61 |
62 | // build runtime
63 | hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost));
64 | hr = pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&pRuntimeInfo));
65 | hr = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost,
66 | IID_PPV_ARGS(&pClrRuntimeHost));
67 |
68 | // start runtime
69 | hr = pClrRuntimeHost->Start();
70 |
71 | // convert malicious assembly to base64-encoded byte stream
72 | FILE *fileptr;
73 | char *buffer;
74 | long filelen;
75 | size_t outputlen;
76 |
77 | _wfopen_s(&fileptr, L"DemoAssembly.dll", L"rb"); // Open the file in binary mode
78 | fseek(fileptr, 0, SEEK_END); // Jump to the end of the file
79 | filelen = ftell(fileptr); // Get the current byte offset in the file
80 | rewind(fileptr); // Jump back to the beginning of the file
81 |
82 | buffer = (char *)calloc((filelen + 1), sizeof(char)); // Enough memory for file + \0
83 | fread(buffer, filelen, 1, fileptr); // Read in the entire file
84 | fclose(fileptr); // Close the file
85 | char *char_base64contents = base64_encode((unsigned char*)buffer, filelen, &outputlen);
86 | LPCWSTR lpcwstr_base64_contents = (LPCWSTR)calloc(outputlen + 1, sizeof(wchar_t));
87 | mbstowcs_s(&outputlen, (wchar_t*)lpcwstr_base64_contents, outputlen + 1, char_base64contents, outputlen);
88 |
89 | // execute managed assembly
90 | DWORD pReturnValue;
91 | hr = pClrRuntimeHost->ExecuteInDefaultAppDomain(
92 | L"AssemblyLoader.dll",
93 | L"AssemblyLoader",
94 | L"StartTimer",
95 | lpcwstr_base64_contents,
96 | &pReturnValue);
97 |
98 | return 0;
99 | }
100 |
101 | BOOL WINAPI DllMain(
102 | __in HINSTANCE hinstDLL,
103 | __in DWORD fdwReason,
104 | __in LPVOID lpvReserved
105 | ) {
106 | switch (fdwReason) {
107 | case DLL_PROCESS_ATTACH:
108 | CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RunDotNet, NULL, 0, NULL);
109 | break;
110 | case DLL_PROCESS_DETACH:
111 | break;
112 | case DLL_THREAD_ATTACH:
113 | break;
114 | case DLL_THREAD_DETACH:
115 | break;
116 | }
117 | return TRUE;
118 | }
119 |
120 | int wmain(int argc, wchar_t *argv[])
121 | {
122 | RunDotNet(NULL);
123 | _getch();
124 | }
--------------------------------------------------------------------------------
/NativeMainApp/NativeMainApp.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WithSecureLabs/dotnet-gargoyle/ee5d0878e4ff7ac485172ca78b3cf522fce0da97/NativeMainApp/NativeMainApp.cpp
--------------------------------------------------------------------------------
/NativeMainApp/NativeMainApp.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 | 15.0
23 | {4BBB15A7-F6E7-492F-92CA-10CA66F0EE1B}
24 | Win32Proj
25 | NativeMainApp
26 | 10.0.17134.0
27 |
28 |
29 |
30 | Application
31 | true
32 | v141
33 | Unicode
34 |
35 |
36 | Application
37 | false
38 | v141
39 | true
40 | Unicode
41 |
42 |
43 | Application
44 | true
45 | v141
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v141
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 | true
78 |
79 |
80 | false
81 |
82 |
83 | false
84 |
85 |
86 |
87 | Use
88 | Level3
89 | Disabled
90 | true
91 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
92 | true
93 |
94 |
95 | Console
96 | true
97 |
98 |
99 |
100 |
101 | Use
102 | Level3
103 | Disabled
104 | true
105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
106 | true
107 |
108 |
109 | Console
110 | true
111 |
112 |
113 |
114 |
115 | Use
116 | Level3
117 | MaxSpeed
118 | true
119 | true
120 | true
121 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
122 | true
123 |
124 |
125 | Console
126 | true
127 | true
128 | true
129 |
130 |
131 |
132 |
133 | Use
134 | Level3
135 | MaxSpeed
136 | true
137 | true
138 | true
139 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
140 | true
141 |
142 |
143 | Console
144 | true
145 | true
146 | true
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 | Create
157 | Create
158 | Create
159 | Create
160 |
161 |
162 |
163 |
164 |
165 |
--------------------------------------------------------------------------------
/NativeMainApp/NativeMainApp.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;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 | Header Files
20 |
21 |
22 | Header Files
23 |
24 |
25 |
26 |
27 | Source Files
28 |
29 |
30 | Source Files
31 |
32 |
33 |
--------------------------------------------------------------------------------
/NativeMainApp/stdafx.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WithSecureLabs/dotnet-gargoyle/ee5d0878e4ff7ac485172ca78b3cf522fce0da97/NativeMainApp/stdafx.cpp
--------------------------------------------------------------------------------
/NativeMainApp/stdafx.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WithSecureLabs/dotnet-gargoyle/ee5d0878e4ff7ac485172ca78b3cf522fce0da97/NativeMainApp/stdafx.h
--------------------------------------------------------------------------------
/NativeMainApp/targetver.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WithSecureLabs/dotnet-gargoyle/ee5d0878e4ff7ac485172ca78b3cf522fce0da97/NativeMainApp/targetver.h
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # dotnet-gargoyle
2 | A spiritual .NET equivalent to the Gargoyle memory scanning evasion technique
3 |
4 | https://www.countercept.com/blog/gargoyle-memory-scanning-evasion-for-net/
5 |
--------------------------------------------------------------------------------