├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── apiset.c ├── apiset.h ├── apiset.sln ├── apiset.vcxproj ├── apiset.vcxproj.filters ├── main.c ├── nls.c ├── ntapi.h ├── ntpsapi.h ├── ntrtl.h ├── ntstatus.h ├── pebteb.h ├── resolve.c ├── string.c └── unicode.c /.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 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ 351 | 352 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21) 2 | 3 | # 4 | # Define the ApiSet project 5 | # 6 | project(apiset C) 7 | 8 | if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") 9 | # Force GCC and Clang to compile with proper unicode support for Windows. 10 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -municode -fshort-wchar") 11 | message(STATUS "Using GCC compiler: ${CMAKE_C_COMPILER}") 12 | elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC") 13 | # Compile as static runtime binary. 14 | message(STATUS "Using MSVC compiler: ${CMAKE_C_COMPILER}") 15 | # https://gitlab.kitware.com/cmake/community/wikis/FAQ#dynamic-replace 16 | foreach(flag_var CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO) 17 | if(${flag_var} MATCHES "/MD") 18 | string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") 19 | endif(${flag_var} MATCHES "/MD") 20 | if(${flag_var} MATCHES "/MDd") 21 | string(REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}") 22 | endif(${flag_var} MATCHES "/MDd") 23 | endforeach(flag_var) 24 | endif() 25 | 26 | set(APISET_SOURCES 27 | string.c 28 | nls.c 29 | apiset.c 30 | resolve.c 31 | main.c 32 | ) 33 | if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") 34 | set(APISET_SOURCES ${APISET_SOURCES} unicode.c) 35 | endif() 36 | 37 | add_executable(apiset ${APISET_SOURCES}) 38 | target_link_libraries(apiset ntdll) 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017-2019 Aidan Khoury 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ApiSet 2 | 3 | API Set resolver written in C. This implementation supports API Set versions V2 to V6. 4 | 5 | The intended purpose of this tool is to resolve Windows API Set stub libraries for assisting in reverse engineering forwarded Windows API exports. 6 | 7 | I wrote this to quickly resolve API Set libraries on different Windows OSes (Windows 7 - Windows 10 1909). 8 | 9 | Usage: 10 | `apiset.exe ext-some-api-set-library-l1-1-0.dll` 11 | 12 | Thanks to [lucasg](https://github.com/lucasg) for a great starting point for this little project. 13 | -------------------------------------------------------------------------------- /apiset.c: -------------------------------------------------------------------------------- 1 | /** 2 | * API Set Lookup 3 | * Copyright (c) 2018-2019 Aidan Khoury. All rights reserved. 4 | * 5 | * @file apiset.c 6 | * @authors Aidan Khoury (ajkhoury) 7 | * @date 11/22/2018 8 | */ 9 | 10 | #include "apiset.h" 11 | #include "ntrtl.h" 12 | 13 | // 14 | // ApiSet DLL prefixes. 15 | // 16 | 17 | #define API_SET_PREFIX_API_ (ULONGLONG)0x002D004900500041 /* L"api-" */ 18 | #define API_SET_PREFIX_EXT_ (ULONGLONG)0x002D005400580045 /* L"ext-" */ 19 | #define API_SET_DLL_EXTENSTION (ULONGLONG)0x004C004C0044002E /* L".DLL" */ 20 | 21 | // 22 | // Useful macros for ApiSet api. 23 | // 24 | 25 | #define API_SET_CHAR_TO_LOWER(c) \ 26 | (((WCHAR)((c) - L'A') <= (L'a' - L'A' - 1)) ? ((c) + 0x20) : (c)) 27 | 28 | 29 | // 30 | // API set schema version 6. 31 | // 32 | 33 | #define GET_API_SET_NAMESPACE_ENTRY_V6(ApiSetNamespace, Index) \ 34 | ((PAPI_SET_NAMESPACE_ENTRY_V6)((ULONG_PTR)(ApiSetNamespace) + \ 35 | ((PAPI_SET_NAMESPACE_V6)(ApiSetNamespace))->EntryOffset + \ 36 | ((Index) * sizeof(API_SET_NAMESPACE_ENTRY_V6)))) 37 | 38 | #define GET_API_SET_NAMESPACE_VALUE_ENTRY_V6(ApiSetNamespace, Entry, Index) \ 39 | ((PAPI_SET_VALUE_ENTRY_V6)((ULONG_PTR)(ApiSetNamespace) + \ 40 | ((PAPI_SET_NAMESPACE_ENTRY_V6)(Entry))->ValueOffset + \ 41 | ((Index) * sizeof(API_SET_VALUE_ENTRY_V6)))) 42 | 43 | #define GET_API_SET_NAMESPACE_ENTRY_NAME_V6(ApiSetNamespace, Entry) \ 44 | ((PWCHAR)((ULONG_PTR)(ApiSetNamespace) + ((PAPI_SET_NAMESPACE_ENTRY_V6)(Entry))->NameOffset)) 45 | 46 | #define GET_API_SET_NAMESPACE_ENTRY_VALUE_V6(ApiSetNamespace, Entry) \ 47 | ((PWCHAR)((ULONG_PTR)(ApiSetNamespace) + ((PAPI_SET_NAMESPACE_ENTRY_V6)(Entry))->ValueOffset)) 48 | 49 | #define GET_API_SET_VALUE_ENTRY_NAME_V6(ApiSetNamespace, Entry) \ 50 | ((PWCHAR)((ULONG_PTR)(ApiSetNamespace) + ((PAPI_SET_VALUE_ENTRY_V6)(Entry))->NameOffset)) 51 | 52 | #define GET_API_SET_VALUE_ENTRY_VALUE_V6(ApiSetNamespace, Entry) \ 53 | ((PWCHAR)((ULONG_PTR)(ApiSetNamespace) + ((PAPI_SET_VALUE_ENTRY_V6)(Entry))->ValueOffset)) 54 | 55 | #define GET_API_SET_HASH_ENTRY_V6(ApiSetNamespace, Middle) \ 56 | ((PAPI_SET_HASH_ENTRY_V6)((ULONG_PTR)(ApiSetNamespace) + \ 57 | ((PAPI_SET_NAMESPACE_V6)(ApiSetNamespace))->HashOffset + \ 58 | ((Middle) * sizeof(API_SET_HASH_ENTRY_V6)))) 59 | 60 | static 61 | PAPI_SET_NAMESPACE_ENTRY_V6 62 | ApiSetpSearchForApiSetV6( 63 | _In_ PAPI_SET_NAMESPACE_V6 ApiSetNamespace, 64 | _In_ PWCHAR ApiSetNameToResolve, 65 | _In_ USHORT ApiSetNameToResolveLength 66 | ) 67 | { 68 | WCHAR *pwc; 69 | USHORT Count; 70 | ULONG HashKey; 71 | LONG Low; 72 | LONG Middle; 73 | LONG High; 74 | PAPI_SET_HASH_ENTRY_V6 HashEntry; 75 | PAPI_SET_NAMESPACE_ENTRY_V6 FoundEntry; 76 | 77 | if (!ApiSetNameToResolveLength) { 78 | return NULL; 79 | } 80 | 81 | // 82 | // Calculate hash key for this ApiSet name. 83 | // 84 | HashKey = 0; 85 | pwc = ApiSetNameToResolve; 86 | Count = ApiSetNameToResolveLength; 87 | do { 88 | HashKey = HashKey * ApiSetNamespace->HashFactor + (USHORT)API_SET_CHAR_TO_LOWER(*pwc); 89 | ++pwc; 90 | --Count; 91 | } while (Count); 92 | 93 | // 94 | // Lookup the matching hash in the ApiSet namespace using a binary search. 95 | // 96 | FoundEntry = NULL; 97 | Low = 0; 98 | Middle = 0; 99 | High = (LONG)ApiSetNamespace->Count - 1; 100 | 101 | while (High >= Low) { 102 | Middle = (Low + High) >> 1; 103 | 104 | HashEntry = GET_API_SET_HASH_ENTRY_V6(ApiSetNamespace, Middle); 105 | 106 | if (HashKey < HashEntry->Hash) { 107 | High = Middle - 1; 108 | } else if (HashKey > HashEntry->Hash) { 109 | Low = Middle + 1; 110 | } else { 111 | // 112 | // Get the namespace entry from the hash entry index. 113 | // 114 | FoundEntry = GET_API_SET_NAMESPACE_ENTRY_V6(ApiSetNamespace, HashEntry->Index); 115 | break; 116 | } 117 | } 118 | 119 | // 120 | // If the high index is less than the low index, then a matching hash entry was not found. 121 | // Otherwise, get the found namespace entry. 122 | // 123 | if (High < Low) { 124 | return NULL; 125 | } 126 | 127 | // 128 | // Final check on apiset library name in order to make sure we didn't collide with 129 | // another hash bucket. 130 | // 131 | if (RtlCompareUnicodeStrings(ApiSetNameToResolve, 132 | ApiSetNameToResolveLength, 133 | GET_API_SET_NAMESPACE_ENTRY_NAME_V6(ApiSetNamespace, FoundEntry), 134 | FoundEntry->HashedLength / sizeof(WCHAR), 135 | TRUE) == 0) { 136 | return FoundEntry; 137 | } 138 | 139 | return NULL; 140 | } 141 | 142 | static 143 | PAPI_SET_VALUE_ENTRY_V6 144 | ApiSetpSearchForApiSetHostV6( 145 | _In_ PAPI_SET_NAMESPACE_ENTRY_V6 Entry, 146 | _In_ WCHAR *ApiSetNameToResolve, 147 | _In_ USHORT ApiSetNameToResolveLength, 148 | _In_ PAPI_SET_NAMESPACE_V6 ApiSetNamespace 149 | ) 150 | { 151 | LONG Low; 152 | LONG Middle; 153 | LONG High; 154 | LONG Result; 155 | PAPI_SET_VALUE_ENTRY_V6 FoundEntry; 156 | PAPI_SET_VALUE_ENTRY_V6 ApiSetHostEntry; 157 | 158 | // 159 | // If there is no alias, don't bother checking each one. 160 | // 161 | FoundEntry = GET_API_SET_NAMESPACE_VALUE_ENTRY_V6(ApiSetNamespace, Entry, 0); 162 | 163 | High = (LONG)(Entry->ValueCount - 1); 164 | if (!High) { 165 | return FoundEntry; 166 | } 167 | 168 | Low = 1; // skip the first entry. 169 | 170 | while (Low <= High) { 171 | Middle = (Low + High) >> 1; 172 | 173 | ApiSetHostEntry = GET_API_SET_NAMESPACE_VALUE_ENTRY_V6(ApiSetNamespace, Entry, Middle); 174 | 175 | // 176 | // Compare API names. 177 | // 178 | Result = RtlCompareUnicodeStrings(ApiSetNameToResolve, 179 | ApiSetNameToResolveLength, 180 | GET_API_SET_VALUE_ENTRY_NAME_V6(ApiSetNamespace, ApiSetHostEntry), 181 | ApiSetHostEntry->NameLength / sizeof(WCHAR), 182 | TRUE); 183 | if (Result < 0) { 184 | High = Middle - 1; 185 | } else if (Result > 0) { 186 | Low = Middle + 1; 187 | } else { 188 | FoundEntry = GET_API_SET_NAMESPACE_VALUE_ENTRY_V6(ApiSetNamespace, Entry, Middle); 189 | break; 190 | } 191 | } 192 | 193 | return FoundEntry; 194 | } 195 | 196 | NTSTATUS 197 | APISETAPI 198 | ApiSetResolveToHostV6( 199 | _In_ PAPI_SET_NAMESPACE ApiSetNamespace, 200 | _In_ PCUNICODE_STRING ApiSetNameToResolve, 201 | _In_opt_ PCUNICODE_STRING ParentName, 202 | _Out_ PBOOLEAN Resolved, 203 | _Out_ PUNICODE_STRING Output 204 | ) 205 | { 206 | NTSTATUS Status; 207 | BOOLEAN IsResolved; 208 | WCHAR *ApiSetNameBuffer; 209 | WCHAR *pwc; 210 | ULONG ApiSetNameBufferLength; 211 | USHORT ApiSetNameNoExtLength; 212 | PAPI_SET_NAMESPACE_ENTRY_V6 ResolvedNamespaceEntry; 213 | PAPI_SET_VALUE_ENTRY_V6 HostLibraryEntry; 214 | ULONGLONG ApiSetNameBufferPrefix; 215 | 216 | IsResolved = FALSE; 217 | RtlInitEmptyUnicodeString(Output, NULL, 0); 218 | 219 | // 220 | // Make sure the API Set name is a valid length. 221 | // 222 | if (ApiSetNameToResolve->Length < sizeof(API_SET_PREFIX_API_)) { 223 | goto Exit; 224 | } 225 | 226 | ApiSetNameBuffer = ApiSetNameToResolve->Buffer; 227 | 228 | // 229 | // Check library name starts with "api-" or "ext-" 230 | // 231 | ApiSetNameBufferPrefix = *(ULONGLONG*)ApiSetNameBuffer; 232 | ApiSetNameBufferPrefix &= ~(ULONGLONG)0x0000002000200020; // Trick to convert the chars to uppercase. 233 | if ((ApiSetNameBufferPrefix != API_SET_PREFIX_API_) && 234 | (ApiSetNameBufferPrefix != API_SET_PREFIX_EXT_)) { 235 | goto Exit; 236 | } 237 | 238 | // 239 | // Compute word count of apiset library name without the dll suffix and anything 240 | // beyond the last hyphen. Example: 241 | // api-ms-win-core-apiquery-l1-1-0.dll -> wordlen(api-ms-win-core-apiquery-l1-1) 242 | // 243 | ApiSetNameBufferLength = (ULONG)ApiSetNameToResolve->Length; 244 | pwc = (WCHAR*)((ULONG_PTR)ApiSetNameBuffer + ApiSetNameBufferLength); 245 | do { 246 | if (ApiSetNameBufferLength <= 1) 247 | break; 248 | ApiSetNameBufferLength -= sizeof(WCHAR); 249 | --pwc; 250 | } while (*pwc != L'-'); 251 | 252 | ApiSetNameNoExtLength = (USHORT)(ApiSetNameBufferLength / sizeof(WCHAR)); 253 | if (!ApiSetNameNoExtLength) { 254 | goto Exit; 255 | } 256 | 257 | // 258 | // Hash table lookup. 259 | // 260 | ResolvedNamespaceEntry = ApiSetpSearchForApiSetV6((PAPI_SET_NAMESPACE_V6)ApiSetNamespace, 261 | ApiSetNameBuffer, 262 | ApiSetNameNoExtLength 263 | ); 264 | if (!ResolvedNamespaceEntry) { 265 | goto Exit; 266 | } 267 | 268 | // 269 | // Look for aliases in hosts libraries if necessary. 270 | // 271 | if (ResolvedNamespaceEntry->ValueCount > 1 && ParentName) { 272 | 273 | HostLibraryEntry = ApiSetpSearchForApiSetHostV6(ResolvedNamespaceEntry, 274 | ParentName->Buffer, 275 | ParentName->Length / sizeof(WCHAR), 276 | (PAPI_SET_NAMESPACE_V6)ApiSetNamespace 277 | ); 278 | 279 | } else if (ResolvedNamespaceEntry->ValueCount > 0) { 280 | 281 | HostLibraryEntry = GET_API_SET_NAMESPACE_VALUE_ENTRY_V6(ApiSetNamespace, 282 | ResolvedNamespaceEntry, 283 | 0); 284 | } else { 285 | goto Exit; 286 | } 287 | 288 | // 289 | // Output resolved host library. 290 | // 291 | Output->Length = (USHORT)HostLibraryEntry->ValueLength; 292 | Output->MaximumLength = Output->Length; 293 | Output->Buffer = GET_API_SET_VALUE_ENTRY_VALUE_V6(ApiSetNamespace, HostLibraryEntry); 294 | 295 | IsResolved = TRUE; 296 | 297 | Exit: 298 | Status = STATUS_SUCCESS; 299 | *Resolved = IsResolved; 300 | 301 | return Status; 302 | } 303 | 304 | 305 | 306 | // 307 | // API set schema version 4. 308 | // 309 | 310 | #define GET_API_SET_NAMESPACE_ENTRY_V4(ApiSetNamespace, Index) \ 311 | ((PAPI_SET_NAMESPACE_ENTRY_V4)(((PAPI_SET_NAMESPACE_ARRAY_V4)(ApiSetNamespace))->Array + \ 312 | Index)) 313 | 314 | #define GET_API_SET_NAMESPACE_ENTRY_NAME_V4(ApiSetNamespace, NamespaceEntry) \ 315 | ((PWCHAR)((ULONG_PTR)(ApiSetNamespace) + \ 316 | ((PAPI_SET_NAMESPACE_ENTRY_V4)(NamespaceEntry))->NameOffset)) 317 | 318 | #define GET_API_SET_NAMESPACE_ENTRY_DATA_V4(ApiSetNamespace, NamespaceEntry) \ 319 | ((PAPI_SET_VALUE_ARRAY_V4)((ULONG_PTR)(ApiSetNamespace) + \ 320 | ((PAPI_SET_NAMESPACE_ENTRY_V4)(NamespaceEntry))->DataOffset)) 321 | 322 | #define GET_API_SET_VALUE_ENTRY_V4(ApiSetNamespace, ResolvedValueArray, Index) \ 323 | ((PAPI_SET_VALUE_ENTRY_V4)(((PAPI_SET_VALUE_ARRAY_V4)(ResolvedValueArray))->Array + \ 324 | Index)) 325 | 326 | #define GET_API_SET_VALUE_ENTRY_NAME_V4(ApiSetNamespace, ApiSetValueEntry) \ 327 | ((WCHAR*)((ULONG_PTR)(ApiSetNamespace) + \ 328 | ((PAPI_SET_VALUE_ENTRY_V4)(ApiSetValueEntry))->NameOffset)) 329 | 330 | #define GET_API_SET_VALUE_ENTRY_VALUE_V4(ApiSetNamespace, ApiSetValueEntry) \ 331 | ((WCHAR*)((ULONG_PTR)(ApiSetNamespace) + \ 332 | ((PAPI_SET_VALUE_ENTRY_V4)(ApiSetValueEntry))->ValueOffset)) 333 | 334 | static 335 | PAPI_SET_NAMESPACE_ENTRY_V4 336 | ApiSetpSearchForApiSetV4( 337 | _In_ PAPI_SET_NAMESPACE ApiSetNamespace, 338 | _In_ PWCHAR ApiSetNameToResolve, 339 | _In_ USHORT ApiSetNameToResolveLength 340 | ) 341 | { 342 | LONG Low; 343 | LONG Middle; 344 | LONG High; 345 | LONG Result; 346 | PAPI_SET_NAMESPACE_ARRAY_V4 ApiSetNamespaceArray; 347 | PAPI_SET_NAMESPACE_ENTRY_V4 ApiSetNamespaceEntry; 348 | 349 | ApiSetNamespaceArray = (PAPI_SET_NAMESPACE_ARRAY_V4)ApiSetNamespace; 350 | 351 | Low = 0; 352 | High = (LONG)(ApiSetNamespaceArray->Count - 1); 353 | 354 | while (High >= Low) { 355 | Middle = (High + Low) >> 1; 356 | 357 | ApiSetNamespaceEntry = GET_API_SET_NAMESPACE_ENTRY_V4(ApiSetNamespace, Middle); 358 | 359 | Result = RtlCompareUnicodeStrings(ApiSetNameToResolve, 360 | ApiSetNameToResolveLength, 361 | GET_API_SET_NAMESPACE_ENTRY_NAME_V4(ApiSetNamespace, ApiSetNamespaceEntry), 362 | ApiSetNamespaceEntry->NameLength, 363 | TRUE 364 | ); 365 | if (Result < 0) { 366 | High = Middle - 1; 367 | } else if (Result > 0) { 368 | Low = Middle + 1; 369 | } else { 370 | return ApiSetNamespaceEntry; 371 | } 372 | } 373 | 374 | return NULL; 375 | } 376 | 377 | static 378 | PAPI_SET_VALUE_ENTRY_V4 379 | ApiSetpSearchForApiSetHostV4( 380 | _In_ PAPI_SET_VALUE_ARRAY_V4 ApiSetValueArray, 381 | _In_ WCHAR *ApiSetNameToResolve, 382 | _In_ USHORT ApiSetNameToResolveLength, 383 | _In_ PAPI_SET_NAMESPACE_ARRAY_V4 ApiSetNamespace 384 | ) 385 | { 386 | LONG Low; 387 | LONG Middle; 388 | LONG High; 389 | LONG Result; 390 | PAPI_SET_VALUE_ENTRY_V4 ApiSetHostEntry; 391 | 392 | Low = 1; // skip first entry. 393 | High = (LONG)(ApiSetValueArray->Count - 1); 394 | 395 | while (High >= Low) { 396 | Middle = (High + Low) >> 1; 397 | 398 | ApiSetHostEntry = GET_API_SET_VALUE_ENTRY_V4(ApiSetNamespace, ApiSetValueArray, Middle); 399 | 400 | Result = RtlCompareUnicodeStrings(ApiSetNameToResolve, 401 | ApiSetNameToResolveLength, 402 | GET_API_SET_VALUE_ENTRY_NAME_V4(ApiSetNamespace, ApiSetHostEntry), 403 | ApiSetHostEntry->NameLength, 404 | TRUE 405 | ); 406 | if (Result < 0) { 407 | High = Middle - 1; 408 | } else if (Result > 0) { 409 | Low = Middle + 1; 410 | } else { 411 | return ApiSetHostEntry; 412 | } 413 | } 414 | 415 | return NULL; 416 | } 417 | 418 | NTSTATUS 419 | APISETAPI 420 | ApiSetResolveToHostV4( 421 | _In_ PAPI_SET_NAMESPACE ApiSetNamespace, 422 | _In_ PCUNICODE_STRING ApiSetNameToResolve, 423 | _In_opt_ PCUNICODE_STRING ParentName, 424 | _Out_ PBOOLEAN Resolved, 425 | _Out_ PUNICODE_STRING Output 426 | ) 427 | { 428 | NTSTATUS Status; 429 | BOOLEAN IsResolved; 430 | ULONGLONG ApiSetNameBufferPrefix; 431 | PAPI_SET_NAMESPACE_ENTRY_V4 ResolvedNamespaceEntry; 432 | PAPI_SET_VALUE_ARRAY_V4 ResolvedValueArray; 433 | PAPI_SET_VALUE_ENTRY_V4 HostLibraryEntry; 434 | UNICODE_STRING ApiSetNameNoExtString; 435 | 436 | IsResolved = FALSE; 437 | RtlInitEmptyUnicodeString(Output, NULL, 0); 438 | 439 | // 440 | // Make sure the API Set name is a valid length. 441 | // 442 | if (ApiSetNameToResolve->Length < sizeof(API_SET_PREFIX_API_)) { 443 | goto Exit; 444 | } 445 | 446 | // 447 | // Check library name starts with "api-" or "ext-" 448 | // 449 | ApiSetNameBufferPrefix = *(ULONGLONG*)ApiSetNameToResolve->Buffer; 450 | ApiSetNameBufferPrefix &= ~(ULONGLONG)0x0000002000200020; // Trick to convert the chars to uppercase. 451 | if (ApiSetNameBufferPrefix != API_SET_PREFIX_API_ && 452 | ApiSetNameBufferPrefix != API_SET_PREFIX_EXT_) { 453 | goto Exit; 454 | } 455 | 456 | // 457 | // Skip the prefix. 458 | // 459 | ApiSetNameNoExtString.Length = ApiSetNameToResolve->Length - sizeof(API_SET_PREFIX_API_); 460 | ApiSetNameNoExtString.MaximumLength = ApiSetNameNoExtString.Length; 461 | ApiSetNameNoExtString.Buffer = (WCHAR*)((ULONG_PTR)ApiSetNameToResolve->Buffer + 462 | sizeof(API_SET_PREFIX_API_)); 463 | 464 | // 465 | // Cut off the '.DLL' extension. 466 | // 467 | if (ApiSetNameNoExtString.Length >= sizeof(API_SET_DLL_EXTENSTION) && 468 | ApiSetNameNoExtString.Buffer[(ApiSetNameNoExtString.Length - 469 | sizeof(API_SET_DLL_EXTENSTION)) / sizeof(WCHAR)] == L'.') { 470 | ApiSetNameNoExtString.Length -= sizeof(API_SET_DLL_EXTENSTION); 471 | } 472 | 473 | ResolvedNamespaceEntry = ApiSetpSearchForApiSetV4(ApiSetNamespace, 474 | ApiSetNameNoExtString.Buffer, 475 | ApiSetNameNoExtString.Length / sizeof(WCHAR) 476 | ); 477 | if (!ResolvedNamespaceEntry) { 478 | goto Exit; 479 | } 480 | 481 | // 482 | // Get the namspace value array. 483 | // 484 | ResolvedValueArray = GET_API_SET_NAMESPACE_ENTRY_DATA_V4(ApiSetNamespace, 485 | ResolvedNamespaceEntry); 486 | 487 | // 488 | // Look for aliases in hosts libraries if necessary. 489 | // 490 | if (ResolvedValueArray->Count > 1 && ParentName) { 491 | 492 | HostLibraryEntry = ApiSetpSearchForApiSetHostV4(ResolvedValueArray, 493 | ParentName->Buffer, 494 | ParentName->Length / sizeof(WCHAR), 495 | (PAPI_SET_NAMESPACE_ARRAY_V4)ApiSetNamespace 496 | ); 497 | 498 | } else if (ResolvedValueArray->Count > 0) { 499 | 500 | HostLibraryEntry = GET_API_SET_VALUE_ENTRY_V4(ApiSetNamespace, ResolvedValueArray, 0); 501 | 502 | } else { 503 | goto Exit; 504 | } 505 | 506 | Output->Length = (USHORT)HostLibraryEntry->ValueLength; 507 | Output->MaximumLength = Output->Length; 508 | Output->Buffer = GET_API_SET_VALUE_ENTRY_VALUE_V4(ApiSetNamespace, HostLibraryEntry); 509 | 510 | IsResolved = TRUE; 511 | 512 | Exit: 513 | Status = STATUS_SUCCESS; 514 | *Resolved = IsResolved; 515 | 516 | return Status; 517 | } 518 | 519 | 520 | 521 | // 522 | // API Set Schema Version 3 523 | // 524 | 525 | #define GET_API_SET_NAMESPACE_ENTRY_V3(ApiSetNamespace, Index) \ 526 | ((PAPI_SET_NAMESPACE_ENTRY_V3)(((PAPI_SET_NAMESPACE_ARRAY_V3)(ApiSetNamespace))->Array + \ 527 | Index)) 528 | 529 | #define GET_API_SET_NAMESPACE_ENTRY_NAME_V3(ApiSetNamespace, NamespaceEntry) \ 530 | ((PWCHAR)((ULONG_PTR)(ApiSetNamespace) + \ 531 | ((PAPI_SET_NAMESPACE_ENTRY_V3)(NamespaceEntry))->NameOffset)) 532 | 533 | #define GET_API_SET_NAMESPACE_ENTRY_DATA_V3(ApiSetNamespace, NamespaceEntry) \ 534 | ((PAPI_SET_VALUE_ARRAY_V3)((ULONG_PTR)(ApiSetNamespace) + \ 535 | ((PAPI_SET_NAMESPACE_ENTRY_V3)(NamespaceEntry))->DataOffset)) 536 | 537 | #define GET_API_SET_VALUE_ENTRY_V3(ApiSetNamespace, ResolvedValueArray, Index) \ 538 | ((PAPI_SET_VALUE_ENTRY_V3)(((PAPI_SET_VALUE_ARRAY_V3)(ResolvedValueArray))->Array + \ 539 | Index)) 540 | 541 | #define GET_API_SET_VALUE_ENTRY_NAME_V3(ApiSetNamespace, ApiSetValueEntry) \ 542 | ((WCHAR*)((ULONG_PTR)(ApiSetNamespace) + \ 543 | ((PAPI_SET_VALUE_ENTRY_V3)(ApiSetValueEntry))->NameOffset)) 544 | 545 | #define GET_API_SET_VALUE_ENTRY_VALUE_V3(ApiSetNamespace, ApiSetValueEntry) \ 546 | ((WCHAR*)((ULONG_PTR)(ApiSetNamespace) + \ 547 | ((PAPI_SET_VALUE_ENTRY_V3)(ApiSetValueEntry))->ValueOffset)) 548 | 549 | static 550 | PAPI_SET_VALUE_ENTRY_V3 551 | ApiSetpSearchForApiSetHostV3( 552 | _In_ PAPI_SET_VALUE_ARRAY_V3 ApiSetValueArray, 553 | _In_ WCHAR *ApiSetNameToResolve, 554 | _In_ USHORT ApiSetNameToResolveLength, 555 | _In_ PAPI_SET_NAMESPACE_ARRAY_V3 ApiSetNamespace 556 | ) 557 | { 558 | LONG Low; 559 | LONG Middle; 560 | LONG High; 561 | LONG Result; 562 | PAPI_SET_VALUE_ENTRY_V3 ApiSetValueEntry; 563 | 564 | Low = 1; // skip first entry. 565 | High = ApiSetValueArray->Count - 1; 566 | 567 | while (High >= Low) { 568 | Middle = (High + Low) >> 1; 569 | 570 | ApiSetValueEntry = GET_API_SET_VALUE_ENTRY_V3(ApiSetNamespace, ApiSetValueArray, Middle); 571 | 572 | Result = RtlCompareUnicodeStrings(ApiSetNameToResolve, 573 | ApiSetNameToResolveLength, 574 | GET_API_SET_VALUE_ENTRY_NAME_V3(ApiSetNamespace, 575 | ApiSetValueEntry), 576 | ApiSetValueEntry->NameLength, 577 | TRUE); 578 | if (Result < 0) { 579 | High = Middle - 1; 580 | } else if (Result > 0) { 581 | Low = Middle + 1; 582 | } else { 583 | return ApiSetValueEntry; 584 | } 585 | } 586 | 587 | return NULL; 588 | } 589 | 590 | NTSTATUS 591 | APISETAPI 592 | ApiSetResolveToHostV3( 593 | _In_ PAPI_SET_NAMESPACE ApiSetNamespace, 594 | _In_ PCUNICODE_STRING ApiSetNameToResolve, 595 | _In_opt_ PCUNICODE_STRING ParentName, 596 | _Out_ PBOOLEAN Resolved, 597 | _Out_ PUNICODE_STRING Output 598 | ) 599 | { 600 | NTSTATUS Status; 601 | BOOLEAN IsResolved; 602 | ULONGLONG ApiSetNameBufferPrefix; 603 | LONG Low; 604 | LONG Middle; 605 | LONG High; 606 | LONG Result; 607 | PAPI_SET_NAMESPACE_ARRAY_V3 ApiSetNamespaceArray; 608 | PAPI_SET_NAMESPACE_ENTRY_V3 ResolvedNamespaceEntry; 609 | PAPI_SET_VALUE_ARRAY_V3 ResolvedValueArray; 610 | PAPI_SET_VALUE_ENTRY_V3 HostLibraryEntry; 611 | UNICODE_STRING ApiSetNameNoExtString; 612 | 613 | IsResolved = FALSE; 614 | RtlInitEmptyUnicodeString(Output, NULL, 0); 615 | 616 | // 617 | // Make sure the API Set name is a valid length. 618 | // 619 | if (ApiSetNameToResolve->Length < sizeof(API_SET_PREFIX_API_)) { 620 | goto Exit; 621 | } 622 | 623 | // 624 | // Check library name starts with "api-" or "ext-" 625 | // 626 | ApiSetNameBufferPrefix = *(ULONGLONG*)ApiSetNameToResolve->Buffer; 627 | ApiSetNameBufferPrefix &= ~(ULONGLONG)0x0000002000200020; // Trick to convert the chars to lowercase. 628 | if (ApiSetNameBufferPrefix != API_SET_PREFIX_API_ && 629 | ApiSetNameBufferPrefix != API_SET_PREFIX_EXT_) { 630 | goto Exit; 631 | } 632 | 633 | // 634 | // Skip the prefix. 635 | // 636 | ApiSetNameNoExtString.Length = ApiSetNameToResolve->Length - sizeof(API_SET_PREFIX_API_); 637 | ApiSetNameNoExtString.MaximumLength = ApiSetNameNoExtString.Length; 638 | ApiSetNameNoExtString.Buffer = (WCHAR*)((ULONG_PTR)ApiSetNameToResolve->Buffer + 639 | sizeof(API_SET_PREFIX_API_)); 640 | 641 | // 642 | // Cut off the '.DLL' extension. 643 | // 644 | if (ApiSetNameNoExtString.Length >= sizeof(API_SET_DLL_EXTENSTION) && 645 | ApiSetNameNoExtString.Buffer[(ApiSetNameNoExtString.Length - 646 | sizeof(API_SET_DLL_EXTENSTION)) / sizeof(WCHAR)] == L'.') { 647 | ApiSetNameNoExtString.Length -= sizeof(API_SET_DLL_EXTENSTION); 648 | } 649 | 650 | ApiSetNamespaceArray = (PAPI_SET_NAMESPACE_ARRAY_V3)ApiSetNamespace; 651 | ResolvedNamespaceEntry = NULL; 652 | 653 | Low = 0; 654 | High = (LONG)(ApiSetNamespaceArray->Count - 1); 655 | 656 | while (High >= Low) { 657 | Middle = (Low + High) >> 1; 658 | 659 | ResolvedNamespaceEntry = GET_API_SET_NAMESPACE_ENTRY_V3(ApiSetNamespace, Middle); 660 | 661 | Result = RtlCompareUnicodeStrings(ApiSetNameNoExtString.Buffer, 662 | ApiSetNameNoExtString.Length / sizeof(WCHAR), 663 | GET_API_SET_NAMESPACE_ENTRY_NAME_V3(ApiSetNamespace, 664 | ResolvedNamespaceEntry), 665 | ResolvedNamespaceEntry->NameLength / sizeof(WCHAR), 666 | TRUE 667 | ); 668 | if (Result < 0) { 669 | High = Middle - 1; 670 | } else if (Result > 0) { 671 | Low = Middle + 1; 672 | } else { 673 | break; 674 | } 675 | } 676 | 677 | // 678 | // If the high index is less than the low index, then a matching namespace 679 | // entry was not found. 680 | // 681 | if (High < Low) { 682 | goto Exit; 683 | } 684 | 685 | // 686 | // Get the namspace value array. 687 | // 688 | ResolvedValueArray = GET_API_SET_NAMESPACE_ENTRY_DATA_V3(ApiSetNamespace, ResolvedNamespaceEntry); 689 | 690 | // 691 | // Look for aliases in hosts libraries if necessary. 692 | // 693 | if (ResolvedValueArray->Count > 1 && ParentName) { 694 | 695 | HostLibraryEntry = ApiSetpSearchForApiSetHostV3(ResolvedValueArray, 696 | ParentName->Buffer, 697 | ParentName->Length / sizeof(WCHAR), 698 | (PAPI_SET_NAMESPACE_ARRAY_V3)ApiSetNamespace 699 | ); 700 | } else { 701 | HostLibraryEntry = NULL; 702 | } 703 | 704 | // 705 | // Default to the first value entry. 706 | // 707 | if (!HostLibraryEntry) { 708 | HostLibraryEntry = GET_API_SET_VALUE_ENTRY_V3(ApiSetNamespace, ResolvedValueArray, 0); 709 | } 710 | 711 | // 712 | // Output resolved host library. 713 | // 714 | Output->Length = (USHORT)HostLibraryEntry->ValueLength; 715 | Output->MaximumLength = Output->Length; 716 | Output->Buffer = GET_API_SET_VALUE_ENTRY_VALUE_V3(ApiSetNamespace, HostLibraryEntry); 717 | 718 | IsResolved = TRUE; 719 | 720 | Exit: 721 | Status = STATUS_SUCCESS; 722 | *Resolved = IsResolved; 723 | 724 | return Status; 725 | } 726 | 727 | 728 | 729 | // 730 | // API Set Schema Version 2 731 | // 732 | 733 | #define GET_API_SET_NAMESPACE_ENTRY_V2(ApiSetNamespace, Index) \ 734 | ((PAPI_SET_NAMESPACE_ENTRY_V2)((ULONG_PTR)(ApiSetNamespace) + \ 735 | ((PAPI_SET_NAMESPACE_ARRAY_V2)(ApiSetNamespace))->Array + \ 736 | Index)) 737 | 738 | static 739 | PAPI_SET_VALUE_ENTRY_V2 740 | ApiSetpSearchForApiSetHostV2( 741 | _In_ PAPI_SET_VALUE_ARRAY_V2 ApiSetValueArray, 742 | _In_ PCUNICODE_STRING ApiToResolve, 743 | _In_ PAPI_SET_NAMESPACE ApiSetNamespace 744 | ) 745 | { 746 | LONG Low; 747 | LONG Middle; 748 | LONG High; 749 | LONG Result; 750 | UNICODE_STRING ApiSetHostString; 751 | PAPI_SET_VALUE_ENTRY_V2 ApiSetValueEntry; 752 | 753 | Low = 1; // skip first entry. 754 | High = ApiSetValueArray->Count - 1; 755 | 756 | while (High >= Low) { 757 | Middle = (High + Low) >> 1; 758 | 759 | ApiSetValueEntry = &ApiSetValueArray->Array[Middle]; 760 | ApiSetHostString.Length = (USHORT)ApiSetValueEntry->NameLength; 761 | ApiSetHostString.MaximumLength = ApiSetHostString.Length; 762 | ApiSetHostString.Buffer = (WCHAR*)((ULONG_PTR)ApiSetNamespace + ApiSetValueEntry->NameOffset); 763 | 764 | Result = RtlCompareUnicodeString(ApiToResolve, &ApiSetHostString, TRUE); 765 | 766 | if (Result < 0) { 767 | High = Middle - 1; 768 | } else if (Result > 0) { 769 | Low = Middle + 1; 770 | } else { 771 | return ApiSetValueEntry; 772 | } 773 | } 774 | 775 | return NULL; 776 | } 777 | 778 | NTSTATUS 779 | APISETAPI 780 | ApiSetResolveToHostV2( 781 | _In_ PAPI_SET_NAMESPACE ApiSetNamespace, 782 | _In_ PCUNICODE_STRING ApiSetNameToResolve, 783 | _In_opt_ PCUNICODE_STRING ParentName, 784 | _Out_ PBOOLEAN Resolved, 785 | _Out_ PUNICODE_STRING Output 786 | ) 787 | { 788 | NTSTATUS Status; 789 | BOOLEAN IsResolved; 790 | ULONGLONG ApiSetNameBufferPrefix; 791 | LONG Low; 792 | LONG Middle; 793 | LONG High; 794 | LONG Result; 795 | PAPI_SET_NAMESPACE_ARRAY_V2 ApiSetNamespaceArray; 796 | PAPI_SET_NAMESPACE_ENTRY_V2 ApiSetNamespaceEntry; 797 | PAPI_SET_VALUE_ARRAY_V2 ApiSetValueArray; 798 | PAPI_SET_VALUE_ENTRY_V2 HostLibraryEntry; 799 | UNICODE_STRING ApiSetNamespaceString; 800 | UNICODE_STRING ApiSetNameNoExtString; 801 | 802 | IsResolved = FALSE; 803 | RtlInitEmptyUnicodeString(Output, NULL, 0); 804 | 805 | // 806 | // Make sure the API Set name is a valid length. 807 | // 808 | if (ApiSetNameToResolve->Length < sizeof(API_SET_PREFIX_API_)) { 809 | goto Exit; 810 | } 811 | 812 | // 813 | // Check library name starts with "api-" 814 | // 815 | ApiSetNameBufferPrefix = *(ULONGLONG*)ApiSetNameToResolve->Buffer; 816 | ApiSetNameBufferPrefix &= ~(ULONGLONG)0x0000002000200020; // Trick to convert the chars to lowercase. 817 | if (ApiSetNameBufferPrefix != API_SET_PREFIX_API_) { 818 | goto Exit; 819 | } 820 | 821 | // 822 | // Skip the prefix. 823 | // 824 | ApiSetNameNoExtString.Length = ApiSetNameToResolve->Length - sizeof(API_SET_PREFIX_API_); 825 | ApiSetNameNoExtString.MaximumLength = ApiSetNameNoExtString.Length; 826 | ApiSetNameNoExtString.Buffer = (WCHAR*)((ULONG_PTR)ApiSetNameToResolve->Buffer + 827 | sizeof(API_SET_PREFIX_API_)); 828 | 829 | // 830 | // Cut off the '.DLL' extension. 831 | // 832 | if (ApiSetNameNoExtString.Length >= sizeof(API_SET_DLL_EXTENSTION) && 833 | ApiSetNameNoExtString.Buffer[(ApiSetNameNoExtString.Length - 834 | sizeof(API_SET_DLL_EXTENSTION)) / sizeof(WCHAR)] == L'.') { 835 | ApiSetNameNoExtString.Length -= sizeof(API_SET_DLL_EXTENSTION); 836 | } 837 | 838 | ApiSetNamespaceArray = (PAPI_SET_NAMESPACE_ARRAY_V2)ApiSetNamespace; 839 | ApiSetNamespaceEntry = NULL; 840 | 841 | Low = 0; 842 | High = (LONG)(ApiSetNamespaceArray->Count - 1); 843 | 844 | while (High >= Low) { 845 | Middle = (Low + High) >> 1; 846 | 847 | ApiSetNamespaceEntry = GET_API_SET_NAMESPACE_ENTRY_V2(ApiSetNamespace, Middle); 848 | ApiSetNamespaceString.Length = (USHORT)ApiSetNamespaceEntry->NameLength; 849 | ApiSetNamespaceString.MaximumLength = ApiSetNamespaceString.Length; 850 | ApiSetNamespaceString.Buffer = (WCHAR*)((ULONG_PTR)ApiSetNamespace + 851 | ApiSetNamespaceEntry->NameOffset); 852 | 853 | Result = RtlCompareUnicodeString(&ApiSetNameNoExtString, &ApiSetNamespaceString, TRUE); 854 | 855 | if (Result < 0) { 856 | High = Middle - 1; 857 | } else if (Result > 0) { 858 | Low = Middle + 1; 859 | } else { 860 | break; 861 | } 862 | } 863 | 864 | // 865 | // If the high index is less than the low index, then a matching namespace 866 | // entry was not found. 867 | // 868 | if (High < Low) { 869 | goto Exit; 870 | } 871 | 872 | // 873 | // Get the namspace value array. 874 | // 875 | ApiSetValueArray = (PAPI_SET_VALUE_ARRAY_V2)((ULONG_PTR)ApiSetNamespace + 876 | ApiSetNamespaceEntry->DataOffset); 877 | 878 | // 879 | // Look for aliases in hosts libraries if necessary. 880 | // 881 | if (ApiSetValueArray->Count > 1 && ParentName) { 882 | 883 | HostLibraryEntry = ApiSetpSearchForApiSetHostV2(ApiSetValueArray, 884 | ParentName, 885 | ApiSetNamespace 886 | ); 887 | } else { 888 | HostLibraryEntry = NULL; 889 | } 890 | 891 | // 892 | // Default to the first value entry. 893 | // 894 | if (!HostLibraryEntry) { 895 | HostLibraryEntry = ApiSetValueArray->Array; 896 | } 897 | 898 | // 899 | // Output resolved host library. 900 | // 901 | Output->Length = (USHORT)HostLibraryEntry->ValueLength; 902 | Output->MaximumLength = Output->Length; 903 | Output->Buffer = (WCHAR*)((ULONG_PTR)ApiSetNamespace + HostLibraryEntry->ValueOffset); 904 | 905 | IsResolved = TRUE; 906 | 907 | Exit: 908 | Status = STATUS_SUCCESS; 909 | *Resolved = IsResolved; 910 | 911 | return Status; 912 | } 913 | -------------------------------------------------------------------------------- /apiset.h: -------------------------------------------------------------------------------- 1 | /** 2 | * API Set Lookup 3 | * Copyright (c) 2018-2019 Aidan Khoury. All rights reserved. 4 | * 5 | * @file apiset.h 6 | * @author Aidan Khoury (ajkhoury) 7 | * @date 11/22/2018 8 | */ 9 | 10 | #ifndef _API_SET_H_ 11 | #define _API_SET_H_ 12 | #if defined(_MSC_VER) 13 | #pragma once 14 | #endif 15 | 16 | #include "ntapi.h" 17 | 18 | // API Set calling convention 19 | #define APISETAPI NTAPI 20 | 21 | 22 | // 23 | // API schema definitions. 24 | // 25 | 26 | #define API_SET_SCHEMA_VERSION_V2 0x00000002 27 | #define API_SET_SCHEMA_VERSION_V3 0x00000003 // No offline support. 28 | #define API_SET_SCHEMA_VERSION_V4 0x00000004 29 | #define API_SET_SCHEMA_VERSION_V6 0x00000006 30 | 31 | 32 | // 33 | // API Set data structures 34 | // 35 | 36 | typedef struct _API_SET_NAMESPACE { 37 | ULONG Version; 38 | } API_SET_NAMESPACE, *PAPI_SET_NAMESPACE; 39 | 40 | 41 | // 42 | // API set schema version 6. 43 | // 44 | 45 | typedef struct _API_SET_NAMESPACE_V6 { 46 | ULONG Version; 47 | ULONG Size; 48 | ULONG Flags; 49 | ULONG Count; 50 | ULONG EntryOffset; // API_SET_NAMESPACE_ENTRY_V6 51 | ULONG HashOffset; // API_SET_NAMESPACE_HASH_ENTRY_V6 52 | ULONG HashFactor; 53 | } API_SET_NAMESPACE_V6, *PAPI_SET_NAMESPACE_V6; 54 | 55 | typedef struct _API_SET_NAMESPACE_ENTRY_V6 { 56 | ULONG Flags; 57 | ULONG NameOffset; 58 | ULONG NameLength; 59 | ULONG HashedLength; 60 | ULONG ValueOffset; 61 | ULONG ValueCount; 62 | } API_SET_NAMESPACE_ENTRY_V6, *PAPI_SET_NAMESPACE_ENTRY_V6; 63 | 64 | typedef struct _API_SET_HASH_ENTRY_V6 { 65 | ULONG Hash; 66 | ULONG Index; 67 | } API_SET_HASH_ENTRY_V6, *PAPI_SET_HASH_ENTRY_V6; 68 | 69 | typedef struct _API_SET_VALUE_ENTRY_V6 { 70 | ULONG Flags; 71 | ULONG NameOffset; 72 | ULONG NameLength; 73 | ULONG ValueOffset; 74 | ULONG ValueLength; 75 | } API_SET_VALUE_ENTRY_V6, *PAPI_SET_VALUE_ENTRY_V6; 76 | 77 | typedef const API_SET_VALUE_ENTRY_V6 *PCAPI_SET_VALUE_ENTRY_V6; 78 | typedef const API_SET_HASH_ENTRY_V6 *PCAPI_SET_HASH_ENTRY_V6; 79 | typedef const API_SET_NAMESPACE_ENTRY_V6 *PCAPI_SET_NAMESPACE_ENTRY_V6; 80 | typedef const API_SET_NAMESPACE_V6 *PCAPI_SET_NAMESPACE_V6; 81 | 82 | 83 | // 84 | // API set schema version 4. 85 | // 86 | 87 | typedef struct _API_SET_VALUE_ENTRY_V4 { 88 | ULONG Flags; // 0x00 89 | ULONG NameOffset; // 0x04 90 | ULONG NameLength; // 0x08 91 | ULONG ValueOffset; // 0x0C 92 | ULONG ValueLength; // 0x10 93 | } API_SET_VALUE_ENTRY_V4, *PAPI_SET_VALUE_ENTRY_V4; 94 | 95 | typedef struct _API_SET_VALUE_ARRAY_V4 { 96 | ULONG Flags; // 0x00 97 | ULONG Count; // 0x04 98 | API_SET_VALUE_ENTRY_V4 Array[ANYSIZE_ARRAY]; 99 | } API_SET_VALUE_ARRAY_V4, *PAPI_SET_VALUE_ARRAY_V4; 100 | 101 | typedef struct _API_SET_NAMESPACE_ENTRY_V4 { 102 | ULONG Flags; 103 | ULONG NameOffset; 104 | ULONG NameLength; 105 | ULONG AliasOffset; 106 | ULONG AliasLength; 107 | ULONG DataOffset; // API_SET_VALUE_ARRAY_V4 108 | } API_SET_NAMESPACE_ENTRY_V4, *PAPI_SET_NAMESPACE_ENTRY_V4; 109 | 110 | typedef struct _API_SET_NAMESPACE_ARRAY_V4 { 111 | ULONG Version; // 0x00 112 | ULONG Size; // 0x04 113 | ULONG Flags; // 0x08 114 | ULONG Count; // 0x0C 115 | API_SET_NAMESPACE_ENTRY_V4 Array[ANYSIZE_ARRAY]; 116 | } API_SET_NAMESPACE_ARRAY_V4, *PAPI_SET_NAMESPACE_ARRAY_V4; 117 | 118 | typedef const API_SET_VALUE_ENTRY_V4 *PCAPI_SET_VALUE_ENTRY_V4; 119 | typedef const API_SET_VALUE_ARRAY_V4 *PCAPI_SET_VALUE_ARRAY_V4; 120 | typedef const API_SET_NAMESPACE_ENTRY_V4 *PCAPI_SET_NAMESPACE_ENTRY_V4; 121 | typedef const API_SET_NAMESPACE_ARRAY_V4 *PCAPI_SET_NAMESPACE_ARRAY_V4; 122 | 123 | #define API_SET_SCHEMA_FLAGS_SEALED 0x00000001 124 | #define API_SET_SCHEMA_FLAGS_HOST_EXTENSION 0x00000002 125 | 126 | #define API_SET_SCHEMA_ENTRY_FLAGS_SEALED 0x00000001 127 | #define API_SET_SCHEMA_ENTRY_FLAGS_EXTENSION 0x00000002 128 | 129 | // 130 | // API set schema version 3. 131 | // 132 | 133 | typedef struct _API_SET_VALUE_ENTRY_V3 { 134 | ULONG NameOffset; 135 | ULONG NameLength; 136 | ULONG ValueOffset; 137 | ULONG ValueLength; 138 | } API_SET_VALUE_ENTRY_V3, *PAPI_SET_VALUE_ENTRY_V3; 139 | 140 | typedef struct _API_SET_VALUE_ARRAY_V3 { 141 | ULONG Count; 142 | API_SET_VALUE_ENTRY_V3 Array[ANYSIZE_ARRAY]; 143 | } API_SET_VALUE_ARRAY_V3, *PAPI_SET_VALUE_ARRAY_V3; 144 | 145 | typedef struct _API_SET_NAMESPACE_ENTRY_V3 { 146 | ULONG NameOffset; 147 | ULONG NameLength; 148 | ULONG DataOffset; // API_SET_VALUE_ARRAY_V3 149 | } API_SET_NAMESPACE_ENTRY_V3, *PAPI_SET_NAMESPACE_ENTRY_V3; 150 | 151 | typedef struct _API_SET_NAMESPACE_ARRAY_V3 { 152 | ULONG Version; 153 | ULONG Count; 154 | API_SET_NAMESPACE_ENTRY_V3 Array[ANYSIZE_ARRAY]; 155 | } API_SET_NAMESPACE_ARRAY_V3, *PAPI_SET_NAMESPACE_ARRAY_V3; 156 | 157 | typedef const API_SET_VALUE_ENTRY_V3 *PCAPI_SET_VALUE_ENTRY_V3; 158 | typedef const API_SET_VALUE_ARRAY_V3 *PCAPI_SET_VALUE_ARRAY_V3; 159 | typedef const API_SET_NAMESPACE_ENTRY_V3 *PCAPI_SET_NAMESPACE_ENTRY_V3; 160 | typedef const API_SET_NAMESPACE_ARRAY_V3 *PCAPI_SET_NAMESPACE_ARRAY_V3; 161 | 162 | // 163 | // Support for downlevel API set schema version 2. 164 | // 165 | 166 | typedef struct _API_SET_VALUE_ENTRY_V2 { 167 | ULONG NameOffset; 168 | ULONG NameLength; 169 | ULONG ValueOffset; 170 | ULONG ValueLength; 171 | } API_SET_VALUE_ENTRY_V2, *PAPI_SET_VALUE_ENTRY_V2; 172 | 173 | typedef struct _API_SET_VALUE_ARRAY_V2 { 174 | ULONG Count; 175 | API_SET_VALUE_ENTRY_V2 Array[ANYSIZE_ARRAY]; 176 | } API_SET_VALUE_ARRAY_V2, *PAPI_SET_VALUE_ARRAY_V2; 177 | 178 | typedef struct _API_SET_NAMESPACE_ENTRY_V2 { 179 | ULONG NameOffset; 180 | ULONG NameLength; 181 | ULONG DataOffset; // API_SET_VALUE_ARRAY_V2 182 | } API_SET_NAMESPACE_ENTRY_V2, *PAPI_SET_NAMESPACE_ENTRY_V2; 183 | 184 | typedef struct _API_SET_NAMESPACE_ARRAY_V2 { 185 | ULONG Version; 186 | ULONG Count; 187 | API_SET_NAMESPACE_ENTRY_V2 Array[ANYSIZE_ARRAY]; 188 | } API_SET_NAMESPACE_ARRAY_V2, *PAPI_SET_NAMESPACE_ARRAY_V2; 189 | 190 | typedef const API_SET_VALUE_ENTRY_V2 *PCAPI_SET_VALUE_ENTRY_V2; 191 | typedef const API_SET_VALUE_ARRAY_V2 *PCAPI_SET_VALUE_ARRAY_V2; 192 | typedef const API_SET_NAMESPACE_ENTRY_V2 *PCAPI_SET_NAMESPACE_ENTRY_V2; 193 | typedef const API_SET_NAMESPACE_ARRAY_V2 *PCAPI_SET_NAMESPACE_ARRAY_V2; 194 | 195 | 196 | // 197 | // API Set Routines 198 | // 199 | 200 | NTSTATUS 201 | APISETAPI 202 | ApiSetResolveToHostV6( 203 | _In_ PAPI_SET_NAMESPACE ApiSetNamespace, 204 | _In_ PCUNICODE_STRING ApiSetNameToResolve, 205 | _In_opt_ PCUNICODE_STRING ParentName, 206 | _Out_ PBOOLEAN Resolved, 207 | _Out_ PUNICODE_STRING Output 208 | ); 209 | 210 | NTSTATUS 211 | APISETAPI 212 | ApiSetResolveToHostV4( 213 | _In_ PAPI_SET_NAMESPACE ApiSetNamespace, 214 | _In_ PCUNICODE_STRING ApiSetNameToResolve, 215 | _In_opt_ PCUNICODE_STRING ParentName, 216 | _Out_ PBOOLEAN Resolved, 217 | _Out_ PUNICODE_STRING Output 218 | ); 219 | 220 | NTSTATUS 221 | APISETAPI 222 | ApiSetResolveToHostV3( 223 | _In_ PAPI_SET_NAMESPACE ApiSetNamespace, 224 | _In_ PCUNICODE_STRING ApiSetNameToResolve, 225 | _In_opt_ PCUNICODE_STRING ParentName, 226 | _Out_ PBOOLEAN Resolved, 227 | _Out_ PUNICODE_STRING Output 228 | ); 229 | 230 | NTSTATUS 231 | APISETAPI 232 | ApiSetResolveToHostV2( 233 | _In_ PAPI_SET_NAMESPACE ApiSetNamespace, 234 | _In_ PCUNICODE_STRING ApiSetNameToResolve, 235 | _In_opt_ PCUNICODE_STRING ParentName, 236 | _Out_ PBOOLEAN Resolved, 237 | _Out_ PUNICODE_STRING Output 238 | ); 239 | 240 | BOOLEAN 241 | APISETAPI 242 | ApiSetResolve( 243 | _In_z_ PWCHAR ApiSetName, 244 | _In_opt_z_ PWCHAR BaseDllName, 245 | _Out_ PUNICODE_STRING ResolvedHostLibrary 246 | ); 247 | 248 | #endif // _ODIN_API_SET_H_ -------------------------------------------------------------------------------- /apiset.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29418.71 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "apiset", "apiset.vcxproj", "{EFFB681D-7C5E-4DEE-A772-DC90E8BF8F4D}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {EFFB681D-7C5E-4DEE-A772-DC90E8BF8F4D}.Debug|x64.ActiveCfg = Debug|x64 17 | {EFFB681D-7C5E-4DEE-A772-DC90E8BF8F4D}.Debug|x64.Build.0 = Debug|x64 18 | {EFFB681D-7C5E-4DEE-A772-DC90E8BF8F4D}.Debug|x86.ActiveCfg = Debug|Win32 19 | {EFFB681D-7C5E-4DEE-A772-DC90E8BF8F4D}.Debug|x86.Build.0 = Debug|Win32 20 | {EFFB681D-7C5E-4DEE-A772-DC90E8BF8F4D}.Release|x64.ActiveCfg = Release|x64 21 | {EFFB681D-7C5E-4DEE-A772-DC90E8BF8F4D}.Release|x64.Build.0 = Release|x64 22 | {EFFB681D-7C5E-4DEE-A772-DC90E8BF8F4D}.Release|x86.ActiveCfg = Release|Win32 23 | {EFFB681D-7C5E-4DEE-A772-DC90E8BF8F4D}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {9DB7E6ED-C673-46CA-B623-50B1DDAE4204} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /apiset.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | {EFFB681D-7C5E-4DEE-A772-DC90E8BF8F4D} 24 | apiset 25 | 10.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v142 32 | MultiByte 33 | 34 | 35 | Application 36 | false 37 | v142 38 | true 39 | MultiByte 40 | 41 | 42 | Application 43 | true 44 | v142 45 | MultiByte 46 | 47 | 48 | Application 49 | false 50 | v142 51 | true 52 | MultiByte 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | apiset 74 | 75 | 76 | 77 | Level3 78 | Disabled 79 | true 80 | true 81 | 82 | 83 | Console 84 | ntdll.lib;%(AdditionalDependencies) 85 | 86 | 87 | 88 | 89 | Level3 90 | Disabled 91 | true 92 | true 93 | CompileAsC 94 | 95 | 96 | Console 97 | ntdll.lib;%(AdditionalDependencies) 98 | 99 | 100 | 101 | 102 | Level3 103 | MaxSpeed 104 | true 105 | true 106 | true 107 | true 108 | 109 | 110 | Console 111 | true 112 | true 113 | 114 | 115 | 116 | 117 | Level3 118 | MaxSpeed 119 | true 120 | true 121 | true 122 | true 123 | MultiThreaded 124 | 125 | 126 | Console 127 | true 128 | true 129 | ntdll.lib;%(AdditionalDependencies) 130 | false 131 | 132 | 133 | copy "$(OutDir)$(TargetName)$(TargetExt)" "F:\tools\bin\$(TargetName)$(TargetExt)" 134 | 135 | 136 | Copying to tools directory... 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /apiset.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 49 | 50 | 51 | Header Files 52 | 53 | 54 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * API Set Lookup 3 | * Copyright (c) 2018-2019 Aidan Khoury. All rights reserved. 4 | * 5 | * @file apiset.c 6 | * @authors Aidan Khoury (ajkhoury) 7 | * lucasg 8 | * @date 11/22/2018 9 | */ 10 | 11 | #include "apiset.h" 12 | 13 | #include 14 | 15 | void help() 16 | { 17 | wprintf(L"ApiSet : resolve api set host library\n"); 18 | wprintf(L"Usage:\n apiset ext-some-api-set-library-l1-1-0.dll [base_dll_name]\n"); 19 | } 20 | 21 | int wmain(int argc, wchar_t* argv[]) 22 | { 23 | PWCHAR ApiSetName; 24 | PWCHAR BaseDllName; 25 | UNICODE_STRING HostApi; 26 | WCHAR HostLibraryName[MAX_PATH]; 27 | 28 | if (argc < 2) { 29 | help(); 30 | return -1; 31 | } 32 | 33 | if (wcscmp(argv[1], L"-h") == 0 || 34 | wcscmp(argv[1], L"/?") == 0 || 35 | wcscmp(argv[1], L"-help") == 0 || 36 | wcscmp(argv[1], L"--help") == 0) { 37 | help(); 38 | return 0; 39 | } 40 | 41 | // 42 | // Process arguments. 43 | // 44 | ApiSetName = argv[1]; 45 | 46 | if (argc > 2) { 47 | BaseDllName = argv[2]; 48 | } else { 49 | BaseDllName = NULL; 50 | } 51 | 52 | // 53 | // Attempt to resolve API Set library. 54 | // 55 | if (!ApiSetResolve(ApiSetName, BaseDllName, &HostApi)) { 56 | wprintf(L"[x] Could not resolve Api set library : %s\n", ApiSetName); 57 | return -1; 58 | } 59 | 60 | // 61 | // Output the resolved host library. 62 | // 63 | if (wcsncpy_s(HostLibraryName, RTL_NUMBER_OF(HostLibraryName), HostApi.Buffer, HostApi.Length)) { 64 | wprintf(L"[x] Could not copy resolved host library name\n"); 65 | return -1; 66 | } 67 | HostLibraryName[HostApi.Length / sizeof(WCHAR)] = '\0'; 68 | 69 | wprintf(L"[!] Api set library resolved : %s -> %s\n", ApiSetName, HostLibraryName); 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /nls.c: -------------------------------------------------------------------------------- 1 | #include "ntrtl.h" 2 | 3 | /** 4 | * Compares two counted Unicode strings. The return value indicates if the 5 | * strings are equal or String1 is less than String2 or String1 is greater 6 | * than String2. 7 | * 8 | * The CaseInSensitive parameter specifies if case is to be ignored when 9 | * doing the comparison. 10 | * 11 | * @param[in] String1 Pointer to the first string. 12 | * @param[in] Length1 Length of the first string. 13 | * @param[in] String2 Pointer to the second string. 14 | * @param[in] Length2 Length of the second string. 15 | * @param[in] CaseInSensitive If TRUE, case should be ignored when doing 16 | * the comparison. 17 | * 18 | * @return Signed value that gives the results of the comparison: 19 | * Zero - String1 equals String2 20 | * < Zero - String1 less than String2 21 | * > Zero - String1 greater than String2 22 | */ 23 | LONG 24 | NTAPI 25 | RtlCompareUnicodeStrings( 26 | IN CONST WCHAR* String1, 27 | IN SIZE_T Length1, 28 | IN CONST WCHAR* String2, 29 | IN SIZE_T Length2, 30 | IN BOOLEAN CaseInSensitive 31 | ) 32 | { 33 | CONST WCHAR* s1, * s2, * Limit; 34 | LONG n1, n2; 35 | UINT32 c1, c2; 36 | 37 | if (Length1 > LONG_MAX || Length2 > LONG_MAX) { 38 | return STATUS_INVALID_BUFFER_SIZE; 39 | } 40 | 41 | s1 = String1; 42 | s2 = String2; 43 | n1 = (LONG)Length1; 44 | n2 = (LONG)Length2; 45 | 46 | Limit = (WCHAR*)((CHAR*)s1 + (n1 <= n2 ? n1 : n2)); 47 | if (CaseInSensitive) { 48 | while (s1 < Limit) { 49 | c1 = *s1; 50 | c2 = *s2; 51 | if (c1 != c2) { 52 | 53 | // 54 | // Note that this needs to reference the translation table! 55 | // 56 | c1 = RTL_UPCASE(c1); 57 | c2 = RTL_UPCASE(c2); 58 | if (c1 != c2) { 59 | return (INT32)(c1)-(INT32)(c2); 60 | } 61 | } 62 | s1 += 1; 63 | s2 += 1; 64 | } 65 | 66 | } else { 67 | 68 | while (s1 < Limit) { 69 | c1 = *s1; 70 | c2 = *s2; 71 | if (c1 != c2) { 72 | return (LONG)(c1)-(LONG)(c2); 73 | } 74 | s1 += 1; 75 | s2 += 1; 76 | } 77 | } 78 | 79 | return n1 - n2; 80 | } -------------------------------------------------------------------------------- /ntapi.h: -------------------------------------------------------------------------------- 1 | #ifndef _NTAPI_ 2 | #define _NTAPI_ 3 | 4 | #include 5 | #include 6 | 7 | #include "ntstatus.h" 8 | 9 | // 10 | // Counted String 11 | // 12 | 13 | typedef USHORT RTL_STRING_LENGTH_TYPE; 14 | 15 | typedef struct _STRING { 16 | USHORT Length; 17 | USHORT MaximumLength; 18 | #ifdef MIDL_PASS 19 | [size_is(MaximumLength), length_is(Length)] 20 | #endif // MIDL_PASS 21 | _Field_size_bytes_part_opt_(MaximumLength, Length) PCHAR Buffer; 22 | } STRING; 23 | typedef STRING* PSTRING; 24 | typedef STRING ANSI_STRING; 25 | typedef PSTRING PANSI_STRING; 26 | 27 | // end_sdfwdm 28 | // end_wudfwdm 29 | 30 | typedef STRING OEM_STRING; 31 | typedef PSTRING POEM_STRING; 32 | typedef CONST STRING* PCOEM_STRING; 33 | 34 | // 35 | // CONSTCounted String 36 | // 37 | 38 | typedef struct _CSTRING { 39 | USHORT Length; 40 | USHORT MaximumLength; 41 | CONST char* Buffer; 42 | } CSTRING; 43 | typedef CSTRING* PCSTRING; 44 | #ifndef ANSI_NULL 45 | #define ANSI_NULL ((CHAR)0) 46 | #endif 47 | 48 | // begin_wudfwdm 49 | // begin_sdfwdm 50 | 51 | typedef STRING CANSI_STRING; 52 | typedef PSTRING PCANSI_STRING; 53 | 54 | // 55 | // Unicode strings are counted 16-bit character strings. If they are 56 | // NULL terminated, Length does not include trailing NULL. 57 | // 58 | 59 | typedef struct _UNICODE_STRING { 60 | USHORT Length; 61 | USHORT MaximumLength; 62 | #ifdef MIDL_PASS 63 | [size_is(MaximumLength / 2), length_is((Length) / 2)] USHORT* Buffer; 64 | #else // MIDL_PASS 65 | _Field_size_bytes_part_opt_(MaximumLength, Length) PWCH Buffer; 66 | #endif // MIDL_PASS 67 | } UNICODE_STRING; 68 | typedef UNICODE_STRING* PUNICODE_STRING; 69 | typedef const UNICODE_STRING* PCUNICODE_STRING; 70 | 71 | #ifndef UNICODE_NULL 72 | #define UNICODE_NULL ((WCHAR)0) 73 | #endif 74 | 75 | #if _WIN32_WINNT >= 0x0500 76 | 77 | #ifndef UNICODE_STRING_MAX_BYTES 78 | #define UNICODE_STRING_MAX_BYTES ((USHORT) 65534) // winnt 79 | #endif 80 | #ifndef UNICODE_STRING_MAX_CHARS 81 | #define UNICODE_STRING_MAX_CHARS (32767) // winnt 82 | #endif 83 | 84 | #define DECLARE_CONST_UNICODE_STRING(_var, _string) \ 85 | const WCHAR _var ## _buffer[] = _string; \ 86 | __pragma(warning(push)) \ 87 | __pragma(warning(disable:4221)) __pragma(warning(disable:4204)) \ 88 | const UNICODE_STRING _var = { sizeof(_string) - sizeof(WCHAR), sizeof(_string), (PWCH) _var ## _buffer } \ 89 | __pragma(warning(pop)) 90 | 91 | #define DECLARE_GLOBAL_CONST_UNICODE_STRING(_var, _str) \ 92 | extern const __declspec(selectany) UNICODE_STRING _var = RTL_CONSTANT_STRING(_str) 93 | 94 | #define DECLARE_UNICODE_STRING_SIZE(_var, _size) \ 95 | WCHAR _var ## _buffer[_size]; \ 96 | __pragma(warning(push)) \ 97 | __pragma(warning(disable:4221)) __pragma(warning(disable:4204)) \ 98 | UNICODE_STRING _var = { 0, (_size) * sizeof(WCHAR) , _var ## _buffer } \ 99 | __pragma(warning(pop)) 100 | 101 | #endif // _WIN32_WINNT >= 0x0500 102 | 103 | // 104 | // This is the maximum MaximumLength for a UNICODE_STRING. 105 | // 106 | #ifndef MAX_USTRING 107 | #define MAX_USTRING ( sizeof(WCHAR) * (MAXUSHORT/sizeof(WCHAR)) ) 108 | #endif 109 | 110 | 111 | // 112 | // Balanced tree node (AVL or RB) structure definition. 113 | // 114 | #if defined(_MSC_VER) 115 | #pragma warning(push) 116 | #pragma warning(disable:4214) 117 | #endif 118 | typedef struct _RTL_BALANCED_NODE { 119 | union { 120 | struct _RTL_BALANCED_NODE* Children[2]; 121 | struct { 122 | struct _RTL_BALANCED_NODE* Left; 123 | struct _RTL_BALANCED_NODE* Right; 124 | } DUMMYSTRUCTNAME; 125 | } DUMMYUNIONNAME; 126 | 127 | #define RTL_BALANCED_NODE_RESERVED_PARENT_MASK 3 128 | 129 | union { 130 | UCHAR Red : 1; 131 | UCHAR Balance : 2; 132 | ULONG_PTR ParentValue; 133 | } DUMMYUNIONNAME2; 134 | } RTL_BALANCED_NODE, * PRTL_BALANCED_NODE; 135 | #if defined(_MSC_VER) 136 | #pragma warning(pop) 137 | #endif 138 | 139 | #define RTL_BALANCED_NODE_GET_PARENT_POINTER(Node) \ 140 | ((PRTL_BALANCED_NODE)((Node)->ParentValue & \ 141 | ~RTL_BALANCED_NODE_RESERVED_PARENT_MASK)) 142 | 143 | 144 | typedef struct _STRING32 { 145 | USHORT Length; 146 | USHORT MaximumLength; 147 | ULONG Buffer; 148 | } STRING32; 149 | typedef STRING32* PSTRING32; 150 | 151 | typedef STRING32 UNICODE_STRING32; 152 | typedef UNICODE_STRING32* PUNICODE_STRING32; 153 | 154 | typedef STRING32 ANSI_STRING32; 155 | typedef ANSI_STRING32* PANSI_STRING32; 156 | 157 | 158 | typedef struct _STRING64 { 159 | USHORT Length; 160 | USHORT MaximumLength; 161 | ULONGLONG Buffer; 162 | } STRING64; 163 | typedef STRING64* PSTRING64; 164 | 165 | typedef STRING64 UNICODE_STRING64; 166 | typedef UNICODE_STRING64* PUNICODE_STRING64; 167 | 168 | typedef STRING64 ANSI_STRING64; 169 | typedef ANSI_STRING64* PANSI_STRING64; 170 | 171 | // 172 | // Valid values for the Attributes field 173 | // 174 | 175 | #ifndef OBJ_INHERIT 176 | #define OBJ_INHERIT 0x00000002L 177 | #endif 178 | #ifndef OBJ_PERMANENT 179 | #define OBJ_PERMANENT 0x00000010L 180 | #endif 181 | #ifndef OBJ_EXCLUSIVE 182 | #define OBJ_EXCLUSIVE 0x00000020L 183 | #endif 184 | #ifndef OBJ_CASE_INSENSITIVE 185 | #define OBJ_CASE_INSENSITIVE 0x00000040L 186 | #endif 187 | #ifndef OBJ_OPENIF 188 | #define OBJ_OPENIF 0x00000080L 189 | #endif 190 | #ifndef OBJ_OPENLINK 191 | #define OBJ_OPENLINK 0x00000100L 192 | #endif 193 | #ifndef OBJ_KERNEL_HANDLE 194 | #define OBJ_KERNEL_HANDLE 0x00000200L 195 | #endif 196 | #ifndef OBJ_FORCE_ACCESS_CHECK 197 | #define OBJ_FORCE_ACCESS_CHECK 0x00000400L 198 | #endif 199 | #ifndef OBJ_IGNORE_IMPERSONATED_DEVICEMAP 200 | #define OBJ_IGNORE_IMPERSONATED_DEVICEMAP 0x00000800L 201 | #endif 202 | #ifndef OBJ_DONT_REPARSE 203 | #define OBJ_DONT_REPARSE 0x00001000L 204 | #endif 205 | #ifndef OBJ_VALID_ATTRIBUTES 206 | #define OBJ_VALID_ATTRIBUTES 0x00001FF2L 207 | #endif 208 | 209 | // 210 | // Object Attributes structure 211 | // 212 | 213 | typedef struct _OBJECT_ATTRIBUTES64 { 214 | ULONG Length; 215 | ULONG64 RootDirectory; 216 | ULONG64 ObjectName; 217 | ULONG Attributes; 218 | ULONG64 SecurityDescriptor; 219 | ULONG64 SecurityQualityOfService; 220 | } OBJECT_ATTRIBUTES64; 221 | typedef OBJECT_ATTRIBUTES64* POBJECT_ATTRIBUTES64; 222 | typedef CONST OBJECT_ATTRIBUTES64* PCOBJECT_ATTRIBUTES64; 223 | 224 | typedef struct _OBJECT_ATTRIBUTES32 { 225 | ULONG Length; 226 | ULONG RootDirectory; 227 | ULONG ObjectName; 228 | ULONG Attributes; 229 | ULONG SecurityDescriptor; 230 | ULONG SecurityQualityOfService; 231 | } OBJECT_ATTRIBUTES32; 232 | typedef OBJECT_ATTRIBUTES32* POBJECT_ATTRIBUTES32; 233 | typedef CONST OBJECT_ATTRIBUTES32* PCOBJECT_ATTRIBUTES32; 234 | 235 | 236 | typedef struct _OBJECT_ATTRIBUTES { 237 | ULONG Length; 238 | HANDLE RootDirectory; 239 | PUNICODE_STRING ObjectName; 240 | ULONG Attributes; 241 | PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR 242 | PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE 243 | } OBJECT_ATTRIBUTES; 244 | typedef OBJECT_ATTRIBUTES* POBJECT_ATTRIBUTES; 245 | typedef CONST OBJECT_ATTRIBUTES* PCOBJECT_ATTRIBUTES; 246 | 247 | //++ 248 | // 249 | // VOID 250 | // InitializeObjectAttributes( 251 | // _Out_ POBJECT_ATTRIBUTES p, 252 | // _In_ PUNICODE_STRING n, 253 | // _In_ ULONG a, 254 | // _In_ HANDLE r, 255 | // _In_ PSECURITY_DESCRIPTOR s 256 | // ) 257 | // 258 | //-- 259 | 260 | #define InitializeObjectAttributes( p, n, a, r, s ) { \ 261 | (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \ 262 | (p)->RootDirectory = r; \ 263 | (p)->Attributes = a; \ 264 | (p)->ObjectName = n; \ 265 | (p)->SecurityDescriptor = s; \ 266 | (p)->SecurityQualityOfService = NULL; \ 267 | } 268 | 269 | 270 | // RTL_ to avoid collisions in the global namespace. 271 | // I don't believe there are possible/likely constant RootDirectory 272 | // or SecurityDescriptor values other than NULL, so they are hardcoded. 273 | // As well, the string will generally be const, so we cast that away. 274 | #define RTL_CONSTANT_OBJECT_ATTRIBUTES(n, a) \ 275 | { sizeof(OBJECT_ATTRIBUTES), NULL, RTL_CONST_CAST(PUNICODE_STRING)(n), a, NULL, NULL } 276 | 277 | // This synonym is more appropriate for initializing what isn't actually const. 278 | #define RTL_INIT_OBJECT_ATTRIBUTES(n, a) RTL_CONSTANT_OBJECT_ATTRIBUTES(n, a) 279 | 280 | 281 | #include 282 | 283 | #ifndef __OBJECTID_DEFINED 284 | #define __OBJECTID_DEFINED 285 | 286 | typedef struct _OBJECTID { // size is 20 287 | GUID Lineage; 288 | ULONG Uniquifier; 289 | } OBJECTID; 290 | #endif // !_OBJECTID_DEFINED 291 | 292 | #ifndef MINCHAR 293 | #define MINCHAR 0x80 294 | #endif 295 | #ifndef MAXCHAR 296 | #define MAXCHAR 0x7f 297 | #endif 298 | #ifndef MINSHORT 299 | #define MINSHORT 0x8000 300 | #endif 301 | #ifndef MAXSHORT 302 | #define MAXSHORT 0x7fff 303 | #endif 304 | #ifndef MINLONG 305 | #define MINLONG 0x80000000 306 | #endif 307 | #ifndef MAXLONG 308 | #define MAXLONG 0x7fffffff 309 | #endif 310 | #ifndef MAXUCHAR 311 | #define MAXUCHAR 0xff 312 | #endif 313 | #ifndef MAXUSHORT 314 | #define MAXUSHORT 0xffff 315 | #endif 316 | #ifndef MAXULONG 317 | #define MAXULONG 0xffffffff 318 | #endif 319 | 320 | // 321 | // Determine if an argument is present by testing the value of the pointer 322 | // to the argument value. 323 | // 324 | 325 | #ifndef ARGUMENT_PRESENT 326 | #define ARGUMENT_PRESENT(ArgumentPointer) (\ 327 | (CHAR *)((ULONG_PTR)(ArgumentPointer)) != (CHAR *)(NULL) ) 328 | #endif 329 | 330 | 331 | #define LOW_PRIORITY 0 // Lowest thread priority level 332 | #define LOW_REALTIME_PRIORITY 16 // Lowest realtime priority level 333 | #define HIGH_PRIORITY 31 // Highest thread priority level 334 | #define MAXIMUM_PRIORITY 32 // Number of thread priority levels 335 | 336 | #define MAXIMUM_WAIT_OBJECTS 64 // Maximum number of wait objects 337 | 338 | #define MAXIMUM_SUSPEND_COUNT MAXCHAR // Maximum times thread can be suspended 339 | 340 | // 341 | // Event type 342 | // 343 | 344 | typedef enum _EVENT_TYPE { 345 | NotificationEvent, 346 | SynchronizationEvent 347 | } EVENT_TYPE; 348 | 349 | // 350 | // Timer type 351 | // 352 | 353 | typedef enum _TIMER_TYPE { 354 | NotificationTimer, 355 | SynchronizationTimer 356 | } TIMER_TYPE; 357 | 358 | // 359 | // Wait type 360 | // 361 | 362 | typedef enum _WAIT_TYPE { 363 | WaitAll, 364 | WaitAny, 365 | WaitNotification, 366 | WaitDequeue 367 | } WAIT_TYPE; 368 | 369 | // 370 | // Processor modes. 371 | // 372 | 373 | typedef enum _MODE { 374 | KernelMode, 375 | UserMode, 376 | MaximumMode 377 | } MODE; 378 | 379 | typedef INT8 KPROCESSOR_MODE; 380 | 381 | // 382 | // Define system time structure. 383 | // 384 | 385 | typedef struct _KSYSTEM_TIME { 386 | ULONG LowPart; 387 | LONG High1Time; 388 | LONG High2Time; 389 | } KSYSTEM_TIME, * PKSYSTEM_TIME; 390 | 391 | 392 | // 393 | // Thread priority 394 | // 395 | 396 | typedef LONG KPRIORITY; 397 | 398 | // 399 | // Spin Lock 400 | // 401 | 402 | typedef ULONG_PTR KSPIN_LOCK; 403 | typedef KSPIN_LOCK* PKSPIN_LOCK; 404 | 405 | // 406 | // Update Sequence Number 407 | // 408 | 409 | typedef LONGLONG USN; 410 | 411 | 412 | // 413 | // Client ID 414 | // 415 | 416 | typedef struct _CLIENT_ID { 417 | HANDLE UniqueProcess; 418 | HANDLE UniqueThread; 419 | } CLIENT_ID; 420 | typedef CLIENT_ID* PCLIENT_ID; 421 | 422 | 423 | #ifndef _PHYSICAL_ADDRESS_T 424 | #define _PHYSICAL_ADDRESS_T 425 | 426 | // 427 | // Physical address. 428 | // 429 | 430 | typedef LARGE_INTEGER PHYSICAL_ADDRESS, * PPHYSICAL_ADDRESS; 431 | 432 | #endif // _PHYSICAL_ADDRESS_T 433 | 434 | 435 | // 436 | // Profile source types 437 | // 438 | 439 | typedef enum _KPROFILE_SOURCE { 440 | ProfileTime, 441 | ProfileAlignmentFixup, 442 | ProfileTotalIssues, 443 | ProfilePipelineDry, 444 | ProfileLoadInstructions, 445 | ProfilePipelineFrozen, 446 | ProfileBranchInstructions, 447 | ProfileTotalNonissues, 448 | ProfileDcacheMisses, 449 | ProfileIcacheMisses, 450 | ProfileCacheMisses, 451 | ProfileBranchMispredictions, 452 | ProfileStoreInstructions, 453 | ProfileFpInstructions, 454 | ProfileIntegerInstructions, 455 | Profile2Issue, 456 | Profile3Issue, 457 | Profile4Issue, 458 | ProfileSpecialInstructions, 459 | ProfileTotalCycles, 460 | ProfileIcacheIssues, 461 | ProfileDcacheAccesses, 462 | ProfileMemoryBarrierCycles, 463 | ProfileLoadLinkedIssues, 464 | ProfileMaximum 465 | } KPROFILE_SOURCE; 466 | 467 | #include "ntpsapi.h" 468 | 469 | #endif // _NTAPI_ 470 | -------------------------------------------------------------------------------- /ntpsapi.h: -------------------------------------------------------------------------------- 1 | #ifndef _NTPSAPI_ 2 | #define _NTPSAPI_ 3 | #if _MSC_VER > 1000 4 | #pragma once 5 | #endif 6 | 7 | #if defined(_MSC_VER) 8 | #pragma warning(push) 9 | #pragma warning(disable : 4201) // nonstandard extension used: nameless struct/union 10 | #pragma warning(disable : 4214) // nonstandard extension used: bit field types other than int 11 | #endif // _MSC_VER 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | // 18 | // Process Environment Block and Thread Environment Block 19 | // 20 | 21 | // 22 | // Handle tag bits for Peb Stdio File Handles 23 | // 24 | 25 | #define PEB_STDIO_HANDLE_NATIVE 0 26 | #define PEB_STDIO_HANDLE_SUBSYS 1 27 | #define PEB_STDIO_HANDLE_PM 2 28 | #define PEB_STDIO_HANDLE_RESERVED 3 29 | 30 | #define GDI_HANDLE_BUFFER_SIZE32 34 31 | #define GDI_HANDLE_BUFFER_SIZE64 60 32 | 33 | #if !(defined(_M_AMD64) || defined(__x86_64__)) 34 | #define GDI_HANDLE_BUFFER_SIZE GDI_HANDLE_BUFFER_SIZE32 35 | #else 36 | #define GDI_HANDLE_BUFFER_SIZE GDI_HANDLE_BUFFER_SIZE64 37 | #endif 38 | 39 | typedef ULONG GDI_HANDLE_BUFFER32[GDI_HANDLE_BUFFER_SIZE32]; 40 | typedef ULONG GDI_HANDLE_BUFFER64[GDI_HANDLE_BUFFER_SIZE64]; 41 | typedef ULONG GDI_HANDLE_BUFFER [GDI_HANDLE_BUFFER_SIZE ]; 42 | 43 | #define FOREGROUND_BASE_PRIORITY 9 44 | #define NORMAL_BASE_PRIORITY 8 45 | 46 | typedef struct _PEB_FREE_BLOCK { 47 | struct _PEB_FREE_BLOCK *Next; 48 | ULONG Size; 49 | } PEB_FREE_BLOCK, *PPEB_FREE_BLOCK; 50 | 51 | 52 | #if !defined(CLIENT_ID64_DEFINED) 53 | 54 | typedef struct _CLIENT_ID64 { 55 | ULONG64 UniqueProcess; 56 | ULONG64 UniqueThread; 57 | } CLIENT_ID64; 58 | typedef CLIENT_ID64 *PCLIENT_ID64; 59 | 60 | typedef struct _CLIENT_ID32 { 61 | ULONG UniqueProcess; 62 | ULONG UniqueThread; 63 | } CLIENT_ID32; 64 | typedef CLIENT_ID32 *PCLIENT_ID32; 65 | 66 | #define CLIENT_ID64_DEFINED 67 | #endif 68 | 69 | #ifndef FLS_MAXIMUM_AVAILABLE 70 | #define FLS_MAXIMUM_AVAILABLE 128 71 | #endif 72 | #ifndef TLS_MINIMUM_AVAILABLE 73 | #define TLS_MINIMUM_AVAILABLE 64 74 | #endif 75 | #ifndef TLS_EXPANSION_SLOTS 76 | #define TLS_EXPANSION_SLOTS 1024 77 | #endif 78 | 79 | typedef 80 | VOID 81 | (*PPS_POST_PROCESS_INIT_ROUTINE) ( 82 | VOID 83 | ); 84 | 85 | 86 | // 87 | // Thread Environment Block (and portable part of Thread Information Block) 88 | // 89 | 90 | // 91 | // NT_TIB - Thread Information Block - Portable part. 92 | // 93 | // This is the subsystem portable part of the Thread Information Block. 94 | // It appears as the first part of the TEB for all threads which have 95 | // a user mode component. 96 | // 97 | // This structure MUST MATCH OS/2 V2.0! 98 | // 99 | // There is another, non-portable part of the TIB which is used 100 | // for by subsystems, i.e. Os2Tib for OS/2 threads. SubSystemTib 101 | // points there. 102 | // 103 | // 104 | 105 | #if !defined(_NTDDK_) && !defined(_WINNT_) 106 | 107 | typedef struct _NT_TIB { 108 | struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList; 109 | PVOID StackBase; 110 | PVOID StackLimit; 111 | PVOID SubSystemTib; 112 | union { 113 | PVOID FiberData; 114 | ULONG Version; 115 | }; 116 | PVOID ArbitraryUserPointer; 117 | struct _NT_TIB *Self; 118 | } NT_TIB; 119 | typedef NT_TIB *PNT_TIB; 120 | 121 | // 122 | // 32 and 64 bit specific version for wow64 and the debugger 123 | // 124 | typedef struct _NT_TIB32 { 125 | ULONG ExceptionList; 126 | ULONG StackBase; 127 | ULONG StackLimit; 128 | ULONG SubSystemTib; 129 | union { 130 | ULONG FiberData; 131 | ULONG Version; 132 | }; 133 | ULONG ArbitraryUserPointer; 134 | ULONG Self; 135 | } NT_TIB32, *PNT_TIB32; 136 | 137 | typedef struct _NT_TIB64 { 138 | ULONG64 ExceptionList; 139 | ULONG64 StackBase; 140 | ULONG64 StackLimit; 141 | ULONG64 SubSystemTib; 142 | union { 143 | ULONG64 FiberData; 144 | ULONG Version; 145 | }; 146 | ULONG64 ArbitraryUserPointer; 147 | ULONG64 Self; 148 | } NT_TIB64, *PNT_TIB64; 149 | 150 | #endif // !_NTDDK_ && !_WINNT_ 151 | 152 | 153 | // 154 | // Gdi command batching 155 | // 156 | 157 | #define GDI_BATCH_BUFFER_SIZE 310 158 | 159 | typedef struct _GDI_TEB_BATCH { 160 | ULONG Offset; 161 | ULONG_PTR HDC; 162 | ULONG Buffer[GDI_BATCH_BUFFER_SIZE]; 163 | } GDI_TEB_BATCH,*PGDI_TEB_BATCH; 164 | 165 | typedef struct _GDI_TEB_BATCH64 { 166 | ULONG Offset; 167 | ULONG64 HDC; 168 | ULONG Buffer[GDI_BATCH_BUFFER_SIZE]; 169 | } GDI_TEB_BATCH64, *PGDI_TEB_BATCH64; 170 | 171 | typedef struct _GDI_TEB_BATCH32 { 172 | ULONG Offset; 173 | ULONG HDC; 174 | ULONG Buffer[GDI_BATCH_BUFFER_SIZE]; 175 | } GDI_TEB_BATCH32, *PGDI_TEB_BATCH32; 176 | 177 | // 178 | // Wx86 thread state information 179 | // 180 | 181 | typedef struct _Wx86ThreadState { 182 | ULONG *CallBx86Eip; 183 | PVOID DeallocationCpu; 184 | BOOLEAN UseKnownWx86Dll; 185 | CHAR OleStubInvoked; 186 | } WX86THREAD, *PWX86THREAD; 187 | 188 | // 189 | // WoW64 Process 190 | // 191 | 192 | typedef struct _WOW64_PROCESS { 193 | PVOID Wow64; 194 | } WOW64_PROCESS, *PWOW64_PROCESS; 195 | 196 | // 197 | // TEB - The thread environment block 198 | // 199 | 200 | #define STATIC_UNICODE_BUFFER_LENGTH 261 201 | #define WIN32_CLIENT_INFO_LENGTH 62 202 | 203 | #define WIN32_CLIENT_INFO_SPIN_COUNT 1 204 | 205 | typedef PVOID* PPVOID; 206 | 207 | #include "pebteb.h" 208 | 209 | #define TYPE32(x) ULONG 210 | #define TYPE64(x) ULONG64 211 | 212 | #define PEBTEB_BITS 32 213 | 214 | #include "pebteb.h" 215 | 216 | #undef PEBTEB_BITS 217 | 218 | #define PEBTEB_BITS 64 219 | 220 | #include "pebteb.h" 221 | 222 | #undef PEBTEB_BITS 223 | 224 | 225 | typedef struct _INITIAL_TEB { 226 | struct { 227 | PVOID OldStackBase; 228 | PVOID OldStackLimit; 229 | } OldInitialTeb; 230 | PVOID StackBase; 231 | PVOID StackLimit; 232 | PVOID StackAllocationBase; 233 | } INITIAL_TEB, *PINITIAL_TEB; 234 | 235 | 236 | #define PROCESS_PRIORITY_CLASS_UNKNOWN 0 237 | #define PROCESS_PRIORITY_CLASS_IDLE 1 238 | #define PROCESS_PRIORITY_CLASS_NORMAL 2 239 | #define PROCESS_PRIORITY_CLASS_HIGH 3 240 | #define PROCESS_PRIORITY_CLASS_REALTIME 4 241 | #define PROCESS_PRIORITY_CLASS_BELOW_NORMAL 5 242 | #define PROCESS_PRIORITY_CLASS_ABOVE_NORMAL 6 243 | 244 | typedef struct _PROCESS_PRIORITY_CLASS { 245 | BOOLEAN Foreground; 246 | UINT8 PriorityClass; 247 | } PROCESS_PRIORITY_CLASS, * PPROCESS_PRIORITY_CLASS; 248 | 249 | typedef struct _PROCESS_FOREGROUND_BACKGROUND { 250 | BOOLEAN Foreground; 251 | } PROCESS_FOREGROUND_BACKGROUND, * PPROCESS_FOREGROUND_BACKGROUND; 252 | 253 | // 254 | // Define process debug flags 255 | // 256 | #define PROCESS_DEBUG_INHERIT 0x00000001 257 | 258 | #if !defined(_NTDDK_) 259 | 260 | // 261 | // Process Information Classes 262 | // 263 | 264 | typedef enum _PROCESSINFOCLASS { 265 | ProcessBasicInformation, // q: PROCESS_BASIC_INFORMATION, PROCESS_EXTENDED_BASIC_INFORMATION 266 | ProcessQuotaLimits, // qs: QUOTA_LIMITS, QUOTA_LIMITS_EX 267 | ProcessIoCounters, // q: IO_COUNTERS 268 | ProcessVmCounters, // q: VM_COUNTERS, VM_COUNTERS_EX, VM_COUNTERS_EX2 269 | ProcessTimes, // q: KERNEL_USER_TIMES 270 | ProcessBasePriority, // s: KPRIORITY 271 | ProcessRaisePriority, // s: ULONG 272 | ProcessDebugPort, // q: HANDLE 273 | ProcessExceptionPort, // s: PROCESS_EXCEPTION_PORT 274 | ProcessAccessToken, // s: PROCESS_ACCESS_TOKEN 275 | ProcessLdtInformation, // qs: PROCESS_LDT_INFORMATION // 10 276 | ProcessLdtSize, // s: PROCESS_LDT_SIZE 277 | ProcessDefaultHardErrorMode, // qs: ULONG 278 | ProcessIoPortHandlers, // (kernel-mode only) 279 | ProcessPooledUsageAndLimits, // q: POOLED_USAGE_AND_LIMITS 280 | ProcessWorkingSetWatch, // q: PROCESS_WS_WATCH_INFORMATION[]; s: void 281 | ProcessUserModeIOPL, 282 | ProcessEnableAlignmentFaultFixup, // s: BOOLEAN 283 | ProcessPriorityClass, // qs: PROCESS_PRIORITY_CLASS 284 | ProcessWx86Information, 285 | ProcessHandleCount, // q: ULONG, PROCESS_HANDLE_INFORMATION // 20 286 | ProcessAffinityMask, // s: KAFFINITY 287 | ProcessPriorityBoost, // qs: ULONG 288 | ProcessDeviceMap, // qs: PROCESS_DEVICEMAP_INFORMATION, PROCESS_DEVICEMAP_INFORMATION_EX 289 | ProcessSessionInformation, // q: PROCESS_SESSION_INFORMATION 290 | ProcessForegroundInformation, // s: PROCESS_FOREGROUND_BACKGROUND 291 | ProcessWow64Information, // q: ULONG_PTR 292 | ProcessImageFileName, // q: UNICODE_STRING 293 | ProcessLUIDDeviceMapsEnabled, // q: ULONG 294 | ProcessBreakOnTermination, // qs: ULONG 295 | ProcessDebugObjectHandle, // q: HANDLE // 30 296 | ProcessDebugFlags, // qs: ULONG 297 | ProcessHandleTracing, // q: PROCESS_HANDLE_TRACING_QUERY; s: size 0 disables, otherwise enables 298 | ProcessIoPriority, // qs: IO_PRIORITY_HINT 299 | ProcessExecuteFlags, // qs: ULONG 300 | ProcessResourceManagement, // ProcessTlsInformation // PROCESS_TLS_INFORMATION 301 | ProcessCookie, // q: ULONG 302 | ProcessImageInformation, // q: SECTION_IMAGE_INFORMATION 303 | ProcessCycleTime, // q: PROCESS_CYCLE_TIME_INFORMATION // since VISTA 304 | ProcessPagePriority, // q: PAGE_PRIORITY_INFORMATION 305 | ProcessInstrumentationCallback, // qs: PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION // 40 306 | ProcessThreadStackAllocation, // s: PROCESS_STACK_ALLOCATION_INFORMATION, PROCESS_STACK_ALLOCATION_INFORMATION_EX 307 | ProcessWorkingSetWatchEx, // q: PROCESS_WS_WATCH_INFORMATION_EX[] 308 | ProcessImageFileNameWin32, // q: UNICODE_STRING 309 | ProcessImageFileMapping, // q: HANDLE (input) 310 | ProcessAffinityUpdateMode, // qs: PROCESS_AFFINITY_UPDATE_MODE 311 | ProcessMemoryAllocationMode, // qs: PROCESS_MEMORY_ALLOCATION_MODE 312 | ProcessGroupInformation, // q: USHORT[] 313 | ProcessTokenVirtualizationEnabled, // s: ULONG 314 | ProcessConsoleHostProcess, // q: ULONG_PTR // ProcessOwnerInformation 315 | ProcessWindowInformation, // q: PROCESS_WINDOW_INFORMATION // 50 316 | ProcessHandleInformation, // q: PROCESS_HANDLE_SNAPSHOT_INFORMATION // since WIN8 317 | ProcessMitigationPolicy, // s: PROCESS_MITIGATION_POLICY_INFORMATION 318 | ProcessDynamicFunctionTableInformation, 319 | ProcessHandleCheckingMode, 320 | ProcessKeepAliveCount, // q: PROCESS_KEEPALIVE_COUNT_INFORMATION 321 | ProcessRevokeFileHandles, // s: PROCESS_REVOKE_FILE_HANDLES_INFORMATION 322 | ProcessWorkingSetControl, // s: PROCESS_WORKING_SET_CONTROL 323 | ProcessHandleTable, // since WINBLUE 324 | ProcessCheckStackExtentsMode, 325 | ProcessCommandLineInformation, // q: UNICODE_STRING // 60 326 | ProcessProtectionInformation, // q: PS_PROTECTION 327 | ProcessMemoryExhaustion, // PROCESS_MEMORY_EXHAUSTION_INFO // since THRESHOLD 328 | ProcessFaultInformation, // PROCESS_FAULT_INFORMATION 329 | ProcessTelemetryIdInformation, // PROCESS_TELEMETRY_ID_INFORMATION 330 | ProcessCommitReleaseInformation, // PROCESS_COMMIT_RELEASE_INFORMATION 331 | ProcessDefaultCpuSetsInformation, 332 | ProcessAllowedCpuSetsInformation, 333 | ProcessSubsystemProcess, 334 | ProcessJobMemoryInformation, // PROCESS_JOB_MEMORY_INFO 335 | ProcessInPrivate, // since THRESHOLD2 // 70 336 | ProcessRaiseUMExceptionOnInvalidHandleClose, 337 | ProcessIumChallengeResponse, 338 | ProcessChildProcessInformation, // PROCESS_CHILD_PROCESS_INFORMATION 339 | ProcessHighGraphicsPriorityInformation, 340 | ProcessSubsystemInformation, // q: SUBSYSTEM_INFORMATION_TYPE // since REDSTONE2 341 | ProcessEnergyValues, // PROCESS_ENERGY_VALUES, PROCESS_EXTENDED_ENERGY_VALUES 342 | ProcessActivityThrottleState, // PROCESS_ACTIVITY_THROTTLE_STATE 343 | ProcessActivityThrottlePolicy, // PROCESS_ACTIVITY_THROTTLE_POLICY 344 | ProcessWin32kSyscallFilterInformation, 345 | ProcessDisableSystemAllowedCpuSets, 346 | ProcessWakeInformation, // PROCESS_WAKE_INFORMATION 347 | ProcessEnergyTrackingState, // PROCESS_ENERGY_TRACKING_STATE 348 | ProcessManageWritesToExecutableMemory, // MANAGE_WRITES_TO_EXECUTABLE_MEMORY // since REDSTONE3 349 | ProcessCaptureTrustletLiveDump, 350 | ProcessTelemetryCoverage, 351 | ProcessEnclaveInformation, 352 | ProcessEnableReadWriteVmLogging, // PROCESS_READWRITEVM_LOGGING_INFORMATION 353 | ProcessUptimeInformation, // PROCESS_UPTIME_INFORMATION 354 | ProcessImageSection, 355 | ProcessDebugAuthInformation, // since REDSTONE4 356 | ProcessSystemResourceManagement, // PROCESS_SYSTEM_RESOURCE_MANAGEMENT 357 | ProcessSequenceNumber, // q: ULONGLONG 358 | MaxProcessInfoClass // MaxProcessInfoClass should always be the last enum 359 | } PROCESSINFOCLASS; 360 | 361 | // 362 | // Thread Information Classes 363 | // 364 | 365 | typedef enum _THREADINFOCLASS { 366 | ThreadBasicInformation, // q: THREAD_BASIC_INFORMATION 367 | ThreadTimes, // q: KERNEL_USER_TIMES 368 | ThreadPriority, // s: KPRIORITY 369 | ThreadBasePriority, // s: LONG 370 | ThreadAffinityMask, // s: KAFFINITY 371 | ThreadImpersonationToken, // s: HANDLE 372 | ThreadDescriptorTableEntry, // q: DESCRIPTOR_TABLE_ENTRY (or WOW64_DESCRIPTOR_TABLE_ENTRY) 373 | ThreadEnableAlignmentFaultFixup, // s: BOOLEAN 374 | ThreadEventPair, 375 | ThreadQuerySetWin32StartAddress, // q: PVOID 376 | ThreadZeroTlsCell, // 10 377 | ThreadPerformanceCount, // q: LARGE_INTEGER 378 | ThreadAmILastThread, // q: ULONG 379 | ThreadIdealProcessor, // s: ULONG 380 | ThreadPriorityBoost, // qs: ULONG 381 | ThreadSetTlsArrayAddress, 382 | ThreadIsIoPending, // q: ULONG 383 | ThreadHideFromDebugger, // s: void 384 | ThreadBreakOnTermination, // qs: ULONG 385 | ThreadSwitchLegacyState, 386 | ThreadIsTerminated, // q: ULONG // 20 387 | ThreadLastSystemCall, // q: THREAD_LAST_SYSCALL_INFORMATION 388 | ThreadIoPriority, // qs: IO_PRIORITY_HINT 389 | ThreadCycleTime, // q: THREAD_CYCLE_TIME_INFORMATION 390 | ThreadPagePriority, // q: ULONG 391 | ThreadActualBasePriority, 392 | ThreadTebInformation, // q: THREAD_TEB_INFORMATION (requires THREAD_GET_CONTEXT + THREAD_SET_CONTEXT) 393 | ThreadCSwitchMon, 394 | ThreadCSwitchPmu, 395 | ThreadWow64Context, // q: WOW64_CONTEXT 396 | ThreadGroupInformation, // q: GROUP_AFFINITY // 30 397 | ThreadUmsInformation, // q: THREAD_UMS_INFORMATION 398 | ThreadCounterProfiling, 399 | ThreadIdealProcessorEx, // q: PROCESSOR_NUMBER 400 | ThreadCpuAccountingInformation, // since WIN8 401 | ThreadSuspendCount, // since WINBLUE 402 | ThreadHeterogeneousCpuPolicy, // q: KHETERO_CPU_POLICY // since THRESHOLD 403 | ThreadContainerId, // q: GUID 404 | ThreadNameInformation, // qs: THREAD_NAME_INFORMATION 405 | ThreadSelectedCpuSets, 406 | ThreadSystemThreadInformation, // q: SYSTEM_THREAD_INFORMATION // 40 407 | ThreadActualGroupAffinity, // since THRESHOLD2 408 | ThreadDynamicCodePolicyInfo, 409 | ThreadExplicitCaseSensitivity, 410 | ThreadWorkOnBehalfTicket, 411 | ThreadSubsystemInformation, // q: SUBSYSTEM_INFORMATION_TYPE // since REDSTONE2 412 | ThreadDbgkWerReportActive, 413 | ThreadAttachContainer, 414 | ThreadManageWritesToExecutableMemory, // MANAGE_WRITES_TO_EXECUTABLE_MEMORY // since REDSTONE3 415 | ThreadPowerThrottlingState, // THREAD_POWER_THROTTLING_STATE 416 | MaxThreadInfoClass 417 | } THREADINFOCLASS; 418 | 419 | // Use with both ProcessPagePriority and ThreadPagePriority 420 | typedef struct _PAGE_PRIORITY_INFORMATION { 421 | ULONG PagePriority; 422 | } PAGE_PRIORITY_INFORMATION, * PPAGE_PRIORITY_INFORMATION; 423 | 424 | #endif // !_NTDDK_ 425 | 426 | #define PROCESS_PRIORITY_SEPARATION_MASK 0x00000003 427 | #define PROCESS_PRIORITY_SEPARATION_MAX 0x00000002 428 | #define PROCESS_QUANTUM_VARIABLE_MASK 0x0000000c 429 | #define PROCESS_QUANTUM_VARIABLE_DEF 0x00000000 430 | #define PROCESS_QUANTUM_VARIABLE_VALUE 0x00000004 431 | #define PROCESS_QUANTUM_FIXED_VALUE 0x00000008 432 | #define PROCESS_QUANTUM_LONG_MASK 0x00000030 433 | #define PROCESS_QUANTUM_LONG_DEF 0x00000000 434 | #define PROCESS_QUANTUM_LONG_VALUE 0x00000010 435 | #define PROCESS_QUANTUM_SHORT_VALUE 0x00000020 436 | 437 | 438 | #define PROCESS_HARDERROR_ALIGNMENT_BIT 0x0004 // from winbase.h, but not tagged 439 | #if defined(_M_AMD64) || defined(__x86_64__) 440 | #define PROCESS_HARDERROR_DEFAULT (1 | PROCESS_HARDERROR_ALIGNMENT_BIT) 441 | #else 442 | #define PROCESS_HARDERROR_DEFAULT 1 443 | #endif 444 | 445 | // 446 | // thread base priority ranges 447 | // 448 | #define THREAD_BASE_PRIORITY_LOWRT 15 // value that gets a thread to LowRealtime-1 449 | #define THREAD_BASE_PRIORITY_MAX 2 // maximum thread base priority boost 450 | #define THREAD_BASE_PRIORITY_MIN (-2) // minimum thread base priority boost 451 | #define THREAD_BASE_PRIORITY_IDLE (-15) // value that gets a thread to idle 452 | 453 | 454 | // 455 | // Process Information Structures 456 | // 457 | 458 | 459 | #if !defined(_NTDDK_) 460 | 461 | // 462 | // PageFaultHistory Information 463 | // NtQueryInformationProcess using ProcessWorkingSetWatch 464 | // 465 | typedef struct _PROCESS_WS_WATCH_INFORMATION { 466 | PVOID FaultingPc; 467 | PVOID FaultingVa; 468 | } PROCESS_WS_WATCH_INFORMATION, * PPROCESS_WS_WATCH_INFORMATION; 469 | 470 | // 471 | // Basic Process Information 472 | // NtQueryInformationProcess using ProcessBasicInfo 473 | // 474 | typedef struct _PROCESS_BASIC_INFORMATION { 475 | NTSTATUS ExitStatus; 476 | PPEB PebBaseAddress; 477 | ULONG_PTR AffinityMask; 478 | KPRIORITY BasePriority; 479 | HANDLE UniqueProcessId; 480 | HANDLE InheritedFromUniqueProcessId; 481 | } PROCESS_BASIC_INFORMATION, * PPROCESS_BASIC_INFORMATION; 482 | 483 | typedef struct _PROCESS_BASIC_INFORMATION64 { 484 | NTSTATUS ExitStatus; 485 | ULONG Pad1; 486 | ULONG64 PebBaseAddress; 487 | ULONG64 AffinityMask; 488 | KPRIORITY BasePriority; 489 | ULONG Pad2; 490 | ULONG64 UniqueProcessId; 491 | ULONG64 InheritedFromUniqueProcessId; 492 | } PROCESS_BASIC_INFORMATION64; 493 | typedef PROCESS_BASIC_INFORMATION64* PPROCESS_BASIC_INFORMATION64; 494 | 495 | typedef struct _PROCESS_EXTENDED_BASIC_INFORMATION { 496 | SIZE_T Size; // set to sizeof structure on input 497 | PROCESS_BASIC_INFORMATION BasicInfo; 498 | union { 499 | ULONG Flags; 500 | struct { 501 | ULONG IsProtectedProcess : 1; 502 | ULONG IsWow64Process : 1; 503 | ULONG IsProcessDeleting : 1; 504 | ULONG IsCrossSessionCreate : 1; 505 | ULONG IsFrozen : 1; 506 | ULONG IsBackground : 1; 507 | ULONG IsStronglyNamed : 1; 508 | ULONG IsSecureProcess : 1; 509 | ULONG IsSubsystemProcess : 1; 510 | ULONG SpareBits : 23; 511 | }; 512 | }; 513 | } PROCESS_EXTENDED_BASIC_INFORMATION, * PPROCESS_EXTENDED_BASIC_INFORMATION; 514 | 515 | // 516 | // Process Device Map information 517 | // NtQueryInformationProcess using ProcessDeviceMap 518 | // NtSetInformationProcess using ProcessDeviceMap 519 | // 520 | 521 | typedef struct _PROCESS_DEVICEMAP_INFORMATION { 522 | union { 523 | struct { 524 | HANDLE DirectoryHandle; 525 | } Set; 526 | struct { 527 | ULONG DriveMap; 528 | UINT8 DriveType[32]; 529 | } Query; 530 | } DUMMYUNIONNAME; 531 | } PROCESS_DEVICEMAP_INFORMATION, * PPROCESS_DEVICEMAP_INFORMATION; 532 | 533 | typedef struct _PROCESS_DEVICEMAP_INFORMATION_EX { 534 | union { 535 | struct { 536 | HANDLE DirectoryHandle; 537 | } Set; 538 | struct { 539 | ULONG DriveMap; 540 | UINT8 DriveType[32]; 541 | } Query; 542 | } DUMMYUNIONNAME; 543 | ULONG Flags; // specifies that the query type 544 | } PROCESS_DEVICEMAP_INFORMATION_EX, * PPROCESS_DEVICEMAP_INFORMATION_EX; 545 | 546 | // 547 | // PROCESS_DEVICEMAP_INFORMATION_EX flags 548 | // 549 | #define PROCESS_LUID_DOSDEVICES_ONLY 0x00000001 550 | 551 | // 552 | // Multi-User Session specific Process Information 553 | // NtQueryInformationProcess using ProcessSessionInformation 554 | // 555 | 556 | typedef struct _PROCESS_SESSION_INFORMATION { 557 | ULONG SessionId; 558 | } PROCESS_SESSION_INFORMATION, * PPROCESS_SESSION_INFORMATION; 559 | 560 | typedef struct _PROCESS_HANDLE_TRACING_ENABLE { 561 | ULONG Flags; 562 | } PROCESS_HANDLE_TRACING_ENABLE, * PPROCESS_HANDLE_TRACING_ENABLE; 563 | 564 | typedef struct _PROCESS_HANDLE_TRACING_ENABLE_EX { 565 | ULONG Flags; 566 | ULONG TotalSlots; 567 | } PROCESS_HANDLE_TRACING_ENABLE_EX, * PPROCESS_HANDLE_TRACING_ENABLE_EX; 568 | 569 | #define PROCESS_HANDLE_EXCEPTIONS_ENABLED 0x00000001 570 | 571 | #define PROCESS_HANDLE_RAISE_UM_EXCEPTION_ON_INVALID_HANDLE_CLOSE_DISABLED 0x00000000 572 | #define PROCESS_HANDLE_RAISE_UM_EXCEPTION_ON_INVALID_HANDLE_CLOSE_ENABLED 0x00000001 573 | 574 | #define PROCESS_HANDLE_TRACING_MAX_STACKS 16 575 | 576 | typedef struct _PROCESS_HANDLE_TRACING_ENTRY { 577 | HANDLE Handle; 578 | struct _CLIENT_ID ClientId; 579 | ULONG Type; 580 | PVOID Stacks[PROCESS_HANDLE_TRACING_MAX_STACKS]; 581 | } PROCESS_HANDLE_TRACING_ENTRY, * PPROCESS_HANDLE_TRACING_ENTRY; 582 | 583 | typedef struct _PROCESS_HANDLE_TRACING_QUERY { 584 | HANDLE Handle; 585 | ULONG TotalTraces; 586 | PROCESS_HANDLE_TRACING_ENTRY HandleTrace[1]; 587 | } PROCESS_HANDLE_TRACING_QUERY, * PPROCESS_HANDLE_TRACING_QUERY; 588 | 589 | #if !defined(_WINNT_) 590 | 591 | // 592 | // Process Quotas 593 | // NtQueryInformationProcess using ProcessQuotaLimits 594 | // NtQueryInformationProcess using ProcessPooledQuotaLimits 595 | // NtSetInformationProcess using ProcessQuotaLimits 596 | // 597 | 598 | typedef struct _QUOTA_LIMITS { 599 | SIZE_T PagedPoolLimit; 600 | SIZE_T NonPagedPoolLimit; 601 | SIZE_T MinimumWorkingSetSize; 602 | SIZE_T MaximumWorkingSetSize; 603 | SIZE_T PagefileLimit; 604 | LARGE_INTEGER TimeLimit; 605 | } QUOTA_LIMITS, * PQUOTA_LIMITS; 606 | 607 | 608 | #define QUOTA_LIMITS_HARDWS_MIN_ENABLE 0x00000001 609 | #define QUOTA_LIMITS_HARDWS_MIN_DISABLE 0x00000002 610 | #define QUOTA_LIMITS_HARDWS_MAX_ENABLE 0x00000004 611 | #define QUOTA_LIMITS_HARDWS_MAX_DISABLE 0x00000008 612 | #define QUOTA_LIMITS_USE_DEFAULT_LIMITS 0x00000010 613 | 614 | typedef union _RATE_QUOTA_LIMIT { 615 | ULONG RateData; 616 | struct { 617 | ULONG RatePercent : 7; 618 | ULONG Reserved0 : 25; 619 | } DUMMYSTRUCTNAME; 620 | } RATE_QUOTA_LIMIT, * PRATE_QUOTA_LIMIT; 621 | 622 | typedef struct _QUOTA_LIMITS_EX { 623 | SIZE_T PagedPoolLimit; 624 | SIZE_T NonPagedPoolLimit; 625 | SIZE_T MinimumWorkingSetSize; 626 | SIZE_T MaximumWorkingSetSize; 627 | SIZE_T PagefileLimit; // Limit expressed in pages 628 | LARGE_INTEGER TimeLimit; 629 | SIZE_T WorkingSetLimit; // Limit expressed in pages 630 | SIZE_T Reserved2; 631 | SIZE_T Reserved3; 632 | SIZE_T Reserved4; 633 | ULONG Flags; 634 | RATE_QUOTA_LIMIT CpuRateLimit; 635 | } QUOTA_LIMITS_EX, * PQUOTA_LIMITS_EX; 636 | 637 | // 638 | // Process I/O Counters 639 | // NtQueryInformationProcess using ProcessIoCounters 640 | // 641 | 642 | typedef struct _IO_COUNTERS { 643 | ULONG64 ReadOperationCount; 644 | ULONG64 WriteOperationCount; 645 | ULONG64 OtherOperationCount; 646 | ULONG64 ReadTransferCount; 647 | ULONG64 WriteTransferCount; 648 | ULONG64 OtherTransferCount; 649 | } IO_COUNTERS; 650 | typedef IO_COUNTERS* PIO_COUNTERS; 651 | 652 | #endif // !_WINNT_ 653 | 654 | // 655 | // Process Virtual Memory Counters 656 | // NtQueryInformationProcess using ProcessVmCounters 657 | // 658 | 659 | typedef struct _VM_COUNTERS { 660 | SIZE_T PeakVirtualSize; 661 | SIZE_T VirtualSize; 662 | ULONG PageFaultCount; 663 | SIZE_T PeakWorkingSetSize; 664 | SIZE_T WorkingSetSize; 665 | SIZE_T QuotaPeakPagedPoolUsage; 666 | SIZE_T QuotaPagedPoolUsage; 667 | SIZE_T QuotaPeakNonPagedPoolUsage; 668 | SIZE_T QuotaNonPagedPoolUsage; 669 | SIZE_T PagefileUsage; 670 | SIZE_T PeakPagefileUsage; 671 | } VM_COUNTERS, * PVM_COUNTERS; 672 | 673 | typedef struct _VM_COUNTERS_EX { 674 | SIZE_T PeakVirtualSize; 675 | SIZE_T VirtualSize; 676 | ULONG PageFaultCount; 677 | SIZE_T PeakWorkingSetSize; 678 | SIZE_T WorkingSetSize; 679 | SIZE_T QuotaPeakPagedPoolUsage; 680 | SIZE_T QuotaPagedPoolUsage; 681 | SIZE_T QuotaPeakNonPagedPoolUsage; 682 | SIZE_T QuotaNonPagedPoolUsage; 683 | SIZE_T PagefileUsage; 684 | SIZE_T PeakPagefileUsage; 685 | SIZE_T PrivateUsage; 686 | } VM_COUNTERS_EX, * PVM_COUNTERS_EX; 687 | 688 | typedef struct _VM_COUNTERS_EX2 { 689 | VM_COUNTERS_EX CountersEx; 690 | SIZE_T PrivateWorkingSetSize; 691 | SIZE_T SharedCommitUsage; 692 | } VM_COUNTERS_EX2, * PVM_COUNTERS_EX2; 693 | 694 | 695 | #if !defined(_WINNT_) 696 | 697 | #define MAX_HW_COUNTERS 16 698 | #define THREAD_PROFILING_FLAG_DISPATCH 0x00000001 699 | 700 | typedef enum _HARDWARE_COUNTER_TYPE { 701 | PMCCounter, 702 | MaxHardwareCounterType 703 | } HARDWARE_COUNTER_TYPE, * PHARDWARE_COUNTER_TYPE; 704 | 705 | #endif // !_WINNT_ 706 | 707 | typedef struct _HARDWARE_COUNTER { 708 | HARDWARE_COUNTER_TYPE Type; 709 | ULONG Reserved; 710 | ULONG Index; 711 | } HARDWARE_COUNTER, * PHARDWARE_COUNTER; 712 | 713 | 714 | #if !defined(_WINNT_) 715 | 716 | // 717 | // Process mitigation policy information 718 | // NtSetInformationProcess using ProcessMitigationPolicy 719 | // 720 | 721 | typedef enum _PROCESS_MITIGATION_POLICY { 722 | ProcessDEPPolicy, 723 | ProcessASLRPolicy, 724 | ProcessDynamicCodePolicy, 725 | ProcessStrictHandleCheckPolicy, 726 | ProcessSystemCallDisablePolicy, 727 | ProcessMitigationOptionsMask, 728 | ProcessExtensionPointDisablePolicy, 729 | ProcessControlFlowGuardPolicy, 730 | ProcessSignaturePolicy, 731 | ProcessFontDisablePolicy, 732 | ProcessImageLoadPolicy, 733 | ProcessSystemCallFilterPolicy, 734 | ProcessPayloadRestrictionPolicy, 735 | ProcessChildProcessPolicy, 736 | MaxProcessMitigationPolicy 737 | } PROCESS_MITIGATION_POLICY, * PPROCESS_MITIGATION_POLICY; 738 | 739 | // 740 | // N.B. High entropy mode is read only and can only be set at creation time 741 | // and not via the ProcessMitigationPolicy APIs. 742 | // 743 | typedef struct _PROCESS_MITIGATION_ASLR_POLICY { 744 | union { 745 | ULONG Flags; 746 | struct { 747 | ULONG EnableBottomUpRandomization : 1; 748 | ULONG EnableForceRelocateImages : 1; 749 | ULONG EnableHighEntropy : 1; 750 | ULONG DisallowStrippedImages : 1; 751 | ULONG ReservedFlags : 28; 752 | } DUMMYSTRUCTNAME; 753 | } DUMMYUNIONNAME; 754 | } PROCESS_MITIGATION_ASLR_POLICY, * PPROCESS_MITIGATION_ASLR_POLICY; 755 | 756 | typedef struct _PROCESS_MITIGATION_DEP_POLICY { 757 | union { 758 | ULONG Flags; 759 | struct { 760 | ULONG Enable : 1; 761 | ULONG DisableAtlThunkEmulation : 1; 762 | ULONG ReservedFlags : 30; 763 | } DUMMYSTRUCTNAME; 764 | } DUMMYUNIONNAME; 765 | BOOLEAN Permanent; 766 | } PROCESS_MITIGATION_DEP_POLICY, * PPROCESS_MITIGATION_DEP_POLICY; 767 | 768 | typedef struct _PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY { 769 | union { 770 | ULONG Flags; 771 | struct { 772 | ULONG RaiseExceptionOnInvalidHandleReference : 1; 773 | ULONG HandleExceptionsPermanentlyEnabled : 1; 774 | ULONG ReservedFlags : 30; 775 | } DUMMYSTRUCTNAME; 776 | } DUMMYUNIONNAME; 777 | } PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY, * PPROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY; 778 | 779 | typedef struct _PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY { 780 | union { 781 | ULONG Flags; 782 | struct { 783 | ULONG DisallowWin32kSystemCalls : 1; 784 | ULONG AuditDisallowWin32kSystemCalls : 1; 785 | ULONG ReservedFlags : 30; 786 | } DUMMYSTRUCTNAME; 787 | } DUMMYUNIONNAME; 788 | } PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY, * PPROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY; 789 | 790 | typedef struct _PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY { 791 | union { 792 | ULONG Flags; 793 | struct { 794 | ULONG DisableExtensionPoints : 1; 795 | ULONG ReservedFlags : 31; 796 | } DUMMYSTRUCTNAME; 797 | } DUMMYUNIONNAME; 798 | } PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY, * PPROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY; 799 | 800 | typedef struct _PROCESS_MITIGATION_DYNAMIC_CODE_POLICY { 801 | union { 802 | ULONG Flags; 803 | struct { 804 | ULONG ProhibitDynamicCode : 1; 805 | ULONG AllowThreadOptOut : 1; 806 | ULONG AllowRemoteDowngrade : 1; 807 | ULONG AuditProhibitDynamicCode : 1; 808 | ULONG ReservedFlags : 28; 809 | } DUMMYSTRUCTNAME; 810 | } DUMMYUNIONNAME; 811 | } PROCESS_MITIGATION_DYNAMIC_CODE_POLICY, * PPROCESS_MITIGATION_DYNAMIC_CODE_POLICY; 812 | typedef struct _PROCESS_MITIGATION_CONTROL_FLOW_GUARD_POLICY { 813 | union { 814 | ULONG Flags; 815 | struct { 816 | ULONG EnableControlFlowGuard : 1; 817 | ULONG EnableExportSuppression : 1; 818 | ULONG StrictMode : 1; 819 | ULONG ReservedFlags : 29; 820 | } DUMMYSTRUCTNAME; 821 | } DUMMYUNIONNAME; 822 | } PROCESS_MITIGATION_CONTROL_FLOW_GUARD_POLICY, * PPROCESS_MITIGATION_CONTROL_FLOW_GUARD_POLICY; 823 | 824 | typedef struct _PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY { 825 | union { 826 | ULONG Flags; 827 | struct { 828 | ULONG MicrosoftSignedOnly : 1; 829 | ULONG StoreSignedOnly : 1; 830 | ULONG MitigationOptIn : 1; 831 | ULONG AuditMicrosoftSignedOnly : 1; 832 | ULONG AuditStoreSignedOnly : 1; 833 | ULONG ReservedFlags : 27; 834 | } DUMMYSTRUCTNAME; 835 | } DUMMYUNIONNAME; 836 | } PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY, * PPROCESS_MITIGATION_BINARY_SIGNATURE_POLICY; 837 | 838 | typedef struct _PROCESS_MITIGATION_FONT_DISABLE_POLICY { 839 | union { 840 | ULONG Flags; 841 | struct { 842 | ULONG DisableNonSystemFonts : 1; 843 | ULONG AuditNonSystemFontLoading : 1; 844 | ULONG ReservedFlags : 30; 845 | } DUMMYSTRUCTNAME; 846 | } DUMMYUNIONNAME; 847 | } PROCESS_MITIGATION_FONT_DISABLE_POLICY, * PPROCESS_MITIGATION_FONT_DISABLE_POLICY; 848 | 849 | typedef struct _PROCESS_MITIGATION_IMAGE_LOAD_POLICY { 850 | union { 851 | ULONG Flags; 852 | struct { 853 | ULONG NoRemoteImages : 1; 854 | ULONG NoLowMandatoryLabelImages : 1; 855 | ULONG PreferSystem32Images : 1; 856 | ULONG AuditNoRemoteImages : 1; 857 | ULONG AuditNoLowMandatoryLabelImages : 1; 858 | ULONG ReservedFlags : 27; 859 | } DUMMYSTRUCTNAME; 860 | } DUMMYUNIONNAME; 861 | } PROCESS_MITIGATION_IMAGE_LOAD_POLICY, * PPROCESS_MITIGATION_IMAGE_LOAD_POLICY; 862 | 863 | typedef struct _PROCESS_MITIGATION_SYSTEM_CALL_FILTER_POLICY { 864 | union { 865 | ULONG Flags; 866 | struct { 867 | ULONG FilterId : 4; 868 | ULONG ReservedFlags : 28; 869 | } DUMMYSTRUCTNAME; 870 | } DUMMYUNIONNAME; 871 | } PROCESS_MITIGATION_SYSTEM_CALL_FILTER_POLICY, * PPROCESS_MITIGATION_SYSTEM_CALL_FILTER_POLICY; 872 | 873 | typedef struct _PROCESS_MITIGATION_PAYLOAD_RESTRICTION_POLICY { 874 | union { 875 | ULONG Flags; 876 | struct { 877 | ULONG EnableExportAddressFilter : 1; 878 | ULONG AuditExportAddressFilter : 1; 879 | 880 | ULONG EnableExportAddressFilterPlus : 1; 881 | ULONG AuditExportAddressFilterPlus : 1; 882 | 883 | ULONG EnableImportAddressFilter : 1; 884 | ULONG AuditImportAddressFilter : 1; 885 | 886 | ULONG EnableRopStackPivot : 1; 887 | ULONG AuditRopStackPivot : 1; 888 | 889 | ULONG EnableRopCallerCheck : 1; 890 | ULONG AuditRopCallerCheck : 1; 891 | 892 | ULONG EnableRopSimExec : 1; 893 | ULONG AuditRopSimExec : 1; 894 | 895 | ULONG ReservedFlags : 20; 896 | } DUMMYSTRUCTNAME; 897 | } DUMMYUNIONNAME; 898 | } PROCESS_MITIGATION_PAYLOAD_RESTRICTION_POLICY, * PPROCESS_MITIGATION_PAYLOAD_RESTRICTION_POLICY; 899 | 900 | typedef struct _PROCESS_MITIGATION_CHILD_PROCESS_POLICY { 901 | union { 902 | ULONG Flags; 903 | struct { 904 | ULONG NoChildProcessCreation : 1; 905 | ULONG AuditNoChildProcessCreation : 1; 906 | ULONG AllowSecureProcessCreation : 1; 907 | ULONG ReservedFlags : 29; 908 | } DUMMYSTRUCTNAME; 909 | } DUMMYUNIONNAME; 910 | } PROCESS_MITIGATION_CHILD_PROCESS_POLICY, * PPROCESS_MITIGATION_CHILD_PROCESS_POLICY; 911 | 912 | typedef struct _PROCESS_MITIGATION_POLICY_INFORMATION { 913 | PROCESS_MITIGATION_POLICY Policy; 914 | union { 915 | PROCESS_MITIGATION_ASLR_POLICY ASLRPolicy; 916 | PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY StrictHandleCheckPolicy; 917 | PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY SystemCallDisablePolicy; 918 | PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY ExtensionPointDisablePolicy; 919 | PROCESS_MITIGATION_DYNAMIC_CODE_POLICY DynamicCodePolicy; 920 | PROCESS_MITIGATION_CONTROL_FLOW_GUARD_POLICY ControlFlowGuardPolicy; 921 | PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY SignaturePolicy; 922 | PROCESS_MITIGATION_FONT_DISABLE_POLICY FontDisablePolicy; 923 | PROCESS_MITIGATION_IMAGE_LOAD_POLICY ImageLoadPolicy; 924 | PROCESS_MITIGATION_SYSTEM_CALL_FILTER_POLICY SystemCallFilterPolicy; 925 | PROCESS_MITIGATION_PAYLOAD_RESTRICTION_POLICY PayloadRestrictionPolicy; 926 | PROCESS_MITIGATION_CHILD_PROCESS_POLICY ChildProcessPolicy; 927 | }; 928 | } PROCESS_MITIGATION_POLICY_INFORMATION, * PPROCESS_MITIGATION_POLICY_INFORMATION; 929 | 930 | #endif // !_WINNT_ 931 | 932 | 933 | // 934 | // Process KeepAlive Count 935 | // NtQueryInformationProcess using ProcessKeepAliveCount 936 | // 937 | 938 | typedef struct _PROCESS_KEEPALIVE_COUNT_INFORMATION { 939 | ULONG WakeCount; 940 | ULONG NoWakeCount; 941 | } PROCESS_KEEPALIVE_COUNT_INFORMATION, * PPROCESS_KEEPALIVE_COUNT_INFORMATION; 942 | 943 | // 944 | // Process File Handle Revocation 945 | // NtSetInformationProcess using ProcessRevokeFileHandles 946 | // 947 | 948 | typedef struct _PROCESS_REVOKE_FILE_HANDLES_INFORMATION { 949 | UNICODE_STRING TargetDevicePath; 950 | } PROCESS_REVOKE_FILE_HANDLES_INFORMATION, * PPROCESS_REVOKE_FILE_HANDLES_INFORMATION; 951 | 952 | // 953 | // Process Read/WriteVm Logging 954 | // NtQueryInformationProcess using ProcessEnableReadWriteVmLogging 955 | // 956 | 957 | #define PROCESS_READWRITEVM_LOGGING_ENABLE_READVM 0x01 958 | #define PROCESS_READWRITEVM_LOGGING_ENABLE_READVM_V 1UL 959 | #define PROCESS_READWRITEVM_LOGGING_ENABLE_WRITEVM 0x02L 960 | #define PROCESS_READWRITEVM_LOGGING_ENABLE_WRITEVM_V 2UL 961 | 962 | typedef union _PROCESS_READWRITEVM_LOGGING_INFORMATION { 963 | UINT8 Flags; 964 | struct { 965 | UINT8 EnableReadVmLogging : 1; 966 | UINT8 EnableWriteVmLogging : 1; 967 | UINT8 Unused : 6; 968 | }; 969 | } PROCESS_READWRITEVM_LOGGING_INFORMATION, * PPROCESS_READWRITEVM_LOGGING_INFORMATION; 970 | 971 | // 972 | // Process Pooled Quota Usage and Limits 973 | // NtQueryInformationProcess using ProcessPooledUsageAndLimits 974 | // 975 | 976 | typedef struct _POOLED_USAGE_AND_LIMITS { 977 | SIZE_T PeakPagedPoolUsage; 978 | SIZE_T PagedPoolUsage; 979 | SIZE_T PagedPoolLimit; 980 | SIZE_T PeakNonPagedPoolUsage; 981 | SIZE_T NonPagedPoolUsage; 982 | SIZE_T NonPagedPoolLimit; 983 | SIZE_T PeakPagefileUsage; 984 | SIZE_T PagefileUsage; 985 | SIZE_T PagefileLimit; 986 | } POOLED_USAGE_AND_LIMITS, * PPOOLED_USAGE_AND_LIMITS; 987 | 988 | // 989 | // Process Exception Port Information 990 | // NtSetInformationProcess using ProcessExceptionPort 991 | // PROCESS_SET_PORT access to the process is needed 992 | // to use this info level. 993 | // 994 | 995 | #define PROCESS_EXCEPTION_PORT_ALL_STATE_BITS 0x00000003UL 996 | #define PROCESS_EXCEPTION_PORT_ALL_STATE_FLAGS ((UINTN)((1UL << PROCESS_EXCEPTION_PORT_ALL_STATE_BITS) - 1)) 997 | 998 | typedef struct _PROCESS_EXCEPTION_PORT { 999 | // 1000 | // Handle to the exception port. No particular access required. 1001 | // 1002 | IN HANDLE ExceptionPortHandle; 1003 | // 1004 | // Miscellaneous state flags to be cached along with the exception 1005 | // port in the kernel. 1006 | // 1007 | IN OUT ULONG StateFlags; 1008 | } PROCESS_EXCEPTION_PORT, * PPROCESS_EXCEPTION_PORT; 1009 | 1010 | // 1011 | // Process Security Context Information 1012 | // NtSetInformationProcess using ProcessAccessToken 1013 | // PROCESS_SET_ACCESS_TOKEN access to the process is needed 1014 | // to use this info level. 1015 | // 1016 | 1017 | typedef struct _PROCESS_ACCESS_TOKEN { 1018 | 1019 | // 1020 | // Handle to Primary token to assign to the process. 1021 | // TOKEN_ASSIGN_PRIMARY access to this token is needed. 1022 | // 1023 | HANDLE Token; 1024 | 1025 | // 1026 | // Handle to the initial thread of the process. 1027 | // A process's access token can only be changed if the process has 1028 | // no threads or one thread. If the process has no threads, this 1029 | // field must be set to NULL. Otherwise, it must contain a handle 1030 | // open to the process's only thread. THREAD_QUERY_INFORMATION access 1031 | // is needed via this handle. 1032 | // 1033 | HANDLE Thread; 1034 | 1035 | } PROCESS_ACCESS_TOKEN, * PPROCESS_ACCESS_TOKEN; 1036 | 1037 | // 1038 | // Process/Thread System and User Time 1039 | // NtQueryInformationProcess using ProcessTimes 1040 | // NtQueryInformationThread using ThreadTimes 1041 | // 1042 | 1043 | typedef struct _KERNEL_USER_TIMES { 1044 | LARGE_INTEGER CreateTime; 1045 | LARGE_INTEGER ExitTime; 1046 | LARGE_INTEGER KernelTime; 1047 | LARGE_INTEGER UserTime; 1048 | } KERNEL_USER_TIMES; 1049 | typedef KERNEL_USER_TIMES* PKERNEL_USER_TIMES; 1050 | 1051 | // 1052 | // Process/Thread subsystem information 1053 | // NtQueryInformationProcess using ProcessSubsystemInformation 1054 | // NtQueryInformationThread using ThreadSubsystemInformation 1055 | // 1056 | 1057 | typedef enum _SUBSYSTEM_INFORMATION_TYPE { 1058 | SubsystemInformationTypeWin32 = 0, 1059 | SubsystemInformationTypeWSL = 1, 1060 | MaxSubsystemInformationType 1061 | } SUBSYSTEM_INFORMATION_TYPE, * PSUBSYSTEM_INFORMATION_TYPE; 1062 | 1063 | // 1064 | // Ums Context 1065 | // 1066 | 1067 | typedef struct _RTL_UMS_CONTEXT { 1068 | SINGLE_LIST_ENTRY Link; 1069 | CONTEXT Context; 1070 | PVOID Teb; 1071 | PVOID UserContext; 1072 | volatile ULONG ScheduledThread; 1073 | volatile ULONG Suspended; 1074 | volatile ULONG VolatileContext; 1075 | volatile ULONG Terminated; 1076 | volatile ULONG DebugActive; 1077 | volatile ULONG RunningOnSelfThread; 1078 | volatile ULONG DenyRunningOnSelfThread; 1079 | volatile INT32 Flags; 1080 | volatile ULONG64 KernelUpdateLock; 1081 | volatile ULONG64 PrimaryClientID; 1082 | volatile ULONG64 ContextLock; 1083 | struct _RTL_UMS_CONTEXT* PrimaryUmsContext; 1084 | ULONG SwitchCount; 1085 | ULONG KernelYieldCount; 1086 | ULONG MixedYieldCount; 1087 | ULONG YieldCount; 1088 | } RTL_UMS_CONTEXT, * PRTL_UMS_CONTEXT; 1089 | 1090 | #endif // !_NTDDK_ && !_WINNT_ 1091 | 1092 | 1093 | typedef 1094 | NTSTATUS 1095 | (NTAPI* PNT_QUERY_INFORMATION_PROCESS)( 1096 | IN HANDLE ProcessHandle, 1097 | IN PROCESSINFOCLASS ProcessInformationClass, 1098 | OUT PVOID ProcessInformation, 1099 | IN ULONG ProcessInformationLength, 1100 | OUT PULONG ReturnLength OPTIONAL 1101 | ); 1102 | NTSYSCALLAPI 1103 | NTSTATUS 1104 | NTAPI 1105 | NtQueryInformationProcess( 1106 | IN HANDLE ProcessHandle, 1107 | IN PROCESSINFOCLASS ProcessInformationClass, 1108 | OUT PVOID ProcessInformation, 1109 | IN ULONG ProcessInformationLength, 1110 | OUT PULONG ReturnLength OPTIONAL 1111 | ); 1112 | 1113 | NTSYSCALLAPI 1114 | NTSTATUS 1115 | NTAPI 1116 | ZwQueryInformationProcess( 1117 | IN HANDLE ProcessHandle, 1118 | IN PROCESSINFOCLASS ProcessInformationClass, 1119 | OUT PVOID ProcessInformation, 1120 | IN ULONG ProcessInformationLength, 1121 | OUT PULONG ReturnLength OPTIONAL 1122 | ); 1123 | 1124 | typedef 1125 | NTSTATUS 1126 | (NTAPI* PNT_QUERY_INFORMATION_THREAD)( 1127 | IN HANDLE ThreadHandle, 1128 | IN THREADINFOCLASS ThreadInformationClass, 1129 | OUT PVOID ThreadInformation, 1130 | IN ULONG ThreadInformationLength, 1131 | OUT PULONG ReturnLength OPTIONAL 1132 | ); 1133 | NTSYSCALLAPI 1134 | NTSTATUS 1135 | NTAPI 1136 | NtQueryInformationThread( 1137 | IN HANDLE ThreadHandle, 1138 | IN THREADINFOCLASS ThreadInformationClass, 1139 | OUT PVOID ThreadInformation, 1140 | IN ULONG ThreadInformationLength, 1141 | OUT PULONG ReturnLength OPTIONAL 1142 | ); 1143 | 1144 | #ifdef __cplusplus 1145 | } // extern "C" 1146 | #endif 1147 | 1148 | #if defined(_MSC_VER) 1149 | #pragma warning(pop) 1150 | #endif // _MSC_VER 1151 | 1152 | #endif // _NTPSAPI_ 1153 | -------------------------------------------------------------------------------- /ntrtl.h: -------------------------------------------------------------------------------- 1 | #include "ntapi.h" 2 | 3 | // Hacky case manipulation macros. 4 | 5 | #define RTL_UPCASE(wch) ( \ 6 | ((wch) < 'a' ? \ 7 | (wch) \ 8 | : \ 9 | ((wch) <= 'z' ? \ 10 | (wch) - ('a'-'A') \ 11 | : \ 12 | ((WCHAR)(wch)) \ 13 | ) \ 14 | ) \ 15 | ) 16 | 17 | #define RTL_DOWNCASE(wch) ( \ 18 | ((wch) < 'A' ? \ 19 | (wch) \ 20 | : \ 21 | ((wch) <= 'Z' ? \ 22 | (wch) + ('a'-'A') \ 23 | : \ 24 | ((WCHAR)(wch)) \ 25 | ) \ 26 | ) \ 27 | ) 28 | 29 | //NTSYSAPI 30 | LONG 31 | NTAPI 32 | RtlCompareUnicodeStrings( 33 | IN CONST WCHAR* String1, 34 | IN SIZE_T Length1, 35 | IN CONST WCHAR* String2, 36 | IN SIZE_T Length2, 37 | IN BOOLEAN CaseInSensitive 38 | ); 39 | 40 | #if !defined(_NTDDK_) 41 | 42 | FORCEINLINE 43 | LONG 44 | NTAPI 45 | RtlCompareUnicodeString( 46 | IN PCUNICODE_STRING String1, 47 | IN PCUNICODE_STRING String2, 48 | IN BOOLEAN CaseInSensitive 49 | ) 50 | { 51 | return RtlCompareUnicodeStrings(String1->Buffer, String1->Length, 52 | String2->Buffer, String2->Length, 53 | CaseInSensitive); 54 | } 55 | 56 | _At_(DestinationString->Buffer, _Post_equal_to_(SourceString)) 57 | _At_(DestinationString->Length, _Post_equal_to_(_String_length_(SourceString) * sizeof(WCHAR))) 58 | _At_(DestinationString->MaximumLength, _Post_equal_to_((_String_length_(SourceString)+1) * sizeof(WCHAR))) 59 | //NTSYSAPI 60 | VOID 61 | NTAPI 62 | RtlInitUnicodeString( 63 | _Out_ PUNICODE_STRING DestinationString, 64 | _In_opt_z_ PCWSTR SourceString 65 | ); 66 | 67 | _At_(UnicodeString->Buffer, _Post_equal_to_(Buffer)) 68 | _At_(UnicodeString->Length, _Post_equal_to_(0)) 69 | _At_(UnicodeString->MaximumLength, _Post_equal_to_(BufferSize)) 70 | FORCEINLINE 71 | VOID 72 | RtlInitEmptyUnicodeString( 73 | OUT PUNICODE_STRING UnicodeString, 74 | IN _Writable_bytes_(BufferSize) _When_(BufferSize != 0, _Notnull_) 75 | PWCHAR Buffer, 76 | IN UINT16 BufferSize 77 | ) 78 | { 79 | memset(UnicodeString, 0, sizeof(*UnicodeString)); 80 | UnicodeString->MaximumLength = BufferSize; 81 | UnicodeString->Buffer = Buffer; 82 | } 83 | 84 | _At_(AnsiString->Buffer, _Post_equal_to_(Buffer)) 85 | _At_(AnsiString->Length, _Post_equal_to_(0)) 86 | _At_(AnsiString->MaximumLength, _Post_equal_to_(BufferSize)) 87 | FORCEINLINE 88 | VOID 89 | RtlInitEmptyAnsiString( 90 | OUT PANSI_STRING AnsiString, 91 | IN _Pre_readable_size_(BufferSize) CHAR* Buffer, 92 | IN UINT16 BufferSize 93 | ) 94 | { 95 | AnsiString->Length = 0; 96 | AnsiString->MaximumLength = BufferSize; 97 | AnsiString->Buffer = Buffer; 98 | } 99 | 100 | #endif // !_NTDDK_ 101 | 102 | -------------------------------------------------------------------------------- /pebteb.h: -------------------------------------------------------------------------------- 1 | // 2 | // Declarations of PEB and TEB, and some types contained in them. 3 | // 4 | // Address the maintenance problem that resulted from PEB and TEB being 5 | // defined three times, once "native" in ntpsapi.w, and twice, 32bit and 64bit 6 | // in wow64t.w. 7 | // 8 | 9 | // 10 | // This file deliberately lacks #pragma once or #ifndef guards. 11 | // It is only included by ntpsapi.h and wow64t.h and ntapi.h, never directly. 12 | // 13 | 14 | // 15 | // This file is #included three times. 16 | // 17 | // 1) by ntpsapi.h, with no "unusual" macros defined, to declare 18 | // PEB and TEB, and some types contained in them 19 | // 2) by wow64t.h to declare PEB32 and TEB32, and some types contained in them 20 | // 3) by wow64t.h to declare PEB64 and TEB64, and some types contained in them 21 | // 22 | // wow64t.h #defines the macro PEBTEB_BITS to guide the declarations. 23 | // 24 | 25 | #define PEBTEB_PRIVATE_PASTE(x, y) x##y 26 | #define PEBTEB_PASTE(x, y) PEBTEB_PRIVATE_PASTE(x,y) 27 | 28 | #if defined(PEBTEB_BITS) /* This is defined by wow64t.h. */ 29 | 30 | #if PEBTEB_BITS == 32 31 | 32 | #define PEBTEB_STRUCT(x) PEBTEB_PASTE(x, 32) /* FOO32 */ 33 | #define PEBTEB_POINTER(x) TYPE32(x) /* ULONG, defined in wow64t.h */ 34 | 35 | #elif PEBTEB_BITS == 64 36 | 37 | #define PEBTEB_STRUCT(x) PEBTEB_PASTE(x, 64) /* FOO64 */ 38 | #define PEBTEB_POINTER(x) TYPE64(x) /* ULONG64, defined in wow64t.h */ 39 | 40 | #else 41 | 42 | #error Unknown value for pebteb_bits (PEBTEB_BITS). 43 | 44 | #endif 45 | 46 | #else 47 | 48 | // 49 | // Declare and use regular native types. 50 | // 51 | #define PEBTEB_POINTER(x) x 52 | #define PEBTEB_STRUCT(x) x 53 | 54 | #endif 55 | 56 | 57 | typedef struct PEBTEB_STRUCT(_PEB_LDR_DATA) { 58 | ULONG Length; 59 | BOOLEAN Initialized; 60 | ULONG SsHandle; 61 | PEBTEB_STRUCT(LIST_ENTRY) InLoadOrderModuleList; 62 | PEBTEB_STRUCT(LIST_ENTRY) InMemoryOrderModuleList; 63 | PEBTEB_STRUCT(LIST_ENTRY) InInitializationOrderModuleList; 64 | ULONG EntryInProgress; 65 | BOOLEAN ShutdownInProgress; 66 | ULONG ShutdownThreadId; 67 | } PEBTEB_STRUCT(PEB_LDR_DATA), *PEBTEB_STRUCT(PPEB_LDR_DATA); 68 | 69 | 70 | /* for searching 71 | typedef struct _PEB 72 | typedef struct _PEB32 73 | typedef struct _PEB64 74 | */ 75 | typedef struct PEBTEB_STRUCT(_PEB) { 76 | BOOLEAN InheritedAddressSpace; // These four fields cannot change unless the 77 | BOOLEAN ReadImageFileExecOptions; // .. 78 | BOOLEAN BeingDebugged; // .. 79 | union { 80 | BOOLEAN BitField; // .. 81 | struct { 82 | BOOLEAN ImageUsesLargePages : 1; 83 | BOOLEAN IsProtectedProcess : 1; 84 | BOOLEAN IsImageDynamicallyRelocated : 1; 85 | BOOLEAN SkipPatchingUser32Forwarders : 1; 86 | BOOLEAN IsPackagedProcess : 1; 87 | BOOLEAN IsAppContainer : 1; 88 | BOOLEAN IsProtectedProcessLight : 1; 89 | BOOLEAN IsLongPathAwareProcess : 1; 90 | }; 91 | }; 92 | 93 | PEBTEB_POINTER(HANDLE) Mutant; // INITIAL_PEB structure is also updated. 94 | 95 | PEBTEB_POINTER(PVOID) ImageBaseAddress; 96 | PEBTEB_POINTER(PPEB_LDR_DATA) Ldr; 97 | PEBTEB_POINTER(struct _RTL_USER_PROCESS_PARAMETERS*)ProcessParameters; 98 | PEBTEB_POINTER(PVOID) SubSystemData; 99 | PEBTEB_POINTER(PVOID) ProcessHeap; 100 | PEBTEB_POINTER(struct _RTL_CRITICAL_SECTION*)FastPebLock; 101 | PEBTEB_POINTER(PVOID) IFEOKey; 102 | PEBTEB_POINTER(PVOID) AtlThunkSListPtr; // Used only for AMD64 PSLIST_HEADER 103 | union { 104 | ULONG CrossProcessFlags; 105 | struct { 106 | ULONG ProcessInJob : 1; 107 | ULONG ProcessInitializing : 1; 108 | ULONG ProcessUsingVEH : 1; 109 | ULONG ProcessUsingVCH : 1; 110 | ULONG ProcessUsingFTH : 1; 111 | ULONG ProcessPreviouslyThrottled : 1; 112 | ULONG ProcessCurrentlyThrottled : 1; 113 | ULONG ReservedBits0 : 25; 114 | }; 115 | }; 116 | union { 117 | PEBTEB_POINTER(PVOID) KernelCallbackTable; 118 | PEBTEB_POINTER(PVOID) UserSharedInfoPtr; 119 | }; 120 | ULONG SystemReserved[1]; 121 | ULONG AtlThunkSListPtr32; 122 | PEBTEB_POINTER(PVOID) ApiSetMap; // PAPI_SET_NAMESPACE 123 | ULONG TlsExpansionCounter; 124 | PEBTEB_POINTER(PVOID) TlsBitmap; 125 | ULONG TlsBitmapBits[2]; // TLS_MINIMUM_AVAILABLE bits 126 | PEBTEB_POINTER(PVOID) ReadOnlySharedMemoryBase; 127 | PEBTEB_POINTER(PVOID) SharedData; // HotpatchInformation 128 | PEBTEB_POINTER(PPVOID) ReadOnlyStaticServerData; 129 | PEBTEB_POINTER(PVOID) AnsiCodePageData; // PCPTABLEINFO 130 | PEBTEB_POINTER(PVOID) OemCodePageData; // PCPTABLEINFO 131 | PEBTEB_POINTER(PVOID) UnicodeCaseTableData; // PNLSTABLEINFO 132 | 133 | // 134 | // Useful information for LdrpInitialize 135 | ULONG NumberOfProcessors; 136 | ULONG NtGlobalFlag; 137 | 138 | // 139 | // Passed up from MmCreatePeb from Session Manager registry key 140 | // 141 | 142 | LARGE_INTEGER CriticalSectionTimeout; 143 | PEBTEB_POINTER(SIZE_T) HeapSegmentReserve; 144 | PEBTEB_POINTER(SIZE_T) HeapSegmentCommit; 145 | PEBTEB_POINTER(SIZE_T) HeapDeCommitTotalFreeThreshold; 146 | PEBTEB_POINTER(SIZE_T) HeapDeCommitFreeBlockThreshold; 147 | 148 | // 149 | // Where heap manager keeps track of all heaps created for a process 150 | // Fields initialized by MmCreatePeb. ProcessHeaps is initialized 151 | // to point to the first free byte after the PEB and MaximumNumberOfHeaps 152 | // is computed from the page size used to hold the PEB, less the fixed 153 | // size of this data structure. 154 | // 155 | 156 | ULONG NumberOfHeaps; 157 | ULONG MaximumNumberOfHeaps; 158 | PEBTEB_POINTER(PPVOID) ProcessHeaps; // PHEAP* 159 | 160 | // 161 | // 162 | PEBTEB_POINTER(PVOID) GdiSharedHandleTable; 163 | PEBTEB_POINTER(PVOID) ProcessStarterHelper; 164 | ULONG GdiDCAttributeList; 165 | PEBTEB_POINTER(struct _RTL_CRITICAL_SECTION*)LoaderLock; 166 | 167 | // 168 | // Following fields filled in by MmCreatePeb from system values and/or 169 | // image header. 170 | // 171 | 172 | ULONG OSMajorVersion; 173 | ULONG OSMinorVersion; 174 | USHORT OSBuildNumber; 175 | USHORT OSCSDVersion; 176 | ULONG OSPlatformId; 177 | ULONG ImageSubsystem; 178 | ULONG ImageSubsystemMajorVersion; 179 | ULONG ImageSubsystemMinorVersion; 180 | PEBTEB_POINTER(UINT_PTR) ActiveProcessAffinityMask; 181 | PEBTEB_STRUCT(GDI_HANDLE_BUFFER) GdiHandleBuffer; 182 | PEBTEB_POINTER(PPS_POST_PROCESS_INIT_ROUTINE) PostProcessInitRoutine; 183 | 184 | PEBTEB_POINTER(PVOID) TlsExpansionBitmap; 185 | ULONG TlsExpansionBitmapBits[32]; // TLS_EXPANSION_SLOTS bits 186 | 187 | // 188 | // Id of the Hydra session in which this process is running 189 | // 190 | ULONG SessionId; 191 | 192 | // 193 | // Filled in by LdrpInstallAppcompatBackend 194 | // 195 | ULARGE_INTEGER AppCompatFlags; 196 | 197 | // 198 | // ntuser appcompat flags 199 | // 200 | ULARGE_INTEGER AppCompatFlagsUser; 201 | 202 | // 203 | // Filled in by LdrpInstallAppcompatBackend 204 | // 205 | PEBTEB_POINTER(PVOID) pShimData; 206 | 207 | // 208 | // Filled in by LdrQueryImageFileExecutionOptions 209 | // 210 | PEBTEB_POINTER(PVOID) AppCompatInfo; // APPCOMPAT_EXE_DATA 211 | 212 | // 213 | // Used by GetVersionExW as the szCSDVersion string 214 | // 215 | PEBTEB_STRUCT(UNICODE_STRING) CSDVersion; 216 | 217 | // 218 | // Fusion stuff 219 | // 220 | PEBTEB_POINTER(const struct _ACTIVATION_CONTEXT_DATA *)ActivationContextData; // ACTIVATION_CONTEXT_DATA 221 | PEBTEB_POINTER(struct _ASSEMBLY_STORAGE_MAP *)ProcessAssemblyStorageMap; // ASSEMBLY_STORAGE_MAP 222 | PEBTEB_POINTER(const struct _ACTIVATION_CONTEXT_DATA *)SystemDefaultActivationContextData; // ACTIVATION_CONTEXT_DATA 223 | PEBTEB_POINTER(struct _ASSEMBLY_STORAGE_MAP *)SystemAssemblyStorageMap; // ASSEMBLY_STORAGE_MAP 224 | 225 | // 226 | // Enforced minimum initial commit stack 227 | // 228 | PEBTEB_POINTER(SIZE_T) MinimumStackCommit; 229 | 230 | // 231 | // Fiber local storage. 232 | // 233 | 234 | PEBTEB_POINTER(PPVOID) FlsCallback; 235 | PEBTEB_STRUCT(LIST_ENTRY) FlsListHead; 236 | PEBTEB_POINTER(PVOID) FlsBitmap; 237 | ULONG FlsBitmapBits[FLS_MAXIMUM_AVAILABLE / (sizeof(ULONG) * 8)]; 238 | ULONG FlsHighIndex; 239 | 240 | PEBTEB_POINTER(PVOID) WerRegistrationData; 241 | PEBTEB_POINTER(PVOID) WerShipAssertPtr; 242 | PEBTEB_POINTER(PVOID) pUnused; // pContextData 243 | PEBTEB_POINTER(PVOID) pImageHeaderHash; 244 | 245 | union { 246 | ULONG TracingFlags; 247 | struct { 248 | ULONG HeapTracingEnabled : 1; 249 | ULONG CritSecTracingEnabled : 1; 250 | ULONG LibLoaderTracingEnabled : 1; 251 | ULONG SpareTracingBits : 29; 252 | }; 253 | }; 254 | 255 | ULONG64 CsrServerReadOnlySharedMemoryBase; 256 | 257 | PEBTEB_POINTER(struct _RTL_CRITICAL_SECTION*)TppWorkerpListLock; 258 | PEBTEB_STRUCT(LIST_ENTRY) TppWorkerpList; 259 | 260 | PEBTEB_POINTER(PVOID) WaitOnAddressHashTable[128]; 261 | 262 | // winver >= rs3 263 | PEBTEB_POINTER(PVOID) TelemetryCoverageHeader; 264 | ULONG CloudFileFlags; 265 | 266 | // winver >= rs4 267 | ULONG CloudFileDiagFlags; 268 | 269 | CHAR PlaceholderCompatibilityMode; 270 | CHAR PlaceholderCompatibilityModeReserved[7]; 271 | 272 | } PEBTEB_STRUCT(PEB), *PEBTEB_STRUCT(PPEB); 273 | 274 | 275 | typedef struct PEBTEB_STRUCT(_RTL_ACTIVATION_CONTEXT_STACK_FRAME) { 276 | // PEBTEB_POINTER(SIZE_T) Size; // -0x10 277 | // ULONG Format; // -0x08 278 | PEBTEB_POINTER(struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME *)Previous; // 0x00 279 | PEBTEB_POINTER(struct _ACTIVATION_CONTEXT *)ActivationContext; // +0x08 280 | ULONG Flags; // +0x10 281 | } PEBTEB_STRUCT(RTL_ACTIVATION_CONTEXT_STACK_FRAME), 282 | *PEBTEB_STRUCT(PRTL_ACTIVATION_CONTEXT_STACK_FRAME); 283 | 284 | typedef struct PEBTEB_STRUCT(_RTL_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED) { 285 | // PEBTEB_POINTER(SIZE_T) Size; // -0x10 286 | // ULONG Format; // -0x08 287 | PEBTEB_POINTER(struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME *)Previous; // 0x00 288 | PEBTEB_POINTER(struct _ACTIVATION_CONTEXT *)ActivationContext; // +0x08 289 | ULONG Flags; // +0x10 290 | PEBTEB_POINTER(SIZE_T) Extra1; // +0x18 291 | PEBTEB_POINTER(SIZE_T) Extra2; // +0x20 292 | PEBTEB_POINTER(SIZE_T) Extra3; // +0x28 293 | PEBTEB_POINTER(SIZE_T) Extra4; // +0x30 294 | } PEBTEB_STRUCT(RTL_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED), 295 | *PEBTEB_STRUCT(PRTL_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED); 296 | 297 | typedef struct PEBTEB_STRUCT(_ACTIVATION_CONTEXT_STACK) { 298 | PEBTEB_POINTER(struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME *)ActiveFrame; 299 | PEBTEB_STRUCT(LIST_ENTRY) FrameListCache; 300 | ULONG Flags; 301 | ULONG NextCookieSequenceNumber; 302 | ULONG StackId; 303 | } PEBTEB_STRUCT(ACTIVATION_CONTEXT_STACK), 304 | *PEBTEB_STRUCT(PACTIVATION_CONTEXT_STACK); 305 | 306 | typedef const PEBTEB_STRUCT(ACTIVATION_CONTEXT_STACK) *PEBTEB_STRUCT(PCACTIVATION_CONTEXT_STACK); 307 | 308 | #define TEB_ACTIVE_FRAME_CONTEXT_FLAG_EXTENDED (0x00000001) 309 | 310 | typedef struct PEBTEB_STRUCT(_TEB_ACTIVE_FRAME_CONTEXT) { 311 | ULONG Flags; 312 | PEBTEB_POINTER(CHAR*)FrameName; 313 | } PEBTEB_STRUCT(TEB_ACTIVE_FRAME_CONTEXT), 314 | *PEBTEB_STRUCT(PTEB_ACTIVE_FRAME_CONTEXT); 315 | 316 | typedef const PEBTEB_STRUCT(TEB_ACTIVE_FRAME_CONTEXT) *PEBTEB_STRUCT(PCTEB_ACTIVE_FRAME_CONTEXT); 317 | 318 | typedef struct PEBTEB_STRUCT(_TEB_ACTIVE_FRAME_CONTEXT_EX) { 319 | PEBTEB_STRUCT(TEB_ACTIVE_FRAME_CONTEXT) BasicContext; 320 | PEBTEB_POINTER(const CHAR*)SourceLocation; // e.g. "Z:\foo\bar\baz.c" 321 | } PEBTEB_STRUCT(TEB_ACTIVE_FRAME_CONTEXT_EX), 322 | *PEBTEB_STRUCT(PTEB_ACTIVE_FRAME_CONTEXT_EX); 323 | 324 | typedef const PEBTEB_STRUCT(TEB_ACTIVE_FRAME_CONTEXT_EX) *PEBTEB_STRUCT( 325 | PCTEB_ACTIVE_FRAME_CONTEXT_EX); 326 | 327 | #define TEB_ACTIVE_FRAME_FLAG_EXTENDED (0x00000001) 328 | 329 | typedef struct PEBTEB_STRUCT(_TEB_ACTIVE_FRAME) { 330 | ULONG Flags; 331 | PEBTEB_POINTER(struct _TEB_ACTIVE_FRAME*)Previous; 332 | PEBTEB_POINTER(PCTEB_ACTIVE_FRAME_CONTEXT) Context; 333 | } PEBTEB_STRUCT(TEB_ACTIVE_FRAME), 334 | *PEBTEB_STRUCT(PTEB_ACTIVE_FRAME); 335 | 336 | typedef const PEBTEB_STRUCT(TEB_ACTIVE_FRAME) *PEBTEB_STRUCT(PCTEB_ACTIVE_FRAME); 337 | 338 | typedef struct PEBTEB_STRUCT(_TEB_ACTIVE_FRAME_EX) { 339 | PEBTEB_STRUCT(TEB_ACTIVE_FRAME) BasicFrame; 340 | PEBTEB_POINTER(PVOID) ExtensionIdentifier; // use address of your DLL Main or something unique to 341 | // your mapping in the address space 342 | } PEBTEB_STRUCT(TEB_ACTIVE_FRAME_EX), 343 | *PEBTEB_STRUCT(PTEB_ACTIVE_FRAME_EX); 344 | 345 | typedef const PEBTEB_STRUCT(TEB_ACTIVE_FRAME_EX) *PEBTEB_STRUCT(PCTEB_ACTIVE_FRAME_EX); 346 | 347 | 348 | /* for searching 349 | typedef struct _TEB 350 | typedef struct _TEB32 351 | typedef struct _TEB64 352 | */ 353 | typedef struct PEBTEB_STRUCT(_TEB) { 354 | PEBTEB_STRUCT(NT_TIB) NtTib; 355 | PEBTEB_POINTER(PVOID) EnvironmentPointer; 356 | PEBTEB_STRUCT(CLIENT_ID) ClientId; 357 | PEBTEB_POINTER(PVOID) ActiveRpcHandle; 358 | PEBTEB_POINTER(PVOID) ThreadLocalStoragePointer; 359 | PEBTEB_POINTER(PPEB) ProcessEnvironmentBlock; 360 | ULONG LastErrorValue; 361 | ULONG CountOfOwnedCriticalSections; 362 | PEBTEB_POINTER(PVOID) CsrClientThread; 363 | PEBTEB_POINTER(PVOID) Win32ThreadInfo; // PtiCurrent 364 | ULONG User32Reserved[26]; // user32.dll items 365 | ULONG UserReserved[5]; // Winsrv SwitchStack 366 | PEBTEB_POINTER(PVOID) WOW32Reserved; // used by WOW 367 | LCID CurrentLocale; 368 | ULONG FpSoftwareStatusRegister; // offset known by outsiders! 369 | PVOID ReservedForDebuggerInstrumentation[16]; 370 | #if defined(_M_AMD64) || defined(__x86_64__) 371 | PEBTEB_POINTER(PVOID) SystemReserved1[30]; 372 | #else 373 | PEBTEB_POINTER( PVOID ) SystemReserved1[26]; 374 | #endif 375 | 376 | CHAR PlaceholderCompatibilityMode; 377 | CHAR PlaceholderReserved[11]; 378 | ULONG ProxiedProcessId; 379 | PEBTEB_STRUCT(ACTIVATION_CONTEXT_STACK) ActivationStack; 380 | 381 | UINT8 WorkingOnBehalfTicket[8]; 382 | NTSTATUS ExceptionCode; // for RaiseUserException 383 | 384 | PEBTEB_POINTER(PEBTEB_STRUCT(PACTIVATION_CONTEXT_STACK)) ActivationContextStackPointer; // Fusion activation stack 385 | PEBTEB_POINTER(ULONG_PTR) InstrumentationCallbackSp; 386 | PEBTEB_POINTER(ULONG_PTR) InstrumentationCallbackPreviousPc; 387 | PEBTEB_POINTER(ULONG_PTR) InstrumentationCallbackPreviousSp; 388 | #if defined(_M_AMD64) || defined(__x86_64__) 389 | ULONG TxFsContext; 390 | #endif 391 | 392 | BOOLEAN InstrumentationCallbackDisabled; 393 | #if !(defined(_M_AMD64) || defined(__x86_64__)) 394 | UCHAR SpareBytes[23]; 395 | ULONG TxFsContext; 396 | #endif 397 | 398 | PEBTEB_STRUCT(GDI_TEB_BATCH) GdiTebBatch; // Gdi batching 399 | PEBTEB_STRUCT(CLIENT_ID) RealClientId; 400 | PEBTEB_POINTER(HANDLE) GdiCachedProcessHandle; 401 | ULONG GdiClientPID; 402 | ULONG GdiClientTID; 403 | PEBTEB_POINTER(PVOID) GdiThreadLocalInfo; 404 | PEBTEB_POINTER(ULONG_PTR) Win32ClientInfo[62]; 405 | PEBTEB_POINTER(PVOID) glDispatchTable[233]; // OpenGL 406 | PEBTEB_POINTER(ULONG_PTR) glReserved1[29]; // OpenGL 407 | PEBTEB_POINTER(PVOID) glReserved2; // OpenGL 408 | PEBTEB_POINTER(PVOID) glSectionInfo; // OpenGL 409 | PEBTEB_POINTER(PVOID) glSection; // OpenGL 410 | PEBTEB_POINTER(PVOID) glTable; // OpenGL 411 | PEBTEB_POINTER(PVOID) glCurrentRC; // OpenGL 412 | PEBTEB_POINTER(PVOID) glContext; // OpenGL 413 | NTSTATUS LastStatusValue; 414 | PEBTEB_STRUCT(UNICODE_STRING) StaticUnicodeString; 415 | WCHAR StaticUnicodeBuffer[STATIC_UNICODE_BUFFER_LENGTH]; 416 | PEBTEB_POINTER(PVOID) DeallocationStack; 417 | PEBTEB_POINTER(PVOID) TlsSlots[TLS_MINIMUM_AVAILABLE]; 418 | PEBTEB_STRUCT(LIST_ENTRY) TlsLinks; 419 | PEBTEB_POINTER(PVOID) Vdm; 420 | PEBTEB_POINTER(PVOID) ReservedForNtRpc; 421 | PEBTEB_POINTER(PVOID) DbgSsReserved[2]; 422 | ULONG HardErrorMode; 423 | #if defined(_M_AMD64) || defined(__x86_64__) 424 | PEBTEB_POINTER(PVOID) Instrumentation[11]; 425 | #else 426 | PEBTEB_POINTER( PVOID ) Instrumentation[9]; 427 | #endif 428 | GUID ActivityId; 429 | PEBTEB_POINTER(PVOID) SubProcessTag; 430 | PEBTEB_POINTER(PVOID) PerflibData; 431 | PEBTEB_POINTER(PVOID) EtwTraceData; 432 | PEBTEB_POINTER(PVOID) WinSockData; // WinSock 433 | ULONG GdiBatchCount; 434 | union { 435 | PROCESSOR_NUMBER CurrentIdealProcessor; 436 | ULONG IdealProcessorValue; 437 | struct { 438 | UINT8 ReservedPad0; 439 | UINT8 ReservedPad1; 440 | UINT8 ReservedPad2; 441 | UINT8 IdealProcessor; 442 | }; 443 | }; 444 | ULONG GuaranteedStackBytes; 445 | PEBTEB_POINTER(PVOID) ReservedForPerf; 446 | PEBTEB_POINTER(PVOID) ReservedForOle; 447 | ULONG WaitingOnLoaderLock; 448 | PEBTEB_POINTER(PVOID) SavedPriorityState; 449 | PEBTEB_POINTER(ULONG_PTR) ReservedForCodeCoverage; 450 | PEBTEB_POINTER(PVOID) ThreadPoolData; 451 | PEBTEB_POINTER(PPVOID) TlsExpansionSlots; 452 | #if ((defined(_M_AMD64) || defined(__x86_64__)) && !defined(PEBTEB_BITS)) \ 453 | || (((defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__))) \ 454 | && defined(PEBTEB_BITS) && PEBTEB_BITS == 64) 455 | // 456 | // These are in native Win64 TEB, Win64 TEB64, and x86 TEB64. 457 | // 458 | PEBTEB_POINTER(PVOID) DeallocationBStore; 459 | PEBTEB_POINTER(PVOID) BStoreLimit; 460 | #endif 461 | ULONG MuiGeneration; 462 | ULONG IsImpersonating; // Thread impersonation status 463 | PEBTEB_POINTER(PVOID) NlsCache; // NLS thread cache 464 | PEBTEB_POINTER(PVOID) pShimData; // Per thread data used in the shim 465 | USHORT HeapVirtualAffinity; 466 | USHORT LowFragHeapDataSlot; 467 | PEBTEB_POINTER(HANDLE) CurrentTransactionHandle;// reserved for TxF transaction context 468 | PEBTEB_POINTER(PTEB_ACTIVE_FRAME) ActiveFrame; 469 | PEBTEB_POINTER(PVOID) FlsData; 470 | PEBTEB_POINTER(PVOID) PreferredLanguages; 471 | PEBTEB_POINTER(PVOID) UserPrefLanguages; 472 | PEBTEB_POINTER(PVOID) MergedPrefLanguages; 473 | ULONG MuiImpersonation; // mui impersonation status 474 | union { 475 | USHORT CrossTebFlags; 476 | USHORT SpareCrossTebBits : 16; 477 | }; 478 | union { 479 | USHORT SameTebFlags; 480 | struct { 481 | USHORT SafeThunkCall : 1; 482 | USHORT InDebugPrint : 1; 483 | USHORT HasFiberData : 1; 484 | USHORT SkipThreadAttach : 1; 485 | USHORT WerInShipAssertCode : 1; 486 | USHORT RanProcessInit : 1; 487 | USHORT ClonedThread : 1; 488 | USHORT SuppressDebugMsg : 1; 489 | USHORT DisableUserStackWalk : 1; 490 | USHORT RtlExceptionAttached : 1; 491 | USHORT InitialThread : 1; 492 | USHORT SessionAware : 1; 493 | USHORT LoadOwner : 1; 494 | USHORT LoaderWorker : 1; 495 | USHORT SkipLoaderInit : 1; 496 | USHORT SpareSameTebBits : 1; 497 | }; 498 | }; 499 | PEBTEB_POINTER(PVOID) TxnScopeEnterCallback; 500 | PEBTEB_POINTER(PVOID) TxnScopeExitCallback; 501 | PEBTEB_POINTER(PVOID) TxnScopeContext; 502 | ULONG LockCount; 503 | INT32 WowTebOffset; 504 | PEBTEB_POINTER(PVOID) ResourceRetValue; 505 | PEBTEB_POINTER(PVOID) ReservedForWdf; 506 | ULONG64 ReservedForCrt; 507 | GUID EffectiveContainerId; 508 | } PEBTEB_STRUCT(TEB), *PEBTEB_STRUCT(PTEB); 509 | 510 | #undef PEBTEB_POINTER 511 | #undef PEBTEB_STRUCT 512 | #undef PEBTEB_PRIVATE_PASTE 513 | #undef PEBTEB_PASTE 514 | -------------------------------------------------------------------------------- /resolve.c: -------------------------------------------------------------------------------- 1 | /** 2 | * API Set Lookup 3 | * Copyright (c) 2018-2019 Aidan Khoury. All rights reserved. 4 | * 5 | * @file resolve.c 6 | * @authors Aidan Khoury (ajkhoury) 7 | * @date 11/22/2018 8 | */ 9 | 10 | #include "apiset.h" 11 | 12 | #include "ntrtl.h" 13 | 14 | static 15 | NTSTATUS 16 | ApiSetpResolve( 17 | _In_ HANDLE Process, 18 | _In_ PCUNICODE_STRING Name, 19 | _In_opt_ PCUNICODE_STRING BaseName, 20 | _Out_ PUNICODE_STRING ResolvedName 21 | ) 22 | { 23 | NTSTATUS Status; 24 | PROCESS_BASIC_INFORMATION BasicInfo; 25 | ULONG ReturnLength; 26 | PPEB Peb; 27 | PVOID PebWow64; 28 | BOOLEAN Resolved; 29 | PAPI_SET_NAMESPACE ApiSetMap; 30 | 31 | // 32 | // Retrieve PEB address for given process. 33 | // 34 | Status = NtQueryInformationProcess(Process, 35 | ProcessBasicInformation, 36 | &BasicInfo, 37 | sizeof(BasicInfo), 38 | &ReturnLength); 39 | if (!NT_SUCCESS(Status)) { 40 | return Status; 41 | } 42 | 43 | Peb = (PPEB)BasicInfo.PebBaseAddress; 44 | 45 | Status = NtQueryInformationProcess(Process, 46 | ProcessWow64Information, 47 | &PebWow64, 48 | sizeof(PebWow64), 49 | &ReturnLength); 50 | if (!NT_SUCCESS(Status)) { 51 | return Status; 52 | } 53 | 54 | if (PebWow64 != NULL) { 55 | ApiSetMap = (PAPI_SET_NAMESPACE)(ULONG_PTR)((PPEB32)PebWow64)->ApiSetMap; 56 | } else { 57 | ApiSetMap = (PAPI_SET_NAMESPACE)Peb->ApiSetMap; 58 | } 59 | 60 | if (!ApiSetMap) { 61 | return STATUS_NOT_FOUND; 62 | } 63 | 64 | switch (ApiSetMap->Version) { 65 | 66 | // 67 | // API set schema version 2 68 | // 69 | case API_SET_SCHEMA_VERSION_V2: 70 | Status = ApiSetResolveToHostV2(ApiSetMap, Name, BaseName, &Resolved, ResolvedName); 71 | if (NT_SUCCESS(Status) && !Resolved) { 72 | Status = STATUS_NOT_FOUND; 73 | } 74 | break; 75 | 76 | // 77 | // API set schema version 3 78 | // 79 | case API_SET_SCHEMA_VERSION_V3: 80 | Status = ApiSetResolveToHostV3(ApiSetMap, Name, BaseName, &Resolved, ResolvedName); 81 | if (NT_SUCCESS(Status) && !Resolved) { 82 | Status = STATUS_NOT_FOUND; 83 | } 84 | break; 85 | 86 | // 87 | // API set schema version 4 88 | // 89 | case API_SET_SCHEMA_VERSION_V4: 90 | Status = ApiSetResolveToHostV4(ApiSetMap, Name, BaseName, &Resolved, ResolvedName); 91 | if (NT_SUCCESS(Status) && !Resolved) { 92 | Status = STATUS_NOT_FOUND; 93 | } 94 | break; 95 | 96 | // 97 | // API set schema version 6 98 | // 99 | case API_SET_SCHEMA_VERSION_V6: 100 | Status = ApiSetResolveToHostV6(ApiSetMap, Name, BaseName, &Resolved, ResolvedName); 101 | if (NT_SUCCESS(Status) && !Resolved) { 102 | Status = STATUS_NOT_FOUND; 103 | } 104 | break; 105 | 106 | default: 107 | Status = STATUS_NOT_SUPPORTED; 108 | break; 109 | } 110 | 111 | return Status; 112 | } 113 | 114 | BOOLEAN 115 | APISETAPI 116 | ApiSetResolve( 117 | _In_z_ PWCHAR ApiSetName, 118 | _In_opt_z_ PWCHAR BaseDllName, 119 | _Out_ PUNICODE_STRING ResolvedHostLibrary 120 | ) 121 | { 122 | NTSTATUS Status; 123 | UNICODE_STRING ApiToResolve; 124 | UNICODE_STRING BaseName; 125 | 126 | RtlInitUnicodeString(&ApiToResolve, ApiSetName); 127 | if (BaseDllName != NULL) { 128 | RtlInitUnicodeString(&BaseName, BaseDllName); 129 | } 130 | 131 | Status = ApiSetpResolve(GetCurrentProcess(), 132 | &ApiToResolve, 133 | BaseDllName ? &BaseName : NULL, 134 | ResolvedHostLibrary 135 | ); 136 | 137 | if (NT_SUCCESS(Status)) { 138 | return TRUE; 139 | } 140 | 141 | return FALSE; 142 | } 143 | -------------------------------------------------------------------------------- /string.c: -------------------------------------------------------------------------------- 1 | #include "ntrtl.h" 2 | 3 | /** 4 | * The RtlInitUnicodeString function initializes an NT counted 5 | * unicode string. The DestinationString is initialized to point to 6 | * the SourceString and the Length and MaximumLength fields of 7 | * DestinationString are initialized to the length of the SourceString, 8 | * which is zero if SourceString is not specified. 9 | * 10 | * @param[out] DestinationString Pointer to the counted string to initialize. 11 | * @param[in] SourceString Optional pointer to a null terminated unicode 12 | * string that the counted string is to point to. 13 | */ 14 | VOID 15 | NTAPI 16 | RtlInitUnicodeString( 17 | _Out_ PUNICODE_STRING DestinationString, 18 | _In_opt_z_ PCWSTR SourceString 19 | ) 20 | { 21 | SIZE_T Length; 22 | 23 | DestinationString->MaximumLength = 0; 24 | DestinationString->Length = 0; 25 | DestinationString->Buffer = (PWCH)SourceString; 26 | 27 | if (ARGUMENT_PRESENT(SourceString)) { 28 | Length = wcslen(SourceString) * sizeof(WCHAR); 29 | if (Length >= MAX_USTRING) { 30 | Length = MAX_USTRING - sizeof(UNICODE_NULL); 31 | } 32 | 33 | DestinationString->Length = (USHORT)Length; 34 | DestinationString->MaximumLength = (USHORT)(Length + sizeof(UNICODE_NULL)); 35 | } 36 | 37 | return; 38 | } 39 | -------------------------------------------------------------------------------- /unicode.c: -------------------------------------------------------------------------------- 1 | // This document is released into the public domain. Absolutely no warranty is provided. 2 | // See http://www.coderforlife.com/projects/utilities. 3 | // 4 | // This is for the MinGW compiler which does not support wmain. 5 | // It is a wrapper for _tmain when _UNICODE is defined (wmain). 6 | // 7 | // !! Do not compile this file, but instead include it right before your _tmain function like: 8 | // #include "mingw-unicode.c" 9 | // int _tmain(int argc, _TCHAR *argv[]) { 10 | // 11 | // If you wish to have enpv in your main, then define the following before including this file: 12 | // #define MAIN_USE_ENVP 13 | // 14 | // This wrapper adds ~300 bytes to the program and negligible overhead 15 | 16 | #undef _tmain 17 | #ifdef _UNICODE 18 | #define _tmain wmain 19 | #else 20 | #define _tmain main 21 | #endif 22 | 23 | #if defined(__GNUC__) && defined(_UNICODE) 24 | 25 | #ifndef __MSVCRT__ 26 | #error Unicode main function requires linking to MSVCRT 27 | #endif 28 | 29 | #include 30 | #include 31 | 32 | extern int _CRT_glob; 33 | extern 34 | #ifdef __cplusplus 35 | "C" 36 | #endif 37 | void __wgetmainargs(int*,wchar_t***,wchar_t***,int,int*); 38 | 39 | #ifdef MAIN_USE_ENVP 40 | int wmain(int argc, wchar_t *argv[], wchar_t *envp[]); 41 | #else 42 | int wmain(int argc, wchar_t *argv[]); 43 | #endif 44 | 45 | int main() { 46 | wchar_t **enpv, **argv; 47 | int argc, si = 0; 48 | __wgetmainargs(&argc, &argv, &enpv, _CRT_glob, &si); // this also creates the global variable __wargv 49 | #ifdef MAIN_USE_ENVP 50 | return wmain(argc, argv, enpv); 51 | #else 52 | return wmain(argc, argv); 53 | #endif 54 | } 55 | 56 | #endif //defined(__GNUC__) && defined(_UNICODE) --------------------------------------------------------------------------------