exit hook分析

最近学习exit hook,网上师傅分析exit hook时都一带而过,没有具体分析细节,所以这里通过看源码给大家详细分析一下几种exit hook:

  • __libc_atexit
  • _rtld_global
    • _dl_rtld_lock_recursive
    • _dl_rtld_unlock_recursive

我用的是2.31的libc源码,本文涉及源码部分较多,而且只截取了关键部分,光阅读可能比较难以接受,建议大家按这个思路边调试边看一下加深理解。

__libc_atexit

调用流程:

exit->__run_exit_handlers->__libc_atexit

对exit下断点,看到调用了__run_exit_handlers函数:

   136 void
   137 exit (int status)
 ► 138 {
   139   __run_exit_handlers (status, &__exit_funcs, true, true);
   140 }

__libc_atexit__run_exit_handlers结束时调用到的:

libc_atexit

源码编写者用了很多宏,光看这个是看不清的,我们一步步看有关的宏来分析。

首先,看exit.c源码,查看__libc_atexit相关代码,首先开头处有一处DEFINE_HOOK宏:

DEFINE_HOOK (__libc_atexit, (void))

然后就是后面调用RUN_HOOK宏了:

  if (run_list_atexit)
    RUN_HOOK (__libc_atexit, ());

  _exit (status);
}

DEFINE_HOOK分析

顾名思义,DEFINE_HOOK应该是跟声明定义有关,我们先看这个。

DEFINE_HOOKRUN_HOOK两处宏都定义在set-hooks.h头文件中,所以我们转到该文件中查看。

DEFINE_HOOK定义:

/* Define a hook variable called NAME.  Functions put on this hook take
   arguments described by PROTO.  Use `text_set_element (NAME, FUNCTION)'
   from include/libc-symbols.h to add a function to the hook.  */

# define DEFINE_HOOK(NAME, PROTO)       \
  typedef void __##NAME##_hook_function_t PROTO; \
  symbol_set_define (NAME)

定义了一个类型,然后symbol_set_define又是一处宏,在libc-symbols.h中定义:

/* Define SET as a symbol set.  This may be required (it is in a.out) to
   be able to use the set's contents.  */
#define symbol_set_define(set)  symbol_set_declare(set)

/* Declare SET for use in this module, if defined in another module.
   In a shared library, this is always local to that shared object.
   For static linking, the set might be wholly absent and so we use
   weak references.  */
#define symbol_set_declare(set) \
  extern char const __start_##set[] __symbol_set_attribute; \
  extern char const __stop_##set[] __symbol_set_attribute;

__symbol_set_attribute又是一处宏,不过不用再继续看下去了,很明显,这里其实就是声明了两个函数指针数组。

总结一下,DEFINE_HOOK的作用就是定义一种函数指针类型,然后声明了两个函数指针数组。

RUN_HOOK分析

RUN_HOOK估计是跟调用hook有关的,看宏定义:

/* Run all the functions hooked on the set called NAME.
   Each function is called like this: `function ARGS'.  */

# define RUN_HOOK(NAME, ARGS)                             \
do {                                          \
  void *const *ptr;                           \
  for (ptr = (void *const *) symbol_set_first_element (NAME);             \
       ! symbol_set_end_p (NAME, ptr); ++ptr)                     \
    (*(__##NAME##_hook_function_t *) *ptr) ARGS;                  \
} while (0)

看到symbol_set_first_elementsymbol_set_end_p也是宏,同样定义在libc-symbols.h中:

/* Return a pointer (void *const *) to the first element of SET.  */
#define symbol_set_first_element(set)   ((void *const *) (&__start_##set))

/* Return true iff PTR (a void *const *) has been incremented
   past the last element in SET.  */
#define symbol_set_end_p(set, ptr) ((ptr) >= (void *const *) &__stop_##set)

很明显了,RUN_HOOK的作用就是遍历上面DEFINE_HOOK定义的函数指针数组。

利用

我们把上面的宏用实际参数带入,得到实际是从__start___libc_atexit开始遍历到__stop___libc_atexit

gdb查看该位置,发现__start___libc_atexit实际上是__elf_set___libc_atexit_element__IO_cleanup__,该地址可写,指向_IO_cleanup

因此,我们可以修改该地址指向one_gadget或进行其他利用。

_rtld_global

这个结构体相关的exit hook,我找到一篇写得很清楚的文章,就不重新分析了,在此贴上链接:浅谈exit函数的利用方式之一——exit hook

暂无评论

发送评论 编辑评论

|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