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

Отслеживание закрытия файла процессом, запущенным через CreateProcess

23.07.2015, 18:18. Показов 7105. Ответов 49
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток!
Возникла нетривиальная(на мой взгляд) задачка: Открываем какой нибудь файл через какую нибудь программу(условно говоря file.docx с помощью MS Word) и нужно отследить закрытие этого файла.
Запуск осуществляю с помощью CreateProcess, а именно:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
STARTUPINFO si;
PROCESS_INFORMATION pi;
 
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
 
CreateProcess
    (
        TEXT("C:\\Program Files (x86)\\Microsoft Office\\Office15\\WINWORD.EXE"),
        L"/t C:\\Temp\\file.docx", NULL, NULL, TRUE,
        CREATE_NEW_CONSOLE,
        NULL, NULL,
        &si,
        &pi
    );
Далее казалось бы всё просто, мониторь себе список запущенных процессов по pi.dwProcessId и всё.
Но есть одно но. Если при этом будет запущен ещё какой либо файл (например something.docx), то он запустится в том же процессе и в таком случае при закрытии отслеживаемого файла, процесс останется. И я не смогу своевременно отреагировать на его закрытие

Вопрос в том можно ли как то отследить закрытие конкретного файла в программе?? Или же можно запустить процесс выполнения программы так, что бы при выполнении других файлов такого типа, они выполнялись в другом процессе??
Помогите пожалуйста(
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
23.07.2015, 18:18
Ответы с готовыми решениями:

Как дождаться закрытия файла другим процессом/потоком
Всем привет. Допустим известно имя файла. Необходимо: * найти его. * если его сейчас использует другой процесс/поток, то дождаться...

Получить список dll, используемых запущенным процессом
Делаю античит для сетевой игры(готовых решений нет) по способу белого\черного листов и сверкой md5 dll модулей, нужно получить список dll...

Отслеживание создания файлов чужим процессом
Здравствуйте. Возникла проблемка с отслеживанием создания новых файлов в определенной папке чужим процессом (видео-проигрыватель). Этот...

49
1378 / 522 / 72
Регистрация: 21.07.2015
Сообщений: 1,308
23.07.2015, 18:50
Есть утилита Filemon с открытыми исходниками она это умеет, но там вроде даже свой драйвер для этого используется.
Есть вариант (хотя не слишком надежный) просто ожидать разблокировки файла на запись.
Есть еще вариант с перечислением всех дескрипторов
1
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
23.07.2015, 21:40
Цитата Сообщение от AdamWest Посмотреть сообщение
Возникла нетривиальная(на мой взгляд) задачка
...
Из описания я так и не понял: в чем конкретно состоит задачка ?
0
0 / 0 / 0
Регистрация: 21.03.2015
Сообщений: 29
24.07.2015, 10:44  [ТС]
С помощью CreateProcess нужно запустить такой процесс, в котором откроется документ(а) и чтобы при открытии любого другого документа(б) из этого процесса, документ(б) открывался в другом процессе. Как то так

Добавлено через 10 часов 0 минут
Или как вообще можно на с++ отследить закрытие файла в программе
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
24.07.2015, 11:17
Цитата Сообщение от AdamWest Посмотреть сообщение
С помощью CreateProcess нужно запустить такой процесс, в котором откроется документ(а) и чтобы при открытии любого другого документа(б) из этого процесса, документ(б) открывался в другом процессе
А что должно произойти с процессом, который открывал документ (а) ?
0
1378 / 522 / 72
Регистрация: 21.07.2015
Сообщений: 1,308
24.07.2015, 11:47
Цитата Сообщение от AdamWest Посмотреть сообщение
Или как вообще можно на с++ отследить закрытие файла в программе
Чем мои варианты не устраивают?
0
0 / 0 / 0
Регистрация: 21.03.2015
Сообщений: 29
24.07.2015, 12:02  [ТС]
Убежденный: Процесс открытия документа(а) должен завершиться.
shmkv: я не понял как подключиться из с++ к FileMon/Procecc Monitor. Гугление по отлову дескрипторов файлов на с++ мне к сожалению ничего не дало.
0
1378 / 522 / 72
Регистрация: 21.07.2015
Сообщений: 1,308
24.07.2015, 12:08
Цитата Сообщение от AdamWest Посмотреть сообщение
я не понял как подключиться из с++ к FileMon/Procecc Monitor
У FileMon есть исходники.
Цитата Сообщение от AdamWest Посмотреть сообщение
угление по отлову дескрипторов файлов на с++ мне к сожалению ничего не дало.
Я тебе дал ссылку на пример. Там делфи, но разобраться можно.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
24.07.2015, 12:21
Лучший ответ Сообщение было отмечено AdamWest как решение

Решение

Я бы сделал так: запускаем процесс с помощью CreateProcess, далее ждем,
пока в него не будет загружена kernel32.dll. После этого ставим в процессе
хук на CreateFileA/W, или даже сразу на ntdll!NtCreateFile.
Далее, когда срабатывает наш перехватчик с интересующим именем файла,
запускаем из него новый процесс и возвращаем какой-нибудь NT-код
ошибки, например 0xc0000022 (access denied). И никаких драйверов
писать не нужно для этого.
3
0 / 0 / 0
Регистрация: 21.03.2015
Сообщений: 29
29.07.2015, 17:53  [ТС]
А как понять что kernel32.dll уже загружена? А хуки на изменения файлов можно ставить?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
29.07.2015, 20:39
Цитата Сообщение от AdamWest Посмотреть сообщение
А как понять что kernel32.dll уже загружена?
Ну можно запускать процесс в режиме DEBUG_PROCESS (флаг CreateProcess),
затем подписываться на события через WaitForDebugEvent и ловить загрузку
kernel32.dll. Или в цикле вызывать CreateToolhelp32Snapshot и смотреть,
загрузилась ли kernel32 в нужный процесс или еще нет.

Цитата Сообщение от AdamWest Посмотреть сообщение
А хуки на изменения файлов можно ставить?
Да. Например, хук на NtWriteFile, на NtSetFileInformation и т.д.
1
0 / 0 / 0
Регистрация: 21.03.2015
Сообщений: 29
02.09.2015, 15:11  [ТС]
Что то у меня не выходит.
Как уже было описано:
1. Запускаю процесс через CreateProcess
2. Снимаю снэпшот системы и ищу нужный мне процесс(по pId).
3. Когда процесс найден, то смотрю загруженные модули для этого процесса
4. Когда найден kernel32.dll Нужно ставить хук. Вот здесь и возникли проблемы и вопросы

Можно ли подобные хуки ставить средствами с++? Если можно то как это делается?
Я пока что пытаюсь поставить хук с помощью библиотеки MinHook, к сожалению безуспешно(kernel32.dll was found выводится в консоль, а HOOKED не выводится, как я понимаю, это значит что DetourCreateFile не вызывается). И нужно ли ставить хук на CreateFile, если мне нужна реакция на закрытие или изменение файла?


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
typedef int (WINAPI *CREATEFILE)(LPCTSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
 
CREATEFILE fpCreateFile = NULL;
 
int WINAPI DetourCreateFile(LPCTSTR lpctst, DWORD dw1, DWORD dw2, LPSECURITY_ATTRIBUTES sec_attr, DWORD dw3, DWORD dw4, HANDLE hndl)
{
    cout << "HOOKED" << endl;
    return 0;
}
 
VOID PrintModuleList(HANDLE CONST hStdOut, DWORD CONST dwProcessId);
 
int _tmain(int argc, _TCHAR* argv[])
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
 
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));
    
        MH_Initialize();
    
        CreateProcess
        (
    TEXT("C:\\Program Files (x86)\\Microsoft Office\\Office15\\WINWORD.EXE"),
    L"/t C:\\Temp\\sendMEplease.docx", NULL, NULL, TRUE,
    CREATE_NEW_CONSOLE,
    NULL, NULL,
    &si,
    &pi
    );
 
    DWORD pId = pi.dwProcessId;
    DWORD ExitCode;
    PROCESSENTRY32 peProcessEntry;
    TCHAR szBuff[1024];
    DWORD dwTemp;
    HANDLE CONST hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    HANDLE CONST hSnapshot = CreateToolhelp32Snapshot(
        TH32CS_SNAPPROCESS, pId);
 
    if (INVALID_HANDLE_VALUE == hSnapshot) {
        return 0;
    }
    peProcessEntry.dwSize = sizeof(PROCESSENTRY32);
    Process32First(hSnapshot, &peProcessEntry);
    do {
        if (peProcessEntry.th32ProcessID == pId) {
            PrintModuleList(hStdOut, peProcessEntry.th32ProcessID);
            break;
        }
    } while (Process32Next(hSnapshot, &peProcessEntry));
 
    CloseHandle(hSnapshot);
    MH_Uninitialize();
    return 0;
}
 
 
VOID PrintModuleList(HANDLE CONST hStdOut, DWORD CONST dwProcessId) {
    MODULEENTRY32 meModuleEntry;
    TCHAR szBuff[1024];
    DWORD dwTemp;
    HANDLE CONST hSnapshot = CreateToolhelp32Snapshot(
        TH32CS_SNAPMODULE, dwProcessId);
    if (INVALID_HANDLE_VALUE == hSnapshot) {
        return;
    }
 
    meModuleEntry.dwSize = sizeof(MODULEENTRY32);
    Module32First(hSnapshot, &meModuleEntry);
    string str = "kernel32.dll";
    wstring w_str(str.begin(), str.end());
    do {
        if (meModuleEntry.szModule == w_str)
        {
            MH_CreateHook(&CreateFile, &DetourCreateFile,
        reinterpret_cast<LPVOID*>(&fpCreateFile));
            MH_EnableHook(&CreateFile);
            cout <<"kernel32.dll was found" << endl;
            break;
        }
    } while (Module32Next(hSnapshot, &meModuleEntry));
 
    CloseHandle(hSnapshot);
}
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
02.09.2015, 15:14
Цитата Сообщение от AdamWest Посмотреть сообщение
kernel32.dll was found выводится в консоль, а HOOKED не выводится, как я понимаю, это значит что DetourCreateFile не вызывается
Хуки надо ставить в процесс, который вы запускаете.
А здесь они ставятся в исходный процесс.
Естественно, ничего не работает.
0
0 / 0 / 0
Регистрация: 21.03.2015
Сообщений: 29
02.09.2015, 16:00  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
Хуки надо ставить в процесс, который вы запускаете.
Хм. А как это делается? Ведь, как я понимаю, процесс создан и запущен после того как вызвана функция CreateProcess. То есть мне нужно каким то образом в CreateProcess зарегистрировать какую то callback функцию?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
02.09.2015, 17:42
1) Находите адрес функции LoadLibrary в своем процессе (GetProcAddress).
С вероятностью 99% он будет таким же и в дочернем процессе.

