├── Hibr2Bin ├── comae.ico ├── precomp.cpp ├── resource.h ├── Hiberfil.h ├── precomp.h ├── Hibr2Bin.h ├── Hibr2Bin.vcxproj.filters ├── Hibr2Bin.rc ├── Disk.cpp ├── Hiber.h ├── Hibr2Bin.cpp ├── Hiberfil.cpp ├── MemoryBlocks.h ├── Hibr2Bin.vcxproj └── MemoryBlocks.cpp ├── .gitmodules ├── Hibr2Bin.sln ├── .gitattributes ├── README.md ├── .gitignore └── LICENSE /Hibr2Bin/comae.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MagnetForensics/Hibr2Bin/HEAD/Hibr2Bin/comae.ico -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Hibr2Bin/CommonLibLight"] 2 | path = Hibr2Bin/CommonLibLight 3 | url = https://github.com/comaeio/CommonLibLight.git 4 | -------------------------------------------------------------------------------- /Hibr2Bin/precomp.cpp: -------------------------------------------------------------------------------- 1 | // precomp.cpp : source file that includes just the standard includes 2 | // Windows Application.pch will be the pre-compiled header 3 | // precomp.obj will contain the pre-compiled type information 4 | 5 | #include "precomp.h" 6 | 7 | // TODO: reference any additional headers you need in precomp.h 8 | // and not in this file -------------------------------------------------------------------------------- /Hibr2Bin/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Hibr2Bin.rc 4 | // 5 | #define IDI_ICON1 102 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 103 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /Hibr2Bin/Hiberfil.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) 2007 - 2017, Matthieu Suiche 4 | Copyright (c) 2012 - 2014, MoonSols Limited 5 | Copyright (c) 2015 - 2017, Comae Technologies FZE 6 | Copyright (c) 2017 - 2018, Comae Technologies DMCC 7 | 8 | Module Name: 9 | 10 | Hiberfil.h 11 | 12 | Abstract: 13 | 14 | This module contains the internal structure definitions and APIs used by 15 | the Hibr2Bin. 16 | 17 | Author: 18 | 19 | Matthieu Suiche (m) 1-April-2016 20 | 21 | Revision History: 22 | 23 | --*/ 24 | 25 | BOOLEAN 26 | ProcessHiberfil( 27 | _In_ PPROGRAM_ARGUMENTS Vars, 28 | _Out_ MemoryBlock **OutMemoryBlock 29 | ); -------------------------------------------------------------------------------- /Hibr2Bin/precomp.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) 2007 - 2017, Matthieu Suiche 4 | Copyright (c) 2012 - 2014, MoonSols Limited 5 | Copyright (c) 2015 - 2017, Comae Technologies FZE 6 | Copyright (c) 2017 - 2018, Comae Technologies DMCC 7 | 8 | Module Name: 9 | 10 | precom.h 11 | 12 | Abstract: 13 | 14 | This module contains the internal structure definitions and APIs used by 15 | the Hibr2Bin. 16 | 17 | Author: 18 | 19 | Matthieu Suiche (m) 1-April-2016 20 | 21 | Revision History: 22 | 23 | --*/ 24 | 25 | #define _WINSOCKAPI_ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | 34 | #define MAX_COMPRESSED_BLOCK_SIZE ((0x10 + 1) * PAGE_SIZE) // 64KB + 4KB) 35 | 36 | // public 37 | #include "CommonLibLight/FileContext.h" 38 | #include "CommonLibLight/Misc.h" 39 | 40 | #include "Hiber.h" 41 | #include "MemoryBlocks.h" 42 | 43 | #include "Hibr2Bin.h" 44 | #include "Hiberfil.h" 45 | 46 | #if _DEBUG 47 | #define DbgPrint wprintf 48 | #else 49 | #define DbgPrint 50 | #endif 51 | -------------------------------------------------------------------------------- /Hibr2Bin/Hibr2Bin.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) 2007 - 2017, Matthieu Suiche 4 | Copyright (c) 2012 - 2014, MoonSols Limited 5 | Copyright (c) 2015 - 2017, Comae Technologies FZE 6 | Copyright (c) 2017 - 2018, Comae Technologies DMCC 7 | 8 | Module Name: 9 | 10 | Hibr2Bin.h 11 | 12 | Abstract: 13 | 14 | This module contains the internal structure definitions and APIs used by 15 | the Hibr2Bin. 16 | 17 | Author: 18 | 19 | Matthieu Suiche (m) 1-April-2016 20 | 21 | Revision History: 22 | 23 | --*/ 24 | 25 | #define WRITE_CACHE_SIZE (1024 * 1024) 26 | 27 | typedef struct _PROGRAM_ARGUMENTS { 28 | LPWSTR FileName; 29 | LPWSTR OutFileName; 30 | 31 | PlatformType Platform; 32 | BOOLEAN HasPlatform; 33 | 34 | ULONG MajorVersion; 35 | BOOLEAN HasMajorVersion; 36 | 37 | ULONG MinorVersion; 38 | BOOLEAN HasMinorVersion; 39 | 40 | ULONGLONG DataOffset; 41 | BOOLEAN HasDataOffset; 42 | } PROGRAM_ARGUMENTS, *PPROGRAM_ARGUMENTS; 43 | 44 | BOOLEAN 45 | ProcessHiberfil( 46 | _In_ PPROGRAM_ARGUMENTS Vars, 47 | _Out_ MemoryBlock **OutMemoryBlock 48 | ); 49 | 50 | BOOLEAN 51 | WriteMemoryBlocksToDisk( 52 | _In_ MemoryBlock *Base, 53 | _In_ PPROGRAM_ARGUMENTS Vars 54 | ); -------------------------------------------------------------------------------- /Hibr2Bin.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Hibr2Bin", "Hibr2Bin\Hibr2Bin.vcxproj", "{3B1F31A6-91FD-4946-AA9C-B93592E57F70}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {3B1F31A6-91FD-4946-AA9C-B93592E57F70}.Debug|x64.ActiveCfg = Debug|x64 17 | {3B1F31A6-91FD-4946-AA9C-B93592E57F70}.Debug|x64.Build.0 = Debug|x64 18 | {3B1F31A6-91FD-4946-AA9C-B93592E57F70}.Debug|x86.ActiveCfg = Debug|Win32 19 | {3B1F31A6-91FD-4946-AA9C-B93592E57F70}.Debug|x86.Build.0 = Debug|Win32 20 | {3B1F31A6-91FD-4946-AA9C-B93592E57F70}.Release|x64.ActiveCfg = Release|x64 21 | {3B1F31A6-91FD-4946-AA9C-B93592E57F70}.Release|x64.Build.0 = Release|x64 22 | {3B1F31A6-91FD-4946-AA9C-B93592E57F70}.Release|x86.ActiveCfg = Release|Win32 23 | {3B1F31A6-91FD-4946-AA9C-B93592E57F70}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /Hibr2Bin/Hibr2Bin.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Source Files 6 | 7 | 8 | Source Files 9 | 10 | 11 | Source Files 12 | 13 | 14 | Source Files 15 | 16 | 17 | Source Files 18 | 19 | 20 | Source Files 21 | 22 | 23 | Source Files 24 | 25 | 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | Header Files 47 | 48 | 49 | Header Files 50 | 51 | 52 | 53 | 54 | {be54bd0e-758a-456a-a54d-11d014c5f1da} 55 | 56 | 57 | {d1021b3b-ff00-4455-a69d-0a5c40833761} 58 | 59 | 60 | {f55c6f1c-0502-474c-ba81-b3e79da04dd1} 61 | 62 | 63 | 64 | 65 | Resource Files 66 | 67 | 68 | 69 | 70 | Resource Files 71 | 72 | 73 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Get the compiled version as part of **Comae Toolkit**. 2 | 3 | # Hibr2Bin 4 | Comae Hibernation File Decompressor (SANDMAN project) 5 | 6 | Back in 2007 [1], after reversing Microsoft Windows Kernel Power Management functions and its compression algorithm. 7 | I started an open source project called Enter SandMan that aimed at decompressing hibernation files on Windows and extracting information out of it via an interactive shell - 10 years later hibernation file based memory forensics became very popular in the Law Enforcement World and helped many investigators to solve many cases all over the World. 8 | 9 | SandMan initially started as an open-source project, but in 2008 a German company called X-Ways stole[2][3][4] my open source code without giving any proper due credits. As a results, I stopped open sourcing my projects. 10 | 11 | 2017 is now here, and I thought it would be a good way to start the year by open sourcing the current version of Hibr2Bin which also had been recently documented [5] by Joe T. Sylve, Vico Marziale, Golden G. Richard III. 12 | 13 | - [1] http://www.msuiche.net/2007/12/06/enter-sandman-japan-pacsec-2007/ 14 | - [2] http://lists.volatilesystems.com/pipermail/vol-users/2009-July/000111.html 15 | - [3] http://computer.forensikblog.de/en/2008/04/the-3-vendors.html 16 | - [4] http://www.msuiche.net/2008/04/03/x-ways-forensics-beta-2-and-hibernation-file/ 17 | - [5] https://www.504ensics.com/uploads/publications/modern-windows-hibernation.pdf 18 | 19 | ## Usage 20 | 21 | ``` 22 | Hibr2Bin 3.0 23 | Copyright (C) 2007 - 2017, Matthieu Suiche 24 | Copyright (C) 2012 - 2014, MoonSols Limited 25 | Copyright (C) 2015 - 2017, Comae Technologies FZE 26 | 27 | Usage: Hibr2Bin [Options] /INPUT /OUTPUT 28 | 29 | Description: 30 | Enables users to uncompress Windows hibernation file. 31 | 32 | Options: 33 | /PLATFORM, /P Select platform (X64 or X86) 34 | 35 | /MAJOR, /V Select major version (e.g. 6 for NT 6.1 36 | 37 | /MINOR, /M Select minor version (e.g. 1 for NT 6.1) 38 | 39 | /OFFSET, /L Data offset in hexadecimal (optional) 40 | 41 | /INPUT, /I Input hiberfil.sys file. 42 | 43 | /OUTPUT, /O Output hiberfil.sys file. 44 | 45 | Versions: 46 | /MAJOR 5 /MINOR 1 Windows XP 47 | /MAJOR 5 /MINOR 2 Windows XP x64, Windows 2003 R2 48 | /MAJOR 6 /MINOR 0 Windows Vista, Windows Server 2008 49 | /MAJOR 6 /MINOR 1 Windows 7, Windows Server 2008 R2 50 | /MAJOR 6 /MINOR 2 Windows 8, Windows Server 2012 51 | /MAJOR 6 /MINOR 3 Windows 8.1, Windows Server 2012 R2 52 | /MAJOR 10 /MINOR 0 Windows 10, Windows Server 2016 53 | 54 | Uncompress a Windows 7 (NT 6.1) x64 hibernation file: 55 | HIBR2BIN /PLATFORM X64 /MAJOR 6 /MINOR 1 /INPUT hiberfil.sys /OUTPUT uncompressed.bin 56 | 57 | Uncompress a Windows 10 (NT 10.0) x86 hibernation file: 58 | HIBR2BIN /PLATFORM X86 /MAJOR 10 /MINOR 0 /INPUT hiberfil.sys /OUTPUT uncompressed.bin 59 | ``` 60 | 61 | ## Contact 62 | www.comae.io 63 | -------------------------------------------------------------------------------- /Hibr2Bin/Hibr2Bin.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #include "resource.h" 4 | 5 | #define APSTUDIO_READONLY_SYMBOLS 6 | ///////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Generated from the TEXTINCLUDE 2 resource. 9 | // 10 | #include "winres.h" 11 | 12 | ///////////////////////////////////////////////////////////////////////////// 13 | #undef APSTUDIO_READONLY_SYMBOLS 14 | 15 | ///////////////////////////////////////////////////////////////////////////// 16 | // English (United States) resources 17 | 18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 19 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 20 | #pragma code_page(1252) 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "#include ""winres.h""\r\n" 36 | "\0" 37 | END 38 | 39 | 3 TEXTINCLUDE 40 | BEGIN 41 | "\r\n" 42 | "\0" 43 | END 44 | 45 | #endif // APSTUDIO_INVOKED 46 | 47 | 48 | ///////////////////////////////////////////////////////////////////////////// 49 | // 50 | // Version 51 | // 52 | 53 | VS_VERSION_INFO VERSIONINFO 54 | FILEVERSION 3,0,0,0 55 | PRODUCTVERSION 3,0,0,0 56 | FILEFLAGSMASK 0x3fL 57 | #ifdef _DEBUG 58 | FILEFLAGS 0x1L 59 | #else 60 | FILEFLAGS 0x0L 61 | #endif 62 | FILEOS 0x40004L 63 | FILETYPE 0x1L 64 | FILESUBTYPE 0x0L 65 | BEGIN 66 | BLOCK "StringFileInfo" 67 | BEGIN 68 | BLOCK "040904b0" 69 | BEGIN 70 | VALUE "CompanyName", "Magnet Forensics, Inc." 71 | VALUE "FileDescription", "Windows hibernation file decompressor." 72 | VALUE "FileVersion", "3.1.0.0" 73 | VALUE "InternalName", "Hibr2Bin.exe" 74 | VALUE "LegalCopyright", "Copyright (C) 2022 Magnet Forensics, Inc." 75 | VALUE "OriginalFilename", "Hibr2Bin.exe" 76 | VALUE "ProductName", "Comae Toolkit" 77 | VALUE "ProductVersion", "3.1.0.0" 78 | END 79 | END 80 | BLOCK "VarFileInfo" 81 | BEGIN 82 | VALUE "Translation", 0x409, 1200 83 | END 84 | END 85 | 86 | 87 | ///////////////////////////////////////////////////////////////////////////// 88 | // 89 | // Icon 90 | // 91 | 92 | // Icon with lowest ID value placed first to ensure application icon 93 | // remains consistent on all systems. 94 | IDI_ICON1 ICON "comae.ico" 95 | 96 | #endif // English (United States) resources 97 | ///////////////////////////////////////////////////////////////////////////// 98 | 99 | 100 | 101 | #ifndef APSTUDIO_INVOKED 102 | ///////////////////////////////////////////////////////////////////////////// 103 | // 104 | // Generated from the TEXTINCLUDE 3 resource. 105 | // 106 | 107 | 108 | ///////////////////////////////////////////////////////////////////////////// 109 | #endif // not APSTUDIO_INVOKED 110 | 111 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | [Xx]64/ 19 | [Xx]86/ 20 | [Bb]uild/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | *.vspx 89 | *.sap 90 | 91 | # TFS 2012 Local Workspace 92 | $tf/ 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | *.DotSettings.user 101 | 102 | # JustCode is a .NET coding add-in 103 | .JustCode 104 | 105 | # TeamCity is a build add-in 106 | _TeamCity* 107 | 108 | # DotCover is a Code Coverage Tool 109 | *.dotCover 110 | 111 | # NCrunch 112 | _NCrunch_* 113 | .*crunch*.local.xml 114 | nCrunchTemp_* 115 | 116 | # MightyMoose 117 | *.mm.* 118 | AutoTest.Net/ 119 | 120 | # Web workbench (sass) 121 | .sass-cache/ 122 | 123 | # Installshield output folder 124 | [Ee]xpress/ 125 | 126 | # DocProject is a documentation generator add-in 127 | DocProject/buildhelp/ 128 | DocProject/Help/*.HxT 129 | DocProject/Help/*.HxC 130 | DocProject/Help/*.hhc 131 | DocProject/Help/*.hhk 132 | DocProject/Help/*.hhp 133 | DocProject/Help/Html2 134 | DocProject/Help/html 135 | 136 | # Click-Once directory 137 | publish/ 138 | 139 | # Publish Web Output 140 | *.[Pp]ublish.xml 141 | *.azurePubxml 142 | 143 | # TODO: Un-comment the next line if you do not want to checkin 144 | # your web deploy settings because they may include unencrypted 145 | # passwords 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # NuGet Packages 150 | *.nupkg 151 | # The packages folder can be ignored because of Package Restore 152 | **/packages/* 153 | # except build/, which is used as an MSBuild target. 154 | !**/packages/build/ 155 | # Uncomment if necessary however generally it will be regenerated when needed 156 | #!**/packages/repositories.config 157 | # NuGet v3's project.json files produces more ignoreable files 158 | *.nuget.props 159 | *.nuget.targets 160 | 161 | # Microsoft Azure Build Output 162 | csx/ 163 | *.build.csdef 164 | 165 | # Microsoft Azure Emulator 166 | ecf/ 167 | rcf/ 168 | 169 | # Windows Store app package directory 170 | AppPackages/ 171 | BundleArtifacts/ 172 | 173 | # Visual Studio cache files 174 | # files ending in .cache can be ignored 175 | *.[Cc]ache 176 | # but keep track of directories ending in .cache 177 | !*.[Cc]ache/ 178 | 179 | # Others 180 | ClientBin/ 181 | [Ss]tyle[Cc]op.* 182 | ~$* 183 | *~ 184 | *.dbmdl 185 | *.dbproj.schemaview 186 | *.pfx 187 | *.publishsettings 188 | node_modules/ 189 | orleans.codegen.cs 190 | 191 | # RIA/Silverlight projects 192 | Generated_Code/ 193 | 194 | # Backup & report files from converting an old project file 195 | # to a newer Visual Studio version. Backup files are not needed, 196 | # because we have git ;-) 197 | _UpgradeReport_Files/ 198 | Backup*/ 199 | UpgradeLog*.XML 200 | UpgradeLog*.htm 201 | 202 | # SQL Server files 203 | *.mdf 204 | *.ldf 205 | 206 | # Business Intelligence projects 207 | *.rdl.data 208 | *.bim.layout 209 | *.bim_*.settings 210 | 211 | # Microsoft Fakes 212 | FakesAssemblies/ 213 | 214 | # GhostDoc plugin setting file 215 | *.GhostDoc.xml 216 | 217 | # Node.js Tools for Visual Studio 218 | .ntvs_analysis.dat 219 | 220 | # Visual Studio 6 build log 221 | *.plg 222 | 223 | # Visual Studio 6 workspace options file 224 | *.opt 225 | 226 | # Visual Studio LightSwitch build output 227 | **/*.HTMLClient/GeneratedArtifacts 228 | **/*.DesktopClient/GeneratedArtifacts 229 | **/*.DesktopClient/ModelManifest.xml 230 | **/*.Server/GeneratedArtifacts 231 | **/*.Server/ModelManifest.xml 232 | _Pvt_Extensions 233 | 234 | # LightSwitch generated files 235 | GeneratedArtifacts/ 236 | ModelManifest.xml 237 | 238 | # Paket dependency manager 239 | .paket/paket.exe 240 | 241 | # FAKE - F# Make 242 | .fake/ 243 | -------------------------------------------------------------------------------- /Hibr2Bin/Disk.cpp: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) 2007 - 2017, Matthieu Suiche 4 | Copyright (c) 2012 - 2014, MoonSols Limited 5 | Copyright (c) Comae Technologies DMCC. All rights reserved. 6 | 7 | Module Name: 8 | 9 | Disk.cpp 10 | 11 | Abstract: 12 | 13 | This module contains the internal structure definitions and APIs used by 14 | the Hibr2Bin. 15 | 16 | Author: 17 | 18 | Matthieu Suiche (m) 1-April-2016 19 | 20 | Revision History: 21 | 22 | --*/ 23 | 24 | #include "precomp.h" 25 | 26 | BOOLEAN 27 | WriteMemoryBlocksToDisk( 28 | _In_ MemoryBlock *Base, 29 | _In_ PPROGRAM_ARGUMENTS Vars 30 | ) 31 | { 32 | ULONG64 FileOffset = 0; 33 | ULONG CacheOffset = 0; 34 | PUCHAR Cache; 35 | 36 | BOOLEAN Result = FALSE; 37 | ULONG i = 0; 38 | BYTE *Hash = NULL; 39 | 40 | // 41 | // Console 42 | // 43 | HANDLE Handle; 44 | COORD Initial; 45 | 46 | BOOLEAN NoMoreEntries = FALSE; 47 | 48 | if (Vars->OutFileName) Base->GetContext()->CreateOutputFile(Vars->OutFileName); 49 | else return FALSE; 50 | 51 | // 52 | // Create a one Mb Cache. 53 | // 54 | Cache = new byte[WRITE_CACHE_SIZE]; 55 | memset(Cache, 0, WRITE_CACHE_SIZE); 56 | 57 | wprintf(L"\n"); 58 | Handle = GetStdHandle(STD_OUTPUT_HANDLE); 59 | GetCursorPosition(Handle, &Initial); 60 | 61 | if (!CryptInitSha256()) { 62 | Red(L" Error: SHA256 initialization failed with error = %d\n", GetLastError()); 63 | } 64 | MemoryNode *Current = Base->GetMemoryNodes()->GetFirstChild(); 65 | CompressedMemoryBlock *Block = NULL; 66 | 67 | ULONG XpressPageIndex = 0; 68 | 69 | while (Current) 70 | { 71 | ULONG BytesToWrite; 72 | 73 | while (CacheOffset < WRITE_CACHE_SIZE) 74 | { 75 | if (Block == NULL) 76 | { 77 | ULONG64 Offset = Current->GetKeyObject()->Compressed.XpressHeader; 78 | 79 | Block = new CompressedMemoryBlock(Base->GetContext(), Offset, TRUE); 80 | //if (Current->GetKeyObject()->NoHeader) 81 | Block->SetCompressionSize(Current->GetKeyObject()->CompressedSize); 82 | Block->SetCompressionType(Current->GetKeyObject()->IsCompressed); 83 | 84 | XpressPageIndex = 0; 85 | } 86 | 87 | while ((FileOffset < Current->GetKeyObject()->Range.Minimum) && 88 | (CacheOffset < WRITE_CACHE_SIZE)) 89 | { 90 | memset(Cache + CacheOffset, 0, PAGE_SIZE); 91 | FileOffset += PAGE_SIZE; 92 | CacheOffset += PAGE_SIZE; 93 | } 94 | 95 | if ((CacheOffset < WRITE_CACHE_SIZE)) 96 | { 97 | if (Current->GetKeyObject()->PageCount) 98 | { 99 | assert((Current->GetKeyObject()->Compressed.XpressIndex + XpressPageIndex) <= 0x10); 100 | 101 | RtlCopyMemory(Cache + CacheOffset, 102 | (PUCHAR)Block->GetDecompressedData() + (Current->GetKeyObject()->Compressed.XpressIndex + XpressPageIndex) * PAGE_SIZE, 103 | PAGE_SIZE); 104 | 105 | FileOffset += PAGE_SIZE; 106 | CacheOffset += PAGE_SIZE; 107 | XpressPageIndex += 1; 108 | } 109 | 110 | // 111 | // Next Mdl. 112 | // 113 | if (FileOffset >= Current->GetKeyObject()->Range.Maximum) 114 | { 115 | MemoryNode *Right = Current->GetRightChild(); 116 | if (Right == NULL) 117 | { 118 | NoMoreEntries = TRUE; 119 | break; 120 | } 121 | 122 | Current = Right; 123 | 124 | if (Block) 125 | { 126 | delete Block; 127 | Block = NULL; 128 | } 129 | } 130 | } 131 | } 132 | 133 | BytesToWrite = CacheOffset; 134 | 135 | SetConsoleCursorPosition(Handle, Initial); 136 | White(L" [0x%llx of 0x%llx] ", FileOffset - BytesToWrite, Current->GetKeyObject()->Range.Maximum); 137 | CryptHashData(Cache, BytesToWrite); 138 | 139 | Result = Base->GetContext()->WriteFile(Cache, BytesToWrite); 140 | if (Result == FALSE) goto CleanUp; 141 | 142 | CacheOffset = 0; 143 | memset(Cache, 0, WRITE_CACHE_SIZE); 144 | 145 | if (NoMoreEntries) break; 146 | } 147 | 148 | Hash = CryptGetHash(); 149 | 150 | Result = TRUE; 151 | 152 | CleanUp: 153 | if (Result == TRUE) 154 | { 155 | SetConsoleCursorPosition(Handle, Initial); 156 | Green(L" [0x%llx of 0x%llx] \n", FileOffset, Current->GetKeyObject()->Range.Maximum); 157 | 158 | if (Hash != NULL) 159 | { 160 | White(L" SHA256 = "); 161 | for (i = 0; i < CryptGetHashLen(); i += 1) wprintf(L"%02x", Hash[i]); 162 | wprintf(L"\n"); 163 | delete[] Hash; 164 | } 165 | } 166 | else 167 | { 168 | SetConsoleCursorPosition(Handle, Initial); 169 | Red(L" [0x%llx of 0x%llx] \n", FileOffset, Current->GetKeyObject()->Range.Maximum); 170 | } 171 | 172 | if (Cache) 173 | { 174 | delete[] Cache; 175 | Cache = NULL; 176 | } 177 | 178 | return Result; 179 | 180 | } -------------------------------------------------------------------------------- /Hibr2Bin/Hiber.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) 2007 - 2017, Matthieu Suiche 4 | Copyright (c) 2012 - 2014, MoonSols Limited 5 | Copyright (c) 2015 - 2017, Comae Technologies FZE 6 | Copyright (c) 2017 - 2018, Comae Technologies DMCC 7 | 8 | Module Name: 9 | 10 | Hiber.h 11 | 12 | Abstract: 13 | 14 | This module contains the internal structure definitions and APIs used by 15 | the Hibr2Bin. 16 | 17 | Author: 18 | 19 | Matthieu Suiche (m) 1-April-2016 20 | 21 | Revision History: 22 | 23 | --*/ 24 | 25 | #ifndef __HIBER_DEF_H__ 26 | #define __HIBER_DEF_H__ 27 | 28 | #define HIBR_IMAGE_SIGNATURE 'RBIH' 29 | #define HIBR_IMAGE_SIGNATURE_RESTORE 'RTSR' 30 | #define HIBR_IMAGE_SIGNATURE_WAKE 'EKAW' 31 | #define HIBR_IMAGE_SIGNATURE_BREAK 'PKRB' 32 | #define HIBR_IMAGE_SIGNATURE_HORM 'MROH' 33 | 34 | #define MAX_HIBER_PAGES (16) 35 | #define PAGE_SIZE 0x1000 36 | #define MAX_COMPRESSED_BLOCK (MAX_HIBER_PAGES * PAGE_SIZE) 37 | 38 | // 39 | // NT 5.0, NT 5.1, NT 6.0 x86 40 | // 41 | typedef struct _PO_MEMORY_RANGE_ARRAY_LINK32 42 | { 43 | ULONG Next; 44 | ULONG NextTable; 45 | ULONG CheckSum; 46 | ULONG EntryCount; 47 | } PO_MEMORY_RANGE_ARRAY_LINK32, *PPO_MEMORY_RANGE_ARRAY_LINK32; 48 | 49 | typedef struct _PO_MEMORY_RANGE_ARRAY_RANGE32 50 | { 51 | ULONG PageNo; 52 | ULONG StartPage; 53 | ULONG EndPage; 54 | ULONG CheckSum; 55 | } PO_MEMORY_RANGE_ARRAY_RANGE32, *PPO_MEMORY_RANGE_ARRAY_RANGE32; 56 | 57 | typedef struct _MEMORY_RANGE_ARRAY 58 | { 59 | PO_MEMORY_RANGE_ARRAY_LINK32 Link; 60 | PO_MEMORY_RANGE_ARRAY_RANGE32 Range[ANYSIZE_ARRAY]; 61 | } PO_MEMORY_RANGE_ARRAY32, *PPO_MEMORY_RANGE_ARRAY32; 62 | 63 | // 64 | // NT 5.2 x64 65 | // 66 | typedef struct _PO_MEMORY_RANGE_ARRAY_LINK64_NT52 67 | { 68 | ULONGLONG Next; 69 | ULONGLONG NextTable; 70 | ULONG Checksum; 71 | ULONG EntryCount; 72 | ULONGLONG Reserved; 73 | } PO_MEMORY_RANGE_ARRAY_LINK64_NT52, *PPO_MEMORY_RANGE_ARRAY_LINK64_NT52; 74 | 75 | typedef struct _PO_MEMORY_RANGE_ARRAY_RANGE64_NT52 76 | { 77 | ULONGLONG PageNo; 78 | ULONGLONG StartPage; 79 | ULONGLONG EndPage; 80 | ULONGLONG CheckSum; 81 | } PO_MEMORY_RANGE_ARRAY_RANGE64_NT52, *PPO_MEMORY_RANGE_ARRAY_RANGE64_NT52; 82 | 83 | typedef struct _MEMORY_RANGE_ARRAY64_NT52 84 | { 85 | PO_MEMORY_RANGE_ARRAY_LINK64_NT52 Link; 86 | PO_MEMORY_RANGE_ARRAY_RANGE64_NT52 Range[ANYSIZE_ARRAY]; 87 | } PO_MEMORY_RANGE_ARRAY64_NT52, *PPO_MEMORY_RANGE_ARRAY64_NT52; 88 | 89 | // 90 | // NT 6.0 x64 91 | // 92 | typedef struct _PO_MEMORY_RANGE_ARRAY_LINK64 93 | { 94 | ULONGLONG Next; 95 | ULONGLONG NextTable; 96 | ULONG EntryCount; 97 | ULONG Padding; 98 | } PO_MEMORY_RANGE_ARRAY_LINK64, *PPO_MEMORY_RANGE_ARRAY_LINK64; 99 | 100 | typedef struct _PO_MEMORY_RANGE_ARRAY_RANGE64 101 | { 102 | ULONGLONG StartPage; 103 | ULONGLONG EndPage; 104 | } PO_MEMORY_RANGE_ARRAY_RANGE64, *PPO_MEMORY_RANGE_ARRAY_RANGE64; 105 | 106 | typedef struct _MEMORY_RANGE_ARRAY64 107 | { 108 | PO_MEMORY_RANGE_ARRAY_LINK64 Link; 109 | PO_MEMORY_RANGE_ARRAY_RANGE64 Range[ANYSIZE_ARRAY]; 110 | } PO_MEMORY_RANGE_ARRAY64, *PPO_MEMORY_RANGE_ARRAY64; 111 | 112 | 113 | // 114 | // NT 6.1 x86 115 | // 116 | typedef struct _PO_MEMORY_RANGE_ARRAY_RANGE32_NT61 { 117 | ULONG StartPage; 118 | ULONG EndPage; 119 | } PO_MEMORY_RANGE_ARRAY_RANGE32_NT61, *PPO_MEMORY_RANGE_ARRAY_RANGE32_NT61; 120 | 121 | typedef struct _PO_MEMORY_RANGE_ARRAY_LINK32_NT61 { 122 | ULONG NextTable; 123 | ULONG EntryCount; 124 | } PO_MEMORY_RANGE_ARRAY_LINK32_NT61, *PPO_MEMORY_RANGE_ARRAY_LINK32_NT61; 125 | 126 | typedef struct _PO_MEMORY_RANGE_ARRAY32_NT61 { 127 | PO_MEMORY_RANGE_ARRAY_LINK32_NT61 Link; 128 | PO_MEMORY_RANGE_ARRAY_RANGE32_NT61 Range[ANYSIZE_ARRAY]; 129 | } PO_MEMORY_RANGE_ARRAY32_NT61, *PPO_MEMORY_RANGE_ARRAY32_NT61; 130 | 131 | // 132 | // NT 6.1 x64 133 | // 134 | typedef struct _PO_MEMORY_RANGE_ARRAY_RANGE64_NT61 { 135 | ULONGLONG StartPage; 136 | ULONGLONG EndPage; 137 | } PO_MEMORY_RANGE_ARRAY_RANGE64_NT61, *PPO_MEMORY_RANGE_ARRAY_RANGE64_NT61; 138 | 139 | typedef struct _PO_MEMORY_RANGE_ARRAY_LINK64_NT61 { 140 | ULONGLONG NextTable; 141 | ULONG EntryCount; 142 | ULONG Padding; 143 | } PO_MEMORY_RANGE_ARRAY_LINK64_NT61, *PPO_MEMORY_RANGE_ARRAY_LINK64_NT61; 144 | 145 | typedef struct _PO_MEMORY_RANGE_ARRAY64_NT61 { 146 | PO_MEMORY_RANGE_ARRAY_LINK64_NT61 Link; 147 | PO_MEMORY_RANGE_ARRAY_RANGE64_NT61 Range[ANYSIZE_ARRAY]; 148 | } PO_MEMORY_RANGE_ARRAY64_NT61, *PPO_MEMORY_RANGE_ARRAY64_NT61; 149 | 150 | 151 | // 152 | // Windows 8 32bits 153 | // 154 | typedef enum _HIBER_COMPRESS_METHOD 155 | { 156 | XpressFast = 0, 157 | XpressMax = 1, 158 | XpressHuffFast = 2, 159 | XpressHuffMax = 3 160 | } HIBER_COMPRESS_METHOD; 161 | 162 | typedef struct _PO_MEMORY_RANGE32_NT62 163 | { 164 | ULONG PageCount : 4; 165 | ULONG StartPage : 28; 166 | } PO_MEMORY_RANGE32_NT62, *PPO_MEMORY_RANGE32_NT62; 167 | 168 | typedef struct _PO_MEMORY_RANGE_TABLE32_NT62 169 | { 170 | ULONG RangeCount : 8; 171 | ULONG CompressedSize : 22; 172 | ULONG CompressMethod : 2; 173 | PO_MEMORY_RANGE32_NT62 Range[ANYSIZE_ARRAY]; 174 | } PO_MEMORY_RANGE_TABLE32_NT62, *PPO_MEMORY_RANGE_TABLE32_NT62; 175 | 176 | #pragma pack(push) // push current alignment to stack 177 | #pragma pack(4) // set alignment to 1 byte boundary 178 | typedef struct _PO_MEMORY_RANGE64_NT62 179 | { 180 | ULONG64 PageCount : 4; 181 | ULONG64 StartPage : 28; 182 | } PO_MEMORY_RANGE64_NT62, *PPO_MEMORY_RANGE64_NT62; 183 | 184 | typedef struct _PO_MEMORY_RANGE_TABLE64_NT62 185 | { 186 | ULONG RangeCount : 8; 187 | ULONG CompressedSize : 22; 188 | ULONG CompressMethod : 2; 189 | PO_MEMORY_RANGE64_NT62 Range[ANYSIZE_ARRAY]; 190 | } PO_MEMORY_RANGE_TABLE64_NT62, *PPO_MEMORY_RANGE_TABLE64_NT62; 191 | #pragma pack(pop) 192 | 193 | #endif -------------------------------------------------------------------------------- /Hibr2Bin/Hibr2Bin.cpp: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) 2007 - 2017, Matthieu Suiche 4 | Copyright (c) 2012 - 2014, MoonSols Limited 5 | Copyright (c) Comae Technologies DMCC. All rights reserved. 6 | Copyright (c) 2022, Magnet Forensics, Inc. All rights reserved. 7 | 8 | Module Name: 9 | 10 | Hibr2Bin.cpp 11 | 12 | Abstract: 13 | 14 | This module contains the internal structure definitions and APIs used by 15 | the Hibr2Bin. 16 | 17 | Author: 18 | 19 | Matthieu Suiche (m) 1-April-2016 20 | 21 | Revision History: 22 | 23 | --*/ 24 | 25 | #include "precomp.h" 26 | 27 | #ifndef COMAE_TOOLKIT_VERSION 28 | #define COMAE_TOOLKIT_VERSION "3.0.0.undefined" 29 | #endif 30 | 31 | VOID 32 | Help() 33 | { 34 | wprintf(L"Usage: Hibr2Bin [Options] /INPUT /OUTPUT \n\n"); 35 | wprintf(L"Description:\n" 36 | L" Enables users to uncompress Windows hibernation file.\n\n"); 37 | 38 | wprintf(L"Options:\n" 39 | L" /PLATFORM, /P Select platform (X64 or X86)\n" 40 | L" /MAJOR, /V Select major version (e.g. 6 for NT 6.1\n" 41 | L" /MINOR, /M Select minor version (e.g. 1 for NT 6.1)\n" 42 | L" /OFFSET, /L Data offset in hexadecimal (optional)\n" 43 | L" /INPUT, /I Input hiberfil.sys file.\n" 44 | L" /OUTPUT, /O Output hiberfil.sys file.\n\n"); 45 | 46 | wprintf(L"Versions:\n" 47 | L" /MAJOR 5 /MINOR 1 Windows XP\n" 48 | L" /MAJOR 5 /MINOR 2 Windows XP x64, Windows 2003 R2\n" 49 | L" /MAJOR 6 /MINOR 0 Windows Vista, Windows Server 2008\n" 50 | L" /MAJOR 6 /MINOR 1 Windows 7, Windows Server 2008 R2\n" 51 | L" /MAJOR 6 /MINOR 2 Windows 8, Windows Server 2012\n" 52 | L" /MAJOR 6 /MINOR 3 Windows 8.1, Windows Server 2012 R2\n" 53 | L" /MAJOR 10 /MINOR 0 Windows 10, Windows Server 2017\n\n"); 54 | 55 | wprintf(L"Examples:\n\n"); 56 | 57 | wprintf(L" Uncompress a Windows 7 (NT 6.1) x64 hibernation file:\n" 58 | L" Hibr2Bin /PLATFORM X64 /MAJOR 6 /MINOR 1 /INPUT hiberfil.sys /OUTPUT uncompressed.bin\n\n" 59 | L" Uncompress a Windows 10 (NT 10.0) x86 hibernation file:\n" 60 | L" Hibr2Bin /PLATFORM X86 /MAJOR 10 /MINOR 0 /INPUT hiberfil.sys /OUTPUT uncompressed.bin\n"); 61 | } 62 | 63 | BOOLEAN 64 | Parse( 65 | ULONG MaxArg, 66 | LPWSTR *argv, 67 | PPROGRAM_ARGUMENTS Arguments 68 | ) 69 | { 70 | ULONG Index = 1; 71 | 72 | while (Index < MaxArg) 73 | { 74 | if ((argv[Index][0] == L'/') || (argv[Index][0] == L'-')) 75 | { 76 | if ((_wcsicmp(argv[Index], L"/PLATFORM") == 0) || (_wcsicmp(argv[Index], L"/P") == 0)) 77 | { 78 | Index++; 79 | 80 | Arguments->HasPlatform = TRUE; 81 | if (_wcsicmp(argv[Index], L"X86") == 0) Arguments->Platform = PlatformX86; 82 | else if (_wcsicmp(argv[Index], L"X64") == 0) Arguments->Platform = PlatformX64; 83 | else 84 | { 85 | Arguments->HasPlatform = FALSE; 86 | } 87 | } 88 | else if ((_wcsicmp(argv[Index], L"/MAJOR") == 0) || (_wcsicmp(argv[Index], L"/V") == 0)) 89 | { 90 | Index++; 91 | 92 | Arguments->MajorVersion = _wtoi(argv[Index]); 93 | Arguments->HasMajorVersion = TRUE; 94 | } 95 | else if ((_wcsicmp(argv[Index], L"/MINOR") == 0) || (_wcsicmp(argv[Index], L"/M") == 0)) 96 | { 97 | Index++; 98 | 99 | Arguments->MinorVersion = _wtoi(argv[Index]); 100 | Arguments->HasMinorVersion = TRUE; 101 | } 102 | else if ((_wcsicmp(argv[Index], L"/OFFSET") == 0) || (_wcsicmp(argv[Index], L"/L") == 0)) 103 | { 104 | LPWSTR p; 105 | Index++; 106 | 107 | Arguments->DataOffset = wcstol(argv[Index], &p, 16); 108 | Arguments->HasDataOffset = TRUE; 109 | } 110 | else if ((_wcsicmp(argv[Index], L"/INPUT") == 0) || (_wcsicmp(argv[Index], L"/I") == 0)) 111 | { 112 | Index++; 113 | Arguments->FileName = argv[Index]; 114 | } 115 | else if ((_wcsicmp(argv[Index], L"/OUTPUT") == 0) || (_wcsicmp(argv[Index], L"/O") == 0)) 116 | { 117 | Index++; 118 | Arguments->OutFileName = argv[Index]; 119 | } 120 | else if ((_wcsicmp(argv[Index], L"/?") == 0) || (_wcsicmp(argv[Index], L"/HELP") == 0)) 121 | { 122 | return FALSE; 123 | } 124 | else 125 | { 126 | wprintf(L" Error: Invalid parameter.\n"); 127 | return FALSE; 128 | } 129 | } 130 | 131 | Index++; 132 | } 133 | 134 | // 135 | // Validate parameters. 136 | // 137 | 138 | if (!Arguments->HasPlatform) wprintf(L" Error: Please provide a platform type using /P.\n"); 139 | if (!Arguments->HasMajorVersion) wprintf(L" Error: Please provide a major version using /V parameter.\n"); 140 | if (!Arguments->HasMinorVersion) wprintf(L" Error: Please provide a minor version using /M parameter.\n"); 141 | 142 | if (!Arguments->HasMajorVersion || !Arguments->HasMinorVersion || !Arguments->HasPlatform) return FALSE; 143 | 144 | // Known versions of Windows: http://www.codeproject.com/Articles/678606/Part-Overcoming-Windows-s-deprecation-of-GetVe 145 | if (Arguments->MajorVersion == 10) 146 | { 147 | // 148 | // NT 10.0 149 | // 150 | if (Arguments->MinorVersion != 0) 151 | { 152 | wprintf(L" Error: Unsupported target version."); 153 | return FALSE; 154 | } 155 | } 156 | else if (Arguments->MajorVersion == 6) 157 | { 158 | // 159 | // NT 6.3, NT 6.2, NT 6.1, NT 6.0 160 | // 161 | if ((Arguments->MinorVersion != 3) && (Arguments->MinorVersion != 2) && 162 | (Arguments->MinorVersion != 1) && (Arguments->MinorVersion != 0)) 163 | { 164 | wprintf(L" Error: Unsupported target version."); 165 | return FALSE; 166 | } 167 | } 168 | else if (Arguments->MajorVersion == 5) 169 | { 170 | // 171 | // NT 5.2 (X64), NT 5.1 (x86) 172 | // 173 | if (((Arguments->MinorVersion != 2) && (Arguments->Platform != PlatformX64)) || 174 | ((Arguments->MinorVersion != 1) && (Arguments->Platform != PlatformX86))) 175 | { 176 | wprintf(L" Error: Unsupported target version."); 177 | return FALSE; 178 | } 179 | } 180 | 181 | return TRUE; 182 | } 183 | 184 | BOOLEAN 185 | IsLicenseValid() 186 | { 187 | SYSTEMTIME SystemTime = { 0 }; 188 | 189 | GetLocalTime(&SystemTime); 190 | #if 0 191 | if (!((SystemTime.wYear == 2017) && (SystemTime.wMonth == 6))) 192 | { 193 | return FALSE; 194 | } 195 | #endif 196 | return TRUE; 197 | } 198 | 199 | LPWSTR 200 | GetPlatformType( 201 | PlatformType Type 202 | ) 203 | { 204 | switch (Type) 205 | { 206 | case PlatformX86: 207 | return L"X86"; 208 | case PlatformX64: 209 | return L"X64"; 210 | } 211 | 212 | return L"Unknown"; 213 | } 214 | 215 | int 216 | wmain( 217 | ULONG argc, 218 | LPWSTR *argv 219 | ) 220 | { 221 | PROGRAM_ARGUMENTS Arguments = { 0 }; 222 | 223 | wprintf(L"\n" 224 | L" Hibr2Bin %S\n" 225 | L" Copyright (C) 2007 - 2021, Matthieu Suiche \n" 226 | L" Copyright (C) 2012 - 2014, MoonSols Limited \n" 227 | L" Copyright (C) 2016 - 2021, Comae Technologies DMCC \n" 228 | L" Copyright (c) 2022, Magnet Forensics, Inc. \n\n", 229 | COMAE_TOOLKIT_VERSION); 230 | 231 | if ((argc < 2) || !Parse(argc, argv, &Arguments)) 232 | { 233 | Help(); 234 | return FALSE; 235 | } 236 | 237 | if (!IsLicenseValid()) 238 | { 239 | Red(L" Error: Beta program expired. Get the latest version on www.comae.io \n"); 240 | return FALSE; 241 | } 242 | 243 | wprintf(L" In File: %s\n", Arguments.FileName); 244 | wprintf(L" Out File: %s\n", Arguments.OutFileName); 245 | wprintf(L" Target Version: Microsoft Windows NT %d.%d (%s)\n", Arguments.MajorVersion, Arguments.MinorVersion, GetPlatformType(Arguments.Platform)); 246 | 247 | MemoryBlock *MemoryBlocks = NULL; 248 | BOOLEAN Result = FALSE; 249 | 250 | if (ProcessHiberfil(&Arguments, &MemoryBlocks)) 251 | { 252 | Result = WriteMemoryBlocksToDisk(MemoryBlocks, &Arguments); 253 | } 254 | 255 | return Result; 256 | } -------------------------------------------------------------------------------- /Hibr2Bin/Hiberfil.cpp: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) 2007 - 2017, Matthieu Suiche 4 | Copyright (c) 2012 - 2014, MoonSols Limited 5 | Copyright (c) Comae Technologies DMCC. All rights reserved. 6 | 7 | Module Name: 8 | 9 | Hiberfil.cpp 10 | 11 | Abstract: 12 | 13 | This module contains the internal structure definitions and APIs used by 14 | the Hibr2Bin. 15 | 16 | Author: 17 | 18 | Matthieu Suiche (m) 1-April-2016 19 | 20 | Revision History: 21 | 22 | --*/ 23 | 24 | #include "precomp.h" 25 | BOOLEAN 26 | ProcessHiberfil( 27 | _In_ PPROGRAM_ARGUMENTS Vars, 28 | _Out_ MemoryBlock **OutMemoryBlock 29 | ) 30 | { 31 | BOOLEAN Result = FALSE; 32 | ULONG64 RestorePage[2]; 33 | ULONG TotalUncompressedPages = 0; 34 | ULONG j = 0; 35 | ULONG i; 36 | 37 | if (!Vars->HasPlatform || !Vars->HasMajorVersion || 38 | !Vars->HasMinorVersion || !Vars->FileName || 39 | !Vars->OutFileName) 40 | { 41 | Red(L" Error: Invalid parameters.\n"); 42 | return FALSE; 43 | } 44 | 45 | MemoryBlock *Base = new MemoryBlock(Vars->Platform, Vars->MajorVersion, Vars->MinorVersion); 46 | if (!Base->GetContext()->OpenFile(Vars->FileName)) 47 | { 48 | wprintf(L" Error: File not found!\n"); 49 | return FALSE; 50 | } 51 | 52 | if ((Base->GetSignature() == HIBR_IMAGE_SIGNATURE_WAKE) && Base->GetContext()->IsWin8AndAbove()) 53 | { 54 | Red(L" Warning: The signature is WAKE. The content of the hibernation file could be wiped out.\n"); 55 | } 56 | 57 | if (Vars->HasDataOffset) { 58 | 59 | White(L" Data offset: 0x%llx\n", Vars->DataOffset); 60 | 61 | RestorePage[0] = Vars->DataOffset; 62 | } 63 | else { 64 | 65 | RestorePage[0] = Base->GetInitialOffset(); 66 | } 67 | 68 | RestorePage[1] = Base->GetFirstKernelRestorePage(); 69 | 70 | for (i = 0; i < _countof(RestorePage); i++) { 71 | 72 | if (RestorePage[i]) { 73 | 74 | Base->SetInitialOffset(RestorePage[i]); 75 | 76 | MemoryRangeTable *RangeTable = Base->GetFirstRangeTable(); 77 | ULONG RangeTableIndex = 0; 78 | 79 | wprintf(L" "); 80 | 81 | while (RangeTable->IsValid()) 82 | { 83 | wprintf(L"."); 84 | // wprintf(L"Table #%d\n", j); 85 | 86 | CompressedMemoryBlock *CompressedBlock = new CompressedMemoryBlock(RangeTable->GetContext(), RangeTable->GetCompressedBlockOffset()); 87 | 88 | ULONG RangeCount = RangeTable->GetRangeCount(); 89 | if (RangeCount > 0x1FF) 90 | { 91 | Red(L" Error: Invalid file format.\n"); 92 | break; 93 | } 94 | 95 | ULONG UncompressedPages = RangeTable->GetCompressedBlockIndex(RangeCount); 96 | ULONG CompressedSize = RangeTable->GetCompressedSize(); 97 | DbgPrint(L"\nRangeTableIndex[%d] has %d ranges @ 0x%llx. Total blocks to be uncompressed: %d 0x%x (Size = 0x%x)- ", 98 | RangeTableIndex, RangeCount, RangeTable->GetCompressedBlockOffset(), 99 | UncompressedPages, UncompressedPages * PAGE_SIZE, 100 | CompressedSize); 101 | RangeTableIndex++; 102 | 103 | if (Base->GetContext()->IsWin8AndAbove()) 104 | { 105 | if ((UncompressedPages == 0) || (UncompressedPages > MAX_HIBER_PAGES)) break; 106 | 107 | if (RangeTable->GetCompressedSize() > MAX_COMPRESSED_BLOCK) break; 108 | } 109 | else 110 | { 111 | if (UncompressedPages == 0) break; 112 | } 113 | 114 | TotalUncompressedPages += UncompressedPages; 115 | 116 | ULONG CompressedPageIndex = 0; 117 | 118 | for (ULONG Index = 0; Index < RangeTable->GetRangeCount(); Index += 1) 119 | { 120 | MemoryRangeEntry *Entry = RangeTable->GetRangeEntry(Index); 121 | ULONG64 StartPage = Entry->GetStartPage(); 122 | ULONG64 PageCount = Entry->GetPageCount(); 123 | 124 | DbgPrint(L"[0x%llx - 0x%llx] CompressedSize = 0x%x\n", 125 | StartPage * PAGE_SIZE, (StartPage + PageCount) * PAGE_SIZE, RangeTable->GetCompressedSize()); 126 | 127 | if (CompressedPageIndex && ((CompressedPageIndex % 0x10) == 0)) CompressedBlock->GetNextCompressedBlock(); 128 | 129 | MEMORY_DESCRIPTOR MemDesc = { 0 }; 130 | 131 | MemDesc.IsCompressed = CompressedBlock->IsCompressed(); 132 | MemDesc.PageCount = (ULONG)PageCount; 133 | MemDesc.Range.Minimum = StartPage * PAGE_SIZE; 134 | MemDesc.Range.Maximum = MemDesc.Range.Minimum + (PageCount * PAGE_SIZE); 135 | MemDesc.Compressed.XpressHeader = CompressedBlock->GetCompressedBlockOffset(); 136 | 137 | if (Base->GetContext()->IsWin8AndAbove()) 138 | { 139 | MemDesc.CompressedSize = RangeTable->GetCompressedSize(); 140 | MemDesc.Compressed.XpressIndex = (CompressedPageIndex % 0x10); 141 | MemDesc.Compressed.CompressionMethod = RangeTable->GetCompressMethod(); 142 | MemDesc.NoHeader = 1; 143 | 144 | if (MemDesc.Compressed.CompressionMethod != XpressFast) 145 | { 146 | DbgPrint(L"Compression %d\n", RangeTable->GetCompressMethod()); 147 | } 148 | } 149 | else 150 | { 151 | if (!MemDesc.IsCompressed) 152 | { 153 | MemDesc.Uncompressed.BaseOffset = CompressedBlock->GetCompressedBlockOffset(); 154 | MemDesc.Uncompressed.BaseOffset += CompressedBlock->GetCompressedHeaderSize(); 155 | } 156 | 157 | MemDesc.Compressed.XpressIndex = (CompressedPageIndex % 0x10); 158 | MemDesc.CompressedSize = CompressedBlock->GetCompressedBlockSize(); 159 | } 160 | 161 | if (((CompressedPageIndex % 0x10) + PageCount) > 0x10) 162 | { 163 | // 164 | // Split required. 165 | // 166 | ULONG LastCompressedBlockStartIndex = 0; 167 | for (ULONG PageIndex = 0; PageIndex < PageCount; PageIndex += 1) 168 | { 169 | CompressedPageIndex += 1; 170 | 171 | if (((CompressedPageIndex % 0x10) == 0) || ((PageIndex + 1) >= PageCount)) 172 | { 173 | MemDesc.PageCount = ((PageIndex + 1) - LastCompressedBlockStartIndex); 174 | MemDesc.Range.Minimum = (StartPage + LastCompressedBlockStartIndex) * PAGE_SIZE; 175 | MemDesc.Range.Maximum = ((StartPage + LastCompressedBlockStartIndex) * PAGE_SIZE) + (MemDesc.PageCount * PAGE_SIZE); 176 | Base->GetMemoryNodes()->InsertNode(StartPage * PAGE_SIZE, &MemDesc); 177 | 178 | // 179 | // Next block 180 | // 181 | LastCompressedBlockStartIndex = PageIndex + 1; 182 | if (((CompressedPageIndex % 0x10) == 0) && !((PageIndex + 1) >= PageCount)) 183 | { 184 | // 185 | // Next Xpress block. 186 | // Make sure we still have another round to go to avoid a double GetNextCompressedBlock() 187 | // 188 | CompressedBlock->GetNextCompressedBlock(); 189 | MemDesc.Compressed.XpressHeader = CompressedBlock->GetCompressedBlockOffset(); 190 | MemDesc.IsCompressed = CompressedBlock->IsCompressed(); 191 | if (!MemDesc.IsCompressed) 192 | { 193 | MemDesc.Uncompressed.BaseOffset = CompressedBlock->GetCompressedBlockOffset(); 194 | MemDesc.Uncompressed.BaseOffset += CompressedBlock->GetCompressedHeaderSize(); 195 | } 196 | MemDesc.CompressedSize = CompressedBlock->GetCompressedBlockSize(); 197 | } 198 | 199 | MemDesc.Compressed.XpressIndex = (CompressedPageIndex % 0x10); 200 | } 201 | } 202 | } 203 | else 204 | { 205 | CompressedPageIndex += (ULONG)PageCount; 206 | Base->GetMemoryNodes()->InsertNode(StartPage * PAGE_SIZE, &MemDesc); 207 | } 208 | 209 | delete Entry; 210 | } 211 | 212 | j++; 213 | if (!RangeTable->GetNextRangeTable()) 214 | { 215 | // 216 | // No more range table to read. 217 | // 218 | if (TotalUncompressedPages) Result = TRUE; 219 | break; 220 | } 221 | delete CompressedBlock; 222 | } 223 | } 224 | } 225 | 226 | #if 0 227 | for (MemoryNode *Current = Base->GetMemoryNodes()->GetFirstChild(); 228 | Current; 229 | Current = Current->GetRightChild()) 230 | { 231 | wprintf(L" -> 0x%I64X-0x%I64X\n", Current->GetKey(), Current->GetKeyObject()->Range.Maximum.QuadPart); 232 | } 233 | #endif 234 | 235 | // 236 | // Windows 10 x86: Dword at [ImageHeader + 0x38] == TotalUncompressedPages 237 | // 238 | wprintf(L"\n Total pages = 0x%x \n", TotalUncompressedPages); 239 | DbgPrint(L"Result = %d\n", Result); 240 | 241 | if (TotalUncompressedPages) Result = TRUE; 242 | 243 | *OutMemoryBlock = Base; 244 | 245 | return Result; 246 | } 247 | -------------------------------------------------------------------------------- /Hibr2Bin/MemoryBlocks.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) 2007 - 2017, Matthieu Suiche 4 | Copyright (c) 2012 - 2014, MoonSols Limited 5 | Copyright (c) 2015 - 2017, Comae Technologies FZE 6 | Copyright (c) 2017 - 2018, Comae Technologies DMCC 7 | 8 | Module Name: 9 | 10 | MemoryBlocks.h 11 | 12 | Abstract: 13 | 14 | This module contains the internal structure definitions and APIs used by 15 | the Hibr2Bin. 16 | 17 | Author: 18 | 19 | Matthieu Suiche (m) 1-April-2016 20 | 21 | Revision History: 22 | 23 | --*/ 24 | 25 | #ifndef __MEMORY_BLOCK_H__ 26 | #define __MEMORY_BLOCK_H__ 27 | 28 | typedef struct _ADDRESS_RANGE { 29 | ULONG64 Minimum; 30 | ULONG64 Maximum; 31 | } ADDRESS_RANGE, *PADDRESS_RANGE; 32 | 33 | typedef struct _MEMORY_DESCRIPTOR { 34 | BOOL IsCompressed; 35 | BOOL NoHeader; 36 | ULONG CompressedSize; 37 | union { 38 | struct { 39 | ULONG64 BaseOffset; 40 | } Uncompressed; 41 | struct { 42 | ULONG64 XpressHeader; 43 | ULONG XpressIndex; 44 | ULONG CompressionMethod; 45 | } Compressed; 46 | }; 47 | ADDRESS_RANGE Range; 48 | ULONG PageCount; 49 | } MEMORY_DESCRIPTOR, *PMEMORY_DESCRIPTOR; 50 | 51 | class MemoryNode { 52 | public: 53 | MemoryNode() { } 54 | 55 | MemoryNode(MemoryNode *Left, MemoryNode *Right) 56 | { 57 | m_LeftChild = Left; 58 | m_RightChild = Right; 59 | } 60 | 61 | MemoryNode(MemoryNode *Left, MemoryNode *Right, ULONG64 Key, PMEMORY_DESCRIPTOR Object) 62 | { 63 | m_LeftChild = Left; 64 | m_RightChild = Right; 65 | m_Key = Key; 66 | m_Object = *Object; 67 | 68 | assert((m_Object.Range.Maximum - m_Object.Range.Minimum) <= 0x10000); 69 | assert(m_Object.PageCount <= 0x10); 70 | } 71 | 72 | MemoryNode *GetLeftChild() 73 | { 74 | return m_LeftChild; 75 | } 76 | 77 | VOID SetLeftChild(MemoryNode *Child) 78 | { 79 | m_LeftChild = Child; 80 | } 81 | 82 | MemoryNode* GetRightChild() 83 | { 84 | if (m_RightChild) 85 | { 86 | if (m_RightChild->GetKeyObject() == NULL) return NULL; 87 | 88 | return m_RightChild; 89 | } 90 | 91 | return NULL; 92 | } 93 | 94 | VOID SetRightChild(MemoryNode *Child) 95 | { 96 | m_RightChild = Child; 97 | } 98 | 99 | MemoryNode *GetFirstChild() 100 | { 101 | MemoryNode *Current = this; 102 | 103 | while (Current->GetLeftChild() && (Current = Current->GetLeftChild())); 104 | 105 | return Current; 106 | } 107 | 108 | ULONG64 109 | GetKey() 110 | { 111 | return m_Key; 112 | } 113 | 114 | PMEMORY_DESCRIPTOR 115 | GetKeyObject() 116 | { 117 | return &m_Object; 118 | } 119 | 120 | BOOLEAN 121 | InsertNode( 122 | ULONG64 Key, 123 | PMEMORY_DESCRIPTOR Object 124 | ) 125 | { 126 | MemoryNode *Current = this; 127 | 128 | if (Key < m_Key) 129 | { 130 | // 131 | // Going left 132 | // 133 | do 134 | { 135 | if (Current->GetLeftChild() == NULL) 136 | { 137 | MemoryNode *NewNode = new MemoryNode(NULL, Current, Key, Object); 138 | Current->SetLeftChild(NewNode); 139 | break; 140 | } 141 | else if (Key > Current->m_Key) 142 | { 143 | MemoryNode *NewNode = new MemoryNode(Current, Current->GetRightChild(), Key, Object); 144 | Current->GetRightChild()->SetLeftChild(NewNode); 145 | Current->SetRightChild(NewNode); 146 | break; 147 | } 148 | } while (Current = Current->GetLeftChild()); 149 | } 150 | else 151 | { 152 | do 153 | { 154 | if (Current->GetRightChild() == NULL) 155 | { 156 | MemoryNode *NewNode = new MemoryNode(Current, NULL, Key, Object); 157 | Current->SetRightChild(NewNode); 158 | 159 | break; 160 | } 161 | else if ((Key < Current->m_Key)) 162 | { 163 | // 164 | // 165 | // 166 | MemoryNode *NewNode = new MemoryNode(Current->GetLeftChild(), Current, Key, Object); 167 | Current->GetLeftChild()->SetRightChild(NewNode); 168 | Current->SetLeftChild(NewNode); 169 | 170 | break; 171 | } 172 | } while (Current = Current->GetRightChild()); 173 | } 174 | 175 | return TRUE; 176 | } 177 | 178 | private: 179 | MemoryNode *m_LeftChild; 180 | MemoryNode *m_RightChild; 181 | 182 | ULONG64 m_Key; // VirtualAddress 183 | MEMORY_DESCRIPTOR m_Object; 184 | 185 | }; 186 | 187 | class MemoryObject { 188 | public: 189 | VOID Init(FileContext *FileContext, ULONG64 FileOffset, ULONG DataSize, BOOLEAN NoAllocationFlag); 190 | 191 | MemoryObject(FileContext *FileContext, ULONG64 FileOffset, ULONG DataSize, BOOLEAN NoAllocationFlag) 192 | { 193 | Init(FileContext, FileOffset, DataSize, NoAllocationFlag); 194 | } 195 | 196 | MemoryObject(FileContext *FileContext, ULONG64 FileOffset, ULONG DataSize) 197 | { 198 | Init(FileContext, FileOffset, DataSize, FALSE); 199 | } 200 | 201 | BOOLEAN 202 | IsValid() { 203 | return m_IsObjectValid; 204 | } 205 | 206 | PVOID 207 | GetData( 208 | ); 209 | 210 | PVOID 211 | GetData( 212 | ULONG64 FileOffset, 213 | ULONG DataSize 214 | ); 215 | 216 | ~MemoryObject() 217 | { 218 | if (!m_NoAllocationFlag) delete[] m_Data; 219 | } 220 | 221 | private: 222 | FileContext *m_FileContext = NULL; 223 | ULONG64 m_FileBaseOffset; 224 | PVOID m_Data = NULL; 225 | ULONG m_DataSize; 226 | BOOLEAN m_IsObjectValid = FALSE; 227 | BOOLEAN m_NoAllocationFlag = FALSE; 228 | }; 229 | 230 | #define XPRESS_ENCODE_MAGIC 0x19880922 231 | 232 | #define XPRESS_MAGIC "\x81\x81xpress" 233 | #define XPRESS_MAGIC_SIZE (sizeof(XPRESS_MAGIC) - 1) 234 | 235 | #define XPRESS_HEADER_SIZE 0x20 236 | 237 | #define XPRESS_ALIGNMENT 8 238 | 239 | class CompressedMemoryBlock { 240 | public: 241 | 242 | VOID 243 | Init( 244 | FileContext *FileContext, 245 | ULONG64 Offset, 246 | BOOLEAN NoAllocationFlag 247 | ); 248 | 249 | CompressedMemoryBlock( 250 | FileContext *FileContext, 251 | ULONG64 Offset 252 | ) 253 | { 254 | Init(FileContext, Offset, FALSE); 255 | } 256 | 257 | CompressedMemoryBlock( 258 | FileContext *FileContext, 259 | ULONG64 Offset, 260 | BOOLEAN NoAllocationFlag 261 | ) 262 | { 263 | Init(FileContext, Offset, NoAllocationFlag); 264 | } 265 | 266 | VOID 267 | SetCompressedBlock( 268 | PVOID CompressedData 269 | ); 270 | 271 | VOID SetCompressionSize(ULONG CompressionSize) { m_CompressedSize = CompressionSize; } 272 | BOOLEAN SetCompressionType(BOOLEAN IsCompressed) { m_IsCompressed = IsCompressed; return m_IsCompressed; } 273 | BOOLEAN IsCompressed() { return m_IsCompressed; } 274 | 275 | ULONG64 GetCompressedBlockOffset() { return m_CompressedBlockOffset; } 276 | 277 | ULONG 278 | Xpress_Decompress( 279 | PUCHAR InputBuffer, 280 | ULONG InputSize, 281 | PUCHAR OutputBuffer, 282 | ULONG OutputSize 283 | ); 284 | 285 | VOID SetContext(FileContext *FileContext) { m_FileContext = FileContext; } 286 | FileContext *GetContext() { return m_FileContext; } 287 | 288 | PVOID 289 | GetDecompressedData( 290 | ); 291 | 292 | PVOID 293 | GetDecompressedPage( 294 | ); 295 | 296 | VOID 297 | GetNextCompressedBlock( 298 | ); 299 | 300 | ULONG 301 | GetCompressedBlockSize() { return /* m_CompressedHeaderSize + */ m_CompressedSize; } 302 | 303 | ULONG 304 | GetCompressedHeaderSize() { return m_CompressedHeaderSize; } 305 | 306 | VOID 307 | DestroyUncompressedBlock( 308 | ) 309 | { 310 | if (!m_NoAllocationFlag && m_IsCompressed) delete[] m_UncompressedData; 311 | m_UncompressedData = NULL; 312 | } 313 | 314 | VOID 315 | DestroyCompressedBlock() 316 | { 317 | if (m_CompressedBlock) delete m_CompressedBlock; 318 | m_CompressedBlock = NULL; 319 | } 320 | 321 | ~CompressedMemoryBlock() 322 | { 323 | DestroyUncompressedBlock(); 324 | DestroyCompressedBlock(); 325 | } 326 | 327 | private: 328 | PUCHAR m_CompressedData = NULL; 329 | PUCHAR m_UncompressedData = NULL; 330 | ULONG m_CompressedHeaderSize = 0; 331 | ULONG m_CompressedSize = 0; 332 | ULONG m_NumberOfUncompressedPages = 0; 333 | ULONG m_MaxDataLength = 0; // 64KB + 4KB 334 | BOOLEAN m_IsCompressed = FALSE; 335 | 336 | ULONG m_UncompressedPageIndex = 0; 337 | 338 | FileContext *m_FileContext = NULL; 339 | MemoryObject *m_CompressedBlock = NULL; 340 | ULONG64 m_CompressedBlockOffset = 0; 341 | ULONG64 m_CurrentOffset = 0; 342 | 343 | BOOLEAN m_NoAllocationFlag = FALSE; 344 | }; 345 | 346 | 347 | class MemoryRangeEntry { 348 | 349 | public: 350 | MemoryRangeEntry( 351 | FileContext *FileContext, 352 | PVOID Range 353 | ) 354 | { 355 | m_FileContext = FileContext; 356 | m_MemoryRangeEntry = Range; 357 | } 358 | 359 | FileContext *GetContext() { return m_FileContext; } 360 | 361 | ULONG64 362 | GetPageCount( 363 | ); 364 | 365 | ULONG64 366 | GetStartPage( 367 | ); 368 | 369 | private: 370 | ULONG64 m_CurrentOffset = 0; 371 | PVOID m_MemoryRangeEntry = NULL; 372 | FileContext *m_FileContext; 373 | }; 374 | 375 | class MemoryRangeTable { 376 | 377 | public: 378 | MemoryRangeTable( 379 | FileContext *Context, 380 | ULONG64 RangeTable 381 | ) 382 | { 383 | m_FileContext = Context; 384 | m_CurrentOffset = RangeTable; 385 | 386 | m_MemoryRangeTable = new MemoryObject(GetContext(), m_CurrentOffset, m_MemoryRangeTableSize); 387 | } 388 | 389 | BOOLEAN IsValid() { return m_MemoryRangeTable->IsValid(); } 390 | 391 | FileContext *GetContext() { return m_FileContext; } 392 | 393 | ULONG 394 | GetRangeCount( 395 | ); 396 | 397 | ULONG 398 | GetCompressedSize( 399 | ); 400 | 401 | HIBER_COMPRESS_METHOD 402 | GetCompressMethod( 403 | ); 404 | 405 | PVOID 406 | GetRangeBase( 407 | ); 408 | 409 | BOOLEAN 410 | GetNextRangeTable( 411 | ); 412 | 413 | MemoryRangeEntry * 414 | GetRangeEntry( 415 | _In_ ULONG Index 416 | ); 417 | 418 | ULONG 419 | GetCompressedBlockIndex( 420 | _In_ ULONG RangeIndex 421 | ); 422 | 423 | ULONG 424 | GetMemoryRangeEntrySize( 425 | ); 426 | 427 | ULONG 428 | GetMemoryRangeTableSize( 429 | ); 430 | 431 | ULONG64 GetMemoryRangeTableOffset() { return m_CurrentOffset; } 432 | 433 | ULONG64 434 | GetCompressedBlockOffset( 435 | ); 436 | 437 | ~MemoryRangeTable() 438 | { 439 | delete m_MemoryRangeTable; 440 | } 441 | 442 | private: 443 | FileContext *m_FileContext; 444 | ULONG64 m_CurrentOffset = 0; 445 | MemoryObject *m_MemoryRangeTable; 446 | ULONG m_MemoryRangeTableSize = PAGE_SIZE + (PAGE_SIZE * 0x10); 447 | }; 448 | 449 | class MemoryBlock 450 | { 451 | public: 452 | MemoryBlock(PlatformType Platform, ULONG Major, ULONG Minor) 453 | { 454 | m_FileContext = new FileContext(Platform, Major, Minor); 455 | } 456 | 457 | FileContext * GetContext() { return m_FileContext; } 458 | 459 | ULONG GetSignature(); 460 | 461 | VOID 462 | SetInitialOffset(ULONG64 Offset) { m_InitialOffset = Offset; } 463 | 464 | ULONG64 465 | GetInitialOffset( 466 | ); 467 | 468 | ULONG64 469 | GetFirstKernelRestorePage( 470 | VOID 471 | ); 472 | 473 | MemoryRangeTable *GetFirstRangeTable() { return new MemoryRangeTable(GetContext(), m_InitialOffset); } 474 | 475 | MemoryNode *GetMemoryNodes() { return m_MemoryNodes; } 476 | 477 | private: 478 | ULONG64 m_InitialOffset = 0; 479 | FileContext *m_FileContext = NULL; 480 | MemoryNode *m_MemoryNodes = new MemoryNode(NULL, NULL); 481 | }; 482 | #endif -------------------------------------------------------------------------------- /Hibr2Bin/Hibr2Bin.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | ARM64 7 | 8 | 9 | Debug 10 | Win32 11 | 12 | 13 | Release 14 | ARM64 15 | 16 | 17 | Release 18 | Win32 19 | 20 | 21 | Debug 22 | x64 23 | 24 | 25 | Release 26 | x64 27 | 28 | 29 | 30 | {3B1F31A6-91FD-4946-AA9C-B93592E57F70} 31 | Hibr2Bin 32 | 10.0 33 | 34 | 35 | 36 | Application 37 | true 38 | v142 39 | MultiByte 40 | 41 | 42 | Application 43 | false 44 | v142 45 | true 46 | MultiByte 47 | 48 | 49 | Application 50 | true 51 | v142 52 | MultiByte 53 | 54 | 55 | Application 56 | true 57 | v142 58 | MultiByte 59 | 60 | 61 | Application 62 | false 63 | v142 64 | true 65 | MultiByte 66 | 67 | 68 | Application 69 | false 70 | v142 71 | true 72 | MultiByte 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | $(SolutionDir)$(Configuration)\$(PlatformTarget)\ 100 | $(Configuration)\$(PlatformTarget)\ 101 | 102 | 103 | $(SolutionDir)$(Configuration)\$(PlatformTarget)\ 104 | $(Configuration)\$(PlatformTarget)\ 105 | false 106 | 107 | 108 | $(SolutionDir)$(Configuration)\$(PlatformTarget)\ 109 | $(Configuration)\$(PlatformTarget)\ 110 | 111 | 112 | false 113 | $(SolutionDir)$(Configuration)\$(PlatformTarget)\ 114 | $(Configuration)\$(PlatformTarget)\ 115 | 116 | 117 | false 118 | $(SolutionDir)$(Configuration)\$(Platform)\ 119 | $(Configuration)\$(Platform)\ 120 | 121 | 122 | $(SolutionDir)$(Configuration)\$(Platform)\ 123 | $(Configuration)\$(Platform)\ 124 | 125 | 126 | 127 | Level3 128 | Disabled 129 | true 130 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 131 | Use 132 | precomp.h 133 | 134 | 135 | 136 | 137 | Console 138 | true 139 | 140 | 141 | 142 | 143 | Level3 144 | Disabled 145 | true 146 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 147 | Use 148 | precomp.h 149 | 150 | 151 | 152 | 153 | true 154 | Console 155 | 156 | 157 | 158 | 159 | Level3 160 | Disabled 161 | true 162 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 163 | Use 164 | precomp.h 165 | 166 | 167 | 168 | true 169 | Console 170 | 171 | 172 | 173 | 174 | Level3 175 | true 176 | true 177 | true 178 | MultiThreaded 179 | Use 180 | precomp.h 181 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 182 | Guard 183 | /Qspectre 184 | 185 | 186 | true 187 | true 188 | /PDBALTPATH:%_PDB% %(AdditionalOptions) 189 | Console 190 | true 191 | 192 | 193 | 194 | 195 | 196 | 197 | Level3 198 | true 199 | true 200 | true 201 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 202 | Use 203 | precomp.h 204 | MultiThreaded 205 | Guard 206 | /Qspectre 207 | 208 | 209 | true 210 | true 211 | /PDBALTPATH:%_PDB% %(AdditionalOptions) 212 | Console 213 | true 214 | 215 | 216 | 217 | 218 | 219 | 220 | Level3 221 | true 222 | true 223 | true 224 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 225 | Use 226 | precomp.h 227 | MultiThreaded 228 | Guard 229 | /Qspectre 230 | 231 | 232 | true 233 | true 234 | /PDBALTPATH:%_PDB% %(AdditionalOptions) 235 | Console 236 | true 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | Create 249 | Create 250 | Create 251 | Create 252 | Create 253 | Create 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | -------------------------------------------------------------------------------- /Hibr2Bin/MemoryBlocks.cpp: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) 2007 - 2017, Matthieu Suiche 4 | Copyright (c) 2012 - 2014, MoonSols Limited 5 | Copyright (c) Comae Technologies DMCC. All rights reserved. 6 | 7 | Module Name: 8 | 9 | MemoryBlocks.cpp 10 | 11 | Abstract: 12 | 13 | This module contains the internal structure definitions and APIs used by 14 | the Hibr2Bin. 15 | 16 | Author: 17 | 18 | Matthieu Suiche (m) 1-April-2016 19 | 20 | Revision History: 21 | 22 | --*/ 23 | 24 | #include "precomp.h" 25 | 26 | // 27 | // MemoryObject 28 | // 29 | VOID 30 | MemoryObject::Init(FileContext *FileContext, ULONG64 FileOffset, ULONG DataSize, BOOLEAN NoAllocationFlag) 31 | { 32 | m_NoAllocationFlag = NoAllocationFlag; 33 | m_Data = FileContext->ReadFile(FileOffset, DataSize, NoAllocationFlag ? NULL : &m_Data); 34 | 35 | m_IsObjectValid = !!(m_Data); 36 | if (IsValid()) 37 | { 38 | m_FileContext = FileContext; 39 | m_FileBaseOffset = FileOffset; 40 | m_DataSize = DataSize; 41 | } 42 | } 43 | 44 | PVOID 45 | MemoryObject::GetData( 46 | ) 47 | { 48 | if (!IsValid()) return NULL; 49 | 50 | return m_Data; 51 | } 52 | 53 | PVOID 54 | MemoryObject::GetData( 55 | ULONG64 FileOffset, 56 | ULONG DataSize 57 | ) 58 | { 59 | PVOID Data = NULL; 60 | 61 | // 62 | // Within range. 63 | // 64 | if ((FileOffset >= m_FileBaseOffset) && ((FileOffset + DataSize) <= (m_FileBaseOffset + m_DataSize))) 65 | { 66 | ULONG64 Offset = FileOffset - m_FileBaseOffset; 67 | Data = (((PUCHAR)m_Data) + (ULONG)Offset); 68 | } 69 | 70 | return Data; 71 | } 72 | 73 | // 74 | // MemoryRangeTable 75 | // 76 | 77 | ULONG 78 | MemoryRangeTable::GetRangeCount( 79 | ) 80 | { 81 | ULONG RangeCount = 0; 82 | 83 | switch (GetContext()->GetPlatform()) 84 | { 85 | case PlatformX86: 86 | if (GetContext()->IsWin8AndAbove()) 87 | RangeCount = ((PPO_MEMORY_RANGE_TABLE32_NT62)m_MemoryRangeTable->GetData())->RangeCount; 88 | else if (GetContext()->IsWin7()) 89 | RangeCount = ((PPO_MEMORY_RANGE_ARRAY32_NT61)m_MemoryRangeTable->GetData())->Link.EntryCount; 90 | else if (GetContext()->IsWinVista() || GetContext()->IsWinXP()) 91 | RangeCount = ((PPO_MEMORY_RANGE_ARRAY_LINK32)m_MemoryRangeTable->GetData())->EntryCount; 92 | else 93 | { 94 | throw; 95 | } 96 | break; 97 | case PlatformX64: 98 | if (GetContext()->IsWin8AndAbove()) 99 | RangeCount = ((PPO_MEMORY_RANGE_TABLE64_NT62)m_MemoryRangeTable->GetData())->RangeCount; 100 | else if (GetContext()->IsWin7()) 101 | RangeCount = ((PPO_MEMORY_RANGE_ARRAY64_NT61)m_MemoryRangeTable->GetData())->Link.EntryCount; 102 | else if (GetContext()->IsWinVista()) 103 | RangeCount = ((PPO_MEMORY_RANGE_ARRAY_LINK64)m_MemoryRangeTable->GetData())->EntryCount; 104 | else if (GetContext()->IsWinXP64()) 105 | RangeCount = ((PPO_MEMORY_RANGE_ARRAY_LINK64_NT52)m_MemoryRangeTable->GetData())->EntryCount; 106 | else 107 | { 108 | throw; 109 | } 110 | break; 111 | } 112 | 113 | return RangeCount; 114 | } 115 | 116 | ULONG 117 | MemoryRangeTable::GetCompressedSize( 118 | ) 119 | { 120 | ULONG CompressedSize = 0; 121 | 122 | switch (GetContext()->GetPlatform()) 123 | { 124 | case PlatformX86: 125 | if (GetContext()->IsWin8AndAbove()) 126 | CompressedSize = ((PPO_MEMORY_RANGE_TABLE32_NT62)m_MemoryRangeTable->GetData())->CompressedSize; 127 | else 128 | { 129 | // assert(0); 130 | //throw; 131 | } 132 | break; 133 | case PlatformX64: 134 | if (GetContext()->IsWin8AndAbove()) 135 | CompressedSize = ((PPO_MEMORY_RANGE_TABLE64_NT62)m_MemoryRangeTable->GetData())->CompressedSize; 136 | else 137 | { 138 | // assert(0); 139 | // throw; 140 | } 141 | break; 142 | } 143 | 144 | return CompressedSize; 145 | } 146 | 147 | HIBER_COMPRESS_METHOD 148 | MemoryRangeTable::GetCompressMethod( 149 | ) 150 | { 151 | ULONG CompressMethod = 0; 152 | 153 | switch (GetContext()->GetPlatform()) 154 | { 155 | case PlatformX86: 156 | if (GetContext()->IsWin8AndAbove()) 157 | CompressMethod = ((PPO_MEMORY_RANGE_TABLE64_NT62)m_MemoryRangeTable->GetData())->CompressMethod; 158 | else 159 | { 160 | assert(0); 161 | throw; 162 | } 163 | break; 164 | case PlatformX64: 165 | if (GetContext()->IsWin8AndAbove()) 166 | CompressMethod = ((PPO_MEMORY_RANGE_TABLE64_NT62)m_MemoryRangeTable->GetData())->CompressMethod; 167 | else 168 | { 169 | assert(0); 170 | throw; 171 | } 172 | break; 173 | } 174 | 175 | return (HIBER_COMPRESS_METHOD)CompressMethod; 176 | } 177 | 178 | PVOID 179 | MemoryRangeTable::GetRangeBase( 180 | ) 181 | { 182 | PVOID RangeBase = 0; 183 | 184 | switch (GetContext()->GetPlatform()) 185 | { 186 | case PlatformX86: 187 | if (GetContext()->IsWin8AndAbove()) 188 | RangeBase = ((PPO_MEMORY_RANGE_TABLE32_NT62)m_MemoryRangeTable->GetData())->Range; 189 | else if (GetContext()->IsWin7()) 190 | RangeBase = ((PPO_MEMORY_RANGE_ARRAY32_NT61)m_MemoryRangeTable->GetData())->Range; 191 | else if (GetContext()->IsWinVista()) 192 | RangeBase = ((PPO_MEMORY_RANGE_ARRAY32)m_MemoryRangeTable->GetData())->Range; 193 | else if (GetContext()->IsWinXP()) 194 | RangeBase = ((PPO_MEMORY_RANGE_ARRAY32)m_MemoryRangeTable->GetData())->Range; 195 | break; 196 | case PlatformX64: 197 | if (GetContext()->IsWin8AndAbove()) 198 | RangeBase = ((PPO_MEMORY_RANGE_TABLE64_NT62)m_MemoryRangeTable->GetData())->Range; 199 | else if (GetContext()->IsWin7()) 200 | RangeBase = ((PPO_MEMORY_RANGE_ARRAY64_NT61)m_MemoryRangeTable->GetData())->Range; 201 | else if (GetContext()->IsWinVista()) 202 | RangeBase = ((PPO_MEMORY_RANGE_ARRAY64)m_MemoryRangeTable->GetData())->Range; 203 | else if (GetContext()->IsWinXP64()) 204 | RangeBase = ((PPO_MEMORY_RANGE_ARRAY64_NT52)m_MemoryRangeTable->GetData())->Range; 205 | break; 206 | } 207 | 208 | return RangeBase; 209 | } 210 | 211 | ULONG 212 | MemoryRangeTable::GetMemoryRangeTableSize() 213 | { 214 | ULONG SizeOfMemoryRangeTable = 0; 215 | 216 | switch (GetContext()->GetPlatform()) 217 | { 218 | case PlatformX86: 219 | if (GetContext()->IsWin8AndAbove()) 220 | { 221 | SizeOfMemoryRangeTable = sizeof(PO_MEMORY_RANGE_TABLE32_NT62); 222 | } 223 | else if (GetContext()->IsWin7()) 224 | { 225 | SizeOfMemoryRangeTable = sizeof(PO_MEMORY_RANGE_ARRAY32_NT61); 226 | } 227 | else if (GetContext()->IsWinVista() || GetContext()->IsWinXP()) 228 | { 229 | SizeOfMemoryRangeTable = sizeof(PO_MEMORY_RANGE_ARRAY32); 230 | } 231 | break; 232 | 233 | case PlatformX64: 234 | if (GetContext()->IsWin8AndAbove()) 235 | { 236 | SizeOfMemoryRangeTable = sizeof(PO_MEMORY_RANGE_TABLE64_NT62); 237 | } 238 | else if (GetContext()->IsWin7()) 239 | { 240 | SizeOfMemoryRangeTable = sizeof(PO_MEMORY_RANGE_ARRAY64_NT61); 241 | } 242 | else if (GetContext()->IsWinVista()) 243 | { 244 | SizeOfMemoryRangeTable = sizeof(PO_MEMORY_RANGE_ARRAY64); 245 | } 246 | else if (GetContext()->IsWinXP64()) 247 | { 248 | SizeOfMemoryRangeTable = sizeof(PO_MEMORY_RANGE_ARRAY64_NT52); 249 | } 250 | break; 251 | } 252 | return SizeOfMemoryRangeTable; 253 | } 254 | 255 | BOOLEAN 256 | MemoryRangeTable::GetNextRangeTable( 257 | ) 258 | { 259 | ULONG64 NextRangeTable; 260 | ULONG64 NextTableOffset = 0; 261 | 262 | NextRangeTable = m_CurrentOffset; 263 | ULONG SizeOfMemoryRangeTable = 0; 264 | ULONG SizeOfMemoryRange = 0; 265 | 266 | switch (GetContext()->GetPlatform()) 267 | { 268 | case PlatformX86: 269 | if (GetContext()->IsWin7()) 270 | { 271 | NextTableOffset = ((PPO_MEMORY_RANGE_ARRAY32_NT61)m_MemoryRangeTable->GetData())->Link.NextTable; 272 | 273 | if (NextTableOffset == NULL) return FALSE; 274 | NextTableOffset *= PAGE_SIZE; 275 | } 276 | else if (GetContext()->IsWinVista() || GetContext()->IsWinXP()) 277 | { 278 | SizeOfMemoryRangeTable = sizeof(PO_MEMORY_RANGE_ARRAY32); 279 | 280 | NextTableOffset = ((PPO_MEMORY_RANGE_ARRAY32)m_MemoryRangeTable->GetData())->Link.NextTable; 281 | 282 | if (NextTableOffset == NULL) return FALSE; 283 | NextTableOffset *= PAGE_SIZE; 284 | } 285 | break; 286 | case PlatformX64: 287 | if (GetContext()->IsWin7()) 288 | { 289 | NextTableOffset = ((PPO_MEMORY_RANGE_ARRAY32_NT61)m_MemoryRangeTable->GetData())->Link.NextTable; 290 | 291 | if (NextTableOffset == NULL) return FALSE; 292 | NextTableOffset *= PAGE_SIZE; 293 | } 294 | else if (GetContext()->IsWinVista()) 295 | { 296 | NextTableOffset = ((PPO_MEMORY_RANGE_ARRAY64)m_MemoryRangeTable->GetData())->Link.NextTable; 297 | 298 | if (NextTableOffset == NULL) return FALSE; 299 | NextTableOffset *= PAGE_SIZE; 300 | } 301 | else if (GetContext()->IsWinXP64()) 302 | { 303 | NextTableOffset = ((PPO_MEMORY_RANGE_ARRAY64_NT52)m_MemoryRangeTable->GetData())->Link.NextTable; 304 | 305 | if (NextTableOffset == NULL) return FALSE; 306 | NextTableOffset *= PAGE_SIZE; 307 | } 308 | break; 309 | default: 310 | wprintf(L" Error: Platform non defined.\n"); 311 | break; 312 | } 313 | 314 | // DbgPrint(L"GetRangeCount() = 0x%x\n", GetRangeCount()); 315 | // m_MemoryRangeTableSize = PAGE_SIZE; 316 | 317 | if (NextTableOffset == 0) 318 | { 319 | // 320 | // Windows NT 6.2+ 321 | // 322 | NextRangeTable += GetMemoryRangeTableSize(); 323 | NextRangeTable += ((GetRangeCount() - 1)* GetMemoryRangeEntrySize()); 324 | NextRangeTable += GetCompressedSize(); 325 | 326 | m_CurrentOffset = NextRangeTable; 327 | } 328 | else 329 | { 330 | // 331 | // This means we are already on the last table. 332 | // 333 | ULONG RangeCount = GetRangeCount(); 334 | 335 | if (!((RangeCount == 0xFF) || (RangeCount == 0x7F) || 336 | (RangeCount == 0x1FF) || (RangeCount == 0xFE))) return FALSE; 337 | 338 | m_CurrentOffset = NextTableOffset; 339 | } 340 | 341 | delete m_MemoryRangeTable; 342 | m_MemoryRangeTable = new MemoryObject(GetContext(), m_CurrentOffset, m_MemoryRangeTableSize); 343 | 344 | if (m_MemoryRangeTable->IsValid()) 345 | { 346 | ULONG RangeCount = GetRangeCount(); 347 | if (GetContext()->IsWin8AndAbove()) 348 | { 349 | if ((RangeCount > MAX_HIBER_PAGES) || (RangeCount == 0)) 350 | { 351 | return FALSE; 352 | } 353 | } 354 | } 355 | 356 | return m_MemoryRangeTable->IsValid(); 357 | } 358 | 359 | ULONG 360 | MemoryRangeTable::GetMemoryRangeEntrySize() 361 | { 362 | switch (GetContext()->GetPlatform()) 363 | { 364 | case PlatformX86: 365 | if (GetContext()->IsWin10()) return sizeof(PO_MEMORY_RANGE32_NT62); 366 | else if (GetContext()->IsWin81()) return sizeof(PO_MEMORY_RANGE32_NT62); 367 | else if (GetContext()->IsWin8()) return sizeof(PO_MEMORY_RANGE32_NT62); 368 | else if (GetContext()->IsWin7()) return sizeof(PO_MEMORY_RANGE_ARRAY_RANGE32_NT61); 369 | else if (GetContext()->IsWinVista() || GetContext()->IsWinXP()) 370 | { 371 | return sizeof(PO_MEMORY_RANGE_ARRAY_RANGE32); 372 | } 373 | break; 374 | 375 | case PlatformX64: 376 | if (GetContext()->IsWin10()) return sizeof(PO_MEMORY_RANGE64_NT62); 377 | else if (GetContext()->IsWin81()) return sizeof(PO_MEMORY_RANGE64_NT62); 378 | else if (GetContext()->IsWin8()) return sizeof(PO_MEMORY_RANGE64_NT62); 379 | else if (GetContext()->IsWin7()) return sizeof(PO_MEMORY_RANGE_ARRAY_RANGE64_NT61); 380 | else if (GetContext()->IsWinVista()) return sizeof(PO_MEMORY_RANGE_ARRAY_RANGE64); 381 | else if (GetContext()->IsWinXP64()) return sizeof(PO_MEMORY_RANGE_ARRAY_RANGE64_NT52); 382 | break; 383 | } 384 | 385 | return 0; 386 | } 387 | 388 | MemoryRangeEntry * 389 | MemoryRangeTable::GetRangeEntry( 390 | _In_ ULONG Index 391 | ) 392 | { 393 | return new MemoryRangeEntry(GetContext(), ((PUCHAR)GetRangeBase()) + (Index * GetMemoryRangeEntrySize())); 394 | } 395 | 396 | ULONG 397 | MemoryRangeTable::GetCompressedBlockIndex( 398 | _In_ ULONG RangeIndex 399 | ) 400 | { 401 | ULONG CompressedPagesCount = 0; 402 | 403 | if (RangeIndex > 0x1FF) return 0; 404 | 405 | for (ULONG i = 0; i < RangeIndex; i++) 406 | { 407 | MemoryRangeEntry *Entry = GetRangeEntry(i); 408 | CompressedPagesCount += (ULONG)Entry->GetPageCount(); 409 | delete Entry; 410 | } 411 | 412 | return CompressedPagesCount; 413 | } 414 | 415 | ULONG64 416 | MemoryRangeTable::GetCompressedBlockOffset( 417 | ) 418 | { 419 | if (GetContext()->IsWin8AndAbove()) 420 | { 421 | return GetMemoryRangeTableOffset() + GetMemoryRangeTableSize() + (GetRangeCount() - 1) * GetMemoryRangeEntrySize(); 422 | } 423 | 424 | return GetMemoryRangeTableOffset() + PAGE_SIZE; 425 | } 426 | 427 | // 428 | // Memory Range Entries (MemoryRangeEntry) 429 | // 430 | 431 | ULONG64 432 | MemoryRangeEntry::GetPageCount( 433 | ) 434 | { 435 | ULONG64 PageCount = 0; 436 | 437 | switch (GetContext()->GetPlatform()) 438 | { 439 | case PlatformX86: 440 | if (GetContext()->IsWin10()) 441 | PageCount = ((PPO_MEMORY_RANGE32_NT62)m_MemoryRangeEntry)->PageCount + 1; 442 | else if (GetContext()->IsWin81()) 443 | PageCount = ((PPO_MEMORY_RANGE32_NT62)m_MemoryRangeEntry)->PageCount + 1; 444 | else if (GetContext()->IsWin8()) 445 | PageCount = ((PPO_MEMORY_RANGE32_NT62)m_MemoryRangeEntry)->PageCount + 1; 446 | else if (GetContext()->IsWin7()) 447 | { 448 | ULONG StartPage, EndPage; 449 | StartPage = ((PPO_MEMORY_RANGE_ARRAY_RANGE32_NT61)m_MemoryRangeEntry)->StartPage; 450 | EndPage = ((PPO_MEMORY_RANGE_ARRAY_RANGE32_NT61)m_MemoryRangeEntry)->EndPage; 451 | PageCount = EndPage - StartPage; 452 | } 453 | else if (GetContext()->IsWinVista() || GetContext()->IsWinXP()) 454 | { 455 | ULONG StartPage, EndPage; 456 | StartPage = ((PPO_MEMORY_RANGE_ARRAY_RANGE32)m_MemoryRangeEntry)->StartPage; 457 | EndPage = ((PPO_MEMORY_RANGE_ARRAY_RANGE32)m_MemoryRangeEntry)->EndPage; 458 | PageCount = EndPage - StartPage; 459 | } 460 | break; 461 | case PlatformX64: 462 | if (GetContext()->IsWin10()) 463 | PageCount = ((PPO_MEMORY_RANGE64_NT62)m_MemoryRangeEntry)->PageCount + 1; 464 | else if (GetContext()->IsWin81()) 465 | PageCount = ((PPO_MEMORY_RANGE64_NT62)m_MemoryRangeEntry)->PageCount + 1; 466 | else if (GetContext()->IsWin8()) 467 | PageCount = ((PPO_MEMORY_RANGE64_NT62)m_MemoryRangeEntry)->PageCount + 1; 468 | else if (GetContext()->IsWin7()) 469 | { 470 | ULONG64 StartPage, EndPage; 471 | StartPage = ((PPO_MEMORY_RANGE_ARRAY_RANGE64_NT61)m_MemoryRangeEntry)->StartPage; 472 | EndPage = ((PPO_MEMORY_RANGE_ARRAY_RANGE64_NT61)m_MemoryRangeEntry)->EndPage; 473 | PageCount = EndPage - StartPage; 474 | } 475 | else if (GetContext()->IsWinVista()) 476 | { 477 | ULONG64 StartPage, EndPage; 478 | StartPage = ((PPO_MEMORY_RANGE_ARRAY_RANGE64)m_MemoryRangeEntry)->StartPage; 479 | EndPage = ((PPO_MEMORY_RANGE_ARRAY_RANGE64)m_MemoryRangeEntry)->EndPage; 480 | PageCount = EndPage - StartPage; 481 | } 482 | else if (GetContext()->IsWinXP64()) 483 | { 484 | ULONG64 StartPage, EndPage; 485 | StartPage = ((PPO_MEMORY_RANGE_ARRAY_RANGE64_NT52)m_MemoryRangeEntry)->StartPage; 486 | EndPage = ((PPO_MEMORY_RANGE_ARRAY_RANGE64_NT52)m_MemoryRangeEntry)->EndPage; 487 | PageCount = EndPage - StartPage; 488 | } 489 | break; 490 | } 491 | 492 | return PageCount; 493 | } 494 | 495 | ULONG64 496 | MemoryRangeEntry::GetStartPage( 497 | ) 498 | { 499 | ULONG64 StartPage = 0; 500 | 501 | switch (GetContext()->GetPlatform()) 502 | { 503 | case PlatformX86: 504 | if (GetContext()->IsWin10()) 505 | StartPage = ((PPO_MEMORY_RANGE32_NT62)m_MemoryRangeEntry)->StartPage; 506 | else if (GetContext()->IsWin81()) 507 | StartPage = ((PPO_MEMORY_RANGE32_NT62)m_MemoryRangeEntry)->StartPage; 508 | else if (GetContext()->IsWin8()) 509 | StartPage = ((PPO_MEMORY_RANGE32_NT62)m_MemoryRangeEntry)->StartPage; 510 | else if (GetContext()->IsWin7()) 511 | StartPage = ((PPO_MEMORY_RANGE_ARRAY_RANGE32_NT61)m_MemoryRangeEntry)->StartPage; 512 | else if (GetContext()->IsWinXP() || GetContext()->IsWinVista()) 513 | StartPage = ((PPO_MEMORY_RANGE_ARRAY_RANGE32)m_MemoryRangeEntry)->StartPage; 514 | break; 515 | case PlatformX64: 516 | if (GetContext()->IsWin10()) 517 | StartPage = ((PPO_MEMORY_RANGE64_NT62)m_MemoryRangeEntry)->StartPage; 518 | else if (GetContext()->IsWin81()) 519 | StartPage = ((PPO_MEMORY_RANGE64_NT62)m_MemoryRangeEntry)->StartPage; 520 | else if (GetContext()->IsWin8()) 521 | StartPage = ((PPO_MEMORY_RANGE64_NT62)m_MemoryRangeEntry)->StartPage; 522 | else if (GetContext()->IsWin7()) 523 | StartPage = ((PPO_MEMORY_RANGE_ARRAY_RANGE64_NT61)m_MemoryRangeEntry)->StartPage; 524 | else if (GetContext()->IsWinVista()) 525 | StartPage = ((PPO_MEMORY_RANGE_ARRAY_RANGE64)m_MemoryRangeEntry)->StartPage; 526 | else if (GetContext()->IsWinXP64()) 527 | StartPage = ((PPO_MEMORY_RANGE_ARRAY_RANGE64_NT52)m_MemoryRangeEntry)->StartPage; 528 | break; 529 | } 530 | 531 | return StartPage; 532 | } 533 | 534 | // 535 | // CompressedMemoryBlock 536 | // 537 | 538 | VOID 539 | CompressedMemoryBlock::Init( 540 | FileContext *FileContext, 541 | ULONG64 Offset, 542 | BOOLEAN NoAllocationFlag 543 | ) 544 | { 545 | m_FileContext = FileContext; 546 | m_CurrentOffset = Offset; 547 | m_CompressedBlockOffset = m_CurrentOffset; 548 | 549 | m_MaxDataLength = PAGE_SIZE; 550 | m_NoAllocationFlag = NoAllocationFlag; 551 | m_CompressedBlock = new MemoryObject(GetContext(), m_CurrentOffset, m_MaxDataLength, m_NoAllocationFlag); 552 | 553 | SetCompressedBlock(m_CompressedBlock->GetData()); 554 | } 555 | 556 | VOID 557 | CompressedMemoryBlock::SetCompressedBlock( 558 | PVOID CompressedData 559 | ) 560 | { 561 | m_CompressedData = (PUCHAR)CompressedData; 562 | 563 | assert(m_CompressedData); 564 | 565 | if (memcmp(m_CompressedData, XPRESS_MAGIC, XPRESS_MAGIC_SIZE) == 0) 566 | { 567 | // Old version (XPRESS tag present) 568 | 569 | UCHAR xprs[XPRESS_HEADER_SIZE]; 570 | ULONG Info; 571 | 572 | RtlCopyMemory(xprs, m_CompressedData, XPRESS_HEADER_SIZE); 573 | m_CompressedHeaderSize = XPRESS_HEADER_SIZE; 574 | m_CompressedData += m_CompressedHeaderSize; 575 | 576 | Info = xprs[XPRESS_MAGIC_SIZE + 0]; 577 | Info |= (xprs[XPRESS_MAGIC_SIZE + 1]) << 8; 578 | Info |= (xprs[XPRESS_MAGIC_SIZE + 2]) << 16; 579 | Info |= (xprs[XPRESS_MAGIC_SIZE + 3]) << 24; 580 | 581 | m_CompressedSize = ((Info >> 10) + 1); 582 | m_CompressedSize = (m_CompressedSize + (XPRESS_ALIGNMENT - 1)) & ~(XPRESS_ALIGNMENT - 1); 583 | m_NumberOfUncompressedPages = ((Info & 0x3ff) + 1); 584 | 585 | m_IsCompressed = !((m_CompressedSize == (m_NumberOfUncompressedPages * PAGE_SIZE))); 586 | } 587 | else 588 | { 589 | m_IsCompressed = TRUE; 590 | } 591 | } 592 | 593 | PVOID 594 | CompressedMemoryBlock::GetDecompressedPage( 595 | ) 596 | { 597 | if ((m_UncompressedPageIndex % 0x10) == 0) GetNextCompressedBlock(); 598 | if (m_UncompressedData == NULL) GetDecompressedData(); 599 | 600 | PUCHAR Page = (PUCHAR)m_UncompressedData + (m_UncompressedPageIndex * PAGE_SIZE); 601 | m_UncompressedPageIndex += 1; 602 | 603 | return Page; 604 | } 605 | 606 | PVOID 607 | CompressedMemoryBlock::GetDecompressedData( 608 | ) 609 | /*++ 610 | - Expected to return 0x10000 (64KB) 611 | --*/ 612 | { 613 | ULONG UncompressedBytes; 614 | 615 | m_MaxDataLength = MAX_COMPRESSED_BLOCK_SIZE; 616 | delete m_CompressedBlock; 617 | m_CompressedBlock = new MemoryObject(GetContext(), m_CurrentOffset, m_MaxDataLength, TRUE); 618 | m_CompressedData = (PUCHAR)m_CompressedBlock->GetData(); 619 | m_CompressedData += m_CompressedHeaderSize; 620 | 621 | m_UncompressedPageIndex = 0; 622 | 623 | if ((!m_IsCompressed) || (m_CompressedSize == (PAGE_SIZE * 0x10))) 624 | { 625 | m_UncompressedData = m_CompressedData; 626 | return m_UncompressedData; 627 | } 628 | 629 | assert(m_CompressedSize != (PAGE_SIZE * 0x10)); 630 | 631 | m_UncompressedData = (PUCHAR)GetContext()->GetTempBuffer(); 632 | UncompressedBytes = Xpress_Decompress(m_CompressedData, m_CompressedSize, m_UncompressedData, 0x10 * PAGE_SIZE); 633 | // assert(UncompressedBytes == (m_NumberOfUncompressedPages * PAGE_SIZE)); 634 | // assert(UncompressedBytes == 0x10 * PAGE_SIZE); 635 | 636 | return m_UncompressedData; 637 | } 638 | 639 | VOID 640 | CompressedMemoryBlock::GetNextCompressedBlock( 641 | ) 642 | { 643 | DestroyUncompressedBlock(); 644 | DestroyCompressedBlock(); 645 | 646 | m_CurrentOffset = m_CurrentOffset + m_CompressedHeaderSize + GetCompressedBlockSize(); 647 | m_CompressedBlockOffset = m_CurrentOffset; 648 | m_MaxDataLength = PAGE_SIZE; 649 | m_CompressedBlock = new MemoryObject(GetContext(), m_CurrentOffset, m_MaxDataLength, m_NoAllocationFlag); 650 | 651 | SetCompressedBlock(m_CompressedBlock->GetData()); 652 | } 653 | 654 | ULONG 655 | CompressedMemoryBlock::Xpress_Decompress( 656 | PUCHAR InputBuffer, 657 | ULONG InputSize, 658 | PUCHAR OutputBuffer, 659 | ULONG OutputSize 660 | ) 661 | /*++ 662 | 663 | Routine Description: 664 | 665 | Desc. 666 | 667 | Arguments: 668 | 669 | Arg1 - Desc. 670 | 671 | Arg2 - Desc. 672 | 673 | Arg3 - Desc. 674 | 675 | Return Value: 676 | 677 | Ret1 - Desc. 678 | 679 | Ret2 - Desc. 680 | 681 | --*/ 682 | { 683 | ULONG OutputIndex, InputIndex; 684 | ULONG Indicator, IndicatorBit; 685 | ULONG Length; 686 | ULONG Offset; 687 | ULONG NibbleIndex; 688 | ULONG NibbleIndicator; 689 | 690 | Indicator = 0; 691 | IndicatorBit = 0; 692 | Length = 0; 693 | Offset = 0; 694 | NibbleIndex = 0; 695 | 696 | NibbleIndicator = XPRESS_ENCODE_MAGIC; 697 | 698 | for (OutputIndex = 0, InputIndex = 0; 699 | (OutputIndex < OutputSize) && (InputIndex < InputSize); 700 | ) 701 | { 702 | 703 | if (IndicatorBit == 0) 704 | { 705 | Indicator = (InputBuffer[InputIndex + 3] << 24); 706 | Indicator |= (InputBuffer[InputIndex + 2] << 16); 707 | Indicator |= (InputBuffer[InputIndex + 1] << 8); 708 | Indicator |= InputBuffer[InputIndex]; 709 | 710 | InputIndex += sizeof(ULONG); 711 | 712 | IndicatorBit = 32; 713 | } 714 | 715 | IndicatorBit--; 716 | 717 | // 718 | // Check whether the bit specified by IndicatorBit is set or not 719 | // set in Indicator. For example, if IndicatorBit has value 4 720 | // check whether the 4th bit of the value in Indicator is set. 721 | // 722 | 723 | if (((Indicator >> IndicatorBit) & 1) == 0) 724 | { 725 | if (InputIndex >= InputSize) break; 726 | OutputBuffer[OutputIndex] = InputBuffer[InputIndex]; 727 | 728 | InputIndex += sizeof(UCHAR); 729 | OutputIndex += sizeof(UCHAR); 730 | } 731 | else 732 | { 733 | if ((InputIndex + 1) >= InputSize) break; 734 | Length = (InputBuffer[InputIndex + 1] << 8); 735 | Length |= InputBuffer[InputIndex]; 736 | 737 | InputIndex += sizeof(USHORT); 738 | 739 | Offset = Length / 8; 740 | Length = Length % 8; 741 | 742 | if (Length == 7) 743 | { 744 | if (NibbleIndex == 0) 745 | { 746 | NibbleIndex = InputIndex; 747 | 748 | if (InputIndex >= InputSize) break; 749 | Length = InputBuffer[InputIndex] % 16; 750 | 751 | InputIndex += sizeof(UCHAR); 752 | } 753 | else 754 | { 755 | if (NibbleIndex >= InputSize) break; 756 | Length = InputBuffer[NibbleIndex] / 16; 757 | NibbleIndex = 0; 758 | } 759 | 760 | if (Length == 15) 761 | { 762 | if (InputIndex >= InputSize) break; 763 | Length = InputBuffer[InputIndex]; 764 | 765 | InputIndex += sizeof(UCHAR); 766 | 767 | if (Length == 255) 768 | { 769 | if ((InputIndex + 1) >= InputSize) break; 770 | Length = (InputBuffer[InputIndex + 1] << 8); 771 | Length |= InputBuffer[InputIndex]; 772 | 773 | InputIndex += sizeof(USHORT); 774 | 775 | Length -= (15 + 7); 776 | } 777 | Length += 15; 778 | } 779 | Length += 7; 780 | } 781 | 782 | Length += 3; 783 | 784 | while (Length != 0) 785 | { 786 | if ((OutputIndex >= OutputSize) || ((Offset + 1) > OutputIndex)) break; 787 | 788 | OutputBuffer[OutputIndex] = OutputBuffer[OutputIndex - Offset - 1]; 789 | 790 | OutputIndex += sizeof(UCHAR); 791 | Length -= sizeof(UCHAR); 792 | } 793 | } 794 | } 795 | 796 | return OutputIndex; 797 | } 798 | 799 | // 800 | // MemoryBlock 801 | // 802 | ULONG 803 | MemoryBlock::GetSignature( 804 | ) 805 | { 806 | ULONG Signature = 0; 807 | PVOID pSignature = &Signature; 808 | PVOID Data = NULL; 809 | 810 | Data = GetContext()->ReadFile(0, sizeof(Signature), &pSignature); 811 | assert(pSignature == Data); 812 | 813 | return Signature; 814 | } 815 | 816 | ULONG64 817 | MemoryBlock::GetFirstKernelRestorePage( 818 | VOID 819 | ) 820 | { 821 | BYTE Header[PAGE_SIZE]; 822 | PVOID HeaderPointer = &Header; 823 | ULONG64 FirstKernelRestorePage = NULL; 824 | 825 | GetContext()->ReadFile(0, sizeof(Header), &HeaderPointer); 826 | 827 | if (GetContext()->IsWin8AndAbove()) { 828 | 829 | switch (GetContext()->GetPlatform()) { 830 | 831 | case PlatformX86: 832 | { 833 | FirstKernelRestorePage = *(PULONG)&Header[0x54]; 834 | 835 | break; 836 | } 837 | case PlatformX64: 838 | { 839 | if (GetContext()->IsWin10()) { 840 | 841 | FirstKernelRestorePage = *(PULONG64)&Header[0x70]; 842 | } 843 | else { 844 | 845 | FirstKernelRestorePage = *(PULONG64)&Header[0x68]; 846 | } 847 | 848 | break; 849 | } 850 | } 851 | 852 | return FirstKernelRestorePage * PAGE_SIZE; 853 | } 854 | 855 | return NULL; 856 | } 857 | 858 | ULONG64 859 | MemoryBlock::GetInitialOffset( 860 | ) 861 | { 862 | // 863 | // Fixed offset don't work well with large hiberfil with Windows 8+. 864 | // 865 | if (GetContext()->IsWin8AndAbove()) 866 | { 867 | ULONG64 Offset = 0; 868 | 869 | for (UINT i = 5; i < 0x30; i += 1) 870 | { 871 | ULONG BytesToRead = 0x20; 872 | UCHAR Data[0x20]; 873 | PVOID pData = &Data; 874 | Offset = (i * PAGE_SIZE) - BytesToRead; 875 | ULONG64 CurrentPage = (ULONG64)i * PAGE_SIZE; 876 | if (GetContext()->ReadFile(Offset, sizeof(Data), &pData)) 877 | { 878 | ULONG NullBytes = TRUE; 879 | for (UINT i = 0; i < BytesToRead; i += 1) 880 | { 881 | if (Data[i] != '\0') 882 | { 883 | NullBytes = FALSE; 884 | break; 885 | } 886 | } 887 | 888 | if (NullBytes) { 889 | DbgPrint(L" Potential /OFFSET 0x%llx \n", CurrentPage); 890 | return CurrentPage; 891 | } 892 | } 893 | } 894 | } 895 | 896 | switch (GetContext()->GetPlatform()) 897 | { 898 | case PlatformX86: 899 | if (GetContext()->IsWin10()) return 0x7000ULL; 900 | else if (GetContext()->IsWin81()) return 0x7000ULL; 901 | else if (GetContext()->IsWin8()) return 0x7000ULL; 902 | else if (GetContext()->IsWin7()) return 0x6000ULL; 903 | else if (GetContext()->IsWinVista()) return 0x6000ULL; 904 | else if (GetContext()->IsWinXP()) return 0x6000ULL; 905 | break; 906 | case PlatformX64: 907 | if (GetContext()->IsWin10()) return 0x7000ULL; 908 | else if (GetContext()->IsWin81()) return 0x7000ULL; 909 | else if (GetContext()->IsWin8()) return 0x7000ULL; 910 | else if (GetContext()->IsWin7()) return 0x6000ULL; 911 | else if (GetContext()->IsWinVista()) return 0x6000ULL; 912 | else if (GetContext()->IsWinXP64()) return 0x6000ULL; 913 | break; 914 | } 915 | 916 | return 0x7000ULL; 917 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | {one line to give the program's name and a brief idea of what it does.} 635 | Copyright (C) {year} {name of author} 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | {project} Copyright (C) {year} {fullname} 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | --------------------------------------------------------------------------------