Форум программистов, компьютерный форум, киберфорум
Наши страницы

C++ и WinAPI

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 5.00
AdamWest
0 / 0 / 0
Регистрация: 21.03.2015
Сообщений: 29
#1

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

23.07.2015, 18:18. Просмотров 2170. Ответов 50
Метки нет (Все метки)

Доброго времени суток!
Возникла нетривиальная(на мой взгляд) задачка: Открываем какой нибудь файл через какую нибудь программу(условно говоря 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)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
23.07.2015, 18:18
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Отслеживание закрытия файла процессом, запущенным через CreateProcess (C++ WinAPI):

Не запускается exe через CreateProcess - C++ WinAPI
Здравствуйте! Стоит задача запустить exe файл с параметрами тихой установки, а именно установку opera! Не могу понять почему notepad...

Передача параметров через CreateProcess - C++ WinAPI
такое дело, программа открывает консольную и считывает результат ее работы , но только консольная программа должна брать данные из файла,...

Запуск стороннего приложения через CreateProcess - C++ WinAPI
Доброго времени суток! Есть два одинаковых консольных приложения, но с разными именами. Из первого вызывается второе следующей...

Условие к использованию памяти созданного процесса через CreateProcess() - C++ WinAPI
Здравствуйте, через CreateProcess() запускаю внешнюю програму (у меня это VLC медиаплеер). Можно ли как то реализовать условие: когда...

Запуск приложения через CreateProcess(), передать параметры запуска, указать тот же каталог - C++ WinAPI
Здравствуйте, помогите побороться с CreateProcess() Есть рабочая программа, которая должна запустить независимый процесс. Запуск нужно...

Создать программу, в которой с помощью функции CreateProcess порождается процесс выполняющий чтение файла и вывод его на экран - C++ WinAPI
Доброго всем вечера. Делаю лабу по системному программированию и как бы есть немалые проблемы. Вот сама лаба. Создать программу, в...

50
shmkv
624 / 339 / 43
Регистрация: 21.07.2015
Сообщений: 995
23.07.2015, 18:50 #2
Есть утилита Filemon с открытыми исходниками она это умеет, но там вроде даже свой драйвер для этого используется.
Есть вариант (хотя не слишком надежный) просто ожидать разблокировки файла на запись.
Есть еще вариант с перечислением всех дескрипторов
1
Убежденный
Ушел с форума
Эксперт С++
15793 / 7230 / 1138
Регистрация: 02.05.2013
Сообщений: 11,637
Записей в блоге: 1
Завершенные тесты: 1
23.07.2015, 21:40 #3
Цитата Сообщение от AdamWest Посмотреть сообщение
Возникла нетривиальная(на мой взгляд) задачка
...
Из описания я так и не понял: в чем конкретно состоит задачка ?
0
AdamWest
0 / 0 / 0
Регистрация: 21.03.2015
Сообщений: 29
24.07.2015, 10:44  [ТС] #4
С помощью CreateProcess нужно запустить такой процесс, в котором откроется документ(а) и чтобы при открытии любого другого документа(б) из этого процесса, документ(б) открывался в другом процессе. Как то так

