Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.86/29: Рейтинг темы: голосов - 29, средняя оценка - 4.86
0 / 0 / 0
Регистрация: 25.02.2015
Сообщений: 7

Поиск удаленных файлов в NTFS

23.11.2016, 11:23. Показов 5950. Ответов 8

Студворк — интернет-сервис помощи студентам
Добрый день!
Помогите, пожалуйста.
Пишу программку для поиска удаленных файлов в NTFS и последующей работы с ними. Как написано в книге Брайана Кэрриэ "Криминалистический анализ файловых систем" для поиска удаленных файлов необходимо найти все MFT записи с нулевым флагом. Попытки считать необходимые данные через DeviceIoControl используя FSCTL_GET_NTFS_FILE_RECORD возвращают стуктуру данных с флагом 1, даже если реально флаг нулевой и это видно в HEX-редакторе. Собстенно, вопрос: как это можно исправить, потому что у самого идей уже нет в чем может быть проблемы.
Проверял на win10 и win7 результат везде одинаковый и также проверял на разных томах, все равно одно и тоже.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <winioctl.h>
#include <string>
#include <sstream>
 
 
using namespace std;
 
#define NRH_FILE_TYPE  0x454C4946
#define ATTRIBUTE_TYPE_DATA 0x80
#define ATTRIBUTE_TYPE_SI 0x10
#define ATTRIBUTE_TYPE_FN 0x30
#define ATTRIBUTE_TYPE_END 0xFFFFFFFF
 
 
typedef enum {
    AttributeStandardInformation = 0x10,
    AttributeAttributeList = 0x20,
    AttributeFileName = 0x30,
    AttributeObjectId = 0x40,
    AttributeSecurityDescriptor = 0x50,
    AttributeVolumeName = 0x60,
    AttributeVolumeInformation = 0x70,
    AttributeData = 0x80,
    AttributeIndexRoot = 0x90,
    AttributeIndexAllocation = 0xA0,
    AttributeBitmap = 0xB0,
    AttributeReparsePoint = 0xC0,
    AttributeEAInformation = 0xD0,
    AttributeEA = 0xE0,
    AttributePropertySet = 0xF0,
    AttributeLoggedUtilityStream = 0x100
} attr_types, *pattr_types;
 
typedef struct
{/*0x00*/   attr_types type; //тип атрибута
/*0x04*/    unsigned __int16 length; //длина заголовка; используется для перехода к //следующему   атрибуту
/*0x06*/    unsigned __int16 reserved;
/*0x08*/    unsigned char non_resident; //1 если атрибут нерезидентный, 0 - резидентный
/*0x09*/    unsigned char name_length; //длина имени атрибута, в символах
/*0x0A*/    unsigned __int16 name_offset; //смещение имени атрибута, относительно заголовка 
                                          //атрибута
/*0x0C*/    unsigned __int16 flags; //флаги, перечислены в ATTR_FLAGS
/*0x0E*/    unsigned __int16 instance;
 
union
{
    //Резидентный атрибут
    struct
    {
        /*0x10*/    unsigned __int32 value_length; //размер, в байтах, тела атрибута
        /*0x14*/    unsigned char value_offset; //байтовое смещение тела, относительно заголовка атрибута
        /*0x15*/    unsigned char resident_flags; //флаги, перечислены в RESIDENT_ATTR_FLAGS
        /*0x17*/    unsigned char reserved;
    } resident;
    //Нерезидентный атрибут
    struct
    {
        /*0x10*/    unsigned __int64 lowest_vcn; //стартовый сектор для списка серий
        /*0x18*/    unsigned __int64 highest_vcn; //конечный сектор для списка серий
        /*0x20*/    unsigned __int16 mapping_pairs_offset;//смещение списка отрезков 
        /*0x22*/    unsigned char compression_unit;
        /*0x23*/    unsigned char reserved1[5];
        /*0x28*/    unsigned __int64 allocated_size; //размер дискового пространства, 
                                                     //которое было выделено под тело
                                                     //атрибута
        /*0x30*/    unsigned __int64 data_size; //реальный размер атрибута
        /*0x38*/    unsigned __int64 initialized_size;
    } nonresident;
}u;
} NTFS_ATTR_RECORD, *PNTFS_ATTR_RECORD;
 
