Главная > Программирование, системное > Безопасность: Инспектор файлов на Delphi.

Безопасность: Инспектор файлов на Delphi.

В этой статье мы немного углубимся в дебри компьютерной безопасности. И на повестке дня повис вопрос, как вы уже догадались - "Инспектор файлов". Что это и для чего он нужен я расскажу по мере чтения вами этой статьи, но замечу сразу, что испокон веков компьютерной эры, с тех самых времен когда операционная система содрогнулась от вирусной эпидемии, на стражу ваших и системных файлов встал гроза контроля и целостности - "Инспектор". Прошу прощение за эпическое отступление ;).

Так вот, помимо установленных антивирусов и прочих специальных программ, которые выполняют кучу всяких полезностей, порой даже абсолютно не нужных в данный момент и только лишь отнимают наше драгоценное время. А мы то знаем, что время - деньги!

Что же меня побудило написать статью на эту тема? Во-первых я считаю, и вам даю на заметку, что пользоваться готовым софтом это утеха юзеров и прочих бездельников. Каждый уважающий себя программист должен иметь в своем арсенале собственноручно написанный инструментарий отвечающий его задачам и требованием, и не одной команды лишней. Да и кроме того вы сами знаете что делает ваша программа, и в любой момент можете вспороть ее и что то подправить, добавить или удалить, в отличие от чужих прграммулек. Во-вторых, зная, а кто не знал запомните, что ни один антивирус не может вас защитить на 100% от свеженькой вредоносной информационной субстанции, то бишь вирус и прочая нечисть, так как антивирусная индустрия всегда позади на шаг впереди идущих создателей этой дряни. Поэтому, вашу безопасность можете обеспечить только вы сами и одним из средств обеспечения в этом деле является "Инспектор файлов", который непоколебимо несет свою службу на полях информационного пространства и "своих" знает в "лицо".

После не долгих эпических отступлений, вы уж простите меня, без лишних слов приступаем к реализации нашего стражника "Инспектора". В первую очередь нам необходимо поставить задачу. Ей будет:

  • реализовать поиск файлов,
  • проверку файлов на наличие их в банке данных, по соответствующим признакам (путь к файлу, дата создания, изменения и контрольная сумма),
  • добавление в новых кандидатов на прописку в банк данных,
  • реализация интерфейса связывающего предыдущие описанные задачи и действия пользователя.

В целом, получается вот такое тех. задание. А теперь от слов к делу. Для начала определимся с дизайном формы. Здесь я полагаюсь на ваш вкус, но потребуется нам две кнопки и поле вывода информации (Memo или ListBox). Одну из кнопок определим под выбор папки - "Обзор", и для нее напишем следующий код:


procedure TForm1.Button1Click(Sender: TObject);
begin
Path := GetPath('Выберите папку');
if Path <> ''
then Label4.Caption := Path;
end;

А теперь опишем используемую функцию GetPath():


function GetPath(mes: string):string;
var
Root: string; // корневой каталог
pwRoot : PWideChar;
Dir: string;
begin
Root := ''; // по умолчанию корневой каталог - рабочий стол
GetMem(pwRoot, (Length(Root)+1) * 2);
pwRoot := StringToWideChar(Root,pwRoot,MAX_PATH*2);
if SelectDirectory(mes, pwRoot, Dir)
then
if length(Dir) = 2 // пользователь выбрал корневой каталог
then GetPath := Dir+'\'
else GetPath := Dir
else
GetPath := '';
end;

Итак, процедуру выбора каталога для проверки реализовано. Теперь приступим к реализации проверки файлов. Но сначала для второй кнопки опишем следующий код:


procedure TForm1.Button2Click(Sender: TObject);
begin
Form1.ListBox1.Items.Add(TimeToStr(Time)+' :> Сканирование началось.');
ListFiles.Clear;
FindF(Path);
Scan_File;
Form1.ListBox1.Items.Add('===================================================');
Form1.ListBox1.Items.Add(TimeToStr(Time)+' :> Сканирование завершено.');
end;

