├── .gitignore
├── ClsidExplorer
├── CLSIDExplorer.sln
├── CLSIDExplorer
│ ├── CLSIDExplorer.vcxproj
│ ├── CLSIDExplorer.vcxproj.filters
│ ├── CLSIDExplorer.vcxproj.user
│ ├── Parser.cpp
│ ├── Parser.h
│ ├── main.cpp
│ └── main.h
└── x64
│ └── Debug
│ ├── CLSIDExplorer.exe
│ └── CLSIDExplorer.pdb
├── ComDiver
├── COMDiver.sln
├── COMDiver
│ ├── COMDiver.vcxproj
│ ├── COMDiver.vcxproj.filters
│ ├── COMDiver.vcxproj.user
│ ├── analyzer.cpp
│ ├── analyzer.h
│ ├── argparse.cpp
│ ├── argparse.h
│ ├── enumerator.cpp
│ ├── enumerator.h
│ ├── main.cpp
│ └── main.h
└── x64
│ └── Debug
│ ├── ComDiver.exe
│ └── ComDiver.pdb
├── ComTraveller
├── ComTraveller.sln
├── ComTraveller
│ ├── ComTraveller.vcxproj
│ ├── ComTraveller.vcxproj.filters
│ ├── ComTraveller.vcxproj.user
│ ├── enumerator.cpp
│ ├── enumerator.h
│ ├── main.cpp
│ ├── main.h
│ └── x64
│ │ └── Debug
│ │ ├── ComTraveller.exe.recipe
│ │ ├── ComTraveller.vcxproj.FileListAbsolute.txt
│ │ └── vc143.idb
└── x64
│ └── Debug
│ ├── ComTraveller.exe
│ ├── ComTraveller.pdb
│ └── rep.csv
├── MonikerHound
├── MonikerHound.sln
├── MonikerHound
│ ├── MonikerHound.vcxproj
│ ├── MonikerHound.vcxproj.filters
│ ├── MonikerHound.vcxproj.user
│ └── Source.cpp
└── x64
│ └── Debug
│ ├── MonikerHound.exe
│ └── MonikerHound.pdb
├── PermissionHunter
└── PermissionHunter
│ ├── PermissionHunter.sln
│ ├── PermissionHunter
│ ├── App.config
│ ├── PermissionHunter.csproj
│ ├── Program.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── bin
│ │ └── Debug
│ │ │ ├── PermissionHunter.exe
│ │ │ ├── PermissionHunter.exe.config
│ │ │ ├── PermissionHunter.pdb
│ │ │ └── result.xlsx
│ ├── obj
│ │ └── Debug
│ │ │ ├── .NETFramework,Version=v4.8.AssemblyAttributes.cs
│ │ │ ├── DesignTimeResolveAssemblyReferencesInput.cache
│ │ │ ├── PermissionHunter.csproj.AssemblyReference.cache
│ │ │ ├── PermissionHunter.csproj.CoreCompileInputs.cache
│ │ │ ├── PermissionHunter.csproj.FileListAbsolute.txt
│ │ │ ├── PermissionHunter.exe
│ │ │ └── PermissionHunter.pdb
│ └── packages.config
│ └── packages
│ └── Microsoft.Office.Interop.Excel.15.0.4795.1001
│ ├── .signature.p7s
│ ├── Microsoft.Office.Interop.Excel.15.0.4795.1001.nupkg
│ └── lib
│ ├── net20
│ └── Microsoft.Office.Interop.Excel.dll
│ └── netstandard2.0
│ └── Microsoft.Office.Interop.Excel.dll
└── 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/main/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 | *.csv
19 | *.pdb
20 | *pdb*
21 |
22 |
23 | # Visual Studio 2015/2017 cache/options directory
24 | .vs/
25 | # Uncomment if you have tasks that create the project's static files in wwwroot
26 | #wwwroot/
27 |
28 | # Visual Studio 2017 auto generated files
29 | Generated\ Files/
30 |
31 | # MSTest test Results
32 | [Tt]est[Rr]esult*/
33 | [Bb]uild[Ll]og.*
34 |
35 | # NUnit
36 | *.VisualState.xml
37 | TestResult.xml
38 | nunit-*.xml
39 |
40 | # Build Results of an ATL Project
41 | [Dd]ebugPS/
42 | [Rr]eleasePS/
43 | dlldata.c
44 |
45 | # Benchmark Results
46 | BenchmarkDotNet.Artifacts/
47 |
48 | # .NET Core
49 | project.lock.json
50 | project.fragment.lock.json
51 | artifacts/
52 |
53 | # ASP.NET Scaffolding
54 | ScaffoldingReadMe.txt
55 |
56 | # StyleCop
57 | StyleCopReport.xml
58 |
59 | # Files built by Visual Studio
60 | *_i.c
61 | *_p.c
62 | *_h.h
63 | *.ilk
64 | *.meta
65 | *.obj
66 | *.iobj
67 | *.pch
68 | *.pdb
69 | *.ipdb
70 | *.pgc
71 | *.pgd
72 | *.rsp
73 | *.sbr
74 | *.tlb
75 | *.tli
76 | *.tlh
77 | *.tmp
78 | *.tmp_proj
79 | *_wpftmp.csproj
80 | *.log
81 | *.tlog
82 | *.vspscc
83 | *.vssscc
84 | .builds
85 | *.pidb
86 | *.svclog
87 | *.scc
88 |
89 | # Chutzpah Test files
90 | _Chutzpah*
91 |
92 | # Visual C++ cache files
93 | ipch/
94 | *.aps
95 | *.ncb
96 | *.opendb
97 | *.opensdf
98 | *.sdf
99 | *.cachefile
100 | *.VC.db
101 | *.VC.VC.opendb
102 |
103 | # Visual Studio profiler
104 | *.psess
105 | *.vsp
106 | *.vspx
107 | *.sap
108 |
109 | # Visual Studio Trace Files
110 | *.e2e
111 |
112 | # TFS 2012 Local Workspace
113 | $tf/
114 |
115 | # Guidance Automation Toolkit
116 | *.gpState
117 |
118 | # ReSharper is a .NET coding add-in
119 | _ReSharper*/
120 | *.[Rr]e[Ss]harper
121 | *.DotSettings.user
122 |
123 | # TeamCity is a build add-in
124 | _TeamCity*
125 |
126 | # DotCover is a Code Coverage Tool
127 | *.dotCover
128 |
129 | # AxoCover is a Code Coverage Tool
130 | .axoCover/*
131 | !.axoCover/settings.json
132 |
133 | # Coverlet is a free, cross platform Code Coverage Tool
134 | coverage*.json
135 | coverage*.xml
136 | coverage*.info
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 | # NuGet Symbol Packages
186 | *.snupkg
187 | # The packages folder can be ignored because of Package Restore
188 | **/[Pp]ackages/*
189 | # except build/, which is used as an MSBuild target.
190 | !**/[Pp]ackages/build/
191 | # Uncomment if necessary however generally it will be regenerated when needed
192 | #!**/[Pp]ackages/repositories.config
193 | # NuGet v3's project.json files produces more ignorable files
194 | *.nuget.props
195 | *.nuget.targets
196 |
197 | # Microsoft Azure Build Output
198 | csx/
199 | *.build.csdef
200 |
201 | # Microsoft Azure Emulator
202 | ecf/
203 | rcf/
204 |
205 | # Windows Store app package directories and files
206 | AppPackages/
207 | BundleArtifacts/
208 | Package.StoreAssociation.xml
209 | _pkginfo.txt
210 | *.appx
211 | *.appxbundle
212 | *.appxupload
213 |
214 | # Visual Studio cache files
215 | # files ending in .cache can be ignored
216 | *.[Cc]ache
217 | # but keep track of directories ending in .cache
218 | !?*.[Cc]ache/
219 |
220 | # Others
221 | ClientBin/
222 | ~$*
223 | *~
224 | *.dbmdl
225 | *.dbproj.schemaview
226 | *.jfm
227 | *.pfx
228 | *.publishsettings
229 | orleans.codegen.cs
230 |
231 | # Including strong name files can present a security risk
232 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
233 | #*.snk
234 |
235 | # Since there are multiple workflows, uncomment next line to ignore bower_components
236 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
237 | #bower_components/
238 |
239 | # RIA/Silverlight projects
240 | Generated_Code/
241 |
242 | # Backup & report files from converting an old project file
243 | # to a newer Visual Studio version. Backup files are not needed,
244 | # because we have git ;-)
245 | _UpgradeReport_Files/
246 | Backup*/
247 | UpgradeLog*.XML
248 | UpgradeLog*.htm
249 | ServiceFabricBackup/
250 | *.rptproj.bak
251 |
252 | # SQL Server files
253 | *.mdf
254 | *.ldf
255 | *.ndf
256 |
257 | # Business Intelligence projects
258 | *.rdl.data
259 | *.bim.layout
260 | *.bim_*.settings
261 | *.rptproj.rsuser
262 | *- [Bb]ackup.rdl
263 | *- [Bb]ackup ([0-9]).rdl
264 | *- [Bb]ackup ([0-9][0-9]).rdl
265 |
266 | # Microsoft Fakes
267 | FakesAssemblies/
268 |
269 | # GhostDoc plugin setting file
270 | *.GhostDoc.xml
271 |
272 | # Node.js Tools for Visual Studio
273 | .ntvs_analysis.dat
274 | node_modules/
275 |
276 | # Visual Studio 6 build log
277 | *.plg
278 |
279 | # Visual Studio 6 workspace options file
280 | *.opt
281 |
282 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
283 | *.vbw
284 |
285 | # Visual Studio 6 auto-generated project file (contains which files were open etc.)
286 | *.vbp
287 |
288 | # Visual Studio 6 workspace and project file (working project files containing files to include in project)
289 | *.dsw
290 | *.dsp
291 |
292 | # Visual Studio 6 technical files
293 | *.ncb
294 | *.aps
295 |
296 | # Visual Studio LightSwitch build output
297 | **/*.HTMLClient/GeneratedArtifacts
298 | **/*.DesktopClient/GeneratedArtifacts
299 | **/*.DesktopClient/ModelManifest.xml
300 | **/*.Server/GeneratedArtifacts
301 | **/*.Server/ModelManifest.xml
302 | _Pvt_Extensions
303 |
304 | # Paket dependency manager
305 | .paket/paket.exe
306 | paket-files/
307 |
308 | # FAKE - F# Make
309 | .fake/
310 |
311 | # CodeRush personal settings
312 | .cr/personal
313 |
314 | # Python Tools for Visual Studio (PTVS)
315 | __pycache__/
316 | *.pyc
317 |
318 | # Cake - Uncomment if you are using it
319 | # tools/**
320 | # !tools/packages.config
321 |
322 | # Tabs Studio
323 | *.tss
324 |
325 | # Telerik's JustMock configuration file
326 | *.jmconfig
327 |
328 | # BizTalk build output
329 | *.btp.cs
330 | *.btm.cs
331 | *.odx.cs
332 | *.xsd.cs
333 |
334 | # OpenCover UI analysis results
335 | OpenCover/
336 |
337 | # Azure Stream Analytics local run output
338 | ASALocalRun/
339 |
340 | # MSBuild Binary and Structured Log
341 | *.binlog
342 |
343 | # NVidia Nsight GPU debugger configuration file
344 | *.nvuser
345 |
346 | # MFractors (Xamarin productivity tool) working folder
347 | .mfractor/
348 |
349 | # Local History for Visual Studio
350 | .localhistory/
351 |
352 | # Visual Studio History (VSHistory) files
353 | .vshistory/
354 |
355 | # BeatPulse healthcheck temp database
356 | healthchecksdb
357 |
358 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
359 | MigrationBackup/
360 |
361 | # Ionide (cross platform F# VS Code tools) working folder
362 | .ionide/
363 |
364 | # Fody - auto-generated XML schema
365 | FodyWeavers.xsd
366 |
367 | # VS Code files for those working on multiple tools
368 | .vscode/*
369 | !.vscode/settings.json
370 | !.vscode/tasks.json
371 | !.vscode/launch.json
372 | !.vscode/extensions.json
373 | *.code-workspace
374 |
375 | # Local History for Visual Studio Code
376 | .history/
377 |
378 | # Windows Installer files from build outputs
379 | *.cab
380 | *.msi
381 | *.msix
382 | *.msm
383 | *.msp
384 |
385 | # JetBrains Rider
386 | *.sln.iml
--------------------------------------------------------------------------------
/ClsidExplorer/CLSIDExplorer.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.7.34009.444
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CLSIDExplorer", "CLSIDExplorer\CLSIDExplorer.vcxproj", "{F95126BB-346E-4791-852A-03E7CE87B513}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Debug|x86 = Debug|x86
12 | Release|x64 = Release|x64
13 | Release|x86 = Release|x86
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {F95126BB-346E-4791-852A-03E7CE87B513}.Debug|x64.ActiveCfg = Debug|x64
17 | {F95126BB-346E-4791-852A-03E7CE87B513}.Debug|x64.Build.0 = Debug|x64
18 | {F95126BB-346E-4791-852A-03E7CE87B513}.Debug|x86.ActiveCfg = Debug|Win32
19 | {F95126BB-346E-4791-852A-03E7CE87B513}.Debug|x86.Build.0 = Debug|Win32
20 | {F95126BB-346E-4791-852A-03E7CE87B513}.Release|x64.ActiveCfg = Release|x64
21 | {F95126BB-346E-4791-852A-03E7CE87B513}.Release|x64.Build.0 = Release|x64
22 | {F95126BB-346E-4791-852A-03E7CE87B513}.Release|x86.ActiveCfg = Release|Win32
23 | {F95126BB-346E-4791-852A-03E7CE87B513}.Release|x86.Build.0 = Release|Win32
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {A1707595-5EAC-49C3-865C-A926F0E3EACF}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/ClsidExplorer/CLSIDExplorer/CLSIDExplorer.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 | 17.0
23 | Win32Proj
24 | {f95126bb-346e-4791-852a-03e7ce87b513}
25 | CLSIDExplorer
26 | 10.0
27 |
28 |
29 |
30 | Application
31 | true
32 | v143
33 | Unicode
34 |
35 |
36 | Application
37 | false
38 | v143
39 | true
40 | Unicode
41 |
42 |
43 | Application
44 | true
45 | v143
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v143
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 |
75 | Level3
76 | true
77 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
78 | true
79 |
80 |
81 | Console
82 | true
83 |
84 |
85 |
86 |
87 | Level3
88 | true
89 | true
90 | true
91 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
92 | true
93 |
94 |
95 | Console
96 | true
97 | true
98 | true
99 |
100 |
101 |
102 |
103 | Level3
104 | true
105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
106 | true
107 |
108 |
109 | Console
110 | true
111 |
112 |
113 |
114 |
115 | Level3
116 | true
117 | true
118 | true
119 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
120 | true
121 |
122 |
123 | Console
124 | true
125 | true
126 | true
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/ClsidExplorer/CLSIDExplorer/CLSIDExplorer.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Исходные файлы
20 |
21 |
22 | Исходные файлы
23 |
24 |
25 |
26 |
27 | Файлы заголовков
28 |
29 |
30 | Файлы заголовков
31 |
32 |
33 |
--------------------------------------------------------------------------------
/ClsidExplorer/CLSIDExplorer/CLSIDExplorer.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | --clsid {00000618-0000-0010-8000-00aa006d2ea4}
5 | WindowsLocalDebugger
6 |
7 |
--------------------------------------------------------------------------------
/ClsidExplorer/CLSIDExplorer/Parser.cpp:
--------------------------------------------------------------------------------
1 | #include "Parser.h"
2 |
3 |
4 | DWORD Registry::GetAppIdFromClsid(IN std::wstring clsid, OUT std::wstring& appId)
5 | {
6 | HKEY hClsidKey;
7 | std::wstring clsidSubKey = L"CLSID\\" + clsid;
8 | if (RegOpenKeyEx(HKEY_CLASSES_ROOT, clsidSubKey.c_str(), 0, KEY_READ, &hClsidKey) != ERROR_SUCCESS)
9 | {
10 | return ERROR_OPEN_FAILED;
11 | }
12 |
13 | TCHAR valueBuffer[256];
14 | DWORD valueBufferSize = sizeof(valueBuffer);
15 |
16 | if (RegQueryValueEx(hClsidKey, L"AppID", NULL, NULL, (LPBYTE)valueBuffer, &valueBufferSize) == ERROR_SUCCESS)
17 | {
18 | appId = valueBuffer;
19 | }
20 | else
21 | {
22 | return ERROR_NOT_FOUND;
23 | }
24 |
25 | RegCloseKey(hClsidKey);
26 |
27 | return ERROR_SUCCESS;
28 | }
29 |
30 | DWORD Registry::GetProgIdFromClsid(IN std::wstring clsid, OUT std::wstring& progId)
31 | {
32 | HKEY hKey;
33 | if (RegOpenKeyEx(HKEY_CLASSES_ROOT, NULL, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
34 | {
35 | return ERROR_OPEN_FAILED;
36 | }
37 |
38 | DWORD index = 0;
39 | TCHAR subKeyName[256];
40 | DWORD subKeyNameSize = sizeof(subKeyName) / sizeof(subKeyName[0]);
41 | LONG ret = ERROR_SUCCESS;
42 |
43 | while ((ret = RegEnumKeyEx(hKey, index, subKeyName, &subKeyNameSize, NULL, NULL, NULL, NULL)) == ERROR_SUCCESS)
44 | {
45 | HKEY hSubKey;
46 |
47 | if (RegOpenKeyEx(hKey, subKeyName, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
48 | {
49 | DWORD valueBufferSize = 0;
50 | if (RegQueryValueEx(hSubKey, L"CLSID", NULL, NULL, NULL, &valueBufferSize) == ERROR_SUCCESS)
51 | {
52 | TCHAR* valueBuffer = new TCHAR[valueBufferSize / sizeof(TCHAR)];
53 | if (RegQueryValueEx(hSubKey, L"CLSID", NULL, NULL, (LPBYTE)valueBuffer, &valueBufferSize) == ERROR_SUCCESS)
54 | {
55 | if (clsid == valueBuffer)
56 | {
57 | progId = subKeyName;
58 | delete[] valueBuffer;
59 | RegCloseKey(hSubKey);
60 | RegCloseKey(hKey);
61 | return ERROR_SUCCESS;
62 | }
63 | }
64 | delete[] valueBuffer;
65 | }
66 | RegCloseKey(hSubKey);
67 | }
68 |
69 | subKeyNameSize = sizeof(subKeyName) / sizeof(subKeyName[0]);
70 | index++;
71 | }
72 |
73 | RegCloseKey(hKey);
74 | return ERROR_NOT_FOUND;
75 | }
76 |
77 | DWORD Registry::GetRunAsKeyFromAppId(IN std::wstring appId, OUT std::wstring& runAs)
78 | {
79 | std::wstring appIdSubKey = L"AppID\\" + appId;
80 | HKEY hAppIdKey;
81 | if (RegOpenKeyEx(HKEY_CLASSES_ROOT, appIdSubKey.c_str(), 0, KEY_READ, &hAppIdKey) == ERROR_SUCCESS)
82 | {
83 | DWORD valueBufferSize = 256;
84 | TCHAR* valueBuffer = new TCHAR[valueBufferSize / sizeof(TCHAR)];
85 | if (RegQueryValueEx(hAppIdKey, L"RunAs", NULL, NULL, (LPBYTE)valueBuffer, &valueBufferSize) == ERROR_SUCCESS)
86 | {
87 | runAs = valueBuffer;
88 | return ERROR_SUCCESS;
89 | }
90 | RegCloseKey(hAppIdKey);
91 | }
92 | return ERROR_OBJECT_NOT_FOUND;
93 | }
94 |
95 |
96 | std::wstring TypeLib::GetTypeName(ITypeInfo* pTypeInfo, TYPEDESC* pTypeDesc)
97 | {
98 | CComBSTR bstrName;
99 | HRESULT hr = S_OK;
100 |
101 | switch (pTypeDesc->vt)
102 | {
103 | case VT_I2: return L"short";
104 | case VT_I4: return L"long";
105 | case VT_R4: return L"float";
106 | case VT_R8: return L"double";
107 | case VT_CY: return L"CURRENCY";
108 | case VT_DATE: return L"DATE";
109 | case VT_BSTR: return L"BSTR";
110 | case VT_DISPATCH: return L"IDispatch*";
111 | case VT_ERROR: return L"SCODE";
112 | case VT_BOOL: return L"VARIANT_BOOL";
113 | case VT_VARIANT: return L"VARIANT";
114 | case VT_UNKNOWN: return L"IUnknown*";
115 | case VT_DECIMAL: return L"DECIMAL";
116 | case VT_I1: return L"char";
117 | case VT_UI1: return L"unsigned char";
118 | case VT_UI2: return L"unsigned short";
119 | case VT_UI4: return L"unsigned long";
120 | case VT_INT: return L"int";
121 | case VT_UINT: return L"unsigned int";
122 | case VT_HRESULT: return L"HRESULT";
123 | case VT_VOID: return L"void";
124 | case VT_LPSTR: return L"LPSTR";
125 | case VT_LPWSTR: return L"LPWSTR";
126 | case VT_PTR:
127 | return GetTypeName(pTypeInfo, pTypeDesc->lptdesc) + L"*";
128 | case VT_USERDEFINED:
129 | {
130 | CComPtr spRefTypeInfo;
131 | hr = pTypeInfo->GetRefTypeInfo(pTypeDesc->hreftype, &spRefTypeInfo);
132 | if (SUCCEEDED(hr))
133 | {
134 | TYPEATTR* pRefTypeAttr;
135 | hr = spRefTypeInfo->GetTypeAttr(&pRefTypeAttr);
136 | if (SUCCEEDED(hr))
137 | {
138 | spRefTypeInfo->GetDocumentation(MEMBERID_NIL, &bstrName, NULL, NULL, NULL);
139 | spRefTypeInfo->ReleaseTypeAttr(pRefTypeAttr);
140 | return std::wstring(bstrName);
141 | }
142 | }
143 | }
144 | break;
145 | default:
146 | break;
147 | }
148 |
149 | return L"unknown";
150 | }
151 |
152 | DWORD TypeLib::GetMethodsFromTypelib(IN IUnknown* pUnknown, OUT std::vector& methods)
153 | {
154 | CComPtr pDispatch = nullptr;
155 | HRESULT hr;
156 |
157 | hr = pUnknown->QueryInterface(IID_IDispatch, (void**)&pDispatch);
158 | if (FAILED(hr))
159 | return hr;
160 |
161 | CComPtr spTypeInfo;
162 | TYPEATTR* pTypeAttr = nullptr;
163 |
164 | hr = pDispatch->GetTypeInfo(0, LOCALE_USER_DEFAULT, &spTypeInfo);
165 | if (FAILED(hr))
166 | {
167 | std::wcout << L"Failed to get type info." << std::endl;
168 | return hr;
169 | }
170 |
171 | hr = spTypeInfo->GetTypeAttr(&pTypeAttr);
172 | if (FAILED(hr))
173 | {
174 | std::wcout << L"Failed to get type attributes." << std::endl;
175 | return hr;
176 | }
177 |
178 | for (UINT i = 0; i < pTypeAttr->cFuncs; ++i)
179 | {
180 | FUNCDESC* pFuncDesc = nullptr;
181 | hr = spTypeInfo->GetFuncDesc(i, &pFuncDesc);
182 | if (SUCCEEDED(hr))
183 | {
184 | BSTR bstrName;
185 | UINT cNames;
186 | hr = spTypeInfo->GetNames(pFuncDesc->memid, &bstrName, 1, &cNames);
187 | if (SUCCEEDED(hr))
188 | {
189 | std::wstring returnType = GetTypeName(spTypeInfo, &pFuncDesc->elemdescFunc.tdesc);
190 |
191 | std::wstring callConv;
192 | switch (pFuncDesc->callconv)
193 | {
194 | case CC_FASTCALL:
195 | callConv = L"__fastcall";
196 | break;
197 | case CC_CDECL:
198 | callConv = L"__cdecl";
199 | break;
200 | case CC_MPWPASCAL:
201 | case CC_PASCAL:
202 | callConv = L"__pascal";
203 | break;
204 | case CC_MACPASCAL:
205 | callConv = L"__macpascal";
206 | break;
207 | case CC_MPWCDECL:
208 | case CC_SYSCALL:
209 | case CC_STDCALL:
210 | callConv = L"__stdcall";
211 | break;
212 | case CC_FPFASTCALL:
213 | callConv = L"__fpfastcall";
214 | break;
215 | default:
216 | callConv = L"";
217 | break;
218 | }
219 |
220 | std::wstring params;
221 | for (UINT j = 0; j < pFuncDesc->cParams; ++j)
222 | {
223 | if (j > 0) params += L", ";
224 |
225 | std::wstring paramFlag;
226 | if (pFuncDesc->lprgelemdescParam[j].paramdesc.wParamFlags & PARAMFLAG_FIN)
227 | paramFlag += L"IN ";
228 | if (pFuncDesc->lprgelemdescParam[j].paramdesc.wParamFlags & PARAMFLAG_FOUT)
229 | paramFlag += L"OUT ";
230 |
231 | params += paramFlag + GetTypeName(spTypeInfo, &pFuncDesc->lprgelemdescParam[j].tdesc);
232 | }
233 |
234 | methods.push_back(callConv + L" " + returnType + L" " + bstrName + L"(" + params + L")");
235 |
236 |
237 | SysFreeString(bstrName);
238 | }
239 | spTypeInfo->ReleaseFuncDesc(pFuncDesc);
240 | }
241 | }
242 |
243 | spTypeInfo->ReleaseTypeAttr(pTypeAttr);
244 |
245 | return ERROR_SUCCESS;
246 | }
247 |
248 | std::wstring Process::GetUserNameFromSID(PSID sid)
249 | {
250 | WCHAR name[256];
251 | WCHAR domain[256];
252 | DWORD nameSize = sizeof(name) / sizeof(WCHAR);
253 | DWORD domainSize = sizeof(domain) / sizeof(WCHAR);
254 | SID_NAME_USE sidUse;
255 |
256 | if (!LookupAccountSid(NULL, sid, name, &nameSize, domain, &domainSize, &sidUse))
257 | return L"";
258 |
259 | std::wstring fullName(domain);
260 | fullName += L"\\\\";
261 | fullName += name;
262 |
263 | return fullName;
264 | }
265 |
266 | std::wstring Process::GetProcessUserName(DWORD pid)
267 | {
268 | HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
269 | if (!hProcess)
270 | return L"";
271 |
272 | HANDLE hToken;
273 | if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
274 | {
275 | CloseHandle(hProcess);
276 | return L"";
277 | }
278 |
279 | DWORD bufferSize = 0;
280 | GetTokenInformation(hToken, TokenUser, NULL, 0, &bufferSize);
281 |
282 | if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
283 | {
284 | CloseHandle(hToken);
285 | CloseHandle(hProcess);
286 | return L"";
287 | }
288 |
289 | std::vector buffer(bufferSize);
290 | if (!GetTokenInformation(hToken, TokenUser, buffer.data(), bufferSize, &bufferSize))
291 | {
292 | CloseHandle(hToken);
293 | CloseHandle(hProcess);
294 | return L"";
295 | }
296 |
297 | PSID sid = reinterpret_cast(buffer.data())->User.Sid;
298 | std::wstring userName = Process::GetUserNameFromSID(sid);
299 |
300 | CloseHandle(hToken);
301 | CloseHandle(hProcess);
302 |
303 | return userName;
304 | }
305 |
306 | BOOL Process::GetPIDFromIUnknown(IN IUnknown* pUnknown, OUT DWORD* pid)
307 | {
308 | CComPtr marshalStream;
309 | CreateStreamOnHGlobal(NULL, TRUE, &marshalStream);
310 |
311 | CoMarshalInterface(
312 | marshalStream,
313 | IID_IUnknown,
314 | pUnknown,
315 | MSHCTX_INPROC,
316 | NULL,
317 | MSHLFLAGS_NORMAL
318 | );
319 |
320 | HGLOBAL memoryHandleFromStream = NULL;
321 | GetHGlobalFromStream(marshalStream, &memoryHandleFromStream);
322 |
323 | LPOBJREF objref = reinterpret_cast (GlobalLock(memoryHandleFromStream));
324 | if (objref && objref->signature == OBJREF_SIGNATURE)
325 | {
326 | IPID ipid;
327 |
328 | if (objref->flags == OBJREF_STANDARD)
329 | {
330 | ipid = objref->u_objref.u_standard.std.ipid;
331 | }
332 | else if (objref->flags == OBJREF_HANDLER)
333 | {
334 | ipid = objref->u_objref.u_handler.std.ipid;
335 | }
336 | else if (objref->flags == OBJREF_EXTENDED)
337 | {
338 | ipid = objref->u_objref.u_extended.std.ipid;
339 | }
340 | else if (objref->flags == OBJREF_CUSTOM)
341 | {
342 | return FALSE;
343 | }
344 |
345 | static const int COM_SERVER_PID_OFFSET = 4;
346 |
347 | *pid = *reinterpret_cast(
348 | (reinterpret_cast(&ipid) + COM_SERVER_PID_OFFSET)
349 | );
350 | return *pid != 0xffff;
351 | }
352 | }
353 |
354 | std::wstring Process::GetProcessName(DWORD processID) {
355 | std::wstring processName = L"";
356 |
357 | HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
358 |
359 | if (NULL != hProcess) {
360 | HMODULE hMod;
361 | DWORD cbNeeded;
362 |
363 | if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) {
364 | wchar_t szProcessName[MAX_PATH];
365 | if (GetModuleBaseName(hProcess, hMod, szProcessName, sizeof(szProcessName) / sizeof(wchar_t))) {
366 | processName = szProcessName;
367 | }
368 | }
369 | else
370 | {
371 | std::wcout << L"[-] EnumProcessModules() Failed: " << GetLastError() << std::endl;
372 | }
373 |
374 | CloseHandle(hProcess);
375 | }
376 |
377 | return processName;
378 | }
--------------------------------------------------------------------------------
/ClsidExplorer/CLSIDExplorer/Parser.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | static class Registry
11 | {
12 | public:
13 | static DWORD GetAppIdFromClsid(IN std::wstring clsid, OUT std::wstring& appId);
14 | static DWORD GetProgIdFromClsid(IN std::wstring clsid, OUT std::wstring& progId);
15 | static DWORD GetRunAsKeyFromAppId(IN std::wstring appId, OUT std::wstring& runAs);
16 |
17 | private:
18 |
19 | };
20 |
21 | static class TypeLib
22 | {
23 | public:
24 | static DWORD GetMethodsFromTypelib(IN IUnknown* pUnknown, OUT std::vector& methods);
25 | static std::wstring GetTypeName(ITypeInfo* pTypeInfo, TYPEDESC* pTypeDesc);
26 | };
27 |
28 |
29 | static class Process
30 | {
31 | public:
32 | static std::wstring GetProcessUserName(DWORD pid);
33 | static std::wstring GetProcessName(DWORD processID);
34 | static std::wstring GetUserNameFromSID(PSID sid);
35 | static BOOL GetPIDFromIUnknown(IN IUnknown* pUnknown, OUT DWORD* pid);
36 | };
37 |
38 |
39 |
40 | typedef struct tagDATAELEMENT
41 | {
42 | GUID dataID;
43 | unsigned long cbSize;
44 | unsigned long cbRounded;
45 | /* [size_is] */ BYTE Data[1];
46 | } DATAELEMENT;
47 |
48 | typedef struct tagDUALSTRINGARRAY
49 | {
50 | unsigned short wNumEntries;
51 | unsigned short wSecurityOffset;
52 | /* [size_is] */ unsigned short aStringArray[1];
53 | } DUALSTRINGARRAY;
54 |
55 | typedef unsigned __int64 OXID;
56 | typedef unsigned __int64 OID;
57 | typedef GUID IPID;
58 |
59 | typedef struct tagOBJREFDATA
60 | {
61 | unsigned long nElms;
62 | /* [unique][size_is][size_is] */ DATAELEMENT** ppElmArray;
63 | } OBJREFDATA;
64 |
65 | typedef struct tagSTDOBJREF {
66 | unsigned long flags;
67 | unsigned long cPublicRefs;
68 | OXID oxid;
69 | OID oid;
70 | IPID ipid;
71 | } STDOBJREF;
72 |
73 | typedef struct tagOBJREF {
74 | unsigned long signature;
75 | unsigned long flags;
76 | GUID iid;
77 | union {
78 | struct {
79 | STDOBJREF std;
80 | DUALSTRINGARRAY saResAddr;
81 | } u_standard;
82 | struct {
83 | STDOBJREF std;
84 | CLSID clsid;
85 | DUALSTRINGARRAY saResAddr;
86 | } u_handler;
87 | struct {
88 | CLSID clsid;
89 | unsigned long cbExtension;
90 | unsigned long size;
91 | byte* pData;
92 | } u_custom;
93 | struct {
94 | STDOBJREF std;
95 | unsigned long Signature1;
96 | DUALSTRINGARRAY saResAddr;
97 | unsigned long nElms;
98 | unsigned long Signature2;
99 | DATAELEMENT ElmArray;
100 | } u_extended;
101 | } u_objref;
102 | } OBJREF, * LPOBJREF;
103 |
104 | typedef struct _IPID_ENTRY {
105 | IID iid;
106 | IPID ipid; // IPID to bind to
107 | OXID oxid; // Object Exporter ID
108 | OID oid;
109 | } IPID_ENTRY, * PIPID_ENTRY;
110 |
111 |
112 | #define OBJREF_SIGNATURE ( 0x574f454d )
113 |
114 | #define OBJREF_STANDARD ( 0x1 )
115 | #define OBJREF_HANDLER ( 0x2 )
116 | #define OBJREF_CUSTOM ( 0x4 )
117 | #define OBJREF_EXTENDED ( 0x8 )
--------------------------------------------------------------------------------
/ClsidExplorer/CLSIDExplorer/main.cpp:
--------------------------------------------------------------------------------
1 | #include "main.h"
2 | #include "Parser.h"
3 |
4 | void ShowHelp()
5 | {
6 | std::wcout << L"CLSIDExplorer.exe - get all info about clsid" << std::endl;
7 | std::wcout << L"Usage:" << std::endl;
8 | std::wcout << L".\\CLSIDExplorer.exe --clsid \"{00000618-0000-0010-8000-00aa006d2ea4}\"" << std::endl;
9 | }
10 |
11 | int wmain(int argc, wchar_t* argv[])
12 | {
13 | setlocale(LC_ALL, "");
14 |
15 | std::wstring wsclsid;
16 | for (int i = 1; i < argc; ++i) {
17 | if (std::wstring(argv[i]) == L"--clsid" && i + 1 < argc) {
18 | wsclsid = argv[i + 1];
19 | }
20 | }
21 |
22 | if (argc != 3 || wsclsid.size() == 0)
23 | {
24 | ShowHelp();
25 | return -1;
26 | }
27 |
28 | std::wcout << L"[" << wsclsid << L"]" << std::endl;
29 |
30 | CoInitialize(NULL);
31 |
32 | HRESULT hr;
33 |
34 | CLSID clsid;
35 | hr = CLSIDFromString(wsclsid.c_str(), &clsid);
36 | if (FAILED(hr))
37 | {
38 | std::wcout << L"[-] Cannot convert to CLSID: " << wsclsid << std::endl;
39 | return hr;
40 | }
41 |
42 | std::wstring appId;
43 | if (Registry::GetAppIdFromClsid(wsclsid, appId) == ERROR_SUCCESS)
44 | {
45 | std::wcout << L"\tAppID: " << appId << std::endl;
46 | }
47 | else {
48 | std::wcout << L"\tAppID: Unknown" << std::endl;
49 | }
50 |
51 | std::wstring progId;
52 | if (Registry::GetProgIdFromClsid(wsclsid, progId) == ERROR_SUCCESS)
53 | {
54 | std::wcout << L"\tProgID: " << progId << std::endl;
55 | }
56 | else {
57 | std::wcout << L"\tProgID: Unknown" << std::endl;
58 | }
59 |
60 | std::wstring runAs;
61 | if (!appId.empty())
62 | {
63 | if (Registry::GetRunAsKeyFromAppId(appId, runAs) == ERROR_SUCCESS)
64 | {
65 | std::wcout << L"\tRunAs: " << runAs << std::endl;
66 | }
67 | else {
68 | std::wcout << L"\tRunAs: The launching user" << std::endl;
69 | }
70 | }
71 |
72 | CComPtr pUnknown = nullptr;
73 |
74 | hr = CoCreateInstance(clsid,
75 | nullptr,
76 | CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
77 | IID_IUnknown,
78 | reinterpret_cast(&pUnknown));
79 |
80 | DWORD pid;
81 | if (Process::GetPIDFromIUnknown(pUnknown, &pid))
82 | {
83 | std::wcout << L"\tPID: " << pid << std::endl;
84 |
85 | std::wcout << L"\tProcess Name: " << Process::GetProcessName(pid) << std::endl;
86 |
87 | std::wcout << L"\tUsername: " << Process::GetProcessUserName(pid) << std::endl;
88 |
89 | }
90 | else {
91 | std::wcout << L"\tPID: Unknown" << std::endl;
92 | }
93 |
94 | std::vector methods;
95 |
96 | if (TypeLib::GetMethodsFromTypelib(pUnknown, methods) == ERROR_SUCCESS)
97 | {
98 | std::wcout << "\tMethods:" << std::endl;
99 |
100 | for (int i = 0; i < methods.size(); i++)
101 | {
102 | std::wcout << " \t[" << i << L"] " << methods[i] << std::endl;
103 | }
104 | }
105 |
106 |
107 | std::wcout << L"[END]" << std::endl;
108 |
109 | return 0;
110 | }
--------------------------------------------------------------------------------
/ClsidExplorer/CLSIDExplorer/main.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include
--------------------------------------------------------------------------------
/ClsidExplorer/x64/Debug/CLSIDExplorer.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CICADA8-Research/COMThanasia/903e83ab569fef88b47d8a1d607bf44669d60da1/ClsidExplorer/x64/Debug/CLSIDExplorer.exe
--------------------------------------------------------------------------------
/ClsidExplorer/x64/Debug/CLSIDExplorer.pdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CICADA8-Research/COMThanasia/903e83ab569fef88b47d8a1d607bf44669d60da1/ClsidExplorer/x64/Debug/CLSIDExplorer.pdb
--------------------------------------------------------------------------------
/ComDiver/COMDiver.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.7.34009.444
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "COMDiver", "COMDiver\COMDiver.vcxproj", "{3930EDD4-E045-4374-AD0F-F4DF414A393A}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Debug|x86 = Debug|x86
12 | Release|x64 = Release|x64
13 | Release|x86 = Release|x86
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {3930EDD4-E045-4374-AD0F-F4DF414A393A}.Debug|x64.ActiveCfg = Debug|x64
17 | {3930EDD4-E045-4374-AD0F-F4DF414A393A}.Debug|x64.Build.0 = Debug|x64
18 | {3930EDD4-E045-4374-AD0F-F4DF414A393A}.Debug|x86.ActiveCfg = Debug|Win32
19 | {3930EDD4-E045-4374-AD0F-F4DF414A393A}.Debug|x86.Build.0 = Debug|Win32
20 | {3930EDD4-E045-4374-AD0F-F4DF414A393A}.Release|x64.ActiveCfg = Release|x64
21 | {3930EDD4-E045-4374-AD0F-F4DF414A393A}.Release|x64.Build.0 = Release|x64
22 | {3930EDD4-E045-4374-AD0F-F4DF414A393A}.Release|x86.ActiveCfg = Release|Win32
23 | {3930EDD4-E045-4374-AD0F-F4DF414A393A}.Release|x86.Build.0 = Release|Win32
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {2FD2A10C-7BE0-4E0F-AD1C-128D69CAA423}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/ComDiver/COMDiver/COMDiver.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 | 17.0
23 | Win32Proj
24 | {3930edd4-e045-4374-ad0f-f4df414a393a}
25 | COMDiver
26 | 10.0
27 | ComDiver
28 |
29 |
30 |
31 | Application
32 | true
33 | v143
34 | Unicode
35 |
36 |
37 | Application
38 | false
39 | v143
40 | true
41 | Unicode
42 |
43 |
44 | Application
45 | true
46 | v143
47 | Unicode
48 |
49 |
50 | Application
51 | false
52 | v143
53 | true
54 | Unicode
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | Level3
77 | true
78 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
79 | true
80 |
81 |
82 | Console
83 | true
84 |
85 |
86 |
87 |
88 | Level3
89 | true
90 | true
91 | true
92 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
93 | true
94 |
95 |
96 | Console
97 | true
98 | true
99 | true
100 |
101 |
102 |
103 |
104 | Level3
105 | true
106 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
107 | true
108 |
109 |
110 | Console
111 | true
112 |
113 |
114 |
115 |
116 | Level3
117 | true
118 | true
119 | true
120 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
121 | true
122 |
123 |
124 | Console
125 | true
126 | true
127 | true
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
--------------------------------------------------------------------------------
/ComDiver/COMDiver/COMDiver.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Исходные файлы
20 |
21 |
22 | Исходные файлы
23 |
24 |
25 | Исходные файлы
26 |
27 |
28 | Исходные файлы
29 |
30 |
31 |
32 |
33 | Файлы заголовков
34 |
35 |
36 | Файлы заголовков
37 |
38 |
39 | Файлы заголовков
40 |
41 |
42 | Файлы заголовков
43 |
44 |
45 |
--------------------------------------------------------------------------------
/ComDiver/COMDiver/COMDiver.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | --target "{52B65EB7-907C-4D83-A535-283BE9104DE4}"
5 | WindowsLocalDebugger
6 |
7 |
--------------------------------------------------------------------------------
/ComDiver/COMDiver/analyzer.cpp:
--------------------------------------------------------------------------------
1 | #include "analyzer.h"
2 | #include "enumerator.h"
3 |
4 | void SetConsoleColor(WORD color)
5 | {
6 | HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
7 | SetConsoleTextAttribute(hConsole, color);
8 | }
9 |
10 | std::wstring toLowerCase(const std::wstring& input) {
11 | std::wstring result = input;
12 | std::transform(result.begin(), result.end(), result.begin(), ::tolower);
13 | return result;
14 | }
15 |
16 | void WriteRedText(const std::wstring& text)
17 | {
18 | SetConsoleColor(FOREGROUND_RED | FOREGROUND_INTENSITY);
19 |
20 | std::wcout << text << std::endl;
21 |
22 | SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
23 | }
24 |
25 | void WriteGreenText(const std::wstring& text)
26 | {
27 | SetConsoleColor(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
28 |
29 | std::wcout << text << std::endl;
30 |
31 | SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
32 | }
33 |
34 | bool CheckRegistryKeyExists(HKEY hive, const std::wstring& path) {
35 | HKEY hKey;
36 | DWORD res = RegOpenKeyEx(hive, path.c_str(), 0, KEY_READ, &hKey);
37 | if (res == ERROR_SUCCESS) {
38 | RegCloseKey(hKey);
39 | return true;
40 | }
41 | return false;
42 | }
43 |
44 |
45 | std::wstring GetFullPathFromPID(DWORD pid, const std::wstring& fileName) {
46 | HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
47 | if (hProcess) {
48 | wchar_t processPath[MAX_PATH];
49 | if (GetModuleFileNameEx(hProcess, NULL, processPath, MAX_PATH)) {
50 | wchar_t* filePart;
51 | if (GetFullPathName(fileName.c_str(), MAX_PATH, processPath, &filePart)) {
52 | CloseHandle(hProcess);
53 | return std::wstring(processPath);
54 | }
55 | }
56 | CloseHandle(hProcess);
57 | }
58 | return fileName;
59 | }
60 |
61 | std::wstring GetCurrentUsername()
62 | {
63 | wchar_t username[255 + 1];
64 | DWORD username_len = 255 + 1;
65 | if (GetUserNameW(username, &username_len)) {
66 | return std::wstring(username);
67 | }
68 | else {
69 | return L"";
70 | }
71 | }
72 |
73 | std::wstring ExpandEnvironmentStringsIfNeeded(const std::wstring& input) {
74 | if (input.empty()) {
75 | return input;
76 | }
77 |
78 | std::vector expandedPath(MAX_PATH);
79 | DWORD result = ExpandEnvironmentStrings(input.c_str(), expandedPath.data(), MAX_PATH);
80 | if (result == 0 || result > MAX_PATH) {
81 | return input;
82 | }
83 |
84 | return std::wstring(expandedPath.data());
85 | }
86 |
87 | std::wstring GetRegistryStringValue(HKEY hKeyRoot, const std::wstring& subKey) {
88 | HKEY hKey;
89 | LONG lResult = RegOpenKeyEx(hKeyRoot, subKey.c_str(), 0, KEY_READ, &hKey);
90 |
91 | if (lResult != ERROR_SUCCESS) {
92 | DWORD dw = GetLastError();
93 | return L"";
94 | }
95 |
96 | DWORD dwType = 0;
97 | DWORD dwSize = 0;
98 | lResult = RegQueryValueEx(hKey, nullptr, nullptr, &dwType, nullptr, &dwSize);
99 |
100 | if (lResult != ERROR_SUCCESS || (dwType != REG_SZ && dwType != REG_EXPAND_SZ)) {
101 | RegCloseKey(hKey);
102 | return L"";
103 | }
104 |
105 | std::wstring value(dwSize / sizeof(wchar_t), L'\0');
106 | lResult = RegQueryValueEx(hKey, nullptr, nullptr, nullptr, reinterpret_cast(&value[0]), &dwSize);
107 |
108 | RegCloseKey(hKey);
109 |
110 | if (lResult != ERROR_SUCCESS) {
111 | return L"";
112 | }
113 |
114 | if (!value.empty() && value.back() == L'\0') {
115 | value.pop_back();
116 | }
117 |
118 | if (dwType == REG_EXPAND_SZ) {
119 | value = ExpandEnvironmentStringsIfNeeded(value);
120 | }
121 |
122 | return value;
123 | }
124 |
125 | bool CheckFileWriteAccess(const std::wstring& filePath)
126 | {
127 | DWORD filePermissions = GENERIC_WRITE;
128 | HANDLE hFile = CreateFile(filePath.c_str(), filePermissions, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
129 | if (hFile == INVALID_HANDLE_VALUE)
130 | {
131 | DWORD dw = GetLastError();
132 | return false;
133 | }
134 | else {
135 | CloseHandle(hFile);
136 | return true;
137 | }
138 | }
139 |
140 | std::wstring GetRootKeyName(HKEY hKey) {
141 | if (hKey == HKEY_CURRENT_USER) return L"HKCU";
142 | if (hKey == HKEY_LOCAL_MACHINE) return L"HKLM";
143 | if (hKey == HKEY_CLASSES_ROOT) return L"HKCR";
144 | return L"";
145 | }
146 |
147 | std::pair FindPathFromRegistry(const std::wstring& clsid)
148 | {
149 | const std::wstring paths[] = {
150 | L"SOFTWARE\\Classes\\CLSID\\" + clsid + L"\\TreatAs",
151 | L"SOFTWARE\\Classes\\CLSID\\" + clsid + L"\\InprocServer32",
152 | L"SOFTWARE\\Classes\\CLSID\\" + clsid + L"\\LocalServer32"
153 | };
154 |
155 | for (const auto& hKey : { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE })
156 | {
157 | for (const auto& partialPath : paths)
158 | {
159 | std::wstring value = GetRegistryStringValue(hKey, partialPath);
160 | if (!value.empty())
161 | {
162 | std::wstring fullPath = GetRootKeyName(hKey) + L"\\" + partialPath;
163 | return { value, fullPath };
164 | }
165 | }
166 | }
167 |
168 | return { L"", L"" };
169 | }
170 |
171 | bool CheckRegistryWriteCreateAccess(HKEY hive, const std::wstring& path)
172 | {
173 | HKEY hKey;
174 | REGSAM samDesired = KEY_WRITE | KEY_CREATE_SUB_KEY;
175 |
176 | DWORD res = RegOpenKeyEx(hive, path.c_str(), 0, samDesired, &hKey);
177 | if (res == ERROR_SUCCESS)
178 | {
179 | RegCloseKey(hKey);
180 | return true;
181 | }
182 |
183 | res = RegCreateKeyEx(hive, path.c_str(), 0, NULL,
184 | REG_OPTION_VOLATILE, // temporary key
185 | KEY_WRITE | KEY_CREATE_SUB_KEY,
186 | NULL, &hKey, NULL);
187 |
188 | if (res == ERROR_SUCCESS)
189 | {
190 | RegCloseKey(hKey);
191 |
192 | RegDeleteKey(hive, path.c_str());
193 |
194 | return true;
195 | }
196 | return false;
197 | }
198 |
199 | std::wstring GetFileName(const std::wstring& path)
200 | {
201 | if (path.empty()) {
202 | return L"";
203 | }
204 |
205 | size_t start = 0;
206 | size_t end = path.length();
207 |
208 | if (path[0] == L'"') {
209 | start = 1;
210 | for (size_t i = start; i < path.length(); ++i) {
211 | if (path[i] == L'"') {
212 | end = i;
213 | break;
214 | }
215 | }
216 | }
217 | else {
218 | for (size_t i = 0; i < path.length(); ++i) {
219 | if (path[i] == L' ') {
220 | end = i;
221 | break;
222 | }
223 | }
224 | }
225 |
226 | return path.substr(start, end - start);
227 | }
228 |
229 | VOID AnalyzeCLSID(std::wstring& wsclsid, BOOL checkCreate, BOOL checkAnotherContext)
230 | {
231 | HRESULT hr;
232 | CComPtr pUnknown = nullptr;
233 |
234 | CLSID clsid;
235 |
236 |
237 | hr = CLSIDFromString(wsclsid.c_str(), &clsid);
238 | if (!SUCCEEDED(hr))
239 | {
240 | //std::wcout << L"\t[-] Error in converting " << wsclsid << L" to CLSID" << std::endl;
241 | return;
242 | }
243 |
244 | std::wcout << L"----------------------------" << std::endl;
245 | std::wcout << L"----[" << wsclsid << L"]----" << std::endl;
246 |
247 | // Checking Create Rights
248 | if (checkCreate)
249 | {
250 | hr = CoCreateInstance(clsid,
251 | nullptr,
252 | CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
253 | IID_IUnknown,
254 | reinterpret_cast(&pUnknown));
255 |
256 | if (!SUCCEEDED(hr))
257 | {
258 | std::wcout << L"\t[-] Error in CoCreateInstance: " << hr << L" CLSID: " << wsclsid << std::endl;
259 | return;
260 | }
261 | }
262 |
263 | std::wstring username = L"";
264 | std::wstring processName = L"";
265 | std::wstring runAs = L"";
266 | DWORD pid = 0;
267 |
268 |
269 | // Checking another user context
270 | if (checkAnotherContext)
271 | {
272 | std::wstring appId = L"";
273 |
274 | if (GetAppIdFromClsid(wsclsid, appId) != ERROR_SUCCESS)
275 | {
276 | //std::wcout << L"\t[-] Can't find AppId. May be there is no another context" << std::endl;
277 | return;
278 | }
279 |
280 | if (GetRunAsKeyFromAppId(appId, runAs) != ERROR_SUCCESS)
281 | {
282 | //std::wcout << L"\t[-] Cant get PID and cant get RunAs key -> NO ANOTHER CONTEXT" << std::endl;
283 | return;
284 | }
285 |
286 | if (GetPIDFromIUnknown(pUnknown, &pid) == TRUE)
287 | {
288 | std::wstring currentUsername = GetCurrentUsername();
289 | username = GetProcessUserName(pid);
290 |
291 | if (username.find(currentUsername) != std::wstring::npos && runAs.empty())
292 | {
293 | //std::wcout << L"\t[+] Running from current user: " << username << std::endl;
294 | // runAs.empty() <- NO Option Interactive User
295 | return;
296 | }
297 |
298 | processName = GetProcessName(pid);
299 |
300 | }
301 | }
302 |
303 | std::wcout << L"\t[+] Username: " << username << std::endl;
304 | std::wcout << L"\t[+] RunAs Value: " << runAs << std::endl;
305 | std::wcout << L"\t[+] Process: " << processName << std::endl;
306 | std::wcout << L"\t[+] PID: " << pid << std::endl;
307 |
308 | // Analiyzing Insecure Registry Permissions
309 | std::pair result = FindPathFromRegistry(wsclsid);
310 |
311 | if (result.first.empty())
312 | {
313 | //std::wcout << L"No associated file found for CLSID " << wsclsid << std::endl;
314 | return;
315 | }
316 |
317 | std::wcout << L"\t[+] Disk Path: " << result.first << std::endl;
318 | std::wcout << L"\t[+] Registry Path: " << result.second << std::endl;
319 |
320 | std::wcout << L"\t[?] Load priority hijacking: " << std::endl;
321 | const std::wstring priorities[] = {
322 | L"HKCU\\Software\\Classes\\CLSID\\" + wsclsid + L"\\TreatAs",
323 | L"HKLM\\Software\\Classes\\CLSID\\" + wsclsid + L"\\TreatAs",
324 | L"HKCU\\Software\\Classes\\CLSID\\" + wsclsid + L"\\InprocServer32",
325 | L"HKLM\\Software\\Classes\\CLSID\\" + wsclsid + L"\\InprocServer32",
326 | L"HKCU\\Software\\Classes\\CLSID\\" + wsclsid + L"\\LocalServer32",
327 | L"HKLM\\Software\\Classes\\CLSID\\" + wsclsid + L"\\LocalServer32"
328 | };
329 |
330 | for (size_t i = 0; i < std::size(priorities); ++i) {
331 | const auto& path = priorities[i];
332 | HKEY hKey;
333 | if (path.find(L"HKCU") == 0)
334 | hKey = HKEY_CURRENT_USER;
335 | else if (path.find(L"HKLM") == 0)
336 | hKey = HKEY_LOCAL_MACHINE;
337 | else
338 | continue;
339 |
340 | bool exists = CheckRegistryKeyExists(hKey, path.substr(path.find_first_of(L'\\') + 1));
341 | bool writable = CheckRegistryWriteCreateAccess(hKey, path.substr(path.find_first_of(L'\\') + 1));
342 |
343 | std::wstring output = L"\t\t[" + std::to_wstring(i + 1) + L"] " + (writable ? L"Writable" : L"Non Writable") + L": ";
344 | output += path + L" (" + (exists ? L"Exists" : L"Does not exists") + L")";
345 |
346 | if (writable) {
347 | WriteRedText(output);
348 | }
349 | else {
350 | std::wcout << output << std::endl;
351 | }
352 |
353 | if (toLowerCase(path) == toLowerCase(result.second))
354 | {
355 | WriteGreenText(L"\t\t[" + std::to_wstring(i + 1) + L"] Real Path: " + path);
356 | break;
357 | }
358 | }
359 |
360 |
361 | // Analyzing File Disk Permissions
362 | std::wstring strippedPath = GetFileName(result.first);
363 | if (PathIsRelative(strippedPath.c_str())) {
364 | strippedPath = GetFullPathFromPID(pid, strippedPath);
365 | }
366 |
367 | if (CheckFileWriteAccess(strippedPath))
368 | {
369 | WriteRedText(L"\t[+] Writable path on disk: " + strippedPath);
370 | }
371 |
372 |
373 | return;
374 | }
--------------------------------------------------------------------------------
/ComDiver/COMDiver/analyzer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | VOID AnalyzeCLSID(std::wstring& clsid, BOOL checkCreate, BOOL checkAnotherContext);
--------------------------------------------------------------------------------
/ComDiver/COMDiver/argparse.cpp:
--------------------------------------------------------------------------------
1 | #include "argparse.h"
2 |
3 | wchar_t* getCmdOption(wchar_t** begin, wchar_t** end, const std::wstring& option)
4 | {
5 | wchar_t** itr = std::find(begin, end, option);
6 | if (itr != end && ++itr != end)
7 | {
8 | return *itr;
9 | }
10 | return nullptr;
11 | }
12 |
13 | bool cmdOptionExists(wchar_t** begin, wchar_t** end, const std::wstring& option)
14 | {
15 | return std::find(begin, end, option) != end;
16 | }
--------------------------------------------------------------------------------
/ComDiver/COMDiver/argparse.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 |
5 | bool cmdOptionExists(wchar_t** begin, wchar_t** end, const std::wstring& option);
6 | wchar_t* getCmdOption(wchar_t** begin, wchar_t** end, const std::wstring& option);
--------------------------------------------------------------------------------
/ComDiver/COMDiver/enumerator.cpp:
--------------------------------------------------------------------------------
1 | #include "enumerator.h"
2 |
3 | std::vector EnumerateCLSID()
4 | {
5 | std::vector clsidList;
6 | HKEY hKey;
7 | LONG nError;
8 |
9 | nError = RegOpenKeyEx(HKEY_CLASSES_ROOT, L"CLSID", 0, KEY_READ, &hKey);
10 | if (nError == ERROR_SUCCESS)
11 | {
12 | DWORD dwIndex = 0;
13 | WCHAR szName[MAX_PATH];
14 | DWORD dwNameSize = _countof(szName);
15 | FILETIME ftLastWriteTime;
16 |
17 | while (RegEnumKeyEx(hKey, dwIndex, szName, &dwNameSize, NULL, NULL, NULL, &ftLastWriteTime) == ERROR_SUCCESS)
18 | {
19 | clsidList.push_back(szName);
20 | dwNameSize = _countof(szName);
21 | dwIndex++;
22 | }
23 |
24 | RegCloseKey(hKey);
25 | }
26 | else
27 | {
28 | std::wcerr << L"Cant open HKEY_CLASSES_ROOT\\CLSID. Error: " << nError << std::endl;
29 | }
30 |
31 | return clsidList;
32 | }
33 |
34 | DWORD GetAppIdFromClsid(IN std::wstring clsid, OUT std::wstring& appId)
35 | {
36 | HKEY hClsidKey;
37 | std::wstring clsidSubKey = L"CLSID\\" + clsid;
38 | if (RegOpenKeyEx(HKEY_CLASSES_ROOT, clsidSubKey.c_str(), 0, KEY_READ, &hClsidKey) != ERROR_SUCCESS)
39 | {
40 | return ERROR_OPEN_FAILED;
41 | }
42 |
43 | TCHAR valueBuffer[256];
44 | DWORD valueBufferSize = sizeof(valueBuffer);
45 |
46 | if (RegQueryValueEx(hClsidKey, L"AppID", NULL, NULL, (LPBYTE)valueBuffer, &valueBufferSize) == ERROR_SUCCESS)
47 | {
48 | appId = valueBuffer;
49 | }
50 |
51 | RegCloseKey(hClsidKey);
52 |
53 | return ERROR_SUCCESS;
54 | }
55 |
56 | DWORD GetProgIdFromClsid(IN std::wstring clsid, OUT std::wstring& progId)
57 | {
58 | HKEY hKey;
59 | if (RegOpenKeyEx(HKEY_CLASSES_ROOT, NULL, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
60 | {
61 | return ERROR_OPEN_FAILED;
62 | }
63 |
64 | DWORD index = 0;
65 | TCHAR subKeyName[256];
66 | DWORD subKeyNameSize = sizeof(subKeyName) / sizeof(subKeyName[0]);
67 | LONG ret = ERROR_SUCCESS;
68 |
69 | while ((ret = RegEnumKeyEx(hKey, index, subKeyName, &subKeyNameSize, NULL, NULL, NULL, NULL)) == ERROR_SUCCESS)
70 | {
71 | HKEY hSubKey;
72 |
73 | if (RegOpenKeyEx(hKey, subKeyName, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
74 | {
75 | DWORD valueBufferSize = 0;
76 | if (RegQueryValueEx(hSubKey, L"CLSID", NULL, NULL, NULL, &valueBufferSize) == ERROR_SUCCESS)
77 | {
78 | TCHAR* valueBuffer = new TCHAR[valueBufferSize / sizeof(TCHAR)];
79 | if (RegQueryValueEx(hSubKey, L"CLSID", NULL, NULL, (LPBYTE)valueBuffer, &valueBufferSize) == ERROR_SUCCESS)
80 | {
81 | if (clsid == valueBuffer)
82 | {
83 | progId = subKeyName;
84 | delete[] valueBuffer;
85 | RegCloseKey(hSubKey);
86 | RegCloseKey(hKey);
87 | return ERROR_SUCCESS;
88 | }
89 | }
90 | delete[] valueBuffer;
91 | }
92 | RegCloseKey(hSubKey);
93 | }
94 |
95 | subKeyNameSize = sizeof(subKeyName) / sizeof(subKeyName[0]);
96 | index++;
97 | }
98 |
99 | RegCloseKey(hKey);
100 | return ERROR_NOT_FOUND;
101 | }
102 |
103 | DWORD GetRunAsKeyFromAppId(IN std::wstring appId, OUT std::wstring& runAs)
104 | {
105 | std::wstring appIdSubKey = L"AppID\\" + appId;
106 | HKEY hAppIdKey;
107 | if (RegOpenKeyEx(HKEY_CLASSES_ROOT, appIdSubKey.c_str(), 0, KEY_READ, &hAppIdKey) == ERROR_SUCCESS)
108 | {
109 | DWORD valueBufferSize = 256;
110 | TCHAR* valueBuffer = new TCHAR[valueBufferSize / sizeof(TCHAR)];
111 | if (RegQueryValueEx(hAppIdKey, L"RunAs", NULL, NULL, (LPBYTE)valueBuffer, &valueBufferSize) == ERROR_SUCCESS)
112 | {
113 | runAs = valueBuffer;
114 | return ERROR_SUCCESS;
115 | }
116 | RegCloseKey(hAppIdKey);
117 | }
118 | return ERROR_OBJECT_NOT_FOUND;
119 | }
120 |
121 | std::wstring GetUserNameFromSID(PSID sid)
122 | {
123 | WCHAR name[256];
124 | WCHAR domain[256];
125 | DWORD nameSize = sizeof(name) / sizeof(WCHAR);
126 | DWORD domainSize = sizeof(domain) / sizeof(WCHAR);
127 | SID_NAME_USE sidUse;
128 |
129 | if (!LookupAccountSid(NULL, sid, name, &nameSize, domain, &domainSize, &sidUse))
130 | return L"";
131 |
132 | std::wstring fullName(domain);
133 | fullName += L"\\\\";
134 | fullName += name;
135 |
136 | return fullName;
137 | }
138 |
139 | std::wstring GetProcessUserName(DWORD pid)
140 | {
141 | HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
142 | if (!hProcess)
143 | return L"";
144 |
145 | HANDLE hToken;
146 | if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
147 | {
148 | CloseHandle(hProcess);
149 | return L"";
150 | }
151 |
152 | DWORD bufferSize = 0;
153 | GetTokenInformation(hToken, TokenUser, NULL, 0, &bufferSize);
154 |
155 | if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
156 | {
157 | CloseHandle(hToken);
158 | CloseHandle(hProcess);
159 | return L"";
160 | }
161 |
162 | std::vector buffer(bufferSize);
163 | if (!GetTokenInformation(hToken, TokenUser, buffer.data(), bufferSize, &bufferSize))
164 | {
165 | CloseHandle(hToken);
166 | CloseHandle(hProcess);
167 | return L"";
168 | }
169 |
170 | PSID sid = reinterpret_cast(buffer.data())->User.Sid;
171 | std::wstring userName = GetUserNameFromSID(sid);
172 |
173 | CloseHandle(hToken);
174 | CloseHandle(hProcess);
175 |
176 | return userName;
177 | }
178 |
179 | BOOL GetPIDFromIUnknown(IN IUnknown* pUnknown, OUT DWORD* pid)
180 | {
181 | CComPtr marshalStream;
182 | CreateStreamOnHGlobal(NULL, TRUE, &marshalStream);
183 |
184 | CoMarshalInterface(
185 | marshalStream,
186 | IID_IUnknown,
187 | pUnknown,
188 | MSHCTX_INPROC,
189 | NULL,
190 | MSHLFLAGS_NORMAL
191 | );
192 |
193 | HGLOBAL memoryHandleFromStream = NULL;
194 | GetHGlobalFromStream(marshalStream, &memoryHandleFromStream);
195 |
196 | LPOBJREF objref = reinterpret_cast (GlobalLock(memoryHandleFromStream));
197 | if (objref && objref->signature == OBJREF_SIGNATURE)
198 | {
199 | IPID ipid;
200 |
201 | if (objref->flags == OBJREF_STANDARD)
202 | {
203 | ipid = objref->u_objref.u_standard.std.ipid;
204 | }
205 | else if (objref->flags == OBJREF_HANDLER)
206 | {
207 | ipid = objref->u_objref.u_handler.std.ipid;
208 | }
209 | else if (objref->flags == OBJREF_EXTENDED)
210 | {
211 | ipid = objref->u_objref.u_extended.std.ipid;
212 | }
213 | else if (objref->flags == OBJREF_CUSTOM)
214 | {
215 | return FALSE;
216 | }
217 |
218 | static const int COM_SERVER_PID_OFFSET = 4;
219 |
220 | *pid = *reinterpret_cast(
221 | (reinterpret_cast(&ipid) + COM_SERVER_PID_OFFSET)
222 | );
223 | return *pid != 0xffff;
224 | }
225 | }
226 |
227 | std::wstring GetProcessName(DWORD processID) {
228 | std::wstring processName = L"";
229 |
230 | HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
231 |
232 | if (NULL != hProcess) {
233 | HMODULE hMod;
234 | DWORD cbNeeded;
235 |
236 | if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) {
237 | wchar_t szProcessName[MAX_PATH];
238 | if (GetModuleBaseName(hProcess, hMod, szProcessName, sizeof(szProcessName) / sizeof(wchar_t))) {
239 | processName = szProcessName;
240 | }
241 | }
242 | else
243 | {
244 | std::wcout << L"[-] EnumProcessModules() Failed: " << GetLastError() << std::endl;
245 | }
246 |
247 | CloseHandle(hProcess);
248 | }
249 |
250 | return processName;
251 | }
--------------------------------------------------------------------------------
/ComDiver/COMDiver/enumerator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | std::vector EnumerateCLSID();
11 | DWORD GetAppIdFromClsid(IN std::wstring clsid, OUT std::wstring& appId);
12 | DWORD GetProgIdFromClsid(IN std::wstring clsid, OUT std::wstring& progId);
13 | DWORD GetRunAsKeyFromAppId(IN std::wstring appId, OUT std::wstring& runAs);
14 | BOOL GetPIDFromIUnknown(IN IUnknown* pUnknown, OUT DWORD* pid);
15 | std::wstring GetProcessUserName(DWORD pid);
16 | std::wstring GetProcessName(DWORD processID);
17 |
18 | typedef struct tagDATAELEMENT
19 | {
20 | GUID dataID;
21 | unsigned long cbSize;
22 | unsigned long cbRounded;
23 | /* [size_is] */ BYTE Data[1];
24 | } DATAELEMENT;
25 |
26 | typedef struct tagDUALSTRINGARRAY
27 | {
28 | unsigned short wNumEntries;
29 | unsigned short wSecurityOffset;
30 | /* [size_is] */ unsigned short aStringArray[1];
31 | } DUALSTRINGARRAY;
32 |
33 | typedef unsigned __int64 OXID;
34 | typedef unsigned __int64 OID;
35 | typedef GUID IPID;
36 |
37 | typedef struct tagOBJREFDATA
38 | {
39 | unsigned long nElms;
40 | /* [unique][size_is][size_is] */ DATAELEMENT** ppElmArray;
41 | } OBJREFDATA;
42 |
43 | typedef struct tagSTDOBJREF {
44 | unsigned long flags;
45 | unsigned long cPublicRefs;
46 | OXID oxid;
47 | OID oid;
48 | IPID ipid;
49 | } STDOBJREF;
50 |
51 | typedef struct tagOBJREF {
52 | unsigned long signature;
53 | unsigned long flags;
54 | GUID iid;
55 | union {
56 | struct {
57 | STDOBJREF std;
58 | DUALSTRINGARRAY saResAddr;
59 | } u_standard;
60 | struct {
61 | STDOBJREF std;
62 | CLSID clsid;
63 | DUALSTRINGARRAY saResAddr;
64 | } u_handler;
65 | struct {
66 | CLSID clsid;
67 | unsigned long cbExtension;
68 | unsigned long size;
69 | byte* pData;
70 | } u_custom;
71 | struct {
72 | STDOBJREF std;
73 | unsigned long Signature1;
74 | DUALSTRINGARRAY saResAddr;
75 | unsigned long nElms;
76 | unsigned long Signature2;
77 | DATAELEMENT ElmArray;
78 | } u_extended;
79 | } u_objref;
80 | } OBJREF, * LPOBJREF;
81 |
82 | typedef struct _IPID_ENTRY {
83 | IID iid;
84 | IPID ipid; // IPID to bind to
85 | OXID oxid; // Object Exporter ID
86 | OID oid;
87 | } IPID_ENTRY, * PIPID_ENTRY;
88 |
89 |
90 | #define OBJREF_SIGNATURE ( 0x574f454d )
91 |
92 | #define OBJREF_STANDARD ( 0x1 )
93 | #define OBJREF_HANDLER ( 0x2 )
94 | #define OBJREF_CUSTOM ( 0x4 )
95 | #define OBJREF_EXTENDED ( 0x8 )
--------------------------------------------------------------------------------
/ComDiver/COMDiver/main.cpp:
--------------------------------------------------------------------------------
1 | #include "main.h"
2 | #include "argparse.h"
3 | #include "enumerator.h"
4 | #include "analyzer.h"
5 |
6 |
7 | LONG WINAPI MyVectoredExceptionHandler(PEXCEPTION_POINTERS exceptionInfo)
8 | {
9 | std::wcout << L"\t[!] Exception occurred!" << std::endl;
10 |
11 | std::wcout << L"\t[!] Exception Code: " << exceptionInfo->ExceptionRecord->ExceptionCode << std::endl;
12 | std::wcout << L"\t[!] Exception Address: " << exceptionInfo->ExceptionRecord->ExceptionAddress << std::endl;
13 |
14 | std::wcout << L"\t[!!!] If program had crashed pls restart using .\\COMDiver.exe --from " << std::endl;
15 |
16 | return EXCEPTION_EXECUTE_HANDLER;
17 | }
18 |
19 | void ShowHelp()
20 | {
21 | std::cout << R"(
22 | \ /
23 | \ o ^ o /
24 | \ ( ) /
25 | ____________(%%%%%%%)____________
26 | ( / / )%%%%%%%( \ \ )
27 | (___/___/__/ \__\___\___)
28 | ( / /(%%%%%%%)\ \ )
29 | (__/___/ (%%%%%%%) \___\__)
30 | /( )\
31 | / (%%%%%) \
32 | (%%%)
33 | !
34 | )" << std::endl;
35 | std::wcout << L"----------- COM DIVER --------------" << std::endl;
36 | std::wcout << L"[?] Small tool to check insecure registry and disk permissions on com objects" << std::endl;
37 | std::wcout << L"[?] ARGS" << std::endl;
38 | std::wcout << L"\t-h/--help <- show this message" << std::endl;
39 | std::wcout << L"\t--from <- analyze CLSIDs from this clsid" << std::endl;
40 | std::wcout << L"\t--target <- analyze one target clsid" << std::endl;
41 | std::wcout << L"\t--no-context <- dont check another COM-server context. Only registry analyzing." << std::endl;
42 | std::wcout << L"\t--no-create <- dont create target COM object. This is the fastest mode" << std::endl;
43 | }
44 |
45 | int wmain(int argc, wchar_t* argv[])
46 | {
47 | setlocale(LC_ALL, "");
48 |
49 | if (cmdOptionExists(argv, argv + argc, L"-h") || cmdOptionExists(argv, argv + argc, L"--help"))
50 | {
51 | ShowHelp();
52 | return 0;
53 | }
54 |
55 | std::wstring targetClsid;
56 | if (cmdOptionExists(argv, argv + argc, L"--target"))
57 | {
58 | targetClsid = getCmdOption(argv, argv + argc, L"--target");
59 | }
60 |
61 | std::wstring startFromClsid;
62 | if (cmdOptionExists(argv, argv + argc, L"--from"))
63 | {
64 | startFromClsid = getCmdOption(argv, argv + argc, L"--from");
65 | }
66 |
67 | BOOL checkAnotherContext = TRUE;
68 | if (cmdOptionExists(argv, argv + argc, L"--no-context"))
69 | {
70 | checkAnotherContext = FALSE;
71 | }
72 |
73 | BOOL checkCreate = TRUE;
74 | if (cmdOptionExists(argv, argv + argc, L"--no-create"))
75 | {
76 | checkCreate = FALSE;
77 | }
78 |
79 | if (AddVectoredExceptionHandler(1, MyVectoredExceptionHandler) == nullptr)
80 | {
81 | std::wcout << L"[-] Failed to add the exception handler!" << std::endl;
82 | return 1;
83 | }
84 |
85 | std::vector clsidList;
86 | if (targetClsid.empty())
87 | {
88 | std::wcout << L"[+] Analyzing all CLSIDs" << std::endl;
89 | clsidList = EnumerateCLSID();
90 | }
91 | else
92 | {
93 | std::wcout << L"[+] Analyzing CLSID: " << targetClsid << std::endl;
94 | clsidList.push_back(targetClsid);
95 | }
96 |
97 | CoInitialize(NULL);
98 | std::wcout << "[+] Total CLSID: " << clsidList.size() << std::endl;
99 |
100 | auto it = clsidList.begin();
101 | if (!startFromClsid.empty()) {
102 | it = std::find(clsidList.begin(), clsidList.end(), startFromClsid);
103 | if (it == clsidList.end()) {
104 | std::wcerr << L"[-] Specified CLSID not found in the list: " << startFromClsid << std::endl;
105 | return 1;
106 | }
107 | else
108 | {
109 | ++it; // --from + 1
110 | }
111 | }
112 |
113 | for (; it != clsidList.end(); it++)
114 | {
115 | AnalyzeCLSID(*it, checkCreate, checkAnotherContext);
116 | }
117 |
118 | CoUninitialize();
119 |
120 | return 0;
121 | }
--------------------------------------------------------------------------------
/ComDiver/COMDiver/main.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
--------------------------------------------------------------------------------
/ComDiver/x64/Debug/ComDiver.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CICADA8-Research/COMThanasia/903e83ab569fef88b47d8a1d607bf44669d60da1/ComDiver/x64/Debug/ComDiver.exe
--------------------------------------------------------------------------------
/ComDiver/x64/Debug/ComDiver.pdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CICADA8-Research/COMThanasia/903e83ab569fef88b47d8a1d607bf44669d60da1/ComDiver/x64/Debug/ComDiver.pdb
--------------------------------------------------------------------------------
/ComTraveller/ComTraveller.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.7.34009.444
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ComTraveller", "ComTraveller\ComTraveller.vcxproj", "{87C00375-9918-4779-8458-3E77864BCC57}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Debug|x86 = Debug|x86
12 | Release|x64 = Release|x64
13 | Release|x86 = Release|x86
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {87C00375-9918-4779-8458-3E77864BCC57}.Debug|x64.ActiveCfg = Debug|x64
17 | {87C00375-9918-4779-8458-3E77864BCC57}.Debug|x64.Build.0 = Debug|x64
18 | {87C00375-9918-4779-8458-3E77864BCC57}.Debug|x86.ActiveCfg = Debug|Win32
19 | {87C00375-9918-4779-8458-3E77864BCC57}.Debug|x86.Build.0 = Debug|Win32
20 | {87C00375-9918-4779-8458-3E77864BCC57}.Release|x64.ActiveCfg = Release|x64
21 | {87C00375-9918-4779-8458-3E77864BCC57}.Release|x64.Build.0 = Release|x64
22 | {87C00375-9918-4779-8458-3E77864BCC57}.Release|x86.ActiveCfg = Release|Win32
23 | {87C00375-9918-4779-8458-3E77864BCC57}.Release|x86.Build.0 = Release|Win32
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {C8AD873B-1409-40FE-9B70-0CD26930F0FA}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/ComTraveller/ComTraveller/ComTraveller.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 | 17.0
23 | Win32Proj
24 | {87c00375-9918-4779-8458-3e77864bcc57}
25 | COMHunter
26 | 10.0
27 |
28 |
29 |
30 | Application
31 | true
32 | v143
33 | Unicode
34 |
35 |
36 | Application
37 | false
38 | v143
39 | true
40 | Unicode
41 |
42 |
43 | Application
44 | true
45 | v143
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v143
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 |
75 | Level3
76 | true
77 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
78 | true
79 |
80 |
81 | Console
82 | true
83 |
84 |
85 |
86 |
87 | Level3
88 | true
89 | true
90 | true
91 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
92 | true
93 |
94 |
95 | Console
96 | true
97 | true
98 | true
99 |
100 |
101 |
102 |
103 | Level3
104 | true
105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
106 | true
107 | Default
108 |
109 |
110 | Console
111 | true
112 |
113 |
114 |
115 |
116 | Level3
117 | true
118 | true
119 | true
120 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
121 | true
122 |
123 |
124 | Console
125 | true
126 | true
127 | true
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/ComTraveller/ComTraveller/ComTraveller.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Исходные файлы
20 |
21 |
22 | Исходные файлы
23 |
24 |
25 |
26 |
27 | Файлы заголовков
28 |
29 |
30 | Файлы заголовков
31 |
32 |
33 |
--------------------------------------------------------------------------------
/ComTraveller/ComTraveller/ComTraveller.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | --from {e5b35059-a1be-4977-9bee-5c44226340f7}
5 | WindowsLocalDebugger
6 |
7 |
--------------------------------------------------------------------------------
/ComTraveller/ComTraveller/enumerator.cpp:
--------------------------------------------------------------------------------
1 | #include "enumerator.h"
2 |
3 | bool HasTypeLib(IDispatch* pDispatch)
4 | {
5 | CComPtr spTypeInfo;
6 | TYPEATTR* pTypeAttr = nullptr;
7 |
8 | HRESULT hr = pDispatch->GetTypeInfo(0, LOCALE_USER_DEFAULT, &spTypeInfo);
9 | if (FAILED(hr))
10 | {
11 | //std::wcout << L"Failed to get type info." << std::endl;
12 | return FALSE;
13 | }
14 |
15 | hr = spTypeInfo->GetTypeAttr(&pTypeAttr);
16 | if (FAILED(hr))
17 | {
18 | // std::wcout << L"Failed to get type attributes." << std::endl;
19 | return FALSE;
20 | }
21 |
22 | return TRUE;
23 | }
24 |
25 |
26 | HRESULT CoCreateInstanceInSession(DWORD session, REFCLSID rclsid, REFIID riid, void** ppv)
27 | {
28 | BIND_OPTS3 bo = {};
29 | WCHAR wszCLSID[50];
30 | WCHAR wszMonikerName[300];
31 | StringFromGUID2(rclsid, wszCLSID, _countof(wszCLSID));
32 | StringCchPrintf(wszMonikerName, _countof(wszMonikerName),
33 | L"session:%d!new:%s", session, wszCLSID);
34 | bo.cbStruct = sizeof(bo);
35 | bo.dwClassContext = CLSCTX_LOCAL_SERVER;
36 | return CoGetObject(wszMonikerName, &bo, riid, ppv);
37 | }
38 |
39 | std::vector EnumerateCLSID()
40 | {
41 | std::vector clsidList;
42 | HKEY hKey;
43 | LONG nError;
44 |
45 | nError = RegOpenKeyEx(HKEY_CLASSES_ROOT, L"CLSID", 0, KEY_READ, &hKey);
46 | if (nError == ERROR_SUCCESS)
47 | {
48 | DWORD dwIndex = 0;
49 | WCHAR szName[MAX_PATH];
50 | DWORD dwNameSize = _countof(szName);
51 | FILETIME ftLastWriteTime;
52 |
53 | while (RegEnumKeyEx(hKey, dwIndex, szName, &dwNameSize, NULL, NULL, NULL, &ftLastWriteTime) == ERROR_SUCCESS)
54 | {
55 | clsidList.push_back(szName);
56 | dwNameSize = _countof(szName);
57 | dwIndex++;
58 | }
59 |
60 | RegCloseKey(hKey);
61 | }
62 | else
63 | {
64 | std::wcerr << L"Cant open HKEY_CLASSES_ROOT\\CLSID. Error: " << nError << std::endl;
65 | }
66 |
67 | return clsidList;
68 | }
69 |
70 | DWORD GetAppIdFromClsid(IN std::wstring clsid, OUT std::wstring& appId)
71 | {
72 | HKEY hClsidKey;
73 | std::wstring clsidSubKey = L"CLSID\\" + clsid;
74 | if (RegOpenKeyEx(HKEY_CLASSES_ROOT, clsidSubKey.c_str(), 0, KEY_READ, &hClsidKey) != ERROR_SUCCESS)
75 | {
76 | return ERROR_OPEN_FAILED;
77 | }
78 |
79 | TCHAR valueBuffer[256];
80 | DWORD valueBufferSize = sizeof(valueBuffer);
81 |
82 | if (RegQueryValueEx(hClsidKey, L"AppID", NULL, NULL, (LPBYTE)valueBuffer, &valueBufferSize) == ERROR_SUCCESS)
83 | {
84 | appId = valueBuffer;
85 | }
86 |
87 | RegCloseKey(hClsidKey);
88 |
89 | return ERROR_SUCCESS;
90 | }
91 |
92 | DWORD GetProgIdFromClsid(IN std::wstring clsid, OUT std::wstring& progId)
93 | {
94 | HKEY hKey;
95 | if (RegOpenKeyEx(HKEY_CLASSES_ROOT, NULL, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
96 | {
97 | return ERROR_OPEN_FAILED;
98 | }
99 |
100 | DWORD index = 0;
101 | TCHAR subKeyName[256];
102 | DWORD subKeyNameSize = sizeof(subKeyName) / sizeof(subKeyName[0]);
103 | LONG ret = ERROR_SUCCESS;
104 |
105 | while ((ret = RegEnumKeyEx(hKey, index, subKeyName, &subKeyNameSize, NULL, NULL, NULL, NULL)) == ERROR_SUCCESS)
106 | {
107 | HKEY hSubKey;
108 |
109 | if (RegOpenKeyEx(hKey, subKeyName, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
110 | {
111 | DWORD valueBufferSize = 0;
112 | if (RegQueryValueEx(hSubKey, L"CLSID", NULL, NULL, NULL, &valueBufferSize) == ERROR_SUCCESS)
113 | {
114 | TCHAR* valueBuffer = new TCHAR[valueBufferSize / sizeof(TCHAR)];
115 | if (RegQueryValueEx(hSubKey, L"CLSID", NULL, NULL, (LPBYTE)valueBuffer, &valueBufferSize) == ERROR_SUCCESS)
116 | {
117 | if (clsid == valueBuffer)
118 | {
119 | progId = subKeyName;
120 | delete[] valueBuffer;
121 | RegCloseKey(hSubKey);
122 | RegCloseKey(hKey);
123 | return ERROR_SUCCESS;
124 | }
125 | }
126 | delete[] valueBuffer;
127 | }
128 | RegCloseKey(hSubKey);
129 | }
130 |
131 | subKeyNameSize = sizeof(subKeyName) / sizeof(subKeyName[0]);
132 | index++;
133 | }
134 |
135 | RegCloseKey(hKey);
136 | return ERROR_NOT_FOUND;
137 | }
138 |
139 | DWORD GetRunAsKeyFromAppId(IN std::wstring appId, OUT std::wstring& runAs)
140 | {
141 | std::wstring appIdSubKey = L"AppID\\" + appId;
142 | HKEY hAppIdKey;
143 | if (RegOpenKeyEx(HKEY_CLASSES_ROOT, appIdSubKey.c_str(), 0, KEY_READ, &hAppIdKey) == ERROR_SUCCESS)
144 | {
145 | DWORD valueBufferSize = 256;
146 | TCHAR* valueBuffer = new TCHAR[valueBufferSize / sizeof(TCHAR)];
147 | if (RegQueryValueEx(hAppIdKey, L"RunAs", NULL, NULL, (LPBYTE)valueBuffer, &valueBufferSize) == ERROR_SUCCESS)
148 | {
149 | runAs = valueBuffer;
150 | return ERROR_SUCCESS;
151 | }
152 | RegCloseKey(hAppIdKey);
153 | }
154 | return ERROR_OBJECT_NOT_FOUND;
155 | }
156 |
157 | std::wstring GetUserNameFromSID(PSID sid)
158 | {
159 | WCHAR name[256];
160 | WCHAR domain[256];
161 | DWORD nameSize = sizeof(name) / sizeof(WCHAR);
162 | DWORD domainSize = sizeof(domain) / sizeof(WCHAR);
163 | SID_NAME_USE sidUse;
164 |
165 | if (!LookupAccountSid(NULL, sid, name, &nameSize, domain, &domainSize, &sidUse))
166 | return L"";
167 |
168 | std::wstring fullName(domain);
169 | fullName += L"\\\\";
170 | fullName += name;
171 |
172 | return fullName;
173 | }
174 |
175 | std::wstring GetProcessUserName(DWORD pid)
176 | {
177 | HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
178 | if (!hProcess)
179 | return L"";
180 |
181 | HANDLE hToken;
182 | if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
183 | {
184 | CloseHandle(hProcess);
185 | return L"";
186 | }
187 |
188 | DWORD bufferSize = 0;
189 | GetTokenInformation(hToken, TokenUser, NULL, 0, &bufferSize);
190 |
191 | if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
192 | {
193 | CloseHandle(hToken);
194 | CloseHandle(hProcess);
195 | return L"";
196 | }
197 |
198 | std::vector buffer(bufferSize);
199 | if (!GetTokenInformation(hToken, TokenUser, buffer.data(), bufferSize, &bufferSize))
200 | {
201 | CloseHandle(hToken);
202 | CloseHandle(hProcess);
203 | return L"";
204 | }
205 |
206 | PSID sid = reinterpret_cast(buffer.data())->User.Sid;
207 | std::wstring userName = GetUserNameFromSID(sid);
208 |
209 | CloseHandle(hToken);
210 | CloseHandle(hProcess);
211 |
212 | return userName;
213 | }
214 |
215 | BOOL GetPIDFromIUnknown(IN IUnknown* pUnknown, OUT DWORD* pid)
216 | {
217 | CComPtr marshalStream;
218 | CreateStreamOnHGlobal(NULL, TRUE, &marshalStream);
219 |
220 | CoMarshalInterface(
221 | marshalStream,
222 | IID_IUnknown,
223 | pUnknown,
224 | MSHCTX_INPROC,
225 | NULL,
226 | MSHLFLAGS_NORMAL
227 | );
228 |
229 | HGLOBAL memoryHandleFromStream = NULL;
230 | GetHGlobalFromStream(marshalStream, &memoryHandleFromStream);
231 |
232 | LPOBJREF objref = reinterpret_cast (GlobalLock(memoryHandleFromStream));
233 | if (objref && objref->signature == OBJREF_SIGNATURE)
234 | {
235 | IPID ipid;
236 |
237 | if (objref->flags == OBJREF_STANDARD)
238 | {
239 | ipid = objref->u_objref.u_standard.std.ipid;
240 | }
241 | else if (objref->flags == OBJREF_HANDLER)
242 | {
243 | ipid = objref->u_objref.u_handler.std.ipid;
244 | }
245 | else if (objref->flags == OBJREF_EXTENDED)
246 | {
247 | ipid = objref->u_objref.u_extended.std.ipid;
248 | }
249 | else if (objref->flags == OBJREF_CUSTOM)
250 | {
251 | return FALSE;
252 | }
253 |
254 | static const int COM_SERVER_PID_OFFSET = 4;
255 |
256 | *pid = *reinterpret_cast(
257 | (reinterpret_cast(&ipid) + COM_SERVER_PID_OFFSET)
258 | );
259 | return *pid != 0xffff;
260 | }
261 | }
262 |
263 | std::wstring GetProcessName(DWORD processID) {
264 | std::wstring processName = L"";
265 |
266 | HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
267 |
268 | if (NULL != hProcess) {
269 | HMODULE hMod;
270 | DWORD cbNeeded;
271 |
272 | if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) {
273 | wchar_t szProcessName[MAX_PATH];
274 | if (GetModuleBaseName(hProcess, hMod, szProcessName, sizeof(szProcessName) / sizeof(wchar_t))) {
275 | processName = szProcessName;
276 | }
277 | }
278 | else
279 | {
280 | std::wcout << L"[-] EnumProcessModules() Failed: " << GetLastError() << std::endl;
281 | }
282 |
283 | CloseHandle(hProcess);
284 | }
285 |
286 | return processName;
287 | }
288 |
--------------------------------------------------------------------------------
/ComTraveller/ComTraveller/enumerator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | HRESULT CoCreateInstanceInSession(DWORD session, REFCLSID rclsid, REFIID riid, void** ppv);
12 | bool HasTypeLib(IDispatch* pDispatch);
13 | std::vector EnumerateCLSID();
14 | DWORD GetAppIdFromClsid(IN std::wstring clsid, OUT std::wstring& appId);
15 | DWORD GetProgIdFromClsid(IN std::wstring clsid, OUT std::wstring& progId);
16 | DWORD GetRunAsKeyFromAppId(IN std::wstring appId, OUT std::wstring& runAs);
17 | BOOL GetPIDFromIUnknown(IN IUnknown* pUnknown, OUT DWORD* pid);
18 | std::wstring GetProcessUserName(DWORD pid);
19 | std::wstring GetProcessName(DWORD processID);
20 |
21 | typedef struct tagDATAELEMENT
22 | {
23 | GUID dataID;
24 | unsigned long cbSize;
25 | unsigned long cbRounded;
26 | /* [size_is] */ BYTE Data[1];
27 | } DATAELEMENT;
28 |
29 | typedef struct tagDUALSTRINGARRAY
30 | {
31 | unsigned short wNumEntries;
32 | unsigned short wSecurityOffset;
33 | /* [size_is] */ unsigned short aStringArray[1];
34 | } DUALSTRINGARRAY;
35 |
36 | typedef unsigned __int64 OXID;
37 | typedef unsigned __int64 OID;
38 | typedef GUID IPID;
39 |
40 | typedef struct tagOBJREFDATA
41 | {
42 | unsigned long nElms;
43 | /* [unique][size_is][size_is] */ DATAELEMENT** ppElmArray;
44 | } OBJREFDATA;
45 |
46 | typedef struct tagSTDOBJREF {
47 | unsigned long flags;
48 | unsigned long cPublicRefs;
49 | OXID oxid;
50 | OID oid;
51 | IPID ipid;
52 | } STDOBJREF;
53 |
54 | typedef struct tagOBJREF {
55 | unsigned long signature;
56 | unsigned long flags;
57 | GUID iid;
58 | union {
59 | struct {
60 | STDOBJREF std;
61 | DUALSTRINGARRAY saResAddr;
62 | } u_standard;
63 | struct {
64 | STDOBJREF std;
65 | CLSID clsid;
66 | DUALSTRINGARRAY saResAddr;
67 | } u_handler;
68 | struct {
69 | CLSID clsid;
70 | unsigned long cbExtension;
71 | unsigned long size;
72 | byte* pData;
73 | } u_custom;
74 | struct {
75 | STDOBJREF std;
76 | unsigned long Signature1;
77 | DUALSTRINGARRAY saResAddr;
78 | unsigned long nElms;
79 | unsigned long Signature2;
80 | DATAELEMENT ElmArray;
81 | } u_extended;
82 | } u_objref;
83 | } OBJREF, * LPOBJREF;
84 |
85 | typedef struct _IPID_ENTRY {
86 | IID iid;
87 | IPID ipid; // IPID to bind to
88 | OXID oxid; // Object Exporter ID
89 | OID oid;
90 | } IPID_ENTRY, * PIPID_ENTRY;
91 |
92 |
93 | #define OBJREF_SIGNATURE ( 0x574f454d )
94 |
95 | #define OBJREF_STANDARD ( 0x1 )
96 | #define OBJREF_HANDLER ( 0x2 )
97 | #define OBJREF_CUSTOM ( 0x4 )
98 | #define OBJREF_EXTENDED ( 0x8 )
--------------------------------------------------------------------------------
/ComTraveller/ComTraveller/main.cpp:
--------------------------------------------------------------------------------
1 | #include "main.h"
2 |
3 |
4 | LONG WINAPI MyVectoredExceptionHandler(PEXCEPTION_POINTERS exceptionInfo)
5 | {
6 | std::wcout << L"\t[!] Exception occurred!" << std::endl;
7 |
8 | std::wcout << L"\t[!] Exception Code: " << exceptionInfo->ExceptionRecord->ExceptionCode << std::endl;
9 | std::wcout << L"\t[!] Exception Address: " << exceptionInfo->ExceptionRecord->ExceptionAddress << std::endl;
10 |
11 | std::wcout << L"\t[!!!] If program had crashed pls restart using .\\COMHunter.exe --from " << std::endl;
12 |
13 | return EXCEPTION_EXECUTE_HANDLER;
14 | }
15 |
16 | void WriteDataToCSV(HANDLE hFile, const std::vector& row)
17 | {
18 | SetFilePointer(hFile, 0, NULL, FILE_END);
19 | bool first = true;
20 | for (const auto& cell : row)
21 | {
22 | if (!first)
23 | {
24 | WCHAR comma = L',';
25 | DWORD bytesWritten;
26 | WriteFile(hFile, &comma, sizeof(comma), &bytesWritten, NULL);
27 | }
28 | else
29 | {
30 | first = false;
31 | }
32 |
33 | DWORD bytesWritten;
34 | WriteFile(hFile, cell.c_str(), cell.size() * sizeof(WCHAR), &bytesWritten, NULL);
35 | }
36 |
37 | WCHAR newline = L'\n';
38 | DWORD bytesWritten;
39 | WriteFile(hFile, &newline, sizeof(newline), &bytesWritten, NULL);
40 | }
41 |
42 | std::wstring FormatHResult(HRESULT hr) {
43 | std::wstringstream ss;
44 | ss << L"- Err: 0x" << std::hex << hr;
45 |
46 | if (HRESULT_FACILITY(hr) == FACILITY_WIN32) {
47 | hr = HRESULT_CODE(hr);
48 | }
49 |
50 | LPWSTR errorMsg = nullptr;
51 | DWORD size = FormatMessage(
52 | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
53 | nullptr, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
54 | (LPWSTR)&errorMsg, 0, nullptr);
55 |
56 | std::wstring errorDesc = (size != 0 && errorMsg != nullptr) ? errorMsg : L"Unknown Error";
57 | if (errorMsg) {
58 | LocalFree(errorMsg);
59 | }
60 |
61 | if (!errorDesc.empty() && errorDesc.back() == L'\n') {
62 | errorDesc.pop_back();
63 | }
64 |
65 | return ss.str() + L" " + errorDesc;
66 | }
67 |
68 | bool IsBlacklisted(const std::wstring& clsid, const std::vector& blackList)
69 | {
70 | std::wstring clsidLower = clsid;
71 |
72 | std::transform(clsidLower.begin(), clsidLower.end(), clsidLower.begin(), ::towlower);
73 |
74 | for (const auto& blacklistedClsid : blackList) {
75 | std::wstring blacklistedClsidLower = blacklistedClsid;
76 | std::transform(blacklistedClsidLower.begin(), blacklistedClsidLower.end(), blacklistedClsidLower.begin(), ::towlower);
77 |
78 | if (clsidLower == blacklistedClsidLower) {
79 | return true;
80 | }
81 | }
82 |
83 | return false;
84 | }
85 |
86 |
87 | void ShowHelp()
88 | {
89 | std::cout << R"(
90 | ,,_
91 | zd$$??=
92 | z$$P? F:`c, _
93 | d$$, `c'cc$$i ,cd$?R
94 | $$$$ cud$,?$$$i ,=P"2?z "
95 | $" " ?$$$,?$$$. ,-''`>, bzP
96 | 'cLdb,?$$,?$$$ ,h' "I$'J$P
97 | ... `?$$$,"$$,`$$h $$PxrF'd$"
98 | d$PP""?-,"?$$,?$h`$$,,$$'$F44"
99 | ?,,_`=4c,?=,"?hu?$`?L4$'? '
100 | `""?==""=-"" `""-`'_,,,,
101 | .ccu?m?e?JC,-,"=?
102 | """=='?"
103 | )" << std::endl;
104 | std::wcout << L"ComTraveller - small tool to parse and extract information about all registered CLSIDs on the system" << std::endl;
105 | std::wcout << L"Usage: " << std::endl;
106 | std::wcout << L"--file