typedef struct 
{
    /*0x00*/ unsigned __int64   file_reference; /*базовый адрес родительского каталога*/
    /*0x08*/ unsigned __int64   file_creation_time; /*время создание файла*/
    /*0x10*/ unsigned __int64   file_altered_time; /*время модификации файла*/
    /*0х18*/ unsigned __int64  file_mft_change_time; /*время модификации MFT*/
    /*0x20*/ unsigned __int64   file_read_time; /*время обращения в файлу*/
    /*0x28*/ unsigned __int64   file_size; /*выделенный размер файла*/
    /*0x30*/ unsigned __int64   file_real_size; /*реальный размер файла*/
    /*0x38*/ unsigned __int32   file_flags; /*флаги: директория, сжатый файл и т.д*/
    /*0x3с*/ unsigned __int32  file_mount_points; /*точки подключения*/
    /*0x40*/ unsigned __int8        file_name_in_chars; /*длина имени*/
    /*0x41*/ unsigned __int8        file_name_namespace; /*пространство имен имени*/
    /*0x42*/ char               file_name[64]; /*имя*/
} NTFS_ATTR_FILE_INFO, *PNTFS_ATTR_FILE_INFO;
 
typedef struct {
    ULONG Type;
    USHORT UsaOffset;
    USHORT UsaCount;
    USN Usn;
} NTFS_RECORD_HEADER, *PNTFS_RECORD_HEADER;
 
typedef struct {
    NTFS_RECORD_HEADER Ntfs;
    USHORT SequenceNumber;
    USHORT LinkCount;
    USHORT AttributesOffset;
    unsigned __int16 Flags; // 0x0001 = Используется, 0x0002 = Каталог, 0x0000 = Не используется
    ULONG BytesInUse;
    ULONG BytesAllocated;
    ULONGLONG BaseFileRecord;
    USHORT NextAttributeNumber;
} FILE_RECORD_HEADER, *PFILE_RECORD_HEADER;
 
typedef struct {
    ULONGLONG CreationTime;
    ULONGLONG ChangeTime;
    ULONGLONG LastWriteTime;
    ULONGLONG LastAccessTime;
    ULONG FileAttributes;
    ULONG AlignmentOrReservedOrUnknown[3];
    ULONG QuotaId; // Только на NTFS 3.0
    ULONG SecurityId; // Только на NTFS 3.0
    ULONGLONG QuotaCharge; // Только на NTFS 3.0
    USN Usn; // Только на NTFS 3.0
} STANDARD_INFORMATION, *PSTANDARD_INFORMATION;
 
LONGLONG NTFS_GET_MTF_ENTRIES_COUNT(NTFS_VOLUME_DATA_BUFFER nvdb)
{
    return nvdb.MftValidDataLength.QuadPart / nvdb.BytesPerFileRecordSegment;
}
 
PNTFS_FILE_RECORD_OUTPUT_BUFFER NTFS_GET_MFT_ENTRY_AT(int number, NTFS_VOLUME_DATA_BUFFER nvdb, HANDLE hDrive)
{
    
    DWORD junk;
    NTFS_FILE_RECORD_INPUT_BUFFER ntfs_unput;
    LARGE_INTEGER lnumber;
    lnumber.QuadPart = number;
    ntfs_unput.FileReferenceNumber = lnumber;
    PNTFS_FILE_RECORD_OUTPUT_BUFFER nrb =
        (PNTFS_FILE_RECORD_OUTPUT_BUFFER)malloc(FIELD_OFFSET(NTFS_FILE_RECORD_OUTPUT_BUFFER, FileRecordBuffer)
            + nvdb.BytesPerFileRecordSegment);
    BOOL mft_entry = DeviceIoControl(hDrive, FSCTL_GET_NTFS_FILE_RECORD,
        &ntfs_unput, sizeof(ntfs_unput), nrb,
        sizeof(NTFS_FILE_RECORD_OUTPUT_BUFFER) + nvdb.BytesPerFileRecordSegment,
        &junk, NULL);
    return nrb;
}
 