2) Выделяете в дочернем процессе память - VirtualAllocEx.
Тип - MEM_COMMIT, атрибуты - PAGE_READWRITE.

3) В выделенную память пишете с помощью функции WriteProcessMemory
полный путь к dll, которую нужно загрузить.

4) Запускаете удаленный поток в дочернем процессе - CreateRemoteThread.
В качестве точки входа передаете адрес LoadLibrary, а в качестве аргумента -
указатель на выделенную ранее память. В итоге в удаленном процессе
будет создан поток, который вызовет LoadLibrary и завершится.

5) Из загруженной dll уже можно ставить перехваты.
Только делать это не нужно из DllMain, лучше создать отдельный поток.
2
0 / 0 / 0
Регистрация: 21.03.2015
Сообщений: 29
03.09.2015, 14:15  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
Находите адрес функции LoadLibrary в своем процессе (GetProcAddress).
С вероятностью 99% он будет таким же и в дочернем процессе.
Функция GetProcAddress принимает два аргумента:
HMODULE - Дескриптор модуля. Тк мне нужно искать LoadLibrary для моего процесса, то, насколько я понимаю,
в этот аргумент нужно передать результат выполнения функции GetModuleHandle(NULL)(который и возвращает HMODULE для данного процесса)
LPCSTR - имя функции(тоесть "LoadLibrary")
В итоге я не могу найти адрес вызова LoadLibrary, функция GetProcAddress возвращает NULL
В чём моя ошибка?

