Add support for 32bit Mach-O fixups ##bin

This commit is contained in:
Francesco Tamagni 2022-10-05 16:30:44 +02:00 committed by pancake
parent c21bb3b999
commit d67e569ace
4 changed files with 83 additions and 6 deletions

View File

@ -4622,6 +4622,8 @@ struct MACH0_(mach_header) *MACH0_(get_hdr)(RBuffer *buf) {
return macho_hdr;
}
#define IS_FMT_32BIT(x) (x == DYLD_CHAINED_PTR_32 || x == DYLD_CHAINED_PTR_32_CACHE || x == DYLD_CHAINED_PTR_32_FIRMWARE)
void MACH0_(iterate_chained_fixups)(struct MACH0_(obj_t) *mo, ut64 limit_start, ut64 limit_end, ut32 event_mask, RFixupCallback callback, void * context) {
int i = 0;
for (; i < mo->nsegs && i < mo->segs_count; i++) {
@ -4658,14 +4660,15 @@ void MACH0_(iterate_chained_fixups)(struct MACH0_(obj_t) *mo, ut64 limit_start,
break;
}
mo->rebasing_buffer = previous_rebasing;
ut64 raw_ptr = r_read_le64 (tmp);
ut16 pointer_format = mo->chained_starts[i]->pointer_format;
ut64 raw_ptr = IS_FMT_32BIT (pointer_format)? r_read_le32 (tmp) : r_read_le64 (tmp);
ut64 ptr_value = raw_ptr;
ut64 delta, stride, addend;
ut16 pointer_format = mo->chained_starts[i]->pointer_format;
RFixupEvent event = R_FIXUP_EVENT_NONE;
ut8 key = 0, addr_div = 0;
ut16 diversity = 0;
ut32 ordinal = UT32_MAX;
ut8 ptr_size = 8;
switch (pointer_format) {
case DYLD_CHAINED_PTR_ARM64E:
{
@ -4769,6 +4772,48 @@ void MACH0_(iterate_chained_fixups)(struct MACH0_(obj_t) *mo, ut64 limit_start,
}
}
break;
case DYLD_CHAINED_PTR_32:
{
stride = 4;
ptr_size = 4;
struct dyld_chained_ptr_32_bind *bind =
(struct dyld_chained_ptr_32_bind *) &raw_ptr;
if (bind->bind) {
event = R_FIXUP_EVENT_BIND;
delta = bind->next;
ordinal = bind->ordinal;
addend = bind->addend;
} else {
struct dyld_chained_ptr_32_rebase *p =
(struct dyld_chained_ptr_32_rebase *) &raw_ptr;
event = R_FIXUP_EVENT_REBASE;
delta = p->next;
ptr_value = p->target;
}
}
break;
case DYLD_CHAINED_PTR_32_CACHE:
{
stride = 4;
ptr_size = 4;
struct dyld_chained_ptr_32_cache_rebase *p =
(struct dyld_chained_ptr_32_cache_rebase *) &raw_ptr;
event = R_FIXUP_EVENT_REBASE;
delta = p->next;
ptr_value = p->target;
}
break;
case DYLD_CHAINED_PTR_32_FIRMWARE:
{
stride = 4;
ptr_size = 4;
struct dyld_chained_ptr_32_firmware_rebase *p =
(struct dyld_chained_ptr_32_firmware_rebase *) &raw_ptr;
event = R_FIXUP_EVENT_REBASE;
delta = p->next;
ptr_value = p->target;
}
break;
default:
R_LOG_WARN ("Unsupported chained pointer format %d", pointer_format);
return;
@ -4783,6 +4828,7 @@ void MACH0_(iterate_chained_fixups)(struct MACH0_(obj_t) *mo, ut64 limit_start,
event_details.bin = mo;
event_details.offset = cursor;
event_details.raw_ptr = raw_ptr;
event_details.ptr_size = ptr_size;
event_details.ordinal = ordinal;
event_details.addend = addend;
@ -4796,6 +4842,7 @@ void MACH0_(iterate_chained_fixups)(struct MACH0_(obj_t) *mo, ut64 limit_start,
event_details.bin = mo;
event_details.offset = cursor;
event_details.raw_ptr = raw_ptr;
event_details.ptr_size = ptr_size;
event_details.ordinal = ordinal;
event_details.key = key;
event_details.addr_div = addr_div;
@ -4811,6 +4858,7 @@ void MACH0_(iterate_chained_fixups)(struct MACH0_(obj_t) *mo, ut64 limit_start,
event_details.bin = mo;
event_details.offset = cursor;
event_details.raw_ptr = raw_ptr;
event_details.ptr_size = ptr_size;
event_details.ptr_value = ptr_value;
carry_on = callback (context, (RFixupEventDetails *) &event_details);
@ -4823,6 +4871,7 @@ void MACH0_(iterate_chained_fixups)(struct MACH0_(obj_t) *mo, ut64 limit_start,
event_details.bin = mo;
event_details.offset = cursor;
event_details.raw_ptr = raw_ptr;
event_details.ptr_size = ptr_size;
event_details.ptr_value = ptr_value;
event_details.key = key;
event_details.addr_div = addr_div;

View File

@ -209,6 +209,7 @@ typedef struct {
struct MACH0_(obj_t) *bin;
ut64 offset;
ut64 raw_ptr;
ut8 ptr_size;
} RFixupEventDetails;
typedef struct {
@ -216,6 +217,7 @@ typedef struct {
struct MACH0_(obj_t) *bin;
ut64 offset;
ut64 raw_ptr;
ut8 ptr_size;
ut64 ordinal;
ut64 addend;
} RFixupBindEventDetails;
@ -225,6 +227,7 @@ typedef struct {
struct MACH0_(obj_t) *bin;
ut64 offset;
ut64 raw_ptr;
ut8 ptr_size;
ut32 ordinal;
ut8 key;
ut8 addr_div;
@ -236,6 +239,7 @@ typedef struct {
struct MACH0_(obj_t) *bin;
ut64 offset;
ut64 raw_ptr;
ut8 ptr_size;
ut64 ptr_value;
} RFixupRebaseEventDetails;
@ -244,6 +248,7 @@ typedef struct {
struct MACH0_(obj_t) *bin;
ut64 offset;
ut64 raw_ptr;
ut8 ptr_size;
ut64 ptr_value;
ut8 key;
ut8 addr_div;

View File

@ -1582,6 +1582,29 @@ struct dyld_chained_ptr_arm64e_auth_bind24 {
auth : 1; // == 1
};
struct dyld_chained_ptr_32_rebase {
uint32_t target : 26,
next : 5,
bind : 1; // == 0
};
struct dyld_chained_ptr_32_bind {
uint32_t ordinal : 20,
addend : 6,
next : 5,
bind : 1; // == 1
};
struct dyld_chained_ptr_32_cache_rebase {
uint32_t target : 30,
next : 2;
};
struct dyld_chained_ptr_32_firmware_rebase {
uint32_t target : 26,
next : 6;
};
enum {
DYLD_CHAINED_IMPORT = 1,
DYLD_CHAINED_IMPORT_ADDEND = 2,

View File

@ -782,9 +782,9 @@ static bool rebase_buffer_callback2(void *context, RFixupEventDetails * event_de
switch (event_details->type) {
case R_FIXUP_EVENT_BIND:
case R_FIXUP_EVENT_BIND_AUTH:
r_buf_write_at (ctx->obj->b, in_buf, (const ut8*)"\x00\x00\x00\x00\x00\x00\x00", 8);
r_buf_write_at (ctx->obj->b, in_buf, (const ut8*)"\x00\x00\x00\x00\x00\x00\x00", event_details->ptr_size);
ut8 data[8] = {0};
r_buf_read_at (ctx->obj->b, in_buf, data, 8);
r_buf_read_at (ctx->obj->b, in_buf, data, event_details->ptr_size);
add_fixup (rflist, in_buf, 0);
if (data[0]) {
eprintf ("DATA0 write has failed\n");
@ -796,8 +796,8 @@ static bool rebase_buffer_callback2(void *context, RFixupEventDetails * event_de
ut8 data[8] = {0};
ut64 v = ((RFixupRebaseEventDetails *) event_details)->ptr_value;
add_fixup (rflist, in_buf, v);
memcpy (&data, &v, sizeof (data));
r_buf_write_at (ctx->obj->b, in_buf, data, 8);
memcpy (&data, &v, event_details->ptr_size);
r_buf_write_at (ctx->obj->b, in_buf, data, event_details->ptr_size);
}
break;
default: