#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. Итак, цель этого — получить флаг. Я просто не понимаю, как нулевой ограничитель представляется как и в хэше.