Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions bindings/java/src/main/java/me/zero/libhat/Hat.java
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,20 @@ public static OptionalInt findPattern(@NotNull final Signature signature, @NotNu
final long start = Pointer.nativeValue(Native.getDirectBufferPointer(buffer)) + buffer.position();
final int count = buffer.remaining();

final Pointer result = Libhat.INSTANCE.libhat_find_pattern(
final PointerByReference out = new PointerByReference();
final int status = Libhat.INSTANCE.libhat_find_pattern(
Objects.requireNonNull(signature.handle),
new Pointer(start),
new Libhat.size_t(count),
out,
alignment.alignment(),
ScanHint.toFlags(hints)
);
if (status != 0) {
throw new LibhatException(status);
}

final Pointer result = out.getValue();
if (result == Pointer.NULL) {
return OptionalInt.empty();
}
Expand Down Expand Up @@ -190,15 +196,20 @@ public static Optional<Pointer> findPattern(@NotNull final Signature signature,
Objects.requireNonNull(section);
Objects.requireNonNull(alignment);

final Pointer result = Libhat.INSTANCE.libhat_find_pattern_mod(
final PointerByReference out = new PointerByReference();
final int status = Libhat.INSTANCE.libhat_find_pattern_mod(
Objects.requireNonNull(signature.handle),
Objects.requireNonNull(module.handle),
section,
out,
alignment.alignment(),
ScanHint.toFlags(hints)
);
if (status != 0) {
throw new LibhatException(status);
}

return Optional.ofNullable(result);
return Optional.ofNullable(out.getValue());
}

/**
Expand Down
51 changes: 44 additions & 7 deletions bindings/java/src/main/java/me/zero/libhat/ProcessModule.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package me.zero.libhat;

import com.sun.jna.Pointer;
import com.sun.jna.ptr.PointerByReference;
import me.zero.libhat.jna.Libhat;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -32,20 +33,33 @@ public void close() {

/**
* @return The base address of this module, as a {@code long}.
* @throws LibhatException if an internal error occurred
*/
public long getBaseAddress() {
return Libhat.INSTANCE.libhat_module_address(this.checkHandle()).longValue();
PointerByReference out = new PointerByReference();
final int status = Libhat.INSTANCE.libhat_module_address(this.checkHandle(), out);
if (status != 0) {
throw new LibhatException(status);
}
return Pointer.nativeValue(out.getValue());
}

/**
* Returns the complete memory region for this module. This may include portions which are uncommitted.
* To verify whether the region is safe to read, use {@link Hat#isReadable(ByteBuffer)}.
*
* @return The module data
* @throws IllegalStateException If the module data was empty
* @throws IllegalStateException if the module data was empty
* @throws LibhatException if an internal error occurred
*/
public @NotNull ByteBuffer getModuleData() {
final ByteBuffer data = Libhat.INSTANCE.libhat_module_get_data(this.checkHandle()).toBuffer();
final Libhat.Span.ByReference out = new Libhat.Span.ByReference();
final int status = Libhat.INSTANCE.libhat_module_get_data(this.checkHandle(), out);
if (status != 0) {
throw new LibhatException(status);
}

final ByteBuffer data = out.toBuffer();
if (data == null) {
throw new IllegalStateException("Module data was unexpectedly empty");
}
Expand All @@ -58,9 +72,16 @@ public long getBaseAddress() {
* by name, the first executable region defined by the module will be returned instead.
*
* @return The module's executable data, or {@link Optional#empty()} if it cannot be found.
* @throws LibhatException if an internal error occurred
*/
public @NotNull Optional<ByteBuffer> getExecutableData() {
return Optional.ofNullable(Libhat.INSTANCE.libhat_module_get_executable_data(this.checkHandle()).toBuffer());
final Libhat.Span.ByReference out = new Libhat.Span.ByReference();
final int status = Libhat.INSTANCE.libhat_module_get_executable_data(this.checkHandle(), out);
if (status != 0) {
throw new LibhatException(status);
}

return Optional.ofNullable(out.toBuffer());
}

/**
Expand All @@ -71,10 +92,18 @@ public long getBaseAddress() {
* @param name The section name
* @return The data for the section, or {@link Optional#empty()} if it cannot be found.
* @throws NullPointerException if any arguments are {@code null}
* @throws LibhatException if an internal error occurred
*/
public @NotNull Optional<ByteBuffer> getSectionData(@NotNull final String name) {
Objects.requireNonNull(name);
return Optional.ofNullable(Libhat.INSTANCE.libhat_module_get_section_data(this.checkHandle(), name).toBuffer());

final Libhat.Span.ByReference out = new Libhat.Span.ByReference();
final int status = Libhat.INSTANCE.libhat_module_get_section_data(this.checkHandle(), name, out);
if (status != 0) {
throw new LibhatException(status);
}

return Optional.ofNullable(out.toBuffer());
}

/**
Expand All @@ -86,11 +115,15 @@ public long getBaseAddress() {
*
* @param callback The callback to accept each section
* @throws NullPointerException if any arguments are {@code null}
* @throws LibhatException if an internal error occurred
*/
public void forEachSection(@NotNull final Predicate<@NotNull Section> callback) {
Objects.requireNonNull(callback);
Libhat.INSTANCE.libhat_module_for_each_section(this.checkHandle(), (name, data, prot, ud)
final int status = Libhat.INSTANCE.libhat_module_for_each_section(this.checkHandle(), (name, data, prot, ud)
-> callback.test(new Section(name, data.toBuffer(), Protection.fromFlags(prot))), null);
if (status != 0) {
throw new LibhatException(status);
}
}

/**
Expand All @@ -101,11 +134,15 @@ public void forEachSection(@NotNull final Predicate<@NotNull Section> callback)
*
* @param callback The callback to accept each segment
* @throws NullPointerException if any arguments are {@code null}
* @throws LibhatException if an internal error occurred
*/
public void forEachSegment(@NotNull final Predicate<@NotNull Segment> callback) {
Objects.requireNonNull(callback);
Libhat.INSTANCE.libhat_module_for_each_segment(this.checkHandle(), (data, prot, ud)
final int status = Libhat.INSTANCE.libhat_module_for_each_segment(this.checkHandle(), (data, prot, ud)
-> callback.test(new Segment(data.toBuffer(), Protection.fromFlags(prot))), null);
if (status != 0) {
throw new LibhatException(status);
}
}

@NotNull
Expand Down
39 changes: 21 additions & 18 deletions bindings/java/src/main/java/me/zero/libhat/jna/Libhat.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public uintptr_t(long value) {
// Structures
// ------------------------------------------------------------------------

@Structure.FieldOrder({ "data", "size" })
@Structure.FieldOrder({"data", "size"})
class Span extends Structure {
public Pointer data;
public size_t size;
Expand All @@ -66,6 +66,7 @@ public final ByteBuffer toBuffer() {
}

public static class ByValue extends Span implements Structure.ByValue {}
public static class ByReference extends Span implements Structure.ByReference {}
}

// ------------------------------------------------------------------------
Expand Down Expand Up @@ -118,64 +119,66 @@ interface ForEachSegmentCallback extends Callback {
int libhat_create_signature(byte[] bytes, byte[] mask, size_t size, PointerByReference signatureOut);

/*
* const void* libhat_find_pattern(
* libhat_status libhat_find_pattern(
* const libhat_signature* signature,
* const void* buffer,
* size_t size,
* const void** resultOut,
* libhat_alignment align,
* libhat_hint hints
* libhat_hint hints
* );
*/
Pointer libhat_find_pattern(Pointer signature, Pointer buffer, size_t size, int align, int hints);
int libhat_find_pattern(Pointer signature, Pointer buffer, size_t size, PointerByReference resultOut, int align, int hints);

/*
* const void* libhat_find_pattern_mod(
* libhat_status libhat_find_pattern_mod(
* const libhat_signature* signature,
* const libhat_module* module,
* const char* section,
* const void** resultOut,
* libhat_alignment align,
* libhat_hint hints
* );
*/
Pointer libhat_find_pattern_mod(Pointer signature, Pointer module, String section, int align, int hints);
int libhat_find_pattern_mod(Pointer signature, Pointer module, String section, PointerByReference resultOut, int align, int hints);

/*
* uintptr_t libhat_module_address(const libhat_module* module);
* libhat_status libhat_module_address(const libhat_module* module, uintptr_t* out);
*/
uintptr_t libhat_module_address(Pointer module);
int libhat_module_address(Pointer module, PointerByReference out);

/*
* libhat_span libhat_module_get_data(const libhat_module* module);
* libhat_status libhat_module_get_data(const libhat_module* module, libhat_span* out);
*/
Span.ByValue libhat_module_get_data(Pointer module);
int libhat_module_get_data(Pointer module, Span.ByReference data);

/*
* libhat_span libhat_module_get_executable_data(const libhat_module* module);
* libhat_status libhat_module_get_executable_data(const libhat_module* module, libhat_span* out);
*/
Span.ByValue libhat_module_get_executable_data(Pointer module);
int libhat_module_get_executable_data(Pointer module, Span.ByReference data);

/*
* libhat_span libhat_module_get_section_data(const libhat_module* module, const char* name);
* libhat_status libhat_module_get_section_data(const libhat_module* module, const char* name, libhat_span* out);
*/
Span.ByValue libhat_module_get_section_data(Pointer module, String name);
int libhat_module_get_section_data(Pointer module, String name, Span.ByReference data);

/*
* void libhat_module_for_each_section(
* libhat_status libhat_module_for_each_section(
* const libhat_module* module,
* libhat_for_each_section_cb callback,
* void* user_data
* );
*/
void libhat_module_for_each_section(Pointer module, ForEachSectionCallback callback, Pointer userData);
int libhat_module_for_each_section(Pointer module, ForEachSectionCallback callback, Pointer userData);

/*
* void libhat_module_for_each_segment(
* libhat_status libhat_module_for_each_segment(
* const libhat_module* module,
* libhat_for_each_segment_cb callback,
* void* user_data
* );
*/
void libhat_module_for_each_segment(Pointer module, ForEachSegmentCallback callback, Pointer userData);
int libhat_module_for_each_segment(Pointer module, ForEachSegmentCallback callback, Pointer userData);

/*
* bool libhat_is_readable(const void* data, size_t size);
Expand Down
20 changes: 12 additions & 8 deletions include/libhat/c/libhat.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ typedef enum libhat_status {
libhat_err_sig_empty_signature,
libhat_err_sig_expected_wildcard,
libhat_err_sig_invalid_token_length,
libhat_err_invalid_argument_value,
libhat_err_invalid_argument_type,
} libhat_status;

typedef enum libhat_alignment {
Expand Down Expand Up @@ -89,37 +91,39 @@ LIBHAT_API libhat_status libhat_create_signature(
const libhat_signature** signatureOut
);

LIBHAT_API const void* libhat_find_pattern(
LIBHAT_API libhat_status libhat_find_pattern(
const libhat_signature* signature,
const void* buffer,
size_t size,
const void** resultOut,
libhat_alignment align = libhat_alignment_x1,
libhat_hint hints = libhat_hint_none
);

LIBHAT_API const void* libhat_find_pattern_mod(
LIBHAT_API libhat_status libhat_find_pattern_mod(
const libhat_signature* signature,
const libhat_module* module,
const char* section,
const void** resultOut,
libhat_alignment align = libhat_alignment_x1,
libhat_hint hints = libhat_hint_none
);

LIBHAT_API uintptr_t libhat_module_address(const libhat_module* module);
LIBHAT_API libhat_status libhat_module_address(const libhat_module* module, uintptr_t* out);

LIBHAT_API libhat_span libhat_module_get_data(const libhat_module* module);
LIBHAT_API libhat_status libhat_module_get_data(const libhat_module* module, libhat_span* out);

LIBHAT_API libhat_span libhat_module_get_executable_data(const libhat_module* module);
LIBHAT_API libhat_status libhat_module_get_executable_data(const libhat_module* module, libhat_span* out);

LIBHAT_API libhat_span libhat_module_get_section_data(const libhat_module* module, const char* name);
LIBHAT_API libhat_status libhat_module_get_section_data(const libhat_module* module, const char* name, libhat_span* out);

LIBHAT_API void libhat_module_for_each_section(
LIBHAT_API libhat_status libhat_module_for_each_section(
const libhat_module* module,
libhat_for_each_section_cb callback,
void* user_data
);

LIBHAT_API void libhat_module_for_each_segment(
LIBHAT_API libhat_status libhat_module_for_each_segment(
const libhat_module* module,
libhat_for_each_segment_cb callback,
void* user_data
Expand Down
Loading
Loading