Selfpatch ipin and dpin patching

This commit is contained in:
York Jasper Niebuhr 2025-10-28 01:47:40 +01:00
parent 1b184f5740
commit 989aa63881
3 changed files with 182 additions and 1 deletions

View File

@ -1,12 +1,138 @@
#include "patcher.h"
#include "targets.h"
// TODO
#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>
#define PAGE_MASK ~(0x1000ull - 1)
static int get_prot(void* addr, int* prot) {
FILE* f = fopen("/proc/self/maps", "r");
if (!f)
return -1;
uintptr_t query = (uintptr_t)addr;
char line[512];
while (fgets(line, sizeof(line), f)) {
uintptr_t start, end;
char perms[5];
if (sscanf(line, "%lx-%lx %4s", &start, &end, perms) != 3)
continue;
if (query < start || query >= end)
continue;
*prot = 0;
if (perms[0] == 'r')
*prot |= PROT_READ;
if (perms[1] == 'w')
*prot |= PROT_WRITE;
if (perms[2] == 'x')
*prot |= PROT_EXEC;
fclose(f);
return 0;
}
fclose(f);
return -1;
}
static int patch_immediate(void* ptr, uint32_t size, uint32_t v) {
if (size != 4)
return -1;
memcpy(ptr, &v, size);
return 0;
}
int spslr_ipatch(void* ptr, uint32_t size, uint32_t target, uint32_t field) {
uint32_t field_offset;
if (spslr_get_randomized_field_offset(target, field, &field_offset))
return -1;
int original_prot;
if (get_prot(ptr, &original_prot))
return -1;
uint64_t ptr_uint = (uint64_t)ptr;
uint64_t ptr_page = ptr_uint & PAGE_MASK;
uint64_t corrected_size = size + (ptr_uint - ptr_page);
int tmp_prot = original_prot | PROT_WRITE;
if (tmp_prot != original_prot)
mprotect((void*)ptr_page, corrected_size, tmp_prot);
if (patch_immediate(ptr, size, field_offset))
return -1;
if (tmp_prot != original_prot)
mprotect((void*)ptr_page, corrected_size, original_prot);
return 0;
}
static int reorder_object(const void* src, void* dst, uint32_t target) {
if (!src || !dst)
return -1;
uint32_t field_count;
if (spslr_get_target_fieldcnt(target, &field_count))
return -1;
const uint8_t* src_countable = (const uint8_t*)src;
uint8_t* dst_countable = (uint8_t*)dst;
for (uint32_t i = 0; i < field_count; i++) {
uint32_t field_offset, field_size, field_initial_offset;
if (spslr_get_target_field_ordered(target, i, &field_offset, &field_size, &field_initial_offset))
return -1;
memcpy(dst_countable + field_offset, src_countable + field_initial_offset, field_size);
}
return 0;
}
int spslr_dpatch(void* ptr, uint32_t target) {
uint32_t target_size;
if (spslr_get_target_size(target, &target_size))
return -1;
int original_prot;
if (get_prot(ptr, &original_prot))
return -1;
uint64_t ptr_uint = (uint64_t)ptr;
uint64_t ptr_page = ptr_uint & PAGE_MASK;
uint64_t corrected_size = target_size + (ptr_uint - ptr_page);
int tmp_prot = original_prot | PROT_WRITE | PROT_READ;
if (tmp_prot != original_prot)
mprotect((void*)ptr_page, corrected_size, tmp_prot);
void* tmp_obj = malloc(target_size);
if (!tmp_obj)
return -1;
memset(tmp_obj, 0, target_size);
if (reorder_object(ptr, tmp_obj, target))
return -1;
memcpy(ptr, tmp_obj, target_size);
free(tmp_obj);
if (tmp_prot != original_prot)
mprotect((void*)ptr_page, corrected_size, original_prot);
return 0;
}

View File

@ -361,6 +361,55 @@ int spslr_randomize(uint32_t target) {
return 0;
}
int spslr_get_randomized_field_offset(uint32_t target, uint32_t field, uint32_t* offset) {
const struct Target* t = find_target(target);
if (!t || !offset)
return -1;
if (field >= t->field_count)
return -1;
if (!t->final_fields)
return -1;
*offset = t->final_fields[field].offset;
return 0;
}
int spslr_get_target_size(uint32_t target, uint32_t* size) {
const struct Target* t = find_target(target);
if (!t || !size)
return -1;
*size = t->size;
return 0;
}
int spslr_get_target_fieldcnt(uint32_t target, uint32_t* cnt) {
const struct Target* t = find_target(target);
if (!t || !cnt)
return -1;
*cnt = t->field_count;
return 0;
}
int spslr_get_target_field_ordered(uint32_t target, uint32_t field, uint32_t* offset,
uint32_t* size, uint32_t* initial_offset) {
const struct Target* t = find_target(target);
if (!t || !offset || !size || !initial_offset)
return -1;
if (field >= t->field_count)
return -1;
const struct Field* f = &t->fields[field];
*offset = f->offset;
*size = f->size;
*initial_offset = f->initial_offset;
return 0;
}
void spslr_targets_clear() {
clear_targets();
}

View File

@ -7,6 +7,12 @@ int spslr_target(uint32_t uid, uint32_t size, uint32_t fieldcnt);
int spslr_field(uint32_t target, uint32_t offset, uint32_t size, uint32_t alignment, uint32_t flags);
int spslr_randomize(uint32_t target);
int spslr_get_randomized_field_offset(uint32_t target, uint32_t field, uint32_t* offset);
int spslr_get_target_size(uint32_t target, uint32_t* size);
int spslr_get_target_fieldcnt(uint32_t target, uint32_t* cnt);
int spslr_get_target_field_ordered(uint32_t target, uint32_t field, uint32_t* offset,
uint32_t* size, uint32_t* initial_offset);
void spslr_targets_clear();
#endif