wstring get_filename(PNTFS_ATTR_FILE_INFO file)
{
    wstringstream wss;
    wstring result;
    for (size_t i = 0; i < 2 * file->file_name_in_chars; i++)
    {
        wss << file->file_name[i];
    }
    wss >> result;
    return result;
}
 
int main()
{
    setlocale(LC_ALL, "Russian");
    HANDLE hDrive = CreateFile(L"\\\\.\\H:", GENERIC_READ,
        FILE_SHARE_READ, 0,
        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if (INVALID_HANDLE_VALUE == hDrive)
    {
        cout << hDrive << endl;
        cout << "Invalid Handle To Volume" << endl;
    }
    DWORD junk;
    NTFS_VOLUME_DATA_BUFFER ntfs_volume_data;
    BOOL bResult = DeviceIoControl((HANDLE)hDrive, FSCTL_GET_NTFS_VOLUME_DATA
        , NULL, 0,
        &ntfs_volume_data,
        sizeof(NTFS_VOLUME_DATA_BUFFER),
        &junk,
        (LPOVERLAPPED)NULL);
    LONGLONG mft_entries_count = NTFS_GET_MTF_ENTRIES_COUNT(ntfs_volume_data);
    for (int i = 0; i < mft_entries_count; i++)
    {
        PNTFS_FILE_RECORD_OUTPUT_BUFFER mft_entry = NTFS_GET_MFT_ENTRY_AT(i, ntfs_volume_data, hDrive);
        PFILE_RECORD_HEADER pfileRecordheader = (PFILE_RECORD_HEADER)mft_entry->FileRecordBuffer;
        PNTFS_ATTR_RECORD attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)pfileRecordheader + pfileRecordheader->AttributesOffset);
        cout << "-----" << i << "-----" << endl;
        cout << "-----" << pfileRecordheader->Flags << "-----" << endl;
        
    }   
    return 0;
}
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
23.11.2016, 11:23
Ответы с готовыми решениями:

Поиск и удаление файлов по маске в директории admin$ на удалённых машинах
Привет всем. Очень надеюсь на вас в данном вопросе! Пробежав по форму, я наткнулся на парочку тем с похожими вопросами, но попросту не могу...

Восстановление данных с удаленных разделов NTFS
Здравствуйте. Вы одна из последних надежд...)) Суть проблемы такова, есть заведомо рабочий диск Seagate 2 Tb SATA на нем было 3...

Удаление файлов на NTFS
Здравствуйте. После восстановления файлов после форматирования на другом диске остались копии файлов, которые не нужны. Хочц удалить папку...

8
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
23.11.2016, 15:59
Для начала неплохо бы вставить проверки, что DeviceIoControl и
другие функции во всех местах отрабатывают без ошибок.
0
0 / 0 / 0
Регистрация: 25.02.2015
Сообщений: 7
24.11.2016, 11:13  [ТС]
Проверки это, конечно, хорошо, но вся проблема именно в одном флаге, остальные поля структуры заполнены корректными значениями и дальше я по инфе их этой структуры выдираю атрибуты и инфу по ним и все сходится (проверял через SleuthKit)
Тоесть даже Encase и SleuthKit показывают, что файл удален (запись не используется), а api'шка говорит, что это не так, вот и вопрос: кому верить?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
24.11.2016, 13:53
Цитата Сообщение от sparemail Посмотреть сообщение
Проверки это, конечно, хорошо, но вся проблема именно в одном флаге
Я не понимаю, как можно делать какие-то предположения о работе кода,
когда проверка ошибок отсутствует? Где гарантия, что DeviceIoControl
вообще заполняет буфер какими-то данными?
0
0 / 0 / 0
Регистрация: 25.02.2015
Сообщений: 7
24.11.2016, 14:01  [ТС]
Вывод можно сделать потому, что из буфера я и получаю корректные данные, проблема не в том, что данные не записываются в буфер, они там есть и все хорошо, проблема в том что одно из полей структуры имеет значение, которое не должно быть (согласно программам для проведения экпертизы), все остальные поля 100% корректны.
И проверки написал, никаких ошибок.
Поэтому и написал на форум, я не особо шарю в winapi и может просто что-то успускаю, но сам код работает (я получаю корректные данные и значение атрибутов $STANDARD_INFORMATION и $FILE_NAME) иначе бы не писал на форум.

