Warsztat.GD

Programowanie => Platformy => Windows => Wątek zaczęty przez: krzyfn w Październik 18, 2010, 20:52:44

Tytuł: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: krzyfn w Październik 18, 2010, 20:52:44
Tworzę aplikację w C#, która automatyzuje pewne procesy.
Chcę obsłużyć następujące okienko:

(http://codefromthe70s.org/images/kernelsigning_nosignature.png)

Za pomocą funkcji FindWindow:
http://msdn.microsoft.com/en-us/library/ms633499%28v=VS.85%29.aspx (http://msdn.microsoft.com/en-us/library/ms633499%28v=VS.85%29.aspx)

uzyskuję uchwyt do tego okna. Teraz chciałbym przy użyciu funkcji SendDlgItemMessage:
http://msdn.microsoft.com/en-us/library/ms645515%28v=VS.85%29.aspx (http://msdn.microsoft.com/en-us/library/ms645515%28v=VS.85%29.aspx)

wysłać do tego okna kliknięcie odpowiedniego przycisku. Niestety nie posiadam numerów ID tych przycisków i nie bardzo wiem jak je poznać. Czy ktoś wie co zrobić, aby poznać numery ID tych kontrolek? Albo może ktoś ma pomysł jak za pomocą WinApi obsłużyć kliknięcie jednego z przycisków?
Numery tych kontrolek, to na pewno nie 0, 1, 2...
Tytuł: Odp: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: Kos w Październik 18, 2010, 21:12:34
Niech mnie, jeśli się da. :)
Tytuł: Odp: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: krzyfn w Październik 18, 2010, 21:14:08
No skoro jest funkcja "SendDlgItemMessage" która jako parametr przyjmuje uchwyt do okna, ID kontrolki i wiadomość którą chcemy do tej kontrolki wysłać, to chyba jakoś się da co?

Wyczytałem coś ciekawego tutaj:
http://msdn.microsoft.com/en-us/library/bb775494%28v=VS.85%29.aspx#Common_Control_Messages (http://msdn.microsoft.com/en-us/library/bb775494%28v=VS.85%29.aspx#Common_Control_Messages)

Controls are child windows that send notification messages to the parent window when events, usually triggered by input from the user, occur in the control.

O ile dobrze to rozumiem, to znaczy że kontrolki takie jak 'button', 'label', etc. są po prostu 'child windows', a to oznacza że można się do nich dobrać np. przy pomocy 'EnumChildWindows' - swoją drogą dość zawikłana funkcja...
Tytuł: Odp: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: Kos w Październik 18, 2010, 21:20:26
Cóż, wydaje mi się, że w czasach Windows 7 w MS poleciałyby głowy za zabezpieczenie, które można obejść prostym SendDlgItemMessage.

