10.6. 共享库注入

首先弄清楚如何加载一个共享库?libdl提供了dlopen(),dlsymb(),dlclose().
objdump --dynamic-syms /lib/libc.so.6 | \
grep _dl_ | egrep "open|close|sym"
000f7d10 g DF .text 000001ad GLIBC_2.2 _dl_vsym
000f6f10 g DF .text 000006b8 GLIBC_2.0 _dl_close
000f6d80 g DF .text 00000190 GLIBC_2.0 _dl_open
000f7c00 g DF .text 0000010d GLIBC_2.2 _dl_sym
可以看到共享库lib.so.6有_dl_open, _dl_sym,和_dl_close。
来看看他们的原型
extern void *dlopen (const char *file, int mode);
extern void *dlsym (void *handle, const char *name)
extern int dlclose (void *handle)
而这些是
void *_dl_open (const char *file, int mode, const void *caller)
void *_dl_sym (void *handle, const char *name, void *who)
void _dl_close (void *_map)
        000f6d80 <.text+0xdde00> (_dl_open):
           f6d80:       55                      push   %ebp
           f6d81:       89 e5                   mov    %esp,%ebp
           f6d83:       83 ec 2c                sub    $0x2c,%esp
           f6d86:       57                      push   %edi
           f6d87:       56                      push   %esi
           f6d88:       53                      push   %ebx
           f6d89:       e8 00 00 00 00          call   0xf6d8e
           f6d8e:       5b                      pop    %ebx
           f6d8f:       81 c3 ba 10 02 00       add    $0x210ba,%ebx
           f6d95:       89 c7                   mov    %eax,%edi
           f6d97:       89 d6                   mov    %edx,%esi
           f6d99:       89 4d e4                mov    %ecx,0xffffffe4(%ebp)
           f6d9c:       f7 c6 03 00 00 00       test   $0x3,%esi
           f6da2:       75 1c                   jne    0xf6dc0
           f6da4:       83 c4 f4                add    $0xfffffff4,%esp

      void *
      internal_function
      _dl_open (const char *file, int mode, const void *caller)
      {
           struct dl_open_args args;
           const char *objname;
           const char *errstring;
           int errcode;
         
           if ((mode & RTLD_BINDING_MASK) == 0)
                /* One of the flags must be set.  */
                _dl_signal_error (EINVAL, file, NULL, 
                  N_("invalid mode for dlopen()"));

         ....

      }

      其中eax = library name共享库名 (例如: /lib/libc.so.6)
      ecx = caller调用者 (例如: ./example)
      edx = mode模式 (例如:RTLD_NOW | 0x80000000)

那么我们可以写下如下代码:
nop
nop
nop
nop
nop
nop

call *%edi # 调用_dl_open
int $0x3 # 断点
nop

其它的期望参数是:
_dl_sym:
eax = library handle被_dl_open打开的库句柄
edx = symbol name符号名(例如:pthread_create)

_dl_close:
eax = library hanlde被_dl_open打开的库句柄