Как решить проблему переполнения буфера с ограниченным набором строк и хешированием?

#c #scanf #sha1 #buffer-overflow

#c #scanf #sha1 #переполнение буфера

Вопрос:

ПРЕДВАРИТЕЛЬНО: Здесь есть только один похожий вопрос с другим алгоритмом хеширования и измененными размерами массива, но это не ответило на некоторые вопросы в моей голове, и сообщение от 2016. Проблема заключается в выполнении атаки переполнения буфера на программу, которая получает входные данные в виде пароля, хэширует его (SHA1) и сравнивает с ним правильный хэш. (Scanf ограничен)

То, что я уже знаю:

-Нулевой байт (x00) принимается scanf.

-Если я ввожу 20 символов для ввода, нулевой ограничитель перезаписывает первое правильное значение хэша.

-Если я загружаю входные данные из 37 символов (ограничение scanf), то мы перезаписываем первые 17 байт правильного хэша нашим собственным, а 18-й — нулевым ограничителем.

Я попытался написать скрипт грубой силы на python, чтобы найти такой хэш, который соответствовал бы последним 3 байтам, но чего я не понимаю, так это того, что 18-й байт из 20 байт является нулевым ограничителем в нашем правильном хэше. Как это сравнить? Я пытался сделать так, но не сработало = «00a450» в качестве последнего 3-байтового представления в строке. Ниже приведен код для программы на C и моего скрипта на Python.

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/sha.h>

int
main(void) {
    FILE *file;
    unsigned char flag[128];
    unsigned char correct_hash[20] = {
        0x4a, 0xc9, 0xb0, 0x57, 0xf8, 0x02, 0x12, 0x60, 0x6c, 0xea,
        0xab, 0xf3, 0xc6, 0x50, 0x5d, 0xaf, 0xed, 0x40, 0xa4, 0x50
    };
    unsigned char password[20];

    printf("Insert your password: ");
    scanf("7s", password);
    SHA1(password, strlen((char *)password), password);
    if(memcmp(password, correct_hash, 20) == 0) {
        printf("CORRECT PASSWORD!n");
        file = fopen("/flag", "r");
        if(file != NULL) {
            fscanf(file, "%s", flag);
            fclose(file);
            printf("Flag: %sn", flag);
        } else {
            printf("Error while opening the flag filen");
        }
    } else {
        printf("WRONG PASSWORD!n");
    }
    fflush(stdout);

    return 0;
}
  
 import hashlib
from itertools import *

st = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
hash_ending = "00a450"
found = False
for i in range(2,3):
    perms = list(map("".join, permutations(st,i)))
    for permutation in perms:
       full_hash =  hashlib.sha1(permutation.encode()).hexdigest()
       print("Testing = "   full_hash)
       if(full_hash[-6:] == hash_ending):
           found = True
           print("Full Hash = "   full_hash )
           print("Password = "   permutation)
           break
    if(found == True):
        break

  

Мне трудно понять байт NUL и переопределенный байт в качестве завершителя строки в правильном хэше и его значение при сравнении.

Комментарии:

1. Вы видели memcmp ?

2. Да, но для чего это полезно в данном случае? Он по-прежнему сравнивает 20 байт из password и correct_hash.

3. Он сравнивает с того места, где вы укажете ему начать, для любой длины, которую вы ему задаете.

4. Значит, это намеренно, что password длина всего 20 символов, но scanf формат, с помощью которого он читается, явно принимает до 37 байт (плюс ограничитель)? Я полагаю, вы намеренно разрабатываете некорректную программу, чтобы изучить, как ее можно атаковать?

5. @JohnBollinger ну, это назначение CTF. Итак, цель этого — получить флаг. Я просто не понимаю, как нулевой ограничитель представляется как и в хэше.