Ale jakby Ci się udało, to od razu możesz z rozpędu obejść w taki sam sposób ostrzeżenia UAC (http://upload.wikimedia.org/wikipedia/en/5/51/Windows_7_UAC.png) i przywrócić erę nawału wirusów na Windowsach. Sprytne... Aż dziw, że też nikt jeszcze nie spróbował, nie? :)
Tytuł: Odp: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: krzyfn w Październik 18, 2010, 22:19:00
Nie do końca rozumiem co masz na myśli, ale jeśli chodzi o ingerowanie w zawartość okienek, to praktycznie wszechmogący jest ahk, który można kompilować do plików *.exe. Jeśli nie uda mi się tego zrobić za pomocą WinApi, to wyklikam sobie w ahk, jednak to nie jest zgodne z sztuką programowania, skoro główna aplikacja jest w C#.
Tytuł: Odp: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: Kos w Październik 18, 2010, 23:30:01
Hm. "praktycznie wszechmogący" as in "wiadomo, że da się nim ingerować w systemowe alerty bezpieczeństwa"?

Sprawa jest taka: Jeśli systemowe alerty bezpieczeństwa da się zatwierdzić programatycznie, to jest to bug w systemie (i nie powinieneś go wykorzystywać, dopóki nie piszesz exploita :)). Żyję w nadziei, że Win7 jest na tyle bezpieczny, że żaden z nas tego nie obejdzie.
Tytuł: Odp: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: Xirdus w Październik 18, 2010, 23:41:50
Jeśli ta aplikacja (http://www.mediafire.com/?r2zrmcmzxcfdx2j) działa, to nic nie jest bezpieczne.
Tytuł: Odp: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: Kos w Październik 18, 2010, 23:44:54
Jeśli ta aplikacja (http://www.mediafire.com/?r2zrmcmzxcfdx2j) działa, to nic nie jest bezpieczne.
Taaa? :) To spróbuj odpalić cokolwiek z prawami admina i jak wyskoczy alert UPC, to kliknij w "yes" tym swoim magicznym autoklikającym programem. Ups? :>

mwahahah, uwielbiam mieć rację :> ale dzięki za link, idę bić rekordy w grze Xirdusa >_>
Tytuł: Odp: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: krzyfn w Październik 19, 2010, 00:38:38
No dobra, ale odeszliśmy od meritum. Tu nie chodzi o żadne bezpieczeństwo, tylko pozbycie się głupiego okienka, które do niczego nie jest potrzebne, a na systemie Vista x64 jest taki bug, że pomimo wyłączenia sprawdzania podpisów to okienko i tak się pojawia.
Jeszcze jakieś pomysły jak się go pozbyć przy użyciu C#?
Tytuł: Odp: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: Kos w Październik 19, 2010, 00:45:01
Nie odeszliśmy od meritum. Wniosek jest prosty: nie da się, nie należy, odpuść. Sama Twoja chęć zrobienia tego jest błędna. Zastanów się nad sobą! :)
Tytuł: Odp: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: sqrczybyk w Październik 19, 2010, 13:47:38
IntPtr syn = WinAPI.GetWindow(ojciec, WinAPI.GW_CHILD);
IntPtr nastepnySyn = WinAPI.GetWindow(syn, WinAPI.GW_HWNDNEXT);
Ale Kos dobrze radzi, nie rób tego^^.
Tytuł: Odp: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: blizniak w Październik 19, 2010, 14:36:27
spokojnie możesz użyć AHK do tego jak najbardziej daje radę (widziałem skrypt w AHK który klikał dokładnie w takie okienko).

co do podglądania ID przycisków użyj Spy++ (standardowo z MSVC++) - proponuję odszukiwać buttony po ich "caption" lub czymś takim - wtedy możesz wyszukać taki child window (przycisk jest jak najbardziej okienkiem) i wysyłać mu wiadomość kliknięcia
Tytuł: Odp: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: krzyfn w Październik 20, 2010, 00:27:19
No tak, tylko idealnym scenariuszem byłoby dopisanie fragmentu kodu w C# do już istniejącej sporej aplikacji, bez dodatkowych kombinacji (jak np. AHK, Spy++, etc.), dlatego zależy mi na tym, aby zrobić to w czystym WinApi.
Dlaczego 'nie rób tego', skoro potrzebuję takiego klikadła, aby ułatwiło mi życie?
Jutro przetestuję propozycję sqrczybyka i sprawdzę jak się sprawuje funkcja EnumChildWindows.
Tytuł: Odp: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: sqrczybyk w Październik 20, 2010, 00:42:35
Chyba już masz wszystko co potrzeba... FindWindow wyszukujesz okna z belką tytułową. Napisałem jak dobrać się do dzieci, czyli kontrolek których szukasz. Jeśli są to zwykłe buttony, to powinno zadziałać: WinAPI.SendMessage(uchwytPrzycisku, WinAPI.BM_CLICK, IntPtr.Zero, IntPtr.Zero);
Tytuł: Odp: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: krzyfn w Październik 20, 2010, 14:12:41
Niestety:
IntPtr syn = WinAPI.GetWindow(ojciec, WinAPI.GW_CHILD);
IntPtr nastepnySyn = WinAPI.GetWindow(syn, WinAPI.GW_HWNDNEXT);
zwraca pusty wskaźnik, co by znaczyło, że te przyciski nie są 'child windows'
Tytuł: Odp: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: sqrczybyk w Październik 20, 2010, 14:21:18
Daj szybki przepis jak wywołać takie okienko, sprawdzę sam czy jest to możliwe.
Tytuł: Odp: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: krzyfn w Październik 20, 2010, 16:10:37
Szybki przepis jest taki, że musisz posiadać niepodpisane cyfrowo sterowniki do czegokolwiek, które chcesz zainstalować. Niestety nie mogę Ci dostarczyć moich sterowników, ponieważ nie będziesz mógł ich zainstalować (mam specyficzną kartę).