ЗЫ. Раз уж такое дело, подскажите как правильно проверить, что функция отрабатывает без ошибок?
Так корректно?
C++
1
2
3
4
5
6
7
8
9
10
BOOL bResult = DeviceIoControl((HANDLE)hDrive, FSCTL_GET_NTFS_VOLUME_DATA
        , NULL, 0,
        &ntfs_volume_data,
        sizeof(NTFS_VOLUME_DATA_BUFFER),
        &junk,
        (LPOVERLAPPED)NULL);
    if (!bResult)
    {
        //обработка ошибки
    }
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
24.11.2016, 14:12
Цитата Сообщение от sparemail Посмотреть сообщение
Вывод можно сделать потому, что из буфера я и получаю корректные данные, проблема не в том, что данные не записываются в буфер, они там есть и все хорошо
Ок.

Цитата Сообщение от sparemail Посмотреть сообщение
проблема в том что одно из полей структуры имеет значение, которое не должно быть
Цитата Сообщение от sparemail Посмотреть сообщение
необходимо найти все MFT записи с нулевым флагом.
О каком конкретно флаге (или поле структуры) идет речь?

Цитата Сообщение от sparemail Посмотреть сообщение
Раз уж такое дело, подскажите как правильно проверить, что функция отрабатывает без ошибок?
Так корректно?
Да. Еще полезно в блоке обработки ошибки узнать код GetLastError().
0
0 / 0 / 0
Регистрация: 25.02.2015
Сообщений: 7
24.11.2016, 14:34  [ТС]
В данной структуре
typedef struct {
NTFS_RECORD_HEADER Ntfs;
USHORT SequenceNumber;
USHORT LinkCount;
USHORT AttributesOffset;
unsigned __int16 Flags; // 0x0001 = Используется, 0x0002 = Каталог, 0x0000 = Не используется
ULONG BytesInUse;
ULONG BytesAllocated;
ULONGLONG BaseFileRecord;
USHORT NextAttributeNumber;
} FILE_RECORD_HEADER, *PFILE_RECORD_HEADER;

поле FLAGS;

Все остальные поля корретны
И не могу понять почему, толи это какая-то недокументированная особенность, толи это у меня лыжи не едут (хотя я вроде все перепроверил), весь интернет перерыл ничего не нашел, даже в сорцы ReactOS смотрел, как там устроена работа с NTFS, там вроде все также
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
24.11.2016, 15:10
Судя по всему, это достаточно древняя проблема.

Incorrect Flags values in MFT FILE_RECORD_SEGMENT_HEADER documentation?
https://social.msdn.microsoft.... mentissues

Я также нашел на RSDN один топик 2010 года, в котором
описывается эта же самая проблема на Windows XP.
2
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18030 / 7733 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
30.11.2016, 20:51
Лучший ответ Сообщение было отмечено sparemail как решение

Решение

sparemail, передайте управляющий код FSCTL_ENUM_USN_DATA, чтобы составить список номеров обновлений USN всех существующих на томе файловых объектов. Так вы отфильтруете только удалённые.

Или передайте NTFS_RECORD_HEADER -> Usn в NtCreateFile с флагом FILE_OPEN_BY_FILE_ID. Так вы узнаете существует файл или нет.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
30.11.2016, 20:51
Помогаю со студенческими работами здесь

Удаление файлов в NTFS
Не могу разобраться, как всё-таки происходит удаление файла, на низком уровне, с точки зрения файловой системы. Удаляется ли запись из MFT,...

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

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

Восстановление удаленных файлов
такая проблема сидел в компе чтот смотрел вдруг комп выключается я его пытаюсь включить а мне типа востановите систему и хлоп обратно...

восстановление удаленных файлов
подскажите, пожалуйста, кто знает, дайте ссылки на статьи и книги, где можно прочитать про то, как это можно реализовать программно.


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит переходные токи и напряжения на элементах схемы. . . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru