Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ObfuGuard/ObfuGuard.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@
<ClCompile Include="junkcode\junkcode.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="constants.h" />
<ClInclude Include="cfflattening\cfflattening.h" />
<ClInclude Include="func2rva\func2rva.h" />
<ClInclude Include="obfuscatecff\obfuscatecff.h" />
Expand Down
3 changes: 3 additions & 0 deletions ObfuGuard/ObfuGuard.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="constants.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pe\pe.h">
<Filter>Header Files\pe</Filter>
</ClInclude>
Expand Down
4 changes: 3 additions & 1 deletion ObfuGuard/cfflattening/cfflattening.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ bool obfuscatecff::apply_control_flow_flattening(std::vector<obfuscatecff::funct
// perform flow restructuring with dispatcher through comparison with rax state variable
instruction_t push_rax{}; push_rax.load(func->func_id, { 0x50 });
push_rax.inst_id = first_inst_id;
push_rax.is_first_instruction = false;
push_rax.is_first_instruction = true;
auto it = func->instructions.insert(func->instructions.begin(), push_rax);
instruction_t push_f{}; push_f.load(func->func_id, { 0x66, 0x9C });
it = func->instructions.insert(it + 1, push_f);
Expand Down Expand Up @@ -196,6 +196,8 @@ bool obfuscatecff::apply_control_flow_flattening(std::vector<obfuscatecff::funct
return inst.inst_id == (block_iter->instructions.end() - 1)->inst_id;
});

if (last_inst == func->instructions.end()) continue;

// Find the next block in the execution chain
auto next_block_iter = std::find_if(blocks.begin(), blocks.end(),
[&](const basic_block& blk) { return blk.block_id == block_iter->next_block; });
Expand Down
35 changes: 35 additions & 0 deletions ObfuGuard/constants.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once
#include <cstdint>

