logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Monitorowanie rozpoczęcia / zakończenia działania aplikacji.

lord_dagoth 01 Lip 2012 12:11 1853 10
REKLAMA
  • #1 11060029
    lord_dagoth
    Poziom 25  
    Posty: 860
    Pomógł: 68
    Ocena: 6
    Witam,

    Mam przed sobą do rozwiązania następujący problem: potrzebuję wykonać kilka operacji na działającym procesie (nie uruchomionym przez moją aplikację) tuż po jego uruchomieniu oraz tuż przed jego zamknięciem (jeszcze zanim OS "posprząta" po procesie).

    Na wejściu mam informacje o nazwie .exe aplikacji (więc z pozyskaniem PID'a procesu nie będzie problemu).

    Moje pytanie: Czy ktoś wie, czy jest sposób żeby OS poinformował moją aplikację o tym, że aplikacja monitorowana zaczęła działać / zaraz zakończy działanie?

    Technologia i środowisko: aplikacje które będą monitorowane będą działać na systemach Win7+, język może być dowolny (ale najlepiej C++ / C#)

    Czy ktoś miał kiedyś styczność z podobnym zagadnieniem?
  • REKLAMA
  • #2 11060148
    Dżyszla
    Poziom 42  
    Posty: 7075
    Pomógł: 1095
    Ocena: 225
    Zaczęła działać - to zależy, co pod tym rozumiesz... Możesz np monitorować pojawienie się jakiejś konkretnej kontrolki.

    Zaraz zakończy - tu problem jest bardziej skomplikowany. Jeśli aplikacja coś specyficznego wyświetla - patrz wyżej. Jeśli nie, to pozostało by chyba przechwycenie komunikatu WM_CLOSE, ale nie jestem pewien, czy to aby możliwe...
  • #3 11060571
    lord_dagoth
    Poziom 25  
    Posty: 860
    Pomógł: 68
    Ocena: 6
    Kontrolki żadnej nie ma - to ma być niezależne od typu aplikacji (będzie ich wiele).

    W sumie pojawienie się procesu to nie będzie aż tak duży problem - mogę np co 1 sekunde sprawdzać wszystkie procesy.

    W jaki sposób można "przechwytywać" komunikację pomiędzy OS'em a jakimś procesem? Jest to możliwe?

    Czy można wymusić, żeby proces chcący się zakończyć "zaczekał" aż wykonam swoje operacje, a następnie się zakończył?
  • REKLAMA
  • #4 11060595
    sedr
    Poziom 17  
    Posty: 186
    Pomógł: 19
    Ocena: 3
    Masz przynajmniej kilka technik, dzięki którym możesz to uzyskać. Najprosciej będzie założyć hooka na proces.
  • REKLAMA
  • #6 11060811
    PDT
    Poziom 24  
    Posty: 511
    Pomógł: 79
    Ocena: 50
    lord_dagoth napisał:
    Mam przed sobą do rozwiązania następujący problem: potrzebuję wykonać kilka operacji na działającym procesie (nie uruchomionym przez moją aplikację) tuż po jego uruchomieniu oraz tuż przed jego zamknięciem (jeszcze zanim OS "posprząta" po procesie).

    Na wejściu mam informacje o nazwie .exe aplikacji ...


    Oczywistym sposobem jest podmiana wspomnianego .exe własnym programem, który uruchomi oryginalny .exe w trybie debugowania. Każdy OS wspiera takie rozwiązania. Panujemy nad przygotowaniem środowiska nowego procesu oraz przebiegiem jego wykonywania aż do zakończenia.

    Pozdrawiam

    PS Radzę podejrzeć jakikolwiek opensourcowy debugger i przerobić go pod swoje potrzeby.
  • Pomocny post
    #7 11061785
    Akane
    Poziom 27  
    Posty: 638
    Pomógł: 144
    Ocena: 33
    Oto 2 sposoby, których na codzień używam:

    1. HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows
    AppInit_DLLs = "myappinit.dll"

    W tym kluczu dodajemy nazwę własnego pliku dll (bez spacji). Jeżeli jest tam już coś, do oddzielamy nowy wpis spacją lub przecinkiem.

    Jak to działa: każda uruchamiana aplikacja, która ładuje user32.dll (np. otwiera jakieś okna), załaduje nasz dll, w którym należy sprawdzić, co za program właśnie się uruchamia - funkcja GetModuleFileName. Jeżeli to jakiś nieznany program, to z DllMain, podczas obsługi DLL_PROCESS_ATTACH, można od razu zwrócić FALSE, by wyładować dll. W przeciwnym razie (gdy to program który mamy zamiar monitorować) tworzymy nowy wątek (funkcją CreateThread) i zwracamy TRUE.

    Funkcja uruchamiana w nowym wątku powinna wykonać jakąś swoją pracę i zakończyć (return 0), zawiesić się (Sleep -1), bądź ciągle siedzieć w pętli.

    Gdy aplikacja przestanie działać, ale jeszcze będzie istnieć (podczas wywołania funkcji ExitProcess), dll zostanie o tym powiadomiony poprzez funkcję DllMain z argumentem DLL_PROCESS_DETACH. Tutaj nie można zbyt wiele zrobić, większość funkcji api będzie działać wadliwie, jedynie proste operacje, jak zapis do pliku, będą działać poprawnie.

    Nowo dodane dllki do tego klucza mogą być ignorowane aż do następnego restartu systemu.

    2. HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
    Tutaj tworzymy podklucz o nazwie identycznej jak monitorowany program, razem z końcówką .exe, a w tym podkluczu tworzymy wartość "debugger" typu string, ze ścieżką do programu, który zostanie uruchomiony zamiast programu monitorowanego, jako debugger.

    Przykład:
    HKLM\ ... \Image File Execution Options\notepad.exe
    debugger = winlogon.exe


    Efekt: uruchomienie notatnika spowoduje uruchomienie natywnego programu winlogon, który po pierwsze nie uruchomi się wcale (inna budowa programu), a po drugie, notatnik też się nie uruchomi, chyba że zmienisz mu nazwę.

    Praktyczniejszy przykład:
    HKLM\ ...\ Image File Execution Options\notepad.exe
    debugger = c:\moje_programy\app_monitor.exe


    Podczas uruchamiania notatnika, program app_monitor.exe zostanie uruchomiony z parametrem "c:\windows\notepad.exe", lub gdziekolwiek indziej notepad.exe się znajduje - katalog będzie inny. Notatnik nie zostanie uruchomiony, to app_monitor.exe ma o to zadbać.
    UWAGA! jeżeli spróbujesz uruchomić notatnik (z programu app_monitor.exe) ot tak po prostu, to ponownie uruchomisz sam siebie. Musisz albo najpierw usunąć cały string "debugger" z rejestru, albo uruchomić notatnik w trybie debugowania - CreateProcess z flagą DEBUG_PROCESS.

    Oba sposoby są dobre, pierwszego używam do naprawiania błędów w programach, lub dodawania do nich czegoś nowego, a drugi sposób służy mi głównie do blokowania aplikacji - nie chcę, by niektóre się uruchamiały.

    Trzeci sposób - powiązany z WMI, z takim oto zapytaniem:
    SELECT * FROM __InstanceCreationEvent WITHIN 10 WHERE TargetInstance ISA 'Win32_Process'

    Sporo przykładów znajdziesz w google.
  • #8 11065858
    lord_dagoth
    Poziom 25  
    Posty: 860
    Pomógł: 68
    Ocena: 6
    Super, o to właśnie mi chodziło!

    Spróbowałem sposób pierwszy, z tą DLL'ką i działa dokładnie tak, jak potrzebowałem.

    Dodam jeszcze tylko, żeby nasza DLL'ka była dołączana, trzeba ustawić klucz:
    LoadAppInit_DLLs = 1
  • Pomocny post
    #9 11066551
    beluosus
    Poziom 25  
    Posty: 362
    Pomógł: 123
    Ocena: 18
    Ścieżki w kluczu AppInit_DLLs powinny być w formacie Short FileName (tzw 8.3) - @Akane wspomniał o spacjach, a to tylko część prawdy. :)

    Dodam jeszcze, że ze względu na wczesny etap ładowania biblioteki musimy ograniczać się do funkcji oferowanych przez kernel32.dll. Pamiętam, że miałem z tym jakieś problemy, bo aplikacja była zależna od msvcp i msvsr (dll). Wystarczyło skorzystać z opcji Multi-threaded zamiast Multi-threaded DLL (Code Generation w Visual Studio). Polecam program Dependency Walker.

    Myślę, że to jest najłatwiejsze rozwiązanie, ale prócz tego co wspomniał @Akane można także:
    - sprawdzać czy jest uruchomiony proces i zrobić DLL Injection,
    - pod Entrypoint wrzucić kod ładujący naszą DLLkę,
    - zrobić Proxy DLL,
    - pewnie coś jeszcze się znajdzie.
    Możliwości jest wiele, większość z nich polega na dołączeniu DLLki do procesu.

    PS
    Nie wiadomo czy AppInit_DLLs będzie wspierane w przyszłych wersjach Windows (zastosowanie innej metody nie będzie wymagało wielkiego nakładu pracy, bo na szczęście kod DLLki może zostać [niemal] niezmieniony).
  • REKLAMA
  • #10 11067384
    lord_dagoth
    Poziom 25  
    Posty: 860
    Pomógł: 68
    Ocena: 6
    Kolejna rzecz jaką zauważyłem: dla 64 bitowych os'ów te klucze są w
    HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Windows
  • #11 11136745
    lord_dagoth
    Poziom 25  
    Posty: 860
    Pomógł: 68
    Ocena: 6
    Niestety w praniu wyszło, że podczas DLL_PROCESS_DETACH jest już za późno. Muszę wywołać swoją operację trochę wcześniej.

    Natknąłem się na mechanizm Windows Hooks.

    Spróbuję wykonać swoje operacje podczas message'a WM_QUIT.

    Miał może ktoś do czynieniaz windows hooks?

Podsumowanie tematu

✨ Użytkownik poszukiwał sposobu na monitorowanie rozpoczęcia i zakończenia działania aplikacji, które nie są uruchamiane przez jego program. Wskazano kilka technik, takich jak monitorowanie pojawienia się procesów, przechwytywanie komunikatów WM_CLOSE oraz użycie hooków do wstrzymywania działania procesów. Zasugerowano również wykorzystanie mechanizmu AppInit_DLLs do ładowania własnej biblioteki DLL, co pozwala na monitorowanie uruchamianych aplikacji. Użytkownik potwierdził skuteczność tego rozwiązania, a także zauważył, że dla 64-bitowych systemów klucze rejestru są zlokalizowane w innym miejscu. W końcu, użytkownik napotkał problem z wywołaniem operacji w odpowiednim czasie i rozważał użycie Windows Hooks do przechwytywania komunikatu WM_QUIT.
Wygenerowane przez model językowy.
REKLAMA