Selfpatch ipin and dpin patching
This commit is contained in:
parent
1b184f5740
commit
989aa63881
@ -1,12 +1,138 @@
|
|||||||
#include "patcher.h"
|
#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) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int spslr_dpatch(void* ptr, uint32_t target) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -361,6 +361,55 @@ int spslr_randomize(uint32_t target) {
|
|||||||
return 0;
|
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() {
|
void spslr_targets_clear() {
|
||||||
clear_targets();
|
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_field(uint32_t target, uint32_t offset, uint32_t size, uint32_t alignment, uint32_t flags);
|
||||||
int spslr_randomize(uint32_t target);
|
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();
|
void spslr_targets_clear();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user