Skip to content

Commit

Permalink
16 byte bundles
Browse files Browse the repository at this point in the history
  • Loading branch information
zyedidia committed Jun 21, 2024
1 parent 7a1addb commit 616d5a4
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 16 deletions.
1 change: 1 addition & 0 deletions lfi-ld/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ int main(int argc, char** argv) {
return 0;
if (ehdr->type != ET_DYN && ehdr->type != ET_EXEC)
return 0;
printf("rewriting\n");

size_t total = 0;
for (int i = 0; i < ehdr->phnum; i++) {
Expand Down
35 changes: 25 additions & 10 deletions lfi-ld/rewrite.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <Zydis/Zydis.h>

enum {
BUNDLE_SIZE = 16,
BUNDLE_SIZE = 32,
};

void rewrite(uint8_t* insns, size_t n, size_t addr) {
Expand All @@ -14,6 +14,7 @@ void rewrite(uint8_t* insns, size_t n, size_t addr) {
ZydisDecoderContext context;
ZydisDecodedInstruction instr;
size_t count = 0;
size_t curbundle = 0;
while (count < n) {
ZyanStatus status = ZydisDecoderDecodeInstruction(&decoder, &context, &insns[count], n-count, &instr);
if (ZYAN_FAILED(status)) {
Expand All @@ -30,17 +31,25 @@ void rewrite(uint8_t* insns, size_t n, size_t addr) {
} else {
if ((addr + instr.length) % BUNDLE_SIZE != 0) {
ZydisDecodedInstruction next;
status = ZydisDecoderDecodeInstruction(&decoder, &context, &insns[count+instr.length], n-count-instr.length, &next);
assert(!ZYAN_FAILED(status) && next.mnemonic == ZYDIS_MNEMONIC_NOP);
size_t noplen = 0;
do {
status = ZydisDecoderDecodeInstruction(&decoder, &context, &insns[count+instr.length+noplen], n-count-instr.length-noplen, &next);
assert(!ZYAN_FAILED(status));
if (next.mnemonic != ZYDIS_MNEMONIC_NOP) {
fprintf(stderr, "%lx: error: expected nop after unaligned call\n", addr);
exit(1);
}
noplen += next.length;
} while ((addr + instr.length + noplen) % BUNDLE_SIZE != 0);

char* nop = malloc(next.length);
memcpy(nop, &insns[count+instr.length], next.length);
char* nop = malloc(noplen);
memcpy(nop, &insns[count+instr.length], noplen);

char* call = malloc(instr.length);
memcpy(call, &insns[count], instr.length);

if (operands[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && instr.length == 5) {
operands[0].imm.value.u -= next.length;
operands[0].imm.value.u -= noplen;
ZydisEncoderRequest req;
memset(&req, 0, sizeof(req));
ZydisEncoderDecodedInstructionToEncoderRequest(&instr, operands, instr.operand_count_visible, &req);
Expand All @@ -51,15 +60,21 @@ void rewrite(uint8_t* insns, size_t n, size_t addr) {
}
}

memcpy(&insns[count], nop, next.length);
memcpy(&insns[count+next.length], call, instr.length);
addr += next.length;
count += next.length;
memcpy(&insns[count], nop, noplen);
memcpy(&insns[count+noplen], call, instr.length);
addr += noplen;
count += noplen;
}
}
}

addr += instr.length;
count += instr.length;

if (count - curbundle >= BUNDLE_SIZE) {
addr = addr - (addr % BUNDLE_SIZE);
count = count - (count % BUNDLE_SIZE);
curbundle = count;
}
}
}
5 changes: 3 additions & 2 deletions lfi-leg/lfi-amd64-baseline.leg
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#define BUNDLE_MASK_16 "0xfffffff0"
#define BUNDLE_MASK_32 "0xffffffe0"

#define BUNDLE_P2 "5"
#define BUNDLE_P2 "4"
#define BUNDLE_MASK BUNDLE_MASK_16

extern FILE* input;
Expand Down Expand Up @@ -168,7 +168,8 @@ AnyInsnPrefix = p:PREFIX rest:REMAINDER {
}

AnyInsn = rest:REMAINDER {
mkinsn("%s\n", rest.val);
if (strlen(rest.val) > 0)
mkinsn("%s\n", rest.val);
}

# --- loads and stores ---
Expand Down
4 changes: 2 additions & 2 deletions lfi-leg/lfi-amd64.leg
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
#define BUNDLE_MASK_16 "0xfffffff0"
#define BUNDLE_MASK_32 "0xffffffe0"

#define BUNDLE_P2 "5"
#define BUNDLE_MASK BUNDLE_MASK_32
#define BUNDLE_P2 "4"
#define BUNDLE_MASK BUNDLE_MASK_16

extern FILE* input;
extern FILE* output;
Expand Down
2 changes: 1 addition & 1 deletion lfi-run/Knitfile
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ local dflags = {

local flags = {
dc = dflags[dc],
ld := -Wl,--gc-sections -fno-pic -L../liblfi -L../lfi-veribdd -llfi -llfiveribdd
ld := -Wl,--gc-sections -fno-pic -L../liblfi -L../lfi-veribdd -llfi -llfiveribdd -lZydis
}

if pagesize == "16384" then
Expand Down
2 changes: 1 addition & 1 deletion liblfi/Knitfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ return b{
$ liblfi.a: $obj
ar rcs $output $input
$ .%.o:D[.%.dep]: %.c
$cc $cflags -MD -MF $dep -c $input -o $output -I. -DARCH_$arch
$cc $cflags -MD -MF $dep -c $input -o $output -I. -DARCH_$arch -DZYDIS_STATIC_BUILD
$ .%.o: %.S
$cc -c $input -o $output

Expand Down
6 changes: 6 additions & 0 deletions liblfi/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,8 @@ static void lfi_proc_clear_regions(struct lfi_proc* proc) {
lfi_proc_clear(&proc->segments);
}

void lfi_rewrite_code(uint8_t* insns, size_t n, size_t addr);

int lfi_proc_exec(struct lfi_proc* proc, uint8_t* prog, size_t size, struct lfi_proc_info* info) {
if (proc->guards[0].base != 0) {
lfi_proc_clear_regions(proc);
Expand Down Expand Up @@ -292,6 +294,10 @@ int lfi_proc_exec(struct lfi_proc* proc, uint8_t* prog, size_t size, struct lfi_
memcpy((void*) (seg.base + offset), &prog[p->offset], p->filesz);
memset((void*) (seg.base + offset + p->filesz), 0, p->memsz - p->filesz);

if ((p->flags & PF_X) != 0) {
lfi_rewrite_code((uint8_t*) (seg.base + offset), p->memsz, start + offset);
}

if ((err = lfi_mem_protect(&seg, proc->base, pflags(p->flags), proc->lfi->opts.noverify)) < 0) {
goto err1;
}
Expand Down
80 changes: 80 additions & 0 deletions liblfi/rewrite.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <Zydis/Zydis.h>

enum {
BUNDLE_SIZE = 16,
};

void lfi_rewrite_code(uint8_t* insns, size_t n, size_t addr) {
ZydisDecoder decoder;
ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_STACK_WIDTH_64);

ZydisDecoderContext context;
ZydisDecodedInstruction instr;
size_t count = 0;
size_t curbundle = 0;
while (count < n) {
ZyanStatus status = ZydisDecoderDecodeInstruction(&decoder, &context, &insns[count], n-count, &instr);
if (ZYAN_FAILED(status)) {
fprintf(stderr, "failed %lx\n", addr);
return;
}

if (instr.mnemonic == ZYDIS_MNEMONIC_CALL) {
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
status = ZydisDecoderDecodeOperands(&decoder, &context, &instr,
operands, instr.operand_count);

if (operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && operands[0].mem.segment == ZYDIS_REGISTER_GS) {
} else {
if ((addr + instr.length) % BUNDLE_SIZE != 0) {
ZydisDecodedInstruction next;
size_t noplen = 0;
do {
status = ZydisDecoderDecodeInstruction(&decoder, &context, &insns[count+instr.length+noplen], n-count-instr.length-noplen, &next);
assert(!ZYAN_FAILED(status));
if (next.mnemonic != ZYDIS_MNEMONIC_NOP) {
fprintf(stderr, "%lx: error: expected nop after unaligned call\n", addr);
exit(1);
}
noplen += next.length;
} while ((addr + instr.length + noplen) % BUNDLE_SIZE != 0);

char* nop = malloc(noplen);
memcpy(nop, &insns[count+instr.length], noplen);

char* call = malloc(instr.length);
memcpy(call, &insns[count], instr.length);

if (operands[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && instr.length == 5) {
operands[0].imm.value.u -= noplen;
ZydisEncoderRequest req;
memset(&req, 0, sizeof(req));
ZydisEncoderDecodedInstructionToEncoderRequest(&instr, operands, instr.operand_count_visible, &req);
ZyanUSize encoded_length = instr.length;
if (ZYAN_FAILED(ZydisEncoderEncodeInstruction(&req, call, &encoded_length))) {
fprintf(stderr, "error: zyan failed\n");
exit(1);
}
}

memcpy(&insns[count], nop, noplen);
memcpy(&insns[count+noplen], call, instr.length);
addr += noplen;
count += noplen;
}
}
}

addr += instr.length;
count += instr.length;

if (count - curbundle >= BUNDLE_SIZE) {
addr = addr - (addr % BUNDLE_SIZE);
count = count - (count % BUNDLE_SIZE);
curbundle = count;
}
}
}

0 comments on commit 616d5a4

Please sign in to comment.