├── img └── chart.png ├── CheckSDL ├── Release │ └── CheckSDL.exe ├── CheckSDL │ ├── stdafx.cpp │ ├── targetver.h │ ├── CollectFileStatuses.h │ ├── FileStatus.h │ ├── stdafx.h │ ├── SDLStatus.h │ ├── DataCollectionDisplayer.h │ ├── ImportStatus.h │ ├── PEConfig.h │ ├── N3949 │ │ ├── scope_guard.h │ │ └── unique_resource.h │ ├── CheckSDL.vcxproj.filters │ ├── CollectFileStatuses.cpp │ ├── CheckSDL.cpp │ ├── SDLStatus.cpp │ ├── BannedFunctions.h │ ├── CheckSDL.vcxproj │ ├── ImportStatus.cpp │ ├── banned.h │ ├── DataCollectionDisplayer.cpp │ └── PEConfig.cpp └── CheckSDL.sln ├── LICENSE └── README.md /img/chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tandasat/CheckSDL/HEAD/img/chart.png -------------------------------------------------------------------------------- /CheckSDL/Release/CheckSDL.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tandasat/CheckSDL/HEAD/CheckSDL/Release/CheckSDL.exe -------------------------------------------------------------------------------- /CheckSDL/CheckSDL/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // EvalSecurity.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /CheckSDL/CheckSDL/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | #define _WIN32_WINNT _WIN32_WINNT_WINXP 10 | #include 11 | 12 | -------------------------------------------------------------------------------- /CheckSDL/CheckSDL.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Express 2013 for Windows Desktop 4 | VisualStudioVersion = 12.0.30501.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CheckSDL", "CheckSDL\CheckSDL.vcxproj", "{E901889E-352B-4BC8-8D9C-125B14C9B6F5}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {E901889E-352B-4BC8-8D9C-125B14C9B6F5}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {E901889E-352B-4BC8-8D9C-125B14C9B6F5}.Debug|Win32.Build.0 = Debug|Win32 16 | {E901889E-352B-4BC8-8D9C-125B14C9B6F5}.Release|Win32.ActiveCfg = Release|Win32 17 | {E901889E-352B-4BC8-8D9C-125B14C9B6F5}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 tandasat 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /CheckSDL/CheckSDL/CollectFileStatuses.h: -------------------------------------------------------------------------------- 1 | // 2 | // This module declares an interface responsible for collecting FileStatus items 3 | // 4 | #pragma once 5 | 6 | 7 | // C/C++ standard headers 8 | // Other external headers 9 | // Windows headers 10 | // Project headers 11 | #include "FileStatus.h" 12 | 13 | 14 | //////////////////////////////////////////////////////////////////////////////// 15 | // 16 | // macro utilities 17 | // 18 | 19 | 20 | //////////////////////////////////////////////////////////////////////////////// 21 | // 22 | // constants and macros 23 | // 24 | 25 | 26 | //////////////////////////////////////////////////////////////////////////////// 27 | // 28 | // types 29 | // 30 | 31 | 32 | //////////////////////////////////////////////////////////////////////////////// 33 | // 34 | // prototypes 35 | // 36 | 37 | std::vector CollectFileStatuses( 38 | const std::tr2::sys::path& TargetPath); 39 | 40 | 41 | //////////////////////////////////////////////////////////////////////////////// 42 | // 43 | // variables 44 | // 45 | 46 | 47 | //////////////////////////////////////////////////////////////////////////////// 48 | // 49 | // implementations 50 | // 51 | -------------------------------------------------------------------------------- /CheckSDL/CheckSDL/FileStatus.h: -------------------------------------------------------------------------------- 1 | // 2 | // This module defines a struct representing PE characteristics and the 3 | // evaluation result of them pertaining to the file 4 | // 5 | #pragma once 6 | 7 | 8 | // C/C++ standard headers 9 | // Other external headers 10 | // Windows headers 11 | // Project headers 12 | #include "ImportStatus.h" 13 | #include "PEConfig.h" 14 | #include "SDLStatus.h" 15 | 16 | 17 | //////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // macro utilities 20 | // 21 | 22 | 23 | //////////////////////////////////////////////////////////////////////////////// 24 | // 25 | // constants and macros 26 | // 27 | 28 | 29 | //////////////////////////////////////////////////////////////////////////////// 30 | // 31 | // types 32 | // 33 | 34 | 35 | //////////////////////////////////////////////////////////////////////////////// 36 | // 37 | // prototypes 38 | // 39 | 40 | struct FileStatus 41 | { 42 | FileStatus( 43 | std::tr2::sys::path Path, 44 | PEConfig Config, 45 | SDLStatus Status) 46 | : path(std::move(Path)) 47 | , peConfig(std::move(Config)) 48 | , sdlStatus(std::move(Status)) 49 | {} 50 | std::tr2::sys::path path; 51 | PEConfig peConfig; 52 | SDLStatus sdlStatus; 53 | }; 54 | 55 | 56 | //////////////////////////////////////////////////////////////////////////////// 57 | // 58 | // variables 59 | // 60 | 61 | 62 | //////////////////////////////////////////////////////////////////////////////// 63 | // 64 | // implementations 65 | // 66 | -------------------------------------------------------------------------------- /CheckSDL/CheckSDL/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | #pragma once 6 | #include "targetver.h" 7 | 8 | 9 | // C/C++ standard headers 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | // Other external headers 23 | // Windows headers 24 | #include 25 | #include 26 | #include 27 | #pragma comment(lib, "Dbghelp.lib") 28 | 29 | // Project headers 30 | #include "N3949/scope_guard.h" 31 | #include "N3949/unique_resource.h" 32 | #define _SDL_BANNED_RECOMMENDED 33 | #include "banned.h" 34 | 35 | 36 | //////////////////////////////////////////////////////////////////////////////// 37 | // 38 | // macro utilities 39 | // 40 | 41 | 42 | //////////////////////////////////////////////////////////////////////////////// 43 | // 44 | // constants and macros 45 | // 46 | 47 | 48 | //////////////////////////////////////////////////////////////////////////////// 49 | // 50 | // types 51 | // 52 | 53 | enum class TriBool : std::uint8_t 54 | { 55 | False = 0, 56 | True, 57 | NotApplicable, 58 | }; 59 | 60 | 61 | //////////////////////////////////////////////////////////////////////////////// 62 | // 63 | // prototypes 64 | // 65 | 66 | 67 | //////////////////////////////////////////////////////////////////////////////// 68 | // 69 | // variables 70 | // 71 | 72 | 73 | //////////////////////////////////////////////////////////////////////////////// 74 | // 75 | // implementations 76 | // 77 | -------------------------------------------------------------------------------- /CheckSDL/CheckSDL/SDLStatus.h: -------------------------------------------------------------------------------- 1 | // 2 | // This module declares a class responsible for evaluating PE characteristics 3 | // based on the SDL criteria 4 | // 5 | #pragma once 6 | 7 | 8 | // C/C++ standard headers 9 | // Other external headers 10 | // Windows headers 11 | // Project headers 12 | 13 | 14 | //////////////////////////////////////////////////////////////////////////////// 15 | // 16 | // macro utilities 17 | // 18 | 19 | 20 | //////////////////////////////////////////////////////////////////////////////// 21 | // 22 | // constants and macros 23 | // 24 | 25 | 26 | //////////////////////////////////////////////////////////////////////////////// 27 | // 28 | // types 29 | // 30 | 31 | struct Severity 32 | { 33 | std::uint32_t numberOfCriticalPriorityViolations; 34 | std::uint32_t numberOfHighPriorityViolations; 35 | }; 36 | 37 | 38 | //////////////////////////////////////////////////////////////////////////////// 39 | // 40 | // prototypes 41 | // 42 | 43 | class PEConfig; 44 | 45 | class SDLStatus 46 | { 47 | public: 48 | explicit SDLStatus( 49 | const PEConfig* pe); 50 | bool isBuildByGoodCompiler() const; 51 | bool isASLREnabled() const; 52 | bool isDEPEnabled() const; 53 | bool isSEHProtectionEnabled() const; 54 | bool isGSEnabled() const; 55 | TriBool isHeapProtectionEnabled() const; 56 | const Severity& getSeverity() const; 57 | 58 | private: 59 | bool m_isBuildByGoodCompiler; 60 | bool m_isASLREnabled; 61 | bool m_isDEPEnabled; 62 | bool m_isSEHProtectionEnabled; 63 | bool m_isGSEnabled; 64 | TriBool m_isHeapProtectionEnabled; 65 | Severity m_severity; 66 | }; 67 | 68 | 69 | //////////////////////////////////////////////////////////////////////////////// 70 | // 71 | // variables 72 | // 73 | 74 | 75 | //////////////////////////////////////////////////////////////////////////////// 76 | // 77 | // implementations 78 | // 79 | -------------------------------------------------------------------------------- /CheckSDL/CheckSDL/DataCollectionDisplayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // This module declares a class responsible for outputting FileStatus 3 | // 4 | #pragma once 5 | 6 | 7 | // C/C++ standard headers 8 | // Other external headers 9 | // Windows headers 10 | // Project headers 11 | #include "FileStatus.h" 12 | 13 | 14 | //////////////////////////////////////////////////////////////////////////////// 15 | // 16 | // macro utilities 17 | // 18 | 19 | 20 | //////////////////////////////////////////////////////////////////////////////// 21 | // 22 | // constants and macros 23 | // 24 | 25 | 26 | //////////////////////////////////////////////////////////////////////////////// 27 | // 28 | // types 29 | // 30 | 31 | 32 | //////////////////////////////////////////////////////////////////////////////// 33 | // 34 | // prototypes 35 | // 36 | 37 | class DataCollectionDisplayer 38 | { 39 | public: 40 | explicit DataCollectionDisplayer( 41 | std::vector Files); 42 | bool hasData() const; 43 | bool csvWrite( 44 | const std::tr2::sys::path& FilePath) const; 45 | void print() const; 46 | 47 | struct Statistics 48 | { 49 | std::uint32_t sumOfCriticalPriorityViolations; 50 | std::uint32_t sumOfHighPriorityViolations; 51 | std::uint32_t sumOfBadCompilerUsages; 52 | std::uint32_t sumOfNoGS; 53 | std::uint32_t sumOfNoSEHProtection; 54 | std::uint32_t sumOfNoASLR; 55 | std::uint32_t sumOfNoDEP; 56 | std::uint32_t sumOfNoHeapProtection; 57 | std::uint32_t numberOfExecutableFiles; 58 | std::uint32_t sumOfSharedSections; 59 | std::uint32_t sumOfBannedFuncs1; 60 | std::uint32_t sumOfBannedFuncs2; 61 | }; 62 | 63 | private: 64 | std::vector m_files; 65 | Statistics m_stat; 66 | }; 67 | 68 | 69 | //////////////////////////////////////////////////////////////////////////////// 70 | // 71 | // variables 72 | // 73 | 74 | 75 | //////////////////////////////////////////////////////////////////////////////// 76 | // 77 | // implementations 78 | // 79 | -------------------------------------------------------------------------------- /CheckSDL/CheckSDL/ImportStatus.h: -------------------------------------------------------------------------------- 1 | // 2 | // This module declares a class responsible for extracting interesting 3 | // characteristics from an import section 4 | // 5 | #pragma once 6 | 7 | 8 | // C/C++ standard headers 9 | #include 10 | #include 11 | #include 12 | 13 | // Other external headers 14 | // Windows headers 15 | // Project headers 16 | 17 | 18 | //////////////////////////////////////////////////////////////////////////////// 19 | // 20 | // macro utilities 21 | // 22 | 23 | 24 | //////////////////////////////////////////////////////////////////////////////// 25 | // 26 | // constants and macros 27 | // 28 | 29 | 30 | //////////////////////////////////////////////////////////////////////////////// 31 | // 32 | // types 33 | // 34 | 35 | 36 | //////////////////////////////////////////////////////////////////////////////// 37 | // 38 | // prototypes 39 | // 40 | 41 | class ImportStatus 42 | { 43 | public: 44 | explicit ImportStatus( 45 | void* BaseAddress); 46 | bool isVB6PE() const; 47 | bool isManagedPE() const; 48 | bool isHeapProtectionFunctionImported() const; 49 | const std::vector& getImportedBannedFunctionsRequired() const; 50 | const std::vector& getimportedBannedFunctionsRecommended() const; 51 | 52 | private: 53 | void ProcessImportedModule( 54 | std::uintptr_t BaseAddress, 55 | const PIMAGE_IMPORT_DESCRIPTOR ImportDesc); 56 | void ProcessImportedFunction( 57 | std::uintptr_t BaseAddress, 58 | const PIMAGE_THUNK_DATA ThunkData); 59 | 60 | bool m_isVB6PE; 61 | bool m_isManagedPE; 62 | bool m_isMSVBVM60Imported; 63 | bool m_isMSCOREEImported; 64 | bool m_isHeapProtectionFunctionImported; 65 | std::vector m_importedBannedFunctionsRequired; 66 | std::vector m_importedBannedFunctionsRecommended; 67 | }; 68 | 69 | 70 | //////////////////////////////////////////////////////////////////////////////// 71 | // 72 | // variables 73 | // 74 | 75 | 76 | //////////////////////////////////////////////////////////////////////////////// 77 | // 78 | // implementations 79 | // 80 | -------------------------------------------------------------------------------- /CheckSDL/CheckSDL/PEConfig.h: -------------------------------------------------------------------------------- 1 | // 2 | // This module declares a class responsible for extracting interesting 3 | // characteristics from a PE file 4 | // 5 | #pragma once 6 | 7 | 8 | // C/C++ standard headers 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | // Other external headers 16 | // Windows headers 17 | // Project headers 18 | 19 | 20 | //////////////////////////////////////////////////////////////////////////////// 21 | // 22 | // macro utilities 23 | // 24 | 25 | 26 | //////////////////////////////////////////////////////////////////////////////// 27 | // 28 | // constants and macros 29 | // 30 | 31 | 32 | //////////////////////////////////////////////////////////////////////////////// 33 | // 34 | // types 35 | // 36 | 37 | 38 | //////////////////////////////////////////////////////////////////////////////// 39 | // 40 | // prototypes 41 | // 42 | 43 | class ImportStatus; 44 | 45 | class PEConfig 46 | { 47 | public: 48 | explicit PEConfig( 49 | const std::tr2::sys::path& Path); 50 | bool isExecutable() const; 51 | bool isVB6PE() const; 52 | bool isManagedPE() const; 53 | bool isDynamicBaseCompatible() const; 54 | bool isNXCompatible() const; 55 | bool isSEHProtectionEnabled() const; 56 | bool isGSEnabled() const; 57 | std::uint32_t getTimeStamp() const; 58 | std::uint32_t getLinkerVersion() const; 59 | const std::vector& getSharedSectionNames() const; 60 | bool isHeapProtectionEnabled() const; 61 | const std::vector& getImportedBannedFunctionsRequired() const; 62 | const std::vector& getimportedBannedFunctionsRecommended() const; 63 | 64 | private: 65 | bool m_isExecutalbe; 66 | bool m_hasDotNetHeader; 67 | bool m_isDynamicBaseCompatible; 68 | bool m_isNXCompatible; 69 | bool m_hasSEH; 70 | bool m_hasSafeSEH; 71 | bool m_hasGS; 72 | std::uint32_t m_timestamp; 73 | std::uint32_t m_linkerVersion; 74 | std::vector m_sharedSectionNames; 75 | std::shared_ptr m_importStatus; 76 | }; 77 | 78 | 79 | //////////////////////////////////////////////////////////////////////////////// 80 | // 81 | // variables 82 | // 83 | 84 | 85 | //////////////////////////////////////////////////////////////////////////////// 86 | // 87 | // implementations 88 | // 89 | -------------------------------------------------------------------------------- /CheckSDL/CheckSDL/N3949/scope_guard.h: -------------------------------------------------------------------------------- 1 | // 2 | // N3949 - Scoped Resource - Generic RAII Wrapper for the Standard Library 3 | // Peter Sommerlad and Andrew L. Sandoval 4 | // 5 | #ifndef SCOPE_GUARD_H_ 6 | #define SCOPE_GUARD_H_ 7 | 8 | #ifndef _MSC_VER 9 | #define SCOPE_GUARD_NOEXCEPT noexcept 10 | #else 11 | #define SCOPE_GUARD_NOEXCEPT 12 | #endif 13 | 14 | #if _HAS_EXCEPTIONS 15 | #define SCOPE_GUARD_TRY_BEGIN try { 16 | #define SCOPE_GUARD_CATCH_ALL } catch (...) { 17 | #define SCOPE_GUARD_CATCH_END } 18 | #else 19 | #define SCOPE_GUARD_TRY_BEGIN {{ 20 | #define SCOPE_GUARD_CATCH_ALL \ 21 | __pragma(warning(push)) \ 22 | __pragma(warning(disable:4127)) \ 23 | } if (0) { \ 24 | __pragma(warning(pop)) 25 | #define SCOPE_GUARD_CATCH_END }} 26 | #endif 27 | 28 | 29 | // modeled slightly after Andrescu's talk and article(s) 30 | namespace std { 31 | namespace experimental { 32 | 33 | template 34 | struct scope_guard_t 35 | { 36 | // construction 37 | explicit scope_guard_t(D &&f) SCOPE_GUARD_NOEXCEPT 38 | : deleter(std::move(f)) 39 | , execute_on_destruction{ true } 40 | {} 41 | 42 | // move 43 | scope_guard_t(scope_guard_t &&rhs) SCOPE_GUARD_NOEXCEPT 44 | : deleter(std::move(rhs.deleter)) 45 | , execute_on_destruction{ rhs.execute_on_destruction } 46 | { 47 | rhs.release(); 48 | } 49 | 50 | // release 51 | ~scope_guard_t() 52 | { 53 | if (execute_on_destruction) 54 | { 55 | SCOPE_GUARD_TRY_BEGIN 56 | deleter(); 57 | SCOPE_GUARD_CATCH_ALL 58 | SCOPE_GUARD_CATCH_END 59 | } 60 | } 61 | 62 | void release() SCOPE_GUARD_NOEXCEPT 63 | { 64 | execute_on_destruction = false; 65 | } 66 | 67 | private: 68 | scope_guard_t(scope_guard_t const &) = delete; 69 | void operator=(scope_guard_t const &) = delete; 70 | scope_guard_t& operator=(scope_guard_t &&) = delete; 71 | D deleter; 72 | bool execute_on_destruction; // exposition only 73 | }; 74 | 75 | // usage: auto guard=scope guard([] std::cout << "done...";); 76 | template 77 | scope_guard_t scope_guard(D && deleter) SCOPE_GUARD_NOEXCEPT 78 | { 79 | return scope_guard_t(std::move(deleter)); // fails with curlies 80 | } 81 | } 82 | } 83 | 84 | 85 | #undef SCOPE_GUARD_TRY_BEGIN 86 | #undef SCOPE_GUARD_CATCH_ALL 87 | #undef SCOPE_GUARD_CATCH_END 88 | #undef SCOPE_GUARD_NOEXCEPT 89 | #endif /* SCOPE GUARD H */ 90 | -------------------------------------------------------------------------------- /CheckSDL/CheckSDL/CheckSDL.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {c28ad5cc-c41c-4d72-8a45-eef278d73666} 18 | 19 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files\N3949 29 | 30 | 31 | Header Files\N3949 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 | Header Files 53 | 54 | 55 | Header Files 56 | 57 | 58 | 59 | 60 | Source Files 61 | 62 | 63 | Source Files 64 | 65 | 66 | Source Files 67 | 68 | 69 | Source Files 70 | 71 | 72 | Source Files 73 | 74 | 75 | Source Files 76 | 77 | 78 | Source Files 79 | 80 | 81 | -------------------------------------------------------------------------------- /CheckSDL/CheckSDL/CollectFileStatuses.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This module implements functions responsible for collecting FileStatus items 3 | // 4 | #include "stdafx.h" 5 | #include "CollectFileStatuses.h" 6 | 7 | 8 | // C/C++ standard headers 9 | // Other external headers 10 | // Windows headers 11 | // Project headers 12 | 13 | 14 | namespace fs = std::tr2::sys; 15 | 16 | 17 | //////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // macro utilities 20 | // 21 | 22 | 23 | //////////////////////////////////////////////////////////////////////////////// 24 | // 25 | // constants and macros 26 | // 27 | 28 | 29 | //////////////////////////////////////////////////////////////////////////////// 30 | // 31 | // types 32 | // 33 | 34 | 35 | //////////////////////////////////////////////////////////////////////////////// 36 | // 37 | // prototypes 38 | // 39 | 40 | namespace { 41 | 42 | 43 | bool AnalyzeFile( 44 | const fs::path& Path, 45 | std::vector& Files); 46 | 47 | 48 | bool IsSupportedFileType( 49 | const fs::path& Path); 50 | 51 | 52 | } // End of namespace {unnamed} 53 | 54 | 55 | //////////////////////////////////////////////////////////////////////////////// 56 | // 57 | // variables 58 | // 59 | 60 | 61 | //////////////////////////////////////////////////////////////////////////////// 62 | // 63 | // implementations 64 | // 65 | 66 | std::vector CollectFileStatuses( 67 | const fs::path& TargetPath) 68 | { 69 | if (!fs::exists(TargetPath)) 70 | { 71 | throw std::runtime_error("The specified file or directory does not exist."); 72 | } 73 | 74 | std::function&)> traverse; 75 | traverse = [&traverse]( 76 | const fs::path& Path, 77 | std::vector& Files) 78 | { 79 | if (fs::is_regular_file(Path)) 80 | { 81 | if (IsSupportedFileType(Path)) 82 | { 83 | AnalyzeFile(Path, Files); 84 | } 85 | } 86 | else if (fs::is_directory(Path)) 87 | { 88 | fs::directory_iterator endit; 89 | for (fs::directory_iterator it{ Path }; it != endit; ++it) 90 | { 91 | traverse(it->path(), Files); 92 | } 93 | } 94 | }; 95 | 96 | std::vector files; 97 | traverse(TargetPath, files); 98 | return files; 99 | } 100 | 101 | 102 | namespace { 103 | 104 | 105 | bool AnalyzeFile( 106 | const fs::path& Path, 107 | std::vector& Files) 108 | { 109 | try 110 | { 111 | std::cout << Path << std::endl; 112 | PEConfig pe{ Path }; 113 | SDLStatus sdl{ &pe }; 114 | Files.emplace_back(Path, std::move(pe), std::move(sdl)); 115 | return true; 116 | } 117 | catch (std::exception& e) 118 | { 119 | std::cout << e.what() << std::endl; 120 | } 121 | return false; 122 | } 123 | 124 | 125 | bool IsSupportedFileType( 126 | const fs::path& Path) 127 | { 128 | return(::_stricmp(Path.extension().c_str(), ".exe") == 0 129 | || ::_stricmp(Path.extension().c_str(), ".dll") == 0 130 | || ::_stricmp(Path.extension().c_str(), ".ocx") == 0); 131 | } 132 | 133 | 134 | } // End of namespace {unnamed} 135 | -------------------------------------------------------------------------------- /CheckSDL/CheckSDL/CheckSDL.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This module implements the top level procedure of this tool. 3 | // 4 | // Windows ISV Software Security Defenses 5 | // http://msdn.microsoft.com/en-us/library/bb430720.aspx 6 | // 7 | #include "stdafx.h" 8 | 9 | 10 | // C/C++ standard headers 11 | // Other external headers 12 | // Windows headers 13 | // Project headers 14 | #include "FileStatus.h" 15 | #include "DataCollectionDisplayer.h" 16 | #include "CollectFileStatuses.h" 17 | 18 | 19 | namespace fs = std::tr2::sys; 20 | 21 | 22 | //////////////////////////////////////////////////////////////////////////////// 23 | // 24 | // macro utilities 25 | // 26 | 27 | 28 | //////////////////////////////////////////////////////////////////////////////// 29 | // 30 | // constants and macros 31 | // 32 | 33 | 34 | //////////////////////////////////////////////////////////////////////////////// 35 | // 36 | // types 37 | // 38 | 39 | 40 | //////////////////////////////////////////////////////////////////////////////// 41 | // 42 | // prototypes 43 | // 44 | 45 | namespace { 46 | 47 | 48 | bool AppMain( 49 | const std::vector& Args); 50 | 51 | 52 | } // End of namespace {unnamed} 53 | 54 | 55 | //////////////////////////////////////////////////////////////////////////////// 56 | // 57 | // variables 58 | // 59 | 60 | 61 | //////////////////////////////////////////////////////////////////////////////// 62 | // 63 | // implementations 64 | // 65 | 66 | int main(int argc, char* argv[]) 67 | { 68 | int result = EXIT_FAILURE; 69 | try 70 | { 71 | std::vector args; 72 | for (int i = 0; i < argc; ++i) 73 | { 74 | args.emplace_back(argv[i]); 75 | } 76 | if (AppMain(args)) 77 | { 78 | result = EXIT_SUCCESS; 79 | } 80 | } 81 | catch (std::exception& e) 82 | { 83 | std::cout << e.what() << std::endl; 84 | } 85 | catch (...) 86 | { 87 | std::cout << "Unhandled exception.\n"; 88 | } 89 | return result; 90 | } 91 | 92 | 93 | namespace { 94 | 95 | 96 | bool AppMain( 97 | const std::vector& Args) 98 | { 99 | if (Args.size() == 1) 100 | { 101 | std::cout 102 | << "Usage:\n" 103 | << " >CheckSDL.exe target_path [csv_out_path]\n" 104 | << "\n" 105 | << " target_path: A path of either a file or a directory to evaluate.\n" 106 | << " csv_out_path: A path of a CSV file to save the result if needed.\n" 107 | << " An existing file will be overwritten without warning.\n" 108 | << "\n" 109 | << "Example:\n" 110 | << " >CheckSDL.exe CheckSDL.exe\n" 111 | << " >CheckSDL.exe C:\\Windows\\system32 system32.csv\n" 112 | << std::endl; 113 | return false; 114 | } 115 | 116 | const fs::path targetPath{ Args.at(1) }; 117 | const DataCollectionDisplayer displayer{ CollectFileStatuses(targetPath) }; 118 | if (!displayer.hasData()) 119 | { 120 | std::cout << "No applicable file was found.\n"; 121 | return false; 122 | } 123 | 124 | displayer.print(); 125 | if (Args.size() > 2) 126 | { 127 | const fs::path csvPath{ Args.at(2) }; 128 | if (!displayer.csvWrite(csvPath)) 129 | { 130 | std::cout << "Failed to output on " << csvPath << std::endl; 131 | } 132 | } 133 | return true; 134 | } 135 | 136 | 137 | } // End of namespace {unnamed} 138 | -------------------------------------------------------------------------------- /CheckSDL/CheckSDL/SDLStatus.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This module implements a class responsible for evaluating PE characteristics 3 | // based on the SDL criteria 4 | // 5 | #include "stdafx.h" 6 | #include "SDLStatus.h" 7 | 8 | 9 | // C/C++ standard headers 10 | // Other external headers 11 | // Windows headers 12 | // Project headers 13 | #include "PEConfig.h" 14 | 15 | 16 | //////////////////////////////////////////////////////////////////////////////// 17 | // 18 | // macro utilities 19 | // 20 | 21 | 22 | //////////////////////////////////////////////////////////////////////////////// 23 | // 24 | // constants and macros 25 | // 26 | 27 | 28 | //////////////////////////////////////////////////////////////////////////////// 29 | // 30 | // types 31 | // 32 | 33 | 34 | //////////////////////////////////////////////////////////////////////////////// 35 | // 36 | // prototypes 37 | // 38 | 39 | namespace { 40 | 41 | 42 | bool IsOldCompiler( 43 | std::uint32_t MajorLinkerVersion); 44 | 45 | 46 | } // End of namespace {unnamed} 47 | 48 | 49 | //////////////////////////////////////////////////////////////////////////////// 50 | // 51 | // variables 52 | // 53 | 54 | 55 | //////////////////////////////////////////////////////////////////////////////// 56 | // 57 | // implementations 58 | // 59 | 60 | SDLStatus::SDLStatus( 61 | const PEConfig* pe) 62 | : m_isBuildByGoodCompiler(!pe->isVB6PE() && !IsOldCompiler(pe->getLinkerVersion())) 63 | , m_isASLREnabled(pe->isManagedPE() || pe->isDynamicBaseCompatible()) 64 | , m_isDEPEnabled(pe->isManagedPE() || pe->isNXCompatible()) 65 | , m_isSEHProtectionEnabled(pe->isSEHProtectionEnabled()) 66 | , m_isGSEnabled(pe->isManagedPE() || pe->isGSEnabled()) 67 | , m_isHeapProtectionEnabled(!pe->isExecutable() ? TriBool::NotApplicable 68 | : pe->isManagedPE() ? TriBool::True 69 | : pe->isHeapProtectionEnabled() ? TriBool::True 70 | : TriBool::False) 71 | , m_severity({}) 72 | { 73 | // 74 | // CriticalPriority 75 | // 76 | if (!m_isBuildByGoodCompiler) 77 | { 78 | ++m_severity.numberOfCriticalPriorityViolations; 79 | } 80 | if (!m_isASLREnabled) 81 | { 82 | ++m_severity.numberOfCriticalPriorityViolations; 83 | } 84 | if (!m_isDEPEnabled) 85 | { 86 | ++m_severity.numberOfCriticalPriorityViolations; 87 | } 88 | if (!m_isSEHProtectionEnabled) 89 | { 90 | ++m_severity.numberOfCriticalPriorityViolations; 91 | } 92 | if (!m_isGSEnabled) 93 | { 94 | ++m_severity.numberOfCriticalPriorityViolations; 95 | } 96 | 97 | // 98 | // HighPriority 99 | // 100 | if (m_isHeapProtectionEnabled == TriBool::False) 101 | { 102 | ++m_severity.numberOfHighPriorityViolations; 103 | } 104 | if (!pe->getSharedSectionNames().empty()) 105 | { 106 | ++m_severity.numberOfHighPriorityViolations; 107 | } 108 | if (!pe->getImportedBannedFunctionsRequired().empty()) 109 | { 110 | ++m_severity.numberOfHighPriorityViolations; 111 | } 112 | if (!pe->getimportedBannedFunctionsRecommended().empty()) 113 | { 114 | ++m_severity.numberOfHighPriorityViolations; 115 | } 116 | } 117 | 118 | 119 | bool SDLStatus::isBuildByGoodCompiler() const 120 | { 121 | return m_isBuildByGoodCompiler; 122 | } 123 | 124 | 125 | bool SDLStatus::isASLREnabled() const 126 | { 127 | return m_isASLREnabled; 128 | } 129 | 130 | 131 | bool SDLStatus::isDEPEnabled() const 132 | { 133 | return m_isDEPEnabled; 134 | } 135 | 136 | 137 | bool SDLStatus::isSEHProtectionEnabled() const 138 | { 139 | return m_isSEHProtectionEnabled; 140 | } 141 | 142 | 143 | bool SDLStatus::isGSEnabled() const 144 | { 145 | return m_isGSEnabled; 146 | } 147 | 148 | 149 | TriBool SDLStatus::isHeapProtectionEnabled() const 150 | { 151 | return m_isHeapProtectionEnabled; 152 | } 153 | 154 | 155 | const Severity& SDLStatus::getSeverity() const 156 | { 157 | return m_severity; 158 | } 159 | 160 | 161 | namespace { 162 | 163 | 164 | // What hints in machine code can point me to the compiler which was used to generate it? 165 | // http://reverseengineering.stackexchange.com/questions/11/what-hints-in-machine-code-can-point-me-to-the-compiler-which-was-used-to-genera 166 | bool IsOldCompiler( 167 | std::uint32_t MajorLinkerVersion) 168 | { 169 | if (MajorLinkerVersion == 3 || // Microsoft Visual C++ v3.x 170 | MajorLinkerVersion == 4 || // Microsoft Visual C++ v4.x 171 | MajorLinkerVersion == 5 || // Microsoft Visual C++ v5.x / Borland C++ 172 | MajorLinkerVersion == 6 || // Microsoft VIsual Studio 6 173 | MajorLinkerVersion == 7) // Microsoft VIsual Studio .NET 174 | { 175 | return true; 176 | } 177 | return false; 178 | } 179 | 180 | 181 | } // End of namespace {unnamed} 182 | -------------------------------------------------------------------------------- /CheckSDL/CheckSDL/N3949/unique_resource.h: -------------------------------------------------------------------------------- 1 | // 2 | // N3949 - Scoped Resource - Generic RAII Wrapper for the Standard Library 3 | // Peter Sommerlad and Andrew L. Sandoval 4 | // 5 | #ifndef UNIQUE_RESOURCE_H_ 6 | #define UNIQUE_RESOURCE_H_ 7 | 8 | #include 9 | 10 | #ifndef _MSC_VER 11 | #define UNIQUE_RESOURCE_NOEXCEPT noexpect 12 | #else 13 | #define UNIQUE_RESOURCE_NOEXCEPT 14 | #endif 15 | 16 | #if _HAS_EXCEPTIONS 17 | #define UNIQUE_RESOURCE_TRY_BEGIN try { 18 | #define UNIQUE_RESOURCE_CATCH_ALL } catch (...) { 19 | #define UNIQUE_RESOURCE_CATCH_END } 20 | #else 21 | #define UNIQUE_RESOURCE_TRY_BEGIN {{ 22 | #define UNIQUE_RESOURCE_CATCH_ALL \ 23 | __pragma(warning(push)) \ 24 | __pragma(warning(disable:4127)) \ 25 | } if (0) { \ 26 | __pragma(warning(pop)) 27 | #define UNIQUE_RESOURCE_CATCH_END }} 28 | #endif 29 | 30 | 31 | namespace std { 32 | namespace experimental { 33 | 34 | enum class invoke_it { once, again }; 35 | 36 | template 37 | class unique_resource_t 38 | { 39 | R resource; 40 | D deleter; 41 | bool execute_on_destruction; // exposition only 42 | unique_resource_t& operator=(unique_resource_t const &) = delete; 43 | unique_resource_t(unique_resource_t const &) = delete; // no copies! 44 | 45 | public: 46 | // construction 47 | explicit unique_resource_t(R && resource, D && deleter, bool shouldrun = true) UNIQUE_RESOURCE_NOEXCEPT 48 | : resource(std::move(resource)) 49 | , deleter(std::move(deleter)) 50 | , execute_on_destruction{ shouldrun } 51 | {} 52 | 53 | // move 54 | unique_resource_t(unique_resource_t &&other) UNIQUE_RESOURCE_NOEXCEPT 55 | : resource(std::move(other.resource)) 56 | , deleter(std::move(other.deleter)) 57 | , execute_on_destruction{ other.execute_on_destruction } 58 | { 59 | other.release(); 60 | } 61 | 62 | unique_resource_t& operator=(unique_resource_t &&other) UNIQUE_RESOURCE_NOEXCEPT 63 | { 64 | this->invoke(invoke_it::once); 65 | deleter = std::move(other.deleter); 66 | resource = std::move(other.resource); 67 | execute_on_destruction = other.execute_on_destruction; 68 | other.release(); 69 | return *this; 70 | } 71 | 72 | // resource release 73 | ~unique_resource_t() 74 | { 75 | this->invoke(invoke_it::once); 76 | } 77 | 78 | void invoke(invoke_it const strategy = invoke_it::once) UNIQUE_RESOURCE_NOEXCEPT 79 | { 80 | if (execute_on_destruction) 81 | { 82 | UNIQUE_RESOURCE_TRY_BEGIN 83 | this->get_deleter()(resource); 84 | UNIQUE_RESOURCE_CATCH_ALL 85 | UNIQUE_RESOURCE_CATCH_END 86 | } 87 | execute_on_destruction = strategy == invoke_it::again; 88 | } 89 | 90 | R const & release() UNIQUE_RESOURCE_NOEXCEPT 91 | { 92 | execute_on_destruction = false; 93 | return this->get(); 94 | } 95 | 96 | void reset(R && newresource) UNIQUE_RESOURCE_NOEXCEPT 97 | { 98 | invoke(invoke_it::again); 99 | resource = std::move(newresource); 100 | } 101 | 102 | // resource access 103 | R const & get() const UNIQUE_RESOURCE_NOEXCEPT 104 | { 105 | return resource; 106 | } 107 | 108 | operator R const &() const UNIQUE_RESOURCE_NOEXCEPT 109 | { 110 | return resource; 111 | } 112 | 113 | R operator->() const UNIQUE_RESOURCE_NOEXCEPT 114 | { 115 | return resource; 116 | } 117 | 118 | std::add_lvalue_reference_t> operator*() const 119 | { 120 | return *resource; 121 | } 122 | 123 | // deleter access 124 | const D & get_deleter() const UNIQUE_RESOURCE_NOEXCEPT 125 | { 126 | return deleter; 127 | } 128 | }; 129 | 130 | //factories 131 | template 132 | unique_resource_t unique_resource(R && r, D t) UNIQUE_RESOURCE_NOEXCEPT 133 | { 134 | return unique_resource_t(std::move(r), std::move(t), true); 135 | } 136 | 137 | template 138 | unique_resource_t unique_resource_checked(R r, R invalid, D t) UNIQUE_RESOURCE_NOEXCEPT 139 | { 140 | bool shouldrun = (r != invalid); 141 | return unique_resource_t(std::move(r), std::move(t), shouldrun); 142 | } 143 | } 144 | } 145 | 146 | 147 | #undef UNIQUE_RESOURCE_TRY_BEGIN 148 | #undef UNIQUE_RESOURCE_CATCH_ALL 149 | #undef UNIQUE_RESOURCE_CATCH_END 150 | #undef UNIQUE_RESOURCE_NOEXCEPT 151 | #endif /* UNIQUE RESOURCE H */ 152 | -------------------------------------------------------------------------------- /CheckSDL/CheckSDL/BannedFunctions.h: -------------------------------------------------------------------------------- 1 | // 2 | // This module defines all banned function names defined by SDL 3 | // 4 | #pragma once 5 | 6 | 7 | //////////////////////////////////////////////////////////////////////////////// 8 | // 9 | // macro utilities 10 | // 11 | 12 | 13 | //////////////////////////////////////////////////////////////////////////////// 14 | // 15 | // constants and macros 16 | // 17 | 18 | // 19 | // Security Development Lifecycle (SDL) Banned Function Calls 20 | // http://msdn.microsoft.com/en-us/library/bb288454.aspx 21 | // 22 | static const char* BANNED_FUNCTIONS_REQUIRED[] = 23 | { 24 | "strcpy", 25 | "strcpyA", 26 | "strcpyW", 27 | "wcscpy", 28 | "_tcscpy", 29 | "_mbscpy", 30 | "StrCpy", 31 | "StrCpyA", 32 | "StrCpyW", 33 | "lstrcpy", 34 | "lstrcpyA", 35 | "lstrcpyW", 36 | "_tccpy", 37 | "_mbccpy", 38 | "_ftcscpy", 39 | "strncpy", 40 | "wcsncpy", 41 | "_tcsncpy", 42 | "_mbsncpy", 43 | "_mbsnbcpy", 44 | "StrCpyN", 45 | "StrCpyNA", 46 | "StrCpyNW", 47 | "StrNCpy", 48 | "strcpynA", 49 | "StrNCpyA", 50 | "StrNCpyW", 51 | "lstrcpyn", 52 | "lstrcpynA", 53 | "lstrcpynW", 54 | "strcat", 55 | "strcatA", 56 | "strcatW", 57 | "wcscat", 58 | "_tcscat", 59 | "_mbscat", 60 | "StrCat", 61 | "StrCatA", 62 | "StrCatW", 63 | "lstrcat", 64 | "lstrcatA", 65 | "lstrcatW", 66 | "StrCatBuff", 67 | "StrCatBuffA", 68 | "StrCatBuffW", 69 | "StrCatChainW", 70 | "_tccat", 71 | "_mbccat", 72 | "_ftcscat", 73 | "strncat", 74 | "wcsncat", 75 | "_tcsncat", 76 | "_mbsncat", 77 | "_mbsnbcat", 78 | "StrCatN", 79 | "StrCatNA", 80 | "StrCatNW", 81 | "StrNCat", 82 | "StrNCatA", 83 | "StrNCatW", 84 | "lstrncat", 85 | "lstrcatnA", 86 | "lstrcatnW", 87 | "lstrcatn", 88 | "sprintfW", 89 | "sprintfA", 90 | "wsprintf", 91 | "wsprintfW", 92 | "wsprintfA", 93 | "sprintf", 94 | "swprintf", 95 | "_stprintf", 96 | "wvsprintf", 97 | "wvsprintfA", 98 | "wvsprintfW", 99 | "vsprintf", 100 | "_vstprintf", 101 | "vswprintf", 102 | "wvsprintf", 103 | "wvsprintfA", 104 | "wvsprintfW", 105 | "vsprintf", 106 | "_vstprintf", 107 | "vswprintf", 108 | "strncpy", 109 | "wcsncpy", 110 | "_tcsncpy", 111 | "_mbsncpy", 112 | "_mbsnbcpy", 113 | "StrCpyN", 114 | "StrCpyNA", 115 | "StrCpyNW", 116 | "StrNCpy", 117 | "strcpynA", 118 | "StrNCpyA", 119 | "StrNCpyW", 120 | "lstrcpyn", 121 | "lstrcpynA", 122 | "lstrcpynW", 123 | "_fstrncpy", 124 | "strncat", 125 | "wcsncat", 126 | "_tcsncat", 127 | "_mbsncat", 128 | "_mbsnbcat", 129 | "StrCatN", 130 | "StrCatNA", 131 | "StrCatNW", 132 | "StrNCat", 133 | "StrNCatA", 134 | "StrNCatW", 135 | "lstrncat", 136 | "lstrcatnA", 137 | "lstrcatnW", 138 | "lstrcatn", 139 | "_fstrncat", 140 | "gets", 141 | "_getts", 142 | "_gettws", 143 | "IsBadWritePtr", 144 | "IsBadHugeWritePtr", 145 | "IsBadReadPtr", 146 | "IsBadHugeReadPtr", 147 | "IsBadCodePtr", 148 | "IsBadStringPtr", 149 | "memcpy", 150 | "RtlCopyMemory", 151 | "CopyMemory", 152 | "wmemcpy", 153 | }; 154 | 155 | 156 | static const char* BANNED_FUNCTIONS_RECOMMENDED[] = 157 | { 158 | "wnsprintf", 159 | "wnsprintfA", 160 | "wnsprintfW", 161 | "_snwprintf", 162 | "snprintf", 163 | "sntprintf", 164 | "_vsnprintf", 165 | "vsnprintf", 166 | "_vsnwprintf", 167 | "_vsntprintf", 168 | "wvnsprintf", 169 | "wvnsprintfA", 170 | "wvnsprintfW", 171 | "_snwprintf", 172 | "_snprintf", 173 | "_sntprintf", 174 | "nsprintf", 175 | "_vsnprintf", 176 | "_vsnwprintf", 177 | "_vsntprintf", 178 | "wvnsprintf", 179 | "wvnsprintfA", 180 | "wvnsprintfW", 181 | "strtok", 182 | "_tcstok", 183 | "wcstok", 184 | "_mbstok", 185 | "makepath", 186 | "_tmakepath", 187 | "_makepath", 188 | "_wmakepath", 189 | "_splitpath", 190 | "_tsplitpath", 191 | "_wsplitpath", 192 | "scanf", 193 | "wscanf", 194 | "_tscanf", 195 | "sscanf", 196 | "swscanf", 197 | "_stscanf", 198 | "_itoa", 199 | "_itow", 200 | "_i64toa", 201 | "_i64tow", 202 | "_ui64toa", 203 | "_ui64tot", 204 | "_ui64tow", 205 | "_ultoa", 206 | "_ultot", 207 | "_ultow", 208 | "CharToOem", 209 | "CharToOemA", 210 | "CharToOemW", 211 | "OemToChar", 212 | "OemToCharA", 213 | "OemToCharW", 214 | "CharToOemBuffA", 215 | "CharToOemBuffW", 216 | "alloca", 217 | "_alloca", 218 | "strlen", 219 | "wcslen", 220 | "_mbslen", 221 | "_mbstrlen", 222 | "StrLen", 223 | "lstrlen", 224 | "ChangeWindowMessageFilter", 225 | }; 226 | 227 | 228 | //////////////////////////////////////////////////////////////////////////////// 229 | // 230 | // types 231 | // 232 | 233 | 234 | //////////////////////////////////////////////////////////////////////////////// 235 | // 236 | // prototypes 237 | // 238 | 239 | 240 | //////////////////////////////////////////////////////////////////////////////// 241 | // 242 | // variables 243 | // 244 | 245 | 246 | //////////////////////////////////////////////////////////////////////////////// 247 | // 248 | // implementations 249 | // 250 | -------------------------------------------------------------------------------- /CheckSDL/CheckSDL/CheckSDL.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {E901889E-352B-4BC8-8D9C-125B14C9B6F5} 15 | Win32Proj 16 | CheckSDL 17 | 18 | 19 | 20 | Application 21 | true 22 | v120 23 | Unicode 24 | 25 | 26 | Application 27 | false 28 | v120_xp 29 | true 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | 45 | 46 | false 47 | 48 | 49 | 50 | Use 51 | Level4 52 | Disabled 53 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 54 | true 55 | 56 | 57 | Console 58 | true 59 | 60 | 61 | 62 | 63 | Level4 64 | Use 65 | MaxSpeed 66 | true 67 | true 68 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 69 | true 70 | MultiThreaded 71 | 72 | 73 | Console 74 | true 75 | true 76 | true 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | Create 102 | Create 103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CheckSDL 2 | ======== 3 | 4 | A tool evaluates security configurations of a given file based on Microsoft Security Development Lifecycle (SDL). 5 | 6 | This tool can be used for both defensive and offensive purposes since it can unveil PE files compiled with insecure configurations. 7 | 8 | 9 | Usage 10 | ----------------- 11 | >CheckSDL.exe target_path [csv_out_path] 12 | 13 | target_path: A path of either a file or a directory to evaluate. 14 | csv_out_path: A path of a CSV file to save the result if needed. 15 | An existing file will be overwritten without warning. 16 | 17 | In a nutshell, this tool checks if a PE file is: 18 | - Compiled by a reasonably new version of compiler. 19 | - Using /GS Stack buffer overrun detection. 20 | - Using either /SafeSEH exception handling protection or IMAGE_DLLCHARACTERISTICS_NO_SEH DllCharacteristics. 21 | - Using Data Execution Prevention (DEP) / No eXecute (NX). 22 | - Using Address space layout randomization (ASLR). 23 | - Using Heap corruption detection. 24 | - NOT containing any shared sections. 25 | - NOT using any of banned functions such as buffer-overrun prone functions. 26 | 27 | These criteria are defined and explained in [Windows ISV Software Security Defenses](http://msdn.microsoft.com/en-us/library/bb430720.aspx) and the pages linked by this page. 28 | 29 | There are some differences between this tool and SDL. For example, this tool defines severity for each check point either Critical or High for simplicity, while SDL prioritized them as either Critical, High or Moderate, but most things are conforming to SDL. Other caveats are listed on a Note section. 30 | 31 | 32 | Sample Output 33 | ----------------- 34 | Let's see some sample outputs. Here is a result of analysis for a system32 directory on Windows XP SP3. 35 | 36 | ... 37 | #ofCV #ofHV (Built) NewComp (Ver) GS SEHP DEP ASLR HeapP #ofSS #ofBF1 #ofBF2 (Path) 38 | ... 39 | 5 3 2001/ 8 false 7 false false false false false 0 10 3 c:/WINDOWS/system32/Restore/srdiag.exe 40 | ... 41 | 0 0 2012/ 6 true 9 true true true true N/A 0 0 0 c:/WINDOWS/system32/wups2.dll 42 | 3.61 1.68 94.19% 32.15% 44.90% 95.14% 95.05% 99.05% 0.00 3.53 1.64 43 | 44 | The First line is a header. Meaning of each column is as follows: 45 | - #ofCV: A number of Critical severity violations. 46 | - #ofHV: A number of High severity violations. 47 | - (Built): A date the file was compiled. 48 | - NewComp: New Compiler, namely, if it was compiled by a reasonably new version of a compiler. If not, it is a Critical violation. 49 | - (Ver): A version of a compiler used to compiled the file. 50 | - GS: If it is using /GS Stack buffer overrun detection. If not, it is a Critical violation. 51 | - SEHP: SEH Protection, namely, if it is using either /SafeSEH exception handling protection or IMAGE_DLLCHARACTERISTICS_NO_SEH DllCharacteristics. If neither, it is a Critical violation. 52 | - DEP: If it is using Data Execution Prevention (DEP) / No eXecute (NX). If not, it is a Critical violation. 53 | - ASLR: If it is using Address space layout randomization (ASLR). If not, it is a Critical violation. 54 | - HeapP: Heap Protection, namely, if it is using Heap corruption detection. If not, it is a High violation. 55 | - #ofSS: A number of shared sections. If exists, it is a High violation. 56 | - #ofBF1: A number of imported banned functions categorized as Require. If exists, it is a High violation. 57 | - #ofBF2: A number of imported banned functions categorized as Recommended. If exists, it is a High violation. 58 | - (Path): A path of the file. 59 | 60 | Columns with parentheses are additional information, and files are sorted by their violation levels (#ofCV and #ofHV0). 61 | 62 | The last line is statistics of the result. Each column means: 63 | - An average number of Critical severity violations. 64 | - An average number of High severity violations. 65 | - Proportion of violations of NewComp. 66 | - Proportion of violations of GS. 67 | - Proportion of violations of SEHP. 68 | - Proportion of violations of DEP. 69 | - Proportion of violations of ASLR. 70 | - Proportion of violations of HeapP. 71 | - An average number of shared sections. 72 | - An average number of imported banned functions categorized as Require. 73 | - An average number of imported banned functions categorized as Recommended. 74 | 75 | For all of them, the lower number, the better. So let's compare results for system32 directories on both Windows XP SP3 and 7 SP1. 76 | 77 | #ofCV #ofHV (Built) NewComp (Ver) GS SEHP DEP ASLR HeapP #ofSS #ofBF1 #ofBF2 (Path) 78 | 3.61 1.68 94.19% 32.15% 44.90% 95.14% 95.05% 99.05% 0.00 3.53 1.64 XP SP3 79 | 0.09 1.33 0.64% 3.02% 0.87% 2.55% 2.32% 33.12% 0.00 0.87 1.13 7 SP1 80 | 81 | ![chart](/img/chart.png) 82 | 83 | As you can see, there are significant differences in #ofCV and many of other criteria. By using this tool, you will be able to measure security levels of a file, or the product package or detect a component that could be exploited and should be improved. 84 | 85 | 86 | Note 87 | ----------------- 88 | - A 64 bit file is not analyzed. 89 | - Only .exe, .dll and .ocx are analyzed. 90 | - A kernel mode file with the above extensions will be analyzed incorrectly since analysis is done in the same manner as a user mode file. 91 | - Analysis of imported banned functions are not as accurate as a result of source code based analysis since these functions may be either inlined (the tool causes false negatives) or emitted by some of StrSafe functions (the tool causes false positives). 92 | - When a file is Managed PE file, some configurations are treated as enabled regardless of actual value in a PE header; these are GS, DEP, ASLR and Heap Protection. 93 | - Heap Protection is only evaluated when a file is an executable file according to the SDL criteria. 94 | 95 | 96 | Supported Platforms 97 | ----------------- 98 | - Windows XP SP3 and later (both x86 and x64) 99 | 100 | 101 | License 102 | ----------------- 103 | This software is released under the MIT License, see LICENSE. 104 | 105 | -------------------------------------------------------------------------------- /CheckSDL/CheckSDL/ImportStatus.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This module implements a class responsible for extracting interesting 3 | // characteristics from an import section 4 | // 5 | #include "stdafx.h" 6 | #include "ImportStatus.h" 7 | 8 | 9 | // C/C++ standard headers 10 | // Other external headers 11 | // Windows headers 12 | // Project headers 13 | #include "BannedFunctions.h" 14 | 15 | 16 | //////////////////////////////////////////////////////////////////////////////// 17 | // 18 | // macro utilities 19 | // 20 | 21 | 22 | //////////////////////////////////////////////////////////////////////////////// 23 | // 24 | // constants and macros 25 | // 26 | 27 | 28 | //////////////////////////////////////////////////////////////////////////////// 29 | // 30 | // types 31 | // 32 | 33 | 34 | //////////////////////////////////////////////////////////////////////////////// 35 | // 36 | // prototypes 37 | // 38 | 39 | namespace { 40 | 41 | 42 | bool IsMSVB( 43 | const char* ModuleName); 44 | 45 | 46 | bool IsMSCOREE( 47 | const char* ModuleName); 48 | 49 | 50 | bool IsBannedRequiredFunction( 51 | const char* FunctionName); 52 | 53 | 54 | bool IsBannedRecommendedFunction( 55 | const char* FunctionName); 56 | 57 | 58 | bool IsHeapProtectionFunction( 59 | const char* FunctionName); 60 | 61 | 62 | } // End of namespace {unnamed} 63 | 64 | 65 | //////////////////////////////////////////////////////////////////////////////// 66 | // 67 | // variables 68 | // 69 | 70 | 71 | //////////////////////////////////////////////////////////////////////////////// 72 | // 73 | // implementations 74 | // 75 | 76 | ImportStatus::ImportStatus( 77 | void* BaseAddress) 78 | : m_isVB6PE(false) 79 | , m_isManagedPE(false) 80 | , m_isMSVBVM60Imported(false) 81 | , m_isMSCOREEImported(false) 82 | , m_isHeapProtectionFunctionImported(false) 83 | { 84 | auto bytesOfDirectoryEntry = 0ul; 85 | auto importDesc = static_cast( 86 | ::ImageDirectoryEntryToData(BaseAddress, TRUE, 87 | IMAGE_DIRECTORY_ENTRY_IMPORT, &bytesOfDirectoryEntry)); 88 | if (!importDesc) 89 | { 90 | throw std::runtime_error("No Import Directory."); 91 | } 92 | 93 | const auto baseAddr = reinterpret_cast(BaseAddress); 94 | auto numberOfImportedModules = 0ul; 95 | for (; importDesc->OriginalFirstThunk; ++importDesc, ++numberOfImportedModules) 96 | { 97 | ProcessImportedModule(baseAddr, importDesc); 98 | } 99 | m_isVB6PE = (m_isMSVBVM60Imported && numberOfImportedModules == 1); 100 | m_isManagedPE = (m_isMSCOREEImported && numberOfImportedModules == 1); 101 | } 102 | 103 | 104 | bool ImportStatus::isVB6PE() const 105 | { 106 | return m_isVB6PE; 107 | } 108 | 109 | 110 | bool ImportStatus::isManagedPE() const 111 | { 112 | return m_isManagedPE; 113 | } 114 | 115 | 116 | bool ImportStatus::isHeapProtectionFunctionImported() const 117 | { 118 | return m_isHeapProtectionFunctionImported; 119 | } 120 | 121 | 122 | const std::vector& ImportStatus::getImportedBannedFunctionsRequired() const 123 | { 124 | return m_importedBannedFunctionsRequired; 125 | } 126 | 127 | 128 | const std::vector& ImportStatus::getimportedBannedFunctionsRecommended() const 129 | { 130 | return m_importedBannedFunctionsRecommended; 131 | } 132 | 133 | 134 | void ImportStatus::ProcessImportedModule( 135 | std::uintptr_t BaseAddress, 136 | const PIMAGE_IMPORT_DESCRIPTOR ImportDesc) 137 | { 138 | const auto moduleName = reinterpret_cast(BaseAddress + ImportDesc->Name); 139 | m_isMSVBVM60Imported = m_isMSVBVM60Imported || IsMSVB(moduleName); 140 | m_isMSCOREEImported = m_isMSCOREEImported || IsMSCOREE(moduleName); 141 | 142 | auto thunkData = reinterpret_cast( 143 | BaseAddress + ImportDesc->OriginalFirstThunk); 144 | for (; thunkData->u1.Ordinal; ++thunkData) 145 | { 146 | ProcessImportedFunction(BaseAddress, thunkData); 147 | } 148 | } 149 | 150 | 151 | void ImportStatus::ProcessImportedFunction( 152 | std::uintptr_t BaseAddress, 153 | const PIMAGE_THUNK_DATA ThunkData) 154 | { 155 | if (IMAGE_SNAP_BY_ORDINAL(ThunkData->u1.Ordinal)) 156 | { 157 | return; 158 | } 159 | const auto importByName = reinterpret_cast( 160 | BaseAddress + ThunkData->u1.AddressOfData); 161 | const auto functionName = reinterpret_cast( 162 | importByName->Name); 163 | 164 | if (IsBannedRequiredFunction(functionName)) 165 | { 166 | m_importedBannedFunctionsRequired.push_back(functionName); 167 | } 168 | if (IsBannedRecommendedFunction(functionName)) 169 | { 170 | m_importedBannedFunctionsRecommended.push_back(functionName); 171 | } 172 | m_isHeapProtectionFunctionImported = m_isHeapProtectionFunctionImported 173 | || IsHeapProtectionFunction(functionName); 174 | } 175 | 176 | 177 | namespace { 178 | 179 | 180 | bool IsMSVB( 181 | const char* ModuleName) 182 | { 183 | return ::_stricmp(ModuleName, "MSVBVM60.DLL") == 0; 184 | } 185 | 186 | 187 | bool IsMSCOREE( 188 | const char* ModuleName) 189 | { 190 | return ::_stricmp(ModuleName, "MSCOREE.DLL") == 0; 191 | } 192 | 193 | 194 | bool IsBannedRequiredFunction( 195 | const char* FunctionName) 196 | { 197 | return std::find_if( 198 | std::begin(BANNED_FUNCTIONS_REQUIRED), 199 | std::end(BANNED_FUNCTIONS_REQUIRED), 200 | [=](const char* Banned) 201 | { 202 | return strcmp(Banned, FunctionName) == 0; 203 | }) != std::end(BANNED_FUNCTIONS_REQUIRED); 204 | } 205 | 206 | 207 | bool IsBannedRecommendedFunction( 208 | const char* FunctionName) 209 | { 210 | return std::find_if( 211 | std::begin(BANNED_FUNCTIONS_RECOMMENDED), 212 | std::end(BANNED_FUNCTIONS_RECOMMENDED), 213 | [=](const char* Banned) 214 | { 215 | return strcmp(Banned, FunctionName) == 0; 216 | }) != std::end(BANNED_FUNCTIONS_RECOMMENDED); 217 | } 218 | 219 | 220 | bool IsHeapProtectionFunction( 221 | const char* FunctionName) 222 | { 223 | return ::strcmp("HeapSetInformation", FunctionName) == 0; 224 | } 225 | 226 | 227 | } // End of namespace {unnamed} 228 | -------------------------------------------------------------------------------- /CheckSDL/CheckSDL/banned.h: -------------------------------------------------------------------------------- 1 | /*** 2 | * banned.h - list of Microsoft Security Development Lifecycle (SDL) banned APIs 3 | * Copyright (c) Microsoft Corporation. All rights reserved. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 6 | * and associated documentation files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all copies or 12 | * substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 15 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 16 | * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 17 | * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | * 21 | * Purpose: 22 | * This include file contains a list of banned APIs which should not be used in new code and 23 | * removed from legacy code over time. 24 | * 25 | * History 26 | * 01-Jan-2006 - mikehow - Initial Version 27 | * 22-Apr-2008 - mikehow - Updated to SDL 4.1, commented out recommendations and added memcpy 28 | * 26-Jan-2009 - mikehow - Updated to SDL 5.0, made the list sane, added SDL compliance levels 29 | * 10-Feb-2009 - mikehow - Updated based on feedback from MS Office 30 | * 12-May-2009 - jpardue - Added wmemcpy 31 | * 08-Jul-2009 - mikehow - Fixed header #ifndef/#endif logic, made the SDL recommended compliance level name more obvious 32 | * 05-Nov-2009 - mikehow - Added vsnprintf (ANSI version of _vsnprintf) 33 | * 01-Jan-2010 - mikehow - Added better strsafe integration, now the following works: 34 | * #include "strsafe.h" 35 | * #include "banned.h" 36 | * 04-Jun-2010 - mikehow - Small "#if" bug fix 37 | * 16-Jun-2011 - mikehow - Added the two _CRT_SECURE_xxxxx macros 38 | * 07-Jul-2011 - mikehow - Bugfix when using recommended banned functions and StrSafe. Locally surpressed C4005 warnings 39 | * 01-Feb-2013 - martinwo - Added license to header. 40 | ***/ 41 | 42 | #ifndef _INC_BANNED 43 | # define _INC_BANNED 44 | 45 | # if defined(_MSC_VER) 46 | # pragma once 47 | 48 | // Flip the 'auto-migrate' functionality in VC++ 49 | // Some functions, such as strcpy() are changed to safer functions by the compiler 50 | // More info: http://blogs.msdn.com/b/sdl/archive/2010/02/16/vc-2010-and-memcpy.aspx 51 | #ifndef _SDL_DONT_AUTO_FIX 52 | 53 | # pragma warning(push) 54 | # pragma warning(disable: 4005) 55 | 56 | // strcpy etc 57 | # define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES (1) 58 | 59 | // memcpy etc 60 | # define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_MEMORY (1) 61 | 62 | # pragma warning(pop) 63 | 64 | #endif 65 | 66 | // SDL 5.0 and later Requirements 67 | # if defined(_STRSAFE_H_INCLUDED_) && !defined(STRSAFE_NO_DEPRECATE) 68 | 69 | // Only deprecate what's not already deprecated by StrSafe 70 | # pragma deprecated (_mbscpy, _mbccpy) 71 | # pragma deprecated (strcatA, strcatW, _mbscat, StrCatBuff, StrCatBuffA, StrCatBuffW, StrCatChainW, _tccat, _mbccat) 72 | # pragma deprecated (strncpy, wcsncpy, _tcsncpy, _mbsncpy, _mbsnbcpy, StrCpyN, StrCpyNA, StrCpyNW, StrNCpy, strcpynA, StrNCpyA, StrNCpyW, lstrcpyn, lstrcpynA, lstrcpynW) 73 | # pragma deprecated (strncat, wcsncat, _tcsncat, _mbsncat, _mbsnbcat, lstrncat, lstrcatnA, lstrcatnW, lstrcatn) 74 | # pragma deprecated (IsBadWritePtr, IsBadHugeWritePtr, IsBadReadPtr, IsBadHugeReadPtr, IsBadCodePtr, IsBadStringPtr) 75 | # pragma deprecated (memcpy, RtlCopyMemory, CopyMemory, wmemcpy) 76 | 77 | # else 78 | // StrSafe not loaded, so deprecate everything! 79 | # pragma deprecated (strcpy, strcpyA, strcpyW, wcscpy, _tcscpy, _mbscpy, StrCpy, StrCpyA, StrCpyW, lstrcpy, lstrcpyA, lstrcpyW, _tccpy, _mbccpy, _ftcscpy) 80 | # pragma deprecated (strcat, strcatA, strcatW, wcscat, _tcscat, _mbscat, StrCat, StrCatA, StrCatW, lstrcat, lstrcatA, lstrcatW, StrCatBuff, StrCatBuffA, StrCatBuffW, StrCatChainW, _tccat, _mbccat, _ftcscat) 81 | # pragma deprecated (sprintfW, sprintfA, wsprintf, wsprintfW, wsprintfA, sprintf, swprintf, _stprintf) 82 | # pragma deprecated (wvsprintf, wvsprintfA, wvsprintfW, vsprintf, _vstprintf, vswprintf) 83 | # pragma deprecated (strncpy, wcsncpy, _tcsncpy, _mbsncpy, _mbsnbcpy, StrCpyN, StrCpyNA, StrCpyNW, StrNCpy, strcpynA, StrNCpyA, StrNCpyW, lstrcpyn, lstrcpynA, lstrcpynW) 84 | # pragma deprecated (strncat, wcsncat, _tcsncat, _mbsncat, _mbsnbcat, StrCatN, StrCatNA, StrCatNW, StrNCat, StrNCatA, StrNCatW, lstrncat, lstrcatnA, lstrcatnW, lstrcatn) 85 | # pragma deprecated (gets, _getts, _gettws) 86 | # pragma deprecated (IsBadWritePtr, IsBadHugeWritePtr, IsBadReadPtr, IsBadHugeReadPtr, IsBadCodePtr, IsBadStringPtr) 87 | # pragma deprecated (memcpy, RtlCopyMemory, CopyMemory, wmemcpy) 88 | # endif //defined(_STRSAFE_H_INCLUDED_) && !defined(STRSAFE_NO_DEPRECATE) 89 | 90 | // SDL 5.0 and later Recommendations 91 | # if defined(_SDL_BANNED_RECOMMENDED) 92 | # if defined(_STRSAFE_H_INCLUDED_) && !defined(STRSAFE_NO_DEPRECATE) 93 | // Only deprecate what's not already deprecated by StrSafe 94 | # pragma deprecated (wnsprintf, wnsprintfA, wnsprintfW) 95 | # pragma deprecated (vsnprintf, wvnsprintf, wvnsprintfA, wvnsprintfW) 96 | # pragma deprecated (strtok, _tcstok, wcstok, _mbstok) 97 | # pragma deprecated (makepath, _tmakepath, _makepath, _wmakepath) 98 | # pragma deprecated (_splitpath, _tsplitpath, _wsplitpath) 99 | # pragma deprecated (scanf, wscanf, _tscanf, sscanf, swscanf, _stscanf, snscanf, snwscanf, _sntscanf) 100 | # pragma deprecated (_itoa, _itow, _i64toa, _i64tow, _ui64toa, _ui64tot, _ui64tow, _ultoa, _ultot, _ultow) 101 | # pragma deprecated (CharToOem, CharToOemA, CharToOemW, OemToChar, OemToCharA, OemToCharW, CharToOemBuffA, CharToOemBuffW) 102 | # pragma deprecated (alloca, _alloca) 103 | # pragma deprecated (strlen, wcslen, _mbslen, _mbstrlen, StrLen, lstrlen) 104 | # pragma deprecated (ChangeWindowMessageFilter) 105 | # else 106 | // StrSafe not loaded, so deprecate everything! 107 | # pragma deprecated (wnsprintf, wnsprintfA, wnsprintfW, _snwprintf, _snprintf, _sntprintf) 108 | # pragma deprecated (_vsnprintf, vsnprintf, _vsnwprintf, _vsntprintf, wvnsprintf, wvnsprintfA, wvnsprintfW) 109 | # pragma deprecated (strtok, _tcstok, wcstok, _mbstok) 110 | # pragma deprecated (makepath, _tmakepath, _makepath, _wmakepath) 111 | # pragma deprecated (_splitpath, _tsplitpath, _wsplitpath) 112 | # pragma deprecated (scanf, wscanf, _tscanf, sscanf, swscanf, _stscanf, snscanf, snwscanf, _sntscanf) 113 | # pragma deprecated (_itoa, _itow, _i64toa, _i64tow, _ui64toa, _ui64tot, _ui64tow, _ultoa, _ultot, _ultow) 114 | # pragma deprecated (CharToOem, CharToOemA, CharToOemW, OemToChar, OemToCharA, OemToCharW, CharToOemBuffA, CharToOemBuffW) 115 | # pragma deprecated (alloca, _alloca) 116 | # pragma deprecated (strlen, wcslen, _mbslen, _mbstrlen, StrLen, lstrlen) 117 | # pragma deprecated (ChangeWindowMessageFilter) 118 | # endif // StrSafe 119 | # endif // SDL recommended 120 | 121 | # endif // _MSC_VER_ 122 | 123 | #endif // _INC_BANNED 124 | 125 | 126 | -------------------------------------------------------------------------------- /CheckSDL/CheckSDL/DataCollectionDisplayer.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This module implements a class responsible for outputting FileStatus 3 | // 4 | #include "stdafx.h" 5 | #include "DataCollectionDisplayer.h" 6 | 7 | 8 | // C/C++ standard headers 9 | // Other external headers 10 | // Windows headers 11 | // Project headers 12 | 13 | 14 | namespace fs = std::tr2::sys; 15 | 16 | 17 | //////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // macro utilities 20 | // 21 | 22 | 23 | //////////////////////////////////////////////////////////////////////////////// 24 | // 25 | // constants and macros 26 | // 27 | 28 | 29 | //////////////////////////////////////////////////////////////////////////////// 30 | // 31 | // types 32 | // 33 | 34 | 35 | //////////////////////////////////////////////////////////////////////////////// 36 | // 37 | // prototypes 38 | // 39 | 40 | namespace { 41 | 42 | 43 | template 44 | void write( 45 | const std::vector& Files, 46 | const DataCollectionDisplayer::Statistics& Stat, 47 | OutPutDevice& Device, 48 | char Separator); 49 | 50 | 51 | tm UintToTm( 52 | std::uint32_t SecSince1900); 53 | 54 | 55 | } // End of namespace {unnamed} 56 | 57 | 58 | //////////////////////////////////////////////////////////////////////////////// 59 | // 60 | // variables 61 | // 62 | 63 | 64 | //////////////////////////////////////////////////////////////////////////////// 65 | // 66 | // implementations 67 | // 68 | 69 | DataCollectionDisplayer::DataCollectionDisplayer( 70 | std::vector Files) 71 | : m_files(std::move(Files)) 72 | , m_stat({}) 73 | { 74 | // Sorts elements in that priority: 75 | // numberOfCriticalPriorityViolations > numberOfHighPriorityViolations > path 76 | std::sort(std::begin(m_files), std::end(m_files), []( 77 | const decltype(m_files)::value_type& Lhs, 78 | const decltype(m_files)::value_type& Rhs) 79 | { 80 | if (Lhs.sdlStatus.getSeverity().numberOfCriticalPriorityViolations != 81 | Rhs.sdlStatus.getSeverity().numberOfCriticalPriorityViolations) 82 | { 83 | return 84 | Lhs.sdlStatus.getSeverity().numberOfCriticalPriorityViolations > 85 | Rhs.sdlStatus.getSeverity().numberOfCriticalPriorityViolations; 86 | } 87 | else if ( 88 | Lhs.sdlStatus.getSeverity().numberOfHighPriorityViolations != 89 | Rhs.sdlStatus.getSeverity().numberOfHighPriorityViolations) 90 | { 91 | return 92 | Lhs.sdlStatus.getSeverity().numberOfHighPriorityViolations > 93 | Rhs.sdlStatus.getSeverity().numberOfHighPriorityViolations; 94 | } 95 | else 96 | { 97 | return Lhs.path < Rhs.path; 98 | } 99 | }); 100 | 101 | // Fill data into Statistics 102 | for (const auto& file : m_files) 103 | { 104 | m_stat.sumOfCriticalPriorityViolations += file.sdlStatus.getSeverity().numberOfCriticalPriorityViolations; 105 | m_stat.sumOfHighPriorityViolations += file.sdlStatus.getSeverity().numberOfHighPriorityViolations; 106 | if (!file.sdlStatus.isBuildByGoodCompiler()) { m_stat.sumOfBadCompilerUsages++; } 107 | if (!file.sdlStatus.isASLREnabled()) { m_stat.sumOfNoASLR++; } 108 | if (!file.sdlStatus.isDEPEnabled()) { m_stat.sumOfNoDEP++; } 109 | if (!file.sdlStatus.isSEHProtectionEnabled()) { m_stat.sumOfNoSEHProtection++; } 110 | if (!file.sdlStatus.isGSEnabled()) { m_stat.sumOfNoGS++; } 111 | if (file.sdlStatus.isHeapProtectionEnabled() == TriBool::False) { m_stat.sumOfNoHeapProtection++; } 112 | if (file.peConfig.isExecutable()) { m_stat.numberOfExecutableFiles++; } 113 | m_stat.sumOfSharedSections += file.peConfig.getSharedSectionNames().size(); 114 | m_stat.sumOfBannedFuncs1 += file.peConfig.getImportedBannedFunctionsRequired().size(); 115 | m_stat.sumOfBannedFuncs2 += file.peConfig.getimportedBannedFunctionsRecommended().size(); 116 | } 117 | } 118 | 119 | 120 | bool DataCollectionDisplayer::hasData() const 121 | { 122 | return !m_files.empty(); 123 | } 124 | 125 | 126 | bool DataCollectionDisplayer::csvWrite( 127 | const fs::path& FilePath) const 128 | { 129 | std::ofstream file(FilePath); 130 | if (!file) 131 | { 132 | return false; 133 | } 134 | write(m_files, m_stat, file, ','); 135 | return true; 136 | } 137 | 138 | 139 | void DataCollectionDisplayer::print() const 140 | { 141 | write(m_files, m_stat, std::cout, '\t'); 142 | } 143 | 144 | 145 | namespace { 146 | 147 | 148 | template 149 | void write( 150 | const std::vector& Files, 151 | const DataCollectionDisplayer::Statistics& Stat, 152 | OutPutDevice& Device, 153 | char Separator) 154 | { 155 | Device 156 | << "#ofCV" << Separator 157 | << "#ofHV" << Separator 158 | << "(Built)" << Separator 159 | << "NewComp" << Separator 160 | << "(Ver)" << Separator 161 | << "GS" << Separator 162 | << "SEHP" << Separator 163 | << "DEP" << Separator 164 | << "ASLR" << Separator 165 | << "HeapP" << Separator 166 | << "#ofSS" << Separator 167 | << "#ofBF1" << Separator 168 | << "#ofBF2" << Separator 169 | << "(Path)" << Separator 170 | << "\n"; 171 | 172 | for (const auto& file : Files) 173 | { 174 | const auto tm = UintToTm(file.peConfig.getTimeStamp()); 175 | const auto note = file.peConfig.isVB6PE() ? "(VB6)" 176 | : file.peConfig.isManagedPE() ? "(NET)" : ""; 177 | const auto heap = file.sdlStatus.isHeapProtectionEnabled() == TriBool::True ? "true" 178 | : file.sdlStatus.isHeapProtectionEnabled() == TriBool::False ? "false" : "N/A"; 179 | 180 | Device 181 | << std::boolalpha << std::dec 182 | << file.sdlStatus.getSeverity().numberOfCriticalPriorityViolations << Separator 183 | << file.sdlStatus.getSeverity().numberOfHighPriorityViolations << Separator 184 | << tm.tm_year + 1900 << "/" << std::setw(2) << tm.tm_mon + 1 << Separator 185 | << file.sdlStatus.isBuildByGoodCompiler() << Separator 186 | << file.peConfig.getLinkerVersion() << note << Separator 187 | << file.sdlStatus.isGSEnabled() << Separator 188 | << file.sdlStatus.isSEHProtectionEnabled() << Separator 189 | << file.sdlStatus.isDEPEnabled() << Separator 190 | << file.sdlStatus.isASLREnabled() << Separator 191 | << heap << Separator 192 | << file.peConfig.getSharedSectionNames().size() << Separator 193 | << file.peConfig.getImportedBannedFunctionsRequired().size() << Separator 194 | << file.peConfig.getimportedBannedFunctionsRecommended().size() << Separator 195 | << file.path << Separator 196 | << "\n"; 197 | } 198 | Device 199 | << std::setprecision(2) << std::fixed 200 | << static_cast(Stat.sumOfCriticalPriorityViolations) / Files.size() << Separator 201 | << static_cast(Stat.sumOfHighPriorityViolations) / Files.size() << Separator 202 | << Separator 203 | << static_cast(Stat.sumOfBadCompilerUsages) / Files.size() * 100 << "%" << Separator 204 | << Separator 205 | << static_cast(Stat.sumOfNoGS) / Files.size() * 100 << "%" << Separator 206 | << static_cast(Stat.sumOfNoSEHProtection) / Files.size() * 100 << "%" << Separator 207 | << static_cast(Stat.sumOfNoDEP) / Files.size() * 100 << "%" << Separator 208 | << static_cast(Stat.sumOfNoASLR) / Files.size() * 100 << "%" << Separator 209 | << static_cast(Stat.sumOfNoHeapProtection) / Stat.numberOfExecutableFiles * 100 << "%" << Separator 210 | << static_cast(Stat.sumOfSharedSections) / Files.size() << Separator 211 | << static_cast(Stat.sumOfBannedFuncs1) / Files.size() << Separator 212 | << static_cast(Stat.sumOfBannedFuncs2) / Files.size() << Separator 213 | << "\n"; 214 | } 215 | 216 | 217 | tm UintToTm( 218 | std::uint32_t SecSince1900) 219 | { 220 | time_t t = SecSince1900; 221 | tm time{}; 222 | ::gmtime_s(&time, &t); 223 | return time; 224 | } 225 | 226 | 227 | } // End of namespace {unnamed} 228 | -------------------------------------------------------------------------------- /CheckSDL/CheckSDL/PEConfig.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This module implements a class responsible for extracting interesting 3 | // characteristics from a PE file 4 | // 5 | #include "stdafx.h" 6 | #include "PEConfig.h" 7 | 8 | 9 | // C/C++ standard headers 10 | // Other external headers 11 | // Windows headers 12 | // Project headers 13 | #include "ImportStatus.h" 14 | 15 | 16 | namespace fs = std::tr2::sys; 17 | 18 | 19 | //////////////////////////////////////////////////////////////////////////////// 20 | // 21 | // macro utilities 22 | // 23 | 24 | 25 | //////////////////////////////////////////////////////////////////////////////// 26 | // 27 | // constants and macros 28 | // 29 | 30 | 31 | //////////////////////////////////////////////////////////////////////////////// 32 | // 33 | // types 34 | // 35 | 36 | 37 | //////////////////////////////////////////////////////////////////////////////// 38 | // 39 | // prototypes 40 | // 41 | 42 | namespace { 43 | 44 | 45 | bool HasDotNetHeader( 46 | void* BaseAddress); 47 | 48 | 49 | bool HasSEH( 50 | const IMAGE_NT_HEADERS* Nt); 51 | 52 | 53 | bool IsDynamicBaseCompatible( 54 | const IMAGE_NT_HEADERS* Nt); 55 | 56 | 57 | bool IsNXCompatible( 58 | const IMAGE_NT_HEADERS* Nt); 59 | 60 | 61 | bool HasSafeSEH( 62 | void* BaseAddress); 63 | 64 | 65 | bool HasGS( 66 | void* BaseAddress, 67 | std::uint64_t AddressGap); 68 | 69 | 70 | std::vector GetSharedSectionNames( 71 | const IMAGE_NT_HEADERS* Nt); 72 | 73 | 74 | bool IsHeapProtectionSupportedCompilerVersion( 75 | std::uint32_t MajorLinkerVersion); 76 | 77 | 78 | } // End of namespace {unnamed} 79 | 80 | 81 | //////////////////////////////////////////////////////////////////////////////// 82 | // 83 | // variables 84 | // 85 | 86 | 87 | //////////////////////////////////////////////////////////////////////////////// 88 | // 89 | // implementations 90 | // 91 | 92 | PEConfig::PEConfig( 93 | const fs::path& Path) 94 | : m_isExecutalbe(false) 95 | , m_hasDotNetHeader(false) 96 | , m_isDynamicBaseCompatible(false) 97 | , m_isNXCompatible(false) 98 | , m_hasSEH(false) 99 | , m_hasSafeSEH(false) 100 | , m_hasGS(false) 101 | , m_timestamp(0) 102 | , m_linkerVersion(0) 103 | { 104 | // As LoadLibraryEx may display an error dialog 105 | ::SetErrorMode(SEM_FAILCRITICALERRORS); 106 | 107 | const auto dll = std::experimental::unique_resource( 108 | ::LoadLibraryExA(Path.string().c_str(), nullptr, DONT_RESOLVE_DLL_REFERENCES), 109 | ::FreeLibrary); 110 | if (!dll) 111 | { 112 | throw std::runtime_error("LoadLibraryExA failed."); 113 | } 114 | 115 | // FIXME: Do not trust what a PE header says. Treat it like malware. 116 | const auto baseAddr = 117 | reinterpret_cast(dll.get()) & 0xffffffffffff0000; 118 | const auto dos = reinterpret_cast(baseAddr); 119 | const auto nt = reinterpret_cast(baseAddr + dos->e_lfanew); 120 | if (nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) 121 | { 122 | throw std::runtime_error("Not PE32 header was detected."); 123 | } 124 | 125 | m_importStatus = std::make_shared(dos); 126 | m_isExecutalbe = ::_stricmp(Path.extension().c_str(), ".exe") == 0; 127 | m_hasDotNetHeader = HasDotNetHeader(dos); 128 | m_isDynamicBaseCompatible = IsDynamicBaseCompatible(nt); 129 | m_isNXCompatible = IsNXCompatible(nt); 130 | m_hasSEH = HasSEH(nt); 131 | m_hasSafeSEH = HasSafeSEH(dos); 132 | m_hasGS = HasGS(dos, nt->OptionalHeader.ImageBase - baseAddr); 133 | m_timestamp = nt->FileHeader.TimeDateStamp; 134 | m_linkerVersion = nt->OptionalHeader.MajorLinkerVersion; 135 | m_sharedSectionNames = GetSharedSectionNames(nt); 136 | } 137 | 138 | 139 | bool PEConfig::isExecutable() const 140 | { 141 | return m_isExecutalbe; 142 | } 143 | 144 | 145 | bool PEConfig::isVB6PE() const 146 | { 147 | return m_importStatus->isVB6PE(); 148 | } 149 | 150 | 151 | bool PEConfig::isManagedPE() const 152 | { 153 | return m_importStatus->isManagedPE() && m_hasDotNetHeader; 154 | } 155 | 156 | 157 | bool PEConfig::isDynamicBaseCompatible() const 158 | { 159 | return m_isDynamicBaseCompatible; 160 | } 161 | 162 | 163 | bool PEConfig::isNXCompatible() const 164 | { 165 | return m_isNXCompatible; 166 | } 167 | 168 | 169 | bool PEConfig::isSEHProtectionEnabled() const 170 | { 171 | return !m_hasSEH || m_hasSafeSEH; 172 | } 173 | 174 | 175 | bool PEConfig::isGSEnabled() const 176 | { 177 | return m_hasGS; 178 | } 179 | 180 | 181 | std::uint32_t PEConfig::getTimeStamp() const 182 | { 183 | return m_timestamp; 184 | } 185 | 186 | 187 | std::uint32_t PEConfig::getLinkerVersion() const 188 | { 189 | return m_linkerVersion; 190 | } 191 | 192 | 193 | const std::vector& PEConfig::getSharedSectionNames() const 194 | { 195 | return m_sharedSectionNames; 196 | } 197 | 198 | 199 | bool PEConfig::isHeapProtectionEnabled() const 200 | { 201 | return IsHeapProtectionSupportedCompilerVersion(m_linkerVersion) 202 | || m_importStatus->isHeapProtectionFunctionImported(); 203 | } 204 | 205 | 206 | const std::vector& PEConfig::getImportedBannedFunctionsRequired() const 207 | { 208 | return m_importStatus->getImportedBannedFunctionsRequired(); 209 | } 210 | 211 | 212 | const std::vector& PEConfig::getimportedBannedFunctionsRecommended() const 213 | { 214 | return m_importStatus->getimportedBannedFunctionsRecommended(); 215 | } 216 | 217 | 218 | namespace { 219 | 220 | 221 | bool HasDotNetHeader( 222 | void* BaseAddress) 223 | { 224 | auto bytesOfDirectoryEntry = 0ul; 225 | return (::ImageDirectoryEntryToData(BaseAddress, TRUE, 226 | IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, &bytesOfDirectoryEntry) != nullptr); 227 | } 228 | 229 | 230 | // SEH Stack Based Windows Buffer Overflow Tutorial 231 | // http://www.thegreycorner.com/2010/01/seh-stack-based-windows-buffer-overflow.html 232 | bool HasSEH( 233 | const IMAGE_NT_HEADERS* Nt) 234 | { 235 | return (Nt->OptionalHeader.DllCharacteristics & 236 | IMAGE_DLLCHARACTERISTICS_NO_SEH) == 0; 237 | } 238 | 239 | 240 | bool IsDynamicBaseCompatible( 241 | const IMAGE_NT_HEADERS* Nt) 242 | { 243 | return (Nt->OptionalHeader.DllCharacteristics & 244 | IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) != 0; 245 | } 246 | 247 | 248 | bool IsNXCompatible( 249 | const IMAGE_NT_HEADERS* Nt) 250 | { 251 | return (Nt->OptionalHeader.DllCharacteristics & 252 | IMAGE_DLLCHARACTERISTICS_NX_COMPAT) != 0; 253 | } 254 | 255 | 256 | bool HasSafeSEH( 257 | void* BaseAddress) 258 | { 259 | auto bytesOfDirectoryEntry = 0ul; 260 | const auto moduleConfig = static_cast( 261 | ::ImageDirectoryEntryToData(BaseAddress, TRUE, 262 | IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &bytesOfDirectoryEntry)); 263 | return moduleConfig && moduleConfig->SEHandlerCount; 264 | } 265 | 266 | 267 | bool HasGS( 268 | void* BaseAddress, 269 | std::uint64_t AddressGap) 270 | { 271 | const auto isValidCookieValue = []( 272 | DWORD* Address) 273 | { 274 | __try { return *Address != 0; } 275 | __except (1) { return false; } 276 | }; 277 | 278 | auto bytesOfDirectoryEntry = 0ul; 279 | const auto moduleConfig = static_cast( 280 | ::ImageDirectoryEntryToData(BaseAddress, TRUE, 281 | IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &bytesOfDirectoryEntry)); 282 | return moduleConfig 283 | && moduleConfig->SecurityCookie 284 | && isValidCookieValue(reinterpret_cast( 285 | moduleConfig->SecurityCookie - AddressGap)); 286 | } 287 | 288 | 289 | // Appendix G: SDL Requirement: No Shared Sections 290 | // http://msdn.microsoft.com/en-us/library/windows/desktop/cc307397.aspx 291 | std::vector GetSharedSectionNames( 292 | const IMAGE_NT_HEADERS* Nt) 293 | { 294 | std::vector sharedSectionNames; 295 | const auto firstSection = IMAGE_FIRST_SECTION(Nt); 296 | for (std::uint32_t i = 0; i < Nt->FileHeader.NumberOfSections; ++i) 297 | { 298 | const auto section = firstSection + i; 299 | if ((section->Characteristics & IMAGE_SCN_MEM_SHARED) == 0) 300 | { 301 | continue; 302 | } 303 | 304 | std::vector sectionName; 305 | for (auto c : section->Name) 306 | { 307 | const char normalized = 308 | (c == '\0' || ::isprint(c)) ? c : '?'; 309 | sectionName.push_back(normalized); 310 | } 311 | sectionName.push_back('\0'); // null-terminator 312 | sharedSectionNames.push_back(sectionName.data()); 313 | } 314 | return sharedSectionNames; 315 | } 316 | 317 | 318 | // HeapSetInformation in Visual C++ 2010 beta 2 319 | // http://blogs.msdn.com/b/sdl/archive/2010/01/14/heapsetinformation-in-visual-c-2010-beta-2.aspx 320 | bool IsHeapProtectionSupportedCompilerVersion( 321 | std::uint32_t MajorLinkerVersion) 322 | { 323 | return MajorLinkerVersion >= 10; // Microsoft VIsual Studio 2010 324 | } 325 | 326 | 327 | } // End of namespace {unnamed} 328 | --------------------------------------------------------------------------------