Selfpatch ipin and dpin patching
This commit is contained in:
parent
1b184f5740
commit
989aa63881
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user