├── .gitignore ├── LICENSE ├── README.md └── valinet ├── hooking ├── exeinject.h └── iatpatch.h ├── ini └── ini.h ├── internet ├── get.h └── post.h ├── pdb └── pdb.h ├── universal └── toast │ └── toast.h └── utility ├── memmem.h ├── osversion.h └── takeown.h /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libvalinet 2 | A header-only collection of generic implementations shared between multiple projects. 3 | 4 | To use in your project, simply include any of the header files. Methods beginning with "Vn" are meant to be called (are "public"), while methods internal to a certain header file are prefixed with "libvalinet_". 5 | 6 | Headers that compile only with C++ have an ".hpp" extension. ".h" files compile with both C, and C++ compilers. 7 | 8 | The following header files are currently available: 9 | 10 | * hooking/exeinject.h (-) - injects a DLL into a process and starts its entry point, reinjects should a crash occur 11 | * ini/ini.h (-) - manipulates ini files (subset of [CIni](https://www.codeproject.com/Articles/5401/CIni) ported to C) 12 | * internet/get.h - downloads a resource from the Internet and saves it to a file (uses WinINet) 13 | * internet/post/h - posts data to a web resource (uses WinINet) 14 | * pdb/pdb.h (depends on internet/get.h) [WIP] - downloads the symbol file of a library (by obtaining the path from the DLL), and retrieves the addresses of a set of symbol names; this works well, but is unfinished, having non-conformant method and symbol names; it is a subset of [pdbdump](https://gist.github.com/mridgers/2968595), and [PDBDownloader](https://github.com/rajkumar-rangaraj/PDB-Downloader) (ported from C# to C) 15 | 16 | Items marked with [WIP] are subject to having their "public" methods (structure) changed (names, parameters etc). Other items are subject to having new methods added or critical fixes implemented to existing methods. 17 | -------------------------------------------------------------------------------- /valinet/hooking/exeinject.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBVALINET_HOOKING_EXEINJECT_H_ 2 | #define LIBVALINET_HOOKING_EXEINJECT_H_ 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define MODULE_ARRAY_INITIAL_SIZE 100 9 | #define WM_APP_CRASHED WM_USER + 100 10 | #define ERROR_LOAD_LIBRARY 0x2 11 | #define ERROR_NO_MAIN_IN_INJECTION_LIB 0x21 12 | #define ERROR_GETMODULEHANDLE_KERNEL32 0x3 13 | #define ERROR_GETPROCADDRESS_LOADLIBRARYW 0x31 14 | #define ERROR_GETPROCADDRESS_FREELIBRARY 0x32 15 | #define ERROR_APP_NOT_RUNNING 0x4 16 | #define ERROR_APP_OPENPROCESS 0x41 17 | #define ERROR_APP_VIRTUALALLOC 0x5 18 | #define ERROR_APP_WRITEPROCESSMEMORY 0x51 19 | #define ERROR_FAILED_TO_INJECT 0x6 20 | #define ERROR_FAILED_TO_RUN_ENTRY_POINT 0x61 21 | #define ERROR_CANNOT_FIND_LIBRARY_IN_APP 0x8 22 | #define ERROR_MODULE_ARRAY_ALLOC 0x81 23 | #define ERROR_APP_MODULE_ENUM 0x82 24 | #define ERROR_MODULE_ARRAY_REALLOC 0x83 25 | #define ERROR_CANNOT_GET_ADDRESS_MODULE 0x84 26 | #define ERROR_CANNOT_RUN_INJECTION_MAIN 0x91 27 | #define ERROR_CANNOT_DETERMINE_STATUS_DLL 0x93 28 | #define ERROR_CREATE_MESSAGE_WINDOW 0x10 29 | #define ERROR_REGISTER_APP_WATCH 0x11 30 | #define ERROR_REGISTER_EXIT_HANDLER 0x12 31 | #define ERROR_MESSAGE_QUEUE 0x13 32 | #define ERROR_APP_CRASHED 0x222 33 | #define ERROR_FAILED_TO_CALL_FREELIBRARY 0x500 34 | #define ERROR_FREELIBRARY_FAILED 0x501 35 | #define HOOK_CLASSIC_LOOKUP 0x0 36 | #define HOOK_BY_SHELLCODE 0x1 37 | #define HOOK_METHOD HOOK_CLASSIC_LOOKUP 38 | 39 | LRESULT CALLBACK VnWindowProc( 40 | HWND hWnd, 41 | UINT uMsg, 42 | WPARAM wParam, 43 | LPARAM lParam 44 | ) 45 | { 46 | switch (uMsg) 47 | { 48 | case WM_CLOSE: 49 | case WM_DESTROY: 50 | PostQuitMessage(0); 51 | break; 52 | case WM_APP_CRASHED: 53 | PostMessage( 54 | hWnd, 55 | WM_QUIT, 56 | ERROR_APP_CRASHED, 57 | 0 58 | ); 59 | break; 60 | } 61 | return DefWindowProc(hWnd, uMsg, wParam, lParam); 62 | } 63 | 64 | VOID CALLBACK libvalinet_hooking_exeinject_WaitForDWMToCrash( 65 | _In_ PVOID lpParameter, 66 | _In_ BOOLEAN TimerOrWaitFired 67 | ) 68 | { 69 | SendMessage( 70 | (HWND)(lpParameter), 71 | WM_APP_CRASHED, 72 | 0, 73 | 0 74 | ); 75 | } 76 | 77 | DWORD libvalinet_hooking_exeinject_ExitHandler( 78 | HANDLE hProcess, 79 | HMODULE hMod, 80 | uintptr_t hInjection, 81 | FILE* stream, 82 | LPTHREAD_START_ROUTINE lpCustomExitHandler 83 | ) 84 | { 85 | HANDLE hThread = NULL; 86 | DWORD dwThreadExitCode = 0; 87 | 88 | hThread = CreateRemoteThread( 89 | hProcess, 90 | NULL, 91 | 0, 92 | (LPTHREAD_START_ROUTINE)((uintptr_t)hMod + (uintptr_t)hInjection), 93 | NULL, 94 | 0, 95 | NULL 96 | ); 97 | WaitForSingleObject( 98 | hThread, 99 | INFINITE 100 | ); 101 | GetExitCodeThread( 102 | hThread, 103 | &dwThreadExitCode 104 | ); 105 | if (dwThreadExitCode) 106 | { 107 | if (stream) 108 | { 109 | fprintf( 110 | stream, 111 | "E. Error while unhooking application (%d).\n", 112 | dwThreadExitCode 113 | ); 114 | } 115 | } 116 | 117 | if (stream) 118 | { 119 | fprintf( 120 | stream, 121 | "E. Successfully unhooked application.\n" 122 | ); 123 | } 124 | 125 | if (lpCustomExitHandler) 126 | { 127 | lpCustomExitHandler(NULL); 128 | } 129 | 130 | return ERROR_SUCCESS; 131 | } 132 | 133 | DWORD libvalinet_hooking_exeinject_FreeRemoteLibrary( 134 | HANDLE hProcess, 135 | HANDLE hMod, 136 | FARPROC hAddrFreeLibrary, 137 | FILE* stream 138 | ) 139 | { 140 | DWORD dwThreadExitCode = 0; 141 | HANDLE hThread = CreateRemoteThread( 142 | hProcess, 143 | NULL, 144 | 0, 145 | (LPTHREAD_START_ROUTINE)hAddrFreeLibrary, 146 | hMod, 147 | 0, 148 | NULL 149 | ); 150 | if (hThread == NULL) 151 | { 152 | 153 | if (stream) 154 | { 155 | fprintf( 156 | stream, 157 | "ERROR: Unable to call FreeLibrary.\n" 158 | ); 159 | } 160 | 161 | TerminateProcess(hProcess, 0); 162 | return ERROR_FAILED_TO_CALL_FREELIBRARY; 163 | } 164 | WaitForSingleObject( 165 | hThread, 166 | INFINITE 167 | ); 168 | BOOL bResult = GetExitCodeThread( 169 | hThread, 170 | &dwThreadExitCode 171 | ); 172 | if (!dwThreadExitCode || !bResult) 173 | { 174 | 175 | if (stream) 176 | { 177 | fprintf( 178 | stream, 179 | "ERROR: FreeLibrary failed.\n" 180 | ); 181 | } 182 | 183 | return ERROR_FREELIBRARY_FAILED; 184 | } 185 | 186 | if (stream) 187 | { 188 | fprintf( 189 | stream, 190 | "FreeLibrary OK.\n" 191 | ); 192 | } 193 | 194 | return ERROR_SUCCESS; 195 | } 196 | 197 | int VnInjectAndMonitorProcess( 198 | TCHAR* szLibPath, 199 | DWORD dwLibPathSize, 200 | char* entryPoint, 201 | const TCHAR* szProcessName, 202 | const TCHAR* szClassName, 203 | LPTHREAD_START_ROUTINE lpCrashOrFailureCallback, 204 | HINSTANCE hInstance, 205 | FILE* stream, 206 | DWORD dwRestartDelay, 207 | LRESULT (*lpWindowProc)(HWND, UINT, WPARAM, LPARAM), 208 | BOOL bWaitForProcess, 209 | DWORD dwCheckDelay, 210 | DWORD dwStartupDelay, 211 | LPTHREAD_START_ROUTINE lpCustomExitHandler, 212 | LPHANDLE lphProcess, 213 | HMODULE* lphMod, 214 | LPVOID* lphInjection, 215 | int* messages, 216 | DWORD messagesSize, 217 | HWND* lphwnd, 218 | LPVOID* lpParam 219 | ) 220 | { 221 | SIZE_T i = 0; 222 | BOOL bRet = FALSE; 223 | DWORD dwRet = 0; 224 | BOOL bErr = FALSE; 225 | HANDLE hProcess = NULL; 226 | HMODULE hMod = NULL; 227 | uintptr_t hInjection = NULL; 228 | HMODULE hKernel32 = NULL; 229 | FARPROC hAdrLoadLibraryW = NULL; 230 | FARPROC hAdrFreeLibrary = NULL; 231 | void* pLibRemote = NULL; 232 | void* pShellCode = NULL; 233 | wchar_t szTmpLibPath[_MAX_PATH]; 234 | BOOL bResult = FALSE; 235 | HANDLE hSnapshot = NULL; 236 | PROCESSENTRY32 stProcessEntry = { 0 }; 237 | DWORD dwProcessId = 0; 238 | HMODULE* hMods = NULL; 239 | DWORD hModuleArrayInitialBytesInitial = 240 | MODULE_ARRAY_INITIAL_SIZE * sizeof(HMODULE); 241 | DWORD hModuleArrayInitialBytes = hModuleArrayInitialBytesInitial; 242 | DWORD hModuleArrayBytesNeeded = 0; 243 | HMODULE hInjectionDll = NULL; 244 | FARPROC hInjectionMainFunc = NULL; 245 | WNDCLASS wc = { 0 }; 246 | HWND hWnd = NULL; 247 | MSG msg = { 0 }; 248 | HANDLE hWaitObject = NULL; 249 | HANDLE hThread = NULL; 250 | DWORD dwThreadExitCode = 0; 251 | SIZE_T dwBytesRead = 0; 252 | BYTE shellCode[] = 253 | { 254 | 0x53, 0x48, 0x89, 0xE3, 0x48, 0x83, 0xEC, 0x20, 0x66, 0x83, 255 | 0xE4, 0xC0, 0x48, 0xB9, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 256 | 0x41, 0x41, 0x48, 0xBA, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 257 | 0x41, 0x41, 0xFF, 0xD2, 0x48, 0xBA, 0x41, 0x41, 0x41, 0x41, 258 | 0x41, 0x41, 0x41, 0x41, 0x48, 0x89, 0x02, 0x48, 0x89, 0xDC, 259 | 0x5B, 0xC3 260 | }; 261 | // shell code injection technique on x64 courtesy of: 262 | // https://clymb3r.wordpress.com/2013/05/26/implementing-remote-loadlibrary-and-remote-getprocaddress-using-powershell-and-assembly/ 263 | /* x64 assembly is: 264 | [SECTION .text] 265 | global _start 266 | _start: 267 | ; Save rsp and setup stack for function call 268 | push rbx 269 | mov rbx, rsp 270 | sub rsp, 0x20 271 | and sp, 0xffc0 272 | 273 | ; Call LoadLibraryA 274 | mov rcx, 0x4141414141414141 ; Ptr to string of library, set by injector 275 | mov rdx, 0x4141414141414141 ; Address of LoadLibrary, set by injector 276 | call rdx 277 | 278 | mov rdx, 0x4141414141414141 ; Ptr to save result, set by injector 279 | mov [rdx], rax 280 | 281 | ; Fix stack 282 | mov rsp, rbx 283 | pop rbx 284 | ret 285 | */ 286 | 287 | // Step 1: Print library path 288 | wprintf( 289 | L"1. Hook Library Path: %s\n", 290 | szLibPath 291 | ); 292 | 293 | // Step 2: Get DLL entry point address 294 | hInjectionDll = LoadLibrary(szLibPath); 295 | if (hInjectionDll == NULL) 296 | { 297 | if (stream) 298 | { 299 | fprintf( 300 | stream, 301 | "2. ERROR: Cannot load injection library.\n" 302 | ); 303 | } 304 | return ERROR_LOAD_LIBRARY; 305 | } 306 | hInjectionMainFunc = GetProcAddress( 307 | hInjectionDll, 308 | entryPoint 309 | ); 310 | if (hInjectionMainFunc == NULL) 311 | { 312 | if (stream) 313 | { 314 | fprintf( 315 | stream, 316 | "2. ERROR: Injection library lacks entry point.\n" 317 | ); 318 | } 319 | return ERROR_NO_MAIN_IN_INJECTION_LIB; 320 | } 321 | hInjection = (uintptr_t)(hInjectionMainFunc) - (uintptr_t)(hInjectionDll); 322 | if (lphInjection) 323 | { 324 | *lphInjection = hInjection; 325 | } 326 | FreeLibrary(hInjectionDll); 327 | wprintf( 328 | L"2. Hook Library Entry Point: 0x%x\n", 329 | hInjection 330 | ); 331 | 332 | // Step 3: Get address of LoadLibraryW & FreeLibrary 333 | hKernel32 = GetModuleHandle(L"Kernel32"); 334 | if (hKernel32 == NULL) 335 | { 336 | if (stream) 337 | { 338 | fprintf( 339 | stream, 340 | "3. ERROR: Cannot find address of Kernel32.\n" 341 | ); 342 | } 343 | return ERROR_GETMODULEHANDLE_KERNEL32; 344 | } 345 | hAdrLoadLibraryW = GetProcAddress( 346 | hKernel32, 347 | "LoadLibraryW" 348 | ); 349 | if (hAdrLoadLibraryW == NULL) 350 | { 351 | if (stream) 352 | { 353 | fprintf( 354 | stream, 355 | "3. ERROR: Cannot find address of LoadLibraryW.\n" 356 | ); 357 | } 358 | return ERROR_GETPROCADDRESS_LOADLIBRARYW; 359 | } 360 | wprintf( 361 | L"3. LoadLibraryW address: %d\n", 362 | hAdrLoadLibraryW 363 | ); 364 | hAdrFreeLibrary = GetProcAddress( 365 | hKernel32, 366 | "FreeLibrary" 367 | ); 368 | if (hAdrFreeLibrary == NULL) 369 | { 370 | 371 | if (stream) 372 | { 373 | fprintf( 374 | stream, 375 | "3. ERROR: Cannot find address of FreeLibrary.\n" 376 | ); 377 | } 378 | 379 | return ERROR_GETPROCADDRESS_FREELIBRARY; 380 | } 381 | wprintf( 382 | L"3. FreeLibrary address: %d\n", 383 | hAdrFreeLibrary 384 | ); 385 | // Repeatedly inject application 386 | while (TRUE) 387 | { 388 | // Step 4: Find application.exe 389 | do 390 | { 391 | stProcessEntry.dwSize = sizeof(PROCESSENTRY32); 392 | hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); 393 | if (Process32First(hSnapshot, &stProcessEntry) == TRUE) 394 | { 395 | while (Process32Next(hSnapshot, &stProcessEntry) == TRUE) 396 | { 397 | if (!wcscmp(stProcessEntry.szExeFile, szProcessName)) 398 | { 399 | dwProcessId = stProcessEntry.th32ProcessID; 400 | hProcess = OpenProcess( 401 | PROCESS_ALL_ACCESS, 402 | FALSE, 403 | dwProcessId 404 | ); 405 | if (lphProcess) 406 | { 407 | *lphProcess = hProcess; 408 | } 409 | if (hProcess == NULL) 410 | { 411 | if (stream) 412 | { 413 | fprintf( 414 | stream, 415 | "4. ERROR: Cannot get handle to application.\n" 416 | ); 417 | } 418 | return ERROR_APP_OPENPROCESS; 419 | } 420 | if (stream) 421 | { 422 | fprintf( 423 | stream, 424 | "4. Found application, PID: %d\n", 425 | dwProcessId 426 | ); 427 | } 428 | break; 429 | } 430 | } 431 | } 432 | CloseHandle(hSnapshot); 433 | if (bWaitForProcess) 434 | { 435 | if (dwProcessId == 0) 436 | { 437 | if (stream) 438 | { 439 | fprintf(stream, "4. Waiting for application to start...\n"); 440 | } 441 | } 442 | else 443 | { 444 | break; 445 | } 446 | } 447 | else 448 | { 449 | if (dwProcessId == 0) 450 | { 451 | if (stream) 452 | { 453 | fprintf( 454 | stream, 455 | "4. ERROR: Application is not running.\n" 456 | ); 457 | } 458 | return ERROR_APP_NOT_RUNNING; 459 | } 460 | } 461 | Sleep(dwCheckDelay); 462 | } 463 | while (dwProcessId == 0); 464 | Sleep(dwStartupDelay); 465 | 466 | // Step 5: Write path to library in application's memory 467 | pLibRemote = VirtualAllocEx( 468 | hProcess, 469 | NULL, 470 | dwLibPathSize, 471 | MEM_COMMIT, 472 | PAGE_READWRITE 473 | ); 474 | if (pLibRemote == NULL) 475 | { 476 | if (stream) 477 | { 478 | fprintf( 479 | stream, 480 | "5. ERROR: Cannot alloc memory in application.\n" 481 | ); 482 | } 483 | return ERROR_APP_VIRTUALALLOC; 484 | } 485 | bResult = WriteProcessMemory( 486 | hProcess, 487 | pLibRemote, 488 | (void*)szLibPath, 489 | dwLibPathSize, 490 | NULL 491 | ); 492 | if (!bResult) 493 | { 494 | 495 | if (stream) 496 | { 497 | fprintf( 498 | stream, 499 | "5. ERROR: Cannot write memory in application.\n" 500 | ); 501 | } 502 | 503 | VirtualFreeEx( 504 | hProcess, 505 | (LPVOID)pLibRemote, 506 | 0, 507 | MEM_RELEASE 508 | ); 509 | return ERROR_APP_WRITEPROCESSMEMORY; 510 | } 511 | if (stream) 512 | { 513 | fprintf( 514 | stream, 515 | "5. Wrote library path in application's memory.\n" 516 | ); 517 | } 518 | 519 | #if HOOK_METHOD == HOOK_BY_SHELLCODE && _WIN64 520 | // Step 6: Write shell code to application's memory 521 | pShellCode = VirtualAllocEx( 522 | hProcess, 523 | NULL, 524 | dwLibPathSize, 525 | MEM_COMMIT, 526 | PAGE_EXECUTE_READWRITE 527 | ); 528 | if (pShellCode == NULL) 529 | { 530 | if (stream) 531 | { 532 | fprintf( 533 | stream, 534 | "6. ERROR: Cannot alloc memory in application.\n" 535 | ); 536 | } 537 | VirtualFreeEx( 538 | hProcess, 539 | (LPVOID)pLibRemote, 540 | 0, 541 | MEM_RELEASE 542 | ); 543 | return ERROR_APP_VIRTUALALLOC; 544 | } 545 | // Address of string containing path of module to load 546 | *((uintptr_t*)(shellCode + 14)) = (uintptr_t)pLibRemote; 547 | // Address of function to call (LoadLibraryW) 548 | *((uintptr_t*)(shellCode + 24)) = (uintptr_t)hAdrLoadLibraryW; 549 | // Address to write return value to 550 | // Writing on top of the path in order to spare some calls, 551 | // since the path is not required after calling LoadLibraryW 552 | *((uintptr_t*)(shellCode + 36)) = (uintptr_t)pLibRemote; 553 | bResult = WriteProcessMemory( 554 | hProcess, 555 | pShellCode, 556 | (void*)shellCode, 557 | sizeof(shellCode), 558 | NULL 559 | ); 560 | if (!bResult) 561 | { 562 | if (stream) 563 | { 564 | fprintf( 565 | stream, 566 | "6. ERROR: Cannot write memory in application.\n" 567 | ); 568 | } 569 | VirtualFreeEx( 570 | hProcess, 571 | (LPVOID)pLibRemote, 572 | 0, 573 | MEM_RELEASE 574 | ); 575 | VirtualFreeEx( 576 | hProcess, 577 | (LPVOID)pShellCode, 578 | 0, 579 | MEM_RELEASE 580 | ); 581 | return ERROR_APP_WRITEPROCESSMEMORY; 582 | } 583 | if (stream) 584 | { 585 | fprintf( 586 | stream, 587 | "6. Wrote shell code in application's memory.\n" 588 | ); 589 | } 590 | 591 | // Step 7: Call shell code 592 | hThread = CreateRemoteThread( 593 | hProcess, 594 | NULL, 595 | 0, 596 | (LPTHREAD_START_ROUTINE)pShellCode, 597 | NULL, 598 | 0, 599 | NULL 600 | ); 601 | if (hThread == NULL) 602 | { 603 | if (stream) 604 | { 605 | fprintf( 606 | stream, 607 | "7. ERROR: Failed to inject library into application.\n" 608 | ); 609 | } 610 | VirtualFreeEx( 611 | hProcess, 612 | (LPVOID)pLibRemote, 613 | 0, 614 | MEM_RELEASE 615 | ); 616 | VirtualFreeEx( 617 | hProcess, 618 | (LPVOID)pShellCode, 619 | 0, 620 | MEM_RELEASE 621 | ); 622 | return ERROR_FAILED_TO_INJECT; 623 | } 624 | WaitForSingleObject( 625 | hThread, 626 | INFINITE 627 | ); 628 | bResult = GetExitCodeThread( 629 | hThread, 630 | &dwThreadExitCode 631 | ); 632 | if (!dwThreadExitCode || !bResult) 633 | { 634 | if (stream) 635 | { 636 | fprintf( 637 | stream, 638 | "7. ERROR: Failed to run lib entry point in application.\n" 639 | ); 640 | } 641 | bErr = TRUE; 642 | } 643 | else 644 | { 645 | if (stream) 646 | { 647 | fprintf( 648 | stream, 649 | "7. Successfully injected library into application.\n" 650 | ); 651 | } 652 | } 653 | 654 | 655 | // Step 8: Check result and cleanup 656 | bResult = ReadProcessMemory( 657 | hProcess, 658 | pLibRemote, 659 | &hMod, 660 | sizeof(HMODULE), 661 | &dwBytesRead 662 | ); 663 | if (!bResult || dwBytesRead != sizeof(HMODULE)) 664 | { 665 | if (stream) 666 | { 667 | fprintf( 668 | stream, 669 | "8. ERROR: Cannot get address of loaded module.\n" 670 | ); 671 | } 672 | VirtualFreeEx( 673 | hProcess, 674 | (LPVOID)pLibRemote, 675 | 0, 676 | MEM_RELEASE 677 | ); 678 | VirtualFreeEx( 679 | hProcess, 680 | (LPVOID)pShellCode, 681 | 0, 682 | MEM_RELEASE 683 | ); 684 | TerminateProcess(hProcess, 0); 685 | return ERROR_CANNOT_GET_ADDRESS_MODULE; 686 | } 687 | if (lphMod) 688 | { 689 | *lphMod = hMod; 690 | } 691 | VirtualFreeEx( 692 | hProcess, 693 | (LPVOID)pLibRemote, 694 | 0, 695 | MEM_RELEASE 696 | ); 697 | VirtualFreeEx( 698 | hProcess, 699 | (LPVOID)pShellCode, 700 | 0, 701 | MEM_RELEASE 702 | ); 703 | if (bErr) 704 | { 705 | if (dwRet = libvalinet_hooking_exeinject_FreeRemoteLibrary( 706 | hProcess, 707 | hMod, 708 | hAdrFreeLibrary, 709 | stream 710 | )) 711 | { 712 | TerminateProcess(hProcess, 0); 713 | return dwRet; 714 | } 715 | return ERROR_FAILED_TO_RUN_ENTRY_POINT; 716 | } 717 | #else 718 | // Step 6: Load library in application 719 | hThread = CreateRemoteThread( 720 | hProcess, 721 | NULL, 722 | 0, 723 | (LPTHREAD_START_ROUTINE)hAdrLoadLibraryW, 724 | pLibRemote, 725 | 0, 726 | NULL 727 | ); 728 | if (hThread == NULL) 729 | { 730 | if (stream) 731 | { 732 | fprintf( 733 | stream, 734 | "6. ERROR: Failed to inject library into application.\n" 735 | ); 736 | } 737 | return ERROR_FAILED_TO_INJECT; 738 | } 739 | WaitForSingleObject( 740 | hThread, 741 | INFINITE 742 | ); 743 | bResult = GetExitCodeThread( 744 | hThread, 745 | &dwThreadExitCode 746 | ); 747 | if (!dwThreadExitCode || !bResult) 748 | { 749 | if (stream) 750 | { 751 | fprintf( 752 | stream, 753 | "6. ERROR: Failed to run library entry point in " 754 | "application.\n" 755 | ); 756 | } 757 | return ERROR_FAILED_TO_RUN_ENTRY_POINT; 758 | } 759 | hMod = (HMODULE)dwThreadExitCode; 760 | if (lphMod) 761 | { 762 | *lphMod = hMod; 763 | } 764 | if (stream) 765 | { 766 | fprintf( 767 | stream, 768 | "6. Successfully injected library into application.\n" 769 | ); 770 | } 771 | 772 | // Step 7: Free path from application's memory 773 | VirtualFreeEx( 774 | hProcess, 775 | (LPVOID)pLibRemote, 776 | 0, 777 | MEM_RELEASE 778 | ); 779 | if (stream) 780 | { 781 | fprintf( 782 | stream, 783 | "7. Freed path from application's memory.\n" 784 | ); 785 | } 786 | 787 | // Step 8: Get address of library in application's memory 788 | // This is actually optional, but application is not tested without 789 | hModuleArrayInitialBytes = hModuleArrayInitialBytesInitial; 790 | hMods = (HMODULE*)calloc( 791 | hModuleArrayInitialBytes, 792 | 1 793 | ); 794 | if (hMods == NULL) 795 | { 796 | 797 | if (stream) 798 | { 799 | fprintf( 800 | stream, 801 | "8. ERROR: Cannot allocate module array.\n" 802 | ); 803 | } 804 | 805 | if (dwRet = libvalinet_hooking_exeinject_FreeRemoteLibrary( 806 | hProcess, 807 | hMod, 808 | hAdrFreeLibrary, 809 | stream 810 | )) 811 | { 812 | TerminateProcess(hProcess, 0); 813 | return dwRet; 814 | } 815 | return ERROR_MODULE_ARRAY_ALLOC; 816 | } 817 | bResult = EnumProcessModulesEx( 818 | hProcess, 819 | hMods, 820 | hModuleArrayInitialBytes, 821 | &hModuleArrayBytesNeeded, 822 | LIST_MODULES_ALL 823 | ); 824 | if (!bResult) 825 | { 826 | 827 | if (stream) 828 | { 829 | fprintf( 830 | stream, 831 | "8. ERROR: Unable to enum modules in application.\n" 832 | ); 833 | } 834 | 835 | if (dwRet = libvalinet_hooking_exeinject_FreeRemoteLibrary( 836 | hProcess, 837 | hMod, 838 | hAdrFreeLibrary, 839 | stream 840 | )) 841 | { 842 | TerminateProcess(hProcess, 0); 843 | return dwRet; 844 | } 845 | return ERROR_APP_MODULE_ENUM; 846 | } 847 | if (hModuleArrayInitialBytes < hModuleArrayBytesNeeded) 848 | { 849 | hMods = (HMODULE*)realloc( 850 | hMods, 851 | hModuleArrayBytesNeeded 852 | ); 853 | if (hMods == NULL) 854 | { 855 | 856 | if (stream) 857 | { 858 | fprintf( 859 | stream, 860 | "8. ERROR: Cannot reallocate module array.\n" 861 | ); 862 | } 863 | 864 | if (dwRet = libvalinet_hooking_exeinject_FreeRemoteLibrary( 865 | hProcess, 866 | hMod, 867 | hAdrFreeLibrary, 868 | stream 869 | )) 870 | { 871 | TerminateProcess(hProcess, 0); 872 | return dwRet; 873 | } 874 | return ERROR_MODULE_ARRAY_REALLOC; 875 | } 876 | hModuleArrayInitialBytes = hModuleArrayBytesNeeded; 877 | bResult = EnumProcessModulesEx( 878 | hProcess, 879 | hMods, 880 | hModuleArrayInitialBytes, 881 | &hModuleArrayBytesNeeded, 882 | LIST_MODULES_ALL 883 | ); 884 | if (!bResult) 885 | { 886 | 887 | if (stream) 888 | { 889 | fprintf( 890 | stream, 891 | "8. ERROR: Unable to enum modules in application.\n" 892 | ); 893 | } 894 | 895 | if (dwRet = libvalinet_hooking_exeinject_FreeRemoteLibrary( 896 | hProcess, 897 | hMod, 898 | hAdrFreeLibrary, 899 | stream 900 | )) 901 | { 902 | TerminateProcess(hProcess, 0); 903 | return dwRet; 904 | } 905 | return ERROR_APP_MODULE_ENUM; 906 | } 907 | } 908 | CharLower(szLibPath); 909 | if (hModuleArrayBytesNeeded / sizeof(HMODULE) == 0) 910 | { 911 | i = -1; 912 | } 913 | else 914 | { 915 | for (i = 0; i <= hModuleArrayBytesNeeded / sizeof(HMODULE); ++i) 916 | { 917 | if (i == hModuleArrayBytesNeeded / sizeof(HMODULE)) 918 | { 919 | i = -1; 920 | break; 921 | } 922 | bResult = GetModuleFileNameEx( 923 | hProcess, 924 | hMods[i], 925 | szTmpLibPath, 926 | _MAX_PATH 927 | ); 928 | if (bResult) 929 | { 930 | CharLower(szTmpLibPath); 931 | if (!wcscmp(szTmpLibPath, szLibPath)) 932 | { 933 | break; 934 | } 935 | } 936 | } 937 | } 938 | if (i == -1) 939 | { 940 | 941 | if (stream) 942 | { 943 | fprintf( 944 | stream, 945 | "8. ERROR: Cannot find library in application's memory.\n" 946 | ); 947 | } 948 | 949 | if (dwRet = libvalinet_hooking_exeinject_FreeRemoteLibrary( 950 | hProcess, 951 | hMod, 952 | hAdrFreeLibrary, 953 | stream 954 | )) 955 | { 956 | TerminateProcess(hProcess, 0); 957 | return dwRet; 958 | } 959 | return ERROR_CANNOT_FIND_LIBRARY_IN_APP; 960 | } 961 | 962 | wprintf( 963 | L"8. Found library in application's memory (%d/%d).\n", 964 | i, 965 | hModuleArrayBytesNeeded / sizeof(HMODULE) 966 | ); 967 | 968 | hMod = hMods[i]; 969 | if (lphMod) 970 | { 971 | *lphMod = hMod; 972 | } 973 | free(hMods); 974 | #endif 975 | 976 | // Step 9: Register and create window 977 | wc.style = CS_DBLCLKS; 978 | wc.lpfnWndProc = lpWindowProc ? lpWindowProc : VnWindowProc; 979 | wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 980 | wc.hInstance = hInstance; 981 | wc.lpszClassName = szClassName; 982 | wc.hCursor = LoadCursorW(NULL, IDC_ARROW); 983 | RegisterClass(&wc); 984 | hWnd = CreateWindowEx( 985 | 0, // Optional window styles 986 | szClassName, // Window class 987 | TEXT(""), // Window text 988 | WS_OVERLAPPEDWINDOW, // Window style 989 | // Size and position 990 | CW_USEDEFAULT, 991 | CW_USEDEFAULT, 992 | CW_USEDEFAULT, 993 | CW_USEDEFAULT, 994 | NULL, // Parent window 995 | NULL, // Menu 996 | hInstance, // Instance handle 997 | NULL // Additional application data 998 | ); 999 | if (!hWnd) 1000 | { 1001 | if (stream) 1002 | { 1003 | fprintf( 1004 | stream, 1005 | "10. Failed to create message window (%d).\n", 1006 | GetLastError() 1007 | ); 1008 | } 1009 | libvalinet_hooking_exeinject_ExitHandler( 1010 | hProcess, 1011 | hMod, 1012 | hInjection, 1013 | stream, 1014 | lpCustomExitHandler 1015 | ); 1016 | return ERROR_CREATE_MESSAGE_WINDOW; 1017 | } 1018 | if (stream) 1019 | { 1020 | fprintf( 1021 | stream, 1022 | "10. Successfully created message window (%d).\n", 1023 | hWnd 1024 | ); 1025 | } 1026 | for (i = 0; i < messagesSize; ++i) 1027 | { 1028 | ChangeWindowMessageFilter( 1029 | messages[i], 1030 | MSGFLT_ADD 1031 | ); 1032 | } 1033 | if (lphwnd) 1034 | { 1035 | *lphwnd = hWnd; 1036 | } 1037 | 1038 | // Step 10: Run DLL's entry point 1039 | hThread = CreateRemoteThread( 1040 | hProcess, 1041 | NULL, 1042 | 0, 1043 | (LPTHREAD_START_ROUTINE)((uintptr_t)hMod + (uintptr_t)hInjection), 1044 | lpParam ? *lpParam : NULL, 1045 | 0, 1046 | NULL 1047 | ); 1048 | if (hThread == NULL) 1049 | { 1050 | if (stream) 1051 | { 1052 | fprintf( 1053 | stream, 1054 | "9. ERROR: Cannot execute injection entry point.\n" 1055 | ); 1056 | } 1057 | if (dwRet = libvalinet_hooking_exeinject_FreeRemoteLibrary( 1058 | hProcess, 1059 | hMod, 1060 | hAdrFreeLibrary, 1061 | stream 1062 | )) 1063 | { 1064 | TerminateProcess(hProcess, 0); 1065 | return dwRet; 1066 | } 1067 | return ERROR_CANNOT_RUN_INJECTION_MAIN; 1068 | } 1069 | WaitForSingleObject( 1070 | hThread, 1071 | INFINITE 1072 | ); 1073 | bResult = GetExitCodeThread( 1074 | hThread, 1075 | &dwThreadExitCode 1076 | ); 1077 | if (!bResult) 1078 | { 1079 | if (stream) 1080 | { 1081 | fprintf( 1082 | stream, 1083 | "9. ERROR: Cannot determine status of injected DLL.\n" 1084 | ); 1085 | } 1086 | if (dwRet = libvalinet_hooking_exeinject_FreeRemoteLibrary( 1087 | hProcess, 1088 | hMod, 1089 | hAdrFreeLibrary, 1090 | stream 1091 | )) 1092 | { 1093 | TerminateProcess(hProcess, 0); 1094 | return dwRet; 1095 | } 1096 | return ERROR_CANNOT_DETERMINE_STATUS_DLL; 1097 | } 1098 | if (dwThreadExitCode) 1099 | { 1100 | if (lpCrashOrFailureCallback != NULL) 1101 | { 1102 | if (dwRet = 1103 | lpCrashOrFailureCallback((LPVOID)dwThreadExitCode)) 1104 | { 1105 | return dwRet; 1106 | } 1107 | } 1108 | else 1109 | { 1110 | return dwThreadExitCode; 1111 | } 1112 | } 1113 | if (stream) 1114 | { 1115 | fprintf( 1116 | stream, 1117 | "9. Successfully hooked application.\n" 1118 | ); 1119 | } 1120 | 1121 | // Step 11: Listen for application crashes 1122 | RegisterWaitForSingleObject( 1123 | &hWaitObject, 1124 | hProcess, 1125 | (WAITORTIMERCALLBACK) 1126 | (libvalinet_hooking_exeinject_WaitForDWMToCrash), 1127 | (PVOID)(hWnd), 1128 | INFINITE, 1129 | WT_EXECUTEONLYONCE 1130 | ); 1131 | if (!hWaitObject) 1132 | { 1133 | if (stream) 1134 | { 1135 | fprintf( 1136 | stream, 1137 | "11. Unable to register for watching application.\n" 1138 | ); 1139 | } 1140 | libvalinet_hooking_exeinject_ExitHandler( 1141 | hProcess, 1142 | hMod, 1143 | hInjection, 1144 | stream, 1145 | lpCustomExitHandler 1146 | ); 1147 | return ERROR_REGISTER_APP_WATCH; 1148 | } 1149 | if (stream) 1150 | { 1151 | fprintf( 1152 | stream, 1153 | "11. Registered for watching application.\n" 1154 | ); 1155 | } 1156 | 1157 | // Step 13: Listen for messages 1158 | if (stream) 1159 | { 1160 | fprintf( 1161 | stream, 1162 | "Listening for messages...\n" 1163 | ); 1164 | } 1165 | while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) 1166 | { 1167 | if (bRet == -1) 1168 | { 1169 | libvalinet_hooking_exeinject_ExitHandler( 1170 | hProcess, 1171 | hMod, 1172 | hInjection, 1173 | stream, 1174 | lpCustomExitHandler 1175 | ); 1176 | return ERROR_MESSAGE_QUEUE; 1177 | } 1178 | else 1179 | { 1180 | TranslateMessage(&msg); 1181 | DispatchMessage(&msg); 1182 | } 1183 | } 1184 | if (msg.wParam != ERROR_APP_CRASHED) 1185 | { 1186 | if (stream) 1187 | { 1188 | fprintf( 1189 | stream, 1190 | "Shutting down application...\n" 1191 | ); 1192 | } 1193 | libvalinet_hooking_exeinject_ExitHandler( 1194 | hProcess, 1195 | hMod, 1196 | hInjection, 1197 | stream, 1198 | lpCustomExitHandler 1199 | ); 1200 | return ERROR_SUCCESS; 1201 | } 1202 | // not required; in fact, it will post a WM_QUIT 1203 | // for the next window we spawn; really stupid idea 1204 | //DestroyWindow(hWnd); 1205 | UnregisterClass(szClassName, hInstance); 1206 | 1207 | if (stream) 1208 | { 1209 | fprintf( 1210 | stream, 1211 | "Application was restarted, rehooking...\n" 1212 | ); 1213 | } 1214 | 1215 | // wait a bit for application to respawn 1216 | Sleep(dwRestartDelay); 1217 | } 1218 | return ERROR_SUCCESS; 1219 | } 1220 | 1221 | #endif -------------------------------------------------------------------------------- /valinet/hooking/iatpatch.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBVALINET_HOOKING_IATPATCH_H_ 2 | #define LIBVALINET_HOOKING_IATPATCH_H_ 3 | #include 4 | #include 5 | #ifdef _LIBVALINET_DEBUG_HOOKING_IATPATCH 6 | #include 7 | #include 8 | #endif 9 | // https://blog.neteril.org/blog/2016/12/23/diverting-functions-windows-iat-patching/ 10 | inline BOOL VnPatchIAT(HMODULE hMod, PSTR libName, PSTR funcName, uintptr_t hookAddr) 11 | { 12 | // Increment module reference count to prevent other threads from unloading it while we're working with it 13 | HMODULE module; 14 | if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)hMod, &module)) return FALSE; 15 | 16 | // Get a reference to the import table to locate the kernel32 entry 17 | ULONG size; 18 | PIMAGE_IMPORT_DESCRIPTOR importDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToDataEx(module, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size, NULL); 19 | 20 | // In the import table find the entry that corresponds to kernel32 21 | BOOL found = FALSE; 22 | while (importDescriptor->Characteristics && importDescriptor->Name) { 23 | PSTR importName = (PSTR)((PBYTE)module + importDescriptor->Name); 24 | if (_stricmp(importName, libName) == 0) { 25 | #ifdef _LIBVALINET_DEBUG_HOOKING_IATPATCH 26 | printf("[PatchIAT] Found %s in IAT.\n", libName); 27 | #endif 28 | found = TRUE; 29 | break; 30 | } 31 | importDescriptor++; 32 | } 33 | if (!found) { 34 | FreeLibrary(module); 35 | return FALSE; 36 | } 37 | 38 | // From the kernel32 import descriptor, go over its IAT thunks to 39 | // find the one used by the rest of the code to call GetProcAddress 40 | PIMAGE_THUNK_DATA oldthunk = (PIMAGE_THUNK_DATA)((PBYTE)module + importDescriptor->OriginalFirstThunk); 41 | PIMAGE_THUNK_DATA thunk = (PIMAGE_THUNK_DATA)((PBYTE)module + importDescriptor->FirstThunk); 42 | while (thunk->u1.Function) { 43 | PROC* funcStorage = (PROC*)&thunk->u1.Function; 44 | 45 | BOOL bFound = FALSE; 46 | if (oldthunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) 47 | { 48 | bFound = (!(*((WORD*)&(funcName)+1)) && IMAGE_ORDINAL32(oldthunk->u1.Ordinal) == (DWORD)funcName); 49 | } 50 | else 51 | { 52 | PIMAGE_IMPORT_BY_NAME byName = (PIMAGE_IMPORT_BY_NAME)((uintptr_t)module + oldthunk->u1.AddressOfData); 53 | bFound = ((*((WORD*)&(funcName)+1)) && !_stricmp((char*)byName->Name, funcName)); 54 | } 55 | 56 | // Found it, now let's patch it 57 | if (bFound) { 58 | // Get the memory page where the info is stored 59 | MEMORY_BASIC_INFORMATION mbi; 60 | VirtualQuery(funcStorage, &mbi, sizeof(MEMORY_BASIC_INFORMATION)); 61 | 62 | // Try to change the page to be writable if it's not already 63 | if (!VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_READWRITE, &mbi.Protect)) { 64 | FreeLibrary(module); 65 | return FALSE; 66 | } 67 | 68 | // Store our hook 69 | *funcStorage = (PROC)hookAddr; 70 | #ifdef _LIBVALINET_DEBUG_HOOKING_IATPATCH 71 | if ((*((WORD*)&(funcName)+1))) 72 | { 73 | printf("[PatchIAT] Patched %s in %s to 0x%p.\n", funcName, libName, hookAddr); 74 | } 75 | else 76 | { 77 | printf("[PatchIAT] Patched 0x%x in %s to 0x%p.\n", funcName, libName, hookAddr); 78 | } 79 | #endif 80 | 81 | // Restore the old flag on the page 82 | DWORD dwOldProtect; 83 | VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &dwOldProtect); 84 | 85 | // Profit 86 | FreeLibrary(module); 87 | return TRUE; 88 | } 89 | 90 | thunk++; 91 | oldthunk++; 92 | } 93 | 94 | FreeLibrary(module); 95 | return FALSE; 96 | } 97 | 98 | // https://stackoverflow.com/questions/50973053/how-to-hook-delay-imports 99 | inline BOOL VnPatchDelayIAT(HMODULE hMod, PSTR libName, PSTR funcName, uintptr_t hookAddr) 100 | { 101 | // Increment module reference count to prevent other threads from unloading it while we're working with it 102 | HMODULE lib; 103 | if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)hMod, &lib)) return FALSE; 104 | 105 | PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)lib; 106 | PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((uintptr_t)lib + dos->e_lfanew); 107 | PIMAGE_DELAYLOAD_DESCRIPTOR dload = (PIMAGE_DELAYLOAD_DESCRIPTOR)((uintptr_t)lib + 108 | nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress); 109 | while (dload->DllNameRVA) 110 | { 111 | char* dll = (char*)((uintptr_t)lib + dload->DllNameRVA); 112 | if (!_stricmp(dll, libName)) { 113 | #ifdef _LIBVALINET_DEBUG_HOOKING_IATPATCH 114 | printf("[PatchDelayIAT] Found %s in IAT.\n", libName); 115 | #endif 116 | 117 | PIMAGE_THUNK_DATA firstthunk = (PIMAGE_THUNK_DATA)((uintptr_t)lib + dload->ImportNameTableRVA); 118 | PIMAGE_THUNK_DATA functhunk = (PIMAGE_THUNK_DATA)((uintptr_t)lib + dload->ImportAddressTableRVA); 119 | while (firstthunk->u1.AddressOfData) 120 | { 121 | if (firstthunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) 122 | { 123 | if (!(*((WORD*)&(funcName)+1)) && IMAGE_ORDINAL32(firstthunk->u1.Ordinal) == (DWORD)funcName) 124 | { 125 | DWORD oldProtect; 126 | if (VirtualProtect(&functhunk->u1.Function, sizeof(uintptr_t), PAGE_EXECUTE_READWRITE, &oldProtect)) 127 | { 128 | functhunk->u1.Function = (uintptr_t)hookAddr; 129 | VirtualProtect(&functhunk->u1.Function, sizeof(uintptr_t), oldProtect, &oldProtect); 130 | #ifdef _LIBVALINET_DEBUG_HOOKING_IATPATCH 131 | printf("[PatchDelayIAT] Patched 0x%x in %s to 0x%p.\n", funcName, libName, hookAddr); 132 | #endif 133 | FreeLibrary(lib); 134 | return TRUE; 135 | } 136 | FreeLibrary(lib); 137 | return FALSE; 138 | } 139 | } 140 | else 141 | { 142 | PIMAGE_IMPORT_BY_NAME byName = (PIMAGE_IMPORT_BY_NAME)((uintptr_t)lib + firstthunk->u1.AddressOfData); 143 | if ((*((WORD*)&(funcName)+1)) && !_stricmp((char*)byName->Name, funcName)) 144 | { 145 | DWORD oldProtect; 146 | if (VirtualProtect(&functhunk->u1.Function, sizeof(uintptr_t), PAGE_EXECUTE_READWRITE, &oldProtect)) 147 | { 148 | functhunk->u1.Function = (uintptr_t)hookAddr; 149 | VirtualProtect(&functhunk->u1.Function, sizeof(uintptr_t), oldProtect, &oldProtect); 150 | #ifdef _LIBVALINET_DEBUG_HOOKING_IATPATCH 151 | printf("[PatchDelayIAT] Patched %s in %s to 0x%p.\n", funcName, libName, hookAddr); 152 | #endif 153 | FreeLibrary(lib); 154 | return TRUE; 155 | } 156 | FreeLibrary(lib); 157 | return FALSE; 158 | } 159 | } 160 | functhunk++; 161 | firstthunk++; 162 | } 163 | } 164 | dload++; 165 | } 166 | FreeLibrary(lib); 167 | return FALSE; 168 | } 169 | #endif -------------------------------------------------------------------------------- /valinet/ini/ini.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBVALINET_INI_INI_H_ 2 | #define LIBVALINET_INI_INI_H_ 3 | 4 | // adapted from original source code: 5 | // https://www.codeproject.com/Articles/5401/CIni 6 | 7 | #include 8 | #include 9 | 10 | #define DEF_PROFILE_NUM_LEN 64 11 | #define DEF_PROFILE_THRESHOLD 512 12 | 13 | LPTSTR libvalinet_ini_ini_GetStringDynamic( 14 | LPCTSTR lpSection, 15 | LPCTSTR lpKey, 16 | LPCTSTR lpDefault, 17 | LPCWSTR m_pszPathName 18 | ) 19 | { 20 | TCHAR* psz = NULL; 21 | if (lpSection == NULL || lpKey == NULL) 22 | { 23 | // Invalid section or key name, just return the default string 24 | if (lpDefault == NULL) 25 | { 26 | // Empty string 27 | psz = (TCHAR*)malloc(sizeof(TCHAR)); 28 | if (psz) 29 | { 30 | *psz = _T('\0'); 31 | } 32 | } 33 | else 34 | { 35 | psz = (TCHAR*)malloc(sizeof(TCHAR) * (_tcslen(lpDefault) + 1)); 36 | if (psz) 37 | { 38 | _tcscpy_s( 39 | psz, 40 | sizeof(TCHAR) * (_tcslen(lpDefault) + 1), 41 | lpDefault 42 | ); 43 | } 44 | } 45 | 46 | return psz; 47 | } 48 | 49 | // Keep enlarging the buffer size until being certain on that the string we 50 | // retrieved was original(not truncated). 51 | DWORD dwLen = DEF_PROFILE_THRESHOLD; 52 | psz = (TCHAR*)malloc(sizeof(TCHAR) * ((SIZE_T)dwLen + 1)); 53 | DWORD dwCopied = GetPrivateProfileString( 54 | lpSection, 55 | lpKey, 56 | lpDefault == NULL ? _T("") : lpDefault, 57 | psz, 58 | dwLen, 59 | m_pszPathName 60 | ); 61 | while (dwCopied + 1 >= dwLen) 62 | { 63 | dwLen += DEF_PROFILE_THRESHOLD; 64 | free(psz); 65 | psz = (TCHAR*)malloc(sizeof(TCHAR) * ((SIZE_T)dwLen + 1)); 66 | dwCopied = GetPrivateProfileString( 67 | lpSection, 68 | lpKey, 69 | lpDefault == NULL ? _T("") : lpDefault, 70 | psz, 71 | dwLen, 72 | m_pszPathName 73 | ); 74 | } 75 | 76 | return psz; // !!! Requires the caller to free this memory !!! 77 | } 78 | 79 | DWORD VnGetString( 80 | LPCTSTR lpSection, 81 | LPCTSTR lpKey, 82 | LPTSTR lpBuffer, 83 | DWORD dwBufferSize, 84 | DWORD dwBufSize, 85 | LPCTSTR lpDefault, 86 | LPCWSTR m_pszPathName 87 | ) 88 | { 89 | if (lpBuffer != NULL) 90 | *lpBuffer = _T('\0'); 91 | 92 | LPTSTR psz = libvalinet_ini_ini_GetStringDynamic( 93 | lpSection, 94 | lpKey, 95 | lpDefault, 96 | m_pszPathName 97 | ); 98 | DWORD dwLen = _tcslen(psz); 99 | 100 | if (lpBuffer != NULL) 101 | { 102 | _tcsncpy_s( 103 | lpBuffer, 104 | dwBufferSize, 105 | psz, 106 | dwBufSize 107 | ); 108 | dwLen = min(dwLen, dwBufSize); 109 | } 110 | 111 | free(psz); 112 | return dwLen; 113 | } 114 | 115 | UINT VnGetUInt( 116 | LPCTSTR lpSection, 117 | LPCTSTR lpKey, 118 | UINT nDefault, 119 | LPCWSTR m_pszPathName 120 | ) 121 | { 122 | TCHAR sz[DEF_PROFILE_NUM_LEN + 1] = _T(""); 123 | VnGetString( 124 | lpSection, 125 | lpKey, 126 | sz, 127 | sizeof(sz) / sizeof(TCHAR), 128 | DEF_PROFILE_NUM_LEN, 129 | NULL, 130 | m_pszPathName 131 | ); 132 | return *sz == _T('\0') ? 133 | nDefault : 134 | (UINT)(_tcstoul(sz, NULL, 10)); 135 | } 136 | 137 | BOOL VnWriteString( 138 | LPCTSTR lpSection, 139 | LPCTSTR lpKey, 140 | LPCTSTR lpValue, 141 | LPCWSTR m_pszPathName 142 | ) 143 | { 144 | if (lpSection == NULL || lpKey == NULL) 145 | return FALSE; 146 | 147 | return WritePrivateProfileString( 148 | lpSection, 149 | lpKey, 150 | lpValue == NULL ? _T("") : lpValue, 151 | m_pszPathName 152 | ); 153 | } 154 | 155 | BOOL VnWriteUInt( 156 | LPCTSTR lpSection, 157 | LPCTSTR lpKey, 158 | UINT nValue, 159 | LPCWSTR m_pszPathName 160 | ) 161 | { 162 | TCHAR szValue[DEF_PROFILE_NUM_LEN + 1] = _T(""); 163 | _stprintf_s( 164 | szValue, 165 | DEF_PROFILE_NUM_LEN + 1, 166 | _T("%u"), 167 | nValue 168 | ); 169 | return VnWriteString( 170 | lpSection, 171 | lpKey, 172 | szValue, 173 | m_pszPathName 174 | ); 175 | } 176 | 177 | #endif // #ifndef __INI_H_ -------------------------------------------------------------------------------- /valinet/internet/get.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBVALINET_INTERNET_GET_H_ 2 | #define LIBVALINET_INTERNET_GET_H_ 3 | #include 4 | #include 5 | #include 6 | #pragma comment(lib, "Wininet.lib") 7 | 8 | DWORD VnDownloadFile( 9 | char* filename, 10 | char* hostname, 11 | char* path, 12 | char* userAgent, 13 | INTERNET_PORT nServerPort, 14 | DWORD dwService, 15 | char* referrer, 16 | char* headers, 17 | DWORD bufsiz 18 | ) 19 | { 20 | DWORD dwRet = 0; 21 | HINTERNET hInternet; 22 | if (hInternet = InternetOpenA( 23 | userAgent, 24 | INTERNET_OPEN_TYPE_DIRECT, 25 | NULL, 26 | NULL, 27 | NULL 28 | )) 29 | { 30 | HINTERNET hConnect; 31 | if (hConnect = InternetConnectA( 32 | hInternet, 33 | hostname, 34 | nServerPort, 35 | NULL, 36 | NULL, 37 | dwService, 38 | NULL, 39 | NULL 40 | )) 41 | { 42 | HINTERNET hRequest; 43 | if (hRequest = HttpOpenRequestA( 44 | hConnect, 45 | "GET", 46 | path, 47 | NULL, 48 | referrer, 49 | NULL, 50 | NULL, 51 | NULL 52 | )) 53 | { 54 | char data[1] = ""; 55 | if (HttpSendRequestA( 56 | hRequest, 57 | headers, 58 | strlen(headers), 59 | (LPVOID)(data), 60 | strlen(data) * sizeof(char) 61 | )) 62 | { 63 | FILE* f = NULL; 64 | if (fopen_s( 65 | &f, 66 | filename, 67 | "wb" 68 | )) 69 | { 70 | dwRet = 7; 71 | } 72 | else 73 | { 74 | BYTE* buffer = (BYTE*)malloc(bufsiz); 75 | if (buffer == NULL) 76 | { 77 | dwRet = 6; 78 | } 79 | else 80 | { 81 | DWORD dwRead; 82 | BOOL bRet = TRUE; 83 | while (bRet = InternetReadFile( 84 | hRequest, 85 | buffer, 86 | bufsiz, 87 | &dwRead 88 | )) 89 | { 90 | if (dwRead == 0) 91 | { 92 | break; 93 | } 94 | fwrite( 95 | buffer, 96 | sizeof(BYTE), 97 | dwRead, 98 | f 99 | ); 100 | dwRead = 0; 101 | } 102 | if (bRet == FALSE) 103 | { 104 | dwRet = 5; 105 | } 106 | free(buffer); 107 | } 108 | fclose(f); 109 | } 110 | } 111 | else 112 | { 113 | dwRet = 4; 114 | } 115 | InternetCloseHandle(hRequest); 116 | } 117 | else 118 | { 119 | dwRet = 3; 120 | } 121 | InternetCloseHandle(hConnect); 122 | } 123 | else 124 | { 125 | dwRet = 2; 126 | } 127 | InternetCloseHandle(hInternet); 128 | } 129 | else 130 | { 131 | dwRet = 1; 132 | } 133 | return dwRet; 134 | } 135 | 136 | #endif -------------------------------------------------------------------------------- /valinet/internet/post.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBVALINET_INTERNET_POST_H_ 2 | #define LIBVALINET_INTERNET_POST_H_ 3 | #include 4 | #include 5 | #include 6 | #pragma comment(lib, "Wininet.lib") 7 | 8 | DWORD VnPostData( 9 | char* data, 10 | char* hostname, 11 | char* path, 12 | char* userAgent, 13 | INTERNET_PORT nServerPort, 14 | DWORD dwService, 15 | char* referrer, 16 | char* headers 17 | ) 18 | { 19 | DWORD dwRet = ERROR_SUCCESS; 20 | HINTERNET hInternet; 21 | if (hInternet = InternetOpenA( 22 | userAgent, 23 | INTERNET_OPEN_TYPE_DIRECT, 24 | NULL, 25 | NULL, 26 | NULL 27 | )) 28 | { 29 | HINTERNET hConnect; 30 | if (hConnect = InternetConnectA( 31 | hInternet, 32 | hostName, 33 | nServerPort, 34 | NULL, 35 | NULL, 36 | dwService, 37 | NULL, 38 | NULL 39 | )) 40 | { 41 | HINTERNET hRequest; 42 | if (hRequest = HttpOpenRequestA( 43 | hConnect, 44 | "POST", 45 | path, 46 | NULL, 47 | referrer, 48 | NULL, 49 | NULL, 50 | NULL 51 | )) 52 | { 53 | if (!HttpSendRequestA( 54 | hRequest, 55 | headers, 56 | wcslen(headers), 57 | reinterpret_cast(const_cast(data)), 58 | strlen(data) * sizeof(char) 59 | )) 60 | { 61 | dwRet = 4; 62 | } 63 | InternetCloseHandle(hRequest); 64 | } 65 | else 66 | { 67 | dwRet = 3; 68 | } 69 | InternetCloseHandle(hConnect); 70 | } 71 | else 72 | { 73 | dwRet = 2; 74 | } 75 | InternetCloseHandle(hInternet); 76 | } 77 | else 78 | { 79 | dwRet = 1; 80 | } 81 | return dwRet; 82 | } 83 | #endif -------------------------------------------------------------------------------- /valinet/pdb/pdb.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBVALINET_PDB_PDB_H_ 2 | #define LIBVALINET_PDB_PDB_H_ 3 | // 4 | // pdb includes: 5 | // * pdbdump - Small tool to list and query symbols in PDB files. 6 | // original source code: https://gist.github.com/mridgers/2968595 7 | // * PDBDownloader 8 | // original source code: https://github.com/rajkumar-rangaraj/PDB-Downloader 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #pragma comment(lib, "dbghelp.lib") 16 | #include 17 | #pragma comment(lib, "Shlwapi.lib") 18 | 19 | #define ASSERT(x, m, ...) if (!(x)) { fprintf(stderr, m, __VA_ARGS__); \ 20 | exit(-1); } 21 | #define VN_PDB_ONE_MB (10240 * 10240) 22 | #define VN_PDB_ADDRESS_OFFSET 0x400000 23 | #define VN_PDB_SYMBOL_HOSTNAME "msdl.microsoft.com" 24 | #define VN_PDB_SYMBOL_WEB "/download/symbols/" 25 | #define VN_PDB_USER_AGENT "Microsoft-Symbol-Server/10.0.10036.206" 26 | #define VN_PDB_FORM_HEADERS "Content-Type: application/octet-stream;\r\n" 27 | #define VN_PDB_DOWNLOAD_FILE_BUFFER_SIZE 4096 28 | 29 | // https://deplinenoise.wordpress.com/2013/06/14/getting-your-pdb-name-from-a-running-executable-windows/ 30 | typedef struct _PdbInfo 31 | { 32 | DWORD Signature; 33 | GUID Guid; 34 | DWORD Age; 35 | char PdbFileName[1]; 36 | }; 37 | typedef struct _PdbInfo PdbInfo; 38 | 39 | //------------------------------------------------------------------------------ 40 | // https://stackoverflow.com/questions/3828835/how-can-we-check-if-a-file-exists-or-not-using-win32-program 41 | int fileExists(char* file) 42 | { 43 | WIN32_FIND_DATAA FindFileData; 44 | HANDLE handle = FindFirstFileA(file, &FindFileData); 45 | int found = handle != INVALID_HANDLE_VALUE; 46 | if (found) 47 | { 48 | FindClose(handle); 49 | } 50 | return found; 51 | } 52 | 53 | enum e_mode 54 | { 55 | e_mode_resolve_stdin, 56 | e_mode_enum_symbols, 57 | }; 58 | 59 | enum e_enum_type 60 | { 61 | e_enum_type_symbols, 62 | e_enum_type_types 63 | }; 64 | 65 | struct _sym_info 66 | { 67 | DWORD64 addr; 68 | int size; 69 | char* name; 70 | char* file; 71 | int tag : 8; 72 | int line : 24; 73 | }; 74 | typedef struct _sym_info sym_info_t; 75 | 76 | struct _pool 77 | { 78 | char* base; 79 | int committed; 80 | int size; 81 | int used; 82 | }; 83 | typedef struct _pool pool_t; 84 | 85 | typedef int (sort_func_t)(const sym_info_t*, const sym_info_t*); 86 | 87 | int g_page_size = 0; 88 | HANDLE g_handle = (HANDLE)0x493; 89 | int g_csv_output = 0; 90 | int g_sym_count = 0; 91 | enum e_mode g_mode = e_mode_enum_symbols; 92 | enum e_enum_type g_enum_type = e_enum_type_symbols; 93 | pool_t g_symbol_pool; 94 | pool_t g_string_pool; 95 | extern const char* g_sym_tag_names[]; /* ...at end of file */ 96 | 97 | void pool_create(pool_t* pool, int size) 98 | { 99 | pool->base = (char*)VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_READWRITE); 100 | pool->size = size; 101 | pool->committed = 0; 102 | pool->used = 0; 103 | } 104 | 105 | void pool_destroy(pool_t* pool) 106 | { 107 | VirtualFree(pool->base, 0, MEM_RELEASE); 108 | } 109 | 110 | void pool_clear(pool_t* pool) 111 | { 112 | pool->used = 0; 113 | } 114 | 115 | void* pool_alloc(pool_t* pool, int size) 116 | { 117 | int i; 118 | char* addr; 119 | 120 | ASSERT(size < g_page_size, "Allocation too large!"); 121 | 122 | i = pool->used + size; 123 | if (i >= pool->committed) 124 | { 125 | ASSERT(i < pool->size, "Memory pool exhausted."); 126 | VirtualAlloc((void*)(pool->base + pool->committed), g_page_size, 127 | MEM_COMMIT, PAGE_READWRITE 128 | ); 129 | pool->committed += g_page_size; 130 | } 131 | 132 | addr = pool->base + pool->used; 133 | pool->used += size; 134 | return addr; 135 | } 136 | 137 | void dbghelp_to_sym_info(SYMBOL_INFO* info, sym_info_t* sym_info) 138 | { 139 | BOOL ok; 140 | DWORD disp; 141 | IMAGEHLP_LINE64 line; 142 | 143 | // General properties 144 | sym_info->addr = info->Address; 145 | sym_info->size = info->Size; 146 | sym_info->tag = info->Tag; 147 | 148 | // Symbol name 149 | sym_info->name = (char*)pool_alloc(&g_string_pool, info->NameLen + 1); 150 | memcpy(sym_info->name, info->Name, info->NameLen); 151 | 152 | // Get file and line number info. 153 | line.SizeOfStruct = sizeof(line); 154 | ok = SymGetLineFromAddr64(g_handle, info->Address, &disp, &line); 155 | if ((ok != FALSE) && line.FileName) 156 | { 157 | sym_info->line = line.LineNumber; 158 | sym_info->file = (char*)pool_alloc(&g_string_pool, strlen(line.FileName) + 1); 159 | memcpy(sym_info->file, line.FileName, strlen(line.FileName)); 160 | } 161 | else 162 | { 163 | sym_info->line = 0; 164 | sym_info->file = (char*)"?"; 165 | } 166 | } 167 | 168 | BOOL CALLBACK enum_proc(SYMBOL_INFO* info, ULONG size, void* param) 169 | { 170 | sym_info_t* sym_info; 171 | 172 | sym_info = (sym_info_t*)pool_alloc(&g_symbol_pool, sizeof(sym_info_t)); 173 | dbghelp_to_sym_info(info, sym_info); 174 | 175 | ++g_sym_count; 176 | 177 | return TRUE; 178 | } 179 | 180 | int create_pools(uintptr_t base_addr) 181 | { 182 | BOOL ok; 183 | FILE* in; 184 | int size, i; 185 | const char* guide; 186 | 187 | // Fetch PDB file for the module. 188 | IMAGEHLP_MODULE64 module = { sizeof(module) }; 189 | ok = SymGetModuleInfo64(g_handle, base_addr, &module); 190 | if (!ok) 191 | { 192 | return 0; 193 | } 194 | 195 | guide = module.LoadedPdbName; 196 | 197 | // An .exe with no symbols available? 198 | if (!guide || guide[0] == '\0') 199 | { 200 | return 0; 201 | } 202 | 203 | // Get file size. 204 | fopen_s(&in, guide, "rb"); 205 | ASSERT(in != NULL, "Failed to open pool-size guide file."); 206 | 207 | fseek(in, 0, SEEK_END); 208 | size = ftell(in); 209 | fclose(in); 210 | 211 | // Use anecdotal evidence to guess at suitable pool sizes :). 212 | i = size / 4; 213 | pool_create(&g_string_pool, (i < VN_PDB_ONE_MB) ? VN_PDB_ONE_MB : i); 214 | 215 | i = size / 25; 216 | pool_create(&g_symbol_pool, (i < VN_PDB_ONE_MB) ? VN_PDB_ONE_MB : i); 217 | 218 | return 1; 219 | } 220 | 221 | uintptr_t load_module(const char* pdb_file) 222 | { 223 | uintptr_t base_addr = VN_PDB_ADDRESS_OFFSET; 224 | 225 | base_addr = (size_t)SymLoadModuleEx(g_handle, NULL, pdb_file, NULL, 226 | base_addr, 0x7fffffff, NULL, 0 227 | ); 228 | 229 | return base_addr; 230 | } 231 | 232 | INT VnGetSymbols( 233 | const char* pdb_file, 234 | DWORD* addresses, 235 | char** symbols, 236 | DWORD numOfSymbols 237 | ) 238 | { 239 | DWORD options; 240 | SYSTEM_INFO sys_info; 241 | int i; 242 | uintptr_t base_addr; 243 | DWORD ok; 244 | 245 | // Get page size. 246 | GetSystemInfo(&sys_info); 247 | g_page_size = sys_info.dwPageSize; 248 | 249 | // Initialise DbgHelp 250 | options = SymGetOptions(); 251 | options &= ~SYMOPT_DEFERRED_LOADS; 252 | options |= SYMOPT_LOAD_LINES; 253 | options |= SYMOPT_IGNORE_NT_SYMPATH; 254 | #if ENABLE_DEBUG_OUTPUT 255 | options |= SYMOPT_DEBUG; 256 | #endif 257 | options |= SYMOPT_UNDNAME; 258 | SymSetOptions(options); 259 | 260 | ok = SymInitialize(g_handle, NULL, FALSE); 261 | if (!ok) 262 | { 263 | return -1; 264 | } 265 | 266 | // Load module. 267 | base_addr = load_module(pdb_file); 268 | if (!base_addr) 269 | { 270 | SymCleanup(g_handle); 271 | return -2; 272 | } 273 | 274 | if (!create_pools(base_addr)) 275 | { 276 | SymCleanup(g_handle); 277 | return -3; 278 | } 279 | 280 | g_sym_count = 0; 281 | for (i = 0; i < numOfSymbols; ++i) 282 | { 283 | SymEnumSymbols(g_handle, base_addr, symbols[i], enum_proc, NULL); 284 | if (g_sym_count != i + 1) 285 | { 286 | SymCleanup(g_handle); 287 | return -4; 288 | } 289 | } 290 | 291 | for (i = 0; i < g_sym_count; ++i) 292 | { 293 | sym_info_t* sym_info = ((sym_info_t*)g_symbol_pool.base) + i; 294 | addresses[i] = sym_info->addr - VN_PDB_ADDRESS_OFFSET; 295 | } 296 | 297 | // Done. 298 | ok = SymUnloadModule64(g_handle, (DWORD64)base_addr); 299 | if (!ok) 300 | { 301 | SymCleanup(g_handle); 302 | return -5; 303 | } 304 | 305 | pool_destroy(&g_string_pool); 306 | pool_destroy(&g_symbol_pool); 307 | 308 | SymCleanup(g_handle); 309 | 310 | return 0; 311 | } 312 | 313 | // adapted from: https://github.com/rajkumar-rangaraj/PDB-Downloader 314 | INT VnDownloadSymbols( 315 | HMODULE hModule, 316 | char* dllName, 317 | char* szLibPath, 318 | UINT sizeLibPath 319 | ) 320 | { 321 | HANDLE hFile; 322 | HANDLE hFileMapping; 323 | LPVOID lpFileBase; 324 | PBYTE baseImage; 325 | PIMAGE_DOS_HEADER dosHeader; 326 | #ifdef _WIN64 327 | PIMAGE_NT_HEADERS64 ntHeader; 328 | #else 329 | PIMAGE_NT_HEADERS32 ntHeader; 330 | #endif 331 | PIMAGE_SECTION_HEADER sectionHeader; 332 | DWORD ptr; 333 | UINT nSectionCount; 334 | UINT i; 335 | uintptr_t offset; 336 | UINT cbDebug = 0; 337 | PIMAGE_DEBUG_DIRECTORY imageDebugDirectory; 338 | PdbInfo* pdb_info = NULL; 339 | char url[_MAX_PATH]; 340 | ZeroMemory(url, _MAX_PATH * sizeof(char)); 341 | strcat_s(url, _MAX_PATH, VN_PDB_SYMBOL_WEB); 342 | 343 | hFile = CreateFileA( 344 | dllName, 345 | GENERIC_READ, 346 | FILE_SHARE_READ, 347 | NULL, 348 | OPEN_EXISTING, 349 | FILE_ATTRIBUTE_NORMAL, 350 | 0 351 | ); 352 | if (hFile == INVALID_HANDLE_VALUE) 353 | { 354 | return 1; 355 | } 356 | 357 | hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); 358 | if (hFileMapping == 0) 359 | { 360 | CloseHandle(hFile); 361 | return 2; 362 | } 363 | 364 | lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0); 365 | if (lpFileBase == 0) 366 | { 367 | CloseHandle(hFileMapping); 368 | CloseHandle(hFile); 369 | return 3; 370 | } 371 | 372 | baseImage = (PBYTE)lpFileBase; 373 | dosHeader = (PIMAGE_DOS_HEADER)lpFileBase; 374 | if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) 375 | { 376 | UnmapViewOfFile(lpFileBase); 377 | CloseHandle(hFileMapping); 378 | CloseHandle(hFile); 379 | return 4; 380 | } 381 | 382 | #ifdef _WIN64 383 | ntHeader = (PIMAGE_NT_HEADERS64)((u_char*)dosHeader + dosHeader->e_lfanew); 384 | #else 385 | ntHeader = (PIMAGE_NT_HEADERS32)((u_char*)dosHeader + dosHeader->e_lfanew); 386 | #endif 387 | if (ntHeader->Signature != IMAGE_NT_SIGNATURE) 388 | { 389 | UnmapViewOfFile(lpFileBase); 390 | CloseHandle(hFileMapping); 391 | CloseHandle(hFile); 392 | return 5; 393 | } 394 | if (ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress == 0) 395 | { 396 | UnmapViewOfFile(lpFileBase); 397 | CloseHandle(hFileMapping); 398 | CloseHandle(hFile); 399 | return 6; 400 | } 401 | cbDebug = ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size; 402 | ptr = ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; 403 | sectionHeader = IMAGE_FIRST_SECTION(ntHeader); 404 | nSectionCount = ntHeader->FileHeader.NumberOfSections; 405 | for (i = 0; i <= nSectionCount; ++i, ++sectionHeader) 406 | { 407 | if ((sectionHeader->VirtualAddress) > ptr) 408 | { 409 | sectionHeader--; 410 | break; 411 | } 412 | } 413 | if (i > nSectionCount) 414 | { 415 | sectionHeader = IMAGE_FIRST_SECTION(ntHeader); 416 | UINT nSectionCount = ntHeader->FileHeader.NumberOfSections; 417 | for (i = 0; i < nSectionCount - 1; ++i, ++sectionHeader); 418 | } 419 | offset = (uintptr_t)baseImage + ptr + (uintptr_t)sectionHeader->PointerToRawData - (uintptr_t)sectionHeader->VirtualAddress; 420 | while (cbDebug >= sizeof(IMAGE_DEBUG_DIRECTORY)) 421 | { 422 | imageDebugDirectory = (PIMAGE_DEBUG_DIRECTORY)(offset); 423 | offset += sizeof(IMAGE_DEBUG_DIRECTORY); 424 | if (imageDebugDirectory->Type == IMAGE_DEBUG_TYPE_CODEVIEW) 425 | { 426 | pdb_info = (PdbInfo*)((uintptr_t)baseImage + imageDebugDirectory->PointerToRawData); 427 | if (0 == memcmp(&pdb_info->Signature, "RSDS", 4)) 428 | { 429 | strcat_s(url, _MAX_PATH, pdb_info->PdbFileName); 430 | strcat_s(url, _MAX_PATH, "/"); 431 | // https://stackoverflow.com/questions/1672677/print-a-guid-variable 432 | sprintf_s( 433 | url + strlen(url), 434 | 33, 435 | "%08lX%04hX%04hX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX", 436 | pdb_info->Guid.Data1, 437 | pdb_info->Guid.Data2, 438 | pdb_info->Guid.Data3, 439 | pdb_info->Guid.Data4[0], 440 | pdb_info->Guid.Data4[1], 441 | pdb_info->Guid.Data4[2], 442 | pdb_info->Guid.Data4[3], 443 | pdb_info->Guid.Data4[4], 444 | pdb_info->Guid.Data4[5], 445 | pdb_info->Guid.Data4[6], 446 | pdb_info->Guid.Data4[7] 447 | ); 448 | sprintf_s( 449 | url + strlen(url), 450 | 4, 451 | "%x/", 452 | pdb_info->Age 453 | ); 454 | strcat_s(url, _MAX_PATH, pdb_info->PdbFileName); 455 | break; 456 | } 457 | } 458 | cbDebug -= (UINT)sizeof(IMAGE_DEBUG_DIRECTORY); 459 | } 460 | if (pdb_info == NULL) 461 | { 462 | UnmapViewOfFile(lpFileBase); 463 | CloseHandle(hFileMapping); 464 | CloseHandle(hFile); 465 | return 7; 466 | } 467 | PathRemoveFileSpecA(szLibPath); 468 | strcat_s( 469 | szLibPath, 470 | sizeLibPath, 471 | "\\" 472 | ); 473 | strcat_s( 474 | szLibPath, 475 | sizeLibPath, 476 | pdb_info->PdbFileName 477 | ); 478 | UnmapViewOfFile(lpFileBase); 479 | CloseHandle(hFileMapping); 480 | CloseHandle(hFile); 481 | if (fileExists(szLibPath)) 482 | { 483 | DeleteFileA(szLibPath); 484 | } 485 | return VnDownloadFile( 486 | szLibPath, 487 | (char*)VN_PDB_SYMBOL_HOSTNAME, 488 | url, 489 | (char*)VN_PDB_USER_AGENT, 490 | INTERNET_DEFAULT_HTTP_PORT, 491 | INTERNET_SERVICE_HTTP, 492 | NULL, 493 | (char*)VN_PDB_FORM_HEADERS, 494 | VN_PDB_DOWNLOAD_FILE_BUFFER_SIZE 495 | ); 496 | } 497 | #endif 498 | -------------------------------------------------------------------------------- /valinet/universal/toast/toast.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBVALINET_UNIVERSAL_TOAST_TOAST_H_ 2 | #define LIBVALINET_UNIVERSAL_TOAST_TOAST_H_ 3 | #ifdef _LIBVALINET_INCLUDE_UNIVERSAL 4 | #pragma comment(lib, "runtimeobject.lib") 5 | #include 6 | #include 7 | #include 8 | #include 9 | // UUID obtained from 10 | // 11 | // ABI.Windows.UI.Notifications.IToastNotificationManagerStatics 12 | // 50ac103f-d235-4598-bbef-98fe4d1a3ad4 13 | DEFINE_GUID(UIID_IToastNotificationManagerStatics, 14 | 0x50ac103f, 15 | 0xd235, 0x4598, 0xbb, 0xef, 16 | 0x98, 0xfe, 0x4d, 0x1a, 0x3a, 0xd4 17 | ); 18 | 19 | // UUID obtained from 20 | // 21 | // ABI.Windows.Notifications.IToastNotificationFactory 22 | // 04124b20-82c6-4229-b109-fd9ed4662b53 23 | DEFINE_GUID(UIID_IToastNotificationFactory, 24 | 0x04124b20, 25 | 0x82c6, 0x4229, 0xb1, 0x09, 26 | 0xfd, 0x9e, 0xd4, 0x66, 0x2b, 0x53 27 | ); 28 | 29 | // UUID obtained from 30 | // 31 | // ABI.Windows.Data.Xml.Dom.IXmlDocument 32 | // f7f3a506-1e87-42d6-bcfb-b8c809fa5494 33 | DEFINE_GUID(UIID_IXmlDocument, 34 | 0xf7f3a506, 35 | 0x1e87, 0x42d6, 0xbc, 0xfb, 36 | 0xb8, 0xc8, 0x09, 0xfa, 0x54, 0x94 37 | ); 38 | 39 | // UUID obtained from 40 | // 41 | // ABI.Windows.Data.Xml.Dom.IXmlDocumentIO 42 | // 6cd0e74e-ee65-4489-9ebf-ca43e87ba637 43 | DEFINE_GUID(UIID_IXmlDocumentIO, 44 | 0x6cd0e74e, 45 | 0xee65, 0x4489, 0x9e, 0xbf, 46 | 0xca, 0x43, 0xe8, 0x7b, 0xa6, 0x37 47 | ); 48 | inline HRESULT ShowToastMessage( 49 | __x_ABI_CWindows_CData_CXml_CDom_CIXmlDocument* inputXml, 50 | wchar_t* pwszAppId, 51 | DWORD dwAppIdLength, 52 | void* stream 53 | ) 54 | { 55 | HRESULT hr = S_OK; 56 | 57 | #pragma warning (disable: 6031) 58 | CoInitialize(NULL); 59 | RoInitialize(RO_INIT_MULTITHREADED); 60 | #pragma warning (default: 6031) 61 | 62 | HSTRING_HEADER header_AppIdHString; 63 | HSTRING AppIdHString; 64 | hr = WindowsCreateStringReference( 65 | pwszAppId, 66 | (UINT32)dwAppIdLength, 67 | &header_AppIdHString, 68 | &AppIdHString 69 | ); 70 | if (FAILED(hr)) 71 | { 72 | if (stream) 73 | { 74 | fprintf(stream, "%s:%d:: WindowsCreateStringReference\n", __FUNCTION__, __LINE__); 75 | } 76 | goto exit1; 77 | } 78 | if (AppIdHString == NULL) 79 | { 80 | hr = E_POINTER; 81 | goto exit1; 82 | } 83 | 84 | HSTRING_HEADER header_ToastNotificationManagerHString; 85 | HSTRING ToastNotificationManagerHString; 86 | hr = WindowsCreateStringReference( 87 | RuntimeClass_Windows_UI_Notifications_ToastNotificationManager, 88 | (UINT32)(sizeof(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager) / sizeof(wchar_t) - 1), 89 | &header_ToastNotificationManagerHString, 90 | &ToastNotificationManagerHString 91 | ); 92 | if (FAILED(hr)) 93 | { 94 | if (stream) 95 | { 96 | fprintf(stream, "%s:%d:: WindowsCreateStringReference\n", __FUNCTION__, __LINE__); 97 | } 98 | goto exit2; 99 | } 100 | if (ToastNotificationManagerHString == NULL) 101 | { 102 | if (stream) 103 | { 104 | fprintf(stream, "%s:%d:: ToastNotificationManagerHString == NULL\n", __FUNCTION__, __LINE__); 105 | } 106 | hr = E_POINTER; 107 | goto exit2; 108 | } 109 | 110 | __x_ABI_CWindows_CUI_CNotifications_CIToastNotificationManagerStatics* toastStatics = NULL; 111 | hr = RoGetActivationFactory( 112 | ToastNotificationManagerHString, 113 | &UIID_IToastNotificationManagerStatics, 114 | (LPVOID*)&toastStatics 115 | ); 116 | if (FAILED(hr)) 117 | { 118 | if (stream) 119 | { 120 | fprintf(stream, "%s:%d:: RoGetActivationFactory\n", __FUNCTION__, __LINE__); 121 | } 122 | goto exit2; 123 | } 124 | 125 | __x_ABI_CWindows_CUI_CNotifications_CIToastNotifier* notifier; 126 | hr = toastStatics->lpVtbl->CreateToastNotifierWithId( 127 | toastStatics, 128 | AppIdHString, 129 | ¬ifier 130 | ); 131 | if (FAILED(hr)) 132 | { 133 | if (stream) 134 | { 135 | fprintf(stream, "%s:%d:: CreateToastNotifierWithId\n", __FUNCTION__, __LINE__); 136 | } 137 | goto exit3; 138 | } 139 | 140 | HSTRING_HEADER header_ToastNotificationHString; 141 | HSTRING ToastNotificationHString; 142 | hr = WindowsCreateStringReference( 143 | RuntimeClass_Windows_UI_Notifications_ToastNotification, 144 | (UINT32)(sizeof(RuntimeClass_Windows_UI_Notifications_ToastNotification) / sizeof(wchar_t) - 1), 145 | &header_ToastNotificationHString, 146 | &ToastNotificationHString 147 | ); 148 | if (FAILED(hr)) 149 | { 150 | if (stream) 151 | { 152 | fprintf(stream, "%s:%d:: WindowsCreateStringReference\n", __FUNCTION__, __LINE__); 153 | } 154 | goto exit4; 155 | } 156 | if (ToastNotificationHString == NULL) 157 | { 158 | if (stream) 159 | { 160 | fprintf(stream, "%s:%d:: ToastNotificationHString == NULL\n", __FUNCTION__, __LINE__); 161 | } 162 | hr = E_POINTER; 163 | goto exit4; 164 | } 165 | 166 | __x_ABI_CWindows_CUI_CNotifications_CIToastNotificationFactory* notifFactory = NULL; 167 | hr = RoGetActivationFactory( 168 | ToastNotificationHString, 169 | &UIID_IToastNotificationFactory, 170 | (LPVOID*)¬ifFactory 171 | ); 172 | if (FAILED(hr)) 173 | { 174 | if (stream) 175 | { 176 | fprintf(stream, "%s:%d:: RoGetActivationFactory\n", __FUNCTION__, __LINE__); 177 | } 178 | goto exit4; 179 | } 180 | 181 | __x_ABI_CWindows_CUI_CNotifications_CIToastNotification* toast = NULL; 182 | hr = notifFactory->lpVtbl->CreateToastNotification(notifFactory, inputXml, &toast); 183 | if (FAILED(hr)) 184 | { 185 | if (stream) 186 | { 187 | fprintf(stream, "%s:%d:: CreateToastNotification\n", __FUNCTION__, __LINE__); 188 | } 189 | goto exit5; 190 | } 191 | 192 | hr = notifier->lpVtbl->Show(notifier, toast); 193 | if (FAILED(hr)) 194 | { 195 | if (stream) 196 | { 197 | fprintf(stream, "%s:%d:: Show\n", __FUNCTION__, __LINE__); 198 | } 199 | goto exit6; 200 | } 201 | 202 | exit6: 203 | toast->lpVtbl->Release(toast); 204 | exit5: 205 | notifFactory->lpVtbl->Release(notifFactory); 206 | exit4: 207 | notifier->lpVtbl->Release(notifier); 208 | exit3: 209 | toastStatics->lpVtbl->Release(toastStatics); 210 | exit2: 211 | inputXml->lpVtbl->Release(inputXml); 212 | exit1: 213 | return hr; 214 | } 215 | 216 | inline HRESULT String2IXMLDocument( 217 | wchar_t* pwszData, 218 | DWORD dwDataLength, 219 | __x_ABI_CWindows_CData_CXml_CDom_CIXmlDocument** pxmlToastMessage, 220 | void* stream 221 | ) 222 | { 223 | HRESULT hr = S_OK; 224 | 225 | CoInitialize(NULL); 226 | RoInitialize(RO_INIT_MULTITHREADED); 227 | 228 | HSTRING_HEADER hshXmlDocumentS_h; 229 | HSTRING hsXmlDocumentS; 230 | hr = WindowsCreateStringReference( 231 | RuntimeClass_Windows_Data_Xml_Dom_XmlDocument, 232 | (UINT32)(sizeof(RuntimeClass_Windows_Data_Xml_Dom_XmlDocument) / sizeof(wchar_t) - 1), 233 | &hshXmlDocumentS_h, 234 | &hsXmlDocumentS 235 | ); 236 | if (FAILED(hr)) 237 | { 238 | if (stream) 239 | { 240 | fprintf(stream, 241 | "%s:%d:: WindowsCreateStringReference = %d\n", __FUNCTION__, __LINE__, 242 | hr 243 | ); 244 | } 245 | goto exit0; 246 | } 247 | 248 | HSTRING_HEADER hshxmlString_h; 249 | HSTRING hshxmlString; 250 | hr = WindowsCreateStringReference( 251 | pwszData, 252 | (UINT32)dwDataLength, 253 | &hshxmlString_h, 254 | &hshxmlString 255 | ); 256 | if (FAILED(hr)) 257 | { 258 | if (stream) 259 | { 260 | fprintf(stream, 261 | "%s:%d:: WindowsCreateStringReference = %d\n", __FUNCTION__, __LINE__, 262 | hr 263 | ); 264 | } 265 | goto exit1; 266 | } 267 | 268 | IInspectable* pInspectable = NULL; 269 | hr = RoActivateInstance(hsXmlDocumentS, &pInspectable); 270 | if (SUCCEEDED(hr)) 271 | { 272 | hr = pInspectable->lpVtbl->QueryInterface( 273 | pInspectable, 274 | &UIID_IXmlDocument, 275 | pxmlToastMessage 276 | ); 277 | pInspectable->lpVtbl->Release(pInspectable); 278 | } 279 | else 280 | { 281 | printf( 282 | "%s:%d:: RoActivateInstance = %d\n", __FUNCTION__, __LINE__, 283 | hr 284 | ); 285 | goto exit2; 286 | } 287 | 288 | __x_ABI_CWindows_CData_CXml_CDom_CIXmlDocumentIO* pxmlDocumentIO = NULL; 289 | (*pxmlToastMessage)->lpVtbl->QueryInterface( 290 | (*pxmlToastMessage), 291 | &UIID_IXmlDocumentIO, 292 | &pxmlDocumentIO 293 | ); 294 | if (FAILED(hr)) 295 | { 296 | printf( 297 | "%s:%d:: QueryInterface = %d\n", __FUNCTION__, __LINE__, 298 | hr 299 | ); 300 | goto exit3; 301 | } 302 | 303 | hr = pxmlDocumentIO->lpVtbl->LoadXml(pxmlDocumentIO, hshxmlString); 304 | if (FAILED(hr)) 305 | { 306 | if (stream) 307 | { 308 | fprintf(stream, 309 | "%s:%d:: pxmlDocumentIO->LoadXml = %d\n", __FUNCTION__, __LINE__, 310 | hr 311 | ); 312 | } 313 | goto exit3; 314 | } 315 | 316 | exit3: 317 | pxmlDocumentIO->lpVtbl->Release(pxmlDocumentIO); 318 | exit2: 319 | WindowsDeleteString(hshxmlString); 320 | exit1: 321 | WindowsDeleteString(hsXmlDocumentS); 322 | exit0: 323 | return hr; 324 | } 325 | #endif 326 | #endif 327 | -------------------------------------------------------------------------------- /valinet/utility/memmem.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBVALINET_UTILITY_MEMMEM_H_ 2 | #define LIBVALINET_UTILITY_MEMMEM_H_ 3 | #include 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | // https://github.com/valinet/ssa/blob/master/KMP/c/kmp.c 11 | inline void* memmem(void* haystack, size_t haystacklen, void* needle, size_t needlelen) 12 | { 13 | const char* text = (const char*)haystack; 14 | const char* pattern = (const char*)needle; 15 | const char* rv = NULL; 16 | 17 | size_t* out = (size_t*)calloc(needlelen, sizeof(size_t)); 18 | if (!out) 19 | { 20 | return NULL; 21 | } 22 | size_t j, i; 23 | 24 | j = 0, i = 1; 25 | while (i < needlelen) { 26 | if (text[j] != text[i]) 27 | { 28 | if (j > 0) 29 | { 30 | j = out[j - 1]; 31 | continue; 32 | } 33 | else j--; 34 | } 35 | j++; 36 | out[i] = j; 37 | i++; 38 | } 39 | 40 | i = 0, j = 0; 41 | for (i = 0; i <= haystacklen; i++) { 42 | if (text[i] == pattern[j]) { 43 | j++; 44 | if (j == needlelen) { 45 | rv = text + (size_t)(i - needlelen + 1); //match++; j = out[j - 1]; 46 | break; 47 | } 48 | } 49 | else { 50 | if (j != 0) { 51 | j = out[j - 1]; 52 | i--; 53 | } 54 | } 55 | } 56 | 57 | free(out); 58 | return (void*)rv; 59 | } 60 | 61 | #ifdef __cplusplus 62 | } 63 | #endif 64 | 65 | #endif -------------------------------------------------------------------------------- /valinet/utility/osversion.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBVALINET_HOOKING_OSVERSION_H_ 2 | #define LIBVALINET_HOOKING_OSVERSION_H_ 3 | #include 4 | 5 | #define _LIBVALINET_HOOKING_OSVERSION_INVALID 0xffffffff 6 | 7 | typedef LONG NTSTATUS, * PNTSTATUS; 8 | #ifndef STATUS_SUCCESS 9 | #define STATUS_SUCCESS (0x00000000) 10 | #endif 11 | 12 | typedef NTSTATUS(WINAPI* VnRtlGetVersionPtr)(PRTL_OSVERSIONINFOW); 13 | 14 | // https://stackoverflow.com/questions/36543301/detecting-windows-10-version/36543774#36543774 15 | inline BOOL VnGetOSVersion(PRTL_OSVERSIONINFOW lpRovi) 16 | { 17 | HMODULE hMod = GetModuleHandleW(L"ntdll.dll"); 18 | if (hMod != NULL) 19 | { 20 | VnRtlGetVersionPtr fxPtr = (VnRtlGetVersionPtr)GetProcAddress( 21 | hMod, 22 | "RtlGetVersion" 23 | ); 24 | if (fxPtr != NULL) 25 | { 26 | lpRovi->dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW); 27 | if (STATUS_SUCCESS == fxPtr(lpRovi)) 28 | { 29 | return TRUE; 30 | } 31 | } 32 | } 33 | return FALSE; 34 | } 35 | 36 | // https://stackoverflow.com/questions/47926094/detecting-windows-10-os-build-minor-version 37 | inline DWORD32 VnGetUBR(void) 38 | { 39 | DWORD32 ubr = 0, ubr_size = sizeof(DWORD32); 40 | HKEY hKey; 41 | LONG lRes = RegOpenKeyExW( 42 | HKEY_LOCAL_MACHINE, 43 | wcschr( 44 | wcschr( 45 | wcschr( 46 | UNIFIEDBUILDREVISION_KEY, 47 | '\\' 48 | ) + 1, 49 | '\\' 50 | ) + 1, 51 | '\\' 52 | ) + 1, 53 | 0, 54 | KEY_READ, 55 | &hKey 56 | ); 57 | if (lRes == ERROR_SUCCESS) 58 | { 59 | RegQueryValueExW( 60 | hKey, 61 | UNIFIEDBUILDREVISION_VALUE, 62 | 0, 63 | NULL, 64 | (LPBYTE)&ubr, 65 | (LPDWORD)&ubr_size 66 | ); 67 | } 68 | return ubr; 69 | } 70 | 71 | inline DWORD32 VnGetOSVersionAndUBR(PRTL_OSVERSIONINFOW lpRovi) 72 | { 73 | if (!VnGetOSVersion(lpRovi)) 74 | { 75 | return _LIBVALINET_HOOKING_OSVERSION_INVALID; 76 | } 77 | return VnGetUBR(); 78 | } 79 | #endif 80 | -------------------------------------------------------------------------------- /valinet/utility/takeown.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBVALINET_UTILITY_TAKEOWN_H_ 2 | #define LIBVALINET_UTILITY_TAKEOWN_H_ 3 | // https://docs.microsoft.com/en-us/windows/win32/secauthz/enabling-and-disabling-privileges-in-c-- 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | BOOL VnSetPrivilege( 10 | HANDLE hToken, // access token handle 11 | LPCTSTR lpszPrivilege, // name of privilege to enable/disable 12 | BOOL bEnablePrivilege // to enable or disable privilege 13 | ) 14 | { 15 | TOKEN_PRIVILEGES tp; 16 | LUID luid; 17 | 18 | if (!LookupPrivilegeValue( 19 | NULL, // lookup privilege on local system 20 | lpszPrivilege, // privilege to lookup 21 | &luid)) // receives LUID of privilege 22 | { 23 | printf("LookupPrivilegeValue error: %u\n", GetLastError()); 24 | return FALSE; 25 | } 26 | 27 | tp.PrivilegeCount = 1; 28 | tp.Privileges[0].Luid = luid; 29 | if (bEnablePrivilege) 30 | tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 31 | else 32 | tp.Privileges[0].Attributes = 0; 33 | 34 | // Enable the privilege or disable all privileges. 35 | 36 | if (!AdjustTokenPrivileges( 37 | hToken, 38 | FALSE, 39 | &tp, 40 | sizeof(TOKEN_PRIVILEGES), 41 | (PTOKEN_PRIVILEGES)NULL, 42 | (PDWORD)NULL)) 43 | { 44 | printf("AdjustTokenPrivileges error: %u\n", GetLastError()); 45 | return FALSE; 46 | } 47 | 48 | if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) 49 | 50 | { 51 | printf("The token does not have the specified privilege. \n"); 52 | return FALSE; 53 | } 54 | 55 | return TRUE; 56 | } 57 | 58 | BOOL VnTakeOwnership(LPTSTR lpszOwnFile) 59 | { 60 | BOOL bRetval = FALSE; 61 | 62 | HANDLE hToken = NULL; 63 | PSID pSIDAdmin = NULL; 64 | PSID pSIDEveryone = NULL; 65 | PACL pACL = NULL; 66 | SID_IDENTIFIER_AUTHORITY SIDAuthWorld = 67 | SECURITY_WORLD_SID_AUTHORITY; 68 | SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; 69 | EXPLICIT_ACCESS ea[2]; 70 | DWORD dwRes; 71 | 72 | // Specify the DACL to use. 73 | // Create a SID for the Everyone group. 74 | if (!AllocateAndInitializeSid(&SIDAuthWorld, 1, 75 | SECURITY_WORLD_RID, 76 | 0, 77 | 0, 0, 0, 0, 0, 0, 78 | &pSIDEveryone)) 79 | { 80 | printf("AllocateAndInitializeSid (Everyone) error %u\n", 81 | GetLastError()); 82 | goto Cleanup; 83 | } 84 | 85 | // Create a SID for the BUILTIN\Administrators group. 86 | if (!AllocateAndInitializeSid(&SIDAuthNT, 2, 87 | SECURITY_BUILTIN_DOMAIN_RID, 88 | DOMAIN_ALIAS_RID_ADMINS, 89 | 0, 0, 0, 0, 0, 0, 90 | &pSIDAdmin)) 91 | { 92 | printf("AllocateAndInitializeSid (Admin) error %u\n", 93 | GetLastError()); 94 | goto Cleanup; 95 | } 96 | 97 | ZeroMemory(&ea, 2 * sizeof(EXPLICIT_ACCESS)); 98 | 99 | // Set read access for Everyone. 100 | ea[0].grfAccessPermissions = GENERIC_READ; 101 | ea[0].grfAccessMode = SET_ACCESS; 102 | ea[0].grfInheritance = NO_INHERITANCE; 103 | ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; 104 | ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; 105 | ea[0].Trustee.ptstrName = (LPTSTR)pSIDEveryone; 106 | 107 | // Set full control for Administrators. 108 | ea[1].grfAccessPermissions = GENERIC_ALL; 109 | ea[1].grfAccessMode = SET_ACCESS; 110 | ea[1].grfInheritance = NO_INHERITANCE; 111 | ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; 112 | ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; 113 | ea[1].Trustee.ptstrName = (LPTSTR)pSIDAdmin; 114 | 115 | if (ERROR_SUCCESS != SetEntriesInAcl(2, 116 | ea, 117 | NULL, 118 | &pACL)) 119 | { 120 | printf("Failed SetEntriesInAcl\n"); 121 | goto Cleanup; 122 | } 123 | 124 | // Try to modify the object's DACL. 125 | dwRes = SetNamedSecurityInfo( 126 | lpszOwnFile, // name of the object 127 | SE_FILE_OBJECT, // type of object 128 | DACL_SECURITY_INFORMATION, // change only the object's DACL 129 | NULL, NULL, // do not change owner or group 130 | pACL, // DACL specified 131 | NULL); // do not change SACL 132 | 133 | if (ERROR_SUCCESS == dwRes) 134 | { 135 | printf("Successfully changed DACL\n"); 136 | bRetval = TRUE; 137 | // No more processing needed. 138 | goto Cleanup; 139 | } 140 | if (dwRes != ERROR_ACCESS_DENIED) 141 | { 142 | printf("First SetNamedSecurityInfo call failed: %u\n", 143 | dwRes); 144 | goto Cleanup; 145 | } 146 | 147 | // If the preceding call failed because access was denied, 148 | // enable the SE_TAKE_OWNERSHIP_NAME privilege, create a SID for 149 | // the Administrators group, take ownership of the object, and 150 | // disable the privilege. Then try again to set the object's DACL. 151 | 152 | // Open a handle to the access token for the calling process. 153 | if (!OpenProcessToken(GetCurrentProcess(), 154 | TOKEN_ADJUST_PRIVILEGES, 155 | &hToken)) 156 | { 157 | printf("OpenProcessToken failed: %u\n", GetLastError()); 158 | goto Cleanup; 159 | } 160 | 161 | // Enable the SE_TAKE_OWNERSHIP_NAME privilege. 162 | if (!VnSetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, TRUE)) 163 | { 164 | printf("You must be logged on as Administrator.\n"); 165 | goto Cleanup; 166 | } 167 | 168 | // Set the owner in the object's security descriptor. 169 | dwRes = SetNamedSecurityInfo( 170 | lpszOwnFile, // name of the object 171 | SE_FILE_OBJECT, // type of object 172 | OWNER_SECURITY_INFORMATION, // change only the object's owner 173 | pSIDAdmin, // SID of Administrator group 174 | NULL, 175 | NULL, 176 | NULL); 177 | 178 | if (dwRes != ERROR_SUCCESS) 179 | { 180 | printf("Could not set owner. Error: %u\n", dwRes); 181 | goto Cleanup; 182 | } 183 | 184 | // Disable the SE_TAKE_OWNERSHIP_NAME privilege. 185 | if (!VnSetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, FALSE)) 186 | { 187 | printf("Failed SetPrivilege call unexpectedly.\n"); 188 | goto Cleanup; 189 | } 190 | 191 | // Try again to modify the object's DACL, 192 | // now that we are the owner. 193 | dwRes = SetNamedSecurityInfo( 194 | lpszOwnFile, // name of the object 195 | SE_FILE_OBJECT, // type of object 196 | DACL_SECURITY_INFORMATION, // change only the object's DACL 197 | NULL, NULL, // do not change owner or group 198 | pACL, // DACL specified 199 | NULL); // do not change SACL 200 | 201 | if (dwRes == ERROR_SUCCESS) 202 | { 203 | printf("Successfully changed DACL\n"); 204 | bRetval = TRUE; 205 | } 206 | else 207 | { 208 | printf("Second SetNamedSecurityInfo call failed: %u\n", 209 | dwRes); 210 | } 211 | 212 | Cleanup: 213 | 214 | if (pSIDAdmin) 215 | FreeSid(pSIDAdmin); 216 | 217 | if (pSIDEveryone) 218 | FreeSid(pSIDEveryone); 219 | 220 | if (pACL) 221 | LocalFree(pACL); 222 | 223 | if (hToken) 224 | CloseHandle(hToken); 225 | 226 | return bRetval; 227 | 228 | } 229 | #endif --------------------------------------------------------------------------------