Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The Great Splitting Out (Part 2 of ??)
(also the 25th birthday commit) - Merge i386/i686 branch - Split out assembly for each arch - Create an x86_gen to reduce code duplication - More cleanup still needed.
- Loading branch information
Showing
10 changed files
with
572 additions
and
232 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#if !defined (_ARCH_H_) | ||
#define _ARCH_H_ | ||
|
||
#if defined(_ARCH_i386_) || defined(_ARCH_i686_) | ||
#include "i386.h" | ||
#elif defined(_ARCH_x86_64_) | ||
#include "x86_64.h" | ||
#else | ||
#error "Unsupported architecture! Cannot continue compilation." | ||
#endif | ||
|
||
/* | ||
* "normal" trampoline | ||
*/ | ||
void * | ||
arch_get_st2_tramp(size_t *size); | ||
|
||
void | ||
arch_insert_st1_tramp(void *start, void *trampee, void *tramp); | ||
|
||
/* | ||
* inline trampoline | ||
*/ | ||
void * | ||
arch_get_inline_st2_tramp(size_t *size); | ||
|
||
void * | ||
arch_set_inline_st2_tramp(void *addr, void *marker, void *trampoline, void *table_entry); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
#if defined (_ARCH_i386_) || defined(_ARCH_i686_) | ||
|
||
#include <stdint.h> | ||
#include <string.h> | ||
|
||
#include <sys/mman.h> | ||
|
||
#include "arch.h" | ||
#include "x86_gen.h" | ||
|
||
/* This is the stage 1 inline trampoline for hooking the inlined add_freelist | ||
* function . | ||
* | ||
* NOTE: The original instruction mov %reg, freelist is 7 bytes wide, | ||
* whereas jmpq $displacement is only 5 bytes wide. We *must* pad out | ||
* the next two bytes. This will be important to remember below. | ||
*/ | ||
struct inline_st1_tramp { | ||
unsigned char jmp; | ||
uint32_t displacement; | ||
unsigned char pad; | ||
} __attribute__((__packed__)) inline_st1_tramp = { | ||
.jmp = '\xe9', | ||
.displacement = 0, | ||
.pad = '\x90', | ||
}; | ||
|
||
struct inline_st1_base_short { | ||
unsigned char mov; | ||
void *addr; | ||
} __attribute__((__packed__)) inline_st1_short = { | ||
.mov = '\xa3', | ||
.addr = 0, | ||
}; | ||
|
||
struct inline_st1_base_long { | ||
unsigned char mov; | ||
unsigned char src_reg; | ||
void *addr; | ||
} __attribute__((__packed__)) inline_st1_long = { | ||
.mov = '\x89', | ||
.src_reg = 0, | ||
.addr = 0 | ||
}; | ||
|
||
static int | ||
arch_check_ins(unsigned char *base) | ||
{ | ||
|
||
/* if the byte is 0xa3 then we're moving from %eax, so | ||
* the length is only 5, so we don't need the pad. | ||
* | ||
* otherwise, we're moving from something else, so the | ||
* length is going to be 6 and we need a NOP. | ||
*/ | ||
|
||
/* is it a mov instruction? */ | ||
if (*base == 0xa3) | ||
return 0; | ||
else if (*base == 0x89) | ||
return 1; | ||
|
||
return -1; | ||
} | ||
|
||
int | ||
arch_insert_inline_st2_tramp(void *addr, void *marker, void *trampoline, void *table_entry) | ||
{ | ||
struct inline_st1_base_long *long_base = addr; | ||
struct inline_st1_base_short *short_base = addr; | ||
struct inline_st1_tramp *st1_tramp = addr; | ||
void *mov_target = NULL; | ||
size_t pad_length = 0; | ||
|
||
if ((pad_length = arch_check_ins(addr)) == -1) | ||
return 1; | ||
|
||
if (pad_length == 0) { | ||
mov_target = short_base->addr; | ||
default_inline_st2_tramp.mov = 0x90; | ||
default_inline_st2_tramp.src_reg = 0xa3; | ||
inline_st1_tramp.displacement = table_entry - (void *)(short_base + 1); | ||
default_inline_st2_tramp.jmp_displacement = (void *)(short_base + 1) - (table_entry + sizeof(default_inline_st2_tramp)); | ||
} else { | ||
mov_target = long_base->addr; | ||
default_inline_st2_tramp.mov = long_base->mov; | ||
default_inline_st2_tramp.src_reg = long_base->src_reg; | ||
inline_st1_tramp.displacement = table_entry - (void *)(long_base + 1) + 1; | ||
default_inline_st2_tramp.jmp_displacement = (void *)(long_base + 1) - (table_entry + sizeof(default_inline_st2_tramp)); | ||
} | ||
|
||
if (marker == mov_target) { | ||
default_inline_st2_tramp.mov_addr= default_inline_st2_tramp.frame.freelist = marker; | ||
default_inline_st2_tramp.frame.fn_addr = trampoline; | ||
if (pad_length) { | ||
copy_instructions(addr, &inline_st1_tramp, sizeof(inline_st1_tramp)); | ||
} else { | ||
copy_instructions(addr, &inline_st1_tramp, sizeof(inline_st1_tramp) - 1); | ||
} | ||
memcpy(table_entry, &default_inline_st2_tramp, sizeof(default_inline_st2_tramp)); | ||
return 0; | ||
} | ||
|
||
return 1; | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
#if !defined(_i386_h_) | ||
#define _i386_h_ | ||
|
||
#include <stdint.h> | ||
#include "arch.h" | ||
|
||
/* | ||
* This is the "normal" stage 2 trampoline with a default entry pre-filled | ||
*/ | ||
static struct tramp_st2_entry { | ||
unsigned char ebx_save; | ||
unsigned char mov; | ||
void *addr; | ||
unsigned char call[2]; | ||
unsigned char ebx_restore; | ||
unsigned char ret; | ||
} __attribute__((__packed__)) default_st2_tramp = { | ||
.ebx_save = 0x53, /* push ebx */ | ||
.mov = 0xbb, /* mov addr into ebx */ | ||
.addr = 0, /* this is filled in later */ | ||
.call = {0xff, 0xd3}, /* calll *ebx */ | ||
.ebx_restore = 0x5b, /* pop ebx */ | ||
.ret = 0xc3, /* ret */ | ||
}; | ||
|
||
|
||
/* | ||
* This is the inline stage 2 trampoline with a default entry pre-filled | ||
*/ | ||
static struct inline_tramp_st2_entry { | ||
|
||
/* this block will be filled in at runtime to replicate the overwritten | ||
* instruction. | ||
*/ | ||
unsigned char mov; | ||
unsigned char src_reg; | ||
void *mov_addr; | ||
|
||
/* this frame will arrange freelist to be passed as an argument to | ||
* the third and final trampoline (C level). | ||
*/ | ||
struct { | ||
unsigned char push_ebx; | ||
unsigned char pushl[2]; | ||
void * freelist; | ||
unsigned char mov_ebx; | ||
void * fn_addr; | ||
unsigned char call[2]; | ||
unsigned char pop_ebx; | ||
unsigned char restore_ebx; | ||
} __attribute__((__packed__)) frame; | ||
|
||
/* this block jumps back to resume execution */ | ||
unsigned char jmp; | ||
uint32_t jmp_displacement; | ||
} __attribute__((__packed__)) default_inline_st2_tramp = { | ||
.mov = 0x89, | ||
.src_reg = 0, | ||
.mov_addr = 0, | ||
|
||
.frame = { | ||
.push_ebx = 0x53, | ||
.pushl = {0xff, 0x35}, | ||
.freelist = 0, | ||
.mov_ebx = 0xbb, | ||
.fn_addr = 0, | ||
.call = {0xff, 0xd3}, | ||
.pop_ebx = 0x5b, | ||
.restore_ebx = 0x5b, | ||
}, | ||
|
||
.jmp = 0xe9, | ||
.jmp_displacement = 0, | ||
}; | ||
#endif |
Oops, something went wrong.