Добавлено через 10 часов 0 минут
Или как вообще можно на с++ отследить закрытие файла в программе
0
Убежденный
Ушел с форума
Эксперт С++
15793 / 7230 / 1138
Регистрация: 02.05.2013
Сообщений: 11,637
Записей в блоге: 1
Завершенные тесты: 1
24.07.2015, 11:17 #5
Цитата Сообщение от AdamWest Посмотреть сообщение
С помощью CreateProcess нужно запустить такой процесс, в котором откроется документ(а) и чтобы при открытии любого другого документа(б) из этого процесса, документ(б) открывался в другом процессе
А что должно произойти с процессом, который открывал документ (а) ?
0
shmkv
624 / 339 / 43
Регистрация: 21.07.2015
Сообщений: 995
24.07.2015, 11:47 #6
Цитата Сообщение от AdamWest Посмотреть сообщение
Или как вообще можно на с++ отследить закрытие файла в программе
Чем мои варианты не устраивают?
0
AdamWest
0 / 0 / 0
Регистрация: 21.03.2015
Сообщений: 29
24.07.2015, 12:02  [ТС] #7
Убежденный: Процесс открытия документа(а) должен завершиться.
shmkv: я не понял как подключиться из с++ к FileMon/Procecc Monitor. Гугление по отлову дескрипторов файлов на с++ мне к сожалению ничего не дало.
0
shmkv
624 / 339 / 43
Регистрация: 21.07.2015
Сообщений: 995
24.07.2015, 12:08 #8
Цитата Сообщение от AdamWest Посмотреть сообщение
я не понял как подключиться из с++ к FileMon/Procecc Monitor
У FileMon есть исходники.
Цитата Сообщение от AdamWest Посмотреть сообщение
угление по отлову дескрипторов файлов на с++ мне к сожалению ничего не дало.
Я тебе дал ссылку на пример. Там делфи, но разобраться можно.
0
Убежденный
Ушел с форума
Эксперт С++
15793 / 7230 / 1138
Регистрация: 02.05.2013
Сообщений: 11,637
Записей в блоге: 1
Завершенные тесты: 1
24.07.2015, 12:21 #9
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Я бы сделал так: запускаем процесс с помощью CreateProcess, далее ждем,
пока в него не будет загружена kernel32.dll. После этого ставим в процессе
хук на CreateFileA/W, или даже сразу на ntdll!NtCreateFile.
Далее, когда срабатывает наш перехватчик с интересующим именем файла,
запускаем из него новый процесс и возвращаем какой-нибудь NT-код
ошибки, например 0xc0000022 (access denied). И никаких драйверов
писать не нужно для этого.
3
AdamWest
0 / 0 / 0
Регистрация: 21.03.2015
Сообщений: 29
29.07.2015, 17:53  [ТС] #10
А как понять что kernel32.dll уже загружена? А хуки на изменения файлов можно ставить?
0
Убежденный
Ушел с форума
Эксперт С++
15793 / 7230 / 1138
Регистрация: 02.05.2013
Сообщений: 11,637
Записей в блоге: 1
Завершенные тесты: 1
29.07.2015, 20:39 #11
Цитата Сообщение от AdamWest Посмотреть сообщение
А как понять что kernel32.dll уже загружена?
Ну можно запускать процесс в режиме DEBUG_PROCESS (флаг CreateProcess),
затем подписываться на события через WaitForDebugEvent и ловить загрузку
kernel32.dll. Или в цикле вызывать CreateToolhelp32Snapshot и смотреть,
загрузилась ли kernel32 в нужный процесс или еще нет.

Цитата Сообщение от AdamWest Посмотреть сообщение
А хуки на изменения файлов можно ставить?
Да. Например, хук на NtWriteFile, на NtSetFileInformation и т.д.
1
AdamWest
0 / 0 / 0
Регистрация: 21.03.2015
Сообщений: 29
02.09.2015, 15:11  [ТС] #12
Что то у меня не выходит.
Как уже было описано:
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
Убежденный
Ушел с форума
Эксперт С++
15793 / 7230 / 1138
Регистрация: 02.05.2013
Сообщений: 11,637
Записей в блоге: 1
Завершенные тесты: 1
02.09.2015, 15:14 #13
Цитата Сообщение от AdamWest Посмотреть сообщение
kernel32.dll was found выводится в консоль, а HOOKED не выводится, как я понимаю, это значит что DetourCreateFile не вызывается
Хуки надо ставить в процесс, который вы запускаете.
А здесь они ставятся в исходный процесс.
Естественно, ничего не работает.
0
AdamWest
0 / 0 / 0
Регистрация: 21.03.2015
Сообщений: 29
02.09.2015, 16:00  [ТС] #14
Цитата Сообщение от Убежденный Посмотреть сообщение
Хуки надо ставить в процесс, который вы запускаете.
Хм. А как это делается? Ведь, как я понимаю, процесс создан и запущен после того как вызвана функция CreateProcess. То есть мне нужно каким то образом в CreateProcess зарегистрировать какую то callback функцию?
0
Убежденный
Ушел с форума
Эксперт С++
15793 / 7230 / 1138
Регистрация: 02.05.2013
Сообщений: 11,637
Записей в блоге: 1
Завершенные тесты: 1
02.09.2015, 17:42 #15
1) Находите адрес функции LoadLibrary в своем процессе (GetProcAddress).
С вероятностью 99% он будет таким же и в дочернем процессе.

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

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

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

5) Из загруженной dll уже можно ставить перехваты.
Только делать это не нужно из DllMain, лучше создать отдельный поток.
2
02.09.2015, 17:42
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.09.2015, 17:42
Привет! Вот еще темы с ответами:

Как дождаться закрытия файла? - C++ WinAPI
Допустим открываем файл, а потом закрываем file.close(); Или открываем для чтения ресурсов и закрываем FreeLibrary(hModule); Так вот На...

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

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

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


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru