// // Copyright (c) Johnny Shaw. All rights reserved. // // File: source/ProcessHerpaderping/utils.hpp // Author: Johnny Shaw // Abstract: Utility functionality for herpaderping. // #pragma once namespace Log { constexpr static uint32_t Success{ 0x00000001ul }; constexpr static uint32_t Information{ 0x00000002ul }; constexpr static uint32_t Warning{ 0x00000004ul }; constexpr static uint32_t Error{ 0x00000008ul }; constexpr static uint32_t Context{ 0x00000010ul }; constexpr static uint32_t Debug{ 0x80000000ul }; } namespace Utils { /// /// Argument parser interface. /// class IArgumentParser { public: virtual ~IArgumentParser() = default; /// /// Implements functionality for parsing arguments. /// /// /// Number of command line arguments. /// /// /// Command line arguments. /// /// /// Success if arguments were parsed successfully. Failure otherwise. /// _Must_inspect_result_ virtual HRESULT ParseArguments( _In_ int Argc, _In_reads_(Argc) const wchar_t* Argv[]) = 0; /// /// Implements retrieving the argument usage. /// /// /// Argument usage. /// virtual std::wstring_view GetUsage() const = 0; /// /// Provides the interface an opportunity to validate the parsed /// arguments. If the arguments are invalid (for example, two options /// are used that may not be specified together) the implementation /// may return failure here to indicate the arguments are invalid. /// _Must_inspect_result_ virtual HRESULT ValidateArguments() const = 0; protected: IArgumentParser() = default; }; /// /// Matches a parameter argument with either short or parameter. /// /// /// Argument to check against short or long parameter argument /// must either be prefixed explicitly as long ("--") or short ("-", "/"). /// /// /// Short parameter representation (e.g. "q"). /// /// /// Long parameter representation (e.g. "quiet"). /// /// /// Success if the argument matches either the short to long parameter. /// _Must_inspect_result_ HRESULT MatchParameter( _In_ std::wstring_view Arg, _In_opt_ std::optional Short, _In_opt_ std::optional Long); /// /// Checks for help options in parameters. /// /// /// Number of command line arguments. /// /// /// Command line arguments. /// /// /// Success if "--help", "-h", "/h", "-?", or "/?" are found in the /// command line arguments. /// _Must_inspect_result_ HRESULT CheckForHelpOptions( _In_ int Argc, _In_reads_(Argc) const wchar_t* Argv[]); /// /// Handles command line arguments for a argument parser. If a help /// option is found or the parser fails. The function prints the header /// and usage text to stdout and return failure. /// /// /// Number of command line arguments. /// /// /// Command line arguments. /// /// /// Header to print before usage. /// /// /// Argument parser to use. /// /// /// Success if the arguments were parsed successfully. Failure if the /// arguments were invalid or a help option was found. /// _Must_inspect_result_ HRESULT HandleCommandLineArgs( _In_ int Argc, _In_reads_(Argc) const wchar_t* Argv[], _In_opt_ std::optional Header, _Inout_ IArgumentParser& Parser); #pragma warning(push) #pragma warning(disable : 4634) // xmldoc: discarding XML document comment for invalid target /// /// Removes all occurrences of a set of values from an object. /// /// /// Object type to remove elements of. Must implement erase, be forward /// iterate-able, and contained value type must be move assignable. /// /// /// Object to erase elements from. /// /// /// Values to remove. /// template void EraseAll( _Inout_ T& Object, _In_ const std::initializer_list& Values) { for (const auto& value : Values) { Object.erase(std::remove(Object.begin(), Object.end(), value), Object.end()); } } #pragma warning(pop) /// /// Formats an error code as a string. /// /// /// Error code to format as a string. /// /// /// Human readable string for the error code if the error is unknown a /// string is returned formatted as "[number] - Unknown Error". /// std::wstring FormatError(_In_ uint32_t Error); /// /// Sets the logging mask. /// /// /// Logging mask to set. /// void SetLoggingMask(_In_ uint32_t Level); /// /// Logs a string. /// /// /// Logging level: Log::Success, Log::Information, Log::Warning, Log:Error. /// /// /// Format for log string. /// /// /// Variadic arguments for formatting. /// void Log( _In_ uint32_t Level, _Printf_format_string_ const wchar_t* Format, ...); /// /// Logs a string with a specified error code appended to the formatted /// string. /// /// /// Logging level: Log::Success, Log::Information, Log::Warning, Log:Error. /// /// /// Error code. /// /// /// Format for log string. /// /// /// Variadic arguments for formatting. /// /// /// Supplied Error /// uint32_t Log( _In_ uint32_t Level, _In_ uint32_t Error, _Printf_format_string_ const wchar_t* Format, ...); /// /// Generates a buffer of a given length containing a supplied pattern. /// /// /// Buffer to fill with the patter, must not be empty. /// /// /// Pattern to write into the buffer. /// /// /// Success when the buffer is filled with the pattern. Failure if Buffer /// is empty. /// _Must_inspect_result_ HRESULT FillBufferWithPattern( _Inout_ std::vector& Buffer, _In_ std::span Pattern); /// /// Generates a buffer of random bytes of a given length. /// /// /// Buffer to assign the bytes to, must not be empty. /// /// /// Success if the buffer is filled with random bytes. /// _Must_inspect_result_ HRESULT FillBufferWithRandomBytes( _Inout_ std::vector& Buffer); /// /// Gets a file size. /// /// /// File to get the size of. /// /// /// Set to the size of the file on success. /// /// /// Success if the file size of retrieved. /// _Must_inspect_result_ HRESULT GetFileSize( _In_ handle_t FileHandle, _Out_ uint64_t& FileSize); /// /// Sets a file pointer. /// /// /// File to set the pointer of. /// /// /// Distance to move the file pointer. /// /// /// Move method to use (FILE_BEGIN, FILE_CURRENT, FILE_END). /// /// /// Success if the file pointer was set (or was already set). /// _Must_inspect_result_ HRESULT SetFilePointer( _In_ handle_t FileHandle, _In_ int64_t DistanceToMove, _In_ uint32_t MoveMethod); /// /// Copies the contents for a source file to the target by handle. /// /// /// Source file handle. /// /// /// Target file handle. /// /// /// Flushes file buffers after copy, optional, defaults to true. /// /// /// Success if the source file has been copied to the target. /// _Must_inspect_result_ HRESULT CopyFileByHandle( _In_ handle_t SourceHandle, _In_ handle_t TargetHandle, _In_ bool FlushFile = true); /// /// Overwrites the contents of a file with a pattern. /// /// /// Target file to overwrite. /// /// /// Pattern write over the file content. /// /// /// Length of Pattern buffer. /// /// /// Flushes file buffers after overwrite, optional, defaults to true. /// /// /// Success if the file content was overwritten. /// _Must_inspect_result_ HRESULT OverwriteFileContentsWithPattern( _In_ handle_t FileHandle, _In_ std::span Pattern, _In_ bool FlushFile = true); /// /// Extends file to meet a new size writes a pattern to the extension. /// /// /// Target file to extend. /// /// /// New size of the file. /// /// /// Pattern to use to extend the target file with. /// /// /// Number of bytes appended. /// /// /// Flushes file buffers after extension, optional, defaults to true. /// /// /// Success if the file was extended. /// _Must_inspect_result_ HRESULT ExtendFileWithPattern( _In_ handle_t FileHandle, _In_ uint64_t NewFileSize, _In_ std::span Pattern, _Out_ uint32_t& AppendedBytes, _In_ bool FlushFile = true); /// /// Overwrites a file from a given offset with a pattern. /// /// /// Target file to overwrite. /// /// /// Offset to begin writing from. /// /// /// Pattern to use to extend the target file with. /// /// /// Number of bytes written. /// /// /// Flushes file buffers after overwrite, optional, defaults to true. /// /// /// Success if the file was overwritten. /// _Must_inspect_result_ HRESULT OverwriteFileAfterWithPattern( _In_ handle_t FileHandle, _In_ uint64_t FileOffset, _In_ std::span Pattern, _Out_ uint32_t& WrittenBytes, _In_ bool FlushFile = true); /// /// Extends a PE file security directory by a number of bytes. /// /// /// Target file handle. /// /// /// Number of bytes to extend the security directory by. /// /// /// Flushes file buffers after extension, optional, defaults to true. /// /// /// Success if the security directory was extended. Failure if the file is /// not a PE file or does not have a security directory. /// _Must_inspect_result_ HRESULT ExtendFileSecurityDirectory( _In_ handle_t FileHandle, _In_ uint32_t ExtendedBy, _In_ bool FlushFile = true); /// /// Retrieves the image entry point RVA from a file. /// /// /// File to parse for the entry point RVA. /// /// /// Set to the entry point RVA on success. /// /// /// Success if the PE image entry RVA is located. /// _Must_inspect_result_ HRESULT GetImageEntryPointRva( _In_ handle_t FileHandle, _Out_ uint32_t& EntryPointRva); /// /// Writes remote process parameters into target process. /// /// /// Process to write parameters into. /// /// /// Dll path to write into the parameters, optional. /// /// /// Image file name to write into the parameters. /// /// /// Current directory to write into the parameters, optional. /// /// /// Command line to write into the parameters, optional. /// /// /// Environment block to write into the parameters, optional. /// /// /// Window title to write into the parameters, optional. /// /// /// Desktop info to write into the parameters, optional. /// /// /// ShellInfo to write into the parameters, optional. /// /// /// Runtime data to write into the parameters, optional. /// /// /// Success if the remote process parameters are written. /// _Must_inspect_result_ HRESULT WriteRemoteProcessParameters( _In_ handle_t ProcessHandle, _In_ const std::wstring ImageFileName, _In_opt_ const std::optional& DllPath, _In_opt_ const std::optional& CurrentDirectory, _In_opt_ const std::optional& CommandLine, _In_opt_ void* EnvironmentBlock, _In_opt_ const std::optional& WindowTitle, _In_opt_ const std::optional& DesktopInfo, _In_opt_ const std::optional& ShellInfo, _In_opt_ const std::optional& RuntimeData); }