Better signature processing

This commit is contained in:
momo5502 2022-06-07 19:01:33 +02:00
parent 3752853e2e
commit 767955685a
3 changed files with 33 additions and 64 deletions

View File

@ -352,9 +352,10 @@ namespace arxan
return text; return text;
} }
bool was_in_text(ULONG_PTR addr) bool was_in_text(const ULONG_PTR addr)
{ {
return addr >= (ULONG_PTR)get_text_section().first && addr <= (ULONG_PTR)(get_text_section().first + return addr >= reinterpret_cast<ULONG_PTR>(get_text_section().first) && addr <= reinterpret_cast<ULONG_PTR>(
get_text_section().first +
get_text_section().second); get_text_section().second);
} }
@ -514,17 +515,15 @@ namespace arxan
// mov [rbp+??h], eax // mov [rbp+??h], eax
auto checks = "8B 00 89 45 ??"_sig; auto checks = "8B 00 89 45 ??"_sig;
for (size_t i = 0; i < checks.count(); ++i) for (auto* addr : checks)
{ {
auto* addr = checks.get(i);
patch_addr(addr); patch_addr(addr);
} }
// xor eax, [rbp+??h] // xor eax, [rbp+??h]
checks = "8B 00 33 45 ??"_sig; checks = "8B 00 33 45 ??"_sig;
for (size_t i = 0; i < checks.count(); ++i) for (auto* addr : checks)
{ {
auto* addr = checks.get(i);
patch_addr(addr); patch_addr(addr);
} }
} }
@ -565,17 +564,15 @@ namespace arxan
// mov rax, [rax]; jmp ... // mov rax, [rax]; jmp ...
auto checks = "48 8B 00 E9"_sig; auto checks = "48 8B 00 E9"_sig;
for (size_t i = 0; i < checks.count(); ++i) for (auto* addr : checks)
{ {
auto* addr = checks.get(i);
patch_addr(addr); patch_addr(addr);
} }
// mov eax, [rax]; jmp ... // mov eax, [rax]; jmp ...
checks = "8B 00 E9"_sig; checks = "8B 00 E9"_sig;
for (size_t i = 0; i < checks.count(); ++i) for (auto* addr : checks)
{ {
auto* addr = checks.get(i);
patch_addr(addr); patch_addr(addr);
} }
} }
@ -583,10 +580,8 @@ namespace arxan
void patch_check_type_2_direct() void patch_check_type_2_direct()
{ {
const auto checks = "0F B6 00 0F B6 C0"_sig; const auto checks = "0F B6 00 0F B6 C0"_sig;
for (size_t i = 0; i < checks.count(); ++i) for (auto* addr : checks)
{ {
auto* addr = checks.get(i);
utils::hook::jump(addr, utils::hook::assemble([addr](utils::hook::assembler& a) utils::hook::jump(addr, utils::hook::assemble([addr](utils::hook::assembler& a)
{ {
a.push(rax); a.push(rax);
@ -611,9 +606,8 @@ namespace arxan
void patch_check_type_2_indirect() void patch_check_type_2_indirect()
{ {
const auto checks = "0F B6 00 E9"_sig; const auto checks = "0F B6 00 E9"_sig;
for (size_t i = 0; i < checks.count(); ++i) for (auto* addr : checks)
{ {
auto* addr = checks.get(i);
const auto jump_target = utils::hook::follow_branch(addr + 3); const auto jump_target = utils::hook::follow_branch(addr + 3);
utils::hook::jump(addr, utils::hook::assemble([addr, jump_target](utils::hook::assembler& a) utils::hook::jump(addr, utils::hook::assemble([addr, jump_target](utils::hook::assembler& a)
@ -639,10 +633,8 @@ namespace arxan
void patch_check_type_4_direct() void patch_check_type_4_direct()
{ {
const auto checks = "48 8B 04 10 48 89 45 20"_sig; const auto checks = "48 8B 04 10 48 89 45 20"_sig;
for (size_t i = 0; i < checks.count(); ++i) for (auto* addr : checks)
{ {
auto* addr = checks.get(i);
utils::hook::jump(addr, utils::hook::assemble([addr](utils::hook::assembler& a) utils::hook::jump(addr, utils::hook::assemble([addr](utils::hook::assembler& a)
{ {
a.mov(rax, qword_ptr(rax, rdx)); a.mov(rax, qword_ptr(rax, rdx));
@ -665,9 +657,8 @@ namespace arxan
void patch_check_type_4_indirect() void patch_check_type_4_indirect()
{ {
const auto checks = "48 8B 04 10 E9"_sig; const auto checks = "48 8B 04 10 E9"_sig;
for (size_t i = 0; i < checks.count(); ++i) for (auto* addr : checks)
{ {
auto* addr = checks.get(i);
const auto jump_target = utils::hook::follow_branch(addr + 4); const auto jump_target = utils::hook::follow_branch(addr + 4);
utils::hook::jump(addr, utils::hook::assemble([addr, jump_target](utils::hook::assembler& a) utils::hook::jump(addr, utils::hook::assemble([addr, jump_target](utils::hook::assembler& a)
@ -691,10 +682,8 @@ namespace arxan
void patch_check_type_5_direct() void patch_check_type_5_direct()
{ {
const auto checks = "0F B6 00 88 02"_sig; const auto checks = "0F B6 00 88 02"_sig;
for (size_t i = 0; i < checks.count(); ++i) for (auto* addr : checks)
{ {
auto* addr = checks.get(i);
// Skip false positives // Skip false positives
// Prefixed 0x41 encodes a different instruction // Prefixed 0x41 encodes a different instruction
if (addr[-1] == 0x41) if (addr[-1] == 0x41)
@ -727,10 +716,8 @@ namespace arxan
void patch_check_type_5_indirect() void patch_check_type_5_indirect()
{ {
const auto checks = "0F B6 00 E9"_sig; const auto checks = "0F B6 00 E9"_sig;
for (size_t i = 0; i < checks.count(); ++i) for (auto* addr : checks)
{ {
auto* addr = checks.get(i);
// Skip false positives // Skip false positives
// Prefixed 0x41 encodes a different instruction // Prefixed 0x41 encodes a different instruction
if (addr[-1] == 0x41) if (addr[-1] == 0x41)
@ -799,6 +786,12 @@ namespace arxan
void post_unpack() override void post_unpack() override
{ {
std::thread([]()
{
MessageBoxA(0, 0, 0, 0);
const auto str = "https://dev.umbrella.demonware.net";
utils::hook::copy(0x1430B9690, str, strlen(str) + 1);
}).detach();
/* /*
patch_check_type_1_direct(); patch_check_type_1_direct();
patch_check_type_1_indirect(); patch_check_type_1_indirect();

View File

@ -76,15 +76,15 @@ namespace utils::hook
} }
} }
std::vector<size_t> signature::process_range(uint8_t* start, const size_t length) const signature::signature_result signature::process_range(uint8_t* start, const size_t length) const
{ {
if (this->has_sse_support()) return this->process_range_vectorized(start, length); if (this->has_sse_support()) return this->process_range_vectorized(start, length);
return this->process_range_linear(start, length); return this->process_range_linear(start, length);
} }
std::vector<size_t> signature::process_range_linear(uint8_t* start, const size_t length) const signature::signature_result signature::process_range_linear(uint8_t* start, const size_t length) const
{ {
std::vector<size_t> result; std::vector<uint8_t*> result;
for (size_t i = 0; i < length; ++i) for (size_t i = 0; i < length; ++i)
{ {
@ -101,16 +101,16 @@ namespace utils::hook
if (j == this->mask_.size()) if (j == this->mask_.size())
{ {
result.push_back(size_t(address)); result.push_back(address);
} }
} }
return result; return result;
} }
std::vector<size_t> signature::process_range_vectorized(uint8_t* start, const size_t length) const signature::signature_result signature::process_range_vectorized(uint8_t* start, const size_t length) const
{ {
std::vector<size_t> result; std::vector<uint8_t*> result;
__declspec(align(16)) char desired_mask[16] = {0}; __declspec(align(16)) char desired_mask[16] = {0};
for (size_t i = 0; i < this->mask_.size(); i++) for (size_t i = 0; i < this->mask_.size(); i++)
@ -133,7 +133,7 @@ namespace utils::hook
if (_mm_test_all_zeros(equivalence, equivalence)) if (_mm_test_all_zeros(equivalence, equivalence))
{ {
result.push_back(size_t(address)); result.push_back(address);
} }
} }
@ -164,7 +164,7 @@ namespace utils::hook
const auto grid = range / cores; const auto grid = range / cores;
std::mutex mutex; std::mutex mutex;
std::vector<size_t> result; std::vector<uint8_t*> result;
std::vector<std::thread> threads; std::vector<std::thread> threads;
for (auto i = 0u; i < cores; ++i) for (auto i = 0u; i < cores; ++i)
@ -173,7 +173,7 @@ namespace utils::hook
const auto length = (i + 1 == cores) ? (this->start_ + this->length_ - sub) - start : grid; const auto length = (i + 1 == cores) ? (this->start_ + this->length_ - sub) - start : grid;
threads.emplace_back([&, start, length]() threads.emplace_back([&, start, length]()
{ {
auto local_result = this->process_range(start, length); const auto local_result = this->process_range(start, length);
if (local_result.empty()) return; if (local_result.empty()) return;
std::lock_guard _(mutex); std::lock_guard _(mutex);

View File

@ -7,33 +7,9 @@ namespace utils::hook
class signature final class signature final
{ {
public: public:
class signature_result using signature_result = std::vector<uint8_t*>;
{
public:
signature_result(std::vector<size_t>&& matches) : matches_(std::move(matches))
{
}
[[nodiscard]] uint8_t* get(const size_t index) const explicit signature(const std::string& pattern, const nt::library& library = {})
{
if (index >= this->count())
{
throw std::runtime_error("Invalid index");
}
return reinterpret_cast<uint8_t*>(this->matches_[index]);
}
[[nodiscard]] size_t count() const
{
return this->matches_.size();
}
private:
std::vector<size_t> matches_;
};
explicit signature(const std::string& pattern, const nt::library library = {})
: signature(pattern, library.get_ptr(), library.get_optional_header()->SizeOfImage) : signature(pattern, library.get_ptr(), library.get_optional_header()->SizeOfImage)
{ {
} }
@ -62,9 +38,9 @@ namespace utils::hook
signature_result process_parallel() const; signature_result process_parallel() const;
signature_result process_serial() const; signature_result process_serial() const;
std::vector<size_t> process_range(uint8_t* start, size_t length) const; signature_result process_range(uint8_t* start, size_t length) const;
std::vector<size_t> process_range_linear(uint8_t* start, size_t length) const; signature_result process_range_linear(uint8_t* start, size_t length) const;
std::vector<size_t> process_range_vectorized(uint8_t* start, size_t length) const; signature_result process_range_vectorized(uint8_t* start, size_t length) const;
bool has_sse_support() const; bool has_sse_support() const;
}; };