Aktualnie instaluję MS Visual Studio na maszynie na której debuguję. Spróbuję uruchomić Spy++ i dowiedzieć się więcej na temat tego okienka.
Tytuł: Odp: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: sqrczybyk w Październik 20, 2010, 16:24:37
Ściągnij -to- (https://docs.google.com/uc?id=0B23FbveYV53IYjI5Y2EyMGMtZjJhZC00YmQyLWI0NWItNzI2MzMzMWY5NTdi&export=download&hl=pl), kliknij Narzędzia => Szpieg => Lista otwartych okien => masz drzewko wszystkich okienek razem z oknami potomnymi. Będziesz wiedział jak dostać się do tych kontrolek.
Przy okazji zareklamowałem swój programik^^.
Tytuł: Odp: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: krzyfn w Październik 20, 2010, 16:34:52
Ok, mam to. Nie wiem jak wkleić obrazek, więc opiszę co mi pokazał Twój program:

#32770 [Windows Security]
 - Direct UIHWND []
  - CtrlNotifySink []
       Button [&Don't install this driver software]
  - CtrlNotifySink []
       Button [&Install this driver software anyway]
  Button [Start]

W skrócie - najpierw rozwijam [Windows Security] (do tego okna mam już uchwyt przez FindWindow), następnie rozwijam [UIHWND], następnie mam do rozwinięcia 2x CtrlNotifySink i w nich dopiero znajdują się buttony.

Jakieś pomysły jak się do nich dobrać?
Button Start, to pewnie 'See details'.
Dzięki za program.
Tytuł: Odp: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: sqrczybyk w Październik 20, 2010, 16:47:36
Czyli w takiej kolejności:
1. GW_CHILD
2. GW_CHILD
3. GW_HWNDNEXT
4. GW_CHILD
I masz uchwyt do Button [&Install this driver software anyway].

EDIT
Mam nadzieję że uwzględniłeś ukryte okna i zablokowane.
Tytuł: Odp: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: krzyfn w Październik 20, 2010, 17:25:29
Nie ;). Okazuje się, że "mój CtrlNotifySink" jest 9 w kolejności, a nie 2.
Wreszcie działa. Wielkie dzięki za pomoc - jednak da się.

Tylko zastanawiam się, czy można by jakoś lepiej to zapisać, zamiast 9x kopiować 'GetWindow...'
Tytuł: Odp: [WinApi]Kliknięcie przycisku w innej aplikacji
Wiadomość wysłana przez: sqrczybyk w Październik 20, 2010, 17:55:09
for (int i = 0; i < 9; ++i) GetWindow...^^.
A poważnie, to chyba jest inna wersja FindWindow, w której podajesz uchwyt okna rodzica i wyszukujesz dzieci. Możesz sobie zrobić rekurencyjną funkcję, która iteruje po wszystkich oknach (nie tylko jednego poziomu) za pomocą GW_CHILD i GW_HWNDNEXT, i sprawdza, czy klasa i tytuł okna się zgadza. Można też wykorzystać tę wspomnianą wcześniej funkcję EnumChildWindows.