Skip to content

Commit

Permalink
[FEATURE] In patch_analyzer: identify new types: padding, breakpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
hasherezade committed Jun 9, 2024
1 parent 985e41a commit f54b294
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 19 deletions.
5 changes: 3 additions & 2 deletions scanners/code_scanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ size_t pesieve::CodeScanner::collectPatches(DWORD section_rva, PBYTE orig_code,
if (currPatch != nullptr) {
// close the patch
currPatch->setEnd(section_rva + i);
analyzer.analyzeOther(*currPatch);
currPatch = nullptr;
}
continue;
Expand All @@ -145,11 +146,11 @@ size_t pesieve::CodeScanner::collectPatches(DWORD section_rva, PBYTE orig_code,
currPatch = new(std::nothrow) PatchList::Patch(moduleData.moduleHandle, patchesList.size(), (DWORD) section_rva + i);
if (!currPatch) continue;
patchesList.insert(currPatch);
DWORD parsed_size = (DWORD) analyzer.analyze(*currPatch);
DWORD parsed_size = (DWORD) analyzer.analyzeHook(*currPatch);
if (parsed_size > 0) {
currPatch->setEnd(section_rva + i + parsed_size);
currPatch = nullptr; // close this patch
i += (parsed_size - 1); //substract 1 because of i++ executed after continue
i += (parsed_size - 1); //subtract 1 because of i++ executed after continue
continue;
}
}
Expand Down
37 changes: 32 additions & 5 deletions scanners/patch_analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ bool pesieve::PatchAnalyzer::isLongModifier(BYTE op)
return false;
}

size_t pesieve::PatchAnalyzer::_analyze(PatchList::Patch &patch, PBYTE patch_ptr, ULONGLONG patch_va)
size_t pesieve::PatchAnalyzer::_analyzeHook(PatchList::Patch &patch, PBYTE patch_ptr, ULONGLONG patch_va)
{
BYTE op = patch_ptr[0];
if (op == OP_JMP || op == OP_CALL_DWORD) {
Expand Down Expand Up @@ -192,7 +192,34 @@ size_t pesieve::PatchAnalyzer::_analyzeRelocated(PatchList::Patch &patch, BYTE*
return fieldSize;
}

size_t pesieve::PatchAnalyzer::analyze(PatchList::Patch &patch)
size_t pesieve::PatchAnalyzer::analyzeOther(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 = patch.endRva - patch.startRva;

if (size > 1) {
bool isPadding = true;
for (size_t i = 1; i < size; ++i) {
if (patch_ptr[0] != patch_ptr[i]) {
isPadding = false;
}
}
if (isPadding) {
patch.type = PATCH_PADDING;
patch.paddingVal = patch_ptr[0];
}
}
if (patch_ptr[0] == 0xCC) {
if (size == 1 || patch.type == PATCH_PADDING) {
patch.type = PATCH_BREAKPOINT;
}
}
return size;
}

size_t pesieve::PatchAnalyzer::analyzeHook(PatchList::Patch &patch)
{
const ULONGLONG patch_va = moduleData.rvaToVa(patch.startRva);
const size_t patch_offset = patch.startRva - sectionRVA;
Expand All @@ -206,13 +233,13 @@ size_t pesieve::PatchAnalyzer::analyze(PatchList::Patch &patch)
if (!peconv::validate_ptr(this->patchedCode, this->codeSize, patch_ptr, kMinSize)) {
return 0;
}
size = _analyze(patch, patch_ptr, patch_va);
size = _analyzeHook(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...
size = _analyze(patch, patch_ptr -1, patch_va - 1);
size = _analyzeHook(patch, patch_ptr -1, patch_va - 1);
if (size > 0) {
// substract the added position:
// subtract the added position:
size--;
}
}
Expand Down
6 changes: 4 additions & 2 deletions scanners/patch_analyzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ namespace pesieve {
moduleData.loadRelocatedFields(relocs);
}

size_t analyze(PatchList::Patch &patch);
size_t analyzeHook(PatchList::Patch &patch);

size_t analyzeOther(PatchList::Patch& patch);

protected:
size_t _analyze(PatchList::Patch &patch, PBYTE patch_ptr, ULONGLONG patch_va);
size_t _analyzeHook(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);
Expand Down
13 changes: 11 additions & 2 deletions scanners/patch_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ std::string pesieve::PatchList::Patch::getFormattedName()
{
std::stringstream stream;

if (this->type == pesieve::PATCH_PADDING) {
stream << "padding:";
stream << std::hex << "0x" << (unsigned int)paddingVal;
return stream.str();
}
if (this->type == pesieve::PATCH_BREAKPOINT) {
stream << "breakpoint";
return stream.str();
}
if (this->hooked_func.length() > 0) {
stream << hooked_func;
} else {
Expand All @@ -22,7 +31,7 @@ std::string pesieve::PatchList::Patch::getFormattedName()
}
stream << id;
}
if (this->type != pesieve::HOOK_NONE) {
if (this->type != pesieve::PATCH_UNKNOWN) {
stream << "->";
if (this->isDirect) {
stream << std::hex << hookTargetVA;
Expand Down Expand Up @@ -81,7 +90,7 @@ const bool pesieve::PatchList::Patch::toJSON(std::stringstream &outs, size_t lev
}
else {
outs << ",\n";
const bool isHook = (this->type != pesieve::HOOK_NONE);
const bool isHook = (this->type == pesieve::HOOK_INLINE || this->type == pesieve::HOOK_ADDR_REPLACEMENT);
OUT_PADDED(outs, (level + 1), "\"is_hook\" : ");
outs << std::dec << isHook;

Expand Down
21 changes: 13 additions & 8 deletions scanners/patch_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
namespace pesieve {

typedef enum {
HOOK_NONE,
PATCH_UNKNOWN,
HOOK_INLINE,
HOOK_ADDR_REPLACEMENT,
COUNT_HOOK_TYPES
} t_hook_type;
PATCH_PADDING,
PATCH_BREAKPOINT,
COUNT_PATCH_TYPES
} t_patch_type;

class PatchList {
public:
Expand All @@ -22,9 +24,10 @@ namespace pesieve {
public:
Patch(HMODULE module_base, size_t patch_id, DWORD start_rva)
: moduleBase(module_base), id(patch_id), startRva(start_rva), endRva(start_rva),
type(pesieve::HOOK_NONE),
type(pesieve::PATCH_UNKNOWN),
isDirect(true),
hookTargetVA(0), hookTargetModule(0), isTargetSuspicious(false)
hookTargetVA(0), hookTargetModule(0), isTargetSuspicious(false),
paddingVal(0)
{
}

Expand All @@ -43,14 +46,15 @@ namespace pesieve {
hookTargetModule = other.hookTargetModule;
isTargetSuspicious = other.isTargetSuspicious;
hookTargetModName = other.hookTargetModName;
paddingVal = other.paddingVal;
}

void setEnd(DWORD end_rva)
{
endRva = end_rva;
}

void setHookTarget(ULONGLONG target_va, bool is_direct = true, t_hook_type hook_type = pesieve::HOOK_INLINE)
void setHookTarget(ULONGLONG target_va, bool is_direct = true, t_patch_type hook_type = pesieve::HOOK_INLINE)
{
hookTargetVA = target_va;
isDirect = is_direct;
Expand All @@ -64,7 +68,7 @@ namespace pesieve {

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

t_hook_type type;
t_patch_type type;
bool isDirect;
ULONGLONG hookTargetVA;
BYTE paddingVal;
std::string hooked_func;

ULONGLONG hookTargetModule;
Expand Down

0 comments on commit f54b294

Please sign in to comment.