dlmopen ã使ã£ã¦ã·ã¹ãã ã³ã¼ã«ã®ããã¯ãããæãã«ããã°ã©ãã³ã°ãã
前回の記事ã§ç´¹ä»ãã¾ãã Zpoline ã¨ããã·ã¹ãã ã³ã¼ã«ããã¯ã®ä»çµã¿ã ã¨ããã¤ããªæ¸ãæãå¾ã®é¢æ°ããã·ã¹ãã ã³ã¼ã«ããã¯ããå¼ã³åºãã¦ãã¾ãã¨ããããããã¯ãããã¯ç¡éã«ã¼ããçºçãããã¨ãããã¨ããåé¡ãããã¾ããã
çµæã¨ãã¦ãã·ã¹ãã ã³ã¼ã«ããã¯ã®å®è£ ã«æ¨æºã©ã¤ãã©ãªå ã®æ©è½ãä¾ãã°ãprintf çã使ããªãã¦ããã°ã©ãã³ã°ããã«ãããªã£ã¦ãã¾ããã
ãã®åé¡ã¯ãdlmopen ã¨ããæ©è½ã使ãã¨è§£æ±ºã§ããã¨æãã¦é ãã¦ãå®éã«å¤§åç°¡åã«ããã¯é¢æ°ãå®è£ ã§ããããã«ãªã£ãã®ã§ãä»åã®è¨äºã§ã¯ãå ·ä½ç㪠Zpoline ã§ã®å©ç¨æ¹æ³ã«ã¤ãã¦èª¬æãã¾ãã
以ä¸ã® GitHub ä¸ã®ãªãã¸ããªã«ç½®ãã¦ããã½ã¼ã¹ã³ã¼ã㯠dlmopen ãå©ç¨ã§ããããã«å¤æ´ãã¦ããã¾ãã®ã§ãããã£ããæ¯é試ãã¦ã¿ã¦ãã ããã
dlmopen ã®åã« dlopen ã¨ã¯ï¼
dlmopen 㯠dlopen ã¨ããæ©è½ã®æ¡å¼µã§ããdlmopen ã®åã«ãç°¡åã« dlopen ã«ã¤ãã¦èª¬æãã¾ãã
dlopen ãå©ç¨ããã¨ãããã°ã©ã ã®ä¸ãããä»»æã®å ±æã©ã¤ãã©ãªãã¡ã¤ã«ããã¼ããããã¨ãã§ãã¾ãã
å ·ä½ä¾ã¨ãã¦ã以ä¸ã®ãããªãµã³ãã«ããã°ã©ã ãç¨æãã¦ã¿ã¾ããã
dlopentest.c
#include <dlfcn.h> int main(void) { void (*example_fn)(void); void *handle = dlopen("./libdlopentest.so", RTLD_NOW); example_fn = dlsym(handle, "example_function"); example_fn(); dlclose(handle); return 0; }
libdlopentest.c
#include <stdio.h> void example_function(void) { printf("I'm example_function\n"); }
ä¸ã®ããã°ã©ã ã¯ãããã以ä¸ã®ã³ãã³ãã§ã³ã³ãã¤ã«ã§ãã¾ãã
$ gcc dlopentest.c -ldl $ gcc -shared -fPIC -o libdlopentest.so libdlopentest.c
çæããã a.out ãå®è¡ããã¨ä»¥ä¸ã®ãããªåºåã«ãªãã¾ãã
$ ./a.out I'm example_function
ä¸ã®ãµã³ãã«ã§ã¯ãa.out (dlopentest.c) ã®ä¸ãããlibdlopentest.so (libdlopentest.c) ã¨ããå ±æã©ã¤ãã©ãªãã¡ã¤ã«ã dlopen ã使ã£ã¦ãã¼ããããã®ä¸ã«å®è£ ããã¦ãããexample_function ã¨ããååã®é¢æ°ãå®è¡ãã¦ãã¾ãã
å¤ãã®å ´åãå ±æã©ã¤ãã©ãªãããã°ã©ã ã«çµã¿è¾¼ãã«ã¯ãä¾ãã°ä»åã®ä¾ã§ã¯ã以ä¸ã®ããã« -l[ã©ã¤ãã©ãªå] ã®ããã«ã³ã³ãã¤ã©ã«å¯¾ãã¦æå®ããã¨æãã¾ããã
$ gcc dlopentest.c -ldlopentest # ããã¯ä¾ã§å®éã«ã¯åãã¾ãã
dlopen ãå©ç¨ããã¨ãã³ã³ãã¤ã©ã«ããç´ä»ãã¨ã¯å¥ã«ããã°ã©ã ã®ä¸ããå ±æã©ã¤ãã©ãªããã¼ããããã¨ãã§ãã¾ãã
dlmopen
dlmopen 㯠dlopen ã¨ãåºæ¬çã«å ±æã©ã¤ãã©ãªãããã°ã©ã å ã¸ãã¼ãã§ããã¨ããç¹ã§åãã§ãããå ±æã©ã¤ãã©ãªããã¼ãããåå空éãæå®ã§ããã¨ããæ¡å¼µãå®è£ ãã¦ããç¹ã§ç°ãªãã¾ãã
ã©ã¤ãã©ãªã®ãã¼ããããåå空éãåãããã¨ã§ãããç¹å®ã®å®è£ ããããã©ã«ãã§ãã¼ãããã¦ããã©ã¤ãã©ãªå®è£ ãä¾ãã° libc ãå©ç¨ããªãããã«ã§ãã¾ãã
å ·ä½çã«ã©ããããã¨ãããããã«ããã¨æãã¾ããã®ã§ã以ä¸ã«ãµã³ãã«ããã°ã©ã ãç¨æãã¦ã¿ã¾ããã以ä¸ã®ããã°ã©ã ã§ã¯ãdlopen ããã㯠dlmopen ã使ã£ã¦ãå ±æã©ã¤ãã©ãªãããã©ã«ãã¨ã¯å¥ã®åå空éã«ãã¼ãããå¾ã§ãmain() 㨠example_function() ãå©ç¨ãã¦ãã printf ã®ã¢ãã¬ã¹ãåºåãã¦ãã¾ããdlopen 㨠dlmopen ã®ã©ã¡ããå©ç¨ãããã¯ãããã°ã©ã (a.out ) ã®å¼æ°ã§æå®ã§ãã¾ããï¼0 => dlopen, 0 ä»¥å¤ => dlmopoenï¼
dlmopentest.c
#ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include <stdio.h> #include <stdlib.h> #include <dlfcn.h> int main(int argc, char const* argv[]) { void (*example_fn)(void); void *handle; if (atoi(argv[1]) == 0) { printf("use dlopen: printf used by main and example_function will be the same\n"); handle = dlopen("./libdlmopentest.so", RTLD_NOW | RTLD_LOCAL); } else { printf("use dlmopen: printf used by main and example_function will be different\n"); handle = dlmopen(LM_ID_NEWLM, "./libdlmopentest.so", RTLD_NOW | RTLD_LOCAL); } example_fn = dlsym(handle, "example_function"); printf("I'm main (printf is at %p)\n", printf); example_fn(); dlclose(handle); return 0; }
libdlmopentest.c
#include <stdio.h> void example_function(void) { printf("I'm example_function (printf is at %p)\n", printf); }
ä¸ã®ããã°ã©ã ã¯ä»¥ä¸ã®ã³ãã³ãã§ã³ã³ãã¤ã«ã§ãã¾ãã
$ gcc dlmopentest.c -ldl $ gcc -shared -fPIC -o libdlmopentest.so libdlmopentest.c
以ä¸ã¯ããã°ã©ã ã®åºåã®ä¾ã§ãã
$ ./a.out 0 use dlopen: printf used by main and example_function will be the same I'm main (printf is at 0x7f26b8dfce10) I'm example_function (printf is at 0x7f26b8dfce10) $ ./a.out 1 use dlmopen: printf used by main and example_function will be different I'm main (printf is at 0x7fb852ce0e10) I'm example_function (printf is at 0x7fb852ad2e10)
dlopen ãå©ç¨ããå ´åï¼ä¸ã®åºåã§ã¯ $ ./a.out 0 ã®å ´åï¼ã¯ãmain 㨠example_function ã表示ãã printf ã®ã¢ãã¬ã¹ãåãï¼0x7f26b8dfce10ï¼ã§ããä¸æ¹ãdlmopen ãå©ç¨ããã¨ï¼ä¸ã®åºå㧠$ ./a.out 1 ã®å ´åï¼ããããããç°ãªãã¢ãã¬ã¹ï¼main: 0x7fb852ce0e10 㨠example_function: 0x7fb852ad2e10ï¼ã表示ãã¦ãã¾ãã
ããã¯ãdlmopen ã libdlmopentest.so 㨠libdlmopentest.so ãä¾åãã¦ããã©ã¤ãã©ãªï¼ä»å㯠libcï¼ããããã©ã«ãã¨ã¯ç°ãªãæ°ããåå空éã«ãã¼ãããlibdlmopentest.so å é¨ã®å®è£ ããæ°ããåå空éã«ãã¼ãããã libc ãå©ç¨ããããã«è¨å®ãã¦ãããããã§ãã
ä»åã¯ãlibdlmopentest.so ã«å®è£ ããã¦ãã example_function ãããã©ã«ãã® libc ãå©ç¨ããªããªã£ããã¨ããã¨ããããã¤ã³ãã§ãã
Zpoline 㧠dlmopen ãå©ç¨ãã
ããã¾ã§ã® Zpoline ãå©ç¨ããå ´åã®ããã¯é¢æ°å®è£ ã«ã¤ãã¦ã®åé¡ã¯ãããã¯é¢æ°ããããã¯é©ç¨å¯¾è±¡ã®ããã°ã©ã ã®ããã«ç¨æãããã©ã¤ãã©ãªçã®ãªã½ã¼ã¹ãå©ç¨ãã¦ãã¾ããã¨ã«èµ·å ãã¾ããã
dlmopen ãå©ç¨ããã¨ãããã¯é¢æ°ã®ããã ãã«ã©ã¤ãã©ãªã®ãããªãªã½ã¼ã¹ãæ°ããç¨æãããã¨ãã§ããã¾ããããã¯é¢æ°ãããããã¯é©ç¨å¯¾è±¡ã®ããã°ã©ã ã®ããã®ãªã½ã¼ã¹ãå©ç¨ããªãããã«ã§ãããã¨ããã®ãä»åã®ãã¤ã³ãã§ãã
ä»åã®å®è£ ã§ã¯ãZpoline ã®åæåç¨ã®å ±æã©ã¤ãã©ãªã¨ãããã¯é¢æ°å®è£ ããå¥ã ã®å ±æã©ã¤ãã©ãªã¨ãã¦ã³ã³ãã¤ã«ãã¾ãã
åæåç¨ã®å ±æã©ã¤ãã©ãªã¯ãLD_PRELOAD ã§ãã¼ãããããã¨ãæ³å®ãã¦ãããããã¯é©ç¨å¯¾è±¡ã®ããã°ã©ã ã® main() ãéå§ããåã«ããã©ã³ããªã³ã³ã¼ãã®ç¨æã¨ãã¤ããªæ¸ãæããè¡ãã¾ããããã«ããã®å¾ãdlmopen ã使ã£ã¦ãããã¯é¢æ°ã®å®è£ ãå«ãå ±æã©ã¤ãã©ãªããæ°ããåå空éã¸ãã¼ããã¾ãã
å®è£
以ä¸ã®ã³ã¼ãããZpoline 㧠dlmopen ãå©ç¨ããåæåç¨ã©ã¤ãã©ãªï¼LD_PRELOAD ã§ãã¼ããããæ¹ï¼ã®å®è£ ã§ãã以ä¸ã§ã¯ãããã¯é¢æ°ã¯ãLIBZPHOOK ã¨ããç°å¢å¤æ°ã«æå®ãããå ±æã©ã¤ãã©ãªã®ä¸ã§ã__hook_fn ã¨ããååã§å®è£ ãã¦ãããã¨ãæ³å®ãã¦ãã¾ããï¼ããããããã®ããã«ç°¡ç¥åãã¦ããã¾ãã詳ããã¯ソースコードããåç §ãã ãããï¼
static long (*hook_fn)(int64_t a1, int64_t a2, int64_t a3, int64_t a4, int64_t a5, int64_t a6, int64_t a7) = NULL; /* trampoline code will jump to syscall_hook */ long syscall_hook(int64_t a1, int64_t a2, int64_t a3, int64_t a4, int64_t a5, int64_t a6, int64_t a7) { return hook_fn(a1, a2, a3, a4, a5, a6, a7); } static void load_hook_lib(void) { void *handle; const char *filename; filename = getenv("LIBZPHOOK"); handle = dlmopen(LM_ID_NEWLM, filename, RTLD_NOW | RTLD_LOCAL); hook_fn = dlsym(handle, "__hook_fn"); } __attribute__((constructor(0xffff))) static void __zpoline_init(void) { setup_trampoline(); rewrite_code(); load_hook_lib(); // load hook function library }
ä¸ã®ã³ã¼ãã§ã¯ãLD_PRELOAD ã«ãã£ã¦ãã¼ããããæã«ã__zpoline_init ãæåã«å®è¡ããããã¨ãæ³å®ãã¦ãã¾ãã
__zpoline_init
__zpoline_init ã¯ããã©ã³ããªã³ã³ã¼ããç¨æã㦠(setup_trampoline)ããã¤ããªæ¸ãæããè¡ã£ãå¾ (rewrite_code)ãããã¯å®è£ ãå«ãã å ±æã©ã¤ãã©ãªã dlmopen ã使ã£ã¦ãã¼ããã¾ã (load_hook_lib)ã
load_hook_lib
ä¸ã®ã³ã¼ãå ã® load_hook_lib ã§ã¯ãdlmopen ã使ã£ã¦ãLIBZPHOOK ã¨ããç°å¢å¤æ°ã«æå®ããããããã¯é¢æ°ã®å®è£ ãå«ãå ±æã©ã¤ãã©ãªããæ°ããåå空éã«ãã¼ããã¾ãã
ãã®æ°ããåå空éã«ãã¼ããããããã°ã©ã ã«å¯¾ãã¦ã¯ããã¤ããªæ¸ãæãã¯è¡ãã¾ãããçµæã¨ãã¦ãããã¯é¢æ°å ã§ãé常ã§ããã°ã·ã¹ãã ã³ã¼ã«ãçºè¡ããã©ã¤ãã©ãªé¢æ°çãå¼ã³åºããã¨ãã¦ãããã®ã·ã¹ãã ã³ã¼ã«ã¯ããã¯ãããããã®ã¾ã¾ã«ã¼ãã«ã«å¯¾ãã¦ã·ã¹ãã ã³ã¼ã«ãçºè¡ããã¾ãã
ããã¯é¢æ°å®è£ ãå«ãå ±æã©ã¤ãã©ãªã®ãã¼ãå®äºå¾ã«ãdlsym ã¨ããæ©è½ã使ã£ã¦ãããã¯é¢æ°ã§ãã __hook_fn ã¨ããååã®é¢æ°ãæ¢ãããã®ã¢ãã¬ã¹ã hook_fn ã¨ããååã®ãã¤ã³ã¿ã¸ä»£å ¥ãã¾ãã
syscall_hook
ãã¤ããªæ¸ãæãå¾ã¯ãããã¯é©ç¨å¾ã®ããã°ã©ã ãçºè¡ãããã¨ããã·ã¹ãã ã³ã¼ã«ã¯ããã¯ãããsyscall_hook ã¨ããé¢æ°ã¸ãªãã¤ã¬ã¯ããããããã«ãªãã¾ãããã®ä¸ã§ãå ã»ã©ã® hook_fn ï¼ã¤ã¾ãå ±æã©ã¤ãã©ãªå ã® __hook_fnï¼ãå¼ã³åºãã¾ãã
__hook_fn
__hook_fn ã®å®è£ èªä½ã¯ãå¥ã®åå空éã«ãã¼ãããã¦ããããã®ä¸ã§å¼ã³åºããããä¾ãã° printf çã¯ãããã¯é©ç¨å¯¾è±¡ã®ããã°ã©ã ãå©ç¨ãããã®ã¨ã¯å¥ã®ãã®ã«ãªãã¾ãã
ããã§ãããã¯é¢æ°å®è£ ï¼__hook_fnï¼ãããã¯é©ç¨å¯¾è±¡ã®ããã°ã©ã ã®ãªã½ã¼ã¹ãå©ç¨ãããã¨ãåé¿ã§ããããã«ãªãã¾ããã
dlmopen ã¯ãããã¯é¢æ°å®è£ ãå«ãå ±æã©ã¤ãã©ãªãä¾åããå¥ã®ã©ã¤ãã©ãªãä¸ç·ã«æ°ããåå空éã«ãã¼ããã¦ããããããããã¯é¢æ°å®è£ 㧠libc 以å¤ã®ã©ã¤ãã©ãªãå©ç¨ãããã¨ãå¯è½ã§ãã
ç¬èªã®ããã¯é¢æ°ãå®è£ ããã«ã¯
ç¬èªã®ã·ã¹ãã ã³ã¼ã«ããã¯ãå®è£ ããã«ã¯ãä»åã®ä¾ã§ã¯ã__hook_fn ã¨ããååã®ããã¯é¢æ°ãå®è£ ããç¬ç«ããå ±æã©ã¤ãã©ãªã¨ãã¦ã³ã³ãã¤ã«ããã¨è¯ãã¨æããã¾ãã
ä¸ã®ä¾ããã®ã¾ã¾ä½¿ãã¨ãä»®ã«ã__hook_fn ãå«ãå ±æã©ã¤ãã©ãªã ./apps/basic/libzphook_basic.so ã¨ãããã¹ã«ã³ã³ãã¤ã«ãã¦è¨ç½®ããå ´åã«ã¯ã以ä¸ã®ãããªã³ãã³ãã§ãç¬èªã® __hook_fn å®è£ ãããã¯é¢æ°ã¨ãã¦é©ç¨ã§ãã¾ãã
$ LIBZPHOOK=./apps/basic/libzphook_basic.so LD_PRELOAD=./libzpoline.so [program you wish to run]
以ä¸ã¯ãããã¯é¢æ°å®è£ ã®ä¾ã§ãã以ä¸ã® __hook_fn 㯠a1 ã«ã·ã¹ãã ã³ã¼ã«çªå·ãa2~a7 ã¸ã·ã¹ãã ã³ã¼ã«ã®å¼æ°ãå ¥ã£ã¦ãã¾ãããã®ä¸ã§ãä¾ãã°ãå®éã«ã·ã¹ãã ã³ã¼ã«ãçºè¡ãããã¨ããã·ã¹ãã ã³ã¼ã«ãã¨ãã¥ã¬ã¼ããããã¨ãã§ãã¾ããï¼ç°¡ç¥åãã¦ããã¾ãã®ã§ã詳細㯠GitHub 上のサンプルプログラムãè¦ã¦ã¿ã¦ãã ãããï¼
#include <stdio.h> #include <stdint.h> #include <unistd.h> #include <syscall.h> long __hook_fn(int64_t a1, int64_t a2, int64_t a3, int64_t a4, int64_t a5, int64_t a6, int64_t a7) { printf("output from __hook_fn: syscall number %ld\n", a1); return syscall(a1, a2, a3, a4, a5, a6, a7); }
ã¾ã¨ã
dlmopen ãå©ç¨ãã¦ãZpoline ã§ã®ããã¯é¢æ°å®è£ ãç°¡åã«ããæ¹æ³ã«ã¤ãã¦èª¬æãã¾ããã詳細ã«ã¤ãã¦ã¯ãGithub 上のリポジトリã«ãããµã³ãã«ããã°ã©ã ããåç §ãã ãããæ¯è¼çç°¡åã«è²ã ãªä»çµã¿ã¸çµã¿è¾¼ããããã«ãªã£ãã¨æãã¾ãã®ã§ããããããã°ãæ¯é使ã£ã¦ã¿ã¦ãã ããã