注册 登录
自由的生活_软路由 返回首页

心想事成的个人空间 https://bbs.routerclub.com/?681 [收藏] [复制] [分享] [RSS]

日志

再谈劫持mips里的函数

已有 1526 次阅读2013-8-14 22:37

我之前在这篇文章(http://bbs.routerclub.com/blog-681-7070.html)里介绍了劫持mips的函数,但是是for mipsl的,现在要针对mipsb的代码
需要将jmp数组里的字节码反转一下。
汇编函数仍然不变,通过as命令
lui $25,0x3000
li $1,0x0
addu $25,$25,$1
jr $25
nop

再通过ida反编译后,可以看到数组:
3C 19 30 00        lui     $t9, 0x3000
24 01 00 00        li      $at, 0
03 21 C8 21        addu    $t9, $at
03 20 00 08        jr      $t9
00 00 00 00        nop

再在c中修改对应的跳转地址就可以了,不过也许要用htons转换一下大小端?

在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);
}



路过

雷人

握手

鲜花

鸡蛋

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

QQ|Archiver|手机版|小黑屋|软路由 ( 渝ICP备15001194号-1|渝公网安备 50011602500124号 )

GMT+8, 2024-4-28 22:38 , Processed in 0.038702 second(s), 5 queries , Gzip On, Redis On.

Powered by Discuz! X3.5 Licensed

© 2001-2023 Discuz! Team.

返回顶部