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

  • 0x210 Что такое программирование

  • 0x240 Основные понятия программирования

  • Операция Символ Пример

  • Полная запись Сокращенная запись Описание

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


    Скачать 2.5 Mb.
    НазваниеКнига дает полное представление о программировании, машин ной архитектуре, сетевых соединениях и хакерских приемах
    АнкорХакинг
    Дата16.06.2022
    Размер2.5 Mb.
    Формат файлаpdf
    Имя файлаХакинг__искусство_эксплоита_2_е_469663841.pdf
    ТипКнига
    #595131
    страница3 из 51
    1   2   3   4   5   6   7   8   9   ...   51
    18
    0x200 Программирование
    Новая функция обратит на себя внимание рынка, а оптимизацию по скорости и памяти большинство пользователей не заметят. Когда все определяется в конечном счете деньгами, тратить время на искусные хаки для оптимизации просто нет смысла.
    По настоящему оценить элегантность программы могут только хаке- ры – компьютерные энтузиасты, конечная цель которых не прибыль, а желание выжать из своего старенького Commodore 64 все, на что он способен; создатели эксплойтов, которые пишут изумительные кро- хотные фрагменты кода, способные проскользнуть сквозь узкую щел- ку в системе защиты; все, кого увлекает поиск лучшего из возмож- ных решений. Это те, кто действительно любит программировать, по- настоящему ценя красоту элегантного кода и остроумие изобретатель- ного хака. Чтобы применять эксплойты, необходимо освоить програм- мирование, поэтому последнее послужит для нас естественной отправ- ной точкой.
    0x210 Что такое программирование?
    Программирование – вполне естественное и интуитивное понятие.
    Программа представляет собой лишь ряд предложений, написанных на особом языке. С программами мы встречаемся повсеместно, и даже технофобы ежедневно имеют с ними дело. Схемы проезда, кулинар- ные рецепты, футбольные матчи и ДНК – все это программы. Типич- ная «программа» для шофера может выглядеть так:
    Начать движение по Главной улице в восточном направлении. Двигаться по
    Главной улице до церкви на правой стороне. Если движение перекрыто из-за ремонта, повернуть направо на 15-ю улицу, затем повернуть налево на Сосновую улицу, затем повернуть направо на 16-ю улицу. В противном случае продолжить движение до 16-й улицы и повернуть направо. Продолжать движение по 16-й улице, затем повернуть налево на Дорогу к цели. Проехать по Дороге к цели
    5 км, нужный дом будет по правой стороне. Адрес: Дорога к цели, дом 743.
    Каждый, кто понимает человеческий язык, способен понять и выпол- нить эти указания. Правда, они лаконичны, но каждая инструкция по- нятна, по крайней мере тем, кто умеет читать.
    Но компьютер не понимает обычную речь, а только машинный язык.
    Чтобы заставить компьютер что-то сделать, надо написать ему ин- струкции на его языке. Однако машинный язык выглядит непонятно, и с ним трудно работать. Он состоит только из битов и байтов и специ- фичен для каждой машинной архитектуры. Чтобы написать програм- му на машинном языке, скажем, для процессора Intel x86, нужно знать числовое значение, соответствующее каждой его команде, осо- бенности ее выполнения и немыслимое количество прочих деталей, от- носящихся к программированию низкого уровня. Такое программиро- вание – долгий, трудоемкий и уж явно не интуитивный процесс.

    0x220 Псевдокод
    19
    Преодолеть сложность написания программ на машинном языке позво- ляет транслятор. Одним из видов трансляторов в машинный язык яв- ляется ассемблер – программа, которая транслирует текст на языке ас- семблера в код, понятный машине. Язык ассемблера не так загадочен, как машинный язык, поскольку различные команды и переменные в нем записываются при помощи имен, а не чисел. Однако и язык ас- семблера не очень-то нагляден. Названия команд понятны лишь посвя- щенным, а язык остается специфичным для данной архитектуры. Это означает, что так же как машинный язык для процессоров Intel x86 от- личается от машинного языка для процессоров Sparc, так и язык ассем- блера для x86 отличается от языка ассемблера для Sparc. Любая про- грамма, написанная на языке ассемблера для процессора одной архи- тектуры, не сможет работать на процессоре другой архитектуры. Если программа написана на языке ассемблера x86, для выполнения в архи- тектуре Sparc ее придется переписать. Кроме того, чтобы писать эффек- тивные программы на языке ассемблера, необходимо знать многие под- робности архитектуры этого процессора.
    Эти проблемы становятся менее существенными, если применяется дру- гой вид транслятора, называемый компилятором. Компилятор преоб- разует язык высокого уровня в машинный язык. Языки высокого уров- ня гораздо нагляднее языков ассемблера и могут преобразовываться в машинные языки процессоров различных архитектур. Это означа- ет, что на языке высокого уровня программу можно написать один раз, а компилятор преобразует этот программный код в машинный язык конкретной архитектуры. Примеры языков высокого уровня – C, C++ и FORTRAN. Написанная на языке высокого уровня программа зна- чительно легче читается и больше похожа на естественный язык, чем язык ассемблера или машинный язык, но тем не менее должна придер- живаться очень жестких правил написания команд, иначе компилятор не сможет их понять.
    0x220 Псевдокод
    У программистов есть еще один вид языка программирования, назы- ваемый псевдокодом. Псевдокод – это естественный язык, по структуре похожий на язык высокого уровня. Его не понимают компиляторы, ас- семблеры и какие-либо компьютеры, но он помогает программистам ор- ганизовать инструкции. Псевдокод не имеет четкого определения. Раз- ные люди пишут на псевдокоде немного по-разному. В некотором роде, это туманное отсутствующее звено между естественными языками, на- пример английским, и языками программирования высокого уровня вроде C. Псевдокод помогает понять общие стандартные принципы про- граммирования.

    20
    0x200 Программирование
    0x230 Управляющие структуры
    Без управляющих структур программа представляла бы собой просто ряд последовательно выполняемых инструкций, или команд. Для про- стейших программ это приемлемо, но большинство программ, в частно- сти наш пример схемы проезда, оказываются сложнее. В них есть такие инструкции, как «если движение перекрыто из-за ремонта» и «в про- тивном случае». Эти инструкции называют управляющими структу-
    рами: они изменяют порядок выполнения программы с простого после- довательного на более сложный и полезный.
    0x231 If-then-else
    В нашем примере движения по городу Главная дорога может оказать- ся закрытой на ремонт. Такую ситуацию нужно обработать с помощью специальных инструкций. В противном случае выполняется первона- чальный набор инструкций. Учесть в программе такие особые случаи позволяет одна из наиболее естественных управляющих структур if- then-else
    (если-то-иначе). Ее общий вид:
    If (условие) then
    {
    Набор инструкций, выполняемых при соблюдении условия;
    }
    Else
    {
    Набор инструкций, выполняемых при несоблюдении условия;
    }
    В этой книге используется псевдокод, похожий на C, поэтому каж- дая инструкция оканчивается точкой с запятой, а наборы инструкций определяются с помощью фигурных скобок и отступов. Если приведен- ную выше схему проезда преобразовать в псевдокод, получится при- мерно следующее:
    Двигаться по Главной улице;
    If (движение перекрыто)
    {
    Повернуть направо на 15-ю улицу;
    Повернуть налево на Сосновую улицу;
    Повернуть направо на 16-ю улицу;
    }
    Else
    {
    Повернуть направо на 16-ю улицу;
    }
    Каждая инструкция занимает отдельную строку, а наборы инструкций, выполняющихся при определенном условии, объединяются фигур- ными скобками и для большей наглядности размещаются с отступом.

    0x230 Управляющие структуры
    21
    В C и многих других языках программирования ключевое слово then подразумевается по умолчанию, поэтому в приведенном псевдокоде оно опущено.
    Конечно, есть много языков, синтаксис которых требует слова then, на- пример BASIC, Fortran и даже Pascal. Такие синтаксические различия между языками очень поверхностны, базовая структура остается той же. Понимающий основные концепции этих языков программист до- статочно легко освоит синтаксические различия между ними.
    Далее в этой книге используется язык C, поэтому и псевдокод здесь имеет аналогичный синтаксис, хотя, вообще говоря, видов псевдокода много.
    Другое стандартное правило синтаксиса C состоит в том, что если набор инструкций в фигурных скобках состоит всего из одной инструкции, фигурные скобки можно опустить. Для наглядности кода полезно пи- сать эти инструкции с отступом, но синтаксически это необязательно.
    Приведенную выше схему проезда можно переписать так:
    Двигаться по Главной улице;
    If (движение перекрыто)
    {
    Повернуть направо на 15-ю улицу;
    Повернуть налево на Сосновую улицу;
    Повернуть направо на 16-ю улицу;
    }
    Else
    Повернуть направо на 16-ю улицу;
    Это правило действует для всех управляющих структур, встречающих- ся в книге, и оно само может быть записано с помощью псевдокода.
    If (набор инструкций состоит всего из одной команды)
    Использовать фигурные скобки, служащие для объединения инструкций, необязательно;
    Else
    {
    Использование фигурных скобок обязательно;
    Поскольку необходим логический способ объединения инструкций;
    }
    Даже само описание синтаксиса можно рассматривать как простую программу. Существуют разновидности конструкции if-then-else, на- пример операторы select/case, но логический принцип сохраняется: если случится это, то надо действовать так, иначе следует выполнять другие действия (которые могут включать новые конструкции if-then).

    22
    0x200 Программирование
    0x232 Циклы while/until
    Другое элементарное понятие программирования – конструкция while
    (пока), разновидность цикла. Часто программисту требуется выпол- нить некоторую группу инструкций несколько раз. Подобную задачу программа решает с помощью цикла, но ей необходим набор условий, по которым она определит, что цикл нужно завершить, чтобы не выпол- нять его бесконечно. Цикл while указывает на то, что заданную груп- пу инструкций нужно выполнять, пока выполняется заданное условие.
    Вот пример простой программы для голодной мыши:
    while (голодна)
    {
    ищи что-то съедобное;
    съешь то, что нашла;
    }
    Набор из двух инструкций, следующий за оператором while, будет по- вторно выполняться, пока мышь все еще голодна. Каждый раз мышь может найти разное количество еды – от крошки хлеба до целой бухан- ки. Поэтому то, сколько раз будет выполнен набор инструкций в этом операторе while, зависит от того, сколько пищи найдет мышь.
    Другой вариант цикла – оператор until (пока не), имеющийся, напри- мер в языке программирования Perl (в C этот синтаксис не применя- ется). Цикл until – это тот же while, в котором условие имеет обратное значение. Для той же мыши программа с циклом until будет выглядеть так:
    until (наелась)
    {
    ищи что-то съедобное;
    съешь то, что нашла;
    }
    Естественно, любой оператор вроде until можно превратить в цикл while
    . Выше в схеме проезда была инструкция Двигаться по Главной улице до церкви на правой стороне
    . Ее можно заменить стандартным циклом while
    , изменив условие на противоположное.
    while (справа нет церкви)
    Двигаться по Главной улице;
    0x233 Циклы for
    Еще один вариант цикла – цикл for. Он удобен в случае, когда програм- мисту нужно, чтобы цикл выполнился заданное число раз. В виде цик- ла for можно записать указание проехать по Дороге к цели 5 км: for (5 раз)
    Проехать 1 км;

    0x240 Основные понятия программирования
    23
    В действительности цикл for – тот же while со счетчиком. Эту же ин- струкцию можно записать так:
    Установить счетчик в 0;
    while (счетчик меньше 5)
    {
    Проехать 1 км;
    Увеличить счетчик на 1;
    }
    Синтаксис цикла for на псевдокоде C еще нагляднее:
    for (i=0; i<5; i++)
    Проехать 1 км;
    В данном случае имя счетчика i, а оператор for разбит на три части, раз- деленные точкой с запятой. В первой части объявляется счетчик, и его значение устанавливается равным 0. Вторая часть – это как цикл while со счетчиком: выполнять цикл, пока счетчик соответствует этому усло- вию. Завершающая третья часть описывает действия, совершаемые со счетчиком при каждом проходе цикла. В данном случае i++ кратко со- общает, что к счетчику с именем i нужно добавить 1.
    С использованием всех управляющих конструкций схему проезда из начала главы 0х210 можно записать в виде псевдокода:
    Начать движение по Главной улице в восточном направлении;
    while (справа нет церкви)
    Двигаться по Главной улице;
    if (движение перекрыто)
    {
    Повернуть направо на 15-ю улицу;
    Повернуть налево на Сосновую улицу;
    Повернуть направо на 16-ю улицу;
    }
    else
    Повернуть направо на 16-ю улицу;
    Повернуть налево на Дорогу к цели;
    for (i=0; i<5; i++)
    Проехать 1 км;
    Остановиться у дома 743 по Дороге к цели;
    0x240 Основные понятия программирования
    В следующих разделах мы познакомимся с другими общими поняти- ями программирования. Эти понятия используются во многих язы- ках программирования с некоторыми синтаксическими различиями.
    По ходу представления этих понятий я буду иллюстрировать их приме- рами псевдокода с C-образным синтаксисом. К концу псевдокод станет очень похож на C.

    24
    0x200 Программирование
    0x241 Переменные
    Счетчик, используемый в цикле for, фактически является переменной.
    Переменную можно представить как некоторый объект, содержащий данные, которые могут изменяться, – отсюда и название. Бывают так- же переменные, которые не меняются, поэтому их назвали константа-
    ми. Если вернуться к примеру с ездой, то скорость машины – перемен- ная, а ее цвет – константа. В псевдокоде переменные абстрактны, но в C
    (и многих других языках), прежде чем использовать переменную, нуж- но объявить ее, присвоив ей определенный тип. Это связано с тем, что программа на C в конечном счете компилируется в выполняемую про- грамму. Подобно тому как в кулинарном рецепте сначала перечисля- ются все необходимые ингредиенты, объявления переменных позво- ляют выполнить некоторые приготовления перед тем, как приступить к основной программе. Все переменные будут храниться где-то в памя- ти, и их объявление дает компилятору возможность более эффективно распределить эту память. Хотя в конечном счете как бы вы ни объяви- ли переменную, это всего лишь участок памяти.
    В языке C переменной присваивается тип, описывающий информацию, которую должна хранить эта переменная. Самые распространенные типы: int (целые числа), float (десятичные числа с плавающей точкой
    1
    ) и char (символьные значения из одного символа). Переменные описыва- ются просто – с помощью ключевого слова, после которого идет список переменных, например:
    int a, b;
    float k;
    char z;
    Переменные a и b теперь определены как целые, k может принимать значения в виде чисел с плавающей точкой (например 3,14), а z содер- жит символьное значение, например A или w. Переменным можно при- сваивать значения во время объявления или в любой последующий мо- мент с помощью оператора =.
    int a = 13, b;
    float k;
    char z = ‘A’;
    k = 3.14;
    z = ‘w’;
    b = a + 5;
    После выполнения этих инструкций переменные будут содержать сле- дующие значения: a – число 13, k – число 3,14, z – букву w, а b – чис- ло 18, поскольку 13 + 5 = 18. Переменные просто позволяют запоминать
    1
    В России целую и дробную части числа принято разделять запятой, поэто- му применяется термин «плавающая запятая». – Прим. ред.

    0x240 Основные понятия программирования
    25
    значения; однако в C вы сначала обязаны объявить тип каждой пере- менной.
    0x242 Арифметические операторы
    Выражение b = a + 7 – пример простейшего арифметического операто- ра. Приведем символы, используемые в C для разных арифметических операций.
    Первые четыре операции имеют знакомый вид. Деление по модулю (це- лочисленное деление) может показаться новинкой, но на самом деле это всего лишь остаток от деления. Если a равно 13, то поделив 13 на 5, по- лучим 2 и 3 в остатке, откуда следует, что a % 5 = 3. Кроме того, посколь- ку переменные a и b – целые, оператор b = a / 5 записывает в b значе- ние 2, поскольку это целая часть результата. Чтобы получить более кор- ректный результат 2,6, нужно использовать переменные с плавающей точкой.
    Операция
    Символ
    Пример
    Сложение
    +
    b = a + 5
    Вычитание
    - b = a - 5
    Умножение
    *
    b = a * 5
    Деление
    /
    b = a / 5
    Деление по модулю
    %
    b = a % 5
    Чтобы заставить программу применять эти понятия, нужно говорить на понятном ей языке. В языке C есть и несколько способов сокращен- ной записи этих арифметических операций. Об одной из них, исполь- зуемой преимущественно в циклах, уже говорилось.
    Полная запись
    Сокращенная
    запись
    Описание
    i = i + 1
    i++ или ++i
    Прибавить 1 к переменной i = i – 1
    i-- или --i
    Вычесть 1 из переменной
    Эти сокращенные выражения можно объединить с другими арифмети- ческими операциями в более сложное выражение. Тут-то и выясняется разница между i++ и ++i. Первое выражение означает, что нужно уве- личить значение i на 1 после того, как будет выполнена арифметиче- ская операция, в второе предписывает увеличить i на 1 перед выполне- нием арифметической операции. Поясним это на следующем примере.

    26
    0x200 Программирование int a, b;
    a = 5;
    b = a++ * 6;
    После выполнения этих инструкций переменная b будет содержать зна- чение 30, а переменная а – значение 6, потому что сокращенная запись b = a++ * 6;
    равносильна следующим инструкциям:
    b = a * 6;
    a = a + 1;
    Однако при использовании команды b = ++a * 6; порядок сложения с a меняется, что равносильно следующим инструкциям:
    a = a + 1;
    b = a * 6;
    Поскольку порядок действий изменился, b теперь будет содержать 36, но a по-прежнему будет хранить 6.
    Нередко в программе требуется изменить переменную прямо на месте.
    Например, нужно прибавить к переменной какое-то значение, ска- жем 12, и записать результат в ту же переменную (например, i = i + 12).
    Для этой популярной операции есть специальная сокращенная запись.
    Полная запись
    Сокращенная запись
    Описание
    i = i + 12
    i+=12
    Прибавить к переменной некоторое значение i = i - 12
    i-=12
    Вычесть из переменной некоторое значение i = i * 12
    i*=12
    Умножить переменную на некоторое значение i = i / 12
    i/=12
    Разделить переменную на некоторое значение
    1   2   3   4   5   6   7   8   9   ...   51


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