diff --git a/makefile b/makefile index ee116a5..1451c36 100644 --- a/makefile +++ b/makefile @@ -4,7 +4,7 @@ PROGRAM_DIR = $(PROJECT_DIR)/programs BIN_DIR = $(PROJECT_DIR)/bin LIBS = libpolarssl liblz4 libfnd libes libpki libhac libhac-hb -PROGS = nstool +PROGS = nstool hexdmp main: build diff --git a/programs/hexdmp/makefile b/programs/hexdmp/makefile new file mode 100644 index 0000000..d73e3b4 --- /dev/null +++ b/programs/hexdmp/makefile @@ -0,0 +1,48 @@ +# Sources +SRC_DIR = source +OBJS = $(foreach dir,$(SRC_DIR),$(subst .cpp,.o,$(wildcard $(dir)/*.cpp))) $(foreach dir,$(SRC_DIR),$(subst .c,.o,$(wildcard $(dir)/*.c))) + +# External dependencies +DEPENDS = hac-hb hac es pki fnd polarssl lz4 +LIB_DIR = ../../lib +LIBS = $(foreach dep,$(DEPENDS), -L"$(LIB_DIR)/lib$(dep)" -l$(dep)) +INCS = $(foreach dep,$(DEPENDS), -I"$(LIB_DIR)/lib$(dep)/include") + +# Compiler Settings +CXXFLAGS = -std=c++11 $(INCS) -D__STDC_FORMAT_MACROS -Wall -Wno-unused-value +CFLAGS = -std=c11 $(INCS) -Wall -Wno-unused-value +ifeq ($(OS),Windows_NT) + # Windows Only Flags/Libs + CC = x86_64-w64-mingw32-gcc + CXX = x86_64-w64-mingw32-g++ + CFLAGS += -Wno-unused-but-set-variable + CXXFLAGS += -Wno-unused-but-set-variable + LIBS += -static +else + UNAME = $(shell uname -s) + ifeq ($(UNAME), Darwin) + # MacOS Only Flags/Libs + CFLAGS += -Wno-unused-private-field + CXXFLAGS += -Wno-unused-private-field + LIBS += + else + # *nix Only Flags/Libs + CFLAGS += -Wno-unused-but-set-variable + CXXFLAGS += -Wno-unused-but-set-variable + LIBS += + endif +endif + +BIN_DIR = bin +OUTPUT = $(BIN_DIR)/$(shell basename $(CURDIR)) + +all: build + +rebuild: clean build + +build: $(OBJS) + mkdir -p $(BIN_DIR) + $(CXX) $(OBJS) $(LIBS) -o $(OUTPUT) + +clean: + rm -rf $(OBJS) $(OUTPUT) $(BIN_DIR) \ No newline at end of file diff --git a/programs/hexdmp/source/HexDumpProcess.cpp b/programs/hexdmp/source/HexDumpProcess.cpp new file mode 100644 index 0000000..e26f8cd --- /dev/null +++ b/programs/hexdmp/source/HexDumpProcess.cpp @@ -0,0 +1,128 @@ +#include "HexDumpProcess.h" +#include +#include +#include + +HexDumpProcess::HexDumpProcess(): + mFile(), + mCliOutputMode(_BIT(OUTPUT_BASIC)), + mShowAsciiRepresentation(true), + mShowOffset(true) +{ + +} + +void HexDumpProcess::process() +{ + if (*mFile == nullptr) + { + throw fnd::Exception(kModuleName, "No file reader set."); + } + + mCache.alloc(kCacheSize); + + size_t offset, size, byte_grouping, row_len, row_num; + + if (mReadOffset.isSet) + offset = *mReadOffset; + else + offset = 0; + + if (mReadSize.isSet) + size = *mReadSize; + else + size = _MIN(kDefaultReadLen, (*mFile)->size()); + + if (mByteGroupingSize.isSet) + byte_grouping = *mByteGroupingSize; + else + byte_grouping = kDefaultByteGrouping; + + row_len = kDefaultRowLen; + + row_num = size / row_len + ((size % row_len) != 0); + + (*mFile)->read(mCache.data(), mCache.size()); + + for (size_t i = 0; i < row_num; i++) + { + size_t print_len = _MIN(row_len, size - row_len*i); + + printRow(mCache.data() + (i * row_len), offset + (i * row_len), row_len, print_len, byte_grouping); + } + +} + +void HexDumpProcess::setInputFile(const fnd::SharedPtr& file) +{ + mFile = file; +} + +void HexDumpProcess::setCliOutputMode(CliOutputMode type) +{ + mCliOutputMode = type; +} + +void HexDumpProcess::setShowAsciiRepresentation(bool enable) +{ + mShowAsciiRepresentation = enable; +} + +void HexDumpProcess::setShowOffset(bool enable) +{ + mShowOffset = enable; +} + +void HexDumpProcess::setByteGroupingSize(const sOptional& var) +{ + mByteGroupingSize = var; +} + +void HexDumpProcess::setReadOffset(const sOptional& var) +{ + mReadOffset = var; +} + +void HexDumpProcess::setReadSize(const sOptional& var) +{ + mReadSize = var; +} + +void HexDumpProcess::printRow(const byte_t* data_row, size_t offset, size_t row_len, size_t print_len, size_t byte_grouping) const +{ + if (mShowOffset) + { + std::cout << std::hex << std::setw(8) << std::setfill('0') << offset << " "; + std::cout << "| "; + } + + for (size_t i = 0; i < row_len; i++) + { + if (i < print_len) + std::cout << std::hex << std::setw(2) << std::setfill('0') << (uint32_t)data_row[i]; + else + std::cout << " "; + + if ((i+1) % byte_grouping == 0 || i+1 == row_len) + std::cout << " "; + } + + if (mShowAsciiRepresentation) + { + std::cout << "| "; + for (size_t i = 0; i < row_len; i++) + { + if (i < print_len) + { + if (isprint((char)data_row[i])) + std::cout << (char)data_row[i]; + else + std::cout << "."; + } + else + std::cout << " "; + } + } + + std::cout << std::endl; +} \ No newline at end of file diff --git a/programs/hexdmp/source/HexDumpProcess.h b/programs/hexdmp/source/HexDumpProcess.h new file mode 100644 index 0000000..7ebb673 --- /dev/null +++ b/programs/hexdmp/source/HexDumpProcess.h @@ -0,0 +1,45 @@ +#pragma once +#include +#include +#include +#include +#include + +#include "common.h" + +class HexDumpProcess +{ +public: + HexDumpProcess(); + + void process(); + + void setInputFile(const fnd::SharedPtr& file); + void setCliOutputMode(CliOutputMode type); + + void setShowAsciiRepresentation(bool enable); + void setShowOffset(bool enable); + void setByteGroupingSize(const sOptional& var); + void setReadOffset(const sOptional& var); + void setReadSize(const sOptional& var); + +private: + const std::string kModuleName = "HexDumpProcess"; + static const size_t kDefaultRowLen = 0x10; + static const size_t kDefaultReadLen = 0x1000; + static const size_t kDefaultByteGrouping = 0x1; + static const size_t kCacheSize = 0x40000; + + fnd::SharedPtr mFile; + CliOutputMode mCliOutputMode; + + bool mShowAsciiRepresentation; + bool mShowOffset; + sOptional mByteGroupingSize; + sOptional mReadOffset; + sOptional mReadSize; + + fnd::Vec mCache; + + void printRow(const byte_t* data_row, size_t offset, size_t row_len, size_t print_len, size_t byte_grouping) const; +}; \ No newline at end of file diff --git a/programs/hexdmp/source/UserSettings.cpp b/programs/hexdmp/source/UserSettings.cpp new file mode 100644 index 0000000..d94adbf --- /dev/null +++ b/programs/hexdmp/source/UserSettings.cpp @@ -0,0 +1,205 @@ +#include "UserSettings.h" +#include "version.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +UserSettings::UserSettings() +{} + +void UserSettings::parseCmdArgs(const std::vector& arg_list) +{ + sCmdArgs args; + populateCmdArgs(arg_list, args); + populateUserSettings(args); +} + +void UserSettings::showHelp() +{ + printf("%s v%d.%d.%d (C) %s\n", APP_NAME, VER_MAJOR, VER_MINOR, VER_PATCH, AUTHORS); + printf("Built: %s %s\n\n", __TIME__, __DATE__); + + printf("Usage: %s [options... ] \n", BIN_NAME); + printf("\n General Options:\n"); + //printf(" -t, --type Specify input file type. [raw]\n"); + printf(" -a, --showascii Show data as ASCII.\n"); + printf(" -p, --showoffset Show data offset.\n"); + printf(" -v, --verbose Verbose output.\n"); + printf(" -g, --grouping Specify byte grouping size (default 1).\n"); + printf(" -o, --read-offset Specify read offset (default 0).\n"); + printf(" -s, --read-size Specify read size (default 0x200).\n"); +} + +const std::string UserSettings::getInputPath() const +{ + return mInputPath; +} + +FileType UserSettings::getFileType() const +{ + return mFileType; +} + +CliOutputMode UserSettings::getCliOutputMode() const +{ + return mOutputMode; +} + +bool UserSettings::isShowAsciiRepresentation() const +{ + return mShowAsciiRepresentation; +} + +bool UserSettings::isShowOffset() const +{ + return mShowOffset; +} + +const sOptional& UserSettings::getByteGroupingSize() const +{ + return mByteGroupingSize; +} + +const sOptional& UserSettings::getReadOffset() const +{ + return mReadOffset; +} + +const sOptional& UserSettings::getReadSize() const +{ + return mReadSize; +} + +void UserSettings::populateCmdArgs(const std::vector& arg_list, sCmdArgs& cmd_args) +{ + // show help text + if (arg_list.size() < 2) + { + showHelp(); + throw fnd::Exception(kModuleName, "Not enough arguments."); + } + + cmd_args.input_path = arg_list.back(); + + for (size_t i = 1; i < arg_list.size(); i++) + { + if (arg_list[i] == "-h" || arg_list[i] == "--help") + { + showHelp(); + throw fnd::Exception(kModuleName, "Nothing to do."); + } + } + + for (size_t i = 1; i+1 < arg_list.size(); i++) + { + bool hasParamter = arg_list[i+1][0] != '-' && i+2 < arg_list.size(); + + if (arg_list[i] == "-a" || arg_list[i] == "--showascii") + { + if (hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " does not take a parameter."); + cmd_args.show_ascii = true; + } + + else if (arg_list[i] == "-p" || arg_list[i] == "--showoffset") + { + if (hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " does not take a parameter."); + cmd_args.show_offset = true; + } + + else if (arg_list[i] == "-v" || arg_list[i] == "--verbose") + { + if (hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " does not take a parameter."); + cmd_args.verbose = true; + } + + else if (arg_list[i] == "-t" || arg_list[i] == "--type") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.file_type = arg_list[i+1]; + } + + else if (arg_list[i] == "-g" || arg_list[i] == "--grouping") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.byte_grouping = arg_list[i+1]; + } + + else if (arg_list[i] == "-o" || arg_list[i] == "--read-offset") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.read_offset = arg_list[i+1]; + } + + else if (arg_list[i] == "-s" || arg_list[i] == "--read-size") + { + if (!hasParamter) throw fnd::Exception(kModuleName, arg_list[i] + " requries a parameter."); + cmd_args.read_size = arg_list[i+1]; + } + else + { + throw fnd::Exception(kModuleName, arg_list[i] + " is not recognised."); + } + + i += hasParamter; + } +} + +void UserSettings::populateUserSettings(sCmdArgs& args) +{ + // check invalid input + if (args.input_path.isSet == false) + throw fnd::Exception(kModuleName, "No input file specified"); + + // save arguments + mInputPath = *args.input_path; + mShowAsciiRepresentation = args.show_ascii.isSet; + mShowOffset = args.show_offset.isSet; + + if (args.byte_grouping.isSet) + mByteGroupingSize = strtoul((*args.byte_grouping).c_str(), nullptr, 0); + if (args.read_offset.isSet) + mReadOffset = strtoul((*args.read_offset).c_str(), nullptr, 0); + if (args.read_size.isSet) + mReadSize = strtoul((*args.read_size).c_str(), nullptr, 0); + + // determine output mode + mOutputMode = _BIT(OUTPUT_BASIC); + if (args.verbose.isSet) + { + mOutputMode |= _BIT(OUTPUT_KEY_DATA); + mOutputMode |= _BIT(OUTPUT_LAYOUT); + mOutputMode |= _BIT(OUTPUT_EXTENDED); + } + + // determine input file type + if (args.file_type.isSet) + mFileType = getFileTypeFromString(*args.file_type); + else + mFileType = FILE_RAW; + + // check is the input file could be identified + if (mFileType == FILE_INVALID) + throw fnd::Exception(kModuleName, "Unknown file type."); +} + +FileType UserSettings::getFileTypeFromString(const std::string& type_str) +{ + std::string str = type_str; + std::transform(str.begin(), str.end(), str.begin(), ::tolower); + + FileType type; + if (str == "raw") + type = FILE_RAW; + else + type = FILE_INVALID; + + return type; +} \ No newline at end of file diff --git a/programs/hexdmp/source/UserSettings.h b/programs/hexdmp/source/UserSettings.h new file mode 100644 index 0000000..dddc46a --- /dev/null +++ b/programs/hexdmp/source/UserSettings.h @@ -0,0 +1,62 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "common.h" + +class UserSettings +{ +public: + UserSettings(); + + void parseCmdArgs(const std::vector& arg_list); + void showHelp(); + + // generic options + const std::string getInputPath() const; + FileType getFileType() const; + CliOutputMode getCliOutputMode() const; + + // toggles + bool isShowAsciiRepresentation() const; + bool isShowOffset() const; + + // parameters + const sOptional& getByteGroupingSize() const; + const sOptional& getReadOffset() const; + const sOptional& getReadSize() const; + +private: + const std::string kModuleName = "UserSettings"; + + + struct sCmdArgs + { + sCmdArgs() {} + sOptional input_path; + sOptional file_type; + sOptional show_ascii; + sOptional show_offset; + sOptional verbose; + sOptional byte_grouping; + sOptional read_offset; + sOptional read_size; + }; + + std::string mInputPath; + FileType mFileType; + CliOutputMode mOutputMode; + + bool mShowAsciiRepresentation; + bool mShowOffset; + sOptional mByteGroupingSize; + sOptional mReadOffset; + sOptional mReadSize; + + void populateCmdArgs(const std::vector& arg_list, sCmdArgs& cmd_args); + void populateUserSettings(sCmdArgs& args); + FileType getFileTypeFromString(const std::string& type_str); +}; \ No newline at end of file diff --git a/programs/hexdmp/source/common.h b/programs/hexdmp/source/common.h new file mode 100644 index 0000000..876dc41 --- /dev/null +++ b/programs/hexdmp/source/common.h @@ -0,0 +1,47 @@ +#pragma once +#include +#include +#include +#include + +enum IFileOwnershipMode +{ + SHARED_IFILE = false, + OWN_IFILE = true +}; + +enum FileType +{ + FILE_RAW, + FILE_INVALID = -1, +}; + +enum CliOutputModeFlag +{ + OUTPUT_BASIC, + OUTPUT_LAYOUT, + OUTPUT_KEY_DATA, + OUTPUT_EXTENDED +}; + +typedef byte_t CliOutputMode; + +template +struct sOptional +{ + bool isSet; + T var; + inline sOptional() : isSet(false) {} + inline sOptional(const T& other) : isSet(true), var(other) {} + inline sOptional(const sOptional& other) : isSet(other.isSet), var(other.var) {} + inline const T& operator=(const T& other) { isSet = true; var = other; return var; } + inline const sOptional& operator=(const sOptional& other) + { + isSet = other.isSet; + if (isSet) { + var = other.var; + } + return *this; + } + inline T& operator*() { return var; } +}; \ No newline at end of file diff --git a/programs/hexdmp/source/main.cpp b/programs/hexdmp/source/main.cpp new file mode 100644 index 0000000..7920505 --- /dev/null +++ b/programs/hexdmp/source/main.cpp @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include "UserSettings.h" +#include "HexDumpProcess.h" + + + + +#ifdef _WIN32 +int wmain(int argc, wchar_t** argv) +#else +int main(int argc, char** argv) +#endif +{ + std::vector args; + for (size_t i = 0; i < (size_t)argc; i++) + { +#ifdef _WIN32 + args.push_back(fnd::StringConv::ConvertChar16ToChar8(std::u16string((char16_t*)argv[i]))); +#else + args.push_back(argv[i]); +#endif + } + + UserSettings user_set; + try { + user_set.parseCmdArgs(args); + + fnd::SharedPtr inputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read)); + + if (user_set.getFileType() == FILE_RAW) + { + HexDumpProcess hexdmp; + + hexdmp.setInputFile(inputFile); + hexdmp.setCliOutputMode(user_set.getCliOutputMode()); + hexdmp.setByteGroupingSize(user_set.getByteGroupingSize()); + hexdmp.setReadOffset(user_set.getReadOffset()); + hexdmp.setReadSize(user_set.getReadSize()); + hexdmp.process(); + } + } + catch (const fnd::Exception& e) { + printf("\n\n%s\n", e.what()); + } + return 0; +} \ No newline at end of file diff --git a/programs/hexdmp/source/version.h b/programs/hexdmp/source/version.h new file mode 100644 index 0000000..0a7ceea --- /dev/null +++ b/programs/hexdmp/source/version.h @@ -0,0 +1,7 @@ +#pragma once +#define APP_NAME "HexDump" +#define BIN_NAME "hexdmp" +#define VER_MAJOR 1 +#define VER_MINOR 0 +#define VER_PATCH 0 +#define AUTHORS "jakcron" \ No newline at end of file diff --git a/programs/makensp/makefile b/programs/makensp/makefile new file mode 100644 index 0000000..75c35eb --- /dev/null +++ b/programs/makensp/makefile @@ -0,0 +1,47 @@ +# Sources +SRC_DIR = source +OBJS = $(foreach dir,$(SRC_DIR),$(subst .cpp,.o,$(wildcard $(dir)/*.cpp))) $(foreach dir,$(SRC_DIR),$(subst .c,.o,$(wildcard $(dir)/*.c))) + +# External dependencies +DEPENDS = hac-hb hac es pki fnd lz4 polarssl +LIB_DIR = ../../lib +LIBS = $(foreach dep,$(DEPENDS), -L"$(LIB_DIR)/lib$(dep)" -l$(dep)) +INCS = $(foreach dep,$(DEPENDS), -I"$(LIB_DIR)/lib$(dep)/include") + +BIN_DIR = bin +OUTPUT = $(BIN_DIR)/$(shell basename $(CURDIR)) + +# Compiler Settings +CXXFLAGS = -std=c++11 $(INCS) -D__STDC_FORMAT_MACROS -Wall -Wno-unused-value +ifeq ($(OS),Windows_NT) + # Windows Only Flags/Libs + CC = x86_64-w64-mingw32-gcc + CXX = x86_64-w64-mingw32-g++ + CFLAGS += -Wno-unused-but-set-variable + CXXFLAGS += -Wno-unused-but-set-variable + LIBS += -static +else + UNAME = $(shell uname -s) + ifeq ($(UNAME), Darwin) + # MacOS Only Flags/Libs + CFLAGS += -Wno-unused-private-field + CXXFLAGS += -Wno-unused-private-field + LIBS += + else + # *nix Only Flags/Libs + CFLAGS += -Wno-unused-but-set-variable + CXXFLAGS += -Wno-unused-but-set-variable + LIBS += + endif +endif + +all: build + +rebuild: clean build + +build: $(OBJS) + mkdir -p $(BIN_DIR) + $(CXX) $(OBJS) $(LIBS) -o $(OUTPUT) + +clean: + rm -rf $(OBJS) $(OUTPUT) $(BIN_DIR) \ No newline at end of file