Better signature processing
This commit is contained in:
parent
3752853e2e
commit
767955685a
@ -352,9 +352,10 @@ namespace arxan
|
||||
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);
|
||||
}
|
||||
|
||||
@ -514,17 +515,15 @@ namespace arxan
|
||||
|
||||
// mov [rbp+??h], eax
|
||||
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);
|
||||
}
|
||||
|
||||
// xor eax, [rbp+??h]
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -565,17 +564,15 @@ namespace arxan
|
||||
|
||||
// mov rax, [rax]; jmp ...
|
||||
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);
|
||||
}
|
||||
|
||||
// mov eax, [rax]; jmp ...
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -583,10 +580,8 @@ namespace arxan
|
||||
void patch_check_type_2_direct()
|
||||
{
|
||||
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)
|
||||
{
|
||||
a.push(rax);
|
||||
@ -611,9 +606,8 @@ namespace arxan
|
||||
void patch_check_type_2_indirect()
|
||||
{
|
||||
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);
|
||||
|
||||
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()
|
||||
{
|
||||
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)
|
||||
{
|
||||
a.mov(rax, qword_ptr(rax, rdx));
|
||||
@ -665,9 +657,8 @@ namespace arxan
|
||||
void patch_check_type_4_indirect()
|
||||
{
|
||||
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);
|
||||
|
||||
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()
|
||||
{
|
||||
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
|
||||
// Prefixed 0x41 encodes a different instruction
|
||||
if (addr[-1] == 0x41)
|
||||
@ -727,10 +716,8 @@ namespace arxan
|
||||
void patch_check_type_5_indirect()
|
||||
{
|
||||
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
|
||||
// Prefixed 0x41 encodes a different instruction
|
||||
if (addr[-1] == 0x41)
|
||||
@ -799,6 +786,12 @@ namespace arxan
|
||||
|
||||
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_indirect();
|
||||
|
@ -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);
|
||||
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)
|
||||
{
|
||||
@ -101,16 +101,16 @@ namespace utils::hook
|
||||
|
||||
if (j == this->mask_.size())
|
||||
{
|
||||
result.push_back(size_t(address));
|
||||
result.push_back(address);
|
||||
}
|
||||
}
|
||||
|
||||
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};
|
||||
|
||||
for (size_t i = 0; i < this->mask_.size(); i++)
|
||||
@ -133,7 +133,7 @@ namespace utils::hook
|
||||
|
||||
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;
|
||||
|
||||
std::mutex mutex;
|
||||
std::vector<size_t> result;
|
||||
std::vector<uint8_t*> result;
|
||||
std::vector<std::thread> threads;
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
std::lock_guard _(mutex);
|
||||
|
@ -7,33 +7,9 @@ namespace utils::hook
|
||||
class signature final
|
||||
{
|
||||
public:
|
||||
class signature_result
|
||||
{
|
||||
public:
|
||||
signature_result(std::vector<size_t>&& matches) : matches_(std::move(matches))
|
||||
{
|
||||
}
|
||||
using signature_result = std::vector<uint8_t*>;
|
||||
|
||||
[[nodiscard]] uint8_t* get(const size_t index) const
|
||||
{
|
||||
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 = {})
|
||||
explicit signature(const std::string& pattern, const nt::library& library = {})
|
||||
: 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_serial() const;
|
||||
std::vector<size_t> process_range(uint8_t* start, size_t length) const;
|
||||
std::vector<size_t> 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(uint8_t* start, size_t length) const;
|
||||
signature_result process_range_linear(uint8_t* start, size_t length) const;
|
||||
signature_result process_range_vectorized(uint8_t* start, size_t length) const;
|
||||
|
||||
bool has_sse_support() const;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user