我之前在这篇文章(http://bbs.routerclub.com/blog-681-7070.html)里介绍了劫持mips的函数,但是是for mipsl的,现在要针对mipsb的代码
在elfs里,也有函数跳转的代码,但它要巧妙精减一些。
它不用加载高位的指令,直接加载hook函数与原函数的差值,然后jmp过去,然后再在hook里把原函数被覆盖的3个指令
cp过来,再直接jmp到原函数。
下面是代码:
int elfsh_cflow_mips32(elfshobj_t *file,
char *name,
elfsh_Sym *symbol,
eresi_Addr addr)
{
elfshsect_t *hooks;
elfshsect_t *source;
uint32_t buff[3];
int ret, len;
int off;
char *hookbuf;
char *hook;
//elfsh_Sym sym;
char bufname[BUFSIZ];
void *data;
PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);
/*
func+0: [addu t9, (hook-func)]
func+4: [jump hook]
func+8: [nop]
func+c: [???]
hook: ...
old_entry+0: [addu t9, (func-old_entry)]
old_entry+4: [instr1]
old_entry+8: [instr2]
old_entry+c: [instr3]
old_entry+10: [jmp func+8]
old_entry+14: [nop]
*/
/* Resolve parameters */
off = elfsh_get_foffset_from_vaddr(file, symbol->st_value);
if (!off)
PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
"Invalid address to hijack", -1);
ret = elfsh_readmemf(file, off, (void *) buff, 3*4);
if (ret != 3*4)
PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
"Function too small to be hijacked", -1);
/* If the hook section does not exist, create it */
hooks = elfsh_get_section_by_name(file, ELFSH_SECTION_NAME_HOOKS, 0, 0, 0);
if (!hooks)
PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
"Cannot get .HOOKS", -1);
hook = (char *) (hooks->shdr->sh_addr + hooks->curend);
if (((uint32_t) symbol->st_value & 0xf0000000) != (addr & 0xf0000000))
PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
"hook function too far from hijacked function", -1);
if (((uint32_t) hook & 0xf0000000) != ((symbol->st_value + 0x8) & 0xf0000000))
PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
"hook section too far from hijacked function", -1);
if ((addr - (uint32_t) symbol->st_value) & (0xffffffff<<16))
PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
"hook function too far from hijacked function", -1);
if (((uint32_t) symbol->st_value - (uint32_t) hook) & (0xffffffff<<16))
PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
"hook section too far from hijacked function", -1);
/* Determine the minimal aligned length */
/* RISC's powa */
/* 3 instructions : 1 add t9..., 1 jmp, 1 nop for delay slot */
ret = 3 * 4;
/* Create the hook for this function */
data = elfsh_readmem(hooks);
memset(data + hooks->curend, 0x00, 40); // nop
/* addi $t, $s, imm : 0010 00ss ssst tttt iiii iiii iiii iiii */
*((uint32_t *) ((char *) (data + hooks->curend) + 0x0)) = 0x23390000;
*((uint32_t *) ((char *) (data + hooks->curend) + 0x0)) |=
(((uint32_t) symbol->st_value - (uint32_t)hook) & 0x0000ffff);
/* first three hijacked function's instructions */
*((uint32_t *) ((char *) (data + hooks->curend) + 0x4)) = buff[0];
*((uint32_t *) ((char *) (data + hooks->curend) + 0x8)) = buff[1];
*((uint32_t *) ((char *) (data + hooks->curend) + 0xc)) = buff[2];
/* non-linked jump to func + 8 (where should be a NOP) */
/* mips32 jump use the 4 MSB of PC reg and 26 bits from instruction left
shited by 2 */
memcpy(data + hooks->curend + 0x10, "\x08\x00\x00\x00", 4);
*((uint32_t *) ((char *) (data + hooks->curend) + 0x10)) |= ((symbol->st_value + 0x8) & (~ 0xe0000000 ))>>2;
/* NOTE : there must be a NOP after this last jump */
/* Insert the old symbol on the original saved bytes */
//name = elfsh_get_symbol_name(file, symbo);
snprintf(bufname, BUFSIZ, "old_%s", name);
elfsh_insert_funcsym(file, bufname, (eresi_Addr) hook,
ret + 0x10, hooks->index);
/*
snprintf(bufname, BUFSIZ, "hook_%s", name);
elfsh_insert_funcsym(file, bufname, addr,
ret + 8, hooks->index);
*/
/* We need to grab the parent section to compute the remaining offset */
source = elfsh_get_parent_section_by_foffset(file, off, NULL);
if (!source)
PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
"Cannot find parent section for hooked addr", -1);
/* Install the hook */
hookbuf = alloca(ret);
/* patch t9 reg */
*((uint32_t *) ((char *) (hookbuf) + 0x0)) = 0x23390000;
*((uint32_t *) ((char *) (hookbuf) + 0x0)) |= ((addr - symbol->st_value) &
0x0000ffff);
/* jump to hook func */
*((uint32_t *) ((char *) (hookbuf) + 0x4)) = 0x08000000;
*((uint32_t *) ((char *) (hookbuf) + 0x4)) |= ((uint32_t) (addr ) &
(~0xe0000000))>>2;
/* delay slot's NOP */
*((uint32_t *) ((char *) (hookbuf) + 0x8)) = 0x00000000;
len = elfsh_writememf(file, off, hookbuf, ret);
if (len != ret)
PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
"Error during hook installation", -1);
/* Everything OK, ret is always 3*4 on mips32 (RISC strike again) */
hooks->curend += ret + 6; // (6 = 1 add, 3 instr, 1 jump, 1 nop)
PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
}