-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add signature scanning #58
Open
Loomeh
wants to merge
18
commits into
wins1ey:main
Choose a base branch
from
Loomeh:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
77e3462
add signature scanning
Loomeh 5938070
bug fixes
Loomeh 1a87cbd
offset handling
Loomeh 76311b4
Update signature.c
Loomeh 4a70d1d
convert sig scan result to hex before returning
Loomeh da0a1d6
add sig_scan to docs
Loomeh fb9573b
add note about sig scan performance to docs
Loomeh 3e30a3f
fix docs formatting
Loomeh 520b7e4
remove unused include
Loomeh 5dc47bb
properly handle FF bytes/integer underflow
Loomeh 2376ebb
fix formatting
Loomeh 164a019
update docs with sig_scan example
Loomeh f3c2ae7
Add info regarding Lua's string to number conversions.
Loomeh 7b12731
fix formatting (again)
Loomeh e2d4b51
prefix return string with "0x" and improve error handling
Loomeh ee9e6b6
Update build.yml
Loomeh 3127706
Revert build.yml
Loomeh c68fa4b
Update docs
Loomeh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,234 @@ | ||
#include "signature.h" | ||
#include <errno.h> | ||
#include <fcntl.h> | ||
#include <inttypes.h> | ||
#include <stdarg.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <sys/uio.h> | ||
#include <unistd.h> | ||
|
||
#include "memory.h" | ||
#include "process.h" | ||
|
||
#include <luajit.h> | ||
|
||
extern game_process process; | ||
|
||
// Error handling macro | ||
#define HANDLE_ERROR(msg) \ | ||
do { \ | ||
perror(msg); \ | ||
return NULL; \ | ||
} while (0) | ||
|
||
// Error logging function | ||
void log_error(const char* format, ...) | ||
{ | ||
va_list args; | ||
va_start(args, format); | ||
fprintf(stderr, "Error in sig_scan: "); | ||
vfprintf(stderr, format, args); | ||
fprintf(stderr, "\n"); | ||
va_end(args); | ||
} | ||
|
||
MemoryRegion* get_memory_regions(pid_t pid, int* count) | ||
{ | ||
char maps_path[256]; | ||
if (snprintf(maps_path, sizeof(maps_path), "/proc/%d/maps", pid) < 0) { | ||
HANDLE_ERROR("Failed to create maps path"); | ||
} | ||
|
||
FILE* maps_file = fopen(maps_path, "r"); | ||
if (!maps_file) { | ||
HANDLE_ERROR("Failed to open maps file"); | ||
} | ||
|
||
MemoryRegion* regions = NULL; | ||
int capacity = 0; | ||
*count = 0; | ||
|
||
char line[256]; | ||
while (fgets(line, sizeof(line), maps_file)) { | ||
if (*count >= capacity) { | ||
capacity = capacity == 0 ? 10 : capacity * 2; | ||
MemoryRegion* temp = realloc(regions, capacity * sizeof(MemoryRegion)); | ||
if (!temp) { | ||
free(regions); | ||
fclose(maps_file); | ||
HANDLE_ERROR("Failed to allocate memory for regions"); | ||
} | ||
regions = temp; | ||
} | ||
|
||
uintptr_t start, end; | ||
if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR, &start, &end) != 2) { | ||
continue; // Skip lines that don't match the expected format | ||
} | ||
regions[*count].start = start; | ||
regions[*count].end = end; | ||
(*count)++; | ||
} | ||
|
||
fclose(maps_file); | ||
return regions; | ||
} | ||
|
||
bool match_pattern(const uint8_t* data, const uint16_t* pattern, size_t pattern_size) | ||
{ | ||
for (size_t i = 0; i < pattern_size; ++i) { | ||
uint8_t byte = pattern[i] & 0xFF; | ||
bool ignore = (pattern[i] >> 8) & 0x1; | ||
if (!ignore && data[i] != byte) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
uint16_t* convert_signature(const char* signature, size_t* pattern_size) | ||
{ | ||
char* signature_copy = strdup(signature); | ||
if (!signature_copy) { | ||
return NULL; | ||
} | ||
|
||
char* token = strtok(signature_copy, " "); | ||
size_t size = 0; | ||
size_t capacity = 10; | ||
uint16_t* pattern = (uint16_t*)malloc(capacity * sizeof(uint16_t)); | ||
if (!pattern) { | ||
free(signature_copy); | ||
return NULL; | ||
} | ||
|
||
while (token != NULL) { | ||
if (size >= capacity) { | ||
capacity *= 2; | ||
uint16_t* temp = (uint16_t*)realloc(pattern, capacity * sizeof(uint16_t)); | ||
if (!temp) { | ||
free(pattern); | ||
free(signature_copy); | ||
return NULL; | ||
} | ||
pattern = temp; | ||
} | ||
|
||
if (strcmp(token, "??") == 0) { | ||
pattern[size] = 0xFF00; // Set the upper byte to 1 to indicate ignoring this byte | ||
} else { | ||
pattern[size] = strtol(token, NULL, 16); | ||
} | ||
size++; | ||
token = strtok(NULL, " "); | ||
} | ||
|
||
free(signature_copy); | ||
*pattern_size = size; | ||
return pattern; | ||
} | ||
|
||
bool validate_process_memory(pid_t pid, uintptr_t address, void* buffer, size_t size) | ||
{ | ||
struct iovec local_iov = { buffer, size }; | ||
struct iovec remote_iov = { (void*)address, size }; | ||
ssize_t nread = process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0); | ||
|
||
return nread == (ssize_t)size; | ||
} | ||
|
||
int perform_sig_scan(lua_State* L) | ||
{ | ||
if (lua_gettop(L) != 2) { | ||
log_error("Invalid number of arguments: expected 2 (signature, offset)"); | ||
lua_pushnil(L); | ||
return 1; | ||
} | ||
|
||
if (!lua_isstring(L, 1) || !lua_isnumber(L, 2)) { | ||
log_error("Invalid argument types: expected (string, number)"); | ||
lua_pushnil(L); | ||
return 1; | ||
} | ||
|
||
pid_t p_pid = process.pid; | ||
const char* signature = lua_tostring(L, 1); | ||
int offset = lua_tointeger(L, 2); | ||
|
||
// Validate signature string | ||
if (strlen(signature) == 0) { | ||
log_error("Signature string cannot be empty"); | ||
lua_pushnil(L); | ||
return 1; | ||
} | ||
|
||
size_t pattern_length; | ||
uint16_t* pattern = convert_signature(signature, &pattern_length); | ||
if (!pattern) { | ||
log_error("Failed to convert signature"); | ||
lua_pushnil(L); | ||
return 1; | ||
} | ||
|
||
int regions_count = 0; | ||
MemoryRegion* regions = get_memory_regions(p_pid, ®ions_count); | ||
if (!regions) { | ||
free(pattern); | ||
log_error("Failed to get memory regions"); | ||
lua_pushnil(L); | ||
return 1; | ||
} | ||
|
||
for (int i = 0; i < regions_count; i++) { | ||
MemoryRegion region = regions[i]; | ||
ssize_t region_size = region.end - region.start; | ||
uint8_t* buffer = malloc(region_size); | ||
if (!buffer) { | ||
free(pattern); | ||
free(regions); | ||
log_error("Failed to allocate memory for region buffer"); | ||
lua_pushnil(L); | ||
return 1; | ||
} | ||
|
||
if (!validate_process_memory(p_pid, region.start, buffer, region_size)) { | ||
free(buffer); | ||
continue; // Continue to next region | ||
} | ||
|
||
for (size_t j = 0; j <= region_size - pattern_length; ++j) { | ||
if (match_pattern(buffer + j, pattern, pattern_length)) { | ||
uintptr_t result = region.start + j + offset; | ||
|
||
char full_hex_str[32]; // Increased buffer size for safety | ||
if (snprintf(full_hex_str, sizeof(full_hex_str), "0x%" PRIxPTR, result) < 0) { | ||
free(buffer); | ||
free(pattern); | ||
free(regions); | ||
log_error("Failed to convert result to string"); | ||
lua_pushnil(L); | ||
return 1; | ||
} | ||
|
||
free(buffer); | ||
free(pattern); | ||
free(regions); | ||
|
||
lua_pushstring(L, full_hex_str); | ||
return 1; | ||
} | ||
} | ||
|
||
free(buffer); | ||
} | ||
|
||
free(pattern); | ||
free(regions); | ||
|
||
// No match found | ||
log_error("No match found for the given signature"); | ||
lua_pushnil(L); | ||
return 1; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#ifndef __SIGNATURE_H__ | ||
#define __SIGNATURE_H__ | ||
|
||
#include <luajit.h> | ||
#include <stdbool.h> | ||
#include <stddef.h> | ||
#include <stdint.h> | ||
#include <sys/types.h> | ||
|
||
typedef struct { | ||
uintptr_t start; | ||
uintptr_t end; | ||
} MemoryRegion; | ||
|
||
MemoryRegion* get_memory_regions(pid_t pid, int* count); | ||
bool match_pattern(const uint8_t* data, const uint16_t* pattern, size_t pattern_size); | ||
uint16_t* convert_signature(const char* signature, size_t* pattern_size); | ||
bool validate_process_memory(pid_t pid, uintptr_t address, void* buffer, size_t size); | ||
int perform_sig_scan(lua_State* L); | ||
|
||
#endif /* __SIGNATURE_H__ */ |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same problem here, this will NEVER be true (if sig_scan returns "0")