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

  • 0x763 Справочная хеш-таблица

  • 0x764 Матрица вероятностей паролей

  • Обычный текст Хеш test jeHEA

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


    Скачать 2.5 Mb.
    НазваниеКнига дает полное представление о программировании, машин ной архитектуре, сетевых соединениях и хакерских приемах
    АнкорХакинг
    Дата16.06.2022
    Размер2.5 Mb.
    Формат файлаpdf
    Имя файлаХакинг__искусство_эксплоита_2_е_469663841.pdf
    ТипКнига
    #595131
    страница47 из 51
    1   ...   43   44   45   46   47   48   49   50   51

    469
    -format:NAME force ciphertext format NAME (DES/BSDI/MD5/BF/AFS/LM)
    -savemem:LEVEL enable memory saving, at LEVEL 1..3
    reader@hacking:

    /booksrc $ sudo tail -3 /etc/shadow matrix:$1$zCcRXVsm$GdpHxqC9epMrdQcayUx0//:13763:0:99999:7:::
    jose:$1$pRS4.I8m$Zy5of8AtD800SeMgm.2Yg.:13786:0:99999:7:::
    reader:U6aMy0wojraho:13764:0:99999:7:::
    reader@hacking:/booksrc $ sudo john /etc/shadow
    Loaded 2 passwords with 2 different salts (FreeBSD MD5 [32/32])
    guesses: 0 time: 0:00:00:01 0% (2) c/s: 5522 trying: koko guesses: 0 time: 0:00:00:03 6% (2) c/s: 5489 trying: exports guesses: 0 time: 0:00:00:05 10% (2) c/s: 5561 trying: catcat guesses: 0 time: 0:00:00:09 20% (2) c/s: 5514 trying: dilbert!
    guesses: 0 time: 0:00:00:10 22% (2) c/s: 5513 trying: redrum3
    testing7 (jose)
    guesses: 1 time: 0:00:00:14 44% (2) c/s: 5539 trying: KnightKnight guesses: 1 time: 0:00:00:17 59% (2) c/s: 5572 trying: Gofish!
    Session aborted
    Этот листинг показывает, что у пользователя jose пароль testing7.
    0x763 Справочная хеш-таблица
    Еще одна интересная идея для взлома паролей заключается в создании гигантской справочной таблицы хешей. Если заранее вычислить хеш- значения для всех возможных паролей и поместить их в какую-нибудь структуру данных, позволяющую вести поиск, то любой пароль можно будет взломать в течение того времени, которое требуется для выпол- нения поиска. В случае бинарного поиска оно составит около O(log
    2
    N), где N – число различных элементов. Для восьмисимвольных паролей
    N равно 95 8
    , что приводит к оценке O(8 log
    2 95) – достаточно быстро.
    Однако справочная таблица такого размера заняла бы порядка сотни тысяч терабайт памяти. Кроме того, в алгоритме хеширования паро- лей была учтена возможность такой атаки, и для противодействия ей введена привязка (salt). Поскольку пароли будут давать разные значе- ния хеша в зависимости от привязки, для каждого значения salt при- дется построить отдельную справочную таблицу. В основанной на DES функции crypt() есть 4096 возможных значений salt, в результате чего таблица хешей даже для коротких четырехсимвольных паролей не- реализуема. Для одной справочной таблицы хешей четырехсимволь- ных паролей при фиксированной привязке требуется около гигабайта памяти, но из-за salt у каждого пароля оказывается 4096 возможных значений хеша, а потому требуется 4096 таблиц. В результате объем необходимой памяти возрастает до 4,6 терабайт, что делает такую ата- ку малопривлекательной.

    470
    0x700 Криптология
    0x764 Матрица вероятностей паролей
    При любых вычислениях мы сталкиваемся с компромиссом между вы- числительной мощностью и объемом памяти. Он проявляется в эле- ментарных задачах вычислительной техники и в повседневной жизни.
    В файлах MP3 применяется сжатие, что позволяет записать высокока- чественный звук в относительно небольшом объеме памяти, но это до- стигается ценой роста необходимых вычислительных ресурсов. В кар- манных калькуляторах этот компромисс «развернут» в обратном на- правлении: функции вроде синуса и косинуса хранятся в виде таблиц, что позволяет избежать интенсивных вычислений.
    Этот компромисс действует и в криптографии. В атаках, основанных на компромиссе между временем и памятью, вероятно, наиболее эф- фективны методы Хеллмана, но здесь приведен другой код, который проще понять. Общий принцип в любом случае тот же: попытаться найти баланс между вычислительной мощностью и объемом памяти, чтобы достаточно быстро выполнить полный перебор ключей, обхо- дясь приемлемым объемом памяти. К сожалению, проблема увеличе- ния объема памяти из-за salt все равно сохраняется. Поскольку раз- ных значений salt для паролей, обрабатываемых функцией crypt(), всего 4096, надо постараться уменьшить объем необходимой в этом ме- тоде памяти настолько, чтобы и с увеличением в 4096 раз он оставался в разумных пределах.
    В данном методе применяется своего рода сжатие с потерей информа- ции. Вместо точного поиска по таблице, для каждого значения хеша возвращается несколько тысяч возможных открытых паролей. Эти значения можно быстро проверить и найти настоящий пароль, при этом сжатие с потерей информации позволяет существенно сократить необходимый размер памяти. В приведенном ниже коде участвует ключевое пространство всех четырехсимвольных паролей (с фиксиро- ванным salt). Необходимый объем памяти уменьшен на 88% по срав- нению со справочной таблицей хешей (для одного salt), а простран- ство ключей, проверяемое полным перебором, уменьшено примерно в 1018 раз. Если выполнять 10 000 проверок в секунду, то этим мето- дом можно взломать пароль из четырех символов (для фиксированного значения salt) меньше чем за 8 секунд, что существенно меньше, чем
    2 часа, необходимые для полного перебора всех ключей.
    В этом методе строится трехмерная двоичная матрица, связываю- щая части значений хешей с частями значений открытого текста. По оси X – обычный текст, разделенный на две пары: первые два симво- ла и вторые два символа. Все их возможные значения перенумерованы в виде двоичного вектора длиной 95 2
    , или 9025 бит (около 1129 байт).
    По оси Y – шифрованный текст, разбитый на четыре трехсимвольных участка. Они также нумеруются по столбцам, но из третьего симво- ла берутся только четыре бита. Таким образом, столбцов будет 64 2
    ×
    4,

    0x760 Взлом паролей
    471
    или 16 384. Ось Z нужна, чтобы хранить восемь двумерных матриц, по четыре для каждой пары обычного текста.
    Основная идея состоит в том, что обычный текст разбивается на две пары символов, которые пронумерованы. Для каждого обычного тек- ста с помощью хеш-функции вычисляется шифрованный текст, по ко- торому определяется соответствующий столбец матрицы. После это- го устанавливается бит на пересечении со строкой матрицы, соответ- ствующей обычному тексту. Поскольку значения шифрованного тек- ста урезаются, неизбежно возникнут коллизии.
    Обычный текст
    Хеш
    test jeHEAX1m66RV.
    !J)h jeHEA38vqlkkQ
    ".F+
    jeHEA1Tbde5FE
    "8,J
    jeHEAnX8kQK3I
    В данном случае в столбце HEA должны быть установлены биты, со- ответствующие парам обычного текста te, !J, “. и “8, когда эти пары обычного текста/хеша будут добавляться в матрицу.
    Пусть матрица заполнена. Тогда, если нам требуется взломать хеш jeHEA38vqlkkQ
    , смотрим в столбец HEA матрицы и получаем из него зна- чения te, !J, “. и “8 для первых двух символов открытого текста. Для первых двух символов таких матриц четыре – для подстрок шифрован- ного текста из символов со второго по четвертый, с четвертого по ше- стой, с шестого по восьмой и с восьмого по десятый – и в каждой из матриц свой вектор возможных значений первых двух символов от- крытого текста. Извлекаем эти векторы и применяем к ним поразряд- ное И. В результате установленными останутся только биты, соответ- ствующие парам обычного текста, входящим в число возможных для каждой подстроки шифрованного текста. Аналогично обращаемся с четырьмя матрицами, соответствующими последним двум символам обычного текста.
    Размер матриц был установлен на основании принципа Дирихле. Этот простой принцип утверждает, что если k + 1 объектов разложить по k ящикам, то хотя бы в одном из ящиков окажется не менее двух объ- ектов. Поэтому лучшие результаты будут получены, если в каждом векторе окажется чуть меньше половины единиц. Поскольку в матри- цах будет размещено 95 4
    , или 81 450 625, элементов, для достижения
    50-процентного насыщения требуется примерно вдвое больше ящиков.
    Так как каждый вектор имеет длину 9025, столбцов должно быть при- мерно (95 4
    × 2) / 9025, то есть примерно 18 000. Если использовать для столбцов трехсимвольные подстроки шифрованного текста, то первые два символа и четыре бита третьего символа дадут 64 2
    × 4, или около

    472
    0x700 Криптология
    16 000 столбцов, (символы шифрованного текста могут принимать
    64 различных значения). Это довольно близко к требуемому, потому что, если бит добавляется дважды, перекрытие игнорируется. На практике каждый вектор оказывается заполненным единицами примерно на 42%.
    Для каждого шифрованного текста выбираются четыре вектора, и ве- роятность того, что в заданной позиции значение 1 окажется во всех четырех векторах, равна примерно 0,42 4
    , или 3,11%. Это означает, что
    9025 возможных комбинаций первых двух символов сокращаются на
    97% – до 280 вариантов. То же справедливо и для последних двух сим- волов, и в итоге получается около 280 2
    , или 78 400, вариантов обычно- го текста. Если осуществлять 10 000 проверок в секунду, это сокращен- ное ключевое пространство будет проверено меньше чем за 8 секунд.
    Конечно, есть и недостатки. Во-первых, изначальное создание матри- цы требует не меньше времени, чем занял бы простой полный перебор, хотя это единовременные затраты. Кроме того, если учитывать значе- ния salt, то такая атака делается невозможной, несмотря на достигну- тое сокращение объема необходимой памяти.
    Следующие две распечатки демонстрируют код, который строит ма- трицу вероятностей паролей (Password Probability Matrix, PPM) и взламывает пароли с ее помощью. Первый листинг содержит код, ге- нерирующий матрицу для взлома всех четырехсимвольных паролей со значением salt, равным je. Код из второго листинга осуществляет фак- тический взлом паролей.
    ppm_gen.c
    /*********************************************************\
    * Матрица вероятностей паролей * Файл: ppm_gen.c *
    ***********************************************************
    * *
    * Автор: Jon Erickson *
    * Организация: Phiral Research Laboratories *
    * *
    * Это программа-генератор для проверки идеи МВП. *
    * Она создает файл 4char.ppm с данными по всем допустимым *
    * 4-символьным паролям с привязкой ‘je’. С помощью этого *
    * файла и соответствующей программы ppm_crack.c *
    * можно быстро вскрывать пароли из этого пространства. *
    * *
    \*********************************************************/
    #define _XOPEN_SOURCE
    #include
    #include
    #include
    #define HEIGHT 16384

    0x760 Взлом паролей
    473
    #define WIDTH 1129
    #define DEPTH 8
    #define SIZE HEIGHT * WIDTH * DEPTH
    /* Отобразить 1 байт хеша в порядковое число. */
    int enum_hashbyte(char a) {
    int i, j;
    i = (int)a;
    if((i >= 46) && (i <= 57))
    j = i - 46;
    else if ((i >= 65) && (i <= 90))
    j = i - 53;
    else if ((i >= 97) && (i <= 122))
    j = i - 59;
    return j;
    }
    /* Отобразить 3 байта хеша в порядковое число. */
    int enum_hashtriplet(char a, char b, char c) {
    return (((enum_hashbyte(c)%4)*4096)+(enum_hashbyte(a)*64)+enum_
    hashbyte(b));
    }
    /* Вывести сообщение и завершить работу. */
    void barf(char *message, char *extra) {
    printf(message, extra);
    exit(1);
    }
    /* Создать файл 4–char.ppm всех 4-символьных паролей (с привязкой je). */
    int main() {
    char plain[5];
    char *code, *data;
    int i, j, k, l;
    unsigned int charval, val;
    FILE *handle;
    if (!(handle = fopen(“4char.ppm”, “w”)))
    barf(“Error: Couldn’t open file ‘4char.ppm’ for writing.\n”, NULL);
    data = (char *) malloc(SIZE);
    if (!(data))
    barf(“Error: Couldn’t allocate memory.\n”, NULL);
    for(i=32; i<127; i++) {
    for(j=32; j<127; j++) {
    printf(“Adding %c%c** to 4char.ppm..\n”, i, j);
    for(k=32; k<127; k++) {
    for(l=32; l<127; l++) {
    plain[0] = (char)i; // Построить все plain[1] = (char)j; // возможные 4-байтные plain[2] = (char)k; // пароли.

    474
    0x700 Криптология plain[3] = (char)l;
    plain[4] = ‘\0’;
    code = crypt((const char *)plain, (const char *)”je”);
    // Вычислить хеш.
    /* Сохранить статистические данные
    /* о соответствиях без потерь.
    */
    val = enum_hashtriplet(code[2], code[3], code[4]);
    // Сохранить сведения о байтах 2-4.
    charval = (i-32)*95 + (j-32);
    // Первые 2 байта обычного текста data[(val*WIDTH)+(charval/8)] |= (1<<(charval%8));
    val += (HEIGHT * 4);
    charval = (k-32)*95 + (l-32); // Последние 2 байта
    // обычного текста data[(val*WIDTH)+(charval/8)] |= (1<<(charval%8));
    val = HEIGHT + enum_hashtriplet(code[4], code[5], code[6]);
    // Байты 4-6
    charval = (i-32)*95 + (j-32); // Первые 2 байта
    // обычного текста data[(val*WIDTH)+(charval/8)] |= (1<<(charval%8));
    val += (HEIGHT * 4);
    charval = (k-32)*95 + (l-32); // Последние 2 байта
    // обычного текста data[(val*WIDTH)+(charval/8)] |= (1<<(charval%8));
    val = (2 * HEIGHT) + enum_hashtriplet(code[6], code[7], code[8]); // Байты 6-8
    charval = (i-32)*95 + (j-32); // Первые 2 байта
    // обычного текста data[(val*WIDTH)+(charval/8)] |= (1<<(charval%8));
    val += (HEIGHT * 4);
    charval = (k-32)*95 + (l-32); // Последние 2 байта
    // обычного текста data[(val*WIDTH)+(charval/8)] |= (1<<(charval%8));
    val = (3 * HEIGHT) + enum_hashtriplet(code[8], code[9], code[10]); // Байты 8-10
    charval = (i-32)*95 + (j-32); // Первые 2 байта
    // обычного текста data[(val*WIDTH)+(charval/8)] |= (1<<(charval%8));
    val += (HEIGHT * 4);
    charval = (k-32)*95 + (l-32); // Последние 2 байта
    // обычного текста data[(val*WIDTH)+(charval/8)] |= (1<<(charval%8));
    }
    }
    }

    0x760 Взлом паролей
    475
    }
    printf(“finished.. saving..\n”);
    fwrite(data, SIZE, 1, handle);
    free(data);
    fclose(handle);
    }
    Первый фрагмент кода (ppm_gen.c) может сгенерировать матрицу для взлома четырехсимвольных паролей, как показано ниже. Опция -O3 компилятора GCC указывает на необходимость компиляции с оптими- зацией по скорости.
    reader@hacking:/booksrc $ gcc -O3 -o ppm_gen ppm_gen.c -lcrypt reader@hacking:/booksrc $ ./ppm_gen
    Adding ** to 4char.ppm..
    Adding !** to 4char.ppm..
    Adding “** to 4char.ppm..
    .:[ вывод сокращен ]:.
    Adding |** to 4char.ppm..
    Adding }** to 4char.ppm..
    Adding ** to 4char.ppm..
    finished.. saving..
    @hacking: $ ls -lh 4char.ppm
    -rw-r--r-- 1 142M 2007-09-30 13:56 4char.ppm reader@hacking:/booksrc $
    Файл 4char.ppm размером 142 Мбайт содержит неточные связи между обычным текстом и хешем для всех четырехсимвольных паролей. Эти данные можно использовать в другой программе, чтобы быстро взла- мывать четырехсимвольные пароли, не поддающиеся атаке со слова- рем.
    ppm_crack.c
    /*********************************************************\
    * Матрица вероятностей паролей * Файл: ppm_crack.c *
    ***********************************************************
    * *
    * Автор: Jon Erickson *
    * Организация: Phiral Research Laboratories *
    * *
    * Это программа-взломщик для проверки идеи МВП. *
    * Она использует готовый файл 4char.ppm данных по всем *
    * допустимым 4-символьным паролям с привязкой ‘je’. Такой *
    * файл можно создать с помощью программы ppm_gen.c. *
    * *
    \*********************************************************/
    #define _XOPEN_SOURCE
    #include

    476
    0x700 Криптология
    #include
    #include
    #define HEIGHT 16384
    #define WIDTH 1129
    #define DEPTH 8
    #define SIZE HEIGHT * WIDTH * DEPTH
    #define DCM HEIGHT * WIDTH
    /* Отобразить 1 байт хеша в порядковое число. */
    int enum_hashbyte(char a) {
    int i, j;
    i = (int)a;
    if((i >= 46) && (i <= 57))
    j = i - 46;
    else if ((i >= 65) && (i <= 90))
    j = i - 53;
    else if ((i >= 97) && (i <= 122))
    j = i - 59;
    return j;
    }
    /* Отобразить 3 байта хеша в порядковое число. */
    int enum_hashtriplet(char a, char b, char c) {
    return (((enum_hashbyte(c)%4)*4096)+(enum_hashbyte(a)*64)+ enum_hashbyte(b));
    }
    /* Объединить два вектора. */
    void merge(char *vector1, char *vector2) {
    int i;
    for(i=0; i < WIDTH; i++)
    vector1[i] &= vector2[i];
    }
    /* Возвращает разряд вектора по заданному индексу*/
    int get_vector_bit(char *vector, int index) {
    return ((vector[(index/8)]&(1<<(index%8)))>>(index%8));
    }
    /* Подсчитывает количество пар (обычный текст) в заданном векторе */
    int count_vector_bits(char *vector) {
    int i, count=0;
    for(i=0; i < 9025; i++)
    count += get_vector_bit(vector, i);
    return count;
    }
    /* Выводит пары (обычный текст), соответствующие всем установленным битам вектора. */
    void print_vector(char *vector) {

    0x760 Взлом паролей
    477
    int i, a, b, val;
    for(i=0; i < 9025; i++) {
    if(get_vector_bit(vector, i) == 1) { // Если бит установлен,
    a = i / 95; // вычислить b = i - (a * 95); // пару printf(“%c%c “,a+32, b+32); // и напечатать ее.
    }
    }
    printf(“\n”);
    }
    /* Вывести сообщение и завершить работу. */
    void barf(char *message, char *extra) {
    printf(message, extra);
    exit(1);
    }
    /* Взлом 4-символьного пароля с помощью готового файла 4char.ppm. */
    int main(int argc, char *argv[]) {
    char *pass, plain[5];
    unsigned char bin_vector1[WIDTH], bin_vector2[WIDTH], temp_vector[WIDTH];
    char prob_vector1[2][9025];
    char prob_vector2[2][9025];
    int a, b, i, j, len, pv1_len=0, pv2_len=0;
    FILE *fd;
    if(argc < 1)
    barf(“Usage: %s
    (will use the file 4char.ppm)\n”, argv[0]);
    if(!(fd = fopen(“4char.ppm”, “r”)))
    barf(“Fatal: Couldn’t open PPM file for reading.\n”, NULL);
    pass = argv[1]; // Первый аргумент - хеш пароля printf(“Filtering possible plaintext bytes for the first two characters:\n”);
    fseek(fd,(DCM*0)+enum_hashtriplet(pass[2], pass[3], pass[4])*WIDTH,
    SEEK_SET);
    fread(bin_vector1, WIDTH, 1, fd); // Прочитать вектор,
    // связывающий байты 2-4 хеша.
    len = count_vector_bits(bin_vector1);
    printf(“only 1 vector of 4:\t%d plaintext pairs, with %0.2f%% saturation\n”, len, len*100.0/9025.0);
    fseek(fd,(DCM*1)+enum_hashtriplet(pass[4], pass[5], pass[6])*WIDTH,
    SEEK_SET);
    fread(temp_vector, WIDTH, 1, fd); // Прочитать вектор,
    // связывающий байты 4-6 хеша.

    478
    0x700 Криптология merge(bin_vector1, temp_vector); // Объединить его с первым вектором.
    len = count_vector_bits(bin_vector1);
    printf(“vectors 1 AND 2 merged:\t%d plaintext pairs, with %0.2f%% saturation\n”, len, len*100.0/9025.0);
    fseek(fd,(DCM*2)+enum_hashtriplet(pass[6], pass[7], pass[8])*WIDTH,
    SEEK_SET);
    fread(temp_vector, WIDTH, 1, fd); // Прочитать вектор,
    // связывающий байты 6-8 хеша.
    merge(bin_vector1, temp_vector); // Объединить его
    // с первыми двумя векторами.
    len = count_vector_bits(bin_vector1);
    printf(“first 3 vectors merged:\t%d plaintext pairs, with %0.2f%% saturation\n”, len, len*100.0/9025.0);
    fseek(fd,(DCM*3)+enum_hashtriplet(pass[8], pass[9],pass[10])*WIDTH,
    SEEK_SET);
    fread(temp_vector, WIDTH, 1, fd); // Прочитать вектор,
    // связывающий байты 8-10 хеша.
    merge(bin_vector1, temp_vector); // Объединить его с остальными векторами.
    len = count_vector_bits(bin_vector1);
    printf(“all 4 vectors merged:\t%d plaintext pairs, with %0.2f%% saturation\n”, len, len*100.0/9025.0);
    printf(“Possible plaintext pairs for the first two bytes:\n”);
    print_vector(bin_vector1);
    printf(“\nFiltering possible plaintext bytes for the last two characters:\n”);
    fseek(fd,(DCM*4)+enum_hashtriplet(pass[2], pass[3], pass[4])*WIDTH,
    SEEK_SET);
    fread(bin_vector2, WIDTH, 1, fd); // Прочитать вектор,
    // связывающий байты 2-4 хеша.
    len = count_vector_bits(bin_vector2);
    printf(“only 1 vector of 4:\t%d plaintext pairs, with %0.2f%% saturation\n”, len, len*100.0/9025.0);
    fseek(fd,(DCM*5)+enum_hashtriplet(pass[4], pass[5], pass[6])*WIDTH,
    SEEK_SET);
    fread(temp_vector, WIDTH, 1, fd); // Прочитать вектор,
    // связывающий байты 4-6 хеша.
    merge(bin_vector2, temp_vector); // Объединить его с первым вектором.
    len = count_vector_bits(bin_vector2);
    printf(“vectors 1 AND 2 merged:\t%d plaintext pairs, with %0.2f%% saturation\n”, len, len*100.0/9025.0);

    0x760 Взлом паролей
    1   ...   43   44   45   46   47   48   49   50   51


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