Skip to content

Commit

Permalink
Merge pull request #71 from hasherezade/master
Browse files Browse the repository at this point in the history
[FEATURE] Increased limit of functions that IAT must have to trigger …
  • Loading branch information
fengjixuchui authored Sep 4, 2021
2 parents 9384a02 + bcfe7f4 commit e5792eb
Show file tree
Hide file tree
Showing 11 changed files with 143 additions and 35 deletions.
4 changes: 2 additions & 2 deletions include/pe_sieve_version.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
namespace pesieve {
#endif

const char PESIEVE_VERSION[] = "0.3.0";
const DWORD PESIEVE_VERSION_ID = 0x00030000; // 00 03 00 00
const char PESIEVE_VERSION[] = "0.3.0.4";
const DWORD PESIEVE_VERSION_ID = 0x00030004; // 00 03 00 04
const char PESIEVE_URL[] = "https://github.com/hasherezade/pe-sieve";

#ifdef __cplusplus
Expand Down
2 changes: 1 addition & 1 deletion libpeconv
10 changes: 5 additions & 5 deletions postprocessors/imp_rec/iat_block.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,19 +110,19 @@ namespace pesieve {
return true;
}

bool isCovered()
bool isCovered() const
{
return isCoverageComplete;
}

bool isValid()
bool isValid() const
{
//allow for every block with complete coverage
return isCovered();
}

//how many functions the IAT has
size_t countThunks()
size_t countThunks() const
{
return functions.size();
}
Expand Down Expand Up @@ -159,8 +159,8 @@ namespace pesieve {
bool is64bit;
bool isCoverageComplete;

std::map<ULONGLONG, const peconv::ExportedFunc*> functions; //TODO: this will be deleted or refactored
std::map<ULONGLONG, ULONGLONG> addrToFunctionVA; //TODO: this will be deleted or refactored
std::map<ULONGLONG, const peconv::ExportedFunc*> functions;
std::map<ULONGLONG, ULONGLONG> addrToFunctionVA;

friend class ImpReconstructor;
};
Expand Down
23 changes: 22 additions & 1 deletion postprocessors/imp_rec/imp_reconstructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

#include <fstream>

//! the minimal function count that the additional Import Table must have to trigger Import Table recreation (if run in autodetect mode)
#define MIN_FUNC_COUNT 3

using namespace pesieve;

namespace pesieve {
Expand Down Expand Up @@ -35,6 +38,24 @@ BYTE* pesieve::ImportTableBuffer::getDllSpaceAt(const DWORD rva, size_t required

//---

bool pesieve::ImpReconstructor::hasNewImportTables() const
{
bool has_new_table = false;
std::map<DWORD, IATBlock*>::const_iterator iats_itr;
for (iats_itr = foundIATs.cbegin(); iats_itr != foundIATs.cend(); ++iats_itr) {
const IATBlock* iblock = iats_itr->second;
if (!iblock->isMain
&& iblock->isTerminated
&& iblock->countThunks() >= MIN_FUNC_COUNT)
{
has_new_table = true;
break;
}

}
return has_new_table;
}

pesieve::ImpReconstructor::t_imprec_res pesieve::ImpReconstructor::rebuildImportTable(const IN peconv::ExportsMapper* exportsMap, IN const pesieve::t_imprec_mode &imprec_mode)
{
if (!exportsMap || imprec_mode == pesieve::PE_IMPREC_NONE) {
Expand All @@ -55,7 +76,7 @@ pesieve::ImpReconstructor::t_imprec_res pesieve::ImpReconstructor::rebuildImport
return IMP_RECOVERY_NOT_APPLICABLE;
}

if (imprec_mode == PE_IMPREC_UNERASE || imprec_mode == PE_IMPREC_AUTO) {
if (imprec_mode == PE_IMPREC_UNERASE || (imprec_mode == PE_IMPREC_AUTO && !hasNewImportTables())) {

if (this->isDefaultImportValid(exportsMap)) {
// Valid Import Table already set
Expand Down
6 changes: 5 additions & 1 deletion postprocessors/imp_rec/imp_reconstructor.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,11 @@ namespace pesieve {

private:

IATBlock * findIAT(IN const peconv::ExportsMapper* exportsMap, size_t start_offset);
IATBlock* findIAT(IN const peconv::ExportsMapper* exportsMap, size_t start_offset);

//! has more IATs that the main one (dynamically loaded)
bool hasNewImportTables() const;

bool findImportTable(IN const peconv::ExportsMapper* exportsMap);
size_t collectIATs(IN const peconv::ExportsMapper* exportsMap);

Expand Down
50 changes: 46 additions & 4 deletions scanners/module_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ bool pesieve::ModuleData::loadModuleName()
bool pesieve::ModuleData::loadOriginal()
{
//disable FS redirection by default
if (_loadOriginal(true)) {
return true;
bool is_ok = _loadOriginal(true);
if (!is_ok) {
//if loading with FS redirection has failed, try without
is_ok = _loadOriginal(false);
}
//if loading with FS redirection has failed, try without
return _loadOriginal(false);
return is_ok;
}

bool pesieve::ModuleData::_loadOriginal(bool disableFSredir)
Expand Down Expand Up @@ -58,6 +59,47 @@ bool pesieve::ModuleData::_loadOriginal(bool disableFSredir)
return true;
}


bool pesieve::ModuleData::loadRelocatedFields(std::set<DWORD>& fields_rvas)
{
if (!original_module || !original_size) {
return false;
}
//---
class CollectRelocField : public peconv::RelocBlockCallback
{
public:
CollectRelocField(ModuleData &_mod, std::set<DWORD>& _fields)
: RelocBlockCallback(_mod.is64bit()), mod(_mod), fields(_fields)
{
}

virtual bool processRelocField(ULONG_PTR relocField)
{
DWORD reloc_rva = mod.vaToRva(relocField, (ULONG_PTR)mod.original_module);
fields.insert(reloc_rva);
return true;
}

std::set<DWORD> &fields;
ModuleData &mod;
};
//---
if (!peconv::has_valid_relocation_table(original_module, original_size)) {
// No reloc table
return false;
}
CollectRelocField collector(*this, fields_rvas);
if (!peconv::process_relocation_table(original_module, original_size, &collector)) {
// Could not collect relocations
return false;
}
if (fields_rvas.size()) {
return true;
}
return false;
}

bool pesieve::ModuleData::relocateToBase(ULONGLONG new_base)
{
if (!original_module) return false;
Expand Down
15 changes: 11 additions & 4 deletions scanners/module_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <windows.h>
#include <psapi.h>
#include <map>
#include <set>

#include <peconv.h>
#include "../utils/format_util.h"
Expand Down Expand Up @@ -46,14 +47,19 @@ namespace pesieve {

bool isDotNet() { return this->is_dot_net; }

ULONGLONG rvaToVa(DWORD rva)
ULONGLONG rvaToVa(DWORD rva, ULONGLONG module_base = 0)
{
return reinterpret_cast<ULONGLONG>(this->moduleHandle) + rva;
if (module_base == 0) {
module_base = reinterpret_cast<ULONGLONG>(this->moduleHandle);
}
return module_base + rva;
}

DWORD vaToRva(ULONGLONG va)
DWORD vaToRva(ULONGLONG va, ULONGLONG module_base = 0)
{
ULONGLONG module_base = reinterpret_cast<ULONGLONG>(this->moduleHandle);
if (module_base == 0) {
module_base = reinterpret_cast<ULONGLONG>(this->moduleHandle);
}
if (va < module_base) {
return 0; // not this module
}
Expand Down Expand Up @@ -85,6 +91,7 @@ namespace pesieve {
bool switchToWow64Path();
bool reloadWow64();
bool relocateToBase(ULONGLONG new_base);
bool loadRelocatedFields(std::set<DWORD>& fields_rvas);

HANDLE processHandle;
HMODULE moduleHandle;
Expand Down
23 changes: 20 additions & 3 deletions scanners/patch_analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,19 +177,36 @@ size_t pesieve::PatchAnalyzer::_analyze(PatchList::Patch &patch, PBYTE patch_ptr
return 0;
}

size_t pesieve::PatchAnalyzer::_analyzeRelocated(PatchList::Patch &patch, BYTE* patch_ptr)
{
if (this->relocs.find(patch.startRva) == this->relocs.end()) {
return 0;
}
// This patch is a relocated field
const size_t fieldSize = (this->moduleData.is64bit()) ? sizeof(ULONGLONG) : sizeof(DWORD);
if (!peconv::validate_ptr(this->patchedCode, this->codeSize, patch_ptr, fieldSize)) {
return 0;
}
ULONGLONG field = (this->moduleData.is64bit()) ? *((ULONGLONG*)patch_ptr) : *((DWORD*)patch_ptr);
patch.setHookTarget(field, true, pesieve::HOOK_ADDR_REPLACEMENT);
return fieldSize;
}

size_t pesieve::PatchAnalyzer::analyze(PatchList::Patch &patch)
{
const ULONGLONG patch_va = moduleData.rvaToVa(patch.startRva);
const size_t patch_offset = patch.startRva - sectionRVA;
BYTE* patch_ptr = this->patchedCode + patch_offset;

size_t size = _analyzeRelocated(patch, patch_ptr);
if (size) {
return size;
}
const size_t kMinSize = 3;
if (!peconv::validate_ptr(this->patchedCode, this->codeSize, patch_ptr, kMinSize)) {
return 0;
}

size_t size = _analyze(patch, patch_ptr, patch_va);

size = _analyze(patch, patch_ptr, patch_va);
if (size == 0 && patch_offset > 0) {
//it may happen that the address of an existing JMP/CALL was replaced
//try to parse a byte before the patch...
Expand Down
4 changes: 4 additions & 0 deletions scanners/patch_analyzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ namespace pesieve {
: moduleData(_moduleData), sectionRVA(_sectionRVA), patchedCode(patched_code), codeSize(code_size)
{
isModule64bit = moduleData.is64bit();
moduleData.loadRelocatedFields(relocs);
}

size_t analyze(PatchList::Patch &patch);

protected:
size_t _analyze(PatchList::Patch &patch, PBYTE patch_ptr, ULONGLONG patch_va);
size_t _analyzeRelocated(PatchList::Patch &patch, BYTE* patch_ptr);

size_t parseJmpViaAddr(PatchList::Patch &patch, PBYTE patch_ptr, ULONGLONG patch_va);
size_t parseShortJmp(PatchList::Patch &patch, PBYTE patch_ptr, ULONGLONG patch_va);
Expand All @@ -47,6 +49,8 @@ namespace pesieve {
DWORD sectionRVA;
PBYTE patchedCode;
size_t codeSize;

std::set<DWORD> relocs;
};

}; //namespace pesieve
Expand Down
20 changes: 12 additions & 8 deletions scanners/patch_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@ std::string pesieve::PatchList::Patch::getFormattedName()
if (this->hooked_func.length() > 0) {
stream << hooked_func;
} else {
if (this->isHook) {
stream << "hook_" << id;
} else {
stream << "patch_" << id;
switch (this->type) {
case pesieve::HOOK_INLINE:
stream << "hook_"; break;
case pesieve::HOOK_ADDR_REPLACEMENT:
stream << "addr_replaced_"; break;
default:
stream << "patch_"; break;
}
stream << id;
}
if (this->isHook) {
if (this->type != pesieve::HOOK_NONE) {
stream << "->";
if (this->isDirect) {
stream << std::hex << hookTargetVA;
Expand Down Expand Up @@ -77,16 +81,16 @@ const bool pesieve::PatchList::Patch::toJSON(std::stringstream &outs, size_t lev
}
else {
outs << ",\n";

const bool isHook = (this->type != pesieve::HOOK_NONE);
OUT_PADDED(outs, (level + 1), "\"is_hook\" : ");
outs << std::dec << this->isHook;
outs << std::dec << isHook;

if (this->hooked_func.length() > 0) {
outs << ",\n";
OUT_PADDED(outs, (level + 1), "\"func_name\" : ");
outs << "\"" << hooked_func << "\"";
}
if (this->isHook) {
if (isHook) {
outs << ",\n";
OUT_PADDED(outs, (level + 1), "\"hook_target\" : {\n");
if (hookTargetModName.length() > 0) {
Expand Down
21 changes: 15 additions & 6 deletions scanners/patch_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,22 @@

namespace pesieve {

typedef enum {
HOOK_NONE,
HOOK_INLINE,
HOOK_ADDR_REPLACEMENT,
COUNT_HOOK_TYPES
} t_hook_type;

class PatchList {
public:
class Patch
{
public:
Patch(HMODULE module_base, size_t patch_id, DWORD start_rva)
: moduleBase(module_base), id(patch_id), startRva(start_rva), endRva(start_rva),
isHook(false), isDirect(true),
type(pesieve::HOOK_NONE),
isDirect(true),
hookTargetVA(0), hookTargetModule(0), isTargetSuspicious(false)
{
}
Expand All @@ -27,7 +35,8 @@ namespace pesieve {
endRva = other.endRva;
moduleBase = other.moduleBase;

isHook = other.isHook;
isDirect = other.isDirect;
type = other.type;
hookTargetVA = other.hookTargetVA;
hooked_func = other.hooked_func;

Expand All @@ -41,11 +50,11 @@ namespace pesieve {
endRva = end_rva;
}

void setHookTarget(ULONGLONG target_va, bool is_direct = true)
void setHookTarget(ULONGLONG target_va, bool is_direct = true, t_hook_type hook_type = pesieve::HOOK_INLINE)
{
hookTargetVA = target_va;
isDirect = is_direct;
isHook = true;
this->type = hook_type;
}

ULONGLONG getHookTargetVA()
Expand All @@ -55,7 +64,7 @@ namespace pesieve {

bool setHookTargetInfo(ULONGLONG targetModuleBase, bool isSuspiocious, std::string targetModuleName)
{
if (!isHook || targetModuleBase == 0 || targetModuleBase > this->hookTargetVA) {
if (type == pesieve::HOOK_NONE || targetModuleBase == 0 || targetModuleBase > this->hookTargetVA) {
return false;
}
this->hookTargetModule = targetModuleBase;
Expand All @@ -77,7 +86,7 @@ namespace pesieve {
DWORD endRva;
HMODULE moduleBase;

bool isHook;
t_hook_type type;
bool isDirect;
ULONGLONG hookTargetVA;
std::string hooked_func;
Expand Down

0 comments on commit e5792eb

Please sign in to comment.