А теперь последовательно опишем используемые функции и первой будет процедура FindF(). Эта процедура осуществляет рекурсивный поиск файлов относительно выбранного корневого каталога, и добавляет их в список для проверки. Смотрим листинг:


procedure FindF(path_f:string);
begin
//Инициируем поиск
if(FindFirst(path_f+'\*.*',faAnyFile,SearchRec) = 0) then
begin
repeat
if not((SearchRec.name = '.')or(SearchRec.name = '..')) then
begin
if SearchRec.Attr <> faDirectory then
begin
ListFiles.Add(path_f+'\'+SearchRec.Name); //если файл, добавляем в список
Inc(Count_file);
end
else
FindF(path_f+'\'+SearchRec.Name); //если папка, запускаем рекурсию

end;
until (FindNext(SearchRec)<>0);
FindClose(SearchRec);
end;
end;

Далее рассмотрим процедуру Scan_File(). Ее задача проверить каждый найденный файл на наличие в своей базе данных, сверить контрольную сумму, дату создания и дату последнего изменения файла. В случае если будут обнаружены какие-либо не соответствия, немедля бьет тревогу. Смотрим:


procedure Scan_File;
var
crc32T,dataCT,dataMT:Cardinal;
i:integer;
f: THandle;
SearchF:TWIN32FindData;
temp:boolean;
begin
i:=0;
//проверка на первый запуск, а точнее база была только что создана или нет.
if newBase = true then
//если да то заносим список найденых файлов с их
//парамметрами(путь, контрольная сумма, дата создания, дата изменения) в базу
while i <= Count_file-1 do begin WriteIB(ListFiles.Strings[i]); Inc(i); end; //далее производим проверку i:=0; while i <= Count_file-1 do begin try //проверяем наличие файла FS:=TFileStream.Create(ListFiles.Strings[i],fmOpenRead or fmShareDenyNone); except on Exception do begin Form1.ListBox1.Items.Add('не открывается '+ListFiles.Strings[i]); break; end; end; //Вычисляем контрольную сумму crc32T:=CRC32Stream(FS,0); FS.Free; f:=FindFirstFile(PChar(ListFiles.Strings[i]),SearchF); if f <> INVALID_HANDLE_VALUE then
begin
//определяем дату создания и дату изменения файла
dataCT:=SearchF.ftCreationTime.dwLowDateTime;
dataMT:=SearchF.ftLastWriteTime.dwLowDateTime;
end;
//запускаем процедуру поиска файла с найденными параметрами
//по базе
temp:=FindIB(ListFiles.Strings[i],crc32T,dataCT,dataMT);
if (Not temp and (FindFlagB=0)) then
begin
//если файл отсутсвует то выводим тревожное сообщение
Form1.ListBox1.Items.Add('ВНИМАНИЕ! Данный файл в базе отсутствует: '+ListFiles.Strings[i]);
end;
//Если файл в наличии то выводим результат проверки
if temp and (FindFlagB=1) then
Form1.ListBox1.Items.Add(ListFiles.Strings[i]+' - файл проверен. ОК.')
else
if (not temp) and (FindFlagB=1) then
Form1.ListBox1.Items.Add(ListFiles.Strings[i]+' - файл был изменен.');
Inc(i);
Form1.Update;
end;
end;

Далее опишем функции для работы с базой. И первая функция FindIB(). Она осуществляет проверку наличия интересующего файла в базе и сверку переданных параметров искомого файла с теми что соответствуют ему.


function FindIB(strS:string;crc32,dataC,dataM:Cardinal):Boolean;
var
fileS:TextFile;
nameD,fn:string;
crc32D,dataCD,dataMD:Cardinal;
i,it:integer;
begin
FindFlagB:=0;
AssignFile(fileS,'IFdb.db');
Reset(fileS);
While Not EOF(fileS) do
begin
//считываем данные из базы
ReadLn(fileS,nameD);
// получаем имя файла
it:=Pos('$',nameD);
fn:=copy(nameD,1,it-1);
Delete(nameD,1,it);
//получаем контрольную сумму
it:=Pos('$',nameD);
crc32D:=StrToInt64(copy(nameD,1,it-1));
Delete(nameD,1,it);
//получаем дату создания файла
it:=Pos('$',nameD);
dataCD:=StrToInt64(copy(nameD,1,it-1));
Delete(nameD,1,it);
//получаем дату последнего изменения
dataMD:=StrToInt64(copy(nameD,1,length(nameD)));
if strS = fn then
begin
FindFlagB:=1;
if crc32 = crc32D then
if dataC = dataCD then
if dataM = dataMD then
begin
FindIB:=true;
CloseFile(fileS);
exit;
end;
end;
end;
FindIB:=false;
CloseFile(fileS);
end;

Теперь рассмотрим функцию WriteIB(). Которая заносит в базу путь к файлу, его контрольную сумму, дату создания и дату последнего изменения.


procedure WriteIB(name:string);
var
dbf:TextFile;
i:Cardinal;
s:string;
f: THandle;
SearchF:TWIN32FindData;
begin
//открываем базу
AssignFile(dbf,'IFdb.db');
Append(dbf);
//инициализируем переменные
s:=name+'$';
try
//проверяем наличие добавляемого файла
FS:=TFileStream.Create(name,fmOpenRead or fmShareDenyNone);
except
on Exception do
begin
Form1.ListBox1.Items.Add('не открывается '+name);
exit;
end;
end;
//вычисляем контрольную сумму
i:=CRC32Stream(FS,0);
s:=s+IntToStr(i);
f:=FindFirstFile(PChar(name),SearchF);
if f <> INVALID_HANDLE_VALUE then
//определяем дату создания и дату изменения файла s:=s+'$'+IntToStr(SearchF.ftCreationTime.dwLowDateTime)+'$'+IntToStr(SearchF.ftLastWriteTime.dwLowDateTime);
writeln(dbf,s);
CloseFile(dbf);
FS.Free;
end;

Далее надо объявить необходимые глобальные переменные:


var
SearchRec: TSearchRec;
Count_file,FindFlagB,step: integer;
Path: string;
ListFiles: TStrings;
FS:TFileStream;
newBase:boolean;

Теперь необходимо для события onCreate написать следующее:


procedure TForm1.FormCreate(Sender: TObject);
var
f: THandle;
SearchF:TWIN32FindData;
begin
SendMessage(ListBox1.Handle,LB_SetHorizontalExtent,1000,0);
newBase:= false;
ListFiles:=TStringList.Create;
Path:='*.*';
f:=FindFirstFile('IFdb.db',SearchF);
if f = INVALID_HANDLE_VALUE then
begin
f:=CreateFile('IFdb.db', GENERIC_READ or GENERIC_WRITE, FILE_SHARE_WRITE or FILE_SHARE_READ, nil, CREATE_NEW, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED, 0);
if f <> INVALID_HANDLE_VALUE then
begin
CloseHandle(f);
newBase:= true;
end;
end;
end;

На этом статью заканчиваю. Надеюсь статья и программный код описал максимально понятно. Но замечу что код требует оптимизации, так как был написан таким образом чтобы был понятен читателю. Премер может быть расширен, в него можно добавить кучу дополнительных возможностей. Все это зависит от вашей фантазии.

Необходимые файлы:
- модуль для вычисления CRC32. Тут была ссылка на скачивание, но она стала битой, по просьбе можно попробовать восстановить.

Пожалуйста, оцените полезность и качество данной статьи. Одна звезда - плохо, 5 - хорошо.
1/5. Мы будем признательны, если вы напишете комментарий с причиной низкой оценки.2/5. Мы будем признательны, если вы напишете комментарий с причиной низкой оценки.3/5. Мы будем признательны, если вы напишете комментарий с причиной низкой оценки.4/5.5/5. (2 голосов, средний: 5,00 из 5)
Загрузка...
  1. Пока что нет комментариев.
  1. Пока что нет уведомлений.