├── .gitattributes ├── .gitignore ├── .gitmodules ├── DepWalk.sln ├── DepWalk ├── AboutDlg.cpp ├── AboutDlg.h ├── DepWalk.cpp ├── DepWalk.h ├── DepWalk.rc ├── DepWalk.vcxproj ├── DepWalk.vcxproj.filters ├── Interfaces.h ├── MainFrm.cpp ├── MainFrm.h ├── ReleaseSigned │ ├── DepWalk.exe.recipe │ └── DepWalk.res ├── View.cpp ├── View.h ├── pch.cpp ├── pch.h ├── res │ ├── DLL.ico │ ├── DepWalk.ico │ ├── Error.ico │ ├── check.ico │ ├── circle.ico │ ├── copy.ico │ ├── function-export.ico │ ├── function-import.ico │ ├── function.ico │ ├── interface.ico │ ├── open.ico │ ├── pin_green.ico │ ├── save.ico │ ├── sysfile.ico │ ├── window-close.ico │ └── windows-close.ico └── resource.h ├── LICENSE.txt ├── PECore ├── PECore.cpp ├── PECore.vcxproj ├── PECore.vcxproj.filters ├── PEFile.cpp ├── PEFile.h ├── ReleaseSigned │ └── PECore.lib.recipe ├── libpe.cpp ├── libpe.h ├── packages.config ├── pch.cpp └── pch.h ├── README.md ├── ReleaseSigned ├── DepWalk.exe ├── PECore.lib └── WTLHelper.lib └── depwalk.png /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.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 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Oo]ut/ 33 | [Ll]og/ 34 | [Ll]ogs/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUnit 49 | *.VisualState.xml 50 | TestResult.xml 51 | nunit-*.xml 52 | 53 | # Build Results of an ATL Project 54 | [Dd]ebugPS/ 55 | [Rr]eleasePS/ 56 | dlldata.c 57 | 58 | # Benchmark Results 59 | BenchmarkDotNet.Artifacts/ 60 | 61 | # .NET Core 62 | project.lock.json 63 | project.fragment.lock.json 64 | artifacts/ 65 | 66 | # ASP.NET Scaffolding 67 | ScaffoldingReadMe.txt 68 | 69 | # StyleCop 70 | StyleCopReport.xml 71 | 72 | # Files built by Visual Studio 73 | *_i.c 74 | *_p.c 75 | *_h.h 76 | *.ilk 77 | *.meta 78 | *.obj 79 | *.iobj 80 | *.pch 81 | *.pdb 82 | *.ipdb 83 | *.pgc 84 | *.pgd 85 | *.rsp 86 | *.sbr 87 | *.tlb 88 | *.tli 89 | *.tlh 90 | *.tmp 91 | *.tmp_proj 92 | *_wpftmp.csproj 93 | *.log 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | *.tlog 101 | 102 | # Chutzpah Test files 103 | _Chutzpah* 104 | 105 | # Visual C++ cache files 106 | ipch/ 107 | *.aps 108 | *.ncb 109 | *.opendb 110 | *.opensdf 111 | *.sdf 112 | *.cachefile 113 | *.VC.db 114 | *.VC.VC.opendb 115 | 116 | # Visual Studio profiler 117 | *.psess 118 | *.vsp 119 | *.vspx 120 | *.sap 121 | 122 | # Visual Studio Trace Files 123 | *.e2e 124 | 125 | # TFS 2012 Local Workspace 126 | $tf/ 127 | 128 | # Guidance Automation Toolkit 129 | *.gpState 130 | 131 | # ReSharper is a .NET coding add-in 132 | _ReSharper*/ 133 | *.[Rr]e[Ss]harper 134 | *.DotSettings.user 135 | 136 | # TeamCity is a build add-in 137 | _TeamCity* 138 | 139 | # DotCover is a Code Coverage Tool 140 | *.dotCover 141 | 142 | # AxoCover is a Code Coverage Tool 143 | .axoCover/* 144 | !.axoCover/settings.json 145 | 146 | # Coverlet is a free, cross platform Code Coverage Tool 147 | coverage*.json 148 | coverage*.xml 149 | coverage*.info 150 | 151 | # Visual Studio code coverage results 152 | *.coverage 153 | *.coveragexml 154 | 155 | # NCrunch 156 | _NCrunch_* 157 | .*crunch*.local.xml 158 | nCrunchTemp_* 159 | 160 | # MightyMoose 161 | *.mm.* 162 | AutoTest.Net/ 163 | 164 | # Web workbench (sass) 165 | .sass-cache/ 166 | 167 | # Installshield output folder 168 | [Ee]xpress/ 169 | 170 | # DocProject is a documentation generator add-in 171 | DocProject/buildhelp/ 172 | DocProject/Help/*.HxT 173 | DocProject/Help/*.HxC 174 | DocProject/Help/*.hhc 175 | DocProject/Help/*.hhk 176 | DocProject/Help/*.hhp 177 | DocProject/Help/Html2 178 | DocProject/Help/html 179 | 180 | # Click-Once directory 181 | publish/ 182 | 183 | # Publish Web Output 184 | *.[Pp]ublish.xml 185 | *.azurePubxml 186 | # Note: Comment the next line if you want to checkin your web deploy settings, 187 | # but database connection strings (with potential passwords) will be unencrypted 188 | *.pubxml 189 | *.publishproj 190 | 191 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 192 | # checkin your Azure Web App publish settings, but sensitive information contained 193 | # in these scripts will be unencrypted 194 | PublishScripts/ 195 | 196 | # NuGet Packages 197 | *.nupkg 198 | # NuGet Symbol Packages 199 | *.snupkg 200 | # The packages folder can be ignored because of Package Restore 201 | **/[Pp]ackages/* 202 | # except build/, which is used as an MSBuild target. 203 | !**/[Pp]ackages/build/ 204 | # Uncomment if necessary however generally it will be regenerated when needed 205 | #!**/[Pp]ackages/repositories.config 206 | # NuGet v3's project.json files produces more ignorable files 207 | *.nuget.props 208 | *.nuget.targets 209 | 210 | # Microsoft Azure Build Output 211 | csx/ 212 | *.build.csdef 213 | 214 | # Microsoft Azure Emulator 215 | ecf/ 216 | rcf/ 217 | 218 | # Windows Store app package directories and files 219 | AppPackages/ 220 | BundleArtifacts/ 221 | Package.StoreAssociation.xml 222 | _pkginfo.txt 223 | *.appx 224 | *.appxbundle 225 | *.appxupload 226 | 227 | # Visual Studio cache files 228 | # files ending in .cache can be ignored 229 | *.[Cc]ache 230 | # but keep track of directories ending in .cache 231 | !?*.[Cc]ache/ 232 | 233 | # Others 234 | ClientBin/ 235 | ~$* 236 | *~ 237 | *.dbmdl 238 | *.dbproj.schemaview 239 | *.jfm 240 | *.pfx 241 | *.publishsettings 242 | orleans.codegen.cs 243 | 244 | # Including strong name files can present a security risk 245 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 246 | #*.snk 247 | 248 | # Since there are multiple workflows, uncomment next line to ignore bower_components 249 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 250 | #bower_components/ 251 | 252 | # RIA/Silverlight projects 253 | Generated_Code/ 254 | 255 | # Backup & report files from converting an old project file 256 | # to a newer Visual Studio version. Backup files are not needed, 257 | # because we have git ;-) 258 | _UpgradeReport_Files/ 259 | Backup*/ 260 | UpgradeLog*.XML 261 | UpgradeLog*.htm 262 | ServiceFabricBackup/ 263 | *.rptproj.bak 264 | 265 | # SQL Server files 266 | *.mdf 267 | *.ldf 268 | *.ndf 269 | 270 | # Business Intelligence projects 271 | *.rdl.data 272 | *.bim.layout 273 | *.bim_*.settings 274 | *.rptproj.rsuser 275 | *- [Bb]ackup.rdl 276 | *- [Bb]ackup ([0-9]).rdl 277 | *- [Bb]ackup ([0-9][0-9]).rdl 278 | 279 | # Microsoft Fakes 280 | FakesAssemblies/ 281 | 282 | # GhostDoc plugin setting file 283 | *.GhostDoc.xml 284 | 285 | # Node.js Tools for Visual Studio 286 | .ntvs_analysis.dat 287 | node_modules/ 288 | 289 | # Visual Studio 6 build log 290 | *.plg 291 | 292 | # Visual Studio 6 workspace options file 293 | *.opt 294 | 295 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 296 | *.vbw 297 | 298 | # Visual Studio LightSwitch build output 299 | **/*.HTMLClient/GeneratedArtifacts 300 | **/*.DesktopClient/GeneratedArtifacts 301 | **/*.DesktopClient/ModelManifest.xml 302 | **/*.Server/GeneratedArtifacts 303 | **/*.Server/ModelManifest.xml 304 | _Pvt_Extensions 305 | 306 | # Paket dependency manager 307 | .paket/paket.exe 308 | paket-files/ 309 | 310 | # FAKE - F# Make 311 | .fake/ 312 | 313 | # CodeRush personal settings 314 | .cr/personal 315 | 316 | # Python Tools for Visual Studio (PTVS) 317 | __pycache__/ 318 | *.pyc 319 | 320 | # Cake - Uncomment if you are using it 321 | # tools/** 322 | # !tools/packages.config 323 | 324 | # Tabs Studio 325 | *.tss 326 | 327 | # Telerik's JustMock configuration file 328 | *.jmconfig 329 | 330 | # BizTalk build output 331 | *.btp.cs 332 | *.btm.cs 333 | *.odx.cs 334 | *.xsd.cs 335 | 336 | # OpenCover UI analysis results 337 | OpenCover/ 338 | 339 | # Azure Stream Analytics local run output 340 | ASALocalRun/ 341 | 342 | # MSBuild Binary and Structured Log 343 | *.binlog 344 | 345 | # NVidia Nsight GPU debugger configuration file 346 | *.nvuser 347 | 348 | # MFractors (Xamarin productivity tool) working folder 349 | .mfractor/ 350 | 351 | # Local History for Visual Studio 352 | .localhistory/ 353 | 354 | # BeatPulse healthcheck temp database 355 | healthchecksdb 356 | 357 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 358 | MigrationBackup/ 359 | 360 | # Ionide (cross platform F# VS Code tools) working folder 361 | .ionide/ 362 | 363 | # Fody - auto-generated XML schema 364 | FodyWeavers.xsd -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "wtlhelper"] 2 | path = wtlhelper 3 | url = https://github.com/zodiacon/wtlhelper.git 4 | -------------------------------------------------------------------------------- /DepWalk.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.6.33417.168 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DepWalk", "DepWalk\DepWalk.vcxproj", "{5DD8C369-7B7C-455B-AFCF-9030EB6F0FBE}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PECore", "PECore\PECore.vcxproj", "{03A66844-1884-41C0-899D-F01C8A601C8E}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WTLHelper", "wtlhelper\WTLHelper\WTLHelper.vcxproj", "{AE53419F-A769-4548-8E15-E311904DF7DF}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|ARM64 = Debug|ARM64 15 | Debug|x64 = Debug|x64 16 | Debug|x86 = Debug|x86 17 | Release|ARM64 = Release|ARM64 18 | Release|x64 = Release|x64 19 | Release|x86 = Release|x86 20 | ReleaseSigned|ARM64 = ReleaseSigned|ARM64 21 | ReleaseSigned|x64 = ReleaseSigned|x64 22 | ReleaseSigned|x86 = ReleaseSigned|x86 23 | EndGlobalSection 24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 25 | {5DD8C369-7B7C-455B-AFCF-9030EB6F0FBE}.Debug|ARM64.ActiveCfg = Debug|x64 26 | {5DD8C369-7B7C-455B-AFCF-9030EB6F0FBE}.Debug|ARM64.Build.0 = Debug|x64 27 | {5DD8C369-7B7C-455B-AFCF-9030EB6F0FBE}.Debug|x64.ActiveCfg = Debug|x64 28 | {5DD8C369-7B7C-455B-AFCF-9030EB6F0FBE}.Debug|x64.Build.0 = Debug|x64 29 | {5DD8C369-7B7C-455B-AFCF-9030EB6F0FBE}.Debug|x86.ActiveCfg = Debug|Win32 30 | {5DD8C369-7B7C-455B-AFCF-9030EB6F0FBE}.Debug|x86.Build.0 = Debug|Win32 31 | {5DD8C369-7B7C-455B-AFCF-9030EB6F0FBE}.Release|ARM64.ActiveCfg = Release|x64 32 | {5DD8C369-7B7C-455B-AFCF-9030EB6F0FBE}.Release|ARM64.Build.0 = Release|x64 33 | {5DD8C369-7B7C-455B-AFCF-9030EB6F0FBE}.Release|x64.ActiveCfg = Release|x64 34 | {5DD8C369-7B7C-455B-AFCF-9030EB6F0FBE}.Release|x64.Build.0 = Release|x64 35 | {5DD8C369-7B7C-455B-AFCF-9030EB6F0FBE}.Release|x86.ActiveCfg = Release|Win32 36 | {5DD8C369-7B7C-455B-AFCF-9030EB6F0FBE}.Release|x86.Build.0 = Release|Win32 37 | {5DD8C369-7B7C-455B-AFCF-9030EB6F0FBE}.ReleaseSigned|ARM64.ActiveCfg = ReleaseSigned|x64 38 | {5DD8C369-7B7C-455B-AFCF-9030EB6F0FBE}.ReleaseSigned|ARM64.Build.0 = ReleaseSigned|x64 39 | {5DD8C369-7B7C-455B-AFCF-9030EB6F0FBE}.ReleaseSigned|x64.ActiveCfg = ReleaseSigned|x64 40 | {5DD8C369-7B7C-455B-AFCF-9030EB6F0FBE}.ReleaseSigned|x64.Build.0 = ReleaseSigned|x64 41 | {5DD8C369-7B7C-455B-AFCF-9030EB6F0FBE}.ReleaseSigned|x86.ActiveCfg = ReleaseSigned|Win32 42 | {5DD8C369-7B7C-455B-AFCF-9030EB6F0FBE}.ReleaseSigned|x86.Build.0 = ReleaseSigned|Win32 43 | {03A66844-1884-41C0-899D-F01C8A601C8E}.Debug|ARM64.ActiveCfg = Debug|x64 44 | {03A66844-1884-41C0-899D-F01C8A601C8E}.Debug|ARM64.Build.0 = Debug|x64 45 | {03A66844-1884-41C0-899D-F01C8A601C8E}.Debug|x64.ActiveCfg = Debug|x64 46 | {03A66844-1884-41C0-899D-F01C8A601C8E}.Debug|x64.Build.0 = Debug|x64 47 | {03A66844-1884-41C0-899D-F01C8A601C8E}.Debug|x86.ActiveCfg = Debug|Win32 48 | {03A66844-1884-41C0-899D-F01C8A601C8E}.Debug|x86.Build.0 = Debug|Win32 49 | {03A66844-1884-41C0-899D-F01C8A601C8E}.Release|ARM64.ActiveCfg = Release|x64 50 | {03A66844-1884-41C0-899D-F01C8A601C8E}.Release|ARM64.Build.0 = Release|x64 51 | {03A66844-1884-41C0-899D-F01C8A601C8E}.Release|x64.ActiveCfg = Release|x64 52 | {03A66844-1884-41C0-899D-F01C8A601C8E}.Release|x64.Build.0 = Release|x64 53 | {03A66844-1884-41C0-899D-F01C8A601C8E}.Release|x86.ActiveCfg = Release|Win32 54 | {03A66844-1884-41C0-899D-F01C8A601C8E}.Release|x86.Build.0 = Release|Win32 55 | {03A66844-1884-41C0-899D-F01C8A601C8E}.ReleaseSigned|ARM64.ActiveCfg = ReleaseSigned|x64 56 | {03A66844-1884-41C0-899D-F01C8A601C8E}.ReleaseSigned|ARM64.Build.0 = ReleaseSigned|x64 57 | {03A66844-1884-41C0-899D-F01C8A601C8E}.ReleaseSigned|x64.ActiveCfg = ReleaseSigned|x64 58 | {03A66844-1884-41C0-899D-F01C8A601C8E}.ReleaseSigned|x64.Build.0 = ReleaseSigned|x64 59 | {03A66844-1884-41C0-899D-F01C8A601C8E}.ReleaseSigned|x86.ActiveCfg = ReleaseSigned|Win32 60 | {03A66844-1884-41C0-899D-F01C8A601C8E}.ReleaseSigned|x86.Build.0 = ReleaseSigned|Win32 61 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Debug|ARM64.ActiveCfg = Debug|ARM64 62 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Debug|ARM64.Build.0 = Debug|ARM64 63 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Debug|x64.ActiveCfg = Debug|x64 64 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Debug|x64.Build.0 = Debug|x64 65 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Debug|x86.ActiveCfg = Debug|Win32 66 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Debug|x86.Build.0 = Debug|Win32 67 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Release|ARM64.ActiveCfg = Release|ARM64 68 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Release|ARM64.Build.0 = Release|ARM64 69 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Release|x64.ActiveCfg = Release|x64 70 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Release|x64.Build.0 = Release|x64 71 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Release|x86.ActiveCfg = Release|Win32 72 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Release|x86.Build.0 = Release|Win32 73 | {AE53419F-A769-4548-8E15-E311904DF7DF}.ReleaseSigned|ARM64.ActiveCfg = ReleaseSigned|ARM64 74 | {AE53419F-A769-4548-8E15-E311904DF7DF}.ReleaseSigned|ARM64.Build.0 = ReleaseSigned|ARM64 75 | {AE53419F-A769-4548-8E15-E311904DF7DF}.ReleaseSigned|x64.ActiveCfg = ReleaseSigned|x64 76 | {AE53419F-A769-4548-8E15-E311904DF7DF}.ReleaseSigned|x64.Build.0 = ReleaseSigned|x64 77 | {AE53419F-A769-4548-8E15-E311904DF7DF}.ReleaseSigned|x86.ActiveCfg = ReleaseSigned|Win32 78 | {AE53419F-A769-4548-8E15-E311904DF7DF}.ReleaseSigned|x86.Build.0 = ReleaseSigned|Win32 79 | EndGlobalSection 80 | GlobalSection(SolutionProperties) = preSolution 81 | HideSolutionNode = FALSE 82 | EndGlobalSection 83 | GlobalSection(ExtensibilityGlobals) = postSolution 84 | SolutionGuid = {BC1A622D-C8E5-46A4-A696-469A04CEDA54} 85 | EndGlobalSection 86 | EndGlobal 87 | -------------------------------------------------------------------------------- /DepWalk/AboutDlg.cpp: -------------------------------------------------------------------------------- 1 | // aboutdlg.cpp : implementation of the CAboutDlg class 2 | // 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #include "pch.h" 6 | #include "resource.h" 7 | #include "aboutdlg.h" 8 | #include 9 | 10 | LRESULT CAboutDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { 11 | SetDialogIcon(IDR_MAINFRAME); 12 | 13 | CenterWindow(GetParent()); 14 | VersionResourceHelper vh; 15 | auto version = vh.GetValue(L"ProductVersion"); 16 | SetDlgItemText(IDC_VERSION, vh.GetValue(L"ProductName") + L" v" + version); 17 | SetDlgItemText(IDC_COPYRIGHT, vh.GetValue(L"LegalCopyright")); 18 | 19 | return TRUE; 20 | } 21 | 22 | LRESULT CAboutDlg::OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 23 | EndDialog(wID); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /DepWalk/AboutDlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class CAboutDlg : 6 | public CDialogImpl, 7 | public CDialogHelper { 8 | public: 9 | enum { IDD = IDD_ABOUTBOX }; 10 | 11 | BEGIN_MSG_MAP(CAboutDlg) 12 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 13 | COMMAND_ID_HANDLER(IDOK, OnCloseCmd) 14 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd) 15 | END_MSG_MAP() 16 | 17 | // Handler prototypes (uncomment arguments if needed): 18 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) 19 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) 20 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) 21 | 22 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 23 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 24 | }; 25 | -------------------------------------------------------------------------------- /DepWalk/DepWalk.cpp: -------------------------------------------------------------------------------- 1 | // DepWalk.cpp : main source file for DepWalk.exe 2 | // 3 | 4 | #include "pch.h" 5 | #include "resource.h" 6 | #include "MainFrm.h" 7 | #include 8 | 9 | CAppModule _Module; 10 | 11 | int Run(LPCTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT) { 12 | CMessageLoop theLoop; 13 | _Module.AddMessageLoop(&theLoop); 14 | 15 | CMainFrame wndMain; 16 | 17 | if (wndMain.CreateEx() == nullptr) { 18 | ATLTRACE(_T("Main window creation failed!\n")); 19 | return 0; 20 | } 21 | 22 | wndMain.ShowWindow(nCmdShow); 23 | 24 | int nRet = theLoop.Run(); 25 | 26 | _Module.RemoveMessageLoop(); 27 | return nRet; 28 | } 29 | 30 | int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow) { 31 | HRESULT hRes = ::CoInitialize(NULL); 32 | ATLASSERT(SUCCEEDED(hRes)); 33 | 34 | AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES | ICC_LISTVIEW_CLASSES); 35 | 36 | hRes = _Module.Init(NULL, hInstance); 37 | ATLASSERT(SUCCEEDED(hRes)); 38 | 39 | ThemeHelper::Init(); 40 | 41 | int nRet = Run(lpstrCmdLine, nCmdShow); 42 | 43 | _Module.Term(); 44 | ::CoUninitialize(); 45 | 46 | return nRet; 47 | } 48 | -------------------------------------------------------------------------------- /DepWalk/DepWalk.h: -------------------------------------------------------------------------------- 1 | // DepWalk.h 2 | -------------------------------------------------------------------------------- /DepWalk/DepWalk.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/DepWalk/DepWalk.rc -------------------------------------------------------------------------------- /DepWalk/DepWalk.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | ReleaseSigned 10 | Win32 11 | 12 | 13 | ReleaseSigned 14 | x64 15 | 16 | 17 | Release 18 | Win32 19 | 20 | 21 | Debug 22 | x64 23 | 24 | 25 | Release 26 | x64 27 | 28 | 29 | 30 | 17.0 31 | {5DD8C369-7B7C-455B-AFCF-9030EB6F0FBE} 32 | 10.0 33 | 34 | 35 | 36 | Application 37 | true 38 | v143 39 | Unicode 40 | 41 | 42 | Application 43 | false 44 | v143 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v143 51 | Unicode 52 | 53 | 54 | Application 55 | true 56 | v143 57 | Unicode 58 | 59 | 60 | Application 61 | false 62 | v143 63 | Unicode 64 | 65 | 66 | Application 67 | false 68 | v143 69 | Unicode 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | true 97 | $(ProjectName)64 98 | 99 | 100 | true 101 | 102 | 103 | false 104 | 105 | 106 | false 107 | 108 | 109 | false 110 | $(ProjectName)64 111 | 112 | 113 | false 114 | $(ProjectName)64 115 | 116 | 117 | 118 | Use 119 | Level3 120 | MultiThreadedDebug 121 | EditAndContinue 122 | EnableFastChecks 123 | Disabled 124 | _WINDOWS;STRICT;_DEBUG;%(PreprocessorDefinitions) 125 | pch.h 126 | ..\WTLHelper\WTLHelper;..\PECore 127 | stdcpp20 128 | 129 | 130 | Windows 131 | true 132 | 133 | 134 | 0x0409 135 | $(IntDir);%(AdditionalIncludeDirectories) 136 | _DEBUG;%(PreprocessorDefinitions) 137 | 138 | 139 | false 140 | _DEBUG;%(PreprocessorDefinitions) 141 | DepWalk.h 142 | DepWalk_i.c 143 | DepWalk_p.c 144 | true 145 | $(IntDir)/DepWalk.tlb 146 | 147 | 148 | 149 | 150 | 151 | Use 152 | Level3 153 | MultiThreadedDebug 154 | EditAndContinue 155 | EnableFastChecks 156 | Disabled 157 | WIN32;_WINDOWS;STRICT;_DEBUG;%(PreprocessorDefinitions) 158 | pch.h 159 | ..\WTLHelper\WTLHelper;..\PECore 160 | stdcpp20 161 | 162 | 163 | Windows 164 | true 165 | 166 | 167 | 0x0409 168 | $(IntDir);%(AdditionalIncludeDirectories) 169 | _DEBUG;%(PreprocessorDefinitions) 170 | 171 | 172 | false 173 | Win32 174 | _DEBUG;%(PreprocessorDefinitions) 175 | DepWalk.h 176 | DepWalk_i.c 177 | DepWalk_p.c 178 | true 179 | $(IntDir)/DepWalk.tlb 180 | 181 | 182 | 183 | 184 | 185 | Use 186 | Level3 187 | MultiThreaded 188 | Async 189 | 190 | WIN32;_WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions) 191 | pch.h 192 | ..\WTLHelper\WTLHelper;..\PECore 193 | stdcpp20 194 | 195 | 196 | Windows 197 | 198 | 199 | 0x0409 200 | $(IntDir);%(AdditionalIncludeDirectories) 201 | NDEBUG;%(PreprocessorDefinitions) 202 | 203 | 204 | false 205 | Win32 206 | NDEBUG;%(PreprocessorDefinitions) 207 | DepWalk.h 208 | DepWalk_i.c 209 | DepWalk_p.c 210 | true 211 | $(IntDir)/DepWalk.tlb 212 | 213 | 214 | 215 | 216 | 217 | Use 218 | Level3 219 | MultiThreaded 220 | Async 221 | 222 | 223 | WIN32;_WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions) 224 | pch.h 225 | ..\WTLHelper\WTLHelper;..\PECore 226 | stdcpp20 227 | 228 | 229 | Windows 230 | 231 | 232 | 0x0409 233 | $(IntDir);%(AdditionalIncludeDirectories) 234 | NDEBUG;%(PreprocessorDefinitions) 235 | 236 | 237 | false 238 | Win32 239 | NDEBUG;%(PreprocessorDefinitions) 240 | DepWalk.h 241 | DepWalk_i.c 242 | DepWalk_p.c 243 | true 244 | $(IntDir)/DepWalk.tlb 245 | 246 | 247 | 248 | 249 | signtool sign /i DigiCert /fd sha256 $(TargetPath) 250 | 251 | 252 | 253 | 254 | Use 255 | Level3 256 | MultiThreaded 257 | Async 258 | 259 | _WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions) 260 | pch.h 261 | ..\WTLHelper\WTLHelper;..\PECore 262 | stdcpp20 263 | 264 | 265 | Windows 266 | 267 | 268 | 0x0409 269 | $(IntDir);%(AdditionalIncludeDirectories) 270 | NDEBUG;%(PreprocessorDefinitions) 271 | 272 | 273 | false 274 | NDEBUG;%(PreprocessorDefinitions) 275 | DepWalk.h 276 | DepWalk_i.c 277 | DepWalk_p.c 278 | true 279 | $(IntDir)/DepWalk.tlb 280 | 281 | 282 | 283 | 284 | 285 | Use 286 | Level3 287 | MultiThreaded 288 | Async 289 | 290 | 291 | _WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions) 292 | pch.h 293 | ..\WTLHelper\WTLHelper;..\PECore 294 | stdcpp20 295 | 296 | 297 | Windows 298 | 299 | 300 | 0x0409 301 | $(IntDir);%(AdditionalIncludeDirectories) 302 | NDEBUG;%(PreprocessorDefinitions) 303 | 304 | 305 | false 306 | NDEBUG;%(PreprocessorDefinitions) 307 | DepWalk.h 308 | DepWalk_i.c 309 | DepWalk_p.c 310 | true 311 | $(IntDir)/DepWalk.tlb 312 | 313 | 314 | 315 | 316 | signtool sign /i DigiCert /fd sha256 $(TargetPath) 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | Create 325 | Create 326 | Create 327 | Create 328 | Create 329 | Create 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | {03a66844-1884-41c0-899d-f01c8a601c8e} 363 | 364 | 365 | {ae53419f-a769-4548-8e15-e311904df7df} 366 | 367 | 368 | 369 | 370 | 371 | -------------------------------------------------------------------------------- /DepWalk/DepWalk.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {792939db-2141-48f0-8398-2a70312a062a} 6 | cpp;c;cxx;def;odl;idl;hpj;bat;asm 7 | 8 | 9 | {39ae8328-99df-406f-8bdb-bc9e79c7e4e7} 10 | h;hpp;hxx;hm;inl;inc 11 | 12 | 13 | {030b6993-d96d-4d0b-884d-09fccda1e124} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest 15 | 16 | 17 | {3863e637-4d2c-4b80-ad92-dd356993916a} 18 | 19 | 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 49 | 50 | 51 | Header Files 52 | 53 | 54 | Header Files 55 | 56 | 57 | 58 | 59 | Resource Files 60 | 61 | 62 | 63 | 64 | Resource Files\Icons 65 | 66 | 67 | Resource Files\Icons 68 | 69 | 70 | Resource Files\Icons 71 | 72 | 73 | Resource Files\Icons 74 | 75 | 76 | Resource Files\Icons 77 | 78 | 79 | Resource Files\Icons 80 | 81 | 82 | Resource Files\Icons 83 | 84 | 85 | Resource Files\Icons 86 | 87 | 88 | Resource Files\Icons 89 | 90 | 91 | Resource Files\Icons 92 | 93 | 94 | Resource Files\Icons 95 | 96 | 97 | Resource Files\Icons 98 | 99 | 100 | Resource Files\Icons 101 | 102 | 103 | Resource Files\Icons 104 | 105 | 106 | -------------------------------------------------------------------------------- /DepWalk/Interfaces.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct IMainFrame abstract { 4 | }; 5 | -------------------------------------------------------------------------------- /DepWalk/MainFrm.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "resource.h" 3 | #include "AboutDlg.h" 4 | #include "View.h" 5 | #include "MainFrm.h" 6 | #include 7 | #include 8 | 9 | const int WINDOW_MENU_POSITION = 5; 10 | 11 | BOOL CMainFrame::PreTranslateMessage(MSG* pMsg) { 12 | if (CFrameWindowImpl::PreTranslateMessage(pMsg)) 13 | return TRUE; 14 | 15 | return m_view.PreTranslateMessage(pMsg); 16 | } 17 | 18 | BOOL CMainFrame::OnIdle() { 19 | UIUpdateToolBar(); 20 | return FALSE; 21 | } 22 | 23 | LRESULT CMainFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { 24 | ToolBarButtonInfo const buttons[] = { 25 | { ID_FILE_OPEN, IDI_OPEN }, 26 | { 0 }, 27 | { ID_EDIT_COPY, IDI_COPY }, 28 | }; 29 | CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE); 30 | auto tb = ToolbarHelper::CreateAndInitToolBar(m_hWnd, buttons, _countof(buttons)); 31 | 32 | AddSimpleReBarBand(tb); 33 | UIAddToolBar(tb); 34 | 35 | CreateSimpleStatusBar(); 36 | 37 | m_hWndClient = m_view.Create(m_hWnd, rcDefault, nullptr, 38 | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN); 39 | CImageList images; 40 | images.Create(16, 16, ILC_COLOR32 | ILC_MASK, 4, 4); 41 | m_view.SetImageList(images); 42 | 43 | UISetCheck(ID_VIEW_TOOLBAR, 1); 44 | UISetCheck(ID_VIEW_STATUS_BAR, 1); 45 | 46 | // register object for message filtering and idle updates 47 | CMessageLoop* pLoop = _Module.GetMessageLoop(); 48 | ATLASSERT(pLoop != NULL); 49 | pLoop->AddMessageFilter(this); 50 | pLoop->AddIdleHandler(this); 51 | 52 | CMenuHandle menuMain = GetMenu(); 53 | m_view.SetWindowMenu(menuMain.GetSubMenu(WINDOW_MENU_POSITION)); 54 | 55 | if (sizeof(PVOID) == 8) { 56 | CString text; 57 | GetWindowText(text); 58 | text += L" (64 bit)"; 59 | SetWindowText(text); 60 | } 61 | 62 | InitMenu(GetMenu()); 63 | AddMenu(GetMenu()); 64 | 65 | return 0; 66 | } 67 | 68 | void CMainFrame::InitMenu(HMENU hMenu) { 69 | struct { 70 | int id; 71 | UINT icon; 72 | HICON hIcon{ nullptr }; 73 | } const commands[] = { 74 | { ID_EDIT_COPY, IDI_COPY }, 75 | { ID_FILE_OPEN, IDI_OPEN }, 76 | { ID_FILE_SAVE, IDI_SAVE }, 77 | { ID_WINDOW_CLOSE, IDI_WIN_CLOSE }, 78 | { ID_WINDOW_CLOSE_ALL, IDI_WIN_CLOSEALL }, 79 | 80 | }; 81 | for (auto& cmd : commands) { 82 | if (cmd.icon) 83 | AddCommand(cmd.id, cmd.icon); 84 | else 85 | AddCommand(cmd.id, cmd.hIcon); 86 | } 87 | } 88 | 89 | LRESULT CMainFrame::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) { 90 | // unregister message filtering and idle updates 91 | CMessageLoop* pLoop = _Module.GetMessageLoop(); 92 | ATLASSERT(pLoop != NULL); 93 | pLoop->RemoveMessageFilter(this); 94 | pLoop->RemoveIdleHandler(this); 95 | 96 | bHandled = FALSE; 97 | return 1; 98 | } 99 | 100 | LRESULT CMainFrame::OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 101 | PostMessage(WM_CLOSE); 102 | return 0; 103 | } 104 | 105 | LRESULT CMainFrame::OnFileOpen(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 106 | CSimpleFileDialog dlg(TRUE, nullptr, nullptr, OFN_EXPLORER | OFN_ENABLESIZING, 107 | L"PE Files\0*.exe;*.dll;*.ocx;*.efi\0All Files\0*.*\0", m_hWnd); 108 | ThemeHelper::Suspend(); 109 | auto ok = dlg.DoModal() == IDOK; 110 | ThemeHelper::Resume(); 111 | if(ok) { 112 | auto pView = new CView(this); 113 | pView->Create(m_view, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0); 114 | CWaitCursor wait; 115 | if (!pView->ParseModules(dlg.m_szFileName)) { 116 | pView->DestroyWindow(); 117 | return 0; 118 | } 119 | auto hIcon = pView->GetMainIcon(); 120 | int index = CImageList(m_view.GetImageList()).AddIcon(hIcon); 121 | m_view.AddPage(pView->m_hWnd, dlg.m_szFileTitle, index, pView); 122 | } 123 | 124 | return 0; 125 | } 126 | 127 | LRESULT CMainFrame::OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 128 | static bool bVisible = TRUE; // initially visible 129 | bVisible = !bVisible; 130 | CReBarCtrl rebar = m_hWndToolBar; 131 | int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST + 1); // toolbar is 2nd added band 132 | rebar.ShowBand(nBandIndex, bVisible); 133 | UISetCheck(ID_VIEW_TOOLBAR, bVisible); 134 | UpdateLayout(); 135 | return 0; 136 | } 137 | 138 | LRESULT CMainFrame::OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 139 | auto bVisible = !::IsWindowVisible(m_hWndStatusBar); 140 | ::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE); 141 | UISetCheck(ID_VIEW_STATUS_BAR, bVisible); 142 | UpdateLayout(); 143 | return 0; 144 | } 145 | 146 | LRESULT CMainFrame::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 147 | CAboutDlg dlg; 148 | dlg.DoModal(); 149 | return 0; 150 | } 151 | 152 | LRESULT CMainFrame::OnAboutWindows(WORD, WORD, HWND, BOOL&) { 153 | std::thread([this]() { ::ShellAbout(m_hWnd, L"Windows", nullptr, nullptr); }).detach(); 154 | return 0; 155 | } 156 | 157 | LRESULT CMainFrame::OnWindowClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 158 | int nActivePage = m_view.GetActivePage(); 159 | if (nActivePage != -1) 160 | m_view.RemovePage(nActivePage); 161 | else 162 | ::MessageBeep((UINT)-1); 163 | 164 | return 0; 165 | } 166 | 167 | LRESULT CMainFrame::OnWindowCloseAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 168 | m_view.RemoveAllPages(); 169 | 170 | return 0; 171 | } 172 | 173 | LRESULT CMainFrame::OnWindowActivate(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 174 | int nPage = wID - ID_WINDOW_TABFIRST; 175 | m_view.SetActivePage(nPage); 176 | 177 | return 0; 178 | } 179 | -------------------------------------------------------------------------------- /DepWalk/MainFrm.h: -------------------------------------------------------------------------------- 1 | // MainFrm.h : interface of the CMainFrame class 2 | // 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #pragma once 6 | 7 | #include "Interfaces.h" 8 | #include 9 | #include 10 | 11 | class CMainFrame : 12 | public CFrameWindowImpl, 13 | public CAutoUpdateUI, 14 | public COwnerDrawnMenu, 15 | public IMainFrame, 16 | public CMessageFilter, 17 | public CIdleHandler { 18 | public: 19 | DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME) 20 | 21 | virtual BOOL PreTranslateMessage(MSG* pMsg); 22 | virtual BOOL OnIdle(); 23 | 24 | BEGIN_MSG_MAP(CMainFrame) 25 | COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit) 26 | COMMAND_ID_HANDLER(ID_FILE_OPEN, OnFileOpen) 27 | COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnViewToolBar) 28 | COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar) 29 | COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout) 30 | COMMAND_ID_HANDLER(ID_HELP_ABOUTWINDOWS, OnAboutWindows) 31 | COMMAND_ID_HANDLER(ID_WINDOW_CLOSE, OnWindowClose) 32 | COMMAND_ID_HANDLER(ID_WINDOW_CLOSE_ALL, OnWindowCloseAll) 33 | COMMAND_RANGE_HANDLER(ID_WINDOW_TABFIRST, ID_WINDOW_TABLAST, OnWindowActivate) 34 | MESSAGE_HANDLER(WM_CREATE, OnCreate) 35 | MESSAGE_HANDLER(WM_DESTROY, OnDestroy) 36 | CHAIN_MSG_MAP(CAutoUpdateUI) 37 | CHAIN_MSG_MAP(CFrameWindowImpl) 38 | CHAIN_MSG_MAP(COwnerDrawnMenu) 39 | END_MSG_MAP() 40 | 41 | private: 42 | void InitMenu(HMENU hMenu); 43 | 44 | // Handler prototypes (uncomment arguments if needed): 45 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) 46 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) 47 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) 48 | 49 | LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 50 | LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled); 51 | LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 52 | LRESULT OnFileOpen(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 53 | LRESULT OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 54 | LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 55 | LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 56 | LRESULT OnAboutWindows(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 57 | LRESULT OnWindowClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 58 | LRESULT OnWindowCloseAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 59 | LRESULT OnWindowActivate(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 60 | 61 | CCustomTabView m_view; 62 | }; 63 | -------------------------------------------------------------------------------- /DepWalk/ReleaseSigned/DepWalk.exe.recipe: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | D:\Dev\DepWalk\ReleaseSigned\DepWalk.exe 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /DepWalk/ReleaseSigned/DepWalk.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/DepWalk/ReleaseSigned/DepWalk.res -------------------------------------------------------------------------------- /DepWalk/View.cpp: -------------------------------------------------------------------------------- 1 | // View.cpp : implementation of the CView class 2 | // 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #include "pch.h" 6 | #include "resource.h" 7 | #include "View.h" 8 | #include 9 | #include 10 | 11 | #pragma comment(lib, "dbghelp") 12 | 13 | BOOL CView::PreTranslateMessage(MSG* pMsg) { 14 | pMsg; 15 | return FALSE; 16 | } 17 | 18 | LRESULT CView::OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { 19 | m_Tree.SetFocus(); 20 | return 0; 21 | } 22 | 23 | bool CView::ParseModules(PCWSTR path) { 24 | auto mi = std::make_unique(); 25 | auto& pe = mi->PE; 26 | if (!pe.Open(path)) 27 | return false; 28 | 29 | m_Modules.reserve(64); 30 | m_Tree.DeleteAllItems(); 31 | m_Tree.SetRedraw(FALSE); 32 | WCHAR fullpath[MAX_PATH]; 33 | wcscpy_s(fullpath, path); 34 | WORD icon = 0; 35 | auto hIcon = ::ExtractAssociatedIcon(_Module.GetModuleInstance(), fullpath, &icon); 36 | int image = -1; 37 | if (hIcon) 38 | image = m_Tree.GetImageList(TVSIL_NORMAL).AddIcon(hIcon); 39 | auto [hItem, m] = ParsePE(path, TVI_ROOT, image); 40 | auto tmi = std::make_unique(); 41 | tmi->Module = m; 42 | m_TreeItems.insert({ hItem, std::move(tmi) }); 43 | m_Tree.Expand(m_Tree.GetRootItem(), TVE_EXPAND); 44 | m_Tree.SelectItem(hItem); 45 | 46 | m_Tree.SetRedraw(TRUE); 47 | 48 | m_ModuleList.SetItemCount((int)m_Modules.size()); 49 | 50 | return true; 51 | } 52 | 53 | HICON CView::GetMainIcon() const { 54 | return m_Tree.GetImageList().GetIcon(m_Tree.GetImageList().GetImageCount() - 1); 55 | } 56 | 57 | PCWSTR CView::MachineTypeToString(WORD type) { 58 | switch (type) { 59 | case IMAGE_FILE_MACHINE_I386: return L"x86"; 60 | case IMAGE_FILE_MACHINE_ARM: return L"ARM"; 61 | case IMAGE_FILE_MACHINE_ARMNT: return L"ARM NT"; 62 | case IMAGE_FILE_MACHINE_IA64: return L"IA64"; 63 | case IMAGE_FILE_MACHINE_AMD64: return L"x64"; 64 | case IMAGE_FILE_MACHINE_ARM64: return L"ARM 64"; 65 | } 66 | return L""; 67 | } 68 | 69 | CString CView::SubsystemToString(uint32_t type) { 70 | CString subsys; 71 | switch (type) { 72 | case IMAGE_SUBSYSTEM_UNKNOWN: return L""; 73 | case IMAGE_SUBSYSTEM_NATIVE: subsys = L"Native"; break; 74 | case IMAGE_SUBSYSTEM_WINDOWS_GUI: subsys = L"Window GUI"; break; 75 | case IMAGE_SUBSYSTEM_WINDOWS_CUI: subsys = L"Windows CUI"; break; 76 | case IMAGE_SUBSYSTEM_OS2_CUI: subsys = L"OS2 CUI"; break; 77 | case IMAGE_SUBSYSTEM_POSIX_CUI: subsys = L"POSIX CUI"; break; 78 | case IMAGE_SUBSYSTEM_NATIVE_WINDOWS: subsys = L"Native Windows 9x"; break; 79 | case IMAGE_SUBSYSTEM_WINDOWS_CE_GUI: subsys = L"Windows CE GUI"; break; 80 | case IMAGE_SUBSYSTEM_EFI_APPLICATION: subsys = L"EFI Application"; break; 81 | case IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: subsys = L"EFI Boot Service Driver"; break; 82 | case IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: subsys = L"EFI Runtime Driver"; break; 83 | case IMAGE_SUBSYSTEM_EFI_ROM: subsys = L"EFI ROM"; break; 84 | case IMAGE_SUBSYSTEM_XBOX: subsys = L"XBOX"; break; 85 | case IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION: subsys = L"Windows Boot Application"; break; 86 | default: subsys = L"(Unknown)"; break; 87 | } 88 | CString temp; 89 | temp.Format(L" (%d)\n", (int)type); 90 | return subsys + temp; 91 | } 92 | 93 | CString CView::GetColumnText(HWND h, int row, int col) const { 94 | auto tag = GetColumnManager(h)->GetColumnTag(col); 95 | if (h == m_ModuleList) { 96 | auto& mi = m_Modules[row]; 97 | switch (tag) { 98 | case ColumnType::Name: return mi->Name.c_str(); 99 | case ColumnType::Path: return mi->FullPath.c_str(); 100 | case ColumnType::FileSize: 101 | if (!mi->IsApiSet && mi->PE->IsLoaded()) { 102 | WCHAR text[64]; 103 | ::StrFormatByteSize(mi->PE.GetFileSize(), text, _countof(text)); 104 | return text; 105 | } 106 | break; 107 | case ColumnType::FileTime: 108 | return mi->FullPath.empty() ? L"" : (PCWSTR)mi->GetFileTime(); 109 | case ColumnType::ImageBase: return mi->GetImageBase() == 0 ? L"" : std::format(L"0x{:X}", mi->GetImageBase()).c_str(); 110 | case ColumnType::Arch: return MachineTypeToString(mi->GetArch()); 111 | case ColumnType::Subsystem: return SubsystemToString(mi->GetSubsystem()); 112 | 113 | } 114 | } 115 | else if (h == m_ExportsList) { 116 | auto const& mod = m_TreeItems.at(m_Tree.GetSelectedItem()); 117 | auto mi = mod->Module; 118 | ATLASSERT(mi); 119 | auto& exp = mi->Exports[row]; 120 | switch (tag) { 121 | case ColumnType::Name: return exp.FuncName.c_str(); 122 | case ColumnType::ForwardedName: return exp.ForwarderName.c_str(); 123 | case ColumnType::Ordinal: return std::to_wstring(exp.Ordinal).c_str(); 124 | case ColumnType::RVA: return std::format(L"0x{:X}", exp.FuncRVA).c_str(); 125 | case ColumnType::NameRVA: return std::format(L"0x{:X}", exp.NameRVA).c_str(); 126 | case ColumnType::UndecoratedName: return exp.FuncName.empty() ? L"" : (PCWSTR)UndecorateName(exp.FuncName.c_str()); 127 | } 128 | } 129 | else { 130 | auto const& mod = m_TreeItems.at(m_Tree.GetSelectedItem()); 131 | auto const& func = mod->Imports[row]; 132 | switch (tag) { 133 | case ColumnType::Name: return func.FuncName.c_str(); 134 | case ColumnType::Hint: return std::to_wstring(func.ImpByName.Hint).c_str(); 135 | case ColumnType::Ordinal: return func.ImpByName.Name[0] == 0 ? std::to_wstring(func.unThunk.Thunk32.u1.Ordinal).c_str() : L"0"; 136 | case ColumnType::UndecoratedName: return func.FuncName.empty() ? L"" : (PCWSTR)UndecorateName(func.FuncName.c_str()); 137 | } 138 | } 139 | 140 | return CString(); 141 | } 142 | 143 | CString CView::UndecorateName(PCSTR name) { 144 | CHAR result[2048]; 145 | return 0 == ::UnDecorateSymbolName(name, result, _countof(result), 0) ? "" : result; 146 | } 147 | 148 | int CView::GetRowImage(HWND h, int row, int col) const { 149 | if (h == m_ModuleList) { 150 | auto& mi = m_Modules[row]; 151 | return mi->Icon; 152 | } 153 | else if (h == m_ExportsList) { 154 | return m_TreeItems.at(m_Tree.GetSelectedItem())->Module->Exports[row].ForwarderName.empty() ? 1 : 0; 155 | } 156 | 157 | return 0; 158 | } 159 | 160 | void CView::OnTreeSelChanged(HWND tree, HTREEITEM hOld, HTREEITEM hNew) { 161 | ATLASSERT(m_Tree.GetSelectedItem() == hNew); 162 | if (auto it = m_TreeItems.find(hNew); it != m_TreeItems.end()) { 163 | m_ImportsList.SetItemCount((int)it->second->Imports.size()); 164 | auto mi = it->second->Module; 165 | m_ExportsList.SetItemCount(mi ? (int)mi->Exports.size() : 0); 166 | Sort(m_ExportsList); 167 | Sort(m_ImportsList); 168 | } 169 | else { 170 | m_ImportsList.SetItemCount(0); 171 | m_ExportsList.SetItemCount(0); 172 | } 173 | } 174 | 175 | void CView::DoSort(SortInfo const* si) { 176 | auto asc = si->SortAscending; 177 | auto tag = GetColumnManager(si->hWnd)->GetColumnTag(si->SortColumn); 178 | 179 | if (si->hWnd == m_ModuleList) { 180 | auto compare = [&](auto& m1, auto& m2) { 181 | switch (tag) { 182 | case ColumnType::Name: return SortHelper::Sort(m1->Name, m2->Name, asc); 183 | case ColumnType::Path: return SortHelper::Sort(m1->FullPath, m2->FullPath, asc); 184 | case ColumnType::FileTime: return SortHelper::Sort(m1->FileTime, m2->FileTime, asc); 185 | case ColumnType::FileSize: return SortHelper::Sort(m1->PE.GetFileSize(), m2->PE.GetFileSize(), asc); 186 | case ColumnType::ImageBase: return SortHelper::Sort(m1->GetImageBase(), m2->GetImageBase(), asc); 187 | case ColumnType::Arch: return SortHelper::Sort(m1->GetArch(), m2->GetArch(), asc); 188 | case ColumnType::Subsystem: return SortHelper::Sort(m1->GetSubsystem(), m2->GetSubsystem(), asc); 189 | } 190 | return false; 191 | }; 192 | std::ranges::sort(m_Modules, compare); 193 | } 194 | else if (si->hWnd == m_ImportsList) { 195 | auto const& mod = m_TreeItems.at(m_Tree.GetSelectedItem()); 196 | 197 | auto compare = [&](auto& f1, auto& f2) { 198 | switch (tag) { 199 | case ColumnType::Name: return SortHelper::Sort(f1.FuncName, f2.FuncName, asc); 200 | case ColumnType::Hint: return SortHelper::Sort(f1.ImpByName.Hint, f2.ImpByName.Hint, asc); 201 | case ColumnType::Ordinal: return SortHelper::Sort(f1.ImpByName.Name[0] ? 0 : f1.unThunk.Thunk32.u1.Ordinal, f2.ImpByName.Name[0] ? 0 : f2.unThunk.Thunk32.u1.Ordinal, asc); 202 | } 203 | return false; 204 | }; 205 | std::ranges::sort(mod->Imports, compare); 206 | } 207 | else { 208 | auto const& mod = m_TreeItems.at(m_Tree.GetSelectedItem()); 209 | 210 | auto compare = [&](auto& f1, auto& f2) { 211 | switch (tag) { 212 | case ColumnType::Name: return SortHelper::Sort(f1.FuncName, f2.FuncName, asc); 213 | case ColumnType::ForwardedName: return SortHelper::Sort(f1.ForwarderName, f2.ForwarderName, asc); 214 | case ColumnType::Ordinal: return SortHelper::Sort(f1.Ordinal, f2.Ordinal, asc); 215 | case ColumnType::RVA: return SortHelper::Sort(f1.FuncRVA, f2.FuncRVA, asc); 216 | case ColumnType::NameRVA: return SortHelper::Sort(f1.NameRVA, f2.NameRVA, asc); 217 | } 218 | return false; 219 | }; 220 | std::ranges::sort(mod->Module->Exports, compare); 221 | } 222 | } 223 | 224 | std::pair CView::ParsePE(PCWSTR name, HTREEITEM hParent, int icon) { 225 | auto apiSet = _wcsnicmp(name, L"api-ms-", 7) == 0 || _wcsnicmp(name, L"ext-ms-", 7) == 0; 226 | auto fullpath = apiSet ? false : wcschr(name, L'\\') != nullptr; 227 | auto mi = std::make_unique(); 228 | auto m = mi.get(); 229 | bool newModule = false; 230 | 231 | if (fullpath) { 232 | if (auto it = m_ModulesMap.find(name); it != m_ModulesMap.end()) 233 | m = it->second; 234 | } 235 | else { 236 | m->Name = name; 237 | } 238 | 239 | auto hLib = apiSet || fullpath ? nullptr : ::LoadLibraryEx(name, nullptr, DONT_RESOLVE_DLL_REFERENCES); 240 | auto ext = wcsrchr(name, L'.'); 241 | if (!apiSet && !fullpath && hLib == nullptr && _wcsicmp(ext, L".sys") == 0) { 242 | // 243 | // try in drivers directory for sys files 244 | // 245 | static std::wstring driversDir; 246 | if (driversDir.empty()) { 247 | WCHAR path[MAX_PATH]; 248 | ::GetSystemDirectory(path, _countof(path)); 249 | wcscat_s(path, L"\\Drivers\\"); 250 | driversDir = path; 251 | } 252 | hLib = ::LoadLibraryEx((driversDir + name).c_str(), nullptr, DONT_RESOLVE_DLL_REFERENCES); 253 | if (hLib) 254 | m->FullPath = driversDir + name; 255 | } 256 | 257 | if (icon < 0) { 258 | // 259 | // icon setting 260 | // 261 | icon = apiSet ? 1 : 0; 262 | if (icon == 0) { 263 | if (_wcsicmp(ext, L".sys") == 0) 264 | icon = 3; 265 | } 266 | } 267 | m->IsApiSet = apiSet; 268 | if (apiSet || fullpath) { 269 | if (auto it = m_ModulesMap.find(name); it != m_ModulesMap.end()) 270 | m = it->second; 271 | else { 272 | newModule = true; 273 | m_ModulesMap.insert({ name, m }); 274 | } 275 | } 276 | HTREEITEM hItem{ nullptr }; 277 | if (hLib || fullpath) { 278 | WCHAR path[MAX_PATH]; 279 | DWORD chars = 1; 280 | if (!fullpath) { 281 | chars = ::GetModuleFileName(hLib, path, _countof(path)); 282 | if (hLib) 283 | ::FreeLibrary(hLib); 284 | if (chars) 285 | name = path; 286 | } 287 | if (auto it = m_ModulesMap.find(name); it != m_ModulesMap.end()) { 288 | m = it->second; 289 | } 290 | else { 291 | m_ModulesMap.insert({ name, m }); 292 | newModule = true; 293 | } 294 | 295 | m->FullPath = name; 296 | if (m->Name.empty()) 297 | m->Name = wcsrchr(name, L'\\') + 1; 298 | hItem = m_Tree.InsertItem(m->Name.c_str(), icon, icon, hParent, TVI_LAST); 299 | if ((chars && !m->PE->IsLoaded() && m->PE.Open(name))) { 300 | auto imports = m->PE->GetImport(); 301 | if (imports) { 302 | for (auto& lib : *imports) { 303 | std::wstring libname = (PCWSTR)CString(lib.ModuleName.c_str()); 304 | auto [hSubItem, m2] = ParsePE(libname.c_str(), hItem); 305 | auto nodeImports = std::make_unique(); 306 | nodeImports->Imports = lib.ImportFunc; 307 | nodeImports->Module = m2; 308 | m_TreeItems.insert({ hSubItem, std::move(nodeImports) }); 309 | } 310 | } 311 | } 312 | } 313 | else { 314 | if (apiSet) { 315 | // TODO 316 | } 317 | if (!apiSet && m->FullPath.empty()) 318 | icon = 2; 319 | hItem = m_Tree.InsertItem(m->Name.c_str(), icon, icon, hParent, TVI_LAST); 320 | } 321 | ATLASSERT(hItem); 322 | m->Icon = icon; 323 | if (m->PE->IsLoaded() && m->Exports.empty()) { 324 | auto exports = m->PE->GetExport(); 325 | if (exports) 326 | BuildExports(m, exports); 327 | } 328 | if (newModule) { 329 | m_Modules.push_back(std::move(mi)); 330 | } 331 | return { hItem, m }; 332 | } 333 | 334 | void CView::BuildExports(ModuleInfo* mi, libpe::PEExport* exports) const { 335 | mi->Exports = exports->Funcs; 336 | } 337 | 338 | LRESULT CView::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { 339 | m_hWndClient = m_MainSplitter.Create(m_hWnd, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN); 340 | m_VSplitter.Create(m_MainSplitter, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN); 341 | m_HSplitter.Create(m_VSplitter, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN); 342 | 343 | m_ModuleList.Create(m_MainSplitter, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | 344 | LVS_OWNERDATA | LVS_REPORT | LVS_SHAREIMAGELISTS); 345 | m_ModuleList.SetExtendedListViewStyle(LVS_EX_DOUBLEBUFFER | LVS_EX_INFOTIP | LVS_EX_FULLROWSELECT); 346 | 347 | m_Tree.Create(m_VSplitter, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_SHOWSELALWAYS); 348 | m_Tree.SetExtendedStyle(TVS_EX_DOUBLEBUFFER, TVS_EX_DOUBLEBUFFER); 349 | 350 | m_MainSplitter.SetSplitterPanes(m_VSplitter, m_ModuleList); 351 | m_MainSplitter.SetSplitterPosPct(65); 352 | m_VSplitter.SetSplitterPanes(m_Tree, m_HSplitter); 353 | m_VSplitter.SetSplitterPosPct(30); 354 | m_HSplitter.SetSplitterPosPct(50); 355 | 356 | m_ImportsList.Create(m_HSplitter, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | 357 | LVS_OWNERDATA | LVS_REPORT); 358 | m_ImportsList.SetExtendedListViewStyle(LVS_EX_DOUBLEBUFFER | LVS_EX_INFOTIP | LVS_EX_FULLROWSELECT); 359 | m_ExportsList.Create(m_HSplitter, rcDefault, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | 360 | LVS_OWNERDATA | LVS_REPORT); 361 | m_ExportsList.SetExtendedListViewStyle(LVS_EX_DOUBLEBUFFER | LVS_EX_INFOTIP | LVS_EX_FULLROWSELECT); 362 | m_HSplitter.SetSplitterPanes(m_ImportsList, m_ExportsList); 363 | 364 | { 365 | UINT icons[] = { IDI_DLL, IDI_INTERFACE, IDI_MOD_ERROR, IDI_SYSFILE }; 366 | CImageList images; 367 | images.Create(16, 16, ILC_COLOR32 | ILC_MASK, 4, 4); 368 | for (auto icon : icons) 369 | images.AddIcon(AtlLoadIconImage(icon, 0, 16, 16)); 370 | m_Tree.SetImageList(images); 371 | m_ModuleList.SetImageList(images, LVSIL_SMALL); 372 | } 373 | { 374 | UINT icons[] = { IDI_FUNC_EXPORT, IDI_FUNC }; 375 | CImageList images; 376 | images.Create(16, 16, ILC_COLOR32 | ILC_MASK, 4, 4); 377 | for (auto icon : icons) 378 | images.AddIcon(AtlLoadIconImage(icon, 0, 16, 16)); 379 | m_ExportsList.SetImageList(images, LVSIL_SMALL); 380 | } 381 | { 382 | UINT icons[] = { IDI_FUNC_IMPORT }; 383 | CImageList images; 384 | images.Create(16, 16, ILC_COLOR32 | ILC_MASK, 4, 4); 385 | for (auto icon : icons) 386 | images.AddIcon(AtlLoadIconImage(icon, 0, 16, 16)); 387 | m_ImportsList.SetImageList(images, LVSIL_SMALL); 388 | } 389 | 390 | auto cm = GetColumnManager(m_ModuleList); 391 | cm->AddColumn(L"Module Name", LVCFMT_LEFT, 280, ColumnType::Name); 392 | cm->AddColumn(L"Full Path", LVCFMT_LEFT, 350, ColumnType::Path); 393 | cm->AddColumn(L"File Size", LVCFMT_RIGHT, 100, ColumnType::FileSize); 394 | cm->AddColumn(L"File Time", LVCFMT_LEFT, 150, ColumnType::FileTime); 395 | cm->AddColumn(L"Link Time Stamp", LVCFMT_LEFT, 100, ColumnType::LinkTime); 396 | cm->AddColumn(L"Arch", LVCFMT_LEFT, 60, ColumnType::Arch); 397 | cm->AddColumn(L"Image Base", LVCFMT_RIGHT, 100, ColumnType::ImageBase); 398 | cm->AddColumn(L"Subsystem", LVCFMT_LEFT, 70, ColumnType::Subsystem); 399 | 400 | cm = GetColumnManager(m_ImportsList); 401 | cm->AddColumn(L"Name", LVCFMT_LEFT, 250, ColumnType::Name); 402 | cm->AddColumn(L"Ordinal", LVCFMT_RIGHT, 70, ColumnType::Ordinal); 403 | cm->AddColumn(L"Hint", LVCFMT_RIGHT, 70, ColumnType::Hint); 404 | cm->AddColumn(L"Undecorated Name", LVCFMT_LEFT, 250, ColumnType::UndecoratedName); 405 | 406 | cm = GetColumnManager(m_ExportsList); 407 | cm->AddColumn(L"Name", LVCFMT_LEFT, 250, ColumnType::Name); 408 | cm->AddColumn(L"Forwarder Name", LVCFMT_LEFT, 250, ColumnType::ForwardedName); 409 | cm->AddColumn(L"Ordinal", LVCFMT_RIGHT, 70, ColumnType::Ordinal); 410 | cm->AddColumn(L"Function RVA", LVCFMT_RIGHT, 100, ColumnType::RVA); 411 | cm->AddColumn(L"Name RVA", LVCFMT_RIGHT, 100, ColumnType::NameRVA); 412 | cm->AddColumn(L"Undecorated Name", LVCFMT_LEFT, 250, ColumnType::UndecoratedName); 413 | 414 | return 0; 415 | } 416 | 417 | CString const& ModuleInfo::GetFileTime() const { 418 | if (!FullPath.empty() && m_FileTimeAsString.IsEmpty()) { 419 | auto hFile = ::CreateFile(FullPath.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr); 420 | if (hFile != INVALID_HANDLE_VALUE) { 421 | FILETIME dummy; 422 | ::GetFileTime(hFile, &dummy, &dummy, (FILETIME*)&FileTime); 423 | WCHAR ft[96]; 424 | DWORD flags = FDTF_SHORTDATE | FDTF_SHORTTIME | FDTF_NOAUTOREADINGORDER; 425 | if (::SHFormatDateTime((FILETIME*)&FileTime, &flags, ft, _countof(ft))) 426 | m_FileTimeAsString = ft; 427 | ::CloseHandle(hFile); 428 | } 429 | } 430 | return m_FileTimeAsString; 431 | } 432 | 433 | ULONG64 ModuleInfo::GetImageBase() const { 434 | if (m_ImageBase == 0 && PE) { 435 | m_ImageBase = PE->GetFileInfo()->IsPE64 ? PE->GetNTHeader()->NTHdr64.OptionalHeader.ImageBase : PE->GetNTHeader()->NTHdr32.OptionalHeader.ImageBase; 436 | } 437 | return m_ImageBase; 438 | } 439 | 440 | WORD ModuleInfo::GetArch() const { 441 | if (m_Arch == 0 && PE) { 442 | m_Arch = PE->GetNTHeader()->NTHdr64.FileHeader.Machine; 443 | } 444 | return m_Arch; 445 | } 446 | 447 | WORD ModuleInfo::GetSubsystem() const { 448 | if (!PE) 449 | return 0; 450 | 451 | if (m_Subsystem == 0) { 452 | m_Subsystem = PE->GetFileInfo()->IsPE64 ? PE->GetNTHeader()->NTHdr64.OptionalHeader.Subsystem : PE->GetNTHeader()->NTHdr32.OptionalHeader.Subsystem; 453 | } 454 | return m_Subsystem; 455 | } 456 | -------------------------------------------------------------------------------- /DepWalk/View.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Interfaces.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | struct ModuleInfo { 11 | PEFile PE; 12 | std::wstring FullPath; 13 | std::wstring Name; 14 | std::vector Exports; 15 | int Icon; 16 | bool IsApiSet; 17 | mutable ULONG64 FileTime{ 0 }; 18 | CString const& GetFileTime() const; 19 | ULONG64 GetImageBase() const; 20 | WORD GetArch() const; 21 | WORD GetSubsystem() const; 22 | 23 | private: 24 | mutable CString m_FileTimeAsString; 25 | mutable ULONG64 m_ImageBase{ 0 }; 26 | mutable WORD m_Arch{ 0 }; 27 | mutable WORD m_Subsystem{ 0 }; 28 | }; 29 | 30 | struct ModuleTreeInfo { 31 | std::vector Imports; 32 | ModuleInfo* Module{ nullptr }; 33 | }; 34 | 35 | class CView : 36 | public CFrameView, 37 | public CVirtualListView, 38 | public CTreeViewHelper { 39 | public: 40 | using CFrameView::CFrameView; 41 | 42 | bool ParseModules(PCWSTR path); 43 | HICON GetMainIcon() const; 44 | CString GetColumnText(HWND h, int row, int col) const; 45 | int GetRowImage(HWND h, int row, int col) const; 46 | void OnTreeSelChanged(HWND tree, HTREEITEM hOld, HTREEITEM hNew); 47 | void DoSort(SortInfo const* si); 48 | 49 | BOOL PreTranslateMessage(MSG* pMsg); 50 | static CString UndecorateName(PCSTR name); 51 | static PCWSTR MachineTypeToString(WORD arch); 52 | static CString SubsystemToString(uint32_t type); 53 | 54 | protected: 55 | BEGIN_MSG_MAP(CView) 56 | MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) 57 | MESSAGE_HANDLER(WM_CREATE, OnCreate) 58 | CHAIN_MSG_MAP(BaseFrame) 59 | CHAIN_MSG_MAP(CVirtualListView) 60 | CHAIN_MSG_MAP(CTreeViewHelper) 61 | END_MSG_MAP() 62 | 63 | // Handler prototypes (uncomment arguments if needed): 64 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) 65 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) 66 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) 67 | 68 | private: 69 | enum class ColumnType { 70 | Name, Path, FileTime, LinkTime, FileSize, LinkChecksum, Arch, Subsystem, ImageBase, OSVersion, 71 | Hint, Ordinal, UndecoratedName, ForwardedName, RVA, NameRVA, 72 | }; 73 | 74 | std::pair ParsePE(PCWSTR name, HTREEITEM hParent, int icon = -1); 75 | void BuildExports(ModuleInfo* mi, libpe::PEExport* exports) const; 76 | 77 | LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 78 | LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 79 | 80 | CListViewCtrl m_ModuleList, m_ImportsList, m_ExportsList; 81 | CTreeViewCtrl m_Tree; 82 | CCustomHorSplitterWindow m_HSplitter, m_MainSplitter; 83 | CCustomSplitterWindow m_VSplitter; 84 | 85 | struct Compare { 86 | bool operator()(std::wstring const& s1, std::wstring const& s2) const { 87 | return _wcsicmp(s1.c_str(), s2.c_str()) < 0; 88 | } 89 | }; 90 | 91 | std::map m_ModulesMap; 92 | std::vector> m_Modules; 93 | std::unordered_map> m_TreeItems; 94 | }; 95 | -------------------------------------------------------------------------------- /DepWalk/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | -------------------------------------------------------------------------------- /DepWalk/pch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Change these values to use different versions 4 | #define WINVER 0x0601 5 | #define _WIN32_WINNT 0x0601 6 | #define _WIN32_IE 0x0700 7 | #define _RICHEDIT_VER 0x0500 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | extern CAppModule _Module; 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #if defined _M_IX86 35 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") 36 | #elif defined _M_IA64 37 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") 38 | #elif defined _M_X64 39 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") 40 | #else 41 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") 42 | #endif 43 | -------------------------------------------------------------------------------- /DepWalk/res/DLL.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/DepWalk/res/DLL.ico -------------------------------------------------------------------------------- /DepWalk/res/DepWalk.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/DepWalk/res/DepWalk.ico -------------------------------------------------------------------------------- /DepWalk/res/Error.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/DepWalk/res/Error.ico -------------------------------------------------------------------------------- /DepWalk/res/check.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/DepWalk/res/check.ico -------------------------------------------------------------------------------- /DepWalk/res/circle.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/DepWalk/res/circle.ico -------------------------------------------------------------------------------- /DepWalk/res/copy.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/DepWalk/res/copy.ico -------------------------------------------------------------------------------- /DepWalk/res/function-export.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/DepWalk/res/function-export.ico -------------------------------------------------------------------------------- /DepWalk/res/function-import.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/DepWalk/res/function-import.ico -------------------------------------------------------------------------------- /DepWalk/res/function.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/DepWalk/res/function.ico -------------------------------------------------------------------------------- /DepWalk/res/interface.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/DepWalk/res/interface.ico -------------------------------------------------------------------------------- /DepWalk/res/open.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/DepWalk/res/open.ico -------------------------------------------------------------------------------- /DepWalk/res/pin_green.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/DepWalk/res/pin_green.ico -------------------------------------------------------------------------------- /DepWalk/res/save.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/DepWalk/res/save.ico -------------------------------------------------------------------------------- /DepWalk/res/sysfile.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/DepWalk/res/sysfile.ico -------------------------------------------------------------------------------- /DepWalk/res/window-close.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/DepWalk/res/window-close.ico -------------------------------------------------------------------------------- /DepWalk/res/windows-close.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/DepWalk/res/windows-close.ico -------------------------------------------------------------------------------- /DepWalk/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by DepWalk.rc 4 | // 5 | #define IDD_ABOUTBOX 100 6 | #define IDR_MAINFRAME 128 7 | #define IDI_DLL 202 8 | #define IDI_FUNC_EXPORT 203 9 | #define IDI_FUNC_IMPORT 204 10 | #define IDI_INTERFACE 205 11 | #define IDI_OPEN 206 12 | #define IDI_PIN 207 13 | #define IDI_SAVE 208 14 | #define IDI_WIN_CLOSE 209 15 | #define IDI_WIN_CLOSEALL 210 16 | #define IDI_COPY 211 17 | #define IDI_ICON2 212 18 | #define IDI_FUNC 212 19 | #define IDI_MOD_ERROR 213 20 | #define IDI_ICON1 214 21 | #define IDI_SYSFILE 214 22 | #define IDC_VERSION 1000 23 | #define IDC_COPYRIGHT 1001 24 | #define IDC_SYSLINK 1002 25 | #define ID_WINDOW_CLOSE 32772 26 | #define ID_WINDOW_CLOSE_ALL 32773 27 | #define ID_OPTIONS_DARKMODE 32775 28 | #define ID_OPTIONS_ALWAYSONTOP 32776 29 | #define ID_TOOLS_SYSTEMINFORMATION 32777 30 | #define ID_HELP_ABOUTWINDOWS 32778 31 | 32 | // Next default values for new objects 33 | // 34 | #ifdef APSTUDIO_INVOKED 35 | #ifndef APSTUDIO_READONLY_SYMBOLS 36 | #define _APS_NEXT_RESOURCE_VALUE 215 37 | #define _APS_NEXT_COMMAND_VALUE 32779 38 | #define _APS_NEXT_CONTROL_VALUE 1003 39 | #define _APS_NEXT_SYMED_VALUE 101 40 | #endif 41 | #endif 42 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [year] [fullname] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PECore/PECore.cpp: -------------------------------------------------------------------------------- 1 | // PECore.cpp : Defines the functions for the static library. 2 | // 3 | 4 | #include "pch.h" 5 | -------------------------------------------------------------------------------- /PECore/PECore.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | ReleaseSigned 10 | Win32 11 | 12 | 13 | ReleaseSigned 14 | x64 15 | 16 | 17 | Release 18 | Win32 19 | 20 | 21 | Debug 22 | x64 23 | 24 | 25 | Release 26 | x64 27 | 28 | 29 | 30 | 16.0 31 | Win32Proj 32 | {03a66844-1884-41c0-899d-f01c8a601c8e} 33 | PECore 34 | 10.0 35 | 36 | 37 | 38 | StaticLibrary 39 | true 40 | v143 41 | Unicode 42 | 43 | 44 | StaticLibrary 45 | false 46 | v143 47 | true 48 | Unicode 49 | 50 | 51 | StaticLibrary 52 | false 53 | v143 54 | true 55 | Unicode 56 | 57 | 58 | StaticLibrary 59 | true 60 | v143 61 | Unicode 62 | 63 | 64 | StaticLibrary 65 | false 66 | v143 67 | true 68 | Unicode 69 | 70 | 71 | StaticLibrary 72 | false 73 | v143 74 | true 75 | Unicode 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | Level3 104 | true 105 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 106 | true 107 | Use 108 | pch.h 109 | stdcpp20 110 | MultiThreadedDebug 111 | 112 | 113 | 114 | 115 | true 116 | 117 | 118 | 119 | 120 | Level3 121 | true 122 | true 123 | true 124 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) 125 | true 126 | Use 127 | pch.h 128 | stdcpp20 129 | MultiThreaded 130 | Async 131 | 132 | 133 | 134 | 135 | true 136 | true 137 | true 138 | 139 | 140 | 141 | 142 | Level3 143 | true 144 | true 145 | true 146 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) 147 | true 148 | Use 149 | pch.h 150 | stdcpp20 151 | MultiThreaded 152 | Async 153 | 154 | 155 | 156 | 157 | true 158 | true 159 | true 160 | 161 | 162 | 163 | 164 | Level3 165 | true 166 | _DEBUG;_LIB;%(PreprocessorDefinitions) 167 | true 168 | Use 169 | pch.h 170 | stdcpp20 171 | MultiThreadedDebug 172 | 173 | 174 | 175 | 176 | true 177 | 178 | 179 | 180 | 181 | Level3 182 | true 183 | true 184 | true 185 | NDEBUG;_LIB;%(PreprocessorDefinitions) 186 | true 187 | Use 188 | pch.h 189 | stdcpp20 190 | MultiThreaded 191 | Async 192 | 193 | 194 | 195 | 196 | true 197 | true 198 | true 199 | 200 | 201 | 202 | 203 | Level3 204 | true 205 | true 206 | true 207 | NDEBUG;_LIB;%(PreprocessorDefinitions) 208 | true 209 | Use 210 | pch.h 211 | stdcpp20 212 | MultiThreaded 213 | Async 214 | 215 | 216 | 217 | 218 | true 219 | true 220 | true 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | Create 232 | Create 233 | Create 234 | Create 235 | Create 236 | Create 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 251 | 252 | 253 | 254 | -------------------------------------------------------------------------------- /PECore/PECore.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 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | 29 | 30 | Source Files 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /PECore/PEFile.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "PEFile.h" 3 | #include "libpe.h" 4 | 5 | bool PEFile::Open(std::wstring_view path) { 6 | auto ok = m_pe->LoadPe(path.data()) == libpe::PEOK; 7 | if (ok) { 8 | m_Path = path; 9 | } 10 | return ok; 11 | } 12 | 13 | void PEFile::Close() { 14 | m_pe->Clear(); 15 | m_Path = L""; 16 | } 17 | 18 | std::wstring const& PEFile::GetPath() const { 19 | return m_Path; 20 | } 21 | 22 | uint32_t PEFile::GetFileSize() const { 23 | return (uint32_t)m_pe->GetDataSize(); 24 | } 25 | 26 | PEFile::operator bool() const { 27 | return !m_Path.empty(); 28 | } 29 | 30 | bool PEFile::Read(uint32_t offset, uint32_t size, void* buffer) const { 31 | memcpy(buffer, (PBYTE)m_pe->GetBaseAddr() + offset, size); 32 | return true; 33 | } 34 | 35 | const BYTE* PEFile::GetData() const { 36 | return (const BYTE*)m_pe->GetBaseAddr(); 37 | } 38 | 39 | std::span PEFile::GetSpan(uint32_t offset, uint32_t size) const { 40 | return std::span((const std::byte*)GetData() + offset, size); 41 | } 42 | 43 | libpe::Ilibpe* PEFile::operator->() const { 44 | return m_pe.get(); 45 | } 46 | 47 | 48 | -------------------------------------------------------------------------------- /PECore/PEFile.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "libpe.h" 7 | #include 8 | 9 | class PEFile { 10 | public: 11 | PEFile() = default; 12 | PEFile(PEFile&&) = default; 13 | 14 | PEFile(PEFile const&) = delete; 15 | PEFile& operator=(PEFile const&) = delete; 16 | 17 | bool Open(std::wstring_view path); 18 | void Close(); 19 | 20 | std::wstring const& GetPath() const; 21 | uint32_t GetFileSize() const; 22 | 23 | bool Read(uint32_t offset, uint32_t size, void* buffer) const; 24 | template 25 | T Read(uint32_t offset) const { 26 | T value; 27 | Read(offset, sizeof(T), &value); 28 | return value; 29 | } 30 | 31 | const BYTE* GetData() const; 32 | std::span GetSpan(uint32_t offset, uint32_t size) const; 33 | 34 | libpe::Ilibpe* operator->() const; 35 | 36 | operator bool() const; 37 | 38 | private: 39 | libpe::IlibpePtr m_pe{ libpe::Createlibpe() }; 40 | std::wstring m_Path; 41 | }; 42 | 43 | -------------------------------------------------------------------------------- /PECore/ReleaseSigned/PECore.lib.recipe: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /PECore/libpe.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | * Copyright © 2018-2022, Jovibor: https://github.com/jovibor/ * 3 | * libpe is a library for obtaining PE32 (x86) and PE32+ (x64) files' inner structure. * 4 | * Official git repository: https://github.com/jovibor/libpe * 5 | * This software is available under the "MIT License". * 6 | ****************************************************************************************/ 7 | #include "pch.h" 8 | #include "libpe.h" 9 | #include 10 | #include 11 | 12 | #define LIBPE_PRODUCT_NAME L"libpe, (C) Jovibor 2018-2022, https://github.com/jovibor/libpe" 13 | #define LIBPE_VERSION_MAJOR 1 14 | #define LIBPE_VERSION_MINOR 2 15 | #define LIBPE_VERSION_MAINTENANCE 0 16 | 17 | #define TO_WSTR_HELPER(x) L## #x 18 | #define TO_WSTR(x) TO_WSTR_HELPER(x) 19 | 20 | namespace libpe { 21 | #ifdef _WIN64 22 | constexpr auto LIBPE_VERSION_WSTR = L"" TO_WSTR(LIBPE_VERSION_MAJOR) L"." TO_WSTR(LIBPE_VERSION_MINOR) L"." TO_WSTR(LIBPE_VERSION_MAINTENANCE) L" (x64)"; 23 | #else 24 | constexpr auto LIBPE_VERSION_WSTR = L"" TO_WSTR(LIBPE_VERSION_MAJOR) L"." TO_WSTR(LIBPE_VERSION_MINOR) L"." TO_WSTR(LIBPE_VERSION_MAINTENANCE); 25 | #endif 26 | 27 | constexpr auto LIBPE_VERSION_ULONGLONG = static_cast((static_cast(LIBPE_VERSION_MAJOR) << 48) 28 | | (static_cast(LIBPE_VERSION_MINOR) << 32) | (static_cast(LIBPE_VERSION_MAINTENANCE) << 16)); 29 | 30 | extern "C" ILIBPEAPI LIBPEINFO __cdecl GetLibInfo() { 31 | return { LIBPE_VERSION_WSTR, LIBPE_VERSION_ULONGLONG }; 32 | } 33 | 34 | //Checking overflow at summing two DWORD_PTR. 35 | constexpr bool IsSumOverflow(DWORD_PTR dwFirst, DWORD_PTR dwSecond) { 36 | return (dwFirst + dwSecond) < dwFirst; 37 | } 38 | 39 | //Class Clibpe. 40 | class Clibpe final : public Ilibpe { 41 | public: 42 | auto LoadPe(LPCWSTR pwszFile) -> int override; 43 | auto LoadPe(std::span spnFile) -> int override; 44 | [[nodiscard]] auto GetFileInfo()const->PEFILEINFO const* override; 45 | [[nodiscard]] auto IsLoaded() const -> bool override; 46 | [[nodiscard]] auto GetOffsetFromRVA(ULONGLONG ullRVA)const->DWORD override; 47 | [[nodiscard]] auto GetOffsetFromVA(ULONGLONG ullVA)const->DWORD override; 48 | [[nodiscard]] auto GetMSDOSHeader() -> IMAGE_DOS_HEADER* override; 49 | [[nodiscard]] auto GetRichHeader() -> PERICHHDR_VEC* override; 50 | [[nodiscard]] auto GetNTHeader() -> PENtHeader* override; 51 | [[nodiscard]] auto GetDataDirs() -> PEDATADIR_VEC* override; 52 | [[nodiscard]] auto GetSecHeaders() -> PESECHDR_VEC* override; 53 | [[nodiscard]] auto GetExport() -> PEExport* override; 54 | [[nodiscard]] auto GetImport() -> PEIMPORT_VEC* override; 55 | [[nodiscard]] auto GetResources() -> PEResRoot* override; 56 | [[nodiscard]] auto GetExceptions() -> PEEXCEPTION_VEC* override; 57 | [[nodiscard]] auto GetSecurity() -> PESECURITY_VEC* override; 58 | [[nodiscard]] auto GetRelocations() -> PERELOC_VEC* override; 59 | [[nodiscard]] auto GetDebug() -> PEDEBUG_VEC* override; 60 | [[nodiscard]] auto GetTLS() -> PETLS* override; 61 | [[nodiscard]] auto GetLoadConfig() -> PELoadConfig* override; 62 | [[nodiscard]] auto GetBoundImport() -> PEBOUNDIMPORT_VEC* override; 63 | [[nodiscard]] auto GetDelayImport() -> PEDELAYIMPORT_VEC* override; 64 | [[nodiscard]] auto GetCOMDescriptor() -> PECOMDESCRIPTOR* override; 65 | 66 | void Clear()override; 67 | void Destroy()override; 68 | private: 69 | void ClearAll(); 70 | [[nodiscard]] auto GetImageBase()const->ULONGLONG override; 71 | [[nodiscard]] auto GetSecHdrFromName(LPCSTR lpszName)const->PIMAGE_SECTION_HEADER override; 72 | [[nodiscard]] auto GetSecHdrFromRVA(ULONGLONG ullRVA)const->PIMAGE_SECTION_HEADER override; 73 | [[nodiscard]] auto GetBaseAddr()const->DWORD_PTR override; 74 | [[nodiscard]] auto GetDataSize()const->ULONGLONG override; 75 | [[nodiscard]] auto GetDosPtr()const->const IMAGE_DOS_HEADER*; 76 | [[nodiscard]] auto GetDirEntryRVA(DWORD dwEntry)const->DWORD; 77 | [[nodiscard]] auto GetDirEntrySize(DWORD dwEntry)const->DWORD; 78 | template 79 | [[nodiscard]] auto GetTData(ULONGLONG ullOffset)const->T; 80 | template 81 | [[nodiscard]] auto IsPtrSafe(T tAddr, bool fCanReferenceBoundary = false)const->bool; 82 | [[nodiscard]] auto PtrToOffset(LPCVOID lp)const->DWORD; 83 | [[nodiscard]] auto RVAToOffset(ULONGLONG ullRVA)const->DWORD; 84 | [[nodiscard]] auto RVAToPtr(ULONGLONG ullRVA)const->LPVOID; 85 | bool ParseMSDOSHeader(); 86 | bool ParseRichHeader(); 87 | bool ParseNTFileOptHeader(); 88 | bool ParseDataDirectories(); 89 | bool ParseSectionsHeaders(); 90 | bool ParseExport(); 91 | bool ParseImport(); 92 | bool ParseResources(); 93 | bool ParseExceptions(); 94 | bool ParseSecurity(); 95 | bool ParseRelocations(); 96 | bool ParseDebug(); 97 | bool ParseArchitecture(); 98 | bool ParseGlobalPtr(); 99 | bool ParseTLS(); 100 | bool ParseLCD(); 101 | bool ParseBoundImport(); 102 | bool ParseIAT(); 103 | bool ParseDelayImport(); 104 | bool ParseCOMDescriptor(); 105 | private: 106 | wil::unique_mapview_ptr m_ptr; 107 | wil::unique_handle m_map; 108 | bool m_fLoaded{ false }; //Flag shows PE load succession. 109 | std::unique_ptr m_pEmergencyMemory{ std::make_unique(0x8FFF) }; //Reserved 16K of memory. 110 | std::span m_spnData; //File data. 111 | PIMAGE_NT_HEADERS32 m_pNTHeader32{ }; //NT header pointer for x86. 112 | PIMAGE_NT_HEADERS64 m_pNTHeader64{ }; //NT header pointer for x64. 113 | 114 | //Further structs are for client code: 115 | PEFILEINFO m_stFileInfo{ }; //File information. 116 | IMAGE_DOS_HEADER m_stMSDOSHeader{ }; //DOS Header. 117 | PERICHHDR_VEC m_vecRichHeader{ }; //«Rich» header. 118 | PENtHeader m_stNTHeader{ }; //NT header. 119 | PEDATADIR_VEC m_vecDataDirs{ }; //DataDirectories. 120 | PESECHDR_VEC m_vecSecHeaders{ }; //Sections. 121 | PEExport m_stExport{ }; //Export table. 122 | PEIMPORT_VEC m_vecImport{ }; //Import table. 123 | PEResRoot m_stResource{ }; //Resources. 124 | PEEXCEPTION_VEC m_vecException{ }; //Exceptions. 125 | PESECURITY_VEC m_vecSecurity{ }; //Security table. 126 | PERELOC_VEC m_vecRelocs{ }; //Relocations. 127 | PEDEBUG_VEC m_vecDebug{ }; //Debug Table. 128 | PETLS m_stTLS{ }; //Thread Local Storage. 129 | PELoadConfig m_stLCD{ }; //LoadConfigTable. 130 | PEBOUNDIMPORT_VEC m_vecBoundImp{ }; //Bound import. 131 | PEDELAYIMPORT_VEC m_vecDelayImp{ }; //Delay import. 132 | PECOMDESCRIPTOR m_stCOR20Desc{ }; //COM table descriptor. 133 | }; 134 | 135 | //CreateRawlibpe implementation. 136 | extern "C" ILIBPEAPI Ilibpe * __cdecl CreateRawlibpe() { 137 | return new Clibpe(); 138 | } 139 | 140 | auto Clibpe::LoadPe(LPCWSTR pwszFile)->int { 141 | assert(pwszFile != nullptr); 142 | 143 | const auto hFile = CreateFileW(pwszFile, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); 144 | assert(hFile != INVALID_HANDLE_VALUE); 145 | if (hFile == INVALID_HANDLE_VALUE) 146 | return ERR_FILE_OPEN; 147 | 148 | LARGE_INTEGER stLI{ }; 149 | ::GetFileSizeEx(hFile, &stLI); 150 | assert(stLI.QuadPart >= sizeof(IMAGE_DOS_HEADER)); 151 | if (stLI.QuadPart < sizeof(IMAGE_DOS_HEADER)) { 152 | CloseHandle(hFile); 153 | return ERR_FILE_SIZESMALL; 154 | } 155 | 156 | m_map.reset(::CreateFileMappingW(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr)); 157 | CloseHandle(hFile); 158 | assert(m_map); 159 | if (!m_map) { 160 | return ERR_FILE_MAPPING; 161 | } 162 | 163 | m_ptr.reset((const std::byte*)MapViewOfFile(m_map.get(), FILE_MAP_READ, 0, 0, 0)); 164 | assert(m_ptr); //Not enough memory? File is too big? 165 | if (m_ptr == nullptr) { 166 | return ERR_FILE_MAPPING; 167 | } 168 | 169 | const auto ret = LoadPe({ m_ptr.get(), static_cast(stLI.QuadPart) }); 170 | m_ptr.reset(); 171 | 172 | return ret; 173 | } 174 | 175 | auto Clibpe::LoadPe(std::span spnFile)->int { 176 | assert(!spnFile.empty()); 177 | if (m_fLoaded) 178 | ClearAll(); 179 | 180 | if (spnFile.size() < sizeof(IMAGE_DOS_HEADER)) 181 | return ERR_FILE_SIZESMALL; 182 | 183 | m_spnData = spnFile; 184 | 185 | if (!ParseMSDOSHeader()) 186 | return ERR_FILE_NODOSHDR; 187 | 188 | m_fLoaded = true; 189 | 190 | ParseRichHeader(); 191 | 192 | if (ParseNTFileOptHeader()) { //If there is no NT header then it's pointless to parse further. 193 | ParseDataDirectories(); 194 | ParseSectionsHeaders(); 195 | ParseExport(); 196 | ParseImport(); 197 | ParseResources(); 198 | ParseExceptions(); 199 | ParseSecurity(); 200 | ParseRelocations(); 201 | ParseDebug(); 202 | ParseArchitecture(); 203 | ParseGlobalPtr(); 204 | ParseTLS(); 205 | ParseLCD(); 206 | ParseBoundImport(); 207 | ParseIAT(); 208 | ParseDelayImport(); 209 | ParseCOMDescriptor(); 210 | } 211 | 212 | return PEOK; 213 | } 214 | 215 | auto Clibpe::IsLoaded() const -> bool { 216 | return m_fLoaded; 217 | } 218 | 219 | auto Clibpe::GetFileInfo()const->PEFILEINFO const* { 220 | if (!m_fLoaded) 221 | return nullptr; 222 | 223 | return &m_stFileInfo; 224 | } 225 | 226 | auto Clibpe::GetOffsetFromRVA(ULONGLONG ullRVA)const->DWORD { 227 | assert(m_fLoaded); 228 | if (!m_fLoaded) 229 | return { }; 230 | 231 | return RVAToOffset(ullRVA); 232 | } 233 | 234 | auto Clibpe::GetOffsetFromVA(ULONGLONG ullVA)const->DWORD { 235 | assert(m_fLoaded); 236 | if (!m_fLoaded) 237 | return { }; 238 | 239 | return RVAToOffset(ullVA - GetImageBase()); 240 | } 241 | 242 | auto Clibpe::GetMSDOSHeader()->IMAGE_DOS_HEADER* { 243 | assert(m_fLoaded); 244 | if (!m_fLoaded || !m_stFileInfo.HasDosHdr) 245 | return nullptr; 246 | 247 | return &m_stMSDOSHeader; 248 | } 249 | 250 | auto Clibpe::GetRichHeader()->PERICHHDR_VEC* { 251 | assert(m_fLoaded); 252 | if (!m_fLoaded || !m_stFileInfo.HasRichHdr) 253 | return nullptr; 254 | 255 | return &m_vecRichHeader; 256 | } 257 | 258 | auto Clibpe::GetNTHeader()->PENtHeader* { 259 | assert(m_fLoaded); 260 | if (!m_fLoaded || !m_stFileInfo.HasNTHdr) 261 | return nullptr; 262 | 263 | return &m_stNTHeader; 264 | } 265 | 266 | auto Clibpe::GetDataDirs()->PEDATADIR_VEC* { 267 | assert(m_fLoaded); 268 | if (!m_fLoaded || !m_stFileInfo.HasDataDirs) 269 | return nullptr; 270 | 271 | return &m_vecDataDirs; 272 | } 273 | 274 | auto Clibpe::GetSecHeaders()->PESECHDR_VEC* { 275 | assert(m_fLoaded); 276 | if (!m_fLoaded || !m_stFileInfo.HasSections) 277 | return nullptr; 278 | 279 | return &m_vecSecHeaders; 280 | } 281 | 282 | auto Clibpe::GetExport()->PEExport* { 283 | assert(m_fLoaded); 284 | if (!m_fLoaded || !m_stFileInfo.HasExport) 285 | return nullptr; 286 | 287 | return &m_stExport; 288 | } 289 | 290 | auto Clibpe::GetImport()->PEIMPORT_VEC* { 291 | assert(m_fLoaded); 292 | if (!m_fLoaded || !m_stFileInfo.HasImport) 293 | return nullptr; 294 | 295 | return &m_vecImport; 296 | } 297 | 298 | auto Clibpe::GetResources()->PEResRoot* { 299 | assert(m_fLoaded); 300 | if (!m_fLoaded || !m_stFileInfo.HasResource) 301 | return nullptr; 302 | 303 | return &m_stResource; 304 | } 305 | 306 | auto Clibpe::GetExceptions()->PEEXCEPTION_VEC* { 307 | assert(m_fLoaded); 308 | if (!m_fLoaded || !m_stFileInfo.HasException) 309 | return nullptr; 310 | 311 | return &m_vecException; 312 | } 313 | 314 | auto Clibpe::GetSecurity()->PESECURITY_VEC* { 315 | assert(m_fLoaded); 316 | if (!m_fLoaded || !m_stFileInfo.HasSecurity) 317 | return nullptr; 318 | 319 | return &m_vecSecurity; 320 | } 321 | 322 | auto Clibpe::GetRelocations()->PERELOC_VEC* { 323 | assert(m_fLoaded); 324 | if (!m_fLoaded || !m_stFileInfo.HasReloc) 325 | return nullptr; 326 | 327 | return &m_vecRelocs; 328 | } 329 | 330 | auto Clibpe::GetDebug()->PEDEBUG_VEC* { 331 | assert(m_fLoaded); 332 | if (!m_fLoaded || !m_stFileInfo.HasDebug) 333 | return nullptr; 334 | 335 | return &m_vecDebug; 336 | } 337 | 338 | auto Clibpe::GetTLS()->PETLS* { 339 | assert(m_fLoaded); 340 | if (!m_fLoaded || !m_stFileInfo.HasTLS) 341 | return nullptr; 342 | 343 | return &m_stTLS; 344 | } 345 | 346 | auto Clibpe::GetLoadConfig()->PELoadConfig* { 347 | assert(m_fLoaded); 348 | if (!m_fLoaded || !m_stFileInfo.HasLoadCFG) 349 | return nullptr; 350 | 351 | return &m_stLCD; 352 | } 353 | 354 | auto Clibpe::GetBoundImport()->PEBOUNDIMPORT_VEC* { 355 | assert(m_fLoaded); 356 | if (!m_fLoaded || !m_stFileInfo.HasBoundImp) 357 | return nullptr; 358 | 359 | return &m_vecBoundImp; 360 | } 361 | 362 | auto Clibpe::GetDelayImport()->PEDELAYIMPORT_VEC* { 363 | assert(m_fLoaded); 364 | if (!m_fLoaded || !m_stFileInfo.HasDelayImp) 365 | return nullptr; 366 | 367 | return &m_vecDelayImp; 368 | } 369 | 370 | auto Clibpe::GetCOMDescriptor()->PECOMDESCRIPTOR* { 371 | assert(m_fLoaded); 372 | if (!m_fLoaded || !m_stFileInfo.HasCOMDescr) 373 | return nullptr; 374 | 375 | return &m_stCOR20Desc; 376 | } 377 | 378 | void Clibpe::Clear() { 379 | ClearAll(); 380 | } 381 | 382 | void Clibpe::Destroy() { 383 | delete this; 384 | } 385 | 386 | auto Ilibpe::FlatResources(const PEResRoot& stResRoot)->PERESFLAT_VEC { 387 | std::size_t sTotalRes{ 0 }; //How many resources total? 388 | for (const auto& iterRoot : stResRoot.ResData) { //To reserve space in vector, count total amount of resources. 389 | const auto pResDirEntry = &iterRoot.ResDirEntry; //Level Root 390 | if (pResDirEntry->DataIsDirectory) { 391 | const auto pstResLvL2 = &iterRoot.ResLvL2; 392 | for (const auto& iterLvL2 : pstResLvL2->ResData) { 393 | const auto pResDirEntry2 = &iterLvL2.ResDirEntry; //Level 2 IMAGE_RESOURCE_DIRECTORY_ENTRY 394 | if (pResDirEntry2->DataIsDirectory) { 395 | sTotalRes += iterLvL2.ResLvL3.ResData.size(); //Level 3 396 | } 397 | else 398 | ++sTotalRes; 399 | } 400 | } 401 | else 402 | ++sTotalRes; 403 | } 404 | 405 | std::vector vecData{ }; 406 | vecData.reserve(sTotalRes); 407 | for (auto& iterRoot : stResRoot.ResData) { 408 | PEResFlat stRes{ }; 409 | const auto pResDirEntryRoot = &iterRoot.ResDirEntry; //Level Root IMAGE_RESOURCE_DIRECTORY_ENTRY 410 | if (pResDirEntryRoot->NameIsString) 411 | stRes.TypeStr = iterRoot.ResName; 412 | else 413 | stRes.TypeID = pResDirEntryRoot->Id; 414 | 415 | if (pResDirEntryRoot->DataIsDirectory) { 416 | for (auto& iterLvL2 : iterRoot.ResLvL2.ResData) { 417 | const auto pResDirEntry2 = &iterLvL2.ResDirEntry; //Level 2 IMAGE_RESOURCE_DIRECTORY_ENTRY 418 | if (pResDirEntry2->NameIsString) 419 | stRes.NameStr = iterLvL2.ResName; 420 | else 421 | stRes.NameID = pResDirEntry2->Id; 422 | 423 | if (pResDirEntry2->DataIsDirectory) { 424 | for (auto& iterLvL3 : iterLvL2.ResLvL3.ResData) { 425 | const auto pResDirEntry3 = &iterLvL3.ResDirEntry; //Level 3 IMAGE_RESOURCE_DIRECTORY_ENTRY 426 | if (pResDirEntry3->NameIsString) 427 | stRes.LangStr = iterLvL3.ResName; 428 | else 429 | stRes.LangID = pResDirEntry3->Id; 430 | 431 | stRes.Data = iterLvL3.RawResData; 432 | vecData.emplace_back(stRes); 433 | } 434 | } 435 | else { 436 | stRes.Data = iterLvL2.RawResData; 437 | vecData.emplace_back(stRes); 438 | } 439 | } 440 | } 441 | else { 442 | stRes.Data = iterRoot.RawResData; 443 | vecData.emplace_back(stRes); 444 | } 445 | } 446 | 447 | return vecData; 448 | } 449 | 450 | 451 | //Clibpe private methods. 452 | 453 | void Clibpe::ClearAll() { 454 | /****************************************************************************** 455 | * Clearing all internal vectors and nullify all structs, pointers and flags. * 456 | * Called if LoadPe is invoked second time by the same Ilibpe pointer. * 457 | ******************************************************************************/ 458 | m_fLoaded = false; 459 | m_spnData = {}; 460 | m_pNTHeader32 = nullptr; 461 | m_pNTHeader64 = nullptr; 462 | m_stFileInfo = { }; 463 | m_stMSDOSHeader = { }; 464 | m_vecRichHeader.clear(); 465 | m_stNTHeader = { }; 466 | m_vecDataDirs.clear(); 467 | m_vecSecHeaders.clear(); 468 | m_stExport = { }; 469 | m_vecImport.clear(); 470 | m_stResource = { }; 471 | m_vecException.clear(); 472 | m_vecSecurity.clear(); 473 | m_vecRelocs.clear(); 474 | m_vecDebug.clear(); 475 | m_stTLS = { }; 476 | m_stLCD = { }; 477 | m_vecBoundImp.clear(); 478 | m_vecDelayImp.clear(); 479 | m_stCOR20Desc = { }; 480 | } 481 | 482 | auto Clibpe::GetBaseAddr()const->DWORD_PTR { 483 | return reinterpret_cast(m_ptr.get()); 484 | } 485 | 486 | auto Clibpe::GetDataSize()const->ULONGLONG { 487 | return m_spnData.size(); 488 | } 489 | 490 | auto Clibpe::GetDosPtr()const->const IMAGE_DOS_HEADER* { 491 | return reinterpret_cast(m_spnData.data()); 492 | } 493 | 494 | auto Clibpe::GetDirEntryRVA(DWORD dwEntry)const->DWORD { 495 | if (!m_stFileInfo.HasNTHdr) 496 | return { }; 497 | 498 | if (m_stFileInfo.IsPE32) 499 | return m_pNTHeader32->OptionalHeader.DataDirectory[dwEntry].VirtualAddress; 500 | 501 | if (m_stFileInfo.IsPE64) 502 | return m_pNTHeader64->OptionalHeader.DataDirectory[dwEntry].VirtualAddress; 503 | 504 | return { }; 505 | } 506 | 507 | auto Clibpe::GetDirEntrySize(DWORD dwEntry)const->DWORD { 508 | if (!m_stFileInfo.HasNTHdr) 509 | return { }; 510 | 511 | if (m_stFileInfo.IsPE32) 512 | return m_pNTHeader32->OptionalHeader.DataDirectory[dwEntry].Size; 513 | 514 | if (m_stFileInfo.IsPE64) 515 | return m_pNTHeader64->OptionalHeader.DataDirectory[dwEntry].Size; 516 | 517 | return { }; 518 | } 519 | 520 | auto Clibpe::GetImageBase()const->ULONGLONG { 521 | if (m_stFileInfo.IsPE32) { 522 | return m_pNTHeader32->OptionalHeader.ImageBase; 523 | } 524 | 525 | if (m_stFileInfo.IsPE64) { 526 | return m_pNTHeader64->OptionalHeader.ImageBase; 527 | } 528 | 529 | return { }; 530 | } 531 | 532 | auto Clibpe::GetSecHdrFromName(LPCSTR lpszName)const->PIMAGE_SECTION_HEADER { 533 | PIMAGE_SECTION_HEADER pSecHdr; 534 | WORD wNumberOfSections; 535 | 536 | if (m_stFileInfo.IsPE32 && m_stFileInfo.HasNTHdr) { 537 | pSecHdr = IMAGE_FIRST_SECTION(m_pNTHeader32); 538 | wNumberOfSections = m_pNTHeader32->FileHeader.NumberOfSections; 539 | } 540 | else if (m_stFileInfo.IsPE64 && m_stFileInfo.HasNTHdr) { 541 | pSecHdr = IMAGE_FIRST_SECTION(m_pNTHeader64); 542 | wNumberOfSections = m_pNTHeader64->FileHeader.NumberOfSections; 543 | } 544 | else 545 | return nullptr; 546 | 547 | for (unsigned i = 0; i < wNumberOfSections; ++i, ++pSecHdr) { 548 | if (!IsPtrSafe(reinterpret_cast(pSecHdr) + sizeof(IMAGE_SECTION_HEADER))) 549 | break; 550 | if (strncmp(reinterpret_cast(pSecHdr->Name), lpszName, IMAGE_SIZEOF_SHORT_NAME) == 0) 551 | return pSecHdr; 552 | } 553 | 554 | return nullptr; 555 | } 556 | 557 | auto Clibpe::GetSecHdrFromRVA(ULONGLONG ullRVA)const->PIMAGE_SECTION_HEADER { 558 | PIMAGE_SECTION_HEADER pSecHdr; 559 | WORD wNumOfSections; 560 | 561 | if (m_stFileInfo.IsPE32 && m_stFileInfo.HasNTHdr) { 562 | pSecHdr = IMAGE_FIRST_SECTION(m_pNTHeader32); 563 | wNumOfSections = m_pNTHeader32->FileHeader.NumberOfSections; 564 | } 565 | else if (m_stFileInfo.IsPE64 && m_stFileInfo.HasNTHdr) { 566 | pSecHdr = IMAGE_FIRST_SECTION(m_pNTHeader64); 567 | wNumOfSections = m_pNTHeader64->FileHeader.NumberOfSections; 568 | } 569 | else 570 | return nullptr; 571 | 572 | for (unsigned i = 0; i < wNumOfSections; ++i, ++pSecHdr) { 573 | if (!IsPtrSafe(reinterpret_cast(pSecHdr) + sizeof(IMAGE_SECTION_HEADER))) 574 | return nullptr; 575 | //Is RVA within this section? 576 | if ((ullRVA >= pSecHdr->VirtualAddress) && (ullRVA < (pSecHdr->VirtualAddress + pSecHdr->Misc.VirtualSize))) 577 | return pSecHdr; 578 | } 579 | 580 | return nullptr; 581 | } 582 | 583 | template 584 | auto Clibpe::GetTData(ULONGLONG ullOffset)const->T { 585 | if (ullOffset > (GetDataSize() - sizeof(T))) //Check for file size exceeding. 586 | return { }; 587 | 588 | return *reinterpret_cast(GetBaseAddr() + ullOffset); 589 | } 590 | 591 | template 592 | auto Clibpe::IsPtrSafe(const T tAddr, bool fCanReferenceBoundary)const->bool { 593 | /************************************************************************************************** 594 | * This func checks given pointer for nullptr and, more important, whether it fits allowed bounds. * 595 | * In PE headers there are plenty of places where wrong (bogus) values for pointers might reside, * 596 | * causing many runtime «fun» if trying to dereference them. * 597 | * Second arg (fCanReferenceBoundary) shows if pointer can point to the very end of a file, it's * 598 | * valid for some PE structures. Template is used just for convenience, sometimes there is a need * 599 | * to check pure address DWORD_PTR instead of a pointer. * 600 | **************************************************************************************************/ 601 | DWORD_PTR dwAddr; 602 | if constexpr (!std::is_same_v) { 603 | dwAddr = reinterpret_cast(tAddr); 604 | } 605 | else { 606 | dwAddr = tAddr; 607 | } 608 | 609 | const auto ullMaxAddr = GetBaseAddr() + GetDataSize(); 610 | 611 | return dwAddr == 0 ? false : (fCanReferenceBoundary ? 612 | ((dwAddr <= ullMaxAddr) && (dwAddr >= GetBaseAddr())) : 613 | ((dwAddr < ullMaxAddr) && (dwAddr >= GetBaseAddr()))); 614 | } 615 | 616 | auto Clibpe::PtrToOffset(LPCVOID lp)const->DWORD { 617 | if (lp == nullptr) 618 | return 0; 619 | 620 | return static_cast(reinterpret_cast(lp) - GetBaseAddr()); 621 | } 622 | 623 | auto Clibpe::RVAToOffset(ULONGLONG ullRVA)const->DWORD { 624 | DWORD dwOffset{ }; 625 | for (const auto& iter : m_vecSecHeaders) { 626 | const auto& pSecHdr = iter.SecHdr; 627 | //Is RVA within this section? 628 | if ((ullRVA >= pSecHdr.VirtualAddress) && (ullRVA < (pSecHdr.VirtualAddress + pSecHdr.Misc.VirtualSize))) { 629 | dwOffset = static_cast(ullRVA) - (pSecHdr.VirtualAddress - pSecHdr.PointerToRawData); 630 | if (dwOffset > static_cast(GetDataSize())) 631 | dwOffset = 0; 632 | } 633 | } 634 | 635 | return dwOffset; 636 | } 637 | 638 | auto Clibpe::RVAToPtr(ULONGLONG ullRVA)const->LPVOID { 639 | const auto pSecHdr = GetSecHdrFromRVA(ullRVA); 640 | if (pSecHdr == nullptr) 641 | return nullptr; 642 | 643 | const auto ptr = reinterpret_cast(GetBaseAddr() + ullRVA 644 | - static_cast(pSecHdr->VirtualAddress - pSecHdr->PointerToRawData)); 645 | 646 | return IsPtrSafe(ptr, true) ? ptr : nullptr; 647 | } 648 | 649 | bool Clibpe::ParseMSDOSHeader() { 650 | const auto pDosHdr = GetDosPtr(); 651 | 652 | //If file has at least MSDOS header signature then we can assume, 653 | //that this is a minimally correct PE file and process further. 654 | if (pDosHdr->e_magic != IMAGE_DOS_SIGNATURE) 655 | return false; 656 | 657 | m_stMSDOSHeader = *pDosHdr; 658 | m_stFileInfo.HasDosHdr = true; 659 | 660 | return true; 661 | } 662 | 663 | bool Clibpe::ParseRichHeader() { 664 | //Undocumented, so called «Rich» header, dwells not in all PE files. 665 | //«Rich» stub starts at 0x80 offset, before pDosHdr->e_lfanew (PE header offset start). 666 | //If e_lfanew <= 0x80 — there is no «Rich» header. 667 | 668 | const auto ullBaseAddr = GetBaseAddr(); 669 | const auto e_lfanew = GetDosPtr()->e_lfanew; 670 | if (e_lfanew <= 0x80 || !IsPtrSafe(ullBaseAddr + static_cast(e_lfanew))) 671 | return false; 672 | 673 | const auto pRichStartVA = reinterpret_cast(ullBaseAddr + 0x80); 674 | PDWORD pRichIter = pRichStartVA; 675 | 676 | for (auto i = 0; i < ((e_lfanew - 0x80) / 4); ++i, ++pRichIter) { 677 | //Check "Rich" (ANSI) sign, it's always at the end of the «Rich» header. 678 | //Then take DWORD right after the "Rich" sign — it's a xor mask. 679 | //Apply this mask to the first DWORD of «Rich» header, it must be "DanS" (ANSI) after xoring. 680 | if ((*pRichIter == 0x68636952/*"Rich"*/) && ((*pRichStartVA ^ *(pRichIter + 1)) == 0x536E6144/*"Dans"*/) 681 | && (reinterpret_cast(pRichIter) >= ullBaseAddr + 0x90)) { //To avoid too small (bogus) «Rich» header. 682 | //Amount of all «Rich» DOUBLE_DWORD structs. 683 | //First 16 bytes in «Rich» header are irrelevant. It's "DanS" itself and 12 more zeroed bytes. 684 | //That's why we subtracting 0x90 to find out amount of all «Rich» structures: 685 | //0x80 («Rich» start) + 16 (0x10) = 0x90. 686 | const DWORD dwRichSize = static_cast((reinterpret_cast(pRichIter) - ullBaseAddr) - 0x90) / 8; 687 | const DWORD dwRichXORMask = *(pRichIter + 1); //xor mask of «Rich» header. 688 | pRichIter = reinterpret_cast(ullBaseAddr + 0x90);//VA of «Rich» DOUBLE_DWORD structs start. 689 | 690 | for (unsigned j = 0; j < dwRichSize; ++j) { 691 | //Pushing double DWORD of «Rich» structure. 692 | //Disassembling first DWORD by two WORDs. 693 | m_vecRichHeader.emplace_back(static_cast(reinterpret_cast(pRichIter) - GetBaseAddr()), 694 | HIWORD(dwRichXORMask ^ *pRichIter), LOWORD(dwRichXORMask ^ *pRichIter), dwRichXORMask ^ *(pRichIter + 1)); 695 | pRichIter += 2; //Jump to the next DOUBLE_DWORD. 696 | } 697 | 698 | m_stFileInfo.HasRichHdr = true; 699 | 700 | return true; 701 | } 702 | } 703 | 704 | return false; 705 | } 706 | 707 | bool Clibpe::ParseNTFileOptHeader() { 708 | const auto pNTHeader = reinterpret_cast(GetBaseAddr() 709 | + static_cast(GetDosPtr()->e_lfanew)); 710 | if (!IsPtrSafe(reinterpret_cast(pNTHeader) + sizeof(IMAGE_NT_HEADERS32))) 711 | return false; 712 | 713 | if (pNTHeader->Signature != IMAGE_NT_SIGNATURE) 714 | return false; 715 | 716 | switch (pNTHeader->OptionalHeader.Magic) { 717 | case IMAGE_NT_OPTIONAL_HDR32_MAGIC: 718 | m_stFileInfo.IsPE32 = true; 719 | m_pNTHeader32 = pNTHeader; 720 | m_stNTHeader.NTHdr32 = *m_pNTHeader32; 721 | m_stNTHeader.dwOffset = PtrToOffset(m_pNTHeader32); 722 | break; 723 | case IMAGE_NT_OPTIONAL_HDR64_MAGIC: 724 | m_stFileInfo.IsPE64 = true; 725 | m_pNTHeader64 = reinterpret_cast(pNTHeader); 726 | m_stNTHeader.NTHdr64 = *m_pNTHeader64; 727 | m_stNTHeader.dwOffset = PtrToOffset(m_pNTHeader64); 728 | break; 729 | //case IMAGE_ROM_OPTIONAL_HDR_MAGIC: //Not implemented yet. 730 | default: 731 | return false; 732 | } 733 | 734 | m_stFileInfo.HasNTHdr = true; 735 | 736 | return true; 737 | } 738 | 739 | bool Clibpe::ParseDataDirectories() { 740 | PIMAGE_DATA_DIRECTORY pDataDir; 741 | PIMAGE_SECTION_HEADER pSecHdr; 742 | DWORD dwRVAAndSizes; 743 | 744 | if (m_stFileInfo.IsPE32 && m_stFileInfo.HasNTHdr) { 745 | pDataDir = reinterpret_cast(m_pNTHeader32->OptionalHeader.DataDirectory); 746 | dwRVAAndSizes = m_pNTHeader32->OptionalHeader.NumberOfRvaAndSizes; 747 | } 748 | else if (m_stFileInfo.IsPE64 && m_stFileInfo.HasNTHdr) { 749 | pDataDir = reinterpret_cast(m_pNTHeader64->OptionalHeader.DataDirectory); 750 | dwRVAAndSizes = m_pNTHeader64->OptionalHeader.NumberOfRvaAndSizes; 751 | } 752 | else 753 | return false; 754 | 755 | //Filling DataDirectories vector. 756 | for (unsigned i = 0; i < (dwRVAAndSizes > 15 ? 15 : dwRVAAndSizes); ++i, ++pDataDir) { 757 | std::string strSecName; 758 | 759 | pSecHdr = GetSecHdrFromRVA(pDataDir->VirtualAddress); 760 | //RVA of IMAGE_DIRECTORY_ENTRY_SECURITY is the file RAW offset. 761 | if (pSecHdr && (i != IMAGE_DIRECTORY_ENTRY_SECURITY)) 762 | strSecName.assign(reinterpret_cast(pSecHdr->Name), 8); 763 | 764 | m_vecDataDirs.emplace_back(*pDataDir, std::move(strSecName)); 765 | } 766 | 767 | if (m_vecDataDirs.empty()) 768 | return false; 769 | 770 | m_stFileInfo.HasDataDirs = true; 771 | 772 | return true; 773 | } 774 | 775 | bool Clibpe::ParseSectionsHeaders() { 776 | PIMAGE_SECTION_HEADER pSecHdr; 777 | WORD wNumSections; 778 | DWORD dwSymbolTable, dwNumberOfSymbols; 779 | 780 | if (m_stFileInfo.IsPE32 && m_stFileInfo.HasNTHdr) { 781 | pSecHdr = IMAGE_FIRST_SECTION(m_pNTHeader32); 782 | wNumSections = m_pNTHeader32->FileHeader.NumberOfSections; 783 | dwSymbolTable = m_pNTHeader32->FileHeader.PointerToSymbolTable; 784 | dwNumberOfSymbols = m_pNTHeader32->FileHeader.NumberOfSymbols; 785 | } 786 | else if (m_stFileInfo.IsPE64 && m_stFileInfo.HasNTHdr) { 787 | pSecHdr = IMAGE_FIRST_SECTION(m_pNTHeader64); 788 | wNumSections = m_pNTHeader64->FileHeader.NumberOfSections; 789 | dwSymbolTable = m_pNTHeader64->FileHeader.PointerToSymbolTable; 790 | dwNumberOfSymbols = m_pNTHeader64->FileHeader.NumberOfSymbols; 791 | } 792 | else 793 | return false; 794 | 795 | m_vecSecHeaders.reserve(wNumSections); 796 | 797 | for (unsigned i = 0; i < wNumSections; ++i, ++pSecHdr) { 798 | if (!IsPtrSafe(reinterpret_cast(pSecHdr) + sizeof(IMAGE_SECTION_HEADER))) 799 | break; 800 | 801 | std::string strSecRealName{ }; 802 | if (pSecHdr->Name[0] == '/') { //Deprecated, but still used "feature" of section name. 803 | //https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_section_header 804 | //«An 8-byte, null-padded UTF-8 string. There is no terminating null character 805 | //if the string is exactly eight characters long. 806 | //For longer names, this member contains a forward slash (/) followed by an ASCII representation 807 | //of a decimal number that is an offset into the string table.» 808 | //String Table dwells right after the end of Symbol Table. 809 | //Each symbol in Symbol Table occupies exactly 18 bytes. 810 | //So String Table's beginning can be calculated like this: 811 | //FileHeader.PointerToSymbolTable + FileHeader.NumberOfSymbols * 18; 812 | 813 | const auto pStart = reinterpret_cast(&pSecHdr->Name[1]); 814 | char* pEnd{ }; 815 | errno = 0; 816 | const auto lOffset = strtol(pStart, &pEnd, 10); 817 | if (pEnd == pStart || errno == ERANGE) 818 | continue; //Going next section entry. 819 | 820 | const auto lpszSecRealName = reinterpret_cast(GetBaseAddr() 821 | + static_cast(dwSymbolTable) + static_cast(dwNumberOfSymbols) * 18 822 | + static_cast(lOffset)); 823 | if (IsPtrSafe(lpszSecRealName)) 824 | strSecRealName = lpszSecRealName; 825 | } 826 | else { 827 | if (pSecHdr->Name[7] == 0) 828 | strSecRealName.assign((char const*)pSecHdr->Name); 829 | else 830 | strSecRealName.assign((char const*)pSecHdr->Name, 8); 831 | } 832 | 833 | m_vecSecHeaders.emplace_back(PtrToOffset(pSecHdr), *pSecHdr, std::move(strSecRealName)); 834 | } 835 | 836 | if (m_vecSecHeaders.empty()) 837 | return false; 838 | 839 | m_stFileInfo.HasSections = true; 840 | 841 | return true; 842 | } 843 | 844 | bool Clibpe::ParseExport() { 845 | const auto dwExportStartRVA = GetDirEntryRVA(IMAGE_DIRECTORY_ENTRY_EXPORT); 846 | const auto dwExportEndRVA = dwExportStartRVA + GetDirEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT); 847 | const auto pExportDir = static_cast(RVAToPtr(dwExportStartRVA)); 848 | if (pExportDir == nullptr) 849 | return false; 850 | 851 | const auto pdwFuncsRVA = static_cast(RVAToPtr(pExportDir->AddressOfFunctions)); 852 | if (pdwFuncsRVA == nullptr) 853 | return false; 854 | 855 | const auto pwOrdinals = static_cast(RVAToPtr(pExportDir->AddressOfNameOrdinals)); 856 | const auto pdwNamesRVA = static_cast(RVAToPtr(pExportDir->AddressOfNames)); 857 | std::vector vecFuncs; 858 | std::string strModuleName; 859 | 860 | try { 861 | for (size_t iterFuncs = 0; iterFuncs < static_cast(pExportDir->NumberOfFunctions); ++iterFuncs) { 862 | if (!IsPtrSafe(pdwFuncsRVA + iterFuncs)) //Checking pdwFuncsRVA array. 863 | break; 864 | 865 | if (pdwFuncsRVA[iterFuncs]) { //if RVA==0 —> going next entry. 866 | std::string strFuncName; 867 | std::string strForwarderName; 868 | DWORD dwNameRVA{ }; 869 | if (pdwNamesRVA && pwOrdinals) { 870 | for (size_t iterFuncNames = 0; iterFuncNames < static_cast(pExportDir->NumberOfNames); ++iterFuncNames) { 871 | if (!IsPtrSafe(pwOrdinals + iterFuncNames)) //Checking pwOrdinals array. 872 | break; 873 | 874 | if (pwOrdinals[iterFuncNames] == iterFuncs) { //Cycling through ordinals table to get func name. 875 | dwNameRVA = pdwNamesRVA[iterFuncNames]; 876 | const auto pszFuncName = static_cast(RVAToPtr(dwNameRVA)); 877 | //Checking func name for length correctness. 878 | if (pszFuncName && (StringCchLengthA(pszFuncName, MAX_PATH, nullptr) != STRSAFE_E_INVALID_PARAMETER)) { 879 | strFuncName = pszFuncName; 880 | } 881 | break; 882 | } 883 | } 884 | } 885 | 886 | if ((pdwFuncsRVA[iterFuncs] >= dwExportStartRVA) && (pdwFuncsRVA[iterFuncs] <= dwExportEndRVA)) { 887 | const auto pszForwarderName = static_cast(RVAToPtr(pdwFuncsRVA[iterFuncs])); 888 | //Checking forwarder name for length correctness. 889 | if (pszForwarderName && (StringCchLengthA(pszForwarderName, MAX_PATH, nullptr) != STRSAFE_E_INVALID_PARAMETER)) 890 | strForwarderName = pszForwarderName; 891 | } 892 | vecFuncs.emplace_back(pdwFuncsRVA[iterFuncs], static_cast(iterFuncs)/*Ordinal*/, dwNameRVA, 893 | std::move(strFuncName), std::move(strForwarderName)); 894 | } 895 | } 896 | const auto szExportName = static_cast(RVAToPtr(pExportDir->Name)); 897 | //Checking Export name for length correctness. 898 | if (szExportName && (StringCchLengthA(szExportName, MAX_PATH, nullptr) != STRSAFE_E_INVALID_PARAMETER)) 899 | strModuleName = szExportName; 900 | 901 | m_stExport = { PtrToOffset(pExportDir), *pExportDir, std::move(strModuleName) /*Actual IMG name*/, std::move(vecFuncs) }; 902 | } 903 | catch (const std::bad_alloc&) { 904 | m_pEmergencyMemory.reset(); 905 | MessageBoxW(nullptr, L"E_OUTOFMEMORY error while trying to get Export table.\nFile seems to be corrupted.", 906 | L"Error", MB_ICONERROR); 907 | 908 | vecFuncs.clear(); 909 | m_pEmergencyMemory = std::make_unique(0x8FFF); 910 | } 911 | catch (...) { 912 | MessageBoxW(nullptr, L"Unknown exception raised while trying to get Export table.\r\nFile seems to be corrupted.", 913 | L"Error", MB_ICONERROR); 914 | } 915 | 916 | m_stFileInfo.HasExport = true; 917 | 918 | return true; 919 | } 920 | 921 | bool Clibpe::ParseImport() { 922 | auto pImpDesc = static_cast(RVAToPtr(GetDirEntryRVA(IMAGE_DIRECTORY_ENTRY_IMPORT))); 923 | if (pImpDesc == nullptr) 924 | return false; 925 | 926 | try { 927 | //Counter for import modules. If it exceeds iMaxModules we stop parsing file, it's definitely bogus. 928 | //Very unlikely PE file has more than 1000 import modules. 929 | constexpr auto iMaxModules = 1000; 930 | constexpr auto iMaxFuncs = 5000; 931 | int iModulesCount = 0; 932 | 933 | if (m_stFileInfo.IsPE32) { 934 | while (pImpDesc->Name) { 935 | auto pThunk32 = reinterpret_cast(static_cast(pImpDesc->OriginalFirstThunk)); 936 | if (!pThunk32) 937 | pThunk32 = reinterpret_cast(static_cast(pImpDesc->FirstThunk)); 938 | 939 | if (pThunk32) { 940 | pThunk32 = static_cast(RVAToPtr(reinterpret_cast(pThunk32))); 941 | if (!pThunk32) 942 | break; 943 | 944 | std::vector vecFunc{ }; 945 | std::string strDllName{ }; 946 | //Counter for import module funcs, if it exceeds iMaxFuncs we stop parsing import descr, it's definitely bogus. 947 | int iFuncsCount = 0; 948 | 949 | while (pThunk32->u1.AddressOfData) { 950 | PEImportFunction::UNPEIMPORTTHUNK unImpThunk32; 951 | unImpThunk32.Thunk32 = *pThunk32; 952 | IMAGE_IMPORT_BY_NAME stImpByName{ }; 953 | std::string strFuncName{ }; 954 | if (!(pThunk32->u1.Ordinal & IMAGE_ORDINAL_FLAG32)) { 955 | const auto pName = static_cast(RVAToPtr(pThunk32->u1.AddressOfData)); 956 | if (pName && (StringCchLengthA(pName->Name, MAX_PATH, nullptr) != STRSAFE_E_INVALID_PARAMETER)) { 957 | stImpByName = *pName; 958 | strFuncName = pName->Name; 959 | } 960 | } 961 | vecFunc.emplace_back(unImpThunk32, stImpByName, std::move(strFuncName)); 962 | 963 | if (!IsPtrSafe(++pThunk32)) 964 | break; 965 | if (++iFuncsCount == iMaxFuncs) 966 | break; 967 | } 968 | 969 | const auto szName = static_cast(RVAToPtr(pImpDesc->Name)); 970 | if (szName && (StringCchLengthA(szName, MAX_PATH, nullptr) != STRSAFE_E_INVALID_PARAMETER)) 971 | strDllName = szName; 972 | 973 | m_vecImport.emplace_back(PtrToOffset(pImpDesc), *pImpDesc, std::move(strDllName), std::move(vecFunc)); 974 | 975 | if (!IsPtrSafe(++pImpDesc)) 976 | break; 977 | } 978 | else //No IMPORT pointers for that DLL?... 979 | if (!IsPtrSafe(++pImpDesc)) //Going next dll. 980 | break; 981 | 982 | if (++iModulesCount == iMaxModules) 983 | break; 984 | } 985 | } 986 | else if (m_stFileInfo.IsPE64) { 987 | while (pImpDesc->Name) { 988 | auto pThunk64 = reinterpret_cast(static_cast(pImpDesc->OriginalFirstThunk)); 989 | if (!pThunk64) 990 | pThunk64 = reinterpret_cast(static_cast(pImpDesc->FirstThunk)); 991 | 992 | if (pThunk64) { 993 | pThunk64 = static_cast(RVAToPtr(reinterpret_cast(pThunk64))); 994 | if (!pThunk64) 995 | return false; 996 | 997 | std::vector vecFunc{ }; 998 | std::string strDllName{ }; 999 | int iFuncsCount = 0; 1000 | 1001 | while (pThunk64->u1.AddressOfData) { 1002 | PEImportFunction::UNPEIMPORTTHUNK unImpThunk64; 1003 | unImpThunk64.Thunk64 = *pThunk64; 1004 | IMAGE_IMPORT_BY_NAME stImpByName{ }; 1005 | std::string strFuncName{ }; 1006 | if (!(pThunk64->u1.Ordinal & IMAGE_ORDINAL_FLAG32)) { 1007 | const auto pName = static_cast(RVAToPtr(pThunk64->u1.AddressOfData)); 1008 | if (pName && (StringCchLengthA(pName->Name, MAX_PATH, nullptr) != STRSAFE_E_INVALID_PARAMETER)) { 1009 | stImpByName = *pName; 1010 | strFuncName = pName->Name; 1011 | } 1012 | } 1013 | vecFunc.emplace_back(unImpThunk64, stImpByName, std::move(strFuncName)); 1014 | 1015 | pThunk64++; 1016 | if (++iFuncsCount == iMaxFuncs) 1017 | break; 1018 | if (++iFuncsCount == iMaxFuncs) 1019 | break; 1020 | } 1021 | 1022 | const auto szName = static_cast(RVAToPtr(pImpDesc->Name)); 1023 | if (szName && (StringCchLengthA(szName, MAX_PATH, nullptr) != STRSAFE_E_INVALID_PARAMETER)) 1024 | strDllName = szName; 1025 | 1026 | m_vecImport.emplace_back(PtrToOffset(pImpDesc), *pImpDesc, std::move(strDllName), std::move(vecFunc)); 1027 | 1028 | if (!IsPtrSafe(++pImpDesc)) 1029 | break; 1030 | } 1031 | else 1032 | if (!IsPtrSafe(++pImpDesc)) 1033 | break; 1034 | 1035 | if (++iModulesCount == iMaxModules) 1036 | break; 1037 | } 1038 | } 1039 | } 1040 | catch (const std::bad_alloc&) { 1041 | m_pEmergencyMemory.reset(); 1042 | MessageBoxW(nullptr, L"E_OUTOFMEMORY error while trying to get Import table.\r\n" 1043 | L"Too many import entries!\nFile seems to be corrupted.", L"Error", MB_ICONERROR); 1044 | 1045 | m_vecImport.clear(); 1046 | m_pEmergencyMemory = std::make_unique(0x8FFF); 1047 | } 1048 | catch (...) { 1049 | MessageBoxW(nullptr, L"Unknown exception raised while trying to get Import table.\r\nFile seems to be corrupted.", 1050 | L"Error", MB_ICONERROR); 1051 | } 1052 | 1053 | m_stFileInfo.HasImport = true; 1054 | 1055 | return true; 1056 | } 1057 | 1058 | bool Clibpe::ParseResources() { 1059 | const auto pResDirRoot = static_cast(RVAToPtr(GetDirEntryRVA(IMAGE_DIRECTORY_ENTRY_RESOURCE))); 1060 | if (pResDirRoot == nullptr) 1061 | return false; 1062 | 1063 | auto pResDirEntryRoot = reinterpret_cast(pResDirRoot + 1); 1064 | if (!IsPtrSafe(pResDirEntryRoot)) 1065 | return false; 1066 | 1067 | PIMAGE_RESOURCE_DIR_STRING_U pResDirStr; 1068 | 1069 | try { 1070 | const DWORD dwNumOfEntriesRoot = pResDirRoot->NumberOfNamedEntries + pResDirRoot->NumberOfIdEntries; 1071 | if (!IsPtrSafe(pResDirEntryRoot + dwNumOfEntriesRoot)) 1072 | return false; 1073 | 1074 | std::vector vecResDataRoot; 1075 | vecResDataRoot.reserve(dwNumOfEntriesRoot); 1076 | for (unsigned iLvLRoot = 0; iLvLRoot < dwNumOfEntriesRoot; ++iLvLRoot) { 1077 | PIMAGE_RESOURCE_DATA_ENTRY pResDataEntryRoot{ }; 1078 | std::wstring wstrResNameRoot{ }; 1079 | std::vector vecRawResDataRoot{ }; 1080 | PEResLevel2 stResLvL2{ }; 1081 | 1082 | //Name of Resource Type (ICON, BITMAP, MENU, etc...). 1083 | if (pResDirEntryRoot->NameIsString) { 1084 | if (IsSumOverflow(reinterpret_cast(pResDirRoot), static_cast(pResDirEntryRoot->NameOffset))) 1085 | break; 1086 | pResDirStr = reinterpret_cast(reinterpret_cast(pResDirRoot) 1087 | + static_cast(pResDirEntryRoot->NameOffset)); 1088 | if (IsPtrSafe(pResDirStr)) 1089 | //Copy not more then MAX_PATH chars into wstrResNameRoot, avoiding overflow. 1090 | wstrResNameRoot.assign(pResDirStr->NameString, pResDirStr->Length < MAX_PATH ? pResDirStr->Length : MAX_PATH); 1091 | } 1092 | if (pResDirEntryRoot->DataIsDirectory) { 1093 | const auto pResDirLvL2 = reinterpret_cast(reinterpret_cast(pResDirRoot) 1094 | + static_cast(pResDirEntryRoot->OffsetToDirectory)); 1095 | if (!IsPtrSafe(pResDirLvL2)) 1096 | break; 1097 | 1098 | std::vector vecResDataLvL2; 1099 | if (pResDirLvL2 == pResDirRoot) //Resource loop hack 1100 | stResLvL2 = { PtrToOffset(pResDirLvL2), *pResDirLvL2, vecResDataLvL2 }; 1101 | else { 1102 | auto pResDirEntryLvL2 = reinterpret_cast(pResDirLvL2 + 1); 1103 | const DWORD dwNumOfEntriesLvL2 = pResDirLvL2->NumberOfNamedEntries + pResDirLvL2->NumberOfIdEntries; 1104 | if (!IsPtrSafe(pResDirEntryLvL2 + dwNumOfEntriesLvL2)) 1105 | break; 1106 | 1107 | vecResDataLvL2.reserve(dwNumOfEntriesLvL2); 1108 | for (unsigned iLvL2 = 0; iLvL2 < dwNumOfEntriesLvL2; ++iLvL2) { 1109 | PIMAGE_RESOURCE_DATA_ENTRY pResDataEntryLvL2{ }; 1110 | std::wstring wstrResNameLvL2{ }; 1111 | std::vector vecRawResDataLvL2{ }; 1112 | PEResLevel3 stResLvL3{ }; 1113 | 1114 | //Name of resource itself if not presented by ID ("AFX_MY_SUPER_DIALOG"...). 1115 | if (pResDirEntryLvL2->NameIsString) { 1116 | if (IsSumOverflow(reinterpret_cast(pResDirRoot), static_cast(pResDirEntryLvL2->NameOffset))) 1117 | break; 1118 | pResDirStr = reinterpret_cast(reinterpret_cast(pResDirRoot) 1119 | + static_cast(pResDirEntryLvL2->NameOffset)); 1120 | if (IsPtrSafe(pResDirStr)) 1121 | //Copy not more then MAX_PATH chars into wstrResNameLvL2, avoiding overflow. 1122 | wstrResNameLvL2.assign(pResDirStr->NameString, pResDirStr->Length < MAX_PATH ? pResDirStr->Length : MAX_PATH); 1123 | } 1124 | 1125 | if (pResDirEntryLvL2->DataIsDirectory) { 1126 | const auto pResDirLvL3 = reinterpret_cast(reinterpret_cast(pResDirRoot) 1127 | + static_cast(pResDirEntryLvL2->OffsetToDirectory)); 1128 | if (!IsPtrSafe(pResDirLvL3)) 1129 | break; 1130 | 1131 | std::vector vecResDataLvL3; 1132 | if (pResDirLvL3 == pResDirLvL2 || pResDirLvL3 == pResDirRoot) 1133 | stResLvL3 = { PtrToOffset(pResDirLvL3), *pResDirLvL3, vecResDataLvL3 }; 1134 | else { 1135 | auto pResDirEntryLvL3 = reinterpret_cast(pResDirLvL3 + 1); 1136 | const DWORD dwNumOfEntriesLvL3 = pResDirLvL3->NumberOfNamedEntries + pResDirLvL3->NumberOfIdEntries; 1137 | if (!IsPtrSafe(pResDirEntryLvL3 + dwNumOfEntriesLvL3)) 1138 | break; 1139 | 1140 | vecResDataLvL3.reserve(dwNumOfEntriesLvL3); 1141 | for (unsigned iLvL3 = 0; iLvL3 < dwNumOfEntriesLvL3; ++iLvL3) { 1142 | std::wstring wstrResNameLvL3{ }; 1143 | std::vector vecRawResDataLvL3{ }; 1144 | 1145 | if (pResDirEntryLvL3->NameIsString) { 1146 | if (IsSumOverflow(reinterpret_cast(pResDirRoot), static_cast(pResDirEntryLvL3->NameOffset))) 1147 | break; 1148 | pResDirStr = reinterpret_cast 1149 | (reinterpret_cast(pResDirRoot) + static_cast(pResDirEntryLvL3->NameOffset)); 1150 | if (IsPtrSafe(pResDirStr)) 1151 | //Copy not more then MAX_PATH chars into wstrResNameLvL3, avoiding overflow. 1152 | wstrResNameLvL3.assign(pResDirStr->NameString, pResDirStr->Length < MAX_PATH ? pResDirStr->Length : MAX_PATH); 1153 | } 1154 | 1155 | const auto pResDataEntryLvL3 = reinterpret_cast(reinterpret_cast(pResDirRoot) 1156 | + static_cast(pResDirEntryLvL3->OffsetToData)); 1157 | if (IsPtrSafe(pResDataEntryLvL3)) { //Resource LvL 3 RAW Data. 1158 | //IMAGE_RESOURCE_DATA_ENTRY::OffsetToData is actually a general RVA, 1159 | //not an offset from root IMAGE_RESOURCE_DIRECTORY, like IMAGE_RESOURCE_DIRECTORY_ENTRY::OffsetToData. 1160 | 1161 | const auto pThirdResRawDataBegin = static_cast(RVAToPtr(pResDataEntryLvL3->OffsetToData)); 1162 | //Checking RAW Resource data pointer out of bounds. 1163 | if (pThirdResRawDataBegin && IsPtrSafe(reinterpret_cast(pThirdResRawDataBegin) 1164 | + static_cast(pResDataEntryLvL3->Size), true)) { 1165 | vecRawResDataLvL3.assign(pThirdResRawDataBegin, pThirdResRawDataBegin + pResDataEntryLvL3->Size); 1166 | } 1167 | } 1168 | 1169 | vecResDataLvL3.emplace_back(*pResDirEntryLvL3, std::move(wstrResNameLvL3), 1170 | IsPtrSafe(pResDataEntryLvL3) ? *pResDataEntryLvL3 : IMAGE_RESOURCE_DATA_ENTRY{ }, std::move(vecRawResDataLvL3)); 1171 | 1172 | if (!IsPtrSafe(++pResDirEntryLvL3)) 1173 | break; 1174 | } 1175 | stResLvL3 = { PtrToOffset(pResDirLvL3), *pResDirLvL3, std::move(vecResDataLvL3) }; 1176 | } 1177 | } 1178 | else { //////Resource LvL2 RAW Data. 1179 | pResDataEntryLvL2 = reinterpret_cast(reinterpret_cast(pResDirRoot) 1180 | + static_cast(pResDirEntryLvL2->OffsetToData)); 1181 | if (IsPtrSafe(pResDataEntryLvL2)) { 1182 | const auto pSecondResRawDataBegin = static_cast(RVAToPtr(pResDataEntryLvL2->OffsetToData)); 1183 | //Checking RAW Resource data pointer out of bounds. 1184 | if (pSecondResRawDataBegin && IsPtrSafe(reinterpret_cast(pSecondResRawDataBegin) 1185 | + static_cast(pResDataEntryLvL2->Size), true)) { 1186 | vecRawResDataLvL2.assign(pSecondResRawDataBegin, pSecondResRawDataBegin + pResDataEntryLvL2->Size); 1187 | } 1188 | } 1189 | } 1190 | vecResDataLvL2.emplace_back(*pResDirEntryLvL2, std::move(wstrResNameLvL2), 1191 | IsPtrSafe(pResDataEntryLvL2) ? *pResDataEntryLvL2 : IMAGE_RESOURCE_DATA_ENTRY{ }, std::move(vecRawResDataLvL2), stResLvL3); 1192 | 1193 | if (!IsPtrSafe(++pResDirEntryLvL2)) 1194 | break; 1195 | } 1196 | stResLvL2 = { PtrToOffset(pResDirLvL2), *pResDirLvL2, std::move(vecResDataLvL2) }; 1197 | } 1198 | } 1199 | else { //////Resource LvL Root RAW Data. 1200 | pResDataEntryRoot = reinterpret_cast(reinterpret_cast(pResDirRoot) 1201 | + static_cast(pResDirEntryRoot->OffsetToData)); 1202 | if (IsPtrSafe(pResDataEntryRoot)) { 1203 | auto pRootResRawDataBegin = static_cast(RVAToPtr(pResDataEntryRoot->OffsetToData)); 1204 | //Checking RAW Resource data pointer out of bounds. 1205 | if (pRootResRawDataBegin && IsPtrSafe(reinterpret_cast(pRootResRawDataBegin) 1206 | + static_cast(pResDataEntryRoot->Size), true)) { 1207 | vecRawResDataRoot.assign(pRootResRawDataBegin, pRootResRawDataBegin + pResDataEntryRoot->Size); 1208 | } 1209 | } 1210 | } 1211 | vecResDataRoot.emplace_back(*pResDirEntryRoot, std::move(wstrResNameRoot), 1212 | IsPtrSafe(pResDataEntryRoot) ? *pResDataEntryRoot : IMAGE_RESOURCE_DATA_ENTRY{ }, std::move(vecRawResDataRoot), stResLvL2); 1213 | 1214 | if (!IsPtrSafe(++pResDirEntryRoot)) 1215 | break; 1216 | } 1217 | m_stResource = { PtrToOffset(pResDirRoot), *pResDirRoot, std::move(vecResDataRoot) }; 1218 | } 1219 | catch (const std::bad_alloc&) { 1220 | m_pEmergencyMemory.reset(); 1221 | MessageBoxW(nullptr, L"E_OUTOFMEMORY error while trying to get Resource table.\nFile seems to be corrupted.", 1222 | L"Error", MB_ICONERROR); 1223 | 1224 | m_pEmergencyMemory = std::make_unique(0x8FFF); 1225 | } 1226 | catch (...) { 1227 | MessageBoxW(nullptr, L"Unknown exception raised while trying to get Resource table.\r\n\nFile seems to be corrupted.", 1228 | L"Error", MB_ICONERROR); 1229 | } 1230 | 1231 | m_stFileInfo.HasResource = true; 1232 | 1233 | return true; 1234 | } 1235 | 1236 | bool Clibpe::ParseExceptions() { 1237 | //IMAGE_RUNTIME_FUNCTION_ENTRY (without leading underscore) 1238 | //might have different typedef depending on defined platform, see winnt.h 1239 | auto pRuntimeFuncsEntry = static_cast<_PIMAGE_RUNTIME_FUNCTION_ENTRY>(RVAToPtr(GetDirEntryRVA(IMAGE_DIRECTORY_ENTRY_EXCEPTION))); 1240 | if (pRuntimeFuncsEntry == nullptr) 1241 | return false; 1242 | 1243 | const auto dwEntries = GetDirEntrySize(IMAGE_DIRECTORY_ENTRY_EXCEPTION) / static_cast(sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY)); 1244 | if (!dwEntries || !IsPtrSafe(reinterpret_cast(pRuntimeFuncsEntry) + static_cast(dwEntries))) 1245 | return false; 1246 | 1247 | for (unsigned i = 0; i < dwEntries; ++i, ++pRuntimeFuncsEntry) { 1248 | if (!IsPtrSafe(pRuntimeFuncsEntry)) 1249 | break; 1250 | 1251 | m_vecException.emplace_back(PtrToOffset(pRuntimeFuncsEntry), *pRuntimeFuncsEntry); 1252 | } 1253 | 1254 | m_stFileInfo.HasException = true; 1255 | 1256 | return true; 1257 | } 1258 | 1259 | bool Clibpe::ParseSecurity() { 1260 | const auto dwSecurityDirOffset = GetDirEntryRVA(IMAGE_DIRECTORY_ENTRY_SECURITY); 1261 | const auto dwSecurityDirSize = GetDirEntrySize(IMAGE_DIRECTORY_ENTRY_SECURITY); 1262 | if (!dwSecurityDirOffset || !dwSecurityDirSize) 1263 | return false; 1264 | 1265 | //Checks for bogus file offsets that can cause DWORD_PTR overflow. 1266 | if (IsSumOverflow(static_cast(dwSecurityDirOffset), GetBaseAddr())) 1267 | return false; 1268 | 1269 | auto dwSecurityDirStartVA = GetBaseAddr() + static_cast(dwSecurityDirOffset); 1270 | if (IsSumOverflow(dwSecurityDirStartVA, static_cast(dwSecurityDirSize))) 1271 | return false; 1272 | 1273 | const DWORD_PTR dwSecurityDirEndVA = dwSecurityDirStartVA + static_cast(dwSecurityDirSize); 1274 | 1275 | if (!IsPtrSafe(dwSecurityDirStartVA) || !IsPtrSafe(dwSecurityDirEndVA, true)) 1276 | return false; 1277 | 1278 | while (dwSecurityDirStartVA < dwSecurityDirEndVA) { 1279 | auto pCertificate = reinterpret_cast(dwSecurityDirStartVA); 1280 | const auto dwCertSize = pCertificate->dwLength - static_cast(offsetof(WIN_CERTIFICATE, bCertificate)); 1281 | if (!IsPtrSafe(dwSecurityDirStartVA + static_cast(dwCertSize))) 1282 | break; 1283 | 1284 | m_vecSecurity.emplace_back(PtrToOffset(pCertificate), *pCertificate); 1285 | 1286 | //Get next certificate entry, all entries start at 8 aligned address. 1287 | DWORD dwLength = pCertificate->dwLength; 1288 | dwLength += (8 - (dwLength & 7)) & 7; 1289 | dwSecurityDirStartVA = dwSecurityDirStartVA + static_cast(dwLength); 1290 | if (!IsPtrSafe(dwSecurityDirStartVA)) 1291 | break; 1292 | } 1293 | 1294 | m_stFileInfo.HasSecurity = true; 1295 | 1296 | return true; 1297 | } 1298 | 1299 | bool Clibpe::ParseRelocations() { 1300 | auto pBaseRelocDesc = static_cast(RVAToPtr(GetDirEntryRVA(IMAGE_DIRECTORY_ENTRY_BASERELOC))); 1301 | if (pBaseRelocDesc == nullptr) 1302 | return false; 1303 | 1304 | try { 1305 | if (!pBaseRelocDesc->SizeOfBlock || !pBaseRelocDesc->VirtualAddress) 1306 | m_vecRelocs.emplace_back(PtrToOffset(pBaseRelocDesc), *pBaseRelocDesc, std::vector { }); 1307 | 1308 | while ((pBaseRelocDesc->SizeOfBlock) && (pBaseRelocDesc->VirtualAddress)) { 1309 | if (pBaseRelocDesc->SizeOfBlock < sizeof(IMAGE_BASE_RELOCATION)) { 1310 | m_vecRelocs.emplace_back(PtrToOffset(pBaseRelocDesc), *pBaseRelocDesc, std::vector{ }); 1311 | break; 1312 | } 1313 | 1314 | //Amount of Reloc entries. 1315 | DWORD dwNumRelocEntries = (pBaseRelocDesc->SizeOfBlock - static_cast(sizeof(IMAGE_BASE_RELOCATION))) / static_cast(sizeof(WORD)); 1316 | auto pwRelocEntry = reinterpret_cast(reinterpret_cast(pBaseRelocDesc) + sizeof(IMAGE_BASE_RELOCATION)); 1317 | std::vector vecRelocs; 1318 | for (DWORD i = 0; i < dwNumRelocEntries; ++i, ++pwRelocEntry) { 1319 | if (!IsPtrSafe(pwRelocEntry)) 1320 | break; 1321 | //Getting HIGH 4 bits of reloc's entry WORD —> reloc type. 1322 | WORD wRelocType = (*pwRelocEntry & 0xF000) >> 12; 1323 | vecRelocs.emplace_back(PtrToOffset(pwRelocEntry), wRelocType, static_cast((*pwRelocEntry) & 0x0fff)/*Low 12 bits —> Offset*/); 1324 | if (wRelocType == IMAGE_REL_BASED_HIGHADJ) { //The base relocation adds the high 16 bits of the difference to the 16-bit field at offset. 1325 | //The 16-bit field represents the high value of a 32-bit word. 1326 | //The low 16 bits of the 32-bit value are stored in the 16-bit word that follows this base relocation. 1327 | //This means that this base relocation occupies two slots. (MSDN) 1328 | if (!IsPtrSafe(++pwRelocEntry)) { 1329 | vecRelocs.clear(); 1330 | break; 1331 | } 1332 | 1333 | vecRelocs.emplace_back(PtrToOffset(pwRelocEntry), wRelocType, *pwRelocEntry /*The low 16-bit field.*/); 1334 | dwNumRelocEntries--; //to compensate pwRelocEntry++. 1335 | } 1336 | } 1337 | 1338 | m_vecRelocs.emplace_back(PtrToOffset(pBaseRelocDesc), *pBaseRelocDesc, std::move(vecRelocs)); 1339 | 1340 | //Too big (bogus) SizeOfBlock may cause DWORD_PTR overflow. Checking to prevent. 1341 | if (IsSumOverflow(reinterpret_cast(pBaseRelocDesc), static_cast(pBaseRelocDesc->SizeOfBlock))) 1342 | break; 1343 | 1344 | pBaseRelocDesc = reinterpret_cast(reinterpret_cast(pBaseRelocDesc) 1345 | + static_cast(pBaseRelocDesc->SizeOfBlock)); 1346 | if (!IsPtrSafe(pBaseRelocDesc)) 1347 | break; 1348 | } 1349 | } 1350 | catch (const std::bad_alloc&) { 1351 | m_pEmergencyMemory.reset(); 1352 | MessageBoxW(nullptr, L"E_OUTOFMEMORY error while trying to get Relocation table.\nFile seems to be corrupted.", 1353 | L"Error", MB_ICONERROR); 1354 | 1355 | m_pEmergencyMemory = std::make_unique(0x8FFF); 1356 | } 1357 | catch (...) { 1358 | MessageBoxW(nullptr, L"Unknown exception raised while trying to get Relocation table.\nFile seems to be corrupted.", 1359 | L"Error", MB_ICONERROR); 1360 | } 1361 | 1362 | m_stFileInfo.HasReloc = true; 1363 | 1364 | return true; 1365 | } 1366 | 1367 | bool Clibpe::ParseDebug() { 1368 | const auto dwDebugDirRVA = GetDirEntryRVA(IMAGE_DIRECTORY_ENTRY_DEBUG); 1369 | if (!dwDebugDirRVA) 1370 | return false; 1371 | 1372 | PIMAGE_DEBUG_DIRECTORY pDebugDir; 1373 | DWORD dwDebugDirSize; 1374 | PIMAGE_SECTION_HEADER pDebugSecHdr = GetSecHdrFromName(".debug"); 1375 | if (pDebugSecHdr && (pDebugSecHdr->VirtualAddress == dwDebugDirRVA)) { 1376 | pDebugDir = reinterpret_cast(GetBaseAddr() + static_cast(pDebugSecHdr->PointerToRawData)); 1377 | dwDebugDirSize = GetDirEntrySize(IMAGE_DIRECTORY_ENTRY_DEBUG) * static_cast(sizeof(IMAGE_DEBUG_DIRECTORY)); 1378 | } 1379 | else //Looking for the debug directory. 1380 | { 1381 | if (pDebugSecHdr = GetSecHdrFromRVA(dwDebugDirRVA); pDebugSecHdr == nullptr) 1382 | return false; 1383 | 1384 | if (pDebugDir = static_cast(RVAToPtr(dwDebugDirRVA)); pDebugDir == nullptr) 1385 | return false; 1386 | 1387 | dwDebugDirSize = GetDirEntrySize(IMAGE_DIRECTORY_ENTRY_DEBUG); 1388 | } 1389 | 1390 | const DWORD dwDebugEntries = dwDebugDirSize / static_cast(sizeof(IMAGE_DEBUG_DIRECTORY)); 1391 | 1392 | if (!dwDebugEntries || IsSumOverflow(reinterpret_cast(pDebugDir), static_cast(dwDebugDirSize)) || 1393 | !IsPtrSafe(reinterpret_cast(pDebugDir) + static_cast(dwDebugDirSize))) 1394 | return false; 1395 | 1396 | try { 1397 | for (unsigned i = 0; i < dwDebugEntries; ++i) { 1398 | PEDebugHeader stDbgHdr; 1399 | for (unsigned iterDbgHdr = 0; iterDbgHdr < (sizeof(PEDebugHeader::Header) / sizeof(DWORD)); iterDbgHdr++) { 1400 | stDbgHdr.Header[iterDbgHdr] = GetTData(static_cast(pDebugDir->PointerToRawData) + (sizeof(DWORD) * iterDbgHdr)); 1401 | } 1402 | 1403 | if (pDebugDir->Type == IMAGE_DEBUG_TYPE_CODEVIEW) { 1404 | DWORD dwOffset = 0; 1405 | if (stDbgHdr.Header[0] == 0x53445352) //"RSDS" 1406 | dwOffset = sizeof(DWORD) * 6; 1407 | else if (stDbgHdr.Header[0] == 0x3031424E) //"NB10" 1408 | dwOffset = sizeof(DWORD) * 4; 1409 | 1410 | std::string strPDBName; 1411 | if (dwOffset > 0) 1412 | for (unsigned iterStr = 0; iterStr < MAX_PATH; iterStr++) { 1413 | const auto byte = GetTData(pDebugDir->PointerToRawData + dwOffset + iterStr); 1414 | if (byte == 0) //End of string. 1415 | break; 1416 | strPDBName += byte; 1417 | } 1418 | stDbgHdr.PDBName = std::move(strPDBName); 1419 | } 1420 | 1421 | m_vecDebug.emplace_back(PtrToOffset(pDebugDir), *pDebugDir, stDbgHdr); 1422 | if (!IsPtrSafe(++pDebugDir)) 1423 | break; 1424 | } 1425 | 1426 | m_stFileInfo.HasDebug = true; 1427 | } 1428 | catch (const std::bad_alloc&) { 1429 | m_pEmergencyMemory.reset(); 1430 | MessageBoxW(nullptr, L"E_OUTOFMEMORY error while trying to get Debug info.\r\n" 1431 | L"File seems to be corrupted.", L"Error", MB_ICONERROR); 1432 | 1433 | m_pEmergencyMemory = std::make_unique(0x8FFF); 1434 | } 1435 | 1436 | return true; 1437 | } 1438 | 1439 | bool Clibpe::ParseArchitecture() { 1440 | const auto dwArchDirRVA = GetDirEntryRVA(IMAGE_DIRECTORY_ENTRY_ARCHITECTURE); 1441 | if (!dwArchDirRVA) 1442 | return false; 1443 | 1444 | const auto pArchEntry = static_cast(RVAToPtr(dwArchDirRVA)); 1445 | if (!pArchEntry) 1446 | return false; 1447 | 1448 | m_stFileInfo.HasArchitect = true; 1449 | 1450 | return true; 1451 | } 1452 | 1453 | bool Clibpe::ParseGlobalPtr() { 1454 | const auto dwGlobalPTRDirRVA = reinterpret_cast(RVAToPtr(GetDirEntryRVA(IMAGE_DIRECTORY_ENTRY_GLOBALPTR))); 1455 | if (!dwGlobalPTRDirRVA) 1456 | return false; 1457 | 1458 | m_stFileInfo.HasGlobalPtr = true; 1459 | 1460 | return true; 1461 | } 1462 | 1463 | bool Clibpe::ParseTLS() { 1464 | const auto dwTLSDirRVA = GetDirEntryRVA(IMAGE_DIRECTORY_ENTRY_TLS); 1465 | if (!dwTLSDirRVA) 1466 | return false; 1467 | 1468 | try { 1469 | std::vector vecTLSCallbacks; 1470 | ULONGLONG ullStartAddressOfRawData{ }; 1471 | ULONGLONG ullEndAddressOfRawData{ }; 1472 | ULONGLONG ullAddressOfCallBacks{ }; 1473 | PETLS::Tls varTLSDir; 1474 | PDWORD pdwTLSPtr; 1475 | 1476 | if (m_stFileInfo.IsPE32) { 1477 | const auto pTLSDir32 = static_cast(RVAToPtr(dwTLSDirRVA)); 1478 | if (!pTLSDir32) 1479 | return false; 1480 | 1481 | varTLSDir.TLSDir32 = *pTLSDir32; 1482 | pdwTLSPtr = reinterpret_cast(pTLSDir32); 1483 | ullStartAddressOfRawData = pTLSDir32->StartAddressOfRawData; 1484 | ullEndAddressOfRawData = pTLSDir32->EndAddressOfRawData; 1485 | ullAddressOfCallBacks = pTLSDir32->AddressOfCallBacks; 1486 | } 1487 | else if (m_stFileInfo.IsPE64) { 1488 | const auto pTLSDir64 = static_cast(RVAToPtr(dwTLSDirRVA)); 1489 | if (!pTLSDir64) 1490 | return false; 1491 | 1492 | varTLSDir.TLSDir64 = *pTLSDir64; 1493 | pdwTLSPtr = reinterpret_cast(pTLSDir64); 1494 | ullStartAddressOfRawData = pTLSDir64->StartAddressOfRawData; 1495 | ullEndAddressOfRawData = pTLSDir64->EndAddressOfRawData; 1496 | ullAddressOfCallBacks = pTLSDir64->AddressOfCallBacks; 1497 | } 1498 | else 1499 | return false; 1500 | 1501 | auto pTLSCallbacks = static_cast(RVAToPtr(ullAddressOfCallBacks - GetImageBase())); 1502 | if (pTLSCallbacks) { 1503 | while (*pTLSCallbacks) { 1504 | vecTLSCallbacks.push_back(*pTLSCallbacks); 1505 | if (!IsPtrSafe(++pTLSCallbacks)) { 1506 | vecTLSCallbacks.clear(); 1507 | break; 1508 | } 1509 | } 1510 | } 1511 | 1512 | m_stTLS = PETLS{ PtrToOffset(pdwTLSPtr), varTLSDir, std::move(vecTLSCallbacks) }; 1513 | m_stFileInfo.HasTLS = true; 1514 | } 1515 | catch (const std::bad_alloc&) { 1516 | m_pEmergencyMemory.reset(); 1517 | MessageBoxW(nullptr, L"E_OUTOFMEMORY error while trying to get TLS table.\r\n" 1518 | L"File seems to be corrupted.", L"Error", MB_ICONERROR); 1519 | 1520 | m_pEmergencyMemory = std::make_unique(0x8FFF); 1521 | } 1522 | catch (...) { 1523 | MessageBoxW(nullptr, L"Unknown exception raised while trying to get TLS table.\r\nFile seems to be corrupted.", 1524 | L"Error", MB_ICONERROR); 1525 | } 1526 | 1527 | return true; 1528 | } 1529 | 1530 | bool Clibpe::ParseLCD() { 1531 | if (m_stFileInfo.IsPE32) { 1532 | const auto pLCD32 = static_cast(RVAToPtr(GetDirEntryRVA(IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG))); 1533 | if (!pLCD32 || !IsPtrSafe(reinterpret_cast(pLCD32) + sizeof(IMAGE_LOAD_CONFIG_DIRECTORY32))) 1534 | return false; 1535 | 1536 | m_stLCD.dwOffset = PtrToOffset(pLCD32); 1537 | m_stLCD.LCD32 = *pLCD32; 1538 | } 1539 | else if (m_stFileInfo.IsPE64) { 1540 | const auto pLCD64 = static_cast(RVAToPtr(GetDirEntryRVA(IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG))); 1541 | if (!pLCD64 || !IsPtrSafe(reinterpret_cast(pLCD64) + sizeof(PIMAGE_LOAD_CONFIG_DIRECTORY64))) 1542 | return false; 1543 | 1544 | m_stLCD.dwOffset = PtrToOffset(pLCD64); 1545 | m_stLCD.LCD64 = *pLCD64; 1546 | } 1547 | else 1548 | return false; 1549 | 1550 | m_stFileInfo.HasLoadCFG = true; 1551 | 1552 | return true; 1553 | } 1554 | 1555 | bool Clibpe::ParseBoundImport() { 1556 | auto pBoundImpDesc = static_cast(RVAToPtr(GetDirEntryRVA(IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT))); 1557 | if (pBoundImpDesc == nullptr) 1558 | return false; 1559 | 1560 | while (pBoundImpDesc->TimeDateStamp) { 1561 | std::string strModuleName; 1562 | std::vector vecBoundForwarders; 1563 | 1564 | auto pBoundImpForwarder = reinterpret_cast(pBoundImpDesc + 1); 1565 | if (!IsPtrSafe(pBoundImpForwarder)) 1566 | break; 1567 | 1568 | for (unsigned i = 0; i < pBoundImpDesc->NumberOfModuleForwarderRefs; ++i) { 1569 | std::string strForwarderModuleName{ }; 1570 | 1571 | const auto szName = reinterpret_cast(reinterpret_cast(pBoundImpDesc) + pBoundImpForwarder->OffsetModuleName); 1572 | if (IsPtrSafe(szName)) 1573 | if (szName && (StringCchLengthA(szName, MAX_PATH, nullptr) != STRSAFE_E_INVALID_PARAMETER)) 1574 | strForwarderModuleName = szName; 1575 | 1576 | vecBoundForwarders.emplace_back(PtrToOffset(pBoundImpForwarder), *pBoundImpForwarder, std::move(strForwarderModuleName)); 1577 | 1578 | if (!IsPtrSafe(++pBoundImpForwarder)) 1579 | break; 1580 | 1581 | pBoundImpDesc = reinterpret_cast(reinterpret_cast(pBoundImpDesc) + sizeof(IMAGE_BOUND_FORWARDER_REF)); 1582 | if (!IsPtrSafe(pBoundImpDesc)) 1583 | break; 1584 | } 1585 | 1586 | const auto szName = reinterpret_cast(reinterpret_cast(pBoundImpDesc) + pBoundImpDesc->OffsetModuleName); 1587 | if (IsPtrSafe(szName)) 1588 | if (StringCchLengthA(szName, MAX_PATH, nullptr) != STRSAFE_E_INVALID_PARAMETER) 1589 | strModuleName = szName; 1590 | 1591 | m_vecBoundImp.emplace_back(PtrToOffset(pBoundImpDesc), *pBoundImpDesc, std::move(strModuleName), std::move(vecBoundForwarders)); 1592 | 1593 | if (!IsPtrSafe(++pBoundImpDesc)) 1594 | break; 1595 | } 1596 | 1597 | m_stFileInfo.HasBoundImp = true; 1598 | 1599 | return true; 1600 | } 1601 | 1602 | bool Clibpe::ParseIAT() { 1603 | const auto dwIATDirRVA = reinterpret_cast(RVAToPtr(GetDirEntryRVA(IMAGE_DIRECTORY_ENTRY_IAT))); 1604 | if (!dwIATDirRVA) 1605 | return false; 1606 | 1607 | m_stFileInfo.HasIAT = true; 1608 | 1609 | return true; 1610 | } 1611 | 1612 | bool Clibpe::ParseDelayImport() { 1613 | auto pDelayImpDescr = static_cast(RVAToPtr(GetDirEntryRVA(IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT))); 1614 | if (pDelayImpDescr == nullptr) 1615 | return false; 1616 | 1617 | if (m_stFileInfo.IsPE32) { 1618 | while (pDelayImpDescr->DllNameRVA) { 1619 | auto pThunk32Name = reinterpret_cast(static_cast(pDelayImpDescr->ImportNameTableRVA)); 1620 | 1621 | if (!pThunk32Name) { 1622 | if (!IsPtrSafe(++pDelayImpDescr)) 1623 | break; 1624 | } 1625 | else { 1626 | std::string strDllName; 1627 | std::vector vecFunc; 1628 | 1629 | pThunk32Name = static_cast(RVAToPtr(reinterpret_cast(pThunk32Name))); 1630 | auto pThunk32IAT = static_cast(RVAToPtr(pDelayImpDescr->ImportAddressTableRVA)); 1631 | auto pThunk32BoundIAT = static_cast(RVAToPtr(pDelayImpDescr->BoundImportAddressTableRVA)); 1632 | auto pThunk32UnloadInfoTable = static_cast(RVAToPtr(pDelayImpDescr->UnloadInformationTableRVA)); 1633 | 1634 | if (!pThunk32Name) 1635 | break; 1636 | 1637 | while (pThunk32Name->u1.AddressOfData) { 1638 | PEDelayImportFunc::PEDelayImportThunk unDelayImpThunk32{ }; 1639 | unDelayImpThunk32.st32.ImportAddressTable = *pThunk32Name; 1640 | unDelayImpThunk32.st32.ImportNameTable = pThunk32IAT ? *pThunk32IAT : IMAGE_THUNK_DATA32{ }; 1641 | unDelayImpThunk32.st32.BoundImportAddressTable = pThunk32BoundIAT ? *pThunk32BoundIAT : IMAGE_THUNK_DATA32{ }; 1642 | unDelayImpThunk32.st32.UnloadInformationTable = pThunk32UnloadInfoTable ? *pThunk32UnloadInfoTable : IMAGE_THUNK_DATA32{ }; 1643 | 1644 | std::string strFuncName{ }; 1645 | IMAGE_IMPORT_BY_NAME stImpByName{ }; 1646 | if (!(pThunk32Name->u1.Ordinal & IMAGE_ORDINAL_FLAG32)) { 1647 | const auto pName = static_cast(RVAToPtr(pThunk32Name->u1.AddressOfData)); 1648 | if (pName && (StringCchLengthA(pName->Name, MAX_PATH, nullptr) != STRSAFE_E_INVALID_PARAMETER)) { 1649 | stImpByName = *pName; 1650 | strFuncName = pName->Name; 1651 | } 1652 | } 1653 | vecFunc.emplace_back(unDelayImpThunk32, stImpByName, std::move(strFuncName)); 1654 | 1655 | if (!IsPtrSafe(++pThunk32Name)) 1656 | break; 1657 | if (pThunk32IAT) 1658 | if (!IsPtrSafe(++pThunk32IAT)) 1659 | break; 1660 | if (pThunk32BoundIAT) 1661 | if (!IsPtrSafe(++pThunk32BoundIAT)) 1662 | break; 1663 | if (pThunk32UnloadInfoTable) 1664 | if (!IsPtrSafe(++pThunk32UnloadInfoTable)) 1665 | break; 1666 | } 1667 | 1668 | const auto szName = static_cast(RVAToPtr(pDelayImpDescr->DllNameRVA)); 1669 | if (szName && (StringCchLengthA(szName, MAX_PATH, nullptr) != STRSAFE_E_INVALID_PARAMETER)) 1670 | strDllName = szName; 1671 | 1672 | m_vecDelayImp.emplace_back(PtrToOffset(pDelayImpDescr), *pDelayImpDescr, std::move(strDllName), std::move(vecFunc)); 1673 | 1674 | if (!IsPtrSafe(++pDelayImpDescr)) 1675 | break; 1676 | } 1677 | } 1678 | } 1679 | else if (m_stFileInfo.IsPE64) { 1680 | while (pDelayImpDescr->DllNameRVA) { 1681 | auto pThunk64Name = reinterpret_cast(static_cast(pDelayImpDescr->ImportNameTableRVA)); 1682 | 1683 | if (!pThunk64Name) { 1684 | if (!IsPtrSafe(++pDelayImpDescr)) 1685 | break; 1686 | } 1687 | else { 1688 | std::string strDllName; 1689 | std::vector vecFunc; 1690 | 1691 | pThunk64Name = static_cast(RVAToPtr(reinterpret_cast(pThunk64Name))); 1692 | auto pThunk64IAT = static_cast(RVAToPtr(pDelayImpDescr->ImportAddressTableRVA)); 1693 | auto pThunk64BoundIAT = static_cast(RVAToPtr(pDelayImpDescr->BoundImportAddressTableRVA)); 1694 | auto pThunk64UnloadInfoTable = static_cast(RVAToPtr(pDelayImpDescr->UnloadInformationTableRVA)); 1695 | 1696 | if (!pThunk64Name) 1697 | break; 1698 | 1699 | while (pThunk64Name->u1.AddressOfData) { 1700 | PEDelayImportFunc::PEDelayImportThunk unDelayImpThunk64{ }; 1701 | unDelayImpThunk64.st64.ImportAddressTable = *pThunk64Name; 1702 | unDelayImpThunk64.st64.ImportNameTable = pThunk64IAT ? *pThunk64IAT : IMAGE_THUNK_DATA64{ }; 1703 | unDelayImpThunk64.st64.BoundImportAddressTable = pThunk64BoundIAT ? *pThunk64BoundIAT : IMAGE_THUNK_DATA64{ }; 1704 | unDelayImpThunk64.st64.UnloadInformationTable = pThunk64UnloadInfoTable ? *pThunk64UnloadInfoTable : IMAGE_THUNK_DATA64{ }; 1705 | 1706 | std::string strFuncName{ }; 1707 | IMAGE_IMPORT_BY_NAME stImpByName{ }; 1708 | if (!(pThunk64Name->u1.Ordinal & IMAGE_ORDINAL_FLAG64)) { 1709 | const auto pName = static_cast(RVAToPtr(pThunk64Name->u1.AddressOfData)); 1710 | if (pName && (StringCchLengthA(pName->Name, MAX_PATH, nullptr) != STRSAFE_E_INVALID_PARAMETER)) { 1711 | stImpByName = *pName; 1712 | strFuncName = pName->Name; 1713 | } 1714 | } 1715 | vecFunc.emplace_back(unDelayImpThunk64, stImpByName, std::move(strFuncName)); 1716 | 1717 | if (!IsPtrSafe(++pThunk64Name)) 1718 | break; 1719 | if (pThunk64IAT) 1720 | if (!IsPtrSafe(++pThunk64IAT)) 1721 | break; 1722 | if (pThunk64BoundIAT) 1723 | if (!IsPtrSafe(++pThunk64BoundIAT)) 1724 | break; 1725 | if (pThunk64UnloadInfoTable) 1726 | if (!IsPtrSafe(++pThunk64UnloadInfoTable)) 1727 | break; 1728 | } 1729 | 1730 | const auto szName = static_cast(RVAToPtr(pDelayImpDescr->DllNameRVA)); 1731 | if (szName && (StringCchLengthA(szName, MAX_PATH, nullptr) != STRSAFE_E_INVALID_PARAMETER)) 1732 | strDllName = szName; 1733 | 1734 | m_vecDelayImp.emplace_back(PtrToOffset(pDelayImpDescr), *pDelayImpDescr, std::move(strDllName), std::move(vecFunc)); 1735 | 1736 | if (!IsPtrSafe(++pDelayImpDescr)) 1737 | break; 1738 | } 1739 | } 1740 | } 1741 | 1742 | m_stFileInfo.HasDelayImp = true; 1743 | 1744 | return true; 1745 | } 1746 | 1747 | bool Clibpe::ParseCOMDescriptor() { 1748 | const auto pCOMDescHeader = static_cast(RVAToPtr(GetDirEntryRVA(IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR))); 1749 | if (pCOMDescHeader == nullptr) 1750 | return false; 1751 | 1752 | m_stCOR20Desc = { PtrToOffset(pCOMDescHeader), *pCOMDescHeader }; 1753 | m_stFileInfo.HasCOMDescr = true; 1754 | 1755 | return true; 1756 | } 1757 | } -------------------------------------------------------------------------------- /PECore/libpe.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | * Copyright © 2018-2022, Jovibor: https://github.com/jovibor/ * 3 | * libpe is a library for obtaining PE32 (x86) and PE32+ (x64) files' inner structure. * 4 | * Official git repository: https://github.com/jovibor/libpe * 5 | * This software is available under the "MIT License". * 6 | ****************************************************************************************/ 7 | #pragma once 8 | #include 9 | #include //WIN_CERTIFICATE struct. 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #ifdef COMIMAGE_FLAGS_32BITPREFERRED 17 | #undef COMIMAGE_FLAGS_32BITPREFERRED 18 | #endif 19 | 20 | #ifndef __cpp_lib_span 21 | static_assert(false, "C++20 compiler is required for libpe, MSVS 16.11.14 or higher."); 22 | #endif 23 | 24 | namespace libpe 25 | { 26 | //Rich. 27 | struct PERichHeader { 28 | DWORD dwOffset; //File's raw offset of this entry. 29 | WORD wId; //Entry Id. 30 | WORD wVersion; //Entry version. 31 | DWORD dwCount; //Amount of occurrences. 32 | }; 33 | using PERICHHDR_VEC = std::vector; 34 | 35 | //NT header. 36 | struct PENtHeader { 37 | DWORD dwOffset; //File's raw offset of this header. 38 | union { //Union of either x86 or x64 NT header. 39 | IMAGE_NT_HEADERS32 NTHdr32; //x86 Header. 40 | IMAGE_NT_HEADERS64 NTHdr64; //x64 Header. 41 | }; 42 | }; 43 | inline const std::unordered_map MapFileHdrMachine { 44 | { IMAGE_FILE_MACHINE_UNKNOWN, L"IMAGE_FILE_MACHINE_UNKNOWN" }, 45 | { IMAGE_FILE_MACHINE_TARGET_HOST, L"IMAGE_FILE_MACHINE_TARGET_HOST" }, 46 | { IMAGE_FILE_MACHINE_I386, L"IMAGE_FILE_MACHINE_I386" }, 47 | { IMAGE_FILE_MACHINE_R3000, L"IMAGE_FILE_MACHINE_R3000" }, 48 | { IMAGE_FILE_MACHINE_R4000, L"IMAGE_FILE_MACHINE_R4000" }, 49 | { IMAGE_FILE_MACHINE_R10000, L"IMAGE_FILE_MACHINE_R10000" }, 50 | { IMAGE_FILE_MACHINE_WCEMIPSV2, L"IMAGE_FILE_MACHINE_WCEMIPSV2" }, 51 | { IMAGE_FILE_MACHINE_ALPHA, L"IMAGE_FILE_MACHINE_ALPHA" }, 52 | { IMAGE_FILE_MACHINE_SH3, L"IMAGE_FILE_MACHINE_SH3" }, 53 | { IMAGE_FILE_MACHINE_SH3DSP, L"IMAGE_FILE_MACHINE_SH3DSP" }, 54 | { IMAGE_FILE_MACHINE_SH3E, L"IMAGE_FILE_MACHINE_SH3E" }, 55 | { IMAGE_FILE_MACHINE_SH4, L"IMAGE_FILE_MACHINE_SH4" }, 56 | { IMAGE_FILE_MACHINE_SH5, L"IMAGE_FILE_MACHINE_SH5" }, 57 | { IMAGE_FILE_MACHINE_ARM, L"IMAGE_FILE_MACHINE_ARM" }, 58 | { IMAGE_FILE_MACHINE_THUMB, L"IMAGE_FILE_MACHINE_THUMB" }, 59 | { IMAGE_FILE_MACHINE_ARMNT, L"IMAGE_FILE_MACHINE_ARMNT" }, 60 | { IMAGE_FILE_MACHINE_AM33, L"IMAGE_FILE_MACHINE_AM33" }, 61 | { IMAGE_FILE_MACHINE_POWERPC, L"IMAGE_FILE_MACHINE_POWERPC" }, 62 | { IMAGE_FILE_MACHINE_POWERPCFP, L"IMAGE_FILE_MACHINE_POWERPCFP" }, 63 | { IMAGE_FILE_MACHINE_IA64, L"IMAGE_FILE_MACHINE_IA64" }, 64 | { IMAGE_FILE_MACHINE_MIPS16, L"IMAGE_FILE_MACHINE_MIPS16" }, 65 | { IMAGE_FILE_MACHINE_ALPHA64, L"IMAGE_FILE_MACHINE_ALPHA64" }, 66 | { IMAGE_FILE_MACHINE_MIPSFPU, L"IMAGE_FILE_MACHINE_MIPSFPU" }, 67 | { IMAGE_FILE_MACHINE_MIPSFPU16, L"IMAGE_FILE_MACHINE_MIPSFPU16" }, 68 | { IMAGE_FILE_MACHINE_TRICORE, L"IMAGE_FILE_MACHINE_TRICORE" }, 69 | { IMAGE_FILE_MACHINE_CEF, L"IMAGE_FILE_MACHINE_CEF" }, 70 | { IMAGE_FILE_MACHINE_EBC, L"IMAGE_FILE_MACHINE_EBC" }, 71 | { IMAGE_FILE_MACHINE_AMD64, L"IMAGE_FILE_MACHINE_AMD64" }, 72 | { IMAGE_FILE_MACHINE_M32R, L"IMAGE_FILE_MACHINE_M32R" }, 73 | { IMAGE_FILE_MACHINE_ARM64, L"IMAGE_FILE_MACHINE_ARM64" }, 74 | { IMAGE_FILE_MACHINE_CEE, L"IMAGE_FILE_MACHINE_CEE" }, 75 | }; 76 | inline const std::unordered_map MapFileHdrCharact { 77 | { IMAGE_FILE_RELOCS_STRIPPED, L"IMAGE_FILE_RELOCS_STRIPPED" }, 78 | { IMAGE_FILE_EXECUTABLE_IMAGE, L"IMAGE_FILE_EXECUTABLE_IMAGE" }, 79 | { IMAGE_FILE_LINE_NUMS_STRIPPED, L"IMAGE_FILE_LINE_NUMS_STRIPPED" }, 80 | { IMAGE_FILE_LOCAL_SYMS_STRIPPED, L"IMAGE_FILE_LOCAL_SYMS_STRIPPED" }, 81 | { IMAGE_FILE_AGGRESIVE_WS_TRIM, L"IMAGE_FILE_AGGRESIVE_WS_TRIM" }, 82 | { IMAGE_FILE_LARGE_ADDRESS_AWARE, L"IMAGE_FILE_LARGE_ADDRESS_AWARE" }, 83 | { IMAGE_FILE_BYTES_REVERSED_LO, L"IMAGE_FILE_BYTES_REVERSED_LO" }, 84 | { IMAGE_FILE_32BIT_MACHINE, L"IMAGE_FILE_32BIT_MACHINE" }, 85 | { IMAGE_FILE_DEBUG_STRIPPED, L"IMAGE_FILE_DEBUG_STRIPPED" }, 86 | { IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP, L"IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP" }, 87 | { IMAGE_FILE_NET_RUN_FROM_SWAP, L"IMAGE_FILE_NET_RUN_FROM_SWAP" }, 88 | { IMAGE_FILE_SYSTEM, L"IMAGE_FILE_SYSTEM" }, 89 | { IMAGE_FILE_DLL, L"IMAGE_FILE_DLL" }, 90 | { IMAGE_FILE_UP_SYSTEM_ONLY, L"IMAGE_FILE_UP_SYSTEM_ONLY" }, 91 | { IMAGE_FILE_BYTES_REVERSED_HI, L"IMAGE_FILE_BYTES_REVERSED_HI" } 92 | }; 93 | inline const std::unordered_map MapOptHdrMagic { 94 | { IMAGE_NT_OPTIONAL_HDR32_MAGIC, L"IMAGE_NT_OPTIONAL_HDR32_MAGIC" }, 95 | { IMAGE_NT_OPTIONAL_HDR64_MAGIC, L"IMAGE_NT_OPTIONAL_HDR64_MAGIC" }, 96 | { IMAGE_ROM_OPTIONAL_HDR_MAGIC, L"IMAGE_ROM_OPTIONAL_HDR_MAGIC" } 97 | }; 98 | inline const std::unordered_map MapOptHdrSubsystem { 99 | { IMAGE_SUBSYSTEM_UNKNOWN, L"IMAGE_SUBSYSTEM_UNKNOWN" }, 100 | { IMAGE_SUBSYSTEM_NATIVE, L"IMAGE_SUBSYSTEM_NATIVE" }, 101 | { IMAGE_SUBSYSTEM_WINDOWS_GUI, L"IMAGE_SUBSYSTEM_WINDOWS_GUI" }, 102 | { IMAGE_SUBSYSTEM_WINDOWS_CUI, L"IMAGE_SUBSYSTEM_WINDOWS_CUI" }, 103 | { IMAGE_SUBSYSTEM_OS2_CUI, L"IMAGE_SUBSYSTEM_OS2_CUI" }, 104 | { IMAGE_SUBSYSTEM_POSIX_CUI, L"IMAGE_SUBSYSTEM_POSIX_CUI" }, 105 | { IMAGE_SUBSYSTEM_NATIVE_WINDOWS, L"IMAGE_SUBSYSTEM_NATIVE_WINDOWS" }, 106 | { IMAGE_SUBSYSTEM_WINDOWS_CE_GUI, L"IMAGE_SUBSYSTEM_WINDOWS_CE_GUI" }, 107 | { IMAGE_SUBSYSTEM_EFI_APPLICATION, L"IMAGE_SUBSYSTEM_EFI_APPLICATION" }, 108 | { IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, L"IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER" }, 109 | { IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER, L"IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER" }, 110 | { IMAGE_SUBSYSTEM_EFI_ROM, L"IMAGE_SUBSYSTEM_EFI_ROM" }, 111 | { IMAGE_SUBSYSTEM_XBOX, L"IMAGE_SUBSYSTEM_XBOX" }, 112 | { IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION, L"IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION" }, 113 | { IMAGE_SUBSYSTEM_XBOX_CODE_CATALOG, L"IMAGE_SUBSYSTEM_XBOX_CODE_CATALOG" } 114 | }; 115 | inline const std::unordered_map MapOptHdrDllCharact { 116 | { 0x0001, L"IMAGE_LIBRARY_PROCESS_INIT" }, 117 | { 0x0002, L"IMAGE_LIBRARY_PROCESS_TERM" }, 118 | { 0x0004, L"IMAGE_LIBRARY_THREAD_INIT" }, 119 | { 0x0008, L"IMAGE_LIBRARY_THREAD_TERM" }, 120 | { IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA, L"IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA" }, 121 | { IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE, L"IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE" }, 122 | { IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY, L"IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY" }, 123 | { IMAGE_DLLCHARACTERISTICS_NX_COMPAT, L"IMAGE_DLLCHARACTERISTICS_NX_COMPAT" }, 124 | { IMAGE_DLLCHARACTERISTICS_NO_ISOLATION, L"IMAGE_DLLCHARACTERISTICS_NO_ISOLATION" }, 125 | { IMAGE_DLLCHARACTERISTICS_NO_SEH, L"IMAGE_DLLCHARACTERISTICS_NO_SEH" }, 126 | { IMAGE_DLLCHARACTERISTICS_NO_BIND, L"IMAGE_DLLCHARACTERISTICS_NO_BIND" }, 127 | { IMAGE_DLLCHARACTERISTICS_APPCONTAINER, L"IMAGE_DLLCHARACTERISTICS_APPCONTAINER" }, 128 | { IMAGE_DLLCHARACTERISTICS_WDM_DRIVER, L"IMAGE_DLLCHARACTERISTICS_WDM_DRIVER" }, 129 | { IMAGE_DLLCHARACTERISTICS_GUARD_CF, L"IMAGE_DLLCHARACTERISTICS_GUARD_CF" }, 130 | { IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE, L"IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE" } 131 | }; 132 | 133 | //Data directories. 134 | struct PEDataDirectory { 135 | IMAGE_DATA_DIRECTORY DataDir; //Standard header. 136 | std::string Section; //Name of the section this directory resides in (points to). 137 | }; 138 | using PEDATADIR_VEC = std::vector; 139 | 140 | //Sections headers. 141 | //For more info check: 142 | //docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_image_section_header#members 143 | //«An 8-byte, null-padded UTF-8 string. For longer names, this member contains a forward slash (/) 144 | //followed by an ASCII representation of a decimal number that is an offset into the string table.» 145 | struct PESectionHeader { 146 | DWORD Offset; //File's raw offset of this section header descriptor. 147 | IMAGE_SECTION_HEADER SecHdr; //Standard section header. 148 | std::string SectionName; //Section full name. 149 | }; 150 | using PESECHDR_VEC = std::vector; 151 | inline const std::unordered_map MapSecHdrCharact { 152 | { 0x00000000, L"IMAGE_SCN_TYPE_REG (Reserved)" }, 153 | { 0x00000001, L"IMAGE_SCN_TYPE_DSECT (Reserved)" }, 154 | { 0x00000002, L"IMAGE_SCN_TYPE_NOLOAD (Reserved)" }, 155 | { 0x00000004, L"IMAGE_SCN_TYPE_GROUP (Reserved)" }, 156 | { IMAGE_SCN_TYPE_NO_PAD, L"IMAGE_SCN_TYPE_NO_PAD (Reserved)" }, 157 | { 0x00000010, L"IMAGE_SCN_TYPE_COPY (Reserved)" }, 158 | { IMAGE_SCN_CNT_CODE, L"IMAGE_SCN_CNT_CODE (Section contains code)" }, 159 | { IMAGE_SCN_CNT_INITIALIZED_DATA, L"IMAGE_SCN_CNT_INITIALIZED_DATA (Section contains initialized data)" }, 160 | { IMAGE_SCN_CNT_UNINITIALIZED_DATA, L"IMAGE_SCN_CNT_UNINITIALIZED_DATA (Section contains uninitialized data)" }, 161 | { IMAGE_SCN_LNK_OTHER, L"IMAGE_SCN_LNK_OTHER (Reserved)" }, 162 | { IMAGE_SCN_LNK_INFO, L"IMAGE_SCN_LNK_INFO (Section contains comments or some other type of information)" }, 163 | { 0x00000400, L"IMAGE_SCN_TYPE_OVER (Reserved)" }, 164 | { IMAGE_SCN_LNK_REMOVE, L"IMAGE_SCN_LNK_REMOVE (Section contents will not become part of image)" }, 165 | { IMAGE_SCN_LNK_COMDAT, L"IMAGE_SCN_LNK_COMDAT (Section contents comdat)" }, 166 | { IMAGE_SCN_NO_DEFER_SPEC_EXC, L"IMAGE_SCN_NO_DEFER_SPEC_EXC (Reset speculative exceptions handling bits in the TLB entries for this section)" }, 167 | { IMAGE_SCN_GPREL, L"IMAGE_SCN_GPREL (Section content can be accessed relative to GP)" }, 168 | { 0x00010000, L"IMAGE_SCN_MEM_SYSHEAP (Obsolete)" }, 169 | { IMAGE_SCN_MEM_PURGEABLE, L"IMAGE_SCN_MEM_PURGEABLE" }, 170 | { IMAGE_SCN_MEM_LOCKED, L"IMAGE_SCN_MEM_LOCKED" }, 171 | { IMAGE_SCN_MEM_PRELOAD, L"IMAGE_SCN_MEM_PRELOAD" }, 172 | { IMAGE_SCN_ALIGN_1BYTES, L"IMAGE_SCN_ALIGN_1BYTES" }, 173 | { IMAGE_SCN_ALIGN_2BYTES, L"IMAGE_SCN_ALIGN_2BYTES" }, 174 | { IMAGE_SCN_ALIGN_4BYTES, L"IMAGE_SCN_ALIGN_4BYTES" }, 175 | { IMAGE_SCN_ALIGN_8BYTES, L"IMAGE_SCN_ALIGN_8BYTES" }, 176 | { IMAGE_SCN_ALIGN_16BYTES, L"IMAGE_SCN_ALIGN_16BYTES (Default alignment if no others are specified)" }, 177 | { IMAGE_SCN_ALIGN_32BYTES, L"IMAGE_SCN_ALIGN_32BYTES" }, 178 | { IMAGE_SCN_ALIGN_64BYTES, L"IMAGE_SCN_ALIGN_64BYTES" }, 179 | { IMAGE_SCN_ALIGN_128BYTES, L"IMAGE_SCN_ALIGN_128BYTES" }, 180 | { IMAGE_SCN_ALIGN_256BYTES, L"IMAGE_SCN_ALIGN_256BYTES" }, 181 | { IMAGE_SCN_ALIGN_512BYTES, L"IMAGE_SCN_ALIGN_512BYTES" }, 182 | { IMAGE_SCN_ALIGN_1024BYTES, L"IMAGE_SCN_ALIGN_1024BYTES" }, 183 | { IMAGE_SCN_ALIGN_2048BYTES, L"IMAGE_SCN_ALIGN_2048BYTES" }, 184 | { IMAGE_SCN_ALIGN_4096BYTES, L"IMAGE_SCN_ALIGN_4096BYTES" }, 185 | { IMAGE_SCN_ALIGN_8192BYTES, L"IMAGE_SCN_ALIGN_8192BYTES" }, 186 | { IMAGE_SCN_ALIGN_MASK, L"IMAGE_SCN_ALIGN_MASK" }, 187 | { IMAGE_SCN_LNK_NRELOC_OVFL, L"IMAGE_SCN_LNK_NRELOC_OVFL (Section contains extended relocations)" }, 188 | { IMAGE_SCN_MEM_DISCARDABLE, L"IMAGE_SCN_MEM_DISCARDABLE (Section can be discarded)" }, 189 | { IMAGE_SCN_MEM_NOT_CACHED, L"IMAGE_SCN_MEM_NOT_CACHED (Section is not cachable)" }, 190 | { IMAGE_SCN_MEM_NOT_PAGED, L"IMAGE_SCN_MEM_NOT_PAGED (Section is not pageable)" }, 191 | { IMAGE_SCN_MEM_SHARED, L"IMAGE_SCN_MEM_SHARED (Section is shareable)" }, 192 | { IMAGE_SCN_MEM_EXECUTE, L"IMAGE_SCN_MEM_EXECUTE (Section is executable)" }, 193 | { IMAGE_SCN_MEM_READ, L"IMAGE_SCN_MEM_READ (Section is readable)" }, 194 | { IMAGE_SCN_MEM_WRITE, L"IMAGE_SCN_MEM_WRITE (Section is writeable)" } 195 | }; 196 | 197 | //Export table. 198 | struct PEExportFunction { 199 | DWORD FuncRVA; //Function RVA. 200 | DWORD Ordinal; //Function ordinal. 201 | DWORD NameRVA; //Name RVA. 202 | std::string FuncName; //Function name. 203 | std::string ForwarderName; //Function forwarder name. 204 | }; 205 | struct PEExport { 206 | DWORD Offset; //File's raw offset of the Export header descriptor. 207 | IMAGE_EXPORT_DIRECTORY ExportDesc; //Standard export header descriptor. 208 | std::string ModuleName; //Actual module name. 209 | std::vector Funcs; //Array of the exported functions struct. 210 | }; 211 | 212 | //Import table: 213 | struct PEImportFunction { 214 | union UNPEIMPORTTHUNK { 215 | IMAGE_THUNK_DATA32 Thunk32; //x86 standard thunk. 216 | IMAGE_THUNK_DATA64 Thunk64; //x64 standard thunk. 217 | } unThunk; 218 | IMAGE_IMPORT_BY_NAME ImpByName; //Standard IMAGE_IMPORT_BY_NAME struct 219 | std::string FuncName; //Function name. 220 | }; 221 | struct PEImport { 222 | DWORD Offset; //File's raw offset of this Import descriptor. 223 | IMAGE_IMPORT_DESCRIPTOR ImportDesc; //Standard Import descriptor. 224 | std::string ModuleName; //Imported module name. 225 | std::vector ImportFunc; //Array of imported functions. 226 | }; 227 | using PEIMPORT_VEC = std::vector; 228 | 229 | /**************************************Resources by Levels******************************************* 230 | * There are 3 levels of resources: 1. Type 2. Name 3. Language. * 231 | * https://docs.microsoft.com/en-us/windows/desktop/Debug/pe-format#the-rsrc-section * 232 | * Highest (root) resource structure is PERESROOT. It's a struct that includes: * 233 | * an IMAGE_RESOURCE_DIRECTORY of root resource directory itself and vector, * 234 | * that contains structs of all IMAGE_RESOURCE_DIRECTORY_ENTRY structures of the root resource * 235 | * directory. It also includes: wstring(Resource name), IMAGE_RESOURCE_DATA_ENTRY, * 236 | * vector (RAW resource data), and PERESLVL2 that is a struct of the next, second, resource * 237 | * level, that replicates struct of root resource level. PERESLVL2 includes IMAGE_RESOURCE_DIRECTORY * 238 | * of the second resource level, and vector that includes PERESLVL3 that is a struct * 239 | * of the last, third, level of resources. Like previous two, this last level's struct consist of * 240 | * IMAGE_RESOURCE_DIRECTORY and vector, that is again a vector of structs of all * 241 | * IMAGE_RESOURCE_DIRECTORY_ENTRY of the last, third, level of resources. * 242 | ****************************************************************************************************/ 243 | 244 | //Level 3/Lang (the lowest) resources. 245 | struct PEResLevel3Data { 246 | IMAGE_RESOURCE_DIRECTORY_ENTRY ResDirEntry; //Level 3 (Lang) standard IMAGE_RESOURCE_DIRECTORY_ENTRY struct. 247 | std::wstring ResName; //Level 3 (Lang) resource name. 248 | IMAGE_RESOURCE_DATA_ENTRY ResDataEntry; //Level 3 (Lang) standard IMAGE_RESOURCE_DATA_ENTRY struct. 249 | std::vector RawResData; //Level 3 (Lang) resource raw data. 250 | }; 251 | using PERESLANGDATA = PEResLevel3Data; 252 | 253 | struct PEResLevel3 { 254 | DWORD Offset; //File's raw offset of this level 3 IMAGE_RESOURCE_DIRECTORY descriptor. 255 | IMAGE_RESOURCE_DIRECTORY ResDir; //Level 3 standard IMAGE_RESOURCE_DIRECTORY header. 256 | std::vector ResData; //Array of level 3 resource entries. 257 | }; 258 | using PERESLANG = PEResLevel3; 259 | 260 | //Level 2/Name resources — Includes Lang resourses. 261 | struct PEResLevel2Data { 262 | IMAGE_RESOURCE_DIRECTORY_ENTRY ResDirEntry; //Level 2 (Name) standard IMAGE_RESOURCE_DIRECTORY_ENTRY struct. 263 | std::wstring ResName; //Level 2 (Name) resource name. 264 | IMAGE_RESOURCE_DATA_ENTRY ResDataEntry; //Level 2 (Name) standard IMAGE_RESOURCE_DATA_ENTRY struct. 265 | std::vector RawResData; //Level 2 (Name) resource raw data. 266 | PEResLevel3 ResLvL3; //Level 3 (Lang) resource struct. 267 | }; 268 | using PERESNAMEDATA = PEResLevel2Data; 269 | 270 | struct PEResLevel2 { 271 | DWORD Offset; //File's raw offset of this level 2 IMAGE_RESOURCE_DIRECTORY descriptor. 272 | IMAGE_RESOURCE_DIRECTORY ResDir; //Level 2 standard IMAGE_RESOURCE_DIRECTORY header. 273 | std::vector ResData; //Array of level 2 resource entries. 274 | }; 275 | using PERESNAME = PEResLevel2; 276 | 277 | //Level 1/Type resources — Includes Name Resources. 278 | struct PEResRootData { 279 | IMAGE_RESOURCE_DIRECTORY_ENTRY ResDirEntry; //Level root (Type) standard IMAGE_RESOURCE_DIRECTORY_ENTRY struct. 280 | std::wstring ResName; //Level root (Type) resource name. 281 | IMAGE_RESOURCE_DATA_ENTRY ResDataEntry; //Level root (Type) standard IMAGE_RESOURCE_DATA_ENTRY struct. 282 | std::vector RawResData; //Level root (Type) resource raw data. 283 | PEResLevel2 ResLvL2; //Level 2 (Name) resource struct. 284 | }; 285 | using PERESTYPEDATA = PEResRootData; 286 | 287 | struct PEResRoot { 288 | DWORD Offset; //File's raw offset of this level root IMAGE_RESOURCE_DIRECTORY descriptor. 289 | IMAGE_RESOURCE_DIRECTORY ResDir; //Level root standard IMAGE_RESOURCE_DIRECTORY header. 290 | std::vector ResData; //Array of level root resource entries. 291 | }; 292 | using PERESTYPE = PEResRoot; 293 | 294 | //Flattened resources. 295 | struct PEResFlat { 296 | std::span Data { }; //Resource data. 297 | std::wstring_view TypeStr { }; //Resource Type name. 298 | std::wstring_view NameStr { }; //Resource Name name (resource itself name). 299 | std::wstring_view LangStr { }; //Resource Lang name. 300 | WORD TypeID { }; //Resource Type ID (RT_CURSOR, RT_BITMAP, etc...). 301 | WORD NameID { }; //Resource Name ID (resource itself ID). 302 | WORD LangID { }; //Resource Lang ID. 303 | }; 304 | using PERESFLAT_VEC = std::vector; 305 | inline const std::unordered_map MapResID { 306 | { 1, L"RT_CURSOR" }, 307 | { 2, L"RT_BITMAP" }, 308 | { 3, L"RT_ICON" }, 309 | { 4, L"RT_MENU" }, 310 | { 5, L"RT_DIALOG" }, 311 | { 6, L"RT_STRING" }, 312 | { 7, L"RT_FONTDIR" }, 313 | { 8, L"RT_FONT" }, 314 | { 9, L"RT_ACCELERATOR" }, 315 | { 10, L"RT_RCDATA" }, 316 | { 11, L"RT_MESSAGETABLE" }, 317 | { 12, L"RT_GROUP_CURSOR" }, 318 | { 14, L"RT_GROUP_ICON" }, 319 | { 16, L"RT_VERSION" }, 320 | { 17, L"RT_DLGINCLUDE" }, 321 | { 19, L"RT_PLUGPLAY" }, 322 | { 20, L"RT_VXD" }, 323 | { 21, L"RT_ANICURSOR" }, 324 | { 22, L"RT_ANIICON" }, 325 | { 23, L"RT_HTML" }, 326 | { 24, L"RT_MANIFEST" }, 327 | { 28, L"RT_RIBBON_XML" }, 328 | { 240, L"RT_DLGINIT" }, 329 | { 241, L"RT_TOOLBAR" } 330 | }; 331 | /*********************************Resources End*****************************************/ 332 | 333 | //Exception table. 334 | struct PEException { 335 | DWORD Offset; //File's raw offset of this exception's descriptor. 336 | IMAGE_RUNTIME_FUNCTION_ENTRY RuntimeFuncEntry; //Standard _IMAGE_RUNTIME_FUNCTION_ENTRY header. 337 | }; 338 | using PEEXCEPTION_VEC = std::vector; 339 | 340 | //Security table. 341 | struct PESecurity { 342 | DWORD Offset; //File's raw offset of this security descriptor. 343 | WIN_CERTIFICATE WinCert; //Standard WIN_CERTIFICATE header. 344 | }; 345 | using PESECURITY_VEC = std::vector; 346 | inline const std::unordered_map MapWinCertRevision { 347 | { WIN_CERT_REVISION_1_0, L"WIN_CERT_REVISION_1_0" }, 348 | { WIN_CERT_REVISION_2_0, L"WIN_CERT_REVISION_2_0" } 349 | }; 350 | inline const std::unordered_map MapWinCertType { 351 | { WIN_CERT_TYPE_X509, L"WIN_CERT_TYPE_X509" }, 352 | { WIN_CERT_TYPE_PKCS_SIGNED_DATA, L"WIN_CERT_TYPE_PKCS_SIGNED_DATA" }, 353 | { WIN_CERT_TYPE_RESERVED_1, L"WIN_CERT_TYPE_RESERVED_1" }, 354 | { WIN_CERT_TYPE_TS_STACK_SIGNED, L"WIN_CERT_TYPE_TS_STACK_SIGNED" }, 355 | }; 356 | 357 | //Relocation table. 358 | struct PERelocData { 359 | DWORD Offset; //File's raw offset of this Relocation data descriptor. 360 | WORD RelocType; //Relocation type. 361 | WORD RelocOffset; //Relocation offset (Offset the relocation must be applied to.) 362 | }; 363 | inline const std::unordered_map MapRelocType { 364 | { IMAGE_REL_BASED_ABSOLUTE, L"IMAGE_REL_BASED_ABSOLUTE" }, 365 | { IMAGE_REL_BASED_HIGH, L"IMAGE_REL_BASED_HIGH" }, 366 | { IMAGE_REL_BASED_LOW, L"IMAGE_REL_BASED_LOW" }, 367 | { IMAGE_REL_BASED_HIGHLOW, L"IMAGE_REL_BASED_HIGHLOW" }, 368 | { IMAGE_REL_BASED_HIGHADJ, L"IMAGE_REL_BASED_HIGHADJ" }, 369 | { IMAGE_REL_BASED_MACHINE_SPECIFIC_5, L"IMAGE_REL_BASED_MACHINE_SPECIFIC_5" }, 370 | { IMAGE_REL_BASED_RESERVED, L"IMAGE_REL_BASED_RESERVED" }, 371 | { IMAGE_REL_BASED_MACHINE_SPECIFIC_7, L"IMAGE_REL_BASED_MACHINE_SPECIFIC_7" }, 372 | { IMAGE_REL_BASED_MACHINE_SPECIFIC_8, L"IMAGE_REL_BASED_MACHINE_SPECIFIC_8" }, 373 | { IMAGE_REL_BASED_MACHINE_SPECIFIC_9, L"IMAGE_REL_BASED_MACHINE_SPECIFIC_9" }, 374 | { IMAGE_REL_BASED_DIR64, L"IMAGE_REL_BASED_DIR64" } 375 | }; 376 | struct PERelocation { 377 | DWORD Offset; //File's raw offset of this Relocation descriptor. 378 | IMAGE_BASE_RELOCATION BaseReloc; //Standard IMAGE_BASE_RELOCATION header. 379 | std::vector RelocData; //Array of the Relocation data struct. 380 | }; 381 | using PERELOC_VEC = std::vector; 382 | 383 | 384 | //Debug table. 385 | struct PEDebugHeader { 386 | //dwHdr[6] is an array of the first six DWORDs of IMAGE_DEBUG_DIRECTORY::PointerToRawData data (Debug info header). 387 | //Their meaning varies depending on dwHdr[0] (Signature) value. 388 | //If dwHdr[0] == 0x53445352 (Ascii "RSDS") it's PDB 7.0 file: 389 | // Then dwHdr[1]-dwHdr[4] is GUID (*((GUID*)&dwHdr[1])). dwHdr[5] is Counter/Age. 390 | //If dwHdr[0] == 0x3031424E (Ascii "NB10") it's PDB 2.0 file: 391 | // Then dwHdr[1] is Offset. dwHdr[2] is Time/Signature. dwHdr[3] is Counter/Age. 392 | DWORD Header[6]; 393 | std::string PDBName; //PDB file name/path. 394 | }; 395 | struct PEDebug { 396 | DWORD Offset; //File's raw offset of this Debug descriptor. 397 | IMAGE_DEBUG_DIRECTORY DebugDir; //Standard IMAGE_DEBUG_DIRECTORY header. 398 | PEDebugHeader DebugHdrInfo; //Debug info header. 399 | }; 400 | using PEDEBUG_VEC = std::vector; 401 | inline const std::unordered_map MapDbgType { 402 | { IMAGE_DEBUG_TYPE_UNKNOWN, L"IMAGE_DEBUG_TYPE_UNKNOWN" }, 403 | { IMAGE_DEBUG_TYPE_COFF, L"IMAGE_DEBUG_TYPE_COFF" }, 404 | { IMAGE_DEBUG_TYPE_CODEVIEW, L"IMAGE_DEBUG_TYPE_CODEVIEW" }, 405 | { IMAGE_DEBUG_TYPE_FPO, L"IMAGE_DEBUG_TYPE_FPO" }, 406 | { IMAGE_DEBUG_TYPE_MISC, L"IMAGE_DEBUG_TYPE_MISC" }, 407 | { IMAGE_DEBUG_TYPE_EXCEPTION, L"IMAGE_DEBUG_TYPE_EXCEPTION" }, 408 | { IMAGE_DEBUG_TYPE_FIXUP, L"IMAGE_DEBUG_TYPE_FIXUP" }, 409 | { IMAGE_DEBUG_TYPE_OMAP_TO_SRC, L"IMAGE_DEBUG_TYPE_OMAP_TO_SRC" }, 410 | { IMAGE_DEBUG_TYPE_OMAP_FROM_SRC, L"IMAGE_DEBUG_TYPE_OMAP_FROM_SRC" }, 411 | { IMAGE_DEBUG_TYPE_BORLAND, L"IMAGE_DEBUG_TYPE_BORLAND" }, 412 | { IMAGE_DEBUG_TYPE_RESERVED10, L"IMAGE_DEBUG_TYPE_RESERVED10" }, 413 | { IMAGE_DEBUG_TYPE_CLSID, L"IMAGE_DEBUG_TYPE_CLSID" }, 414 | { IMAGE_DEBUG_TYPE_VC_FEATURE, L"IMAGE_DEBUG_TYPE_VC_FEATURE" }, 415 | { IMAGE_DEBUG_TYPE_POGO, L"IMAGE_DEBUG_TYPE_POGO" }, 416 | { IMAGE_DEBUG_TYPE_ILTCG, L"IMAGE_DEBUG_TYPE_ILTCG" }, 417 | { IMAGE_DEBUG_TYPE_MPX, L"IMAGE_DEBUG_TYPE_MPX" }, 418 | { IMAGE_DEBUG_TYPE_REPRO, L"IMAGE_DEBUG_TYPE_REPRO" } 419 | }; 420 | 421 | //TLS table. 422 | struct PETLS { 423 | DWORD dwOffset; //File's raw offset of the TLS header descriptor. 424 | union Tls { 425 | IMAGE_TLS_DIRECTORY32 TLSDir32; //x86 standard TLS header. 426 | IMAGE_TLS_DIRECTORY64 TLSDir64; //x64 TLS header. 427 | } unTLS; 428 | std::vector TLSCallbacks; //Array of the TLS callbacks. 429 | }; 430 | inline const std::unordered_map MapTLSCharact { 431 | { IMAGE_SCN_ALIGN_1BYTES, L"IMAGE_SCN_ALIGN_1BYTES" }, 432 | { IMAGE_SCN_ALIGN_2BYTES, L"IMAGE_SCN_ALIGN_2BYTES" }, 433 | { IMAGE_SCN_ALIGN_4BYTES, L"IMAGE_SCN_ALIGN_4BYTES" }, 434 | { IMAGE_SCN_ALIGN_8BYTES, L"IMAGE_SCN_ALIGN_8BYTES" }, 435 | { IMAGE_SCN_ALIGN_16BYTES, L"IMAGE_SCN_ALIGN_16BYTES" }, 436 | { IMAGE_SCN_ALIGN_32BYTES, L"IMAGE_SCN_ALIGN_32BYTES" }, 437 | { IMAGE_SCN_ALIGN_64BYTES, L"IMAGE_SCN_ALIGN_64BYTES" }, 438 | { IMAGE_SCN_ALIGN_128BYTES, L"IMAGE_SCN_ALIGN_128BYTES" }, 439 | { IMAGE_SCN_ALIGN_256BYTES, L"IMAGE_SCN_ALIGN_256BYTES" }, 440 | { IMAGE_SCN_ALIGN_512BYTES, L"IMAGE_SCN_ALIGN_512BYTES" }, 441 | { IMAGE_SCN_ALIGN_1024BYTES, L"IMAGE_SCN_ALIGN_1024BYTES" }, 442 | { IMAGE_SCN_ALIGN_2048BYTES, L"IMAGE_SCN_ALIGN_2048BYTES" }, 443 | { IMAGE_SCN_ALIGN_4096BYTES, L"IMAGE_SCN_ALIGN_4096BYTES" }, 444 | { IMAGE_SCN_ALIGN_8192BYTES, L"IMAGE_SCN_ALIGN_8192BYTES" }, 445 | { IMAGE_SCN_ALIGN_MASK, L"IMAGE_SCN_ALIGN_MASK" } 446 | }; 447 | 448 | //LoadConfigDirectory. 449 | struct PELoadConfig { 450 | DWORD dwOffset; //File's raw offset of the LCD descriptor. 451 | union { 452 | IMAGE_LOAD_CONFIG_DIRECTORY32 LCD32; //x86 LCD descriptor. 453 | IMAGE_LOAD_CONFIG_DIRECTORY64 LCD64; //x64 LCD descriptor. 454 | }; 455 | }; 456 | inline const std::unordered_map MapLCDGuardFlags { 457 | { IMAGE_GUARD_CF_INSTRUMENTED, L"IMAGE_GUARD_CF_INSTRUMENTED (Module performs control flow integrity checks using system-supplied support)" }, 458 | { IMAGE_GUARD_CFW_INSTRUMENTED, L"IMAGE_GUARD_CFW_INSTRUMENTED (Module performs control flow and write integrity checks)" }, 459 | { IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT, L"IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT (Module contains valid control flow target metadata)" }, 460 | { IMAGE_GUARD_SECURITY_COOKIE_UNUSED, L"IMAGE_GUARD_SECURITY_COOKIE_UNUSED (Module does not make use of the /GS security cookie)" }, 461 | { IMAGE_GUARD_PROTECT_DELAYLOAD_IAT, L"IMAGE_GUARD_PROTECT_DELAYLOAD_IAT (Module supports read only delay load IAT)" }, 462 | { IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION, L"IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION (Delayload import table in its own .didat section (with nothing else in it) that can be freely reprotected)" }, 463 | { IMAGE_GUARD_CF_EXPORT_SUPPRESSION_INFO_PRESENT, L"IMAGE_GUARD_CF_EXPORT_SUPPRESSION_INFO_PRESENT (Module contains suppressed export information. This also infers that the address taken IAT table is also present in the load config.)" }, 464 | { IMAGE_GUARD_CF_ENABLE_EXPORT_SUPPRESSION, L"IMAGE_GUARD_CF_ENABLE_EXPORT_SUPPRESSION (Module enables suppression of exports)" }, 465 | { IMAGE_GUARD_CF_LONGJUMP_TABLE_PRESENT, L"IMAGE_GUARD_CF_LONGJUMP_TABLE_PRESENT (Module contains longjmp target information)" }, 466 | { IMAGE_GUARD_RF_INSTRUMENTED, L"IMAGE_GUARD_RF_INSTRUMENTED (Module contains return flow instrumentation and metadata)" }, 467 | { IMAGE_GUARD_RF_ENABLE, L"IMAGE_GUARD_RF_ENABLE (Module requests that the OS enable return flow protection)" }, 468 | { IMAGE_GUARD_RF_STRICT, L"IMAGE_GUARD_RF_STRICT (Module requests that the OS enable return flow protection in strict mode)" }, 469 | { IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK, L"IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK (Stride of Guard CF function table encoded in these bits (additional count of bytes per element))" }, 470 | { IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT, L"IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT (Shift to right-justify Guard CF function table stride)" } 471 | }; 472 | 473 | //Bound import table. 474 | struct PEBoundForwarder { 475 | DWORD Offset; //File's raw offset of this Bound Forwarder descriptor. 476 | IMAGE_BOUND_FORWARDER_REF BoundForwarder; //Standard IMAGE_BOUND_FORWARDER_REF struct. 477 | std::string BoundForwarderName; //Bound forwarder name. 478 | }; 479 | struct PEBoundImport { 480 | DWORD Offset; //File's raw offset of this Bound Import descriptor. 481 | IMAGE_BOUND_IMPORT_DESCRIPTOR BoundImpDesc; //Standard IMAGE_BOUND_IMPORT_DESCRIPTOR struct. 482 | std::string BoundName; //Bound Import name. 483 | std::vector BoundForwarder; //Array of the Bound Forwarder structs. 484 | }; 485 | using PEBOUNDIMPORT_VEC = std::vector; 486 | 487 | //Delay import table. 488 | struct PEDelayImportFunc { 489 | union PEDelayImportThunk 490 | { 491 | struct x32 { 492 | IMAGE_THUNK_DATA32 ImportAddressTable; //x86 Import Address Table struct. 493 | IMAGE_THUNK_DATA32 ImportNameTable; //x86 Import Name Table struct. 494 | IMAGE_THUNK_DATA32 BoundImportAddressTable; //x86 Bound Import Address Table struct. 495 | IMAGE_THUNK_DATA32 UnloadInformationTable; //x86 Unload Information Table struct. 496 | } st32; 497 | struct x64 { 498 | IMAGE_THUNK_DATA64 ImportAddressTable; //x64 Import Address Table struct. 499 | IMAGE_THUNK_DATA64 ImportNameTable; //x64 Import Name Table struct. 500 | IMAGE_THUNK_DATA64 BoundImportAddressTable; //x64 Bound Import Address Table struct 501 | IMAGE_THUNK_DATA64 UnloadInformationTable; //x64 Unload Information Table struct. 502 | } st64; 503 | } unThunk; 504 | IMAGE_IMPORT_BY_NAME ImpByName; //Standard IMAGE_IMPORT_BY_NAME struct. 505 | std::string FuncName; //Function name. 506 | }; 507 | struct PEDelayImport { 508 | DWORD Offset; //File's raw offset of this Delay Import descriptor. 509 | IMAGE_DELAYLOAD_DESCRIPTOR DelayImpDesc; //Standard IMAGE_DELAYLOAD_DESCRIPTOR struct. 510 | std::string ModuleName; //Import module name. 511 | std::vector DelayImpFunc; //Array of the Delay Import module functions. 512 | }; 513 | using PEDELAYIMPORT_VEC = std::vector; 514 | 515 | //COM descriptor table. 516 | struct PECOMDESCRIPTOR { 517 | DWORD Offset; //File's raw offset of the IMAGE_COR20_HEADER descriptor. 518 | IMAGE_COR20_HEADER CorHdr; //Standard IMAGE_COR20_HEADER struct. 519 | }; 520 | inline const std::unordered_map MapCOR20Flags { 521 | { ReplacesCorHdrNumericDefines::COMIMAGE_FLAGS_ILONLY, L"COMIMAGE_FLAGS_ILONLY" }, 522 | { ReplacesCorHdrNumericDefines::COMIMAGE_FLAGS_32BITREQUIRED, L"COMIMAGE_FLAGS_32BITREQUIRED" }, 523 | { ReplacesCorHdrNumericDefines::COMIMAGE_FLAGS_IL_LIBRARY, L"COMIMAGE_FLAGS_IL_LIBRARY" }, 524 | { ReplacesCorHdrNumericDefines::COMIMAGE_FLAGS_STRONGNAMESIGNED, L"COMIMAGE_FLAGS_STRONGNAMESIGNED" }, 525 | { ReplacesCorHdrNumericDefines::COMIMAGE_FLAGS_NATIVE_ENTRYPOINT, L"COMIMAGE_FLAGS_NATIVE_ENTRYPOINT" }, 526 | { ReplacesCorHdrNumericDefines::COMIMAGE_FLAGS_TRACKDEBUGDATA, L"COMIMAGE_FLAGS_TRACKDEBUGDATA" }, 527 | { ReplacesCorHdrNumericDefines::COMIMAGE_FLAGS_32BITPREFERRED, L"COMIMAGE_FLAGS_32BITPREFERRED" } 528 | }; 529 | 530 | //File information struct. 531 | struct PEFILEINFO { 532 | bool IsPE32 : 1 {}; 533 | bool IsPE64 : 1 {}; 534 | bool HasDosHdr : 1 {}; 535 | bool HasRichHdr : 1 {}; 536 | bool HasNTHdr : 1 {}; 537 | bool HasDataDirs : 1 {}; 538 | bool HasSections : 1 {}; 539 | bool HasExport : 1 {}; 540 | bool HasImport : 1 {}; 541 | bool HasResource : 1 {}; 542 | bool HasException : 1 {}; 543 | bool HasSecurity : 1 {}; 544 | bool HasReloc : 1 {}; 545 | bool HasDebug : 1 {}; 546 | bool HasArchitect : 1 {}; 547 | bool HasGlobalPtr : 1 {}; 548 | bool HasTLS : 1 {}; 549 | bool HasLoadCFG : 1 {}; 550 | bool HasBoundImp : 1 {}; 551 | bool HasIAT : 1 {}; 552 | bool HasDelayImp : 1 {}; 553 | bool HasCOMDescr : 1 {}; 554 | }; 555 | 556 | //Pure abstract base class Ilibpe. 557 | class Ilibpe 558 | { 559 | public: 560 | virtual auto LoadPe(LPCWSTR pwszFile) -> int = 0; //Load PE file from file. 561 | virtual auto LoadPe(std::span spnFile) -> int = 0; //Load PE file from memory. 562 | [[nodiscard]] virtual auto IsLoaded() const -> bool = 0; 563 | [[nodiscard]] virtual auto GetFileInfo()const->PEFILEINFO const* = 0; 564 | [[nodiscard]] virtual auto GetOffsetFromRVA(ULONGLONG ullRVA)const->DWORD = 0; 565 | [[nodiscard]] virtual auto GetOffsetFromVA(ULONGLONG ullVA)const->DWORD = 0; 566 | [[nodiscard]] virtual auto GetMSDOSHeader() -> IMAGE_DOS_HEADER* = 0; 567 | [[nodiscard]] virtual auto GetRichHeader() -> PERICHHDR_VEC* = 0; 568 | [[nodiscard]] virtual auto GetNTHeader() -> PENtHeader* = 0; 569 | [[nodiscard]] virtual auto GetDataDirs() -> PEDATADIR_VEC* = 0; 570 | [[nodiscard]] virtual auto GetSecHeaders() -> PESECHDR_VEC* = 0; 571 | [[nodiscard]] virtual auto GetExport() -> PEExport* = 0; 572 | [[nodiscard]] virtual auto GetImport() -> PEIMPORT_VEC* = 0; 573 | [[nodiscard]] virtual auto GetResources() -> PEResRoot* = 0; 574 | [[nodiscard]] virtual auto GetExceptions() -> PEEXCEPTION_VEC* = 0; 575 | [[nodiscard]] virtual auto GetSecurity() -> PESECURITY_VEC* = 0; 576 | [[nodiscard]] virtual auto GetRelocations() -> PERELOC_VEC* = 0; 577 | [[nodiscard]] virtual auto GetDebug() -> PEDEBUG_VEC* = 0; 578 | [[nodiscard]] virtual auto GetTLS() -> PETLS* = 0; 579 | [[nodiscard]] virtual auto GetLoadConfig() -> PELoadConfig* = 0; 580 | [[nodiscard]] virtual auto GetBoundImport() -> PEBOUNDIMPORT_VEC* = 0; 581 | [[nodiscard]] virtual auto GetDelayImport() -> PEDELAYIMPORT_VEC* = 0; 582 | [[nodiscard]] virtual auto GetCOMDescriptor() -> PECOMDESCRIPTOR* = 0; 583 | [[nodiscard]] virtual auto GetImageBase()const->ULONGLONG = 0; 584 | [[nodiscard]] virtual auto GetSecHdrFromName(LPCSTR lpszName)const->PIMAGE_SECTION_HEADER = 0; 585 | [[nodiscard]] virtual auto GetSecHdrFromRVA(ULONGLONG ullRVA)const->PIMAGE_SECTION_HEADER = 0; 586 | [[nodiscard]] virtual auto GetBaseAddr()const->DWORD_PTR = 0; 587 | [[nodiscard]] virtual auto GetDataSize()const->ULONGLONG = 0; 588 | 589 | virtual void Clear() = 0; //Clear all internal structs. 590 | virtual void Destroy() = 0; 591 | [[nodiscard]] static auto FlatResources(const PEResRoot& stResRoot) -> PERESFLAT_VEC; 592 | }; 593 | 594 | //Return codes. 595 | constexpr auto PEOK = 0; 596 | constexpr auto ERR_FILE_OPEN = 0x01; 597 | constexpr auto ERR_FILE_SIZESMALL = 0x02; 598 | constexpr auto ERR_FILE_MAPPING = 0x03; 599 | constexpr auto ERR_FILE_NODOSHDR = 0x04; 600 | 601 | #ifdef LIBPE_SHARED_DLL 602 | #ifdef LIBPE_SHARED_DLL_EXPORT 603 | #define ILIBPEAPI __declspec(dllexport) 604 | #else //LIBPE_SHARED_DLL_EXPORT^^ 605 | #define ILIBPEAPI __declspec(dllimport) 606 | #ifdef _WIN64 607 | #ifdef _DEBUG 608 | #define LIBPE_LIB_NAME(x) x"64d.lib" 609 | #else //_DEBUG 610 | #define LIBPE_LIB_NAME(x) x"64.lib" 611 | #endif //_DEBUG 612 | #else //_WIN64 613 | #ifdef _DEBUG 614 | #define LIBPE_LIB_NAME(x) x"d.lib" 615 | #else //_DEBUG 616 | #define LIBPE_LIB_NAME(x) x".lib" 617 | #endif //_DEBUG 618 | #endif //_WIN64 619 | #pragma comment(lib, LIBPE_LIB_NAME("libpe")) 620 | #endif //LIBPE_SHARED_DLL_EXPORT 621 | #else //LIBPE_SHARED_DLL^^ 622 | #define ILIBPEAPI 623 | #endif //LIBPE_SHARED_DLL 624 | 625 | /******************************************************************************************** 626 | * Factory function Createlibpe, returns IlibpePtr - unique_ptr with custom deleter. * 627 | * If you, for some reason, need a raw pointer, you can directly call CreateRawlibpe * 628 | * function, which returns Ilibpe interface pointer, but in this case you will need to * 629 | * call Ilibpe::Destroy method afterwards manually - to delete Ilibpe object. * 630 | ********************************************************************************************/ 631 | extern "C" ILIBPEAPI Ilibpe * __cdecl CreateRawlibpe(); 632 | using IlibpePtr = std::unique_ptr < Ilibpe, decltype([](Ilibpe* p) { p->Destroy(); }) > ; 633 | 634 | inline IlibpePtr Createlibpe() { 635 | return IlibpePtr { CreateRawlibpe() }; 636 | }; 637 | 638 | /******************************************** 639 | * LIBPEINFO: service info structure. * 640 | ********************************************/ 641 | struct LIBPEINFO { 642 | const wchar_t* pwszVersion { }; //wchar_t string Version. 643 | union { 644 | unsigned long long ullVersion { }; //long long number Version. 645 | struct { 646 | short wMajor; 647 | short wMinor; 648 | short wMaintenance; 649 | short wRevision; 650 | } stVersion; 651 | }; 652 | }; 653 | 654 | extern "C" ILIBPEAPI LIBPEINFO __cdecl GetLibInfo(); 655 | } -------------------------------------------------------------------------------- /PECore/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /PECore/pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: source file corresponding to the pre-compiled header 2 | 3 | #include "pch.h" 4 | 5 | // When you are using pre-compiled headers, this source file is necessary for compilation to succeed. 6 | -------------------------------------------------------------------------------- /PECore/pch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DepWalk 2 | 3 | A modern take on the classic *Dependency Walker* (depends) tool 4 | 5 | (Very much a work in progress) 6 | 7 | ![](https://github.com/zodiacon/DepWalk/blob/master/depwalk.png) 8 | 9 | ## BUilding 10 | 11 | * Clone the repo with `--recursive` to get the submodule (WTLHelper) 12 | * Use ![vcpkg](https://github.com/microsoft/vcpkg) to install the following libraries: `detours`, `wtl`, `wil` for `x64-windows` and/or `x86-windows`. 13 | * Open the solution with Visual Studio 2022 and build it. 14 | -------------------------------------------------------------------------------- /ReleaseSigned/DepWalk.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/ReleaseSigned/DepWalk.exe -------------------------------------------------------------------------------- /ReleaseSigned/PECore.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/ReleaseSigned/PECore.lib -------------------------------------------------------------------------------- /ReleaseSigned/WTLHelper.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/ReleaseSigned/WTLHelper.lib -------------------------------------------------------------------------------- /depwalk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DepWalk/ce3bb79db97b23629d85d5d4a4f0b538d313ccba/depwalk.png --------------------------------------------------------------------------------