From 422c8d756299d00196654bbbafded117e63827b5 Mon Sep 17 00:00:00 2001 From: York Jasper Niebuhr Date: Tue, 7 Apr 2026 21:33:21 +0200 Subject: [PATCH] Updated randomizer towards kernel implementation --- selfpatch/CMakeLists.txt | 2 +- selfpatch/src/env.c | 12 ++ selfpatch/src/env.h | 1 + selfpatch/src/randomizer.c | 352 +++++++++++++++++++++++++++++++ selfpatch/src/randomizer.h | 17 ++ selfpatch/src/selfpatch.c | 72 ++----- selfpatch/src/targets.c | 422 ------------------------------------- selfpatch/src/targets.h | 20 -- subject/main.c | 4 +- 9 files changed, 407 insertions(+), 495 deletions(-) create mode 100644 selfpatch/src/randomizer.c create mode 100644 selfpatch/src/randomizer.h delete mode 100644 selfpatch/src/targets.c delete mode 100644 selfpatch/src/targets.h diff --git a/selfpatch/CMakeLists.txt b/selfpatch/CMakeLists.txt index 14c1dd6..acd075e 100644 --- a/selfpatch/CMakeLists.txt +++ b/selfpatch/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(spslr_selfpatch STATIC src/selfpatch.c src/targets.c src/env.c) +add_library(spslr_selfpatch STATIC src/selfpatch.c src/randomizer.c src/env.c) target_include_directories(spslr_selfpatch PUBLIC $ diff --git a/selfpatch/src/env.c b/selfpatch/src/env.c index 88a2ae2..c2afed4 100644 --- a/selfpatch/src/env.c +++ b/selfpatch/src/env.c @@ -4,6 +4,7 @@ #include #include #include +#include #define PAGE_MASK ~(0x1000ull - 1) @@ -107,3 +108,14 @@ void spslr_env_memcpy(void* dst, const void* src, uint32_t n) { memcpy(dst, src, n); } +static int rand_initialized = 0; + +uint32_t spslr_env_random_u32() { + if (!rand_initialized) { + srand(time(NULL)); + rand_initialized = 1; + } + + return (uint32_t)rand(); +} + diff --git a/selfpatch/src/env.h b/selfpatch/src/env.h index 9bc3c79..b2916bd 100644 --- a/selfpatch/src/env.h +++ b/selfpatch/src/env.h @@ -13,5 +13,6 @@ void spslr_env_free(void* ptr); void spslr_env_poke_data(void* dst, const void* src, uint32_t n); void spslr_env_memset(void* dst, int v, uint32_t n); void spslr_env_memcpy(void* dst, const void* src, uint32_t n); +uint32_t spslr_env_random_u32(); #endif diff --git a/selfpatch/src/randomizer.c b/selfpatch/src/randomizer.c new file mode 100644 index 0000000..a162edd --- /dev/null +++ b/selfpatch/src/randomizer.c @@ -0,0 +1,352 @@ +#include "randomizer.h" + +#include "spslr_list_link.h" +#include "env.h" + +#include + +struct Field { + uint32_t offset; /* Final field offset -> fields[i].offset = offset of field i in final layout */ + uint32_t oidx; /* Original field idx -> fields[i].oidx = original position of field i in final layout */ + uint32_t fidx; /* Final field idx -> fields[i].fidx = randomized/final position of original field i */ +}; + +static struct Field* fields; + +int spslr_randomizer_init() { + fields = (struct Field*)spslr_env_malloc(sizeof(struct Field) * spslr_target_field_cnt); + if (!fields) + return -1; + + for (uint32_t tidx = 0; tidx < spslr_target_cnt; tidx++) { + const struct spslr_target* t = &spslr_targets[tidx]; + + for (uint32_t fidx = 0; fidx < t->fieldcnt; fidx++) { + uint32_t gfidx = t->fieldoff + fidx; + + const struct spslr_target_field* srcf = &spslr_target_fields[gfidx]; + struct Field* dstf = &fields[gfidx]; + + dstf->offset = srcf->offset; + dstf->oidx = fidx; + dstf->fidx = fidx; + } + } + + return 0; +} + +void spslr_randomizer_clear() { + if (!fields) + return; + + spslr_env_free(fields); + fields = NULL; +} + +int spslr_randomizer_get_target(uint32_t target, uint32_t* size, uint32_t* fieldcnt) { + if (target >= spslr_target_cnt) + return -1; + + const struct spslr_target* t = &spslr_targets[target]; + + if (size) + *size = t->size; + + if (fieldcnt) + *fieldcnt = t->fieldcnt; + + return 0; +} + +int spslr_randomizer_get_field(uint32_t target, uint32_t field, int field_idx_mode, + uint32_t* size, uint32_t* offset, uint32_t* initial_offset) { + if (target >= spslr_target_cnt) + return -1; + + const struct spslr_target* t = &spslr_targets[target]; + + if (field >= t->fieldcnt) + return -1; + + const struct spslr_target_field* of = NULL; + const struct Field* rf = NULL; + + switch (field_idx_mode) { + case SPSLR_RANDOMIZER_FIELD_IDX_MODE_ORIGINAL: + of = &spslr_target_fields[t->fieldoff + field]; + rf = &fields[t->fieldoff + fields[t->fieldoff + field].fidx]; + break; + case SPSLR_RANDOMIZER_FIELD_IDX_MODE_FINAL: + of = &spslr_target_fields[t->fieldoff + fields[t->fieldoff + field].oidx]; + rf = &fields[t->fieldoff + field]; + break; + default: + return -1; + } + + if (size) + *size = of->size; + + if (offset) + *offset = rf->offset; + + if (initial_offset) + *initial_offset = of->offset; + + return 0; +} + +// RANDOMIZATION CODE + +struct ShuffleRegion { + uint32_t begin; + uint32_t end; + uint32_t fill_begin; + uint32_t fill_end; +}; + +static uint32_t rand_u32(void); +static struct Field* get_rfield(uint32_t target, uint32_t final_idx); +static const struct spslr_target_field* get_ofield(uint32_t target, uint32_t orig_idx); +static void get_origin_region(uint32_t target, uint32_t final_idx, struct ShuffleRegion* region); +static int pick_shuffle_option(uint32_t target, uint32_t origin_final_idx, + const struct ShuffleRegion* origin, uint32_t alignment, uint32_t* selected); +static void do_swap(uint32_t target, uint32_t origin_final_idx, + const struct ShuffleRegion* origin_region, uint32_t new_offset); +static void shuffle_one_target(uint32_t target); +static void shuffle_target(uint32_t target); + +static uint32_t rand_u32(void) { + return spslr_env_random_u32(); +} + +static struct Field* get_rfield(uint32_t target, uint32_t final_idx) { + const struct spslr_target* t = &spslr_targets[target]; + return &fields[t->fieldoff + final_idx]; +} + +static const struct spslr_target_field* get_ofield(uint32_t target, uint32_t orig_idx) { + const struct spslr_target* t = &spslr_targets[target]; + return &spslr_target_fields[t->fieldoff + orig_idx]; +} + +static void get_origin_region(uint32_t target, uint32_t final_idx, struct ShuffleRegion* region) { + const struct spslr_target* t = &spslr_targets[target]; + const struct Field* rf = get_rfield(target, final_idx); + const struct spslr_target_field* of = get_ofield(target, rf->oidx); + + region->fill_begin = rf->offset; + region->fill_end = rf->offset + of->size; + + if (final_idx == 0) { + region->begin = 0; + } else { + const struct Field* pred_rf = get_rfield(target, final_idx - 1); + const struct spslr_target_field* pred_of = get_ofield(target, pred_rf->oidx); + region->begin = pred_rf->offset + pred_of->size; + } + + if (final_idx + 1 >= t->fieldcnt) { + region->end = t->size; + } else { + const struct Field* succ_rf = get_rfield(target, final_idx + 1); + region->end = succ_rf->offset; + } +} + +static int option_is_valid(uint32_t target, uint32_t origin_final_idx, const struct ShuffleRegion* origin, uint32_t offset) { + const struct spslr_target* t = &spslr_targets[target]; + const struct spslr_target_field* origin_of = + get_ofield(target, get_rfield(target, origin_final_idx)->oidx); + + // When placed at offset, field will occupy [offset, option_would_end) + uint32_t option_would_end = offset + origin_of->size; + if (option_would_end > t->size) + return 0; + + // Field may overlap with origin region. Moving field to offset truly frees: + // [true_origin_region_begin, true_origin_region_end) + uint32_t true_origin_region_begin = origin->begin; + uint32_t true_origin_region_end = origin->end; + + if (offset <= origin->fill_begin && option_would_end > true_origin_region_begin) + true_origin_region_begin = option_would_end; + + if (offset >= origin->fill_begin && offset < true_origin_region_end) + true_origin_region_end = offset; + + // Iterate over fields in target region [offset, option_would_end] and see if they fit into true origin region + uint32_t origin_region_ptr = true_origin_region_begin; + for (uint32_t it = 0; it < t->fieldcnt; it++) { + const struct Field* rf = get_rfield(target, it); + const struct spslr_target_field* of = get_ofield(target, rf->oidx); + + // The field being moved does not need to go into origin region + if (it == origin_final_idx) + continue; + + // Field ends before target region -> must not be moved to origin region + if (rf->offset + of->size <= offset) + continue; + + // Field starts after target region -> must not be moved to origin region + if (rf->offset >= option_would_end) + break; + + // Fixed fields in target region unconditionally deny option + if (of->flags & SPSLR_FLAG_FIELD_FIXED) + return 0; + + // Field from target region must be moved to aligned position in origin region + if (origin_region_ptr % of->alignment != 0) + origin_region_ptr += of->alignment - (origin_region_ptr % of->alignment); + + origin_region_ptr += of->size; + + // Field does not fit into origin region -> option not possible + if (origin_region_ptr > true_origin_region_end) + return 0; + } + + return 1; +} + +static int pick_shuffle_option(uint32_t target, uint32_t origin_final_idx, const struct ShuffleRegion* origin, + uint32_t alignment, uint32_t* selected) { + const struct spslr_target* t = &spslr_targets[target]; + uint32_t seen = 0; + + for (uint32_t offset = 0; offset < t->size; offset += alignment) { + if (!option_is_valid(target, origin_final_idx, origin, offset)) + continue; + + // Reservoir sampling -> uniform distribution with O(1) memory consumption + seen++; + if ((rand_u32() % seen) == 0) + *selected = offset; + } + + return seen ? 0 : -1; +} + +static void do_swap(uint32_t target, uint32_t origin_idx, + const struct ShuffleRegion* origin_region, uint32_t new_offset) { + const struct spslr_target* t = &spslr_targets[target]; + int pulled = 0; + + uint32_t option_fill_end = new_offset + (origin_region->fill_end - origin_region->fill_begin); + + uint32_t true_origin_region_begin = origin_region->begin; + if (new_offset <= origin_region->fill_begin && option_fill_end > true_origin_region_begin) + true_origin_region_begin = option_fill_end; + + uint32_t origin_oidx = get_rfield(target, origin_idx)->oidx; + + uint32_t origin_region_ptr = true_origin_region_begin; + for (uint32_t it = 0; it < t->fieldcnt; it++) { + struct Field* itf = get_rfield(target, it); + + if (itf->oidx == origin_oidx) + continue; + + const struct spslr_target_field* itof = get_ofield(target, itf->oidx); + + if (itf->offset + itof->size <= new_offset) + continue; + + if (itf->offset >= option_fill_end) + break; + + uint32_t falign = itof->alignment; + if (origin_region_ptr % falign != 0) + origin_region_ptr += falign - (origin_region_ptr % falign); + + if (!pulled) { + pulled = 1; + + struct Field tmp = *get_rfield(target, it); + *get_rfield(target, it) = *get_rfield(target, origin_idx); + *get_rfield(target, origin_idx) = tmp; + + get_rfield(target, it)->offset = new_offset; + + get_rfield(target, origin_idx)->offset = origin_region_ptr; + origin_region_ptr += get_ofield(target, get_rfield(target, origin_idx)->oidx)->size; + continue; + } + + { + struct Field tmp = *get_rfield(target, it); + + if (origin_idx >= it) { + for (uint32_t pull_it = it + 1; pull_it <= origin_idx; pull_it++) + *get_rfield(target, pull_it - 1) = *get_rfield(target, pull_it); + + *get_rfield(target, origin_idx) = tmp; + get_rfield(target, origin_idx)->offset = origin_region_ptr; + origin_region_ptr += get_ofield(target, get_rfield(target, origin_idx)->oidx)->size; + } else { + for (uint32_t pull_it = it; pull_it > origin_idx + (uint32_t)pulled; pull_it--) + *get_rfield(target, pull_it) = *get_rfield(target, pull_it - 1); + + *get_rfield(target, origin_idx + (uint32_t)pulled) = tmp; + get_rfield(target, origin_idx + (uint32_t)pulled)->offset = origin_region_ptr; + origin_region_ptr += get_ofield(target, get_rfield(target, origin_idx + (uint32_t)pulled)->oidx)->size; + } + } + + pulled++; + } + + /* + * Rebuild original->final mapping for this target. + */ + for (uint32_t final_idx = 0; final_idx < t->fieldcnt; final_idx++) { + struct Field* rf = get_rfield(target, final_idx); + fields[t->fieldoff + rf->oidx].fidx = final_idx; + } +} + +static void shuffle_one_target(uint32_t target) { + const struct spslr_target* t = &spslr_targets[target]; + if (t->fieldcnt == 0) + return; + + uint32_t origin_final_idx = rand_u32() % t->fieldcnt; + struct Field* origin_rf = get_rfield(target, origin_final_idx); + const struct spslr_target_field* origin_of = get_ofield(target, origin_rf->oidx); + + if (origin_of->flags & SPSLR_FLAG_FIELD_FIXED) + return; + + struct ShuffleRegion origin_region; + uint32_t selected_option; + + get_origin_region(target, origin_final_idx, &origin_region); + + if (pick_shuffle_option(target, origin_final_idx, &origin_region, + origin_of->alignment, &selected_option) < 0) + return; + + do_swap(target, origin_final_idx, &origin_region, selected_option); +} + +static void shuffle_target(uint32_t target) { + const struct spslr_target* t = &spslr_targets[target]; + uint32_t shuffle_count = t->fieldcnt * 2; + + for (uint32_t i = 0; i < shuffle_count; i++) + shuffle_one_target(target); +} + +int spslr_randomize() { + if (!fields) + return -1; + + for (uint32_t tidx = 0; tidx < spslr_target_cnt; tidx++) + shuffle_target(tidx); + + return 0; +} + diff --git a/selfpatch/src/randomizer.h b/selfpatch/src/randomizer.h new file mode 100644 index 0000000..34dbb76 --- /dev/null +++ b/selfpatch/src/randomizer.h @@ -0,0 +1,17 @@ +#ifndef SPSLR_RANDOMIZER_H +#define SPSLR_RANDOMIZER_H + +#include + +#define SPSLR_RANDOMIZER_FIELD_IDX_MODE_ORIGINAL 1 +#define SPSLR_RANDOMIZER_FIELD_IDX_MODE_FINAL 2 + +int spslr_randomizer_init(); +int spslr_randomize(); +void spslr_randomizer_clear(); + +int spslr_randomizer_get_target(uint32_t target, uint32_t* size, uint32_t* fieldcnt); +int spslr_randomizer_get_field(uint32_t target, uint32_t field, int field_idx_mode, + uint32_t* size, uint32_t* offset, uint32_t* initial_offset); + +#endif diff --git a/selfpatch/src/selfpatch.c b/selfpatch/src/selfpatch.c index 8787ca3..7a02aee 100644 --- a/selfpatch/src/selfpatch.c +++ b/selfpatch/src/selfpatch.c @@ -1,7 +1,7 @@ #include #include -#include "targets.h" +#include "randomizer.h" #include "env.h" #include "spslr_list_link.h" @@ -18,49 +18,16 @@ static void reorder_object(void* dst, const void* src, uint32_t target); static int64_t spslr_calculate_ipin_value(uint32_t start); void spslr_selfpatch(void) { - seed_rand_time(); + if (spslr_randomizer_init() < 0) + spslr_env_panic("failed to initialize randomizer"); + + if (spslr_randomize() < 0) + spslr_env_panic("failed to randomize targets"); - spslr_selfpatch_load_targets(); - spslr_selfpatch_randomize_targets(); spslr_selfpatch_patch_dpins(); spslr_selfpatch_patch_ipins(); - spslr_clear_targets(); -} -void spslr_selfpatch_load_targets(void) { - for (uint32_t tidx = 0; tidx < spslr_target_cnt; tidx++) { - const struct spslr_target* t = &spslr_targets[tidx]; - -#ifdef SPSLR_SANITY_CHECK - if (t->fieldoff + t->fieldcnt > spslr_target_field_cnt) - spslr_env_panic("target field offset and count reference invalid fields"); -#endif - - if (spslr_register_target(tidx, t->size, t->fieldcnt) < 0) - spslr_env_panic("failed to register target"); - - for (uint32_t fidx = 0; fidx < t->fieldcnt; fidx++) { - const struct spslr_target_field* f = &spslr_target_fields[t->fieldoff + fidx]; - -#ifdef SPSLR_SANITY_CHECK - if (f->offset + f->size > t->size) - spslr_env_panic("target field resides beyond target size"); - - if (f->offset % f->alignment != 0) - spslr_env_panic("target field is misaligned"); -#endif - - if (spslr_register_target_field(tidx, f->offset, f->size, f->alignment, f->flags) < 0) - spslr_env_panic("failed to register target field"); - } - } -} - -void spslr_selfpatch_randomize_targets(void) { - for (uint32_t tidx = 0; tidx < spslr_target_cnt; tidx++) { - if (spslr_randomize(tidx) < 0) - spslr_env_panic("failed to randomize target"); - } + spslr_randomizer_clear(); } void spslr_selfpatch_patch_dpins(void) { @@ -72,7 +39,7 @@ void spslr_selfpatch_patch_dpins(void) { void reorder_object(void* dst, const void* src, uint32_t target) { uint32_t field_count; - if (spslr_get_target_fieldcnt(target, &field_count)) + if (spslr_randomizer_get_target(target, NULL, &field_count)) spslr_env_panic("failed to get target field count"); const uint8_t* src_countable = (const uint8_t*)src; @@ -80,7 +47,8 @@ void reorder_object(void* dst, const void* src, uint32_t target) { 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)) + if (spslr_randomizer_get_field(target, i, SPSLR_RANDOMIZER_FIELD_IDX_MODE_FINAL, + &field_size, &field_offset, &field_initial_offset)) spslr_env_panic("failed to get ordered field descriptor"); spslr_env_memcpy(dst_countable + field_offset, src_countable + field_initial_offset, field_size); @@ -151,8 +119,9 @@ int64_t spslr_calculate_ipin_value(uint32_t start) { case SPSLR_IPIN_OP_ADD_INITIAL_OFFSET: { uint32_t initial_offset; - if (spslr_get_randomized_field_offset(op->op0.add_initial_offset_target, - op->op1.add_initial_offset_field, NULL, &initial_offset)) + if (spslr_randomizer_get_field(op->op0.add_initial_offset_target, + op->op1.add_initial_offset_field, SPSLR_RANDOMIZER_FIELD_IDX_MODE_ORIGINAL, + NULL, NULL, &initial_offset)) spslr_env_panic("failed to get initial field offset"); res += initial_offset; @@ -161,8 +130,9 @@ int64_t spslr_calculate_ipin_value(uint32_t start) { case SPSLR_IPIN_OP_ADD_OFFSET: { uint32_t offset; - if (spslr_get_randomized_field_offset(op->op0.add_initial_offset_target, - op->op1.add_initial_offset_field, &offset, NULL)) + if (spslr_randomizer_get_field(op->op0.add_initial_offset_target, + op->op1.add_offset_field, SPSLR_RANDOMIZER_FIELD_IDX_MODE_ORIGINAL, + NULL, &offset, NULL)) spslr_env_panic("failed to get initial field offset"); res += offset; @@ -171,8 +141,9 @@ int64_t spslr_calculate_ipin_value(uint32_t start) { case SPSLR_IPIN_OP_SUB_INITIAL_OFFSET: { uint32_t initial_offset; - if (spslr_get_randomized_field_offset(op->op0.add_initial_offset_target, - op->op1.add_initial_offset_field, NULL, &initial_offset)) + if (spslr_randomizer_get_field(op->op0.add_initial_offset_target, + op->op1.sub_initial_offset_field, SPSLR_RANDOMIZER_FIELD_IDX_MODE_ORIGINAL, + NULL, NULL, &initial_offset)) spslr_env_panic("failed to get initial field offset"); res -= initial_offset; @@ -181,8 +152,9 @@ int64_t spslr_calculate_ipin_value(uint32_t start) { case SPSLR_IPIN_OP_SUB_OFFSET: { uint32_t offset; - if (spslr_get_randomized_field_offset(op->op0.add_initial_offset_target, - op->op1.add_initial_offset_field, &offset, NULL)) + if (spslr_randomizer_get_field(op->op0.add_initial_offset_target, + op->op1.sub_offset_field, SPSLR_RANDOMIZER_FIELD_IDX_MODE_ORIGINAL, + NULL, &offset, NULL)) spslr_env_panic("failed to get initial field offset"); res -= offset; diff --git a/selfpatch/src/targets.c b/selfpatch/src/targets.c deleted file mode 100644 index 13e9682..0000000 --- a/selfpatch/src/targets.c +++ /dev/null @@ -1,422 +0,0 @@ -#include "targets.h" - -#include "spslr_list.h" - -#include -#include - -void seed_rand_time() { - srand(time(NULL)); -} - -static uint32_t rand_uint32() { - return (uint32_t)rand(); -} - -struct Field { - uint32_t initial_offset; - uint32_t initial_idx; - - uint32_t offset; - uint32_t size; - uint32_t alignment; - uint32_t flags; -}; - -struct FinalField { - uint32_t initial_offset; - uint32_t offset; -}; - -struct Target { - uint32_t uid; - uint32_t size; - uint32_t field_count; - - uint32_t present_field_count; - struct Field* fields; - struct FinalField* final_fields; // After rand (indexable by initial layout) - - struct Target* next; -}; - -static struct Target* targets = NULL; - -static struct Target* find_target(uint32_t uid) { - struct Target* cur = targets; - while (cur) { - if (cur->uid == uid) - return cur; - - cur = cur->next; - } - - return NULL; -} - -static int add_target(uint32_t uid, uint32_t size, uint32_t fieldcnt) { - if (find_target(uid)) - return -1; - - struct Target* new_target = (struct Target*)malloc(sizeof(struct Target)); - if (!new_target) - return -1; - - new_target->uid = uid; - new_target->size = size; - new_target->field_count = fieldcnt; - - new_target->present_field_count = 0; - new_target->final_fields = NULL; - new_target->fields = (struct Field*)malloc(sizeof(struct Field) * fieldcnt); - - if (!new_target->fields) { - free(new_target); - return -1; - } - - new_target->next = targets; - targets = new_target; - return 0; -} - -static void clear_targets() { - struct Target* cur = targets; - while (cur) { - if (cur->fields) - free(cur->fields); - if (cur->final_fields) - free(cur->final_fields); - - struct Target* tmp = cur; - cur = cur->next; - - free(tmp); - } - - targets = NULL; -} - -int spslr_register_target(uint32_t uid, uint32_t size, uint32_t fieldcnt) { - if (find_target(uid)) - return -1; - - return add_target(uid, size, fieldcnt); -} - -int spslr_register_target_field(uint32_t target, uint32_t offset, uint32_t size, uint32_t alignment, uint32_t flags) { - struct Target* t = find_target(target); - if (!t) - return -1; - - if (offset + size > t->size) - return -1; - - if (t->present_field_count >= t->field_count) - return -1; - - if (offset % alignment != 0) - return -1; - - if (t->present_field_count) { - struct Field* pred = &t->fields[t->present_field_count - 1]; - if (offset < pred->offset + pred->size) - return -1; - } - - uint32_t idx = t->present_field_count++; - - struct Field* f = &t->fields[idx]; - f->initial_offset = offset; - f->initial_idx = idx; - f->offset = offset; - f->size = size; - f->alignment = alignment; - f->flags = flags; - - return 0; -} - -struct ShuffleRegion { - uint32_t begin, end; - uint32_t fill_begin, fill_end; -}; - -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? - uint32_t true_origin_region_begin = origin->begin; - uint32_t true_origin_region_end = origin->end; - - if (offset <= origin->fill_begin && option_would_end > true_origin_region_begin) - true_origin_region_begin = option_would_end; - - if (offset >= origin->fill_begin && offset < true_origin_region_end) - true_origin_region_end = offset; - - int conflict = 0; - uint32_t origin_region_ptr = true_origin_region_begin; - for (uint32_t it = current_field; it < target->field_count; it++) { - struct Field* f = &target->fields[it]; - - if (f->offset == origin->fill_begin) - continue; - - if (f->offset >= option_would_end) - break; - - if (f->flags & SPSLR_FLAG_FIELD_FIXED) { - conflict = 1; - break; - } - - // Could field be placed in origin? - if (origin_region_ptr % f->alignment != 0) - origin_region_ptr += f->alignment - (origin_region_ptr % f->alignment); - - origin_region_ptr += f->size; - - if (origin_region_ptr > true_origin_region_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 pulled = 0; - - uint32_t option_fill_end = new_offset + (origin_region->fill_end - origin_region->fill_begin); - - // If origin->fill_begin was placed at offset, could all fields that overlap with range swap with origin? - uint32_t true_origin_region_begin = origin_region->begin; - - if (new_offset <= origin_region->fill_begin && option_fill_end > true_origin_region_begin) - true_origin_region_begin = option_fill_end; - - uint32_t origin_initial_index = target->fields[origin_idx].initial_idx; - - uint32_t origin_region_ptr = true_origin_region_begin; - for (uint32_t it = 0; it < target->field_count; it++) { - if (target->fields[it].initial_idx == origin_initial_index) - continue; - - // 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 = target->fields[it].alignment; - if (origin_region_ptr % falign != 0) - origin_region_ptr += falign - (origin_region_ptr % falign); - - // First field in swap region is exchanged with origin - if (!pulled) { - 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]; - - if (origin_idx >= it) { - for (uint32_t pull_it = it + 1; pull_it <= origin_idx; pull_it++) - target->fields[pull_it - 1] = target->fields[pull_it]; - - target->fields[origin_idx] = tmp; - target->fields[origin_idx].offset = origin_region_ptr; - origin_region_ptr += target->fields[origin_idx].size; - } else { - // O X A B C -> pulled=0 - // A X O B C -> pulled=1 - // A B X O C -> pulled=2 - // A B C X O -> pulled=3 - for (uint32_t pull_it = it; pull_it > origin_idx + pulled; pull_it--) - target->fields[pull_it] = target->fields[pull_it - 1]; - - target->fields[origin_idx + pulled] = tmp; - target->fields[origin_idx + pulled].offset = origin_region_ptr; - origin_region_ptr += target->fields[origin_idx + pulled].size; - } - - pulled++; - } -} - -static void target_shuffle_one(struct Target* target) { - if (!target || !target->field_count) - return; - - uint32_t origin = rand_uint32() % target->field_count; - - if (target->fields[origin].flags & SPSLR_FLAG_FIELD_FIXED) - return; - - uint32_t origin_alignment = target->fields[origin].alignment; - - 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) { - struct Target* t = find_target(target); - if (!t) - return -1; - - if (t->field_count != t->present_field_count) - return -1; - - uint32_t shuffle_count = t->field_count * 2; - for (uint32_t i = 0; i < shuffle_count; i++) - target_shuffle_one(t); - - // Compile array of final fields - t->final_fields = (struct FinalField*)malloc(sizeof(struct FinalField) * t->field_count); - if (!t->final_fields) - return -1; - - for (uint32_t i = 0; i < t->field_count; i++) { - const struct Field* f = &t->fields[i]; - struct FinalField* ff = &t->final_fields[f->initial_idx]; - - ff->initial_offset = f->initial_offset; - ff->offset = f->offset; - } - - return 0; -} - -int spslr_get_randomized_field_offset(uint32_t target, uint32_t field, uint32_t* offset, uint32_t* initial_offset) { - const struct Target* t = find_target(target); - if (!t) - return -1; - - if (field >= t->field_count) - return -1; - - if (!t->final_fields) - return -1; - - if (offset) - *offset = t->final_fields[field].offset; - - if (initial_offset) - *initial_offset = t->final_fields[field].initial_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) - return -1; - - if (cnt) - *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) - return -1; - - if (field >= t->field_count) - return -1; - - const struct Field* f = &t->fields[field]; - - if (offset) - *offset = f->offset; - - if (size) - *size = f->size; - - if (initial_offset) - *initial_offset = f->initial_offset; - - return 0; -} - -void spslr_clear_targets() { - clear_targets(); -} - diff --git a/selfpatch/src/targets.h b/selfpatch/src/targets.h deleted file mode 100644 index bb61441..0000000 --- a/selfpatch/src/targets.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SPSLR_TARGETS_H -#define SPSLR_TARGETS_H - -#include - -void seed_rand_time(); - -int spslr_register_target(uint32_t uid, uint32_t size, uint32_t fieldcnt); -int spslr_register_target_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, uint32_t* initial_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_clear_targets(); - -#endif diff --git a/subject/main.c b/subject/main.c index 42263f5..92328a4 100644 --- a/subject/main.c +++ b/subject/main.c @@ -65,8 +65,8 @@ int main(void) printf(" pid=%d, comm=%s\n", task->pid, task->comm); } - size_t myOffset = ((size_t)&((struct task_struct*)0)->tasks); - printf("DIY offsetof(task_struct, tasks) yiels %2llu\n", myOffset); + size_t myOffset = ((size_t)&((struct task_struct*)0)->pid); + printf("DIY offsetof(task_struct, pid) yiels %2llu\n", myOffset); printf("Global: pid=%d comm=\"%s\"\n", global.pid, global.comm); printf("Second global: pid=%d comm=\"%s\"\n", second_pid(), second_comm());