C++
1
2
3
    HMODULE hModuleSelf = GetModuleHandle(NULL);
    void* p = GetProcAddress(hModuleSelf, "LoadLibrary");
    cout << p << endl;
Цитата Сообщение от Убежденный Посмотреть сообщение
Выделяете в дочернем процессе память - VirtualAllocEx.
Тип - MEM_COMMIT, атрибуты - PAGE_READWRITE.
Дочерний процесс это получается процесс запуска файла(который порождается функцией CreateProcess )? Как выделить в дочернем процессе память? Просто после CreateProcess вызвать VirtualAllocEx, куда передать HANDLE процесса созданного CreateProcess ?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
03.09.2015, 17:54
Цитата Сообщение от AdamWest Посмотреть сообщение
HMODULE - Дескриптор модуля. Тк мне нужно искать LoadLibrary для моего процесса, то, насколько я понимаю,
в этот аргумент нужно передать результат выполнения функции GetModuleHandle(NULL)(который и возвращает HMODULE для данного процесса)
А зачем гадать ?
В MSDN все описано, какой HMODULE нужно передавать в функцию.

Цитата Сообщение от AdamWest Посмотреть сообщение
Просто после CreateProcess вызвать VirtualAllocEx, куда передать HANDLE процесса созданного CreateProcess ?
Да.
0
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18031 / 7734 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16
09.09.2015, 10:00
AdamWest, пример части с внедрением: Создание удаленного потока
0
0 / 0 / 0
Регистрация: 21.03.2015
Сообщений: 29
09.09.2015, 10:42  [ТС]
Dragokas, Спасибо. Внедрение я всё таки осилил сам и вчера столкнулся с точно такой же проблемой. Код из DLL не выполняется(т.к. не показывается MessageBox сообщение и файл C:\temp.txt не создаётся), хотя внедрение вроде отрабатывает корректно.

