Untested selfpatch randomizer

This commit is contained in:
York Jasper Niebuhr 2025-10-27 00:37:42 +01:00
parent 49d339e424
commit 8a3f325738

View File

@ -1,6 +1,15 @@
#include "targets.h"
#include <stdlib.h>
#include <time.h>
static void seed_rand_time() {
srand(time(NULL));
}
static uint32_t rand_uint32() {
return (uint32_t)rand();
}
struct Field {
uint32_t initial_offset;
@ -121,8 +130,163 @@ int spslr_field(uint32_t target, uint32_t offset, uint32_t size, uint32_t flags)
return 0;
}
struct ShuffleRegion {
uint32_t begin, end;
uint32_t fill_begin, fill_end;
};
static uint32_t field_alignment(const struct Field* field) {
return field->size; // Note -> alignments should be gathered by pinpoint plugin
}
static void target_get_origin_region(const struct Target* target, struct ShuffleRegion* region, uint32_t idx) {
region->fill_begin = target->fields[idx].offset;
region->fill_end = region->fill_begin + target->fields[idx].size;
if (idx <= 0)
region->begin = 0;
else
region->begin = target->fields[idx - 1].offset + target->fields[idx - 1].size;
if (idx >= target->field_count - 1)
region->end = target->size;
else
region->end = target->fields[idx + 1].offset;
}
static uint32_t target_get_shuffle_options(const struct Target* target, uint32_t* options,
const struct ShuffleRegion* origin, uint32_t alignment) {
uint32_t count = 0;
uint32_t current_field = 0;
for (uint32_t offset = 0; offset < target->size; offset += alignment) {
// Placing the origin region here or further would exceed struct boundaries
uint32_t option_would_end = offset + (origin->fill_end - origin->fill_begin);
if (option_would_end > target->size)
break;
// Fields that end before offset are irrelevant at this point
while (current_field < target->field_count && target->fields[current_field].offset
+ target->fields[current_field].size <= offset) current_field++;
// If origin->fill_begin was placed at offset, could all fields that overlap with range swap with origin?
int conflict = 0;
uint32_t origin_region_ptr = origin->begin;
for (uint32_t it = current_field; it < target->field_count; it++) {
struct Field* f = &target->fields[it];
if (f->offset >= option_would_end)
break;
// Could field be placed in origin?
uint32_t falign = field_alignment(f);
if (origin_region_ptr % falign != 0)
origin_region_ptr += falign - (origin_region_ptr % falign);
origin_region_ptr += f->size;
if (origin_region_ptr > origin->end) {
conflict = 1;
break;
}
}
if (!conflict)
options[count++] = offset;
}
return count;
}
static void target_swap(struct Target* target, uint32_t origin_idx, const struct ShuffleRegion* origin_region,
uint32_t new_offset) {
int origin_pulled = 0;
uint32_t origin_region_ptr = origin_region->begin;
uint32_t option_fill_end = new_offset + (origin_region->fill_end - origin_region->fill_begin);
for (uint32_t it = 0; it < target->field_count; it++) {
// Fields that end before new_offset can stay there
if (target->fields[it].offset + target->fields[it].size <= new_offset)
continue;
// Fields that start after where origin goes are irrelevant
if (target->fields[it].offset >= option_fill_end)
break;
uint32_t falign = field_alignment(&target->fields[it]);
if (origin_region_ptr % falign != 0)
origin_region_ptr += falign - (origin_region_ptr % falign);
// First field in swap region is exchanged with origin
if (!origin_pulled) {
origin_pulled = 1;
struct Field tmp = target->fields[it];
target->fields[it] = target->fields[origin_idx];
target->fields[origin_idx] = tmp;
// Update origin field
target->fields[it].offset = new_offset;
// Update swapped field
target->fields[origin_idx].offset = origin_region_ptr;
origin_region_ptr += target->fields[origin_idx].size;
continue;
}
// For all other fields in swap region, pull all until origin_idx one forward and place at origin_idx
struct Field tmp = target->fields[it];
for (uint32_t pull_it = it + 1; pull_it <= origin_idx; pull_it++)
target->fields[it - 1] = target->fields[it];
target->fields[origin_idx] = tmp;
}
}
static void target_shuffle_one(struct Target* target) {
if (!target || !target->field_count)
return;
uint32_t origin = rand_uint32() % target->field_count;
uint32_t origin_alignment = field_alignment(&target->fields[origin]);
uint32_t max_options = target->size / origin_alignment;
uint32_t* swap_options = (uint32_t*)malloc(sizeof(uint32_t) * max_options); // match fill_begin
struct ShuffleRegion origin_region;
target_get_origin_region(target, &origin_region, origin);
uint32_t option_count = target_get_shuffle_options(target, swap_options, &origin_region, origin_alignment);
if (!option_count) {
free(swap_options);
return;
}
uint32_t selected_option_idx = rand_uint32() % option_count;
uint32_t selected_option = swap_options[selected_option_idx];
free(swap_options);
target_swap(target, origin, &origin_region, selected_option);
}
int spslr_randomize(uint32_t target) {
// TODO
struct Target* t = find_target(target);
if (!t)
return -1;
if (t->field_count != t->present_field_count)
return -1;
seed_rand_time(); // Note -> this is obviously not sufficient
uint32_t shuffle_count = t->field_count * 2;
for (uint32_t i = 0; i < shuffle_count; i++)
target_shuffle_one(t);
// TODO final_fields
return 0;
}