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

О проекте

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

MySQL

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

Хостинг

Другое








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

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

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

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

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

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

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

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

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

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

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

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






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





Первые шаги

Вернемся к программе stack:

>>perl -e 'system "./stack \x64\xf6\xff\xbf%.496x%n"'
buffer : [dця›000000000000000000000000000000000000000000000000
00000000000] (63)
i = 500 (bffff664)

Мы задали в качестве строки ввода:
  1. адрес переменной i;
  2. инструкцию форматирования (%.496x);
  3. вторую инструкцию форматирования (%n), которая произведет запись по данному адресу.
Чтобы определить адрес переменной i (здесь 0xbffff664), мы можем запустить программу дважды и соответственно поменять командную строку. Как вы заметили, i имеет новое значение :) Данная строка форматирования и организация стека делают вызов snprintf() подобным на:
snprintf(buffer,
         sizeof buffer,
         "\x64\xf6\xff\xbf%.496x%n",
         tmp,
         4 first bytes in buffer);

Первые четыре байта (содержащие адрес i) записываются в начало buffer. Формат %.496x позволяет нам избавится от переменной tmp, которая расположена в начале стека. Затем, когда доходит дело до инструкции %n, адрес, который она использует, - есть адрес переменной i, расположенный в начале buffer. Хотя требуемая точность равна 496, snprintf записывает максимум 60 байт (т.к. длина буфера - 64 и 4 байта уже записано). Значение 496 - произвольное, оно используется только чтобы изменить "счетчик байтов". Мы видели, что формат %n сохраняет количество байт, которое должно будет записано. Это значение равно 496, к которому мы добавляем 4 из-за 4 байт адреса i в начале buffer. Поэтому у нас получается 500 байт. Это значение будет записано в следующий адрес, расположенный в стеке, который является адресом i.

Мы можем пойти дальше в развитии данного примера. Чтобы изменить i, нам надо было знать ее адрес ... однако иногда программа сама предоставляет его:

/* swap.c */
#include <stdio.h>

main(int argc, char **argv) {

  int cpt1 = 0;
  int cpt2 = 0;
  int addr_cpt1 = &cpt1;
  int addr_cpt2 = &cpt2;

  printf(argv[1]);
  printf("\ncpt1 = %d\n", cpt1);
  printf("cpt2 = %d\n", cpt2);
}

Запуск этой программы показывает, что мы можем управлять стеком (почти) как мы хотим:

>>./swap AAAA
AAAA
cpt1 = 0
cpt2 = 0
>>./swap AAAA%1\$n
AAAA
cpt1 = 0
cpt2 = 4
>>./swap AAAA%2\$n
AAAA
cpt1 = 4
cpt2 = 0

Как вы можете видеть, в зависимости от аргумента, мы можем менять cpt1 или cpt2. Формату %n нужен адрес, вот почему мы не можем напрямую работать с переменными (например используя %3$n (cpt2) или %4$n (cpt1)), однако можем это делать через указатели. Последнее - "полуфабрикат" с огромными возможностями для модификации.

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



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





Copyright © 2005-2016 Project.Net.Ru