Внедрение DLL:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void injectDLL(HANDLE hProcess)
{
    char* dll = "c:\\users\\adam\\documents\\visual studio 2015\\Projects\\HookDll\\Debug\\HookDll.dll";
 
    LPVOID lpSpace = (LPVOID)VirtualAllocEx(hProcess, NULL, strlen(dll), MEM_COMMIT, PAGE_READWRITE);
    
    int n = WriteProcessMemory(hProcess, lpSpace, dll, strlen(dll), NULL);
 
    HMODULE hModule = GetModuleHandle(L"kernel32.dll");
    
    LPVOID lpBaseAddress = (LPVOID)GetProcAddress(hModule, "LoadLibraryW");
    
    HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpBaseAddress, lpSpace, NULL, NULL);
    
};
Смотрел в отладчике, ни одна из переменных lpSpace / n / hModule / lpBaseAddress / hThread не равна NULL

Код HookDll.dll:
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
#include <stdio.h>
#include <winsock2.h>
#include <windows.h>
 
INT APIENTRY DllMain(HMODULE hDll, DWORD Reason, LPVOID Reserved)
{
    MessageBox(NULL,L"DLL", L"DllMain",MB_OK);
    FILE *file;
    fopen_s(&file, "c:\\temp.txt", "a+");
 
    switch (Reason)
    {
    case DLL_PROCESS_ATTACH:
        fprintf(file, "DLL attach function called.n");
        break;
    case DLL_PROCESS_DETACH:
        fprintf(file, "DLL detach function called.n");
        break;
    case DLL_THREAD_ATTACH:
        fprintf(file, "DLL thread attach function called.n");
        break;
    case DLL_THREAD_DETACH:
        fprintf(file, "DLL thread detach function called.n");
        break;
    }
 
    fclose(file);
    return TRUE;
};
Кто нибудь знает в чём проблема? Что я делаю не правильно?
P.S Внедрение происходит в Microsoft Word
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
09.09.2015, 12:06
Цитата Сообщение от AdamWest Посмотреть сообщение
Кто нибудь знает в чём проблема?
Путь к dll задан в char-символах, а удаленный поток зовет LoadLibraryW,
которому нужна строка в wchar_t-символах. Да, и MSDN крайне не советует
звать MessageBox из DllMain...

И путь к dll нужно писать WriteProcessMemory вместе с завершающим нулем,
а здесь его нет (strlen(dll) вообще вернет размер указателя).
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
09.09.2015, 12:06
Помогаю со студенческими работами здесь

Отслеживание закрытия программы.
Как отследить что мою прогу пытаются закрыть. Неважно как, по CTRL Alt Del, или еще как? CloseQuery не пашет.

Отслеживание закрытия программы
Приветствую! Нужна ваша помощь! Каким образом можно запустить exe файл и ждать его завершения? После его завершения вывести сообщение о...

Отслеживание закрытия диалога
Здравствуйте! Имеется вот такой класс: package com.contedevel.timetable; import java.util.ArrayList; import java.util.List; ...

Отслеживание закрытия стороннего приложения
Всем доброго времени суток. Нужно реализовать программу последовательного открытия .exe файлов. То есть указать 2 пути к файлам. После чего...

Отслеживание закрытия формы javafx
Здравствуйте! Такой вопрос. Есть форма (сцена) приложения и вот из нее по кнопке создаю и запускаю экземпляр дочерней формы (другой). можно...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru