首先弄清楚如何加载一个共享库?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打开的库句柄