---[ Phrack Magazine Volume 8, Issue 52 January 26, 1998, article 18 of 20 -------------------------[ Weakening the Linux Kernel -------------------------[ Linux Kernel ¹«·ÂÈ­½Ã۱â --------[ plaguez --------[ ¹ø¿ª : redcloak --------[ ÃÖ±Ù ¼öÁ¤ : 2002³â 2¿ù 8ÀÏ ----[ ¸Ó¸®¸» ´ÙÀ½Àº Linux x86 2.0.x kernelÀ» ´ë»óÀ¸·Î ÇÑ´Ù. ÀÌÀü ¹öÁ¯¿¡¼­µµ Àû¿ë°¡´ÉÇÒ °Í °°À¸³ª, Å×½ºÆ®Çغ¸Áö´Â ¾Ê¾Ò´Ù. 2.1.x kernelÀº memory management ·çƾ¿¡ ÀÖ¾î ÁÖ¸ñÇÒ ¸¸ÇÑ ¸¹Àº º¯È­°¡ ¼Ò°³µÇ¾úÀ¸¹Ç·Î ¿©±â¿¡¼­´Â ´Ù·çÁö ¾Ê´Â´Ù. ¸¹Àº ¼¼·ÃµÈ ¾ÆÀ̵ð¾î¸¦ ÁØ Halflife¿Í Solar Designer¿¡°Ô °¨»çÇϸç, plaguez¿Í WSD°¡ À̸¦ ¼Ò°³ÇϰڴÙ. ----[ »ç¿ëÀÚ °ø°£ vs Ä¿³Î °ø°£ Linux´Â ¼ö¸¹Àº ¾ÆÅ°ÅØÃĸ¦ Á¦°øÇÏÁö¸¸, ÀÌ ¹®¼­ÀÇ ´ëºÎºÐÀÇ ÄÚµå¿Í ³íÀÇ´Â i386 version¿¡ ´ëÇÑ °ÍÀÌ´Ù. ¸Þ¸ð¸®´Â Ä¿³Î °ø°£°ú »ç¿ëÀÚ °ø°£, µÎ ºÎºÐÀ¸·Î ÀÌ·ç¾îÁø´Ù. Ä¿³Î °ø°£Àº GDT(Global Descriptor Table)¿¡¼­ Á¤ÀǵǸç, °¢ ÇÁ·Î¼¼½ºÀÇ ÁÖ¼Ò °ø°£(address space)À¸·Î ´ëÀÀµÈ´Ù. »ç¿ëÀÚ °ø°£Àº LDT(Local Descriptor Table)¿¡¼­ Á¤Àǵǰí, °¢ ÇÁ·Î¼¼½º¿¡ ´ëÇÑ local¿µ¿ªÀ» ³ªÅ¸³½´Ù. ÇÑ ÇÁ·Î±×·¥Àº ±×°ÍÀÌ »ç¿ëÀÚ °ø°£, Ä¿³Î °ø°£¿¡ ´ëÀÀÀÌ µÇ´õ¶óµµ »ç¿ëÀÚ °ø°£°ú Ä¿³Î °ø°£¿¡ µ¿½Ã¿¡ ÀÖÀ» ¼ö ¾øÀ¸¹Ç·Î Ä¿³Î ¸Þ¸ð¸®¿¡ Á÷Á¢ ¾µ ¼ö ¾ø´Ù. ¶ÇÇÑ ÀüÇüÀûÀ¸·Î Ä¿³Î¿¡¼­ »ç¿ëÀÚ °ø°£ÀÇ ¸Þ¸ð¸®·Î Á¢±ÙÇÒ ¼ö ¾øÁö¸¸, ÀÌ´Â Á¤¸» ½±°Ô ±Øº¹ÇÒ ¼ö ÀÖ´Ù. ¿ì¸®°¡ ½Ã½ºÅÛÄÝÀ» ¼öÇàÇÏ°Ô µÇ¸é, Ä¿³ÎÀÌ ÇÏ´Â ÀÏ °¡¿îµ¥ °¡Àå ¸ÕÀú ÇÏ´Â °ÍÀÌ DS(Data Segment register)¿Í ES(Extra data Segment register)¸¦ ¸Þ¸ð¸® ÂüÁ¶¸¦ ÇÒ ¼ö ÀÖµµ·Ï Ä¿³Î µ¥ÀÌÅÍ ¼¼±×¸ÕÆ®¸¦ °¡¸®Å°µµ·Ï ¼¼ÆÃÇÏ´Â °ÍÀÌ´Ù. ¸¸ÀÏ ¿ì¸®°¡ ½Ã½ºÅÛÄÝ¿¡¼­ Ä¿³Î ¸Þ¸ð¸®¸¦ »ç¿ëÇÏ±æ ¿øÇÑ´Ù¸é, FS(F data Segment)¸¦ ¸ÕÀú ½ºÅÿ¡ pushÇÑ ´ÙÀ½, FS°ªÀ» DS°ªÀ¸·Î ¼¼ÆÃÇØ¾ß¸¸ ÇÑ´Ù. ¹°·Ð À̰ÍÀ» Á¤È®È÷ Å×½ºÆ®Çغ¸Áö´Â ¾Ê¾ÒÀ¸¹Ç·Î, ¾ç³äÀ¸·Î ¸Àº¸±æ ¹Ù¶õ´Ù. :) ¿©±â Ä¿³Î ¸ðµå¿¡¼­ »ç¿ëÀÚ °ø°£ÀÇ ¸Þ¸ð¸®¿¡¼­ µ¥ÀÌÅÍ ¹ÙÀÌÆ®¸¦ Àаųª »ç¿ëÀÚ °ø°£ÀÇ ¸Þ¸ð¸®·Î ¾²±â À§ÇØ »ç¿ëÇÏ´Â ¸î °³ÀÇ À¯¿ëÇÑ ÇÔ¼ö°¡ ÀÖ´Ù. #include get_user(ptr) ÀÎÀÚ·Î ÁÖ¾îÁø byte, word, longÇüÀÇ µ¥ÀÌÅ͸¦ »ç¿ëÀÚ °ø°£ÀÇ ¸Þ¸ð¸®¿¡¼­ °¡Á®¿Â´Ù. À̰ÍÀº ¸ÅÅ©·ÎÀ̸ç, Àü¼ÛÇÒ ¹ÙÀÌÆ® ¼ö´Â ÀÎÀÚÀÇ Å¸ÀÔ¿¡ µû¶ó °áÁ¤µÈ´Ù. ¿ì¸®´Â Çüº¯È¯(typecast)À» ÀûÀýÇÏ°Ô »ç¿ëÇØ¾ß ÇÑ´Ù. put_user(ptr) get_user()¿Í °°À¸¸ç, µ¥ÀÌÅ͸¦ ÀÐ´Â°Ô ¾Æ´Ï¶ó »ç¿ëÀÚ °ø°£ÀÇ ¸Þ¸ð¸®¿¡ ¾´´Ù. memcpy_fromfs(void *to, const void *from,unsigned long n) »ç¿ëÀÚ °ø°£ÀÇ ¸Þ¸ð¸® *from°¡ °¡¸®Å°´Â °÷¿¡¼­ Ä¿³Î °ø°£ ¸Þ¸ð¸®ÀÇ *to°¡ °¡¸®Å°´Â °÷¿¡ n ¹ÙÀÌÆ®¸¦ º¹»çÇÑ´Ù. memcpy_tofs(void *to,const *from,unsigned long n) Ä¿³Î ¸Þ¸ð¸®³»¿¡ *fromÀÌ °¡¸®Å°´Â °÷¿¡¼­ »ç¿ëÀÚ °ø°£ ¸Þ¸ð¸®³»ÀÇ *to°¡ °¡¸®Å°´Â °÷À¸·Î n ¹ÙÀÌÆ®¸¦ º¹»çÇÑ´Ù. ----[ System calls ´ëºÎºÐÀÇ libc function callÀº »ç¿ëÀÚ ÇÁ·Î±×·¥ÀÌ È£ÃâÇÒ ¼ö ÀÖ´Â °¡Àå °£´ÜÇÑ Ä¿³Î ÇÔ¼öÀÎ ³»ºÎÀÇ ½Ã½ºÅÛÄÝ¿¡ ÀÇÁ¸ÇÑ´Ù. ÀÌ·¯ÇÑ ½Ã½ºÅÛÄÝÀº Ä¿³Î ÀÚü¿¡¼­ ±¸ÇöµÇ±âµµ Çϰí, Ä¿³Î ÄÚµå¿Í µ¿ÀûÀ¸·Î ¸µÅ©°¡´ÉÇÑ LKM(Loadable Kernel Module, µ¿ÀûÀ¸·Î ÀûÀç°¡´ÉÇÑ Ä¿³Î ¸ðµâ)ÇüÅ·Π±¸ÇöµÇ±âµµ ÇÑ´Ù. MS-DOS¿Í ´Ù¸¥ ¸¹Àº OSó·³, Linux ½Ã½ºÅÛÄÝÀº ÁÖ¾îÁø ¸¶½ºÅ·(¿ªÀÚÁÖ : EFlags ·¹Áö½ºÅÍÀÇ IF(Interrupt Flag)¸¦ 0À¸·Î ¼¼ÆÃÇÏ¿© ÀÎÅÍ·´Æ®¸¦ ±ÝÁö½Ãų ¼ö ÀÖ´Ù) °¡´ÉÇÑ ÀÎÅÍ·´Æ®¿Í ÇÔ²² È£ÃâµÇ´Â ¸ÖƼÇ÷º¼­(¿ªÀÚÁÖ : ½Ã½ºÅÛ ÄÝ Çڵ鷯¸¦ ÀǹÌ) ¸¦ ÅëÇØ¼­ ±¸ÇöµÈ´Ù. Linux¿¡¼­ ÀÌ ÀÎÅÍ·´Æ®°¡ int 0x80ÀÌ´Ù. 'int 0x80' ¾î¼Àºí¸®¾î ¸í·ÉÀÌ ½ÇÇàµÇ¸é, Á¦¾î´Â Ä¿³Î·Î ³Ñ°ÜÁö¸ç(º¸´Ù Á¤È®È÷ ¸»Çϸé, _system_call() ÇÔ¼ö·Î), ½ÇÁ¦ µð¸ÖƼÇ÷º½Ì(¿ªÀÚÁÖ : ½Ã½ºÅÛÄÝ Çڵ鷯¿¡¼­ ÇØ´çÇÏ´Â ½Ã½ºÅÛÄÝ ¼­ºñ½º ·çƾÀ¸·Î ¿¬°è) ÀÛ¾÷ÀÌ ÀÌ·ç¾îÁø´Ù. _system_call() ÇÔ¼ö´Â ´ÙÀ½°ú °°ÀÌ ÀÛµ¿ÇÑ´Ù: ¸ÕÀú, ¸ðµç ·¹Áö½ºÅÍ °ªÀ» ÀúÀåÇϰí, %eax ·¹Áö½ºÅÍÀÇ ³»¿ëÀ» ¸ðµç ½Ã½ºÅÛ Äݰú ¸Þ¸ð¸®»óÀÇ ÁÖ¼Ò¸¦ ¿­°ÅÇϰí ÀÖ´Â Àü¿ª ½Ã½ºÅÛÄÝ Å×À̺íÀÇ ¿£Æ®¸®¿Í ºñ±³ÇÑ´Ù. ÀÌ Å×À̺íÀº extern void *sys_call_table[] º¯¼ö¸¦ °¡Áö°í Á¢±ÙÇÒ ¼ö ÀÖ´Ù. ÀÌ Å×ÀÌºí¿¡¼­ ½Ã½ºÅÛÄÝ ¹øÈ£¿Í ¸Þ¸ð¸®ÁÖ¼Ò(¿ªÀÚÁÖ : ÇØ´ç ½Ã½ºÅÛÄÝ ¼­ºñ½º ·çƾÀÇ ¸Þ¸ð¸®»óÀÇ À§Ä¡)°¡ °¢ ½Ã½ºÅÛÄݰú ÀÏÄ¡ÇÑ´Ù. ½Ã½ºÅÛÄÝ ¹øÈ£´Â /usr/include/sys/syscall.h¿¡ 'SYS_½Ã½ºÅÛÄÝÀ̸§' ÇüÅ·ΠÁ¤ÀÇ µÇ¾î ÀÖ´Ù. ¸¸ÀÏ ¾î¶² ½Ã½ºÅÛÄÝÀÌ ±¸ÇöµÇ¾î ÀÖÁö ¾Ê´Ù¸é, sys_call_table³»¿¡ ºÎÇÕÇÏ´Â ¿£Æ®¸® °ªÀº 0À̸ç error°¡ ¸®ÅϵȴÙ. ±×·¸Áö ¾ÊÀ¸¸é, ½Ã½ºÅÛÄÝÀÌ Á¸ÀçÇÏ¸ç ºÎÇÕÇÏ´Â Å×ÀÌºí³»ÀÇ ¿£Æ® ¸®´Â ½Ã½ºÅÛÄÝ Äڵ尡 ÀÖ´Â ¸Þ¸ð¸®»óÀÇ ÁÖ¼Ò°¡ µÈ´Ù. ¿©±â À¯È¿ÇÏÁö ¾ÊÀº ½Ã½ºÅÛÄÝ ¿¹Á¦°¡ ÀÖ´Ù: [root@plaguez kernel]# cat no1.c #include #include #include extern void *sys_call_table[]; sc() { // ÇöÀç ½Ã½ºÅÛÄÝ ¹øÈ£ 165°¡ Á¸ÀçÇÏÁö ¾Ê´Â´Ù. // (¿ªÀÚÁÖ : sys/syscall.h, asm/unistd.h¿¡ º¸¸é ÇöÀç(linux 2.4.x) 165¹øÀº getresuid // ½Ã½ºÅÛÄÝ¿¡ ÇÒ´çµÇ¾î ÀÖ´Ù.) __asm__( "movl $165,%eax int $0x80"); } main() { errno = -sc(); perror("test of invalid syscall"); } [root@plaguez kernel]# gcc no1.c [root@plaguez kernel]# ./a.out test of invalid syscall: Function not implemented [root@plaguez kernel]# exit Á¤»óÀûÀÎ °æ¿ì¿¡, Á¦¾î´Â »ç¿ëÀÚ°¡ ¿äûÇÑ °ÍÀ» ¼öÇàÇÏ´Â ½ÇÁ¦ ½Ã½ºÅÛÄÝ·Î ¿Å°Ü°¬´Ù°¡ ¸®ÅÏ(¿ªÀÚÁÖ : ½Ã½ºÅÛÄÝ ¼­ºñ½º ·çƾÀ» ½ÇÇàÈÄ ½Ã½ºÅÛÄÝ Çڵ鷯·Î ¸®ÅÏ)ÇÏ°Ô µÈ´Ù. ±×·± ´ÙÀ½ _system_call()Àº ¿©·¯°¡Áö?¸¦ üũÇϱâ À§ÇØ _ret_from_sys_call() À» È£ÃâÇß´Ù°¡ ³¡À¸·Î »ç¿ëÀÚ °ø°£ÀÇ ¸Þ¸ð¸®·Î ¸®ÅÏÇÏ°Ô µÈ´Ù. ----[ libc wrappers ----[ libc Æ÷ÀåÇÔ¼ö int $0x80ÀÌ ½Ã½ºÅÛÄÝÀ» À§Çؼ­ Á÷Á¢ »ç¿ëµÇÁö´Â ¾Ê´Â´Ù; libc ÇÔ¼ö°¡ ÀÎÅÍ·´Æ® 0x80¿¡ ´ëÇÑ Æ÷ÀåÇÔ¼ö(wrapper)·Î »ç¿ëµÈ´Ù. libc´Â ½ÇÁ¦ Ä¿³Î ÇÔ¼ö¿¡ ´ëÇÑ »ç¿ëÀÚ °ø°£ÀÇ ÀÎÅÍÆäÀ̽ºÀÌ´Ù. libc´Â ÀϹÝÀûÀ¸·Î _syscallX() ¸ÅÅ©·Î(X´Â ÇØ´ç ½Ã½ºÅÛÄÝ¿¡ ´ëÇÑ ÆÄ¶ó¹ÌÅÍÀÇ °³¼ö)¸¦ »ç¿ëÇÏ´Â ½Ã½ºÅÛÄÝÀÇ Æ¯¼ºÀ» °®´Â´Ù. ¿¹¸¦ µé¾î, write(2)¿¡ ´ëÇÑ libc ¿£Æ®¸®´Â ½ÇÁ¦ write(2)ÀÇ ÇÁ·ÎÅäŸÀÔÀÌ ÆÄ¶ó¹ÌÅÍ 3°³¸¦ ¿ä±¸Çϱ⠶§¹®¿¡, _syscall3 ¸ÅÅ©·Î·Î ±¸ÇöµÈ´Ù. ÀÎÅÍ·´Æ® 0x80À» È£ÃâÇϱâ Àü¿¡, _syscallX ¸ÅÅ©·Î´Â ½ºÅÃÇÁ·¹ÀÓ°ú ÇØ´ç ½Ã½ºÅÛÄÝÀÌ ¿ä±¸ÇÏ´Â ÀÎÀÚ ¸®½ºÆ®¸¦ ¼¼ÆÃÇØ¾ß ÇÑ´Ù. °á±¹, _system_call()(int $0x80À¸·Î È£ÃâµÇ´Â)¿¡¼­ ¸®ÅϵǸé, _syscallX() ¸ÅÅ©·Î´Â %eax¿¡ ÀÖ´Â ¸®ÅϰªÀÌ À½¼öÀÎÁö È®ÀÎÇϰí errnoÀ» ÇØ´çÇÏ´Â °ªÀ¸·Î ¼¼ÆÃÇÏ°Ô µÈ´Ù. write(2)°¡ ¾î¶»°Ô Àü󸮵ǴÂÁö ´Ù¸¥ ¿¹Á¦¸¦ º¸ÀÚ. [root@plaguez kernel]# cat no2.c #include #include #include #include #include #include #include #include #include _syscall3(ssize_t,write,int,fd,const void *,buf,size_t,count); main() { char *t = "this is a test.\n"; write(0, t, strlen(t)); } [root@plaguez kernel]# gcc -E no2.c > no2.C [root@plaguez kernel]# indent no2.C -kr indent:no2.C:3304: Warning: old style assignment ambiguity in "=-". Assuming "= -" [root@plaguez kernel]# tail -n 50 no2.C #9 "no2.c" 2 ssize_t write(int fd, const void *buf, size_t count) { long __res; __asm__ __volatile("int $0x80":"=a"(__res):"0"(4), "b"((long) (fd)), "c"((long) (buf)), "d"((long) (count))); if (__res >= 0) return (ssize_t) __res; errno = -__res; return -1; }; main() { char *t = "this is a test.\n"; write(0, t, strlen(t)); } [root@plaguez kernel]# exit À§ÀÇ write() ÇÔ¼ö¿¡¼­ '4'°¡ /usr/include/sys/syscall.h(¿ªÀÚÁÖ : 2.4.x kernel¿¡¼­´Â /usr/include/asm/unistd.h¸¦ Âü°í)¿¡¼­ Á¤ÀÇµÈ SYS_write¿Í ÀÏÄ¡ÇÑ´Ù´Â °ÍÀ» ¾Ë ¼ö ÀÖ´Ù. ----[ ³ª¸¸ÀÇ ½Ã½ºÅÛÄÝ ¸¸µé±â ÀڽŸ¸ÀÇ ½Ã½ºÅÛÄÝÀ» ¸¸µå´Â µ¥¿¡´Â ¸î °¡Áö ¹æ¹ýÀÌ ÀÖ´Ù. ¿¹¸¦ µé¸é, Ä¿³Î ¼Ò½º¸¦ º¯°æÇÏ¿© ÀÚ½ÅÀÇ Äڵ带 ºÙÀÏ ¼öµµ ÀÖ´Ù. ÇÏÁö¸¸ Á»´õ ½¬¿î ¹æ¹ýÀº ÀûÀç°¡´ÉÇÑ Ä¿³Î ¸ðµâ(LKM)À» ¸¸µå´Â °ÍÀÌ´Ù. LKMÀº ÇÊ¿äÇÒ ¶§ Ä¿³Î¿¡ µ¿ÀûÀ¸·Î ¸µÅ©µÉ Äڵ带 Æ÷ÇÔÇϰí ÀÖ´Â ÆÄÀÏ °´Ã¼ ÀÌ»ó ¾Æ¹«°Íµµ ¾Æ´Ï´Ù. À̰ÍÀº ÀÛÀº Ä¿³ÎÀ» ¸¸µé±â À§ÇÔ¿¡ ÁÖ ¸ñÀûÀÌ ÀÖÀ¸¸ç, ÇÊ¿äÇÒ ¶§ insmod(1) ¸í·ÉÀ¸·Î ¿øÇÏ´Â µå¶óÀ̹ö¸¦ Ä¿³Î¿¡ ¿Ã¸± ¼ö ÀÖ´Ù. ¶ÇÇÑ Ä¿³Î ¼Ò½º Æ®¸®³»¿¡ Äڵ带 ½á³Ö´Â °Íº¸´Ù lkmÀ» ¸¸µå´Â °ÍÀÌ Á»´õ ½±´Ù. lkmÀ» °¡Áö°í, ½Ã½ºÅÛÄÝÀ» Ãß°¡Çϰųª º¯°æÇÏ´Â °ÍÀº ´ÙÀ½¿¡ º¸°ÔµÉ sys_call_table ¹è¿­À» º¯°æÇÏ´Â ¹®Á¦ÀÏ»ÓÀÌ´Ù. ----[ lkm ¸¸µé±â lkmÀº C·Î ½±°Ô ¸¸µé ¼ö ÀÖ´Ù. ¸î ÁÙÀÇ #define, ÄÚµåºÎºÐ, init_module()À̶ó°í ºÎ¸£´Â ÃʱâÈ­ ÇÔ¼ö¿Í cleanup_module()À̶ó°í ºÎ¸£´Â ¸ðµâÀ» ³»¸®´Â ÇÔ¼ö·Î ±¸¼ºµÈ´Ù. init_module()°ú cleanup_module() ÇÔ¼ö´Â ¸ðµâ ÀûÀç¿Í ¸ðµâ »èÁ¦¶ó°í ºÎ¸¦ °ÍÀÌ´Ù. ¶ÇÇÑ ¸ðµâÀº Ä¿³ÎÄÚµå À̸ç, ¸¸µé±â ½±´Ù°í ÇÒÁö¶óµµ ¾î¶² ÇÁ·Î±×·¡¹Ö ½Ç¼ö³ª ±²ÀåÈ÷ ½É°¢ÇÑ °á°ú¸¦ ÃÊ·¡ÇÒ ¼öµµ ÀÖ´Ù´Â °ÍÀ» ¸í½ÉÇϱ⠹ٶõ´Ù. ¿©±â ÀüÇüÀûÀÎ lkm ¼Ò½º ±¸Á¶°¡ ÀÖ´Ù: #define MODULE #define __KERNEL__ #include #ifdef MODULE #include #include #else #define MOD_INC_USE_COUNT #define MOD_DEC_USE_COUNT #endif #include #include #include #include #include #include #include #include #include #include #include #include #include int errno; char tmp[64]; /* for example, we may need to use ioctl */ _syscall3(int, ioctl, int, d, int, request, unsigned long, arg); int myfunction(int parm1,char *parm2) { int i,j,k; /* ... */ } int init_module(void) { /* ... */ printk("\nModule loaded.\n"); return 0; } void cleanup_module(void) { /* ... */ printk("\nModule unloaded.\n"); } #defines (#define MODULE, #define __KERNEL__)¿Í #includes (#include ...)´Â ²À ½á³Ö¾î¾ß ÇÑ´Ù. ¶ÇÇÑ lkmÀº Ä¿³Î ¸ðµå¿¡¼­ ½ÇÇàµÉ °ÍÀθ¸Å­ libc ÇÔ¼ö¸¦ »ç¿ëÇÒ ¼ö ¾ø´Ù. ÇÏÁö¸¸ ¾Õ¿¡¼­ ³íÀÇ µÈ _syscallX() ¸ÅÅ©·Î¸¦ ÀÌ¿ëÇÏ¿© ½Ã½ºÅÛÄÝÀ» »ç¿ëÇÒ ¼ö ÀÖ°í, ¶Ç´Â sys_call_table ¹è¿­¿¡ ¼­ ÇÔ¼ö¿¡ ´ëÇÑ Æ÷ÀÎÅ͸¦ »ç¿ëÇÔÀ¸·Î½á Á÷Á¢ ½Ã½ºÅÛÄÝÀ» È£ÃâÇÒ ¼öµµ ÀÖ´Ù. ÀÌ ¸ðµâÀ» 'gcc -c -O3 module.c'¿Í °°ÀÌ ÄÄÆÄÀÏÇϰí 'insmod module.o'·Î Ä¿³Î¿¡ »ðÀÔÇÒ ¼ö ÀÖ´Ù. (ÃÖÀûÈ­¸¦ ¹Ýµå½Ã ÇØ¾ßÇÑ´Ù). Á¦¸ñó·³ lkmÀº Ä¿³Î Àüü¸¦ ÄÄÆÄÀÏÇÏÁö ¾Ê°í Ä¿³Î Äڵ带 ¼öÁ¤Çϱâ À§ÇØ »ç¿ëµÉ ¼ö ÀÖ´Ù. ¿¹¸¦ µé¸é, write(2) ½Ã½ºÅÛ ÄÝÀ» ÁÖ¾îÁø ÆÄÀÏÀÇ ºÎºÐÀ» ¼û±âµµ·Ï ÆÐÄ¡ÇÒ ¼ö ÀÖ´Ù. ¶ÇÇÑ ¹éµµ¾î ¸¦ ½É¾î³õ±â¿¡ ÁÁÀº Àå¼ÒÀ̱⵵ ÇÏ´Ù: ¸¸ÀÏ ÀÚ½ÅÀÇ Ä¿³ÎÀ» ½Å·ÚÇÒ ¼ö ¾ø´Ù¸é ¹«½¼ ÀÏÀ» Çϰڴ °¡? :-P ----[ Ä¿³Î°ú ½Ã½ºÅÛ ÄÝ ¹éµµ¾î À̸¦ À§ÇÑ ÁÖ ¾ÆÀ̵ð¾î´Â ±²ÀåÈ÷ °£´ÜÇÏ´Ù. ¿ì¸®´Â º¸ÅëÀÇ ½Ã½ºÅÛÄÝÀ» ¿ì¸®°¡ ¿øÇÏ´Â ´ë·Î Ä¿³Î ÀÌ ¹ÝÀÀÇϵµ·Ï ¸¸µé lkm¾ÈÀÇ ¿ì¸® ÀÚ½ÅÀÇ ½Ã½ºÅÛÄÝ·Î ¸®´ÙÀÌ·ºÆ®ÇÒ °ÍÀÌ´Ù. ¿¹¸¦ µé¾î, ¿ì¸® ´Â IOCTL ½Ã½ºÅÛÄÝÀ» ÆÐÄ¡ÇÏ¿© PROMISC ºñÆ®¸¦ ¸¶½ºÅ·ÇÏ°í ½º´ÏÆÛ¸¦ ¼û±æ ¼ö ÀÖ´Ù. ÃæºÐÇÏ Áø ¾ÊÁö¸¸ È¿°úÀûÀÌ´Ù. ÁÖ¾îÁø ½Ã½ºÅÛÄÝÀ» º¯Á¶ÇÏ·Á¸é, lkm¾È¿¡ extern void *sys_call_table[] Á¤ÀǸ¦ Ãß°¡Çϰí, init_module() ÇÔ¼ö¸¦ sys_call_table¾ÈÀÇ ÇØ´ç ½Ã½ºÅÛÄÝ¿¡ ÀÏÄ¡ÇÏ´Â ¿£Æ®¸®¸¦ ½ÇÁ¦ ½Ã½ºÅÛÄÝ ¼­ºñ½º ·çƾÀÌ ¾Æ´Ñ ¿ì¸® ÀÚ½ÅÀÇ Äڵ带 °¡¸®Å°µµ·Ï º¯Á¶ÇÑ´Ù. ±×·¯¸é ¸ðµç »ç¿ëÀÚ ÇÁ·Î±×·¥ÀÌ ±×·¯ÇÑ ½Ã½ºÅÛÄÝ¿¡ ÀÇÁöÇϱ⠶§¹®¿¡, º¯Á¶µÈ ½Ã½ºÅÛÄÝÀ» »ç¿ëÇÏ´Â °æ¿ì ¿ì¸®°¡ ¿øÇÏ´Â ´ë·Î ÇൿÇϵµ·Ï ÇÒ ¼ö ÀÖ°í, ÀÌ·¸°Ô µÇ¸é ±× Àüü ½Ã½ºÅÛ¿¡ ´ëÇÑ Á¦¾î¸¦ °®°Ô µÇ´Â °ÍÀÌ´Ù. À̰ÍÀº ħÀÔÀÚ°¡ ½Ã½ºÅÛ¿¡ ħÀÔÇßÀ» ¶§, ±× ½Ã½ºÅÛ¿¡ ¸Ó¹«¸£´Â °ÍÀ» ¸·±â°¡ ¸Å¿ì ¾î·Á¿öÁø´Ù´Â °ÍÀ» ÀǹÌÇÑ´Ù. ¸·´Â´Ù´Â °ÍÀº ¿©ÀüÈ÷ º¸¾ÈÀ» À§ÇØ ÃÖ°íÀÇ ¹æ¹ýÀ̸ç, ±â¹ÐÀ» ´Ù·ç´Â ½Ã½ºÅÛÀÇ °æ¿ì¿¡´Â ¸®´ª½º Ä¿³ÎÀ» °ß°íÇÏ°Ô ¸¸µå´Â °ÍÀÌ ÇÊ¿äÇÏ´Ù. ----[ ¸î °¡Áö ÇÁ·Î±×·¡¹Ö Æ®¸¯ - lkm³»¿¡¼­ ½Ã½ºÅÛÄÝÀ» È£ÃâÇÑ´Ù´Â °ÍÀº »ç¿ëÀÚ °ø°£¿¡¼­ ÀÎÀÚ¸¦ ÇØ´ç ½Ã½ºÅÛÄÝ¿¡ ³Ñ±â´Â °Í ¸¸Å­À̳ª ¸Å¿ì ½±´Ù. ¸¸ÀÏ Ä¿³Î °ø°£À¸·Î ÀÎÀÚ¸¦ ³Ñ±æ Çʿ䰡 ÀÖ´Â °æ¿ì¿¡, FS ·¹Áö½ºÅ͸¦ º¯°æÇÏ¿´´ÂÁö È®ÀÎÇØ¾ß ÇÑ´Ù. ±×·¸Áö ¾ÊÀ¸¸é ¸ðµç °ÍÀÌ Ç¥¸éÀ¸·Î µå·¯³¯ °ÍÀÌ´Ù. À̰ÍÀº ÇÔ¼ö¿¡ ´ëÇÑ Æ÷ÀÎÅÍ º¯¼ö¿¡ ½Ã½ºÅÛÄÝ ÇÔ¼ö¸¦ °¡¸®Å°µµ·Ï ÀúÀåÇϰí, ±× º¯¼ö¸¦ »ç¿ëÇÏ´Â ¹®Á¦ÀÏ»ÓÀÌ´Ù. ¿¹¸¦ µé¸é: #define MODULE #define __KERNEL__ #include #ifdef MODULE #include #include #else #define MOD_INC_USE_COUNT #define MOD_DEC_USE_COUNT #endif #include #include #include #include #include #include #include #include int errno; /* pointer to the old setreuid system call */ int (*o_setreuid) (uid_t, uid_t); /* the system calls vectors table */ extern void *sys_call_table[]; int n_setreuid(uid_t ruid, uid_t euid) { printk("uid %i trying to seteuid to euid=%i", current->uid, euid); return (*o_setreuid) (ruid, euid); } int init_module(void) { o_setreuid = sys_call_table[SYS_setreuid]; sys_call_table[SYS_setreuid] = (void *) n_setreuid; printk("swatch loaded.\n"); return 0; } void cleanup_module(void) { sys_call_table[SYS_setreuid] = o_setreuid; printk("\swatch unloaded.\n"); } - ¸ðµâÀº ¿©·¯ ¹æ¹ýÀ¸·Î ¼û±æ ¼ö ÀÖ´Ù. Runar JensenÀÌ ¹ö±×Æ®·¢¿¡¼­ º¸ÀÎ °Íó·³, ´Ù¸¥ ÇÁ·Î±×·¥ÀÌ /proc/modulesÀ» Àбâ Àü¿¡ ¸ô·¡ /proc/modules¿¡¼­ ¾ø¾Ù ¼ö ÀÖ´Ù. ±×·¯³ª ÀÌ ¹æ¹ýÀº Áõ¸íµÈ °Í¸¸Å­, ±¸ÇöÇÏ´Â °ÍÀÌ ´Ù¼Ò ¾î·Á¿ì¸ç 'dd if=/proc/modules bs=1'À¸·Î ¸ðµâÀ» º¼ ¼ö ÀÖ´Ù. ´Ù¸¥ ¹æ¹ýÀÌ ÇÊ¿äÇѵ¥, Solar designer (´Ù¸¥ ¹«¸í¾¾µéµµ :)) °¡ ÇѰ¡Áö ¹æ¹ýÀ» Á¦¾ÈÇß´Ù. ¸ðµâÁ¤º¸(module info) ¸®½ºÆ®´Â Ä¿³Î·Î Àü´ÞµÇÁö(exported) ¾Ê±â ¶§¹®¿¡ ¿ì¸® ¸ðµâÀÇ init_module()¸¦ È£ÃâÇÏ´Â sys_init_module()¿¡¼­ »ç¿ëÇÏ´Â ¸ðµâÁ¤º¸ ±¸Á¶Ã¼¸¦ Á¦¿ÜÇϰí´Â À̰Ϳ¡ Á÷Á¢ Á¢±ÙÇÒ ¼ö ÀÖ´Â ¹æ¹ýÀÌ ¾ø´Ù. gcc´Â init_module()¿¡ µé¾î°¡ ±â Àü¿¡ ·¹Áö½ºÅ͸¦ °Çµå¸®Áö ¾Ê±â ¶§¹®¿¡ struct module *mp¿¡¼­ »ç¿ëµÇ´Â ·¹Áö½ºÅ͸¦ ¹Ì¸® °¡Á®¿Í¼­ ÀÌ ±¸Á¶Ã¼(ȯÇü ¸®½ºÆ®) ¸â¹öÀÇ ÁÖ¼Ò¸¦ ¾òÀ» ¼ö ÀÖ´Ù. ±×·¡¼­ ¿ì¸®ÀÇ init_module() ÇÔ¼ö´Â óÀ½¿¡ ±×·¯ÇÑ °ÍµéÀ» Æ÷ÇÔÇÒ °ÍÀÌ´Ù: int init_module() { register struct module *mp asm("%ebx"); // or whatever register it is in *(char*)mp->name=0; mp->size=0; mp->ref=0; ... } Ä¿³ÎÀº Ä¿³Î ¸ðµâÀ» ¸ðµâÀ̸§°ú ÇÔ²² ÂüÁ¶°è¼öµµ °°ÀÌ º¸¿©Áֱ⠶§¹®¿¡, ¿ì¸®ÀÇ ¸ðµâÀº /proc/modules¿¡¼­ º¼ ¼ö ¾ø´Ù. ----[ ½ÇÀü itf.c¸¦ º¸ÀÚ. ÀÌ ÇÁ·Î±×·¥Àº ½Ã½ºÅÛÄÝ ¸®´ÙÀÌ·º¼ÇÀ» »ç¿ëÇÏ¿© Ä¿³Î ¹éµµ¾î ±â¼úÀ» º¸¿©ÁÖ±â À§ÇÔÀÌ´Ù. ÀÏ´Ü ¼³Ä¡µÇ¸é, À̸¦ ã¾Æ³»±â°¡ ¸Å¿ì ¾î·Æ´Ù. ´ÙÀ½Àº ÀÌ ÇÁ·Î±×·¥ÀÇ Æ¯Â¡ÀÌ´Ù: - stealth ±â´É: insmod¸¦ ÅëÇØ ÀÏ´Ü ¸ðµâÀ» ¿Ã¸®¸é, itf´Â ÀÚ½ÅÀÌ /proc/modules³ª ksymsÀÇ °á°ú¿¡ ³ªÅ¸³ªÁö ¾Êµµ·Ï struct module *mp¿Í get_kernel_symbols(2)¸¦ º¯°æÇÏ°Ô µÈ´Ù. ±×¸®°í ¶ÇÇÑ ¸ðµâÀ» ³»¸± ¼ö ¾ø´Ù. - sniffer ¼û±â±â: PROMISC Ç÷¡±×¸¦ ¼û±â±â À§ÇØ ioctl(2)¸¦ ¹éµµ¾î·Î »ç¿ëÇÒ °ÍÀÌ´Ù. itf´Â PROMISC Ç÷¡±×°¡ ¹Ù²î¸é À̸¦ Àâ¾Æ À̸¦ º¸ÀÌ°Ô ÇÒ °ÍÀ̱⠶§¹®¿¡(±×·¸Áö ¾ÊÀ¸¸é 'ifconfig eth0 +promisc'¸¦ ÇØ¾ß ÇÒ °ÍÀ̸ç, ±× ¸ðµâÀ» º¸°Ô µÉ °ÍÀÌ´Ù.) itf.o¸¦ ¸ðµâ·Î ¿Ã¸®±â Àü¿¡ ½º´ÏÆÛ¸¦ ¸ÕÀú µÎ¾î¾ß ÇÒ °ÍÀÌ´Ù. - ÆÄÀÏ ¼û±â±â: itf´Â ¶Ç getdents(2) ½Ã½ºÅÛÄÝÀ» ÆÐÄ¡ÇÏ¿©, ÆÄÀÏ¸í¿¡¼­ ƯÁ¤ ´Ü¾î¸¦ Æ÷ÇÔÇϰí ÀÖ´Â ÆÄÀÏÀ» ¼û±ä´Ù. - ÇÁ·Î¼¼½º ¼û±â±â: À§¿¡¼­ ¼³¸íÇÑ °°Àº ±â¼úÀ» »ç¿ëÇÏ¿© argv ¿£Æ®¸®¸¦ »ç¿ëÇϰí ÀÖ´Â /proc/P? µð·ºÅ丮¸¦ ¼û±æ °ÍÀÌ´Ù. magic nameÀ» °¡Áø ¾î¶² ÇÁ·Î¼¼½º¶óµµ proc ÆÄÀϽýºÅÛ Æ®¸®¿¡¼­ ¼û°ÜÁú °ÍÀÌ´Ù. - execve ¸®´ÙÀÌ·º¼Ç: phrack 51È£¿¡¼­ ³íÀÇµÈ HalflifeÀÇ »ý°¢À» ±¸ÇöÇÑ °ÍÀÌ´Ù. ¾î¶² ÇÁ·Î±× ·¥(¿¹¸¦ µé¸é /bin/login)ÀÌ ½ÇÇàµÈ´Ù¸é, itf´Â ÀÌ ÇÁ·Î±×·¥ ´ë½Å ´Ù¸¥ ÇÁ·Î±×·¥À» ½ÇÇà½Ãų °ÍÀÌ ´Ù. ÀÌ´Â Linux memory managementÀÇ Á¦ÇÑÀ» ±Øº¹Çϱâ À§ÇÑ Æ®¸¯À» »ç¿ëÇÑ´Ù: È£ÃâÇÏ´Â ÇÁ·Î±×·¥ÀÇ data segment Å©±â¸¦ ´Ã¸®±â À§ÇØ brk(2)¸¦ »ç¿ëÇÏ¿© Ä¿³Î¸ðµå¿¡ ÀÖ´Â µ¿¾È¿¡ (´ëºÎºÐÀÇ ½Ã½ºÅÛÄÝÀº Ä¿³Î ¸Þ¸ð¸®°¡ ¾Æ´Ñ, »ç¿ëÀÚ ¸Þ¸ð¸®¿¡¼­ ÀÎÀÚ¸¦ ±â´Ù¸°´Ù´Â °ÍÀ» ±â¾ïÇØ ¶ó) »ç¿ëÀÚ ¸Þ¸ð¸®¸¦ ÇÒ´çÇÒ ¼ö ÀÖ°Ô ÇÑ´Ù. -socket recvfrom() ¹éµµ¾î: ÁÖ¾îÁø Å©±â¿Í ¹®ÀÚ¿­À» °®´Â ÆÐŶÀÌ µµÂøÇϸé, non-interactive ÇÁ·Î±×·¥ÀÌ ½ÇÇàµÈ´Ù. ´ëÇ¥ÀûÀÎ °ÍÀÌ ´Ù¸¥ Æ÷Æ®¸¦ ¿­°Å³ª ½©¸í·ÉÀ» ±â´Ù¸®´Â ½© ½ºÅ©¸³Æ® (magic nameÀ» »ç¿ëÇÏ¿© ¼û°ÜÁú)¸¦ »ç¿ëÇÏ´Â °ÍÀÌ´Ù. - setuid() trojan: HalflifeÀÇ °Í°ú ºñ½ÁÇÏ´Ù. uid·Î magic number¸¦ °¡Áö°í setuid() ½Ã½ºÅÛÄÝÀ» ÇÏ°Ô µÇ¸é, È£ÃâÇÏ´Â ÇÁ·Î¼¼½º´Â uid = euid = gid = 0À» °¡Áö°Ô µÈ´Ù. * ¸¶Áö¸· ¼Ò½º ÄÚµå ºÎºÐÀº ¾Ç¿ëÀÇ ¼ÒÁö°¡ Àֱ⠶§¹®¿¡ ÀÓÀÇ·Î »èÁ¦ÇÏ¿´½À´Ï´Ù. ÀÌ ºÎºÐ¿¡ ´ëÇÑ ÀÚ·á´Â ¿ø¹® µîÀ» Á÷Á¢ °Ë»öÇÏ¿© Âü°íÇÏ½Ã±æ ¹Ù¶ó°Ú½À´Ï´Ù.