From 2d84f49c8db4473d0bf73ae425c730591e49e084 Mon Sep 17 00:00:00 2001 From: Mikhail Paulyshka Date: Sun, 7 Mar 2021 17:18:29 +0300 Subject: [PATCH] v 0.3 --- .gitignore | 4 +- Readme.md | 33 +- build.ps1 | 98 +- src_cpp/CMakeLists.txt | 94 + src_cpp/include/coff/lib_creator.h | 14 + .../include/commands/command_coff_createlib.h | 58 + src_cpp/include/commands/command_interface.h | 23 + .../include/commands/command_pdb_generate.h | 75 + src_cpp/include/commands/command_pe_exports.h | 73 + src_cpp/include/commands/command_pe_guidage.h | 49 + .../include/commands/command_pe_timestamp.h | 45 + src_cpp/include/common/guid.h | 35 + src_cpp/include/common/hex.h | 20 + src_cpp/include/data/db.h | 29 + src_cpp/include/data/export.h | 25 + src_cpp/include/data/function.h | 24 + src_cpp/include/data/general.h | 25 + src_cpp/include/data/label.h | 19 + src_cpp/include/data/name.h | 19 + src_cpp/include/data/root.h | 53 + src_cpp/include/data/segment.h | 19 + .../include/nlohmann/json.hpp | 11733 ++++++++++------ src_cpp/include/pdb/pdb_creator.h | 70 + src_cpp/include/pe/pe_file.h | 72 + src_cpp/src/coff/lib_creator.cpp | 52 + src_cpp/src/data/db.cpp | 78 + src_cpp/src/main.cpp | 90 + src_cpp/src/pdb/pdb_creator.cpp | 225 + src_cpp/src/pe/pe_file.cpp | 183 + src_pdbgen/CMakeLists.txt | 66 - src_pdbgen/guidhelper.h | 30 - src_pdbgen/hexhelper.h | 13 - src_pdbgen/idadb.cpp | 81 - src_pdbgen/idadb.h | 55 - src_pdbgen/main.cpp | 114 - src_pdbgen/pdbcreator.cpp | 230 - src_pdbgen/pdbcreator.h | 66 - src_pdbgen/pefile.cpp | 129 - src_pdbgen/pefile.h | 59 - src_pdbgen/test/test_pefile_1.cpp | 31 - src_pdbgen/test_assets/test_1.cpp | 14 - src_pdbgen/test_assets/test_1_32.exe | Bin 9728 -> 0 bytes src_pdbgen/test_assets/test_1_32.pdb | Bin 610304 -> 0 bytes src_pdbgen/test_assets/test_1_64.exe | Bin 10752 -> 0 bytes src_pdbgen/test_assets/test_1_64.pdb | Bin 593920 -> 0 bytes {src_ida => src_plugins/ida}/fakepdb.py | 25 +- .../ida}/fakepdb/__init__.py | 2 +- src_plugins/ida/fakepdb/command_dumpinfo.py | 59 + .../ida/fakepdb/command_findsignature.py | 57 + .../ida/fakepdb/command_importoffsets.py | 62 + .../ida/fakepdb/command_libgenerate.py | 81 + .../ida/fakepdb/command_pdbgenerate.py | 63 +- .../ida}/fakepdb/dumpinfo.py | 104 +- src_plugins/ida/fakepdb/native.py | 58 + .../ida/fakepdb/offsets_importer.py | 95 +- .../ida/fakepdb/signature_finder.py | 54 +- 56 files changed, 9233 insertions(+), 5652 deletions(-) create mode 100644 src_cpp/CMakeLists.txt create mode 100644 src_cpp/include/coff/lib_creator.h create mode 100644 src_cpp/include/commands/command_coff_createlib.h create mode 100644 src_cpp/include/commands/command_interface.h create mode 100644 src_cpp/include/commands/command_pdb_generate.h create mode 100644 src_cpp/include/commands/command_pe_exports.h create mode 100644 src_cpp/include/commands/command_pe_guidage.h create mode 100644 src_cpp/include/commands/command_pe_timestamp.h create mode 100644 src_cpp/include/common/guid.h create mode 100644 src_cpp/include/common/hex.h create mode 100644 src_cpp/include/data/db.h create mode 100644 src_cpp/include/data/export.h create mode 100644 src_cpp/include/data/function.h create mode 100644 src_cpp/include/data/general.h create mode 100644 src_cpp/include/data/label.h create mode 100644 src_cpp/include/data/name.h create mode 100644 src_cpp/include/data/root.h create mode 100644 src_cpp/include/data/segment.h rename {src_pdbgen => src_cpp}/include/nlohmann/json.hpp (76%) create mode 100644 src_cpp/include/pdb/pdb_creator.h create mode 100644 src_cpp/include/pe/pe_file.h create mode 100644 src_cpp/src/coff/lib_creator.cpp create mode 100644 src_cpp/src/data/db.cpp create mode 100644 src_cpp/src/main.cpp create mode 100644 src_cpp/src/pdb/pdb_creator.cpp create mode 100644 src_cpp/src/pe/pe_file.cpp delete mode 100644 src_pdbgen/CMakeLists.txt delete mode 100644 src_pdbgen/guidhelper.h delete mode 100644 src_pdbgen/hexhelper.h delete mode 100644 src_pdbgen/idadb.cpp delete mode 100644 src_pdbgen/idadb.h delete mode 100644 src_pdbgen/main.cpp delete mode 100644 src_pdbgen/pdbcreator.cpp delete mode 100644 src_pdbgen/pdbcreator.h delete mode 100644 src_pdbgen/pefile.cpp delete mode 100644 src_pdbgen/pefile.h delete mode 100644 src_pdbgen/test/test_pefile_1.cpp delete mode 100644 src_pdbgen/test_assets/test_1.cpp delete mode 100644 src_pdbgen/test_assets/test_1_32.exe delete mode 100644 src_pdbgen/test_assets/test_1_32.pdb delete mode 100644 src_pdbgen/test_assets/test_1_64.exe delete mode 100644 src_pdbgen/test_assets/test_1_64.pdb rename {src_ida => src_plugins/ida}/fakepdb.py (64%) rename {src_ida => src_plugins/ida}/fakepdb/__init__.py (93%) create mode 100644 src_plugins/ida/fakepdb/command_dumpinfo.py create mode 100644 src_plugins/ida/fakepdb/command_findsignature.py create mode 100644 src_plugins/ida/fakepdb/command_importoffsets.py create mode 100644 src_plugins/ida/fakepdb/command_libgenerate.py rename src_ida/fakepdb/generation.py => src_plugins/ida/fakepdb/command_pdbgenerate.py (61%) rename {src_ida => src_plugins/ida}/fakepdb/dumpinfo.py (79%) create mode 100644 src_plugins/ida/fakepdb/native.py rename src_ida/fakepdb/offsets.py => src_plugins/ida/fakepdb/offsets_importer.py (51%) rename src_ida/fakepdb/signatures.py => src_plugins/ida/fakepdb/signature_finder.py (65%) diff --git a/.gitignore b/.gitignore index ceeb5d5..701ccd8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ build/ ~build/ +cmake-build-*/ +.idea/ .vscode/ -*.pyc \ No newline at end of file +*.pyc diff --git a/Readme.md b/Readme.md index 9a30ab2..25181f5 100644 --- a/Readme.md +++ b/Readme.md @@ -2,7 +2,14 @@ Tool for PDB generation from IDA Pro database -Supports IDA >= 7.0 +Supports: +* IDA >= 7.4 + +## TODO + +* Linux support +* GHIDRA support +* Function arguments support ## How to get @@ -13,31 +20,37 @@ Supports IDA >= 7.0 ## How to install -* copy content of `fakepdb.zip` to `/plugins` +* IDA + * copy content of `fakepdb.zip/ida` to `/plugins` ## How to use There are several features in this plugin: -### 1. PDB file generation - * Open target executable in IDA >= 7.0 +### PDB file generation + * Open target executable in IDA * `Edit` -> `FakePDB` -> `Generate .PDB file` (or `Ctrl`+`Shift`+`4`) * get PDB file from the IDA database directory The PDB can optionally include symbols for function labels: use `Generate .PDB file (with function labels)` (or `Ctrl`+`Shift`+`5`). -### 2. IDA database export to .json +### LIB file generation + * Open target executable in IDA + * `Edit` -> `FakePDB` -> `Generate .LIB file` + * get LIB file from the IDA database directory + +### IDA database export to .json * Open target executable in IDA >= 7.0 * `Edit` -> `FakePDB` -> `Dump info to .json` (or `Ctrl`+`Shift`+`1`) * it will generate `filename.json` near the `.idb` file -### 3. Binary signature search +### Binary signature search * Open target executable in IDA >= 7.0 * Set cursor on start of the target function * `Edit` -> `FakePDB` -> `Find signature` (or `Ctrl`+`Shift`+`2`) * signature will be displayed in IDA console -### 4. Function names import from `.json` file +### Function names import from `.json` file * Open target executable in IDA >= 7.0 * `Edit` -> `FakePDB` -> `Import offset from .json` (or `Ctrl`+`Shift`+`3`) @@ -56,12 +69,6 @@ where: * `YYYY`: offset from the begining of the section in decimal numbers * 0x0124567AF: IDA effective address -## TODO - -* GHIDRA support -* Linux support -* Function arguments support - ## Thanks diff --git a/build.ps1 b/build.ps1 index 7235971..64b3b77 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,44 +1,75 @@ +# +# Config +# + +$build_llvm = $true + +# +# Set environment +# + Push-Location $PSScriptRoot $root = (Get-Location).Path -replace "\\","/" +#https://stackoverflow.com/a/64744522 +Push-Location "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools" +cmd /c "VsDevCmd.bat -arch=amd64 -host_arch=amd64&set " | +ForEach-Object { + if ($_ -match "=") { + $v = $_.split("="); set-item -force -path "ENV:\$($v[0])" -value "$($v[1])" + } +} +Pop-Location + # # Build LLVM # -git clone --depth=1 https://github.com/llvm/llvm-project "./~build/llvm_git" -q - -cmake "./~build/llvm_git/llvm" -B"./~build/llvm_build" ` - -DCMAKE_BUILD_TYPE="Release" ` - -DCMAKE_INSTALL_PREFIX="./~build/llvm_install" ` - -DLLVM_BUILD_LLVM_C_DYLIB=OFF ` - -DLLVM_BUILD_RUNTIME=OFF ` - -DLLVM_BUILD_RUNTIMES=OFF ` - -DLLVM_BUILD_TOOLS=OFF ` - -DLLVM_BUILD_UTILS=OFF ` - -DLLVM_ENABLE_BACKTRACES=OFF ` - -DLLVM_ENABLE_BINDINGS=OFF ` - -DLLVM_ENABLE_CRASH_OVERRIDES=OFF ` - -DLLVM_ENABLE_OCAMLDOC=OFF ` - -DLLVM_ENABLE_PDB=ON ` - -DLLVM_INCLUDE_BENCHMARKS=OFF ` - -DLLVM_INCLUDE_DOCS=OFF ` - -DLLVM_INCLUDE_EXAMPLES=OFF ` - -DLLVM_INCLUDE_GO_TESTS=OFF ` - -DLLVM_INCLUDE_RUNTIMES=OFF ` - -DLLVM_INCLUDE_TESTS=OFF ` - -DLLVM_INCLUDE_TOOLS=OFF ` - -DLLVM_INCLUDE_UTILS=OFF ` - -DLLVM_TARGETS_TO_BUILD="" - -cmake --build "./~build/llvm_build" --config Release --target INSTALL +if($true -eq $build_llvm){ + git clone --depth=1 https://github.com/llvm/llvm-project "./~build/llvm_git" + + cmake "./~build/llvm_git/llvm" ` + -B"./~build/llvm_build" ` + -GNinja ` + -DCMAKE_BUILD_TYPE="Release" ` + -DCMAKE_INSTALL_PREFIX="./~build/llvm_install" ` + -DLLVM_BUILD_LLVM_C_DYLIB=OFF ` + -DLLVM_BUILD_RUNTIME=OFF ` + -DLLVM_BUILD_RUNTIMES=OFF ` + -DLLVM_BUILD_TOOLS=OFF ` + -DLLVM_BUILD_UTILS=OFF ` + -DLLVM_ENABLE_BACKTRACES=OFF ` + -DLLVM_ENABLE_BINDINGS=OFF ` + -DLLVM_ENABLE_CRASH_OVERRIDES=OFF ` + -DLLVM_ENABLE_OCAMLDOC=OFF ` + -DLLVM_ENABLE_PDB=ON ` + -DLLVM_INCLUDE_BENCHMARKS=OFF ` + -DLLVM_INCLUDE_DOCS=OFF ` + -DLLVM_INCLUDE_EXAMPLES=OFF ` + -DLLVM_INCLUDE_GO_TESTS=OFF ` + -DLLVM_INCLUDE_RUNTIMES=OFF ` + -DLLVM_INCLUDE_TESTS=OFF ` + -DLLVM_INCLUDE_TOOLS=OFF ` + -DLLVM_INCLUDE_UTILS=OFF ` + -DLLVM_TARGETS_TO_BUILD="" + + cmake --build "./~build/llvm_build" + cmake --install "./~build/llvm_build" +} # # Build PDBGen # -cmake "./src_pdbgen/" -B"./~build/pdbgen_build" -DCMAKE_BUILD_TYPE="Release" -DCMAKE_INSTALL_PREFIX="./~build/pdbgen_install" -DCMAKE_PREFIX_PATH="$root/~build/llvm_install" -cmake --build "./~build/pdbgen_build" --config Release --target INSTALL +cmake "./src_cpp/" ` + -B"./~build/fakepdb_build" ` + -GNinja ` + -DCMAKE_BUILD_TYPE="Release" ` + -DCMAKE_INSTALL_PREFIX="./~build/fakepdb_install" ` + -DCMAKE_PREFIX_PATH="$root/~build/llvm_install" +cmake --build "./~build/fakepdb_build" +cmake --install "./~build/fakepdb_build" # # Sign @@ -66,7 +97,7 @@ function Sign-Folder($Folder, $Filters = @("*.exe", "*.dll"), $TimestampServer = if(Sign-IsAvailable){ Write-Output "Signing files" - Sign-Folder -Folder "./~build/pdbgen_install/bin/" + Sign-Folder -Folder "./~build/fakepdb_install/bin/" Write-Output "" } @@ -74,10 +105,11 @@ if(Sign-IsAvailable){ # Copy files # -New-Item -Path "./~build/deploy" -ItemType Directory -ErrorAction SilentlyContinue -Copy-Item -Path "./src_ida/*" -Destination "./~build/deploy/" -Recurse -New-Item -Path "./~build/deploy/fakepdb/win32/" -ItemType Directory -ErrorAction SilentlyContinue -Copy-Item -Path "./~build/pdbgen_install/bin/*.exe" -Destination "./~build/deploy/fakepdb/win32/" -Recurse +New-Item -Path "./~build/deploy/ida" -ItemType Directory -ErrorAction SilentlyContinue +Copy-Item -Path "./src_plugins/ida/*" -Destination "./~build/deploy/ida/" -Recurse + +New-Item -Path "./~build/deploy/ida/fakepdb/win32/" -ItemType Directory -ErrorAction SilentlyContinue +Copy-Item -Path "./~build/fakepdb_install/bin/*.exe" -Destination "./~build/deploy/ida/fakepdb/win32/" -Recurse # # Pack files diff --git a/src_cpp/CMakeLists.txt b/src_cpp/CMakeLists.txt new file mode 100644 index 0000000..219de3d --- /dev/null +++ b/src_cpp/CMakeLists.txt @@ -0,0 +1,94 @@ +# +# Copyright 2019-2021 Mikhail Paulyshka +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# Global project settings +# + +cmake_minimum_required(VERSION 3.16) +project(FakePDB) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# +# Packages +# +find_package(LLVM REQUIRED CONFIG) + +# +# Compiler settings +# + +if (MSVC) + add_compile_definitions(_CRT_SECURE_NO_WARNINGS) + add_compile_definitions(_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING) + add_compile_definitions(__STDC_WANT_SECURE_LIB__=1) + + add_compile_options(/Wall) + add_compile_options(/wd4061 /wd4100 /wd4146 /wd4242 /wd4244 /wd4245 /wd4266 /wd4267 /wd4324 /wd4365 /wd4458 /wd4459 /wd4514 /wd4582 /wd4583 /wd4623 /wd4624 /wd4625 /wd4626 /wd4702 /wd4710 /wd4711 /wd4774 /wd4800 /wd4820 /wd5026 /wd5027 /wd5045) +else() + add_compile_options(-Wall -Wextra) +endif() + +# +# fakepdb executable +# + +add_executable(fakepdb) +target_sources(fakepdb PRIVATE + src/main.cpp + + include/coff/lib_creator.h + src/coff/lib_creator.cpp + + include/commands/command_coff_createlib.h + include/commands/command_interface.h + include/commands/command_pdb_generate.h + include/commands/command_pe_exports.h + include/commands/command_pe_guidage.h + include/commands/command_pe_timestamp.h + + include/common/guid.h + include/common/hex.h + + include/data/db.h + include/data/export.h + include/data/function.h + include/data/general.h + include/data/label.h + include/data/name.h + include/data/root.h + include/data/segment.h + src/data/db.cpp + + include/pdb/pdb_creator.h + src/pdb/pdb_creator.cpp + + include/pe/pe_file.h + src/pe/pe_file.cpp +) + +target_include_directories(fakepdb PUBLIC ${LLVM_INCLUDE_DIRS}) +target_include_directories(fakepdb PUBLIC "include") +target_include_directories(fakepdb PUBLIC ".") + +llvm_map_components_to_libnames(llvm_libs core support DebugInfoPDB) +target_link_libraries(fakepdb ${llvm_libs}) + +install( + TARGETS fakepdb + RUNTIME DESTINATION bin +) diff --git a/src_cpp/include/coff/lib_creator.h b/src_cpp/include/coff/lib_creator.h new file mode 100644 index 0000000..5b02e66 --- /dev/null +++ b/src_cpp/include/coff/lib_creator.h @@ -0,0 +1,14 @@ +#pragma once + +//stdlib +#include + +//fakepdb +#include "data/db.h" + +namespace FakePDB::COFF { + class LibCreator { + public: + bool Create(Data::DB &db, std::filesystem::path& path); + }; +} diff --git a/src_cpp/include/commands/command_coff_createlib.h b/src_cpp/include/commands/command_coff_createlib.h new file mode 100644 index 0000000..1fe6159 --- /dev/null +++ b/src_cpp/include/commands/command_coff_createlib.h @@ -0,0 +1,58 @@ +//stdlib +#include +#include +#include + +//nlohmann +#include "nlohmann/json.hpp" + +//FakePDB +#include "commands/command_interface.h" +#include "coff/lib_creator.h" + +namespace FakePDB::Commands { + class CommandCoffCreatelib : public CommandInterface { + public: + ~CommandCoffCreatelib() = default; + + int32_t GetArgsMin() override { + return 2; + }; + + int32_t GetArgsMax() override { + return 2; + }; + + std::string GetCommandName() override { + return "coff_createlib"; + } + + std::vector GetCommandUsage() override { + return { " [lib_path]" }; + } + + std::string GetCommandDescription() override { + return "creates .lib file from .json"; + } + + int Run(int argc, char* argv[]) override { + std::filesystem::path path_json = argv[2]; + std::filesystem::path path_lib = argv[3]; + + if (!std::filesystem::exists(path_json)) { + std::cerr << "json file does not exists"; + return 1; + } + + Data::DB db(path_json); + + COFF::LibCreator libCreator; + if(!libCreator.Create(db, path_lib)) { + std::cerr << "failed to create lib"; + return 2; + } + + return 0; + } + }; +} \ No newline at end of file diff --git a/src_cpp/include/commands/command_interface.h b/src_cpp/include/commands/command_interface.h new file mode 100644 index 0000000..132fc68 --- /dev/null +++ b/src_cpp/include/commands/command_interface.h @@ -0,0 +1,23 @@ +#pragma once + +//stdlib +#include +#include +#include + +namespace FakePDB { + class CommandInterface { + public: + virtual ~CommandInterface() = default; + + virtual int32_t GetArgsMin() = 0; + virtual int32_t GetArgsMax() = 0; + + virtual std::string GetCommandName() = 0; + virtual std::vector GetCommandUsage() = 0; + virtual std::string GetCommandDescription() = 0; + + + virtual int Run(int argc, char* argv[]) = 0; + }; +} \ No newline at end of file diff --git a/src_cpp/include/commands/command_pdb_generate.h b/src_cpp/include/commands/command_pdb_generate.h new file mode 100644 index 0000000..df24590 --- /dev/null +++ b/src_cpp/include/commands/command_pdb_generate.h @@ -0,0 +1,75 @@ +//stdlib +#include +#include +#include + +//nlohmann +#include "nlohmann/json.hpp" + +//FakePDB +#include "commands/command_interface.h" +#include "common/hex.h" +#include "pe/pe_file.h" +#include "data/db.h" +#include "pdb/pdb_creator.h" + +namespace FakePDB::Commands { + class CommandPdbGenerate : public CommandInterface { + public: + ~CommandPdbGenerate() = default; + + int32_t GetArgsMin() override { + return 3; + }; + + int32_t GetArgsMax() override { + return 4; + }; + + std::string GetCommandName() override { + return "pdb_generate"; + } + + std::vector GetCommandUsage() override { + return {"[-l] " }; + } + + std::string GetCommandDescription() override { + return "generate PDB file for given file"; + } + + int Run(int argc, char* argv[]) override { + bool with_labels = false; + size_t arg_exe = 2; + if (argc > 5 && std::string(argv[2]) == "-l") { + arg_exe++; + with_labels = true; + } + std::filesystem::path path_exe = argv[arg_exe]; + std::filesystem::path path_json = argv[arg_exe+1]; + std::filesystem::path path_out = argv[arg_exe+2]; + + if (!std::filesystem::exists(path_exe)) { + std::cerr << ".exe file does not exists"; + return 2; + } + + if (!std::filesystem::exists(path_json)) { + std::cerr << ".json file does not exists"; + return 3; + } + + PE::PeFile pefile(path_exe); + Data::DB ida_db(path_json); + PDB::PdbCreator creator(pefile, with_labels); + + creator.Initialize(); + creator.ImportIDA(ida_db); + + std::filesystem::create_directories(path_out.parent_path()); + creator.Commit(path_out); + + return 0; + } + }; +} \ No newline at end of file diff --git a/src_cpp/include/commands/command_pe_exports.h b/src_cpp/include/commands/command_pe_exports.h new file mode 100644 index 0000000..123baad --- /dev/null +++ b/src_cpp/include/commands/command_pe_exports.h @@ -0,0 +1,73 @@ +//stdlib +#include +#include +#include + +//nlohmann +#include "nlohmann/json.hpp" + +//FakePDB +#include "commands/command_interface.h" +#include "common/hex.h" +#include "pe/pe_file.h" + +namespace FakePDB::Commands { + class CommandPeExports : public CommandInterface { + public: + ~CommandPeExports() = default; + + int32_t GetArgsMin() override { + return 1; + }; + + int32_t GetArgsMax() override { + return 2; + }; + + std::string GetCommandName() override { + return "pe_exports"; + } + + std::vector GetCommandUsage() override { + return { "", " [json_path]" }; + } + + std::string GetCommandDescription() override { + return "returns exports in the fiven PE files"; + } + + int Run(int argc, char* argv[]) override { + std::string pathExe = argv[2]; + + if (!std::filesystem::exists(pathExe)) { + std::cerr << "file does not exists"; + return 1; + } + + PE::PeFile pefile(pathExe); + + Data::DB db; + db.General().filename = std::filesystem::path(pathExe).filename().string(); + db.General().architecture = pefile.GetMachineName(); + db.General().bitness = pefile.GetMachineBitness(); + db.Exports() = pefile.GetExports(); + + if (argc == 3) + { + for (auto& exp : db.Exports()) { + std::cout << "Name : " << exp.name << std::endl; + std::cout << "Ordinal: " << exp.ordinal << std::endl; + std::cout << "RVA : 0x" << Common::Hex::IntToHex(exp.rva) << std::endl; + std::cout << std::endl; + } + } + + if (argc == 4) { + auto json_path = std::filesystem::path(argv[3]); + db.Save(json_path); + } + + return 0; + } + }; +} \ No newline at end of file diff --git a/src_cpp/include/commands/command_pe_guidage.h b/src_cpp/include/commands/command_pe_guidage.h new file mode 100644 index 0000000..a27c4f0 --- /dev/null +++ b/src_cpp/include/commands/command_pe_guidage.h @@ -0,0 +1,49 @@ +//stdlib +#include + +//FakePDB +#include "commands/command_interface.h" +#include "common/guid.h" +#include "common/hex.h" +#include "pe/pe_file.h" + +namespace FakePDB::Commands { + class CommandPeGuidAge : public CommandInterface { +public: + ~CommandPeGuidAge() = default; + + int32_t GetArgsMin() override { + return 1; + }; + + int32_t GetArgsMax() override { + return 1; + }; + + std::string GetCommandName() override { + return "pe_guidage"; + } + + std::vector GetCommandUsage() override { + return { "" }; + } + + std::string GetCommandDescription() override { + return "returns PDB folder name for symbol server"; + } + + int Run(int argc, char* argv[]) override { + std::string pathExe = argv[2]; + + if (!std::filesystem::exists(pathExe)) { + std::cerr << "file does not exists"; + return 1; + } + + PE::PeFile pefile(pathExe); + std::cout << (Common::GUID::ToHex(pefile.GetPdbGuid()) + Common::Hex::IntToHex(pefile.GetPdbAge())); + return 0; + } +}; + +} diff --git a/src_cpp/include/commands/command_pe_timestamp.h b/src_cpp/include/commands/command_pe_timestamp.h new file mode 100644 index 0000000..faf4836 --- /dev/null +++ b/src_cpp/include/commands/command_pe_timestamp.h @@ -0,0 +1,45 @@ +//FakePDB +#include "commands/command_interface.h" +#include "common/hex.h" +#include "pe/pe_file.h" + +namespace FakePDB::Commands { + class CommandPeTimestamp : public CommandInterface { + public: + ~CommandPeTimestamp() = default; + + int32_t GetArgsMin() override { + return 1; + }; + + int32_t GetArgsMax() override { + return 1; + }; + + std::string GetCommandName() override { + return "pe_timestamp"; + } + + std::vector GetCommandUsage() override { + return { "" }; + } + + std::string GetCommandDescription() override { + return "returns EXE/DLL folder name for symbol server"; + } + + int Run(int argc, char* argv[]) override { + std::string pathExe = argv[2]; + + if (!std::filesystem::exists(pathExe)) { + std::cerr << ".exe file does not exists"; + return 1; + } + + PE::PeFile pefile(pathExe); + + std::cout << (Common::Hex::IntToHex(pefile.GetTimestamp()) + Common::Hex::IntToHex(pefile.GetImageSize())); + return 0; + } + }; +} diff --git a/src_cpp/include/common/guid.h b/src_cpp/include/common/guid.h new file mode 100644 index 0000000..da8e7ad --- /dev/null +++ b/src_cpp/include/common/guid.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace FakePDB::Common { + struct GUID { + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; + + [[nodiscard]] std::string ToHex() const { + std::ostringstream oss; + oss << std::hex << std::uppercase; + + oss << std::setw(2) << std::setfill('0') << Data1; + oss << std::setw(2) << std::setfill('0') << Data2; + oss << std::setw(2) << std::setfill('0') << Data3; + for (auto i : Data4) { + oss << std::setw(2) << std::setfill('0') << (unsigned) i; + } + + return oss.str(); + } + + static std::string ToHex(const std::vector &vec) { + auto *guid = reinterpret_cast(vec.data()); + return guid->ToHex(); + } + }; +} diff --git a/src_cpp/include/common/hex.h b/src_cpp/include/common/hex.h new file mode 100644 index 0000000..ffc40fb --- /dev/null +++ b/src_cpp/include/common/hex.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include +#include + +namespace FakePDB::Common { + class Hex { + public: + Hex() = delete; + ~Hex() = delete; + + template + static std::string IntToHex(T i) { + std::ostringstream oss; + oss << std::hex << std::uppercase << i; + return oss.str(); + } + }; +} diff --git a/src_cpp/include/data/db.h b/src_cpp/include/data/db.h new file mode 100644 index 0000000..00dc20b --- /dev/null +++ b/src_cpp/include/data/db.h @@ -0,0 +1,29 @@ +#pragma once + +//stdlib +#include +#include + +//fakepdb +#include "data/root.h" + +namespace FakePDB::Data{ + class DB { + public: + explicit DB(); + explicit DB(std::filesystem::path& filepath); + + General& General(); + std::vector& Segments(); + std::vector& Exports(); + std::vector& Functions(); + std::vector& Names(); + + void Save(std::filesystem::path& filepath); + + private: + void load(std::filesystem::path& filepath); + + Root _root{}; + }; +} \ No newline at end of file diff --git a/src_cpp/include/data/export.h b/src_cpp/include/data/export.h new file mode 100644 index 0000000..9d3f81d --- /dev/null +++ b/src_cpp/include/data/export.h @@ -0,0 +1,25 @@ +#pragma once + +//stdlib +#include + +//Nlohmann +#include "nlohmann/json.hpp" + +namespace FakePDB::Data { + struct Export { + uint32_t ordinal; + uint32_t rva; + std::string name; + + /** + * Possible values: + * - unknown + * - function + * - data + */ + std::string type; + }; + + NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Export, ordinal, rva, name) +} diff --git a/src_cpp/include/data/function.h b/src_cpp/include/data/function.h new file mode 100644 index 0000000..d6d0372 --- /dev/null +++ b/src_cpp/include/data/function.h @@ -0,0 +1,24 @@ +#pragma once + +//stdlib +#include +#include +#include + +//nlohmann +#include "nlohmann/json.hpp" + +//fakepdb +#include "data/label.h" + +namespace FakePDB::Data { + struct Function { + std::string name; + uint32_t start_rva; + bool is_public; + bool is_autonamed; + std::vector