Better signature processing
This commit is contained in:
parent
3752853e2e
commit
767955685a
@ -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();
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user