├── README.md
├── .gitmodules
├── .gitignore
├── hijacken
├── hijacken.vcxproj.filters
├── Utils.h
├── ProcessScan.h
├── Utils.cpp
├── Hijacken.cpp
├── PEParser.h
├── ProcessScan.cpp
├── ImageScan.h
├── Commands.h
├── hijacken.vcxproj
├── System.h
├── PEParser.cpp
├── Commands.cpp
├── ImageScan.cpp
└── System.cpp
└── hijacken.sln
/README.md:
--------------------------------------------------------------------------------
1 | # HiJacken Toolset
2 | Dll hijacking toolset
3 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "hijacken/ntlib"]
2 | path = hijacken/ntlib
3 | url = https://github.com/JKornev/NTlib
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /*.sdf
2 | /*.suo
3 | /Debug
4 | /x64
5 | /hijacken/Debug
6 | /hijacken/x64
7 | /hijacken/*.user
8 | /Release
9 | /hijacken/Release
10 |
--------------------------------------------------------------------------------
/hijacken/hijacken.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/hijacken.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.21005.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hijacken", "hijacken\hijacken.vcxproj", "{D37B1B81-F34C-4977-B350-6242F2F46468}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Win32 = Debug|Win32
11 | Debug|x64 = Debug|x64
12 | Release|Win32 = Release|Win32
13 | Release|x64 = Release|x64
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {D37B1B81-F34C-4977-B350-6242F2F46468}.Debug|Win32.ActiveCfg = Debug|Win32
17 | {D37B1B81-F34C-4977-B350-6242F2F46468}.Debug|Win32.Build.0 = Debug|Win32
18 | {D37B1B81-F34C-4977-B350-6242F2F46468}.Debug|x64.ActiveCfg = Debug|x64
19 | {D37B1B81-F34C-4977-B350-6242F2F46468}.Debug|x64.Build.0 = Debug|x64
20 | {D37B1B81-F34C-4977-B350-6242F2F46468}.Release|Win32.ActiveCfg = Release|Win32
21 | {D37B1B81-F34C-4977-B350-6242F2F46468}.Release|Win32.Build.0 = Release|Win32
22 | {D37B1B81-F34C-4977-B350-6242F2F46468}.Release|x64.ActiveCfg = Release|x64
23 | {D37B1B81-F34C-4977-B350-6242F2F46468}.Release|x64.Build.0 = Release|x64
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | EndGlobal
29 |
--------------------------------------------------------------------------------
/hijacken/Utils.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | namespace Utils
9 | {
10 | // =================
11 |
12 | class Exception
13 | {
14 | private:
15 | std::wstring _message;
16 | unsigned int _code;
17 |
18 | public:
19 | Exception(unsigned int code, const wchar_t* format, ...);
20 | Exception(const wchar_t* format, ...);
21 |
22 | std::wstring GetMessage();
23 | unsigned int GetCode();
24 | };
25 |
26 | static const unsigned int NoExceptionCode = -1;
27 |
28 | // =================
29 |
30 | class Explanation : public Utils::Exception
31 | {
32 | public:
33 | Explanation(const wchar_t* message) : Utils::Exception(message) {}
34 | };
35 |
36 | // =================
37 |
38 | class Arguments
39 | {
40 | private:
41 | std::vector _arguments;
42 | unsigned int _index;
43 |
44 | public:
45 |
46 | Arguments(int argc, wchar_t* argv[], int start = 1);
47 |
48 | size_t GetAmount();
49 |
50 | bool Probe(std::wstring& arg);
51 | bool SwitchToNext();
52 | bool GetNext(std::wstring& arg);
53 |
54 | bool IsEnded();
55 | };
56 |
57 | // =================
58 |
59 | class SeparatedStrings : public std::vector
60 | {
61 | public:
62 | SeparatedStrings(const std::wstring& str, wchar_t seporator);
63 | };
64 |
65 | };
66 |
--------------------------------------------------------------------------------
/hijacken/ProcessScan.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "System.h"
4 |
5 | namespace Engine
6 | {
7 | class ProcessScanEngine
8 | {
9 | public:
10 |
11 | enum class DetectionDirType
12 | {
13 | Executable,
14 | Current,
15 | Users,
16 | Environment,
17 | LoadedModule
18 | };
19 |
20 | enum class DetectionFileType
21 | {
22 | Executable,
23 | LoadedModule
24 | };
25 |
26 | void Scan(DWORD pid, System::TokenAccessChecker& access);
27 |
28 | virtual void NotifyWritableDirectory(DetectionDirType detection, std::wstring& dirPath) = 0;
29 | virtual void NotifyWritableFile(DetectionFileType detection, std::wstring& filePath) = 0;
30 |
31 | static const wchar_t* ConvertDirDetectionToString(DetectionDirType detection);
32 | static const wchar_t* ConvertFileDetectionToString(DetectionFileType detection);
33 |
34 | private:
35 |
36 | void ScanImage(System::TokenAccessChecker& access, System::ProcessInformation& info);
37 | void ScanCurrentDirectory(System::TokenAccessChecker& access, System::ProcessEnvironmentBlock& peb);
38 | void ScanEnvironmentPaths(System::TokenAccessChecker& access, System::ProcessEnvironmentBlock& peb);
39 | void ScanModules(System::TokenAccessChecker& access, System::ProcessInformation& info);
40 |
41 | bool IsFileWritable(std::wstring path, System::TokenAccessChecker& access);
42 | bool IsDirWritable(std::wstring path, System::TokenAccessChecker& access);
43 | };
44 | };
--------------------------------------------------------------------------------
/hijacken/Utils.cpp:
--------------------------------------------------------------------------------
1 | #include "Utils.h"
2 | #include
3 |
4 | namespace Utils
5 | {
6 |
7 | // =================
8 |
9 | Exception::Exception(unsigned int code, const wchar_t* format, ...) :
10 | _code(code)
11 | {
12 | wchar_t buffer[256];
13 |
14 | va_list args;
15 | va_start(args, format);
16 | _vsnwprintf_s(buffer, _countof(buffer), _TRUNCATE, format, args);
17 | va_end(args);
18 |
19 | _message = buffer;
20 | }
21 |
22 | Exception::Exception(const wchar_t* format, ...) :
23 | _code(NoExceptionCode)
24 | {
25 | wchar_t buffer[256];
26 |
27 | va_list args;
28 | va_start(args, format);
29 | _vsnwprintf_s(buffer, _countof(buffer), _TRUNCATE, format, args);
30 | va_end(args);
31 |
32 | _message = buffer;
33 | }
34 |
35 | std::wstring Exception::GetMessage()
36 | {
37 | return _message;
38 | }
39 |
40 | unsigned int Exception::GetCode()
41 | {
42 | return _code;
43 | }
44 |
45 | // =================
46 |
47 | Arguments::Arguments(int argc, wchar_t* argv[], int start) :
48 | _index(0)
49 | {
50 | for (int i = start; i < argc; i++)
51 | _arguments.push_back(argv[i]);
52 | }
53 |
54 | size_t Arguments::GetAmount()
55 | {
56 | return _arguments.size();
57 | }
58 |
59 | bool Arguments::Probe(std::wstring& arg)
60 | {
61 | if (_index >= _arguments.size())
62 | return false;
63 |
64 | arg = _arguments[_index];
65 | return true;
66 | }
67 |
68 | bool Arguments::SwitchToNext()
69 | {
70 | if (_index >= _arguments.size())
71 | return false;
72 |
73 | _index++;
74 | return true;
75 | }
76 |
77 | bool Arguments::GetNext(std::wstring& arg)
78 | {
79 | if (_index >= _arguments.size())
80 | return false;
81 |
82 | arg = _arguments[_index++];
83 | return true;
84 | }
85 |
86 | bool Arguments::IsEnded()
87 | {
88 | return (_index >= _arguments.size());
89 | }
90 |
91 | // =================
92 |
93 | SeparatedStrings::SeparatedStrings(const std::wstring& str, wchar_t seporator)
94 | {
95 | size_t startOffset = 0;
96 | auto endOffset = str.find(seporator);
97 |
98 | if (endOffset == std::wstring::npos)
99 | {
100 | push_back(str);
101 | return;
102 | }
103 |
104 | while (endOffset != std::wstring::npos)
105 | {
106 | if (startOffset != endOffset)
107 | push_back(std::wstring(&str[startOffset], &str[endOffset]));
108 | startOffset = endOffset + 1;
109 | endOffset = str.find(seporator, startOffset);
110 | }
111 |
112 | if (startOffset < str.size())
113 | push_back(std::wstring(str.c_str() + startOffset));
114 | }
115 |
116 | };
--------------------------------------------------------------------------------
/hijacken/Hijacken.cpp:
--------------------------------------------------------------------------------
1 | #include "Utils.h"
2 | #include "Commands.h"
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | namespace
9 | {
10 | void SwitchConsoleToUTF16Mode()
11 | {
12 | _setmode(_fileno(stdout), _O_U16TEXT);
13 | _setmode(_fileno(stderr), _O_U16TEXT);
14 | }
15 |
16 | bool PrintUsageIfNeeded(Utils::Arguments& args)
17 | {
18 | std::wstring command;
19 |
20 | if (!args.Probe(command))
21 | return false;
22 |
23 | if (command != L"/help" && command != L"/?")
24 | return false;
25 |
26 | //TODO: usage
27 |
28 | return true;
29 | }
30 |
31 | Commands::CommandPtr ChooseCommand(Utils::Arguments& args)
32 | {
33 | std::wstring command, sub;
34 | Commands::CommandPtr ptr;
35 |
36 | if (!args.GetNext(command))
37 | throw Utils::Explanation(L"Error, invalid usage. Please use 'hijacken /?'");
38 |
39 | if (command == L"/scan")
40 | {
41 | if (!args.GetNext(sub))
42 | throw Utils::Explanation(L"Error, /scan argument isn't presented");
43 |
44 | if (sub == L"file")
45 | ptr = Commands::CommandPtr(new Commands::ScanFile());
46 | else if (sub == L"directory")
47 | ptr = Commands::CommandPtr(new Commands::ScanDirectory());
48 | else if (sub == L"process")
49 | ptr = Commands::CommandPtr(new Commands::ScanProcess());
50 | else if (sub == L"processes")
51 | ptr = Commands::CommandPtr(new Commands::ScanProcesses());
52 | else if (sub == L"autorun")
53 | ptr = Commands::CommandPtr(new Commands::ScanAutorun());
54 | else if (sub == L"task")
55 | ptr = Commands::CommandPtr(new Commands::ScanTask());
56 | else if (sub == L"tasks")
57 | ptr = Commands::CommandPtr(new Commands::ScanTasks());
58 | else if (sub == L"service")
59 | ptr = Commands::CommandPtr(new Commands::ScanService());
60 | else if (sub == L"services")
61 | ptr = Commands::CommandPtr(new Commands::ScanServices());
62 | else if (sub == L"system")
63 | ptr = Commands::CommandPtr(new Commands::ScanSystem());
64 | else
65 | throw Utils::Explanation(L"Error, invalid /scan argument");
66 | }
67 | else if (command == L"/makedll")
68 | {
69 | ptr = Commands::CommandPtr(new Commands::MakeDll());
70 | }
71 | else
72 | {
73 | throw Utils::Explanation(L"Error, invalid command. Please use 'hijacken /?'");
74 | }
75 |
76 | return ptr;
77 | }
78 | }
79 |
80 | int wmain(int argc, wchar_t* argv[])
81 | {
82 | SwitchConsoleToUTF16Mode();
83 |
84 | try
85 | {
86 | Utils::Arguments arguments(argc, argv);
87 |
88 | if (!arguments.GetAmount())
89 | throw Utils::Explanation(L"Welcome to Hijacken. Please use 'hijacken /?' to get a usage information");
90 |
91 | if (PrintUsageIfNeeded(arguments))
92 | return 0;
93 |
94 | auto command = ChooseCommand(arguments);
95 | command->LoadArgs(arguments);
96 | command->Perform();
97 | }
98 | catch (Utils::Explanation& explanation)
99 | {
100 | std::wcerr << explanation.GetMessage() << std::endl;
101 | return explanation.GetCode();
102 | }
103 | catch (Utils::Exception& exception)
104 | {
105 | std::wcerr << L"Unhandled exception, program has been terminated" << std::endl;
106 | std::wcerr << L" reason: " << exception.GetMessage() << std::endl;
107 | return exception.GetCode();
108 | }
109 | catch (std::exception& exception)
110 | {
111 | std::wcerr << L"Unhandled STD exception, program has been terminated" << std::endl;
112 | std::wcerr << L" reason: " << exception.what() << std::endl;
113 | return Utils::NoExceptionCode;
114 | }
115 | catch (...)
116 | {
117 | std::wcerr << L"Unhandled exception, program has been terminated" << std::endl;
118 | std::wcerr << L" An internal error occured, there is no more information" << std::endl;
119 | return Utils::NoExceptionCode;
120 | }
121 |
122 | return 0;
123 | }
124 |
--------------------------------------------------------------------------------
/hijacken/PEParser.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "System.h"
4 | #include
5 | #include
6 |
7 | namespace PEParser
8 | {
9 |
10 | // =================
11 |
12 | typedef public std::vector ImportTable;
13 |
14 | // =================
15 |
16 | class ResourceData;
17 | class ResourceDirectory;
18 | typedef std::vector ResourceDataSet;
19 | typedef std::vector ResourceDirectorySet;
20 |
21 | // =================
22 |
23 | class ResourceEntry
24 | {
25 | public:
26 |
27 | enum class NamedResourceType {
28 | HasName,
29 | HasId,
30 | Unnamed
31 | };
32 |
33 | ResourceEntry();
34 | ResourceEntry(std::wstring& name);
35 | ResourceEntry(unsigned short id);
36 |
37 | bool operator==(const ResourceEntry& other) const;
38 |
39 | NamedResourceType GetType() const;
40 |
41 | std::wstring GetName() const;
42 | unsigned short GetID() const;
43 |
44 | private:
45 | NamedResourceType _type;
46 | std::wstring _name;
47 | unsigned short _id;
48 | };
49 |
50 | // =================
51 |
52 | class ResourceData : public ResourceEntry
53 | {
54 | private:
55 | unsigned long _offset;
56 | unsigned long _size;
57 | unsigned long _codepage;
58 |
59 | public:
60 | ResourceData();
61 | ResourceData(std::wstring& name, unsigned long offset, System::ImageMapping& image);
62 | ResourceData(unsigned short id, unsigned long offset, System::ImageMapping& image);
63 |
64 | std::vector ReadData(System::ImageMapping& image);
65 |
66 | private:
67 | void LoadDataEntry(unsigned long offset, System::ImageMapping& image);
68 | };
69 |
70 | // =================
71 |
72 | class ResourceDirectory : public ResourceEntry
73 | {
74 | private:
75 | ResourceDirectorySet _dirs;
76 | ResourceDataSet _data;
77 |
78 | public:
79 | ResourceDirectory();
80 | ResourceDirectory(std::wstring& name);
81 | ResourceDirectory(unsigned short id);
82 |
83 | void Push(ResourceDirectory& dir);
84 | void Push(ResourceData& data);
85 |
86 | const ResourceDirectorySet& GetDirs() const;
87 | const ResourceDataSet& GetData() const;
88 | };
89 |
90 |
91 | // =================
92 |
93 | class Resources
94 | {
95 | private:
96 | ResourceDirectory _root;
97 |
98 | public:
99 | Resources();
100 | Resources(ResourceDirectory& root);
101 |
102 | const ResourceDirectory& GetRoot() const;
103 | };
104 |
105 | // =================
106 |
107 | class ResourceUtils
108 | {
109 | public:
110 | static const ResourceDirectory& FindDirectory(const ResourceDirectory& dir, const ResourceEntry& id);
111 | static const ResourceData& FindData(const ResourceDirectory& dir, const ResourceEntry& id);
112 | static const std::vector LoadFirstResource(const Resources& resources, System::ImageMapping& image, const ResourceEntry& id);
113 | };
114 |
115 | // =================
116 |
117 | class Image
118 | {
119 | protected:
120 |
121 | struct SectionRegion
122 | {
123 | DWORD rawOffset;
124 | DWORD rawSize;
125 | DWORD virtualOffset;
126 | DWORD virtualSize;
127 | };
128 |
129 | System::ImageMapping& _mapping;
130 | std::vector _sections;
131 |
132 | System::Bitness _bitness;
133 |
134 | void* GetAddressByRVA(DWORD rva);
135 | std::string LoadStringByRVA(DWORD rva);
136 | std::wstring LoadWStringByRVA(DWORD rva);
137 |
138 | public:
139 | Image(System::ImageMapping& mapping);
140 | virtual ~Image() = default;
141 |
142 | System::Bitness GetBitness();
143 |
144 | virtual ImportTable LoadImportTable() = 0;
145 | virtual ImportTable LoadDelayImportTable() = 0;
146 | virtual Resources LoadResources() = 0;
147 | };
148 |
149 | typedef std::shared_ptr ImagePtr;
150 |
151 | // =================
152 |
153 | class ImageFactory
154 | {
155 | private:
156 | static System::Bitness GetImageBitness(System::ImageMapping& mapping);
157 |
158 | public:
159 | ImagePtr GetImage(System::ImageMapping& mapping);
160 | };
161 |
162 | // =================
163 |
164 | template
165 | class ImageImpl : public Image
166 | {
167 | private:
168 | T* _header;
169 |
170 | public:
171 | ImageImpl(System::ImageMapping& mapping);
172 | virtual ~ImageImpl() = default;
173 |
174 | ImportTable LoadImportTable() override;
175 | ImportTable LoadDelayImportTable() override;
176 |
177 | Resources LoadResources() override;
178 |
179 | private:
180 | void LoadResourceDirectory(DWORD resourceBase, DWORD resourceDir, ResourceDirectory& resource);
181 | };
182 |
183 | }
184 |
--------------------------------------------------------------------------------
/hijacken/ProcessScan.cpp:
--------------------------------------------------------------------------------
1 | #include "ProcessScan.h"
2 |
3 | namespace Engine
4 | {
5 |
6 | void ProcessScanEngine::Scan(DWORD pid, System::TokenAccessChecker& access)
7 | {
8 | System::ProcessInformation info(pid);
9 | System::ProcessEnvironmentBlock peb(info);
10 |
11 | ScanImage(access, info);
12 | ScanCurrentDirectory(access, peb);
13 | ScanEnvironmentPaths(access, peb);
14 | ScanModules(access, info);
15 | }
16 |
17 | void ProcessScanEngine::ScanImage(System::TokenAccessChecker& access, System::ProcessInformation& info)
18 | {
19 | try
20 | {
21 | std::wstring imageDir;
22 | info.GetImageDirectory(imageDir);
23 |
24 | if (IsDirWritable(imageDir, access))
25 | {
26 | NotifyWritableDirectory(DetectionDirType::Executable, imageDir);
27 | return;
28 | }
29 |
30 | std::wstring imageFile;
31 | info.GetImagePath(imageFile);
32 |
33 | if (IsFileWritable(imageFile, access))
34 | {
35 | NotifyWritableFile(DetectionFileType::Executable, imageFile);
36 | return;
37 | }
38 | }
39 | catch (...)
40 | {
41 | }
42 | }
43 |
44 | void ProcessScanEngine::ScanCurrentDirectory(System::TokenAccessChecker& access, System::ProcessEnvironmentBlock& peb)
45 | {
46 | try
47 | {
48 | std::wstring currentDirPath;
49 | peb.GetCurrentDir(currentDirPath);
50 |
51 | if (IsDirWritable(currentDirPath, access))
52 | {
53 | NotifyWritableDirectory(DetectionDirType::Current, currentDirPath);
54 | return;
55 | }
56 | }
57 | catch (...)
58 | {
59 | }
60 | }
61 |
62 | void ProcessScanEngine::ScanEnvironmentPaths(System::TokenAccessChecker& access, System::ProcessEnvironmentBlock& peb)
63 | {
64 | std::wstring pathSet;
65 | auto env = peb.GetProcessEnvironment();
66 |
67 | if (!env->GetValue(L"Path", pathSet) && !env->GetValue(L"PATH", pathSet) && !env->GetValue(L"path", pathSet))
68 | throw Utils::Exception(L"Can't obtain 'Path' environment variable");
69 |
70 | Utils::SeparatedStrings paths(pathSet, L';');
71 |
72 | for (auto& dir : paths)
73 | {
74 | try
75 | {
76 | if (IsDirWritable(dir, access))
77 | NotifyWritableDirectory(DetectionDirType::Environment, dir);
78 | }
79 | catch (...)
80 | {
81 | }
82 | }
83 | }
84 |
85 | void ProcessScanEngine::ScanModules(System::TokenAccessChecker& access, System::ProcessInformation& info)
86 | {
87 | System::ModulesSnapshot snapshot(info.GetProcess()->GetProcessID());
88 | HMODULE module;
89 |
90 | while (snapshot.GetNextModule(module))
91 | {
92 | std::wstring modulePath, moduleDir;
93 | info.GetModulePath(module, modulePath);
94 |
95 | System::FileUtils::ExtractFileDirectory(modulePath, moduleDir);
96 |
97 | if (IsDirWritable(moduleDir, access))
98 | {
99 | NotifyWritableDirectory(DetectionDirType::LoadedModule, moduleDir);
100 | continue;
101 | }
102 |
103 | if (IsFileWritable(modulePath, access))
104 | {
105 | NotifyWritableFile(DetectionFileType::LoadedModule, modulePath);
106 | continue;
107 | }
108 | }
109 | }
110 |
111 | bool ProcessScanEngine::IsFileWritable(std::wstring path, System::TokenAccessChecker& access)
112 | {
113 | System::File file(path.c_str());
114 | System::SecurityDescriptor descriptor(file);
115 | return access.IsFileObjectAccessible(descriptor, FILE_WRITE_DATA);
116 | }
117 |
118 | bool ProcessScanEngine::IsDirWritable(std::wstring path, System::TokenAccessChecker& access)
119 | {
120 | System::Directory directory(path.c_str());
121 | System::SecurityDescriptor descriptor(directory);
122 | return access.IsFileObjectAccessible(descriptor, FILE_ADD_FILE);
123 | }
124 |
125 | const wchar_t* ProcessScanEngine::ConvertDirDetectionToString(DetectionDirType detection)
126 | {
127 | switch (detection)
128 | {
129 | case DetectionDirType::Executable:
130 | return L"Executable directory";
131 | case DetectionDirType::Current:
132 | return L"Current directory";
133 | case DetectionDirType::Users:
134 | return L"Users directory";
135 | case DetectionDirType::Environment:
136 | return L"Environment directory";
137 | case DetectionDirType::LoadedModule:
138 | return L"Module directory";
139 | default:
140 | break;
141 | }
142 | return L"Unknown";
143 | }
144 |
145 | const wchar_t* ProcessScanEngine::ConvertFileDetectionToString(DetectionFileType detection)
146 | {
147 | switch (detection)
148 | {
149 | case DetectionFileType::Executable:
150 | return L"Executable file";
151 | case DetectionFileType::LoadedModule:
152 | return L"Loaded module";
153 | default:
154 | break;
155 | }
156 | return L"Unknown";
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/hijacken/ImageScan.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "System.h"
4 | #include "PEParser.h"
5 | #include
6 | #include
7 | #include
8 |
9 | namespace Engine
10 | {
11 | // =================
12 |
13 | class ImageDirectory
14 | {
15 | public:
16 |
17 | enum class Type
18 | {
19 | Base,
20 | System32,
21 | System,
22 | Windows,
23 | Current,
24 | Environment,
25 | FullPath,
26 | SxS,
27 | Unknown
28 | };
29 |
30 | enum class State
31 | {
32 | Existing,
33 | NotExisting,
34 | Overlapped
35 | };
36 |
37 | private:
38 |
39 | std::wstring _directory;
40 | Type _type;
41 | bool _accessible;
42 | State _state;
43 |
44 | public:
45 |
46 | ImageDirectory();
47 | ImageDirectory(Type type, const std::wstring& imageDir, const System::TokenAccessChecker& access);
48 |
49 | bool operator==(const ImageDirectory& compared) const;
50 |
51 | const std::wstring& GetPath() const;
52 | Type GetType() const;
53 | State GetState() const;
54 | bool IsAccessible() const;
55 |
56 | };
57 |
58 | typedef std::vector ImageDirectories;
59 |
60 | // =================
61 |
62 | class LoadImageOrder
63 | {
64 | private:
65 | ImageDirectories _order;
66 | ImageDirectories _orderWow64;
67 | bool _wow64mode;
68 |
69 | public:
70 | LoadImageOrder(const std::wstring& imageDir, const std::wstring& currentDir, const System::EnvironmentVariables& envVars, const System::TokenAccessChecker& access);
71 |
72 | void SetWow64Mode(bool value);
73 |
74 | const ImageDirectories& GetOrder() const;
75 | const ImageDirectory& GetBaseDir() const;
76 | static bool IsSafeSearchEnabled();
77 |
78 |
79 | private:
80 | void LoadEnvironmentVariables(const System::EnvironmentVariables& envVars, bool wow64mode, const System::TokenAccessChecker& access);
81 | };
82 |
83 | // =================
84 |
85 | class ImageScanOrder : public LoadImageOrder
86 | {
87 | public:
88 | ImageScanOrder(const std::wstring& imageDir, const std::wstring& currentDir, const System::EnvironmentVariables& envVars, const System::TokenAccessChecker& access);
89 |
90 | ImageDirectory FindDllDirectory(const std::wstring& dllname) const;
91 |
92 | private:
93 | bool DirContainsDll(const std::wstring& dllname, ImageDirectory& dir) const;
94 |
95 | };
96 |
97 | // =================
98 |
99 | class DllCache
100 | {
101 | private:
102 | std::unordered_set _dlls;
103 | public:
104 | bool InsertOnlyNew(const std::wstring& dllName);
105 | bool Contain(const std::wstring& dllName);
106 | };
107 |
108 | // =================
109 |
110 | class KnownDlls
111 | {
112 | private:
113 | DllCache _known;
114 | DllCache _knownWow64;
115 | DllCache _excluded;
116 |
117 | bool _supportWow64;
118 |
119 | public:
120 | KnownDlls();
121 |
122 | bool Contain(std::wstring& dllName, System::Bitness bitness);
123 |
124 | private:
125 |
126 | void LoadExcludedDlls();
127 | void UnwindImports(const std::wstring& dllName, bool wow64mode);
128 | };
129 |
130 | // =================
131 |
132 | class ActivationContextStack
133 | {
134 | private:
135 | std::vector _stack;
136 |
137 | public:
138 | void Push(System::ActivationContext& context);
139 | void Pop();
140 |
141 | bool IsLibrarySxS(const std::wstring& dllName, std::wstring& sxsDir);
142 |
143 | };
144 |
145 | class LoadManifestAndPush
146 | {
147 | public:
148 | LoadManifestAndPush(System::ImageMapping& module, const std::wstring& imageDir, ActivationContextStack& stack);
149 |
150 | private:
151 | std::vector ReadManifestFromResources(System::ImageMapping& module);
152 | std::vector NormalizeManifest(const std::vector& manifest);
153 | std::wstring SafeManifestToTempFile(const std::vector& manifest);
154 | };
155 |
156 | // =================
157 |
158 | class ImageScanContext
159 | {
160 | private:
161 |
162 | std::shared_ptr _image;
163 | PEParser::ImagePtr _parser;
164 |
165 | std::wstring _imagePath;
166 | std::wstring _imageDir;
167 | std::wstring _imageFile;
168 | System::Bitness _bitness;
169 |
170 | DllCache _scannedDlls;
171 |
172 | const System::TokenAccessChecker& _accessChecker;
173 |
174 | ActivationContextStack _actxStack;
175 |
176 | public:
177 | ImageScanContext(const std::wstring& imagePath, const System::TokenAccessChecker& access);
178 |
179 | System::ImageMapping GetAppImage() const;
180 | const PEParser::ImagePtr GetAppParser() const;
181 |
182 | const std::wstring& GetAppPath() const;
183 | const std::wstring& GetAppDirectory() const;
184 | const std::wstring& GetAppFileName() const;
185 | System::Bitness GetAppBitness() const;
186 |
187 | DllCache& GetDllsCache();
188 |
189 | const System::TokenAccessChecker& GetAccessChecker() const;
190 |
191 | ActivationContextStack& GetActivationContextStack();
192 |
193 | private:
194 | void LoadDefaultSystemActivationContext();
195 | };
196 |
197 | // =================
198 |
199 | class ImageScanEngine : public System::Wow64NoFsRedirection
200 | {
201 | private:
202 |
203 | bool _unwindImports;
204 | bool _scanDelayLoad;
205 | bool _checkAccessible;
206 |
207 | KnownDlls _knownDlls;
208 |
209 | public:
210 |
211 | void SetOptionUnwindImport(bool enable);
212 | void SetOptionUnwindDelayLoadImport(bool enable);
213 | void SetOptionAccessibleOnly(bool enable);
214 |
215 | void Scan(std::wstring& imagePath, System::EnvironmentVariables& envVars, System::TokenAccessChecker& access);
216 |
217 | private:
218 |
219 | void ScanModule(ImageScanContext& context, std::wstring& dllName, ImageScanOrder& order);
220 | void ScanImports(System::ImageMapping& module, ImageScanContext& context, ImageScanOrder& order);
221 | void ScanImports(const PEParser::ImagePtr& image, ImageScanContext& context, ImageScanOrder& order);
222 | void PerformExistingModuleAction(ImageScanContext& context, std::wstring& dllName, ImageDirectory& dir, ImageScanOrder& order);
223 | void PerformNotExistingModuleAction(ImageScanContext& context, std::wstring& dllName, ImageDirectory& dir, ImageScanOrder& order);
224 | void PerformSxSModuleAction(ImageScanContext& context, std::wstring& dllName, std::wstring& sxsDir, ImageScanOrder& order);
225 |
226 | std::vector CollectVulnerableDirs(const ImageDirectory& last, ImageScanOrder& order);
227 |
228 | static bool IsFileWritable(const std::wstring& path, const System::TokenAccessChecker& access);
229 | static bool IsDirectoryWritable(const std::wstring& path, const System::TokenAccessChecker& access);
230 |
231 | protected:
232 |
233 | virtual void NotifyLoadImageOrder(LoadImageOrder& dir);
234 | virtual void NotifyVulnerableDll(ImageDirectory& dir, std::wstring& dll, bool writtable, std::vector& vulnDirs);
235 | virtual void NotifyVulnerableSxSDll(ImageDirectory& dir, std::wstring& dll, bool writtable);
236 | };
237 | };
238 |
--------------------------------------------------------------------------------
/hijacken/Commands.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Utils.h"
4 | #include "System.h"
5 | #include "ProcessScan.h"
6 | #include "ImageScan.h"
7 | #include
8 |
9 | namespace Commands
10 | {
11 | // =================
12 |
13 | class ICommand
14 | {
15 | public:
16 | virtual ~ICommand() {}
17 |
18 | virtual void LoadArgs(Utils::Arguments& args) = 0;
19 | virtual void Perform() = 0;
20 | };
21 |
22 | typedef std::shared_ptr CommandPtr;
23 |
24 | // =================
25 |
26 | class ImpersonationOptions
27 | {
28 | private:
29 | DWORD _tokenSourceProcessId;
30 | bool _changeIntegrityLevel;
31 | System::IntegrityLevel _tokenIntegrityLevel;
32 |
33 | protected:
34 | ImpersonationOptions();
35 |
36 | void LoadArgs(Utils::Arguments& args);
37 | System::ImpersonateTokenPtr CraftToken();
38 |
39 | static void PrintTokenInformation(System::ImpersonateTokenPtr& token);
40 | static const wchar_t* ConvertIntegrityLevelToString(System::IntegrityLevel level);
41 |
42 | private:
43 | void ChangeIntegrity(System::ImpersonateTokenPtr& token, System::IntegrityLevel level);
44 | static System::IntegrityLevel ConvertStrToIntegrityLevel(std::wstring& level);
45 | };
46 |
47 | // =================
48 |
49 | class SystemOptions
50 | {
51 | private:
52 | bool _scanElevated;
53 |
54 | protected:
55 | SystemOptions();
56 |
57 | void LoadArgs(Utils::Arguments& args);
58 | bool ShouldScanProcess(System::ImpersonateTokenPtr& token, DWORD targetProcessId);
59 | };
60 |
61 | // =================
62 |
63 | class EnvironmentOptions
64 | {
65 | private:
66 | enum class EnvironmentSource
67 | {
68 | System,
69 | User,
70 | Process,
71 | Inherit,
72 | Off
73 | };
74 |
75 | EnvironmentSource _envSource;
76 | DWORD _sourceProcessId;
77 |
78 | protected:
79 | EnvironmentOptions();
80 |
81 | void LoadArgs(Utils::Arguments& args);
82 |
83 | System::EnvironmentVariablesPtr GetEnvironment();
84 | };
85 |
86 | // =================
87 |
88 | class ScanFile :
89 | public ICommand,
90 | protected ImpersonationOptions,
91 | protected EnvironmentOptions,
92 | protected Engine::ImageScanEngine
93 | {
94 | private:
95 | bool _unwindImports;
96 | bool _scanDelayLoad;
97 | bool _checkAccess;
98 |
99 | bool _firstFound;
100 |
101 | std::wstring _filePath;
102 |
103 | void ScanImage(std::string path);
104 |
105 | public:
106 | ScanFile();
107 | virtual ~ScanFile() {}
108 |
109 | void LoadArgs(Utils::Arguments& args) override;
110 | void Perform() override;
111 |
112 | protected:
113 | void NotifyLoadImageOrder(Engine::LoadImageOrder& dirs) override;
114 | void NotifyVulnerableDll(Engine::ImageDirectory& dir, std::wstring& dll, bool writtable, std::vector& vulnDirs) override;
115 | void NotifyVulnerableSxSDll(Engine::ImageDirectory& dir, std::wstring& dll, bool writtable) override;
116 |
117 | public:
118 | static const wchar_t* ConvertImageDirTypeToString(Engine::ImageDirectory::Type type);
119 | static const wchar_t* ConvertImageDirStateToString(const Engine::ImageDirectory& dir);
120 | };
121 |
122 | // =================
123 |
124 | class ScanDirectory :
125 | public ICommand,
126 | protected SystemOptions
127 | {
128 | private:
129 |
130 | public:
131 | ScanDirectory();
132 | virtual ~ScanDirectory() {}
133 |
134 | void LoadArgs(Utils::Arguments& args) override;
135 | void Perform() override;
136 | };
137 |
138 | // =================
139 |
140 | class ScanProcess :
141 | public ICommand,
142 | protected ImpersonationOptions,
143 | protected Engine::ProcessScanEngine
144 | {
145 | private:
146 | DWORD _targetProcessId;
147 |
148 | std::map> _detectedDirs;
149 | std::map> _detectedFiles;
150 |
151 | public:
152 | ScanProcess();
153 | virtual ~ScanProcess() {}
154 |
155 | void LoadArgs(Utils::Arguments& args) override;
156 | void Perform() override;
157 |
158 | protected:
159 | void NotifyWritableDirectory(DetectionDirType detection, std::wstring& dirPath) override;
160 | void NotifyWritableFile(DetectionFileType detection, std::wstring& filePath) override;
161 | };
162 |
163 | // =================
164 |
165 | class ScanProcesses :
166 | public ICommand,
167 | protected SystemOptions,
168 | protected ImpersonationOptions,
169 | protected Engine::ProcessScanEngine
170 | {
171 | private:
172 |
173 | std::map> _detectedDirs;
174 | std::map> _detectedFiles;
175 |
176 | public:
177 | ScanProcesses();
178 | virtual ~ScanProcesses() {}
179 |
180 | void LoadArgs(Utils::Arguments& args) override;
181 | void Perform() override;
182 |
183 | protected:
184 | void NotifyWritableDirectory(DetectionDirType detection, std::wstring& dirPath) override;
185 | void NotifyWritableFile(DetectionFileType detection, std::wstring& filePath) override;
186 | };
187 |
188 | // =================
189 |
190 | class ScanAutorun :
191 | public ICommand,
192 | protected SystemOptions
193 | {
194 | private:
195 |
196 | public:
197 | ScanAutorun();
198 | virtual ~ScanAutorun() {}
199 |
200 | void LoadArgs(Utils::Arguments& args) override;
201 | void Perform() override;
202 | };
203 |
204 | // =================
205 |
206 | class ScanTask : public ICommand
207 | {
208 | private:
209 |
210 | public:
211 | ScanTask();
212 | virtual ~ScanTask() {}
213 |
214 | void LoadArgs(Utils::Arguments& args) override;
215 | void Perform() override;
216 | };
217 |
218 | // =================
219 |
220 | class ScanTasks :
221 | public ICommand,
222 | protected SystemOptions
223 | {
224 | private:
225 |
226 | public:
227 | ScanTasks();
228 | virtual ~ScanTasks() {}
229 |
230 | void LoadArgs(Utils::Arguments& args) override;
231 | void Perform() override;
232 | };
233 |
234 | // =================
235 |
236 | class ScanService : public ICommand
237 | {
238 | private:
239 |
240 | public:
241 | ScanService();
242 | virtual ~ScanService() {}
243 |
244 | void LoadArgs(Utils::Arguments& args) override;
245 | void Perform() override;
246 | };
247 |
248 | // =================
249 |
250 | class ScanServices :
251 | public ICommand,
252 | protected SystemOptions
253 | {
254 | private:
255 |
256 | public:
257 | ScanServices();
258 | virtual ~ScanServices() {}
259 |
260 | void LoadArgs(Utils::Arguments& args) override;
261 | void Perform() override;
262 | };
263 |
264 | // =================
265 |
266 | class ScanSystem : public ICommand
267 | {
268 | private:
269 |
270 | public:
271 | ScanSystem();
272 | virtual ~ScanSystem() {}
273 |
274 | void LoadArgs(Utils::Arguments& args) override;
275 | void Perform() override;
276 | };
277 |
278 | // =================
279 |
280 | class MakeDll : public ICommand
281 | {
282 | private:
283 |
284 | public:
285 | MakeDll();
286 | virtual ~MakeDll() {}
287 |
288 | void LoadArgs(Utils::Arguments& args) override;
289 | void Perform() override;
290 | };
291 | };
292 |
--------------------------------------------------------------------------------
/hijacken/hijacken.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Debug
10 | x64
11 |
12 |
13 | Release
14 | Win32
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | {D37B1B81-F34C-4977-B350-6242F2F46468}
23 | Win32Proj
24 | hijacken
25 |
26 |
27 |
28 | Application
29 | true
30 | v120
31 | Unicode
32 |
33 |
34 | Application
35 | true
36 | v120
37 | Unicode
38 |
39 |
40 | Application
41 | false
42 | v120
43 | true
44 | Unicode
45 |
46 |
47 | Application
48 | false
49 | v120
50 | true
51 | Unicode
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | true
71 | ntlib\include;$(IncludePath)
72 | ntlib\library\x86;$(LibraryPath)
73 |
74 |
75 | true
76 | ntlib\include\;$(IncludePath)
77 | ntlib\library\x64;$(LibraryPath)
78 |
79 |
80 | false
81 | ntlib\include;$(IncludePath)
82 | ntlib\library\x86;$(LibraryPath)
83 |
84 |
85 | false
86 | ntlib\include\;$(IncludePath)
87 | ntlib\library\x64;$(LibraryPath)
88 |
89 |
90 |
91 |
92 |
93 | Level3
94 | Disabled
95 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
96 |
97 |
98 | Console
99 | true
100 | ntlib.lib;%(AdditionalDependencies)
101 |
102 |
103 |
104 |
105 |
106 |
107 | Level3
108 | Disabled
109 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
110 |
111 |
112 | Console
113 | true
114 | ntlib.lib;%(AdditionalDependencies)
115 |
116 |
117 |
118 |
119 | Level3
120 |
121 |
122 | MaxSpeed
123 | true
124 | true
125 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
126 |
127 |
128 | Console
129 | true
130 | true
131 | true
132 | ntlib.lib;%(AdditionalDependencies)
133 |
134 |
135 |
136 |
137 | Level3
138 |
139 |
140 | MaxSpeed
141 | true
142 | true
143 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
144 |
145 |
146 | Console
147 | true
148 | true
149 | true
150 | ntlib.lib;%(AdditionalDependencies)
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
--------------------------------------------------------------------------------
/hijacken/System.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Utils.h"
4 | #include
5 | #include