Skip to content

Commit

Permalink
Use regular parameter for scan_alignment instead of NTTP
Browse files Browse the repository at this point in the history
ZeroMemes committed Oct 13, 2024
1 parent a3bd74d commit 89dee45
Showing 2 changed files with 47 additions and 36 deletions.
75 changes: 43 additions & 32 deletions include/libhat/Scanner.hpp
Original file line number Diff line number Diff line change
@@ -92,7 +92,7 @@ namespace hat {
using scan_result = scan_result_base<std::byte*>;
using const_scan_result = scan_result_base<const std::byte*>;

enum class scan_alignment {
enum class scan_alignment : uint8_t {
X1 = 1,
X16 = 16
};
@@ -152,8 +152,12 @@ namespace hat {
scan_context() = default;
};

LIBHAT_FORCEINLINE constexpr auto to_stride(const scan_alignment alignment) {
return static_cast<std::underlying_type_t<scan_alignment>>(alignment);
}

template<scan_alignment alignment>
inline constexpr auto alignment_stride = static_cast<std::underlying_type_t<scan_alignment>>(alignment);
inline constexpr auto alignment_stride = to_stride(alignment);

template<std::integral type, scan_alignment alignment>
LIBHAT_FORCEINLINE consteval auto create_alignment_mask() {
@@ -340,26 +344,15 @@ namespace hat {
}
}

/// Perform a signature scan on a specific section of the process module or a specified module
template<scan_alignment alignment = scan_alignment::X1>
scan_result find_pattern(
signature_view signature,
std::string_view section,
process::module mod = process::get_process_module(),
scan_hint hints = scan_hint::none
) {
const auto data = mod.get_section_data(section);
return find_pattern<alignment>(data.begin(), data.end(), signature, hints);
}

/// Root implementation of find_pattern
template<scan_alignment alignment = scan_alignment::X1, detail::byte_input_iterator Iter>
constexpr auto find_pattern(
template<detail::byte_input_iterator Iter>
[[nodiscard]] constexpr auto find_pattern(
const Iter beginIt,
const Iter endIt,
const signature_view signature,
const scan_alignment alignment = scan_alignment::X1,
const scan_hint hints = scan_hint::none
) -> detail::result_type_for<Iter> {
) noexcept -> detail::result_type_for<Iter> {
const auto [offset, trunc] = detail::truncate(signature);
const auto begin = std::to_address(beginIt) + offset;
const auto end = std::to_address(endIt);
@@ -375,19 +368,32 @@ namespace hat {
: nullptr;
}

/// Perform a signature scan on a specific section of the process module or a specified module
[[nodiscard]] inline scan_result find_pattern(
const signature_view signature,
const std::string_view section,
const process::module mod = process::get_process_module(),
const scan_alignment alignment = scan_alignment::X1,
const scan_hint hints = scan_hint::none
) noexcept {
const auto data = mod.get_section_data(section);
return find_pattern(data.begin(), data.end(), signature, alignment, hints);
}

/// Finds all of the matches for the given signature in the input range, and writes the results into the output
/// range. If there is no space in the output range, the function will exit early. The first element of the returned
/// pair is an end iterator into the input range at the point in which the pattern search stopped. The second
/// element of the pair is an end iterator into the output range in which the matched results stop.
template<scan_alignment alignment = scan_alignment::X1, detail::byte_input_iterator In, std::output_iterator<detail::result_type_for<In>> Out>
constexpr auto find_all_pattern(
template<detail::byte_input_iterator In, std::output_iterator<detail::result_type_for<In>> Out>
[[nodiscard]] constexpr auto find_all_pattern(
const In beginIn,
const In endIn,
const Out beginOut,
const Out endOut,
const signature_view signature,
const scan_alignment alignment = scan_alignment::X1,
const scan_hint hints = scan_hint::none
) -> std::pair<In, Out> {
) noexcept -> std::pair<In, Out> {
const auto [offset, trunc] = detail::truncate(signature);
const auto begin = std::to_address(beginIn) + offset;
const auto end = std::to_address(endIn);
@@ -405,27 +411,30 @@ namespace hat {
}
const auto addr = const_cast<typename detail::result_type_for<In>::underlying_type>(result.get() - offset);
*out++ = addr;
i = addr + detail::alignment_stride<alignment>;
i = addr + detail::to_stride(alignment);
}

return std::make_pair(std::next(beginIn, i - begin), out);
}

/// Root implementation of find_all_pattern
template<scan_alignment alignment = scan_alignment::X1, detail::byte_input_iterator In, std::output_iterator<detail::result_type_for<In>> Out>
/// Finds all of the matches for the given signature in the input range, and writes the results into the output
/// iterator. The entire input range will be searched and all results written to the output range. The number of
/// matches found is returned.
template<detail::byte_input_iterator In, std::output_iterator<detail::result_type_for<In>> Out>
constexpr size_t find_all_pattern(
const In beginIn,
const In endIn,
const Out outIn,
const Out beginOut,
const signature_view signature,
const scan_alignment alignment = scan_alignment::X1,
const scan_hint hints = scan_hint::none
) {
) noexcept {
const auto [offset, trunc] = detail::truncate(signature);
const auto begin = std::to_address(beginIn) + offset;
const auto end = std::to_address(endIn);

auto i = begin;
auto out = outIn;
auto out = beginOut;
size_t matches{};

const auto context = detail::scan_context::create(trunc, alignment, hints);
@@ -437,22 +446,24 @@ namespace hat {
}
const auto addr = const_cast<typename detail::result_type_for<In>::underlying_type>(result.get() - offset);
*out++ = addr;
i = addr + detail::alignment_stride<alignment>;
i = addr + detail::to_stride(alignment);
matches++;
}

return matches;
}

/// Wrapper around the root find_all_pattern implementation that returns a std::vector of the results
template<scan_alignment alignment = scan_alignment::X1, detail::byte_input_iterator In>
constexpr auto find_all_pattern(
template<detail::byte_input_iterator In>
[[nodiscard]] constexpr auto find_all_pattern(
const In beginIt,
const In endIt,
const signature_view signature
) -> std::vector<detail::result_type_for<In>> {
const signature_view signature,
const scan_alignment alignment = scan_alignment::X1,
const scan_hint hints = scan_hint::none
) noexcept -> std::vector<detail::result_type_for<In>> {
std::vector<detail::result_type_for<In>> results{};
find_all_pattern<alignment>(beginIt, endIt, std::back_inserter(results), signature);
find_all_pattern(beginIt, endIt, std::back_inserter(results), signature, alignment, hints);
return results;
}
}
8 changes: 4 additions & 4 deletions src/c/libhat.cpp
Original file line number Diff line number Diff line change
@@ -61,18 +61,18 @@ LIBHAT_API const void* libhat_find_pattern(
signature->count
};

const auto find_pattern = [=]<hat::scan_alignment A>() {
const auto find_pattern = [=](const hat::scan_alignment alignment) {
const auto begin = static_cast<const std::byte*>(buffer);
const auto end = static_cast<const std::byte*>(buffer) + size;
const auto result = hat::find_pattern<A>(begin, end, view);
const auto result = hat::find_pattern(begin, end, view, alignment);
return result.has_result() ? result.get() : nullptr;
};

switch (align) {
case scan_alignment_x1:
return find_pattern.operator()<hat::scan_alignment::X1>();
return find_pattern(hat::scan_alignment::X1);
case scan_alignment_x16:
return find_pattern.operator()<hat::scan_alignment::X16>();
return find_pattern(hat::scan_alignment::X16);
}
exit(EXIT_FAILURE);
}

0 comments on commit 89dee45

Please sign in to comment.