namespace ObfuGuard {

// PE format constants
constexpr uint32_t PE_FILE_ALIGNMENT = 0x200;
constexpr uint32_t PE_SECTION_ALIGNMENT = 0x1000;
constexpr uint32_t PE_MAX_SECTIONS = 96;
constexpr uint32_t PE_SECTION_SAFETY_MARGIN = 10;
constexpr uint32_t PE_RESERVED_SYSTEM_SECTIONS = 5;
constexpr uint32_t PE_HEADER_SIZE = 0x1000;
constexpr uint32_t MAX_PE_IMAGE_SIZE = 512 * 1024 * 1024;

// CFF obfuscation constants
constexpr uint32_t CFF_SECTION_SIZE = 10'000'000;
constexpr const char* CFF_SECTION_NAME = ".0Cff";
constexpr const char* CFF_DEV_SECTION_NAME = ".0Dev";

// Junk code injection constants
constexpr uint32_t MAX_JUNK_ITERATIONS = 500;
constexpr uint32_t MIN_TRAMPOLINE_PATCH_SIZE = 5;
constexpr uint32_t MAX_TRAMPOLINE_PATCH_SIZE = 0x1000;
constexpr uint32_t MAX_FUNC_SCAN_SIZE = 8192;
constexpr uint32_t DEFAULT_SECTION_SIZE = 0x1000;
constexpr uint32_t LARGE_BINARY_SIZE_THRESHOLD = 350 * 1024;
constexpr uint32_t MIN_FUNCTION_SIZE = 5;

// PDB constants
constexpr uint64_t SYM_LOAD_BASE_ADDRESS = 0x10000000;

// Instruction format buffer
constexpr size_t INSTRUCTION_FORMAT_BUFFER_SIZE = 256;

}
63 changes: 19 additions & 44 deletions ObfuGuard/func2rva/func2rva.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,25 +92,13 @@ namespace FuncToRVA { // Namespace for resolving functions to RVAs
// Return list of resolved functions. If not initialized, return empty list and report error.
const std::vector<FunctionInfo>& RVAResolver::get_functions_info() const {
if (!is_initialized_) {
static std::vector<FunctionInfo> empty_list;
std::cerr << "Error: RVAResolver has not been initialized. Please call initialize() first." << std::endl;
return empty_list;
throw std::runtime_error("RVAResolver has not been initialized. Please call initialize() first.");
}
return resolved_functions_list_;
}

// Display list of functions, let user select one function to get RVA
bool RVAResolver::select_function_rva_interactive(uint32_t& out_rva) {
if (!is_initialized_) {
std::cerr << "Error: RVAResolver has not been initialized. Please call initialize() first." << std::endl;
return false;
}

if (resolved_functions_list_.empty()) {
std::cout << "Info: No functions from PDB available to select." << std::endl;
return false;
}

// Display the function table (header, columns, and all rows)
void RVAResolver::display_function_table() const {
std::cout << "\nAvailable functions from PDB for file: " << pe_path_str_ << std::endl;
std::cout << "PE ImageBase: 0x" << std::hex << image_base_ << std::dec << std::endl;
if (has_text_section_for_reference_) {
Expand Down Expand Up @@ -140,6 +128,21 @@ namespace FuncToRVA { // Namespace for resolving functions to RVAs
<< func_info.name << std::endl;
}
std::cout << "----------------------------------------------------------------------------------------------------" << std::endl;
}

// Display list of functions, let user select one function to get RVA
bool RVAResolver::select_function_rva_interactive(uint32_t& out_rva) {
if (!is_initialized_) {
std::cerr << "Error: RVAResolver has not been initialized. Please call initialize() first." << std::endl;
return false;
}

if (resolved_functions_list_.empty()) {
std::cout << "Info: No functions from PDB available to select." << std::endl;
return false;
}

display_function_table();

int choice = 0;
while (true) {
Expand Down Expand Up @@ -196,35 +199,7 @@ namespace FuncToRVA { // Namespace for resolving functions to RVAs
return false;
}

std::cout << "\nAvailable functions from PDB for file: " << pe_path_str_ << std::endl;
std::cout << "PE ImageBase: 0x" << std::hex << image_base_ << std::dec << std::endl;
if (has_text_section_for_reference_) {
std::cout << "Using PDB offsets relative to '.text' section (RVA: 0x"
<< std::hex << text_section_rva_ << std::dec << ")" << std::endl;
}
else {
std::cout << "Warning: '.text' section not found. Displayed RVAs may be PDB offsets or 0 if unable to compute." << std::endl;
}
std::cout << "----------------------------------------------------------------------------------------------------" << std::endl;
std::cout << std::setw(7) << "No." << " | "
<< std::setw(12) << "RVA (Hex)" << " | "
<< std::setw(12) << "Offset (Hex)" << " | "
<< std::setw(10) << "Size" << " | "
<< "Function Name" << std::endl;
std::cout << "----------------------------------------------------------------------------------------------------" << std::endl;

for (size_t i = 0; i < resolved_functions_list_.size(); ++i) {
const auto& func_info = resolved_functions_list_[i];
std::cout << std::setw(7) << std::left << i + 1 << " | "
<< "0x" << std::hex << std::setw(10) << std::left << func_info.rva
<< " | "
<< "0x" << std::hex << std::setw(10) << std::left << func_info.pdb_offset
<< " | "
<< std::dec << std::setw(10) << std::left << func_info.size
<< " | "
<< func_info.name << std::endl;
}
std::cout << "----------------------------------------------------------------------------------------------------" << std::endl;
display_function_table();

std::string input_str;
while (true) {
Expand Down
1 change: 1 addition & 0 deletions ObfuGuard/func2rva/func2rva.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ namespace FuncToRVA {
bool has_text_section_for_reference_ = false; // Flag indicating if .text section exists

bool load_pe_and_parse_pdb();
void display_function_table() const;
};

// Display function list from PE file and allow user to select one function, returns RVA of that function.
Expand Down
Loading
Loading