-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit d937f5a
Showing
17 changed files
with
1,905 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
.vs | ||
*.vcxproj.user |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// (C) Stormshield 2020 | ||
// Licensed under the Apache license, version 2.0 | ||
// See LICENSE.txt for details | ||
|
||
#include <windows.h> | ||
#include "Constants.h" | ||
#include "CommonFunctions.h" | ||
#include <vector> | ||
#include <iostream> | ||
#include <iomanip> | ||
|
||
void DeleteHiveLogFiles | ||
( | ||
_In_ const std::wstring &HiveFilePath | ||
) | ||
{ | ||
for (auto& Ext : Constants::Hives::LogFileExtensions) | ||
{ | ||
std::wstring LogFilePath = HiveFilePath + Ext; | ||
DWORD Attributes = GetFileAttributesW(LogFilePath.c_str()); | ||
if (Attributes != INVALID_FILE_ATTRIBUTES) | ||
{ | ||
Attributes &= ~FILE_ATTRIBUTE_HIDDEN; | ||
Attributes &= ~FILE_ATTRIBUTE_SYSTEM; | ||
SetFileAttributesW(LogFilePath.c_str(), Attributes); | ||
DeleteFileW(LogFilePath.c_str()); | ||
} | ||
} | ||
} | ||
|
||
void ReportError | ||
( | ||
_In_ const HRESULT ErrorCode, | ||
_In_ const std::wstring& Context | ||
) | ||
{ | ||
LPWSTR MessageBuffer = NULL; | ||
DWORD FmtResult = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | | ||
FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK, | ||
NULL, ErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | ||
(LPWSTR)&MessageBuffer, 0, NULL); | ||
|
||
if (!Context.empty()) | ||
{ | ||
std::wcerr << Context << L":" << std::endl; | ||
} | ||
|
||
if (FmtResult == 0) | ||
{ | ||
std::wcerr << L"ERROR " << std::hex << std::setw(8) << ErrorCode << L" (could not format message)"; | ||
} | ||
else | ||
{ | ||
std::wcerr << L"ERROR " << std::hex << std::setw(8) << ErrorCode << L" (" << MessageBuffer << L")"; | ||
LocalFree((PVOID)MessageBuffer); | ||
MessageBuffer = NULL; | ||
} | ||
|
||
std::wcerr << std::endl << std::endl; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// (C) Stormshield 2020 | ||
// Licensed under the Apache license, version 2.0 | ||
// See LICENSE.txt for details | ||
|
||
#pragma once | ||
#include <string> | ||
|
||
/// @brief Delete .LOG1 and .LOG2 system files that were created when loading an application hive | ||
/// @param[in] HiveFilePath Path to the hive file | ||
void DeleteHiveLogFiles | ||
( | ||
_In_ const std::wstring &HiveFilePath | ||
); | ||
|
||
/// @brief Report an error | ||
/// @param[in] ErrorCode HRESULT value | ||
/// @param[in] Context Optional context | ||
void ReportError | ||
( | ||
_In_ const HRESULT ErrorCode, | ||
_In_ const std::wstring& Context = std::wstring{} | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
// (C) Stormshield 2020 | ||
// Licensed under the Apache license, version 2.0 | ||
// See LICENSE.txt for details | ||
|
||
#pragma once | ||
#include <windows.h> | ||
#include <vector> | ||
#include <string> | ||
|
||
/// Program constants | ||
namespace Constants { | ||
|
||
/// Command-line constants | ||
namespace Program { | ||
/// Switch for converting a hive to a .reg file | ||
static const std::wstring HiveToRegFileSwitch { L"--hive-to-reg-file" }; | ||
|
||
/// Switch for converting a .reg file to a hive | ||
static const std::wstring RegFileToHiveSwitch { L"--reg-file-to-hive" }; | ||
}; | ||
|
||
/// Program defaults | ||
namespace Defaults { | ||
/// Default Root registry path in generated .reg files | ||
static const std::wstring ExportKeyPath { L"(HiveRoot)" }; | ||
}; | ||
|
||
/// Hive-specific constants | ||
namespace Hives { | ||
/// Extensions of extra files that are generated when manipulating registry hives | ||
static const std::vector<std::wstring> LogFileExtensions{ L".LOG1", L".LOG2" }; | ||
}; | ||
|
||
/// .reg file-specific constants | ||
namespace RegFiles { | ||
/// New lines used in .reg files | ||
static const std::wstring NewLines { L"\r\n" }; | ||
|
||
/// Preamble found in .reg files | ||
static const std::wstring Preamble { L"\ufeff" // Byte Order Mark | ||
L"Windows Registry Editor Version 5.00\r\n" | ||
L"\r\n" }; | ||
|
||
/// Character used at start of line beginning a registry key path | ||
static const WCHAR KeyOpening { L'[' }; | ||
|
||
/// Character delimiting parent key from its child in a registry path | ||
static const WCHAR PathSeparator { L'\\' }; | ||
|
||
/// Character used at end of line closing a registry key path | ||
static const WCHAR KeyClosing { L']' }; | ||
|
||
/// Character used for default registry values | ||
static const WCHAR DefaultValue { L'@' }; | ||
|
||
/// Character used for separating value declaration from its content | ||
static const WCHAR ValueNameSeparator { L'=' }; | ||
|
||
/// Sequence used for describing a DWORD rendition | ||
static const std::wstring DwordPrefix { L"dword:" }; | ||
|
||
/// Sequence used for describing a hexadecimal rendition | ||
static const std::wstring HexPrefix { L"hex" }; | ||
|
||
/// Character used when beginning the value type for a hexadecimal rendition | ||
static const WCHAR HexTypeSpecOpening { L'(' }; | ||
|
||
/// Character used when ending the value type for a hexadecimal rendition | ||
static const WCHAR HexTypeSpecClosing { L')' }; | ||
|
||
/// Character at the beginning of the hexadecimal rendition | ||
static const WCHAR HexSuffix { L':' }; | ||
|
||
/// Byte separator in hexadecimal renditions | ||
static const WCHAR HexByteSeparator { L',' }; | ||
|
||
/// Desired maximal line length when dumping hexadecimal rendition of registry values | ||
static const SIZE_T HexWrappingLimit = 80u; | ||
|
||
/// Count of leading spaces when wrapping a hexadecimal rendition | ||
static const SIZE_T HexNewLineLeadingSpaces = 2u; | ||
|
||
/// Sequence used when continuing a hexadecimal rendition on a new line | ||
static const std::wstring HexByteNewLine { L"\\\r\n\u0020\u0020" }; | ||
}; | ||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// (C) Stormshield 2020 | ||
// Licensed under the Apache license, version 2.0 | ||
// See LICENSE.txt for details | ||
|
||
#pragma once | ||
|
||
#include <Windows.h> | ||
#include <string> | ||
#include <vector> | ||
|
||
/// Internal representation of a registry value. | ||
struct RegistryValue { | ||
/// Name of the registry value. May not contain null character | ||
std::wstring Name; | ||
|
||
/// Type of the registry value. Usually a small number. | ||
DWORD Type; | ||
|
||
/// Binary representation of the underlying data as a byte buffer. | ||
std::vector<BYTE> BinaryValue; | ||
}; | ||
|
||
/// Internal representation of a registry key. | ||
struct RegistryKey { | ||
/// Name of the registry key. May contain any character except backslash | ||
std::wstring Name; | ||
|
||
/// Container of subkeys | ||
std::vector<RegistryKey> Subkeys; | ||
|
||
/// Container of values | ||
std::vector<RegistryValue> Values; | ||
}; | ||
|
||
/// @brief Create an internal representation of a registry key from a registry hive (binary) file | ||
/// @param[in] HiveFilePath Path to the registry hive | ||
/// @param[in] RootName Path to the root key for export | ||
/// @param[out] RegKey Internal structure | ||
/// @return HRESULT semantics | ||
/// @note For the moment, system files that are created (.LOG1, .LOG2) are not cleaned up. | ||
_Must_inspect_result_ | ||
HRESULT HiveToInternal | ||
( | ||
_In_ const std::wstring &HiveFilePath, | ||
_In_ const std::wstring &RootName, | ||
_Out_ RegistryKey& RegKey | ||
); | ||
|
||
/// @brief Create a .reg file from the internal representation of a registry key | ||
/// @param[in] RegKey Representation of the registry key | ||
/// @param[in] OutputFilePath Path of the desired output file | ||
/// @return HRESULT semantics | ||
/// @note #OutputFilePath is overwritten if it already exists | ||
_Must_inspect_result_ | ||
HRESULT InternalToRegfile | ||
( | ||
_In_ const RegistryKey& RegKey, | ||
_In_ const std::wstring &OutputFilePath | ||
); | ||
|
||
/// @brief Create a hive file from the internal representation of a registry key | ||
/// @param[in] RegKey Representation of the registry key | ||
/// @param[in] OutputFilePath Path of the desired output file | ||
/// @return HRESULT semantics | ||
/// @note #OutputFilePath is overwritten if it already exists | ||
_Must_inspect_result_ | ||
HRESULT InternalToHive | ||
( | ||
_In_ const RegistryKey& RegKey, | ||
_In_ const std::wstring &OutputFilePath | ||
); | ||
|
||
/// @brief Create an internal representation of a registry key from a registry .reg (text) file | ||
/// @param[in] RegFilePath Path to the registry .reg file | ||
/// @param[out] RegKey Internal structure | ||
/// @return HRESULT semantics | ||
_Must_inspect_result_ | ||
HRESULT RegfileToInternal | ||
( | ||
_In_ const std::wstring& RegFilePath, | ||
_Out_ RegistryKey& RegKey | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// (C) Stormshield 2020 | ||
// Licensed under the Apache license, version 2.0 | ||
// See LICENSE.txt for details | ||
|
||
#include <windows.h> | ||
#include <iostream> | ||
#include "Conversions.h" | ||
#include "CommonFunctions.h" | ||
#include "Constants.h" | ||
|
||
/// @brief Program entry point | ||
/// @param[in] Argc Command line token count, including program name | ||
/// @param[in] Argv Tokens of the command line (#Argc valid entries) | ||
/// @retval EXIT_SUCCESS Program execution successful | ||
/// @retval EXIT_FAILURE Program execution failed | ||
int wmain( | ||
INT CONST Argc, | ||
LPCWSTR CONST* CONST Argv | ||
) | ||
{ | ||
HRESULT Result = E_FAIL; | ||
|
||
RegistryKey InternalStruct; | ||
|
||
auto Usage = [&]() | ||
{ | ||
std::wcerr << L"Usage: " << std::endl << | ||
L"\t" << Argv[0] << L" " << Constants::Program::HiveToRegFileSwitch << L" <HiveFile> <RegFile>" << std::endl << | ||
L"\t" << Argv[0] << L" " << Constants::Program::RegFileToHiveSwitch << L" <RegFile> <HiveFile>" << std::endl << | ||
std::endl; | ||
}; | ||
|
||
if (Argc <= 1) | ||
{ | ||
Usage(); | ||
Result = S_OK; | ||
goto Cleanup; | ||
} | ||
|
||
if (Constants::Program::HiveToRegFileSwitch == Argv[1]) | ||
{ | ||
if (Argc != 4) | ||
{ | ||
Usage(); | ||
Result = E_INVALIDARG; | ||
goto Cleanup; | ||
} | ||
|
||
const std::wstring HivePath { Argv[2] }; | ||
const std::wstring RegPath { Argv[3] }; | ||
|
||
Result = HiveToInternal(HivePath, Constants::Defaults::ExportKeyPath, InternalStruct); | ||
if (FAILED(Result)) | ||
{ | ||
goto Cleanup; | ||
} | ||
|
||
Result = InternalToRegfile(InternalStruct, RegPath); | ||
if (FAILED(Result)) | ||
{ | ||
goto Cleanup; | ||
} | ||
} | ||
else if (Constants::Program::RegFileToHiveSwitch == Argv[1]) | ||
{ | ||
if (Argc != 4) | ||
{ | ||
Usage(); | ||
Result = E_INVALIDARG; | ||
goto Cleanup; | ||
} | ||
|
||
const std::wstring RegPath { Argv[2] }; | ||
const std::wstring HivePath { Argv[3] }; | ||
|
||
Result = RegfileToInternal(RegPath, InternalStruct); | ||
if (FAILED(Result)) | ||
{ | ||
ReportError(Result, L"Serializing registry file" + RegPath); | ||
goto Cleanup; | ||
} | ||
|
||
Result = InternalToHive(InternalStruct, HivePath); | ||
if (FAILED(Result)) | ||
{ | ||
ReportError(Result, L"Writing hive file " + HivePath); | ||
goto Cleanup; | ||
} | ||
} | ||
else | ||
{ | ||
Usage(); | ||
Result = E_INVALIDARG; | ||
goto Cleanup; | ||
} | ||
|
||
Result = S_OK; | ||
|
||
Cleanup: | ||
return FAILED(Result) ? EXIT_FAILURE : EXIT_SUCCESS; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio Version 16 | ||
VisualStudioVersion = 16.0.29609.76 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HiveSwarming", "HiveSwarming.vcxproj", "{00DC3B6B-A592-4736-9CA9-130E4DF06CD4}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|x64 = Debug|x64 | ||
Debug|x86 = Debug|x86 | ||
Release|x64 = Release|x64 | ||
Release|x86 = Release|x86 | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{00DC3B6B-A592-4736-9CA9-130E4DF06CD4}.Debug|x64.ActiveCfg = Debug|x64 | ||
{00DC3B6B-A592-4736-9CA9-130E4DF06CD4}.Debug|x64.Build.0 = Debug|x64 | ||
{00DC3B6B-A592-4736-9CA9-130E4DF06CD4}.Debug|x86.ActiveCfg = Debug|Win32 | ||
{00DC3B6B-A592-4736-9CA9-130E4DF06CD4}.Debug|x86.Build.0 = Debug|Win32 | ||
{00DC3B6B-A592-4736-9CA9-130E4DF06CD4}.Release|x64.ActiveCfg = Release|x64 | ||
{00DC3B6B-A592-4736-9CA9-130E4DF06CD4}.Release|x64.Build.0 = Release|x64 | ||
{00DC3B6B-A592-4736-9CA9-130E4DF06CD4}.Release|x86.ActiveCfg = Release|Win32 | ||
{00DC3B6B-A592-4736-9CA9-130E4DF06CD4}.Release|x86.Build.0 = Release|Win32 | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
GlobalSection(ExtensibilityGlobals) = postSolution | ||
SolutionGuid = {FD1888F9-D331-4CD9-A58D-0C0F01F6735B} | ||
EndGlobalSection | ||
EndGlobal |
Oops, something went wrong.