[C++/Win32] Window properties aanpassen

Pagina: 1
Acties:
  • 183 views sinds 30-01-2008
  • Reageer

  • traviandus
  • Registratie: Februari 2001
  • Laatst online: 25-03-2025
Kan ik de eigenschappen van een externe Window aanpassen?(die dus niet bij mijn proces hoort) Zodat ik bijvoorbeeld de caption-bar van een willekeurige window weg kan halen?

Verwijderd

Je kan met EnumDesktopWindows window handles opvragen van alle windows, dus niet alleen die van je eigen applicatie. Elke applicatie kan de eigenschappen van elk window veranderen, zolang het window van die gebruiker is (je kan dus niet op bijvoorbeeld een win2k met terminal services anderman's windows aan gaan passen).

Op http://unfix.org/projects/onatopp/ staat een tooltje wat van deze eigenschap van Windows gebruik maakt om alpha blending en 'on top' van windows in te stellen. Met spy++ (bijgeleverd met visual c++) kan je kijken wat voor eigenschappen een bepaald window heeft.

  • traviandus
  • Registratie: Februari 2001
  • Laatst online: 25-03-2025
Thanx!

Weet iemand misschien ook met welke WM_??? ik de caption bar van een Window kan verwijderen?

Verwijderd

(zo even uit 't hoofd, dus kan 't helemaal fout hebben)

Niet met een window message, maar met de API functies GetWindowLong() en SetWindowLong(). De caption van een window is onderdeel van de dwStyle die je opgeeft bij CreateWindow().

De code er voor zal vast iets in deze richting zijn:
code:
1
2
3
DWORD dwStyle = GetWindowLong(hWnd, GWL_STYLE);
dwStyle &= ~WS_CAPTION;
SetWindowLong(hWnd, GWL_STYLE, dwStyle);

edit:
Even opgezocht... er zit een grote maar aan:

Remarks
The SetWindowLong function fails if the window specified by the hWnd parameter does not belong to the same process as the calling thread.


Nou is daar ook wel omheen te programmeren (door een thread aan te maken in het proces wat de eigenaar is van dat window) maar dat is niet zo triviaal meer...

  • traviandus
  • Registratie: Februari 2001
  • Laatst online: 25-03-2025
Op donderdag 01 november 2001 12:37 schreef Qlone het volgende:
Even opgezocht... er zit een grote maar aan:

Remarks
The SetWindowLong function fails if the window specified by the hWnd parameter does not belong to the same process as the calling thread.
Da's nou jammer..
Nou is daar ook wel omheen te programmeren (door een thread aan te maken in het proces wat de eigenaar is van dat window) maar dat is niet zo triviaal meer...
Ik hoef het alleen maar te doen bij één specifiek window die in fullscreen mode zijn caption bar laat zien (staat zo lelijk op een beamer bij een presentatie). Dus mag het best een hack zijn..

Maar hoe doe ik zoiets, heb ik dan de HINSTANCE nodig van het proces :? ?

Verwijderd

[een halfuurtje prutsen verder]

Okee. De manier om zoiets te doen is via de window handle die je opvraagt achter het process id te komen van het proces waarvan je een window wilt aanpassen. Vervolgens open je dat proces met OpenProcess, laat je er je eigen thread in draaien met CreateRemoteThread (die dus wel die SetWindowLong() enzo mag uitvoeren) en pas je op die manier dat window aan.

Het klinkt heel eenvoudig, maar er komt nog wel wat programmeerwerk bij kijken. Ik heb even snel een voorbeeldprogrammaatje in elkaar gedraaid wat bovenstaande dus doet op een window handle die er hardcoded in zit, en die ik via spy++ heb opgevraagd voor een notepad.exe. Als je dit zelf gaat gebruiken moet je wel op een wat slimmere manier aan zo'n handle komen; ze zijn telkens anders.

Let op: onderstaande code is niet voor mensen met zwakke zenuwen of maagklachten >:)
code:
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
// Enge code...
//

#include "stdafx.h"
#include <windows.h>

#pragma check_stack (off)

typedef LONG (WINAPI *MyGetWindowLong)(HWND, int);
typedef LONG (WINAPI *MySetWindowLong)(HWND, int, LONG);
typedef LONG (WINAPI *MySetWindowPos)(HWND, HWND, int, int, int, int, UINT);

struct Info
{
    HWND hWnd;

    MyGetWindowLong mgwl;
    MySetWindowLong mswl;
    MySetWindowPos mswp;
};


static DWORD WINAPI MyThread(LPVOID lpParameter)
{
    Info *pInfo = (Info *)lpParameter;

    DWORD dwStyle = pInfo->mgwl(pInfo->hWnd, GWL_STYLE);
    dwStyle &= ~WS_CAPTION;
    pInfo->mswl(pInfo->hWnd, GWL_STYLE, dwStyle);

    pInfo->mswp(pInfo->hWnd, 0, 0, 0, 0, 0, 
        SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);

    return 0;
}

static void After() { }

int main(int argc, char* argv[])
{
    DWORD dwId;
    HWND hWnd = (HWND)0x00B9027E;           // Obtained using spy++...

    GetWindowThreadProcessId(hWnd, &dwId);

    HANDLE hProcess = OpenProcess(
        PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE|
        PROCESS_VM_READ, false, dwId);

    int nCodeSize = ((BYTE *)(DWORD)After - (BYTE *)(DWORD)MyThread);

    void *pRemoteCode = VirtualAllocEx(hProcess, 0, nCodeSize + 100, 
        MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);

    if (pRemoteCode) printf("Remote memory allocated OK\n");

    DWORD dwWritten;
    if (WriteProcessMemory(hProcess, pRemoteCode, MyThread, nCodeSize, &dwWritten))
        printf("Written successfully! (%d bytes)\n", dwWritten);

    HMODULE hUser32 = GetModuleHandle(__TEXT("User32"));

    Info *pData = (Info *)((BYTE *)pRemoteCode + ((nCodeSize + 4) & ~ 3));
    Info LocalData;

    LocalData.hWnd = hWnd;
    LocalData.mgwl = (MyGetWindowLong)GetProcAddress(hUser32, "GetWindowLongA");
    if (LocalData.mgwl) printf("LocalData: mgwl\n");
    LocalData.mswl = (MySetWindowLong)GetProcAddress(hUser32, "SetWindowLongA");
    if (LocalData.mswl) printf("LocalData: mswl\n");
    LocalData.mswp = (MySetWindowPos)GetProcAddress(hUser32, "SetWindowPos");
    if (LocalData.mswp) printf("LocalData: mswp\n");

    WriteProcessMemory(hProcess, pData, &LocalData, sizeof(Info), &dwWritten);
    
    DWORD dwTId;
    CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)(DWORD)pRemoteCode, (void *)pData, 0, &dwTId);

    //CreateThread(NULL, 0, &MyThread, (void *)hWnd, 0, &dwTId);

    Sleep(5000);

    return 0;
}

edit:
nu zonder al die tikfouten.

  • traviandus
  • Registratie: Februari 2001
  • Laatst online: 25-03-2025
Thanx! (again) :) :)

* traviandus houdt wel van enge code

Nu kan ik de window handle wel resolven door zijn naam, want die staat (in mijn geval) vast.

Misschien ook wel leuk om er een interface omheen te bouwen waarmee Window properties van alle desktop window kunnen worden veranderd. Helemaal niet zo moeilijk op deze manier!

:)

  • traviandus
  • Registratie: Februari 2001
  • Laatst online: 25-03-2025
Beetje door de code heen gelopen: Wel heeeeel eng!

Ooit eens een debugger geschreven ofzo!?

Maar ik heb nog een vraag:

De functie VirtualAllocEx() werkt alleen onder NT |:( en ik heb Win98. Alle andere functies werken wel onder 98, behalve dus dus dat remote alloceren. Het progje werkt zo dus niet...

Weet je daar iets op?

  • Primal
  • Registratie: Augustus 2001
  • Laatst online: 11-09 14:32
Ah, kijk een topic waar ik mijn kennis in kwijt kan. :)


Je kunt bij ieder window komen in je complete besturingssysteem. Je kunt dat doen door middel van system-hooks op de GetMessage of SendMessage functies. Op deze manier doet Spy++ dat bijvoorbeeld ook. Op die manier kun je dus dynamisch een window-handle opvragen, van het window dat je nodig hebt. Zoals eerder gezegd veranderen de window-handles continue, je kunt dus niet hardcoded een windowhandle in je source-code zetten, want dat gaat niet werken.
Je moet inderdaad wel gebruik maken van de SetWindowLong functie.

Ik heb bij een software bedrijf gewerkt die applicaties schreef ter beveiliging van het besturingssysteem, daar heb ik een module ontwikkeld welke diep in het besturingssysteem verankerd zat en o.a. de distributie van windows-messages kon analyseren/wijzigen/blokkeren etc.

Als ik tijd heb zal ik er vanavond nog eens uitgebreider naar kijken.

Ik weet niet of het op de manier kan zoals Qlone zegt, maar het ik denk dat hij er ook het nodige vanaf weet dat het ook werkt. Op de manier zoals ik het doe moet je een DLL schrijven die gemapped wordt in de process-adres space van het proces waarvan je het window wilt wijzigen. Dit werkt onder Windows 9x/Windows NT 3.5x en hoger/Windows 2000 en zelfs onder Win 3.1 (na enige aanpassingen) ;) .

"The fastest code, is the code that is never called."


  • traviandus
  • Registratie: Februari 2001
  • Laatst online: 25-03-2025
Op donderdag 01 november 2001 16:48 schreef Primal het volgende:
Ah, kijk een topic waar ik mijn kennis in kwijt kan. :)
D'r komen inderdaad maar weinig hardcore Win32 vraagjes voorbij.. gelukkig zitten er tussen al die script kiddies nog wat mensen die hier een beetje verstand van hebben.
Je kunt bij ieder window komen in je complete besturingssysteem. Je kunt dat doen door middel van system-hooks op de GetMessage of SendMessage functies. Op deze manier doet Spy++ dat bijvoorbeeld ook. Op die manier kun je dus dynamisch een window-handle opvragen, van het window dat je nodig hebt. Zoals eerder gezegd veranderen de window-handles continue, je kunt dus niet hardcoded een windowhandle in je source-code zetten, want dat gaat niet werken.
Je moet inderdaad wel gebruik maken van de SetWindowLong functie.
Ik zie nog niet gelijk het verband tussen een hook op SendMessage() en het wijzigen van de window style..
Op de manier zoals ik het doe moet je een DLL schrijven die gemapped wordt in de process-adres space van het proces waarvan je het window wilt wijzigen. Dit werkt onder Windows 9x/Windows NT 3.5x en hoger/Windows 2000 en zelfs onder Win 3.1 (na enige aanpassingen) ;) .
Aha, nou begin ik het een beetje te snappen. Dan roep je SetWindowLong() aan vanuit je hook proc als bv. het window wordt aangemaakt. Maar hoe implementeer ik zoiets?

Qlone: Jouw methode moet vast wel werken onder Win98, omdat bijna alles kan (WriteProcessMemory(), CreateRemoteThread()) behalve dan dat alloceren.. daar moet toch een workaround voor zijn?

Verwijderd

Ik weet niet of het op de manier kan zoals Qlone zegt, maar het ik denk dat hij er ook het nodige vanaf weet dat het ook werkt.
Op de manier zoals ik het doe moet je een DLL schrijven die gemapped wordt in de process-adres space van het proces waarvan je het window wilt wijzigen.
Het stukje code wat ik gepaste heb werkt uitstekend, maar natuurlijk :? weer alleen op NT/2k/XP... De oplossing met de DLL is haast net zo ranzig als even een thread starten in een ander proces, maar een stuk meer programmeerwerk...
De functie VirtualAllocEx() werkt alleen onder NT en ik heb Win98
Goeie reden om dat dan maar niet meer te gebruiken :) Ik weet wel een manier om om die remote alloc heen te werken overigens, maar dat is een wat klungelige oplossing (helemaal 9x stijl :)). De 'nette' oplossing onder win9x is om een DLL te maken die je mapt in de adresspace van het doelwit en die het werk te laten doen, maar dat is ook weer een boel werk...

Overigens, als je serieus bezig gaat met software ontwikkeling onder windows is het sowieso een goed idee om een NT-gebaseerde versie te nemen; dingen als debuggen en het opvangen van fouten in je code zijn een stuk robuuster daarop.
Ooit eens een debugger geschreven ofzo!?
Nee... het was eigenlijk die vraag van jou en het niet werken van de oplossing die ik in eerste instantie in gedachten had waardoor ik eens verder ben gaan nadenken en hier op ben uitgekomen. Nou zijn dit soort functies wel voornamelijk bedoeld om dingen als debuggen makkelijker te maken, en ze laten zich goed misbruiken als je eens wat creatiefs wil :)

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Op donderdag 01 november 2001 12:37 schreef Qlone het volgende:
Nou is daar ook wel omheen te programmeren (door een thread aan te maken in het proces wat de eigenaar is van dat window) maar dat is niet zo triviaal meer...
Een woord: QueueUserAPC.

En voor nog meer pret over hoe je dat proces nu eigenlijk gaat vinden: CreateToolhelp32Snapshot, Process32First en Process32Next. Daarmee kun je gewoon op exe-name het process met al z'n threads en handles opzoeken a la TaskManager.

Professionele website nodig?


  • Primal
  • Registratie: Augustus 2001
  • Laatst online: 11-09 14:32
Sorry Traviandus, ik had gisteravond geen tijd meer om even verder te kijken. Ik zal het proberen vanavond te doen.
Aha, nou begin ik het een beetje te snappen. Dan roep je SetWindowLong() aan vanuit je hook proc als bv. het window wordt aangemaakt. Maar hoe implementeer ik zoiets?
Kijk kijk, er begint hem al iets te dagen! Right on! Dat heb je goed gedacht ja. *D
De oplossing met de DLL is haast net zo ranzig als even een thread starten in een ander proces, maar een stuk meer programmeerwerk...
Sorry, maar dat ben ik niet met je eens. Je schrijft een normale DLL, die automatisch in het process-address space van een ander proces wordt gemapped. Dit gebeurt als je de system-hooks gaat gebruiken. De DLL krijgt de window-messages die bestemd zijn voor het betreffende window, dan eerst te zien, voordat deze worden door gestuurd naar de thread (die iedere applicatie heeft) die de afhandeling van window-messages verzorgd.

Maar het kan natuurlijk ook op een heel andere manier. Je kunt ook de handle naar de parent-window (de root) opvragen, is geloof ik altijd het desktop window. Daaronder hangt een boom-structuur van child-windows (alle andere applicaties). Je kunt deze structuur dan doorlopen en dan testen of je het goede window te pakken hebt (door bijvoorbeeld te checken op de window-titel).

Er zijn veel oplossingen, maar nogmaals ik heb nog niet veel tijd gehad om hier serieus over na te denken (ik werk namelijk ook :) ).
Overigens, als je serieus bezig gaat met software ontwikkeling onder windows is het sowieso een goed idee om een NT-gebaseerde versie te nemen; dingen als debuggen en het opvangen van fouten in je code zijn een stuk robuuster daarop.
Inderdaad ja. Helaas gold dat voor mij niet tijdens het ontwikkelen van de module. :) Ik heb zoveel systeem-crashes gehad, dat wil je niet weten. Maar ja, ik was natuurlijk wel wat 'low-level' bezig. ;)
En voor nog meer pret over hoe je dat proces nu eigenlijk gaat vinden: CreateToolhelp32Snapshot, Process32First en Process32Next. Daarmee kun je gewoon op exe-name het process met al z'n threads en handles opzoeken a la TaskManager.
Schot in de roos! *D

"The fastest code, is the code that is never called."


Verwijderd

Sorry, maar dat ben ik niet met je eens. Je schrijft een normale DLL, die automatisch in het process-address space van een ander proces wordt gemapped. Dit gebeurt als je de system-hooks gaat gebruiken. De DLL krijgt de window-messages die bestemd zijn voor het betreffende window, dan eerst te zien, voordat deze worden door gestuurd naar de thread (die iedere applicatie heeft) die de afhandeling van window-messages verzorgd.
Als ie automatisch in de adres space van de ander gemapped wordt gebeurt dat neem ik aan voor *alle* processen. Dat is wat ik tegen zulke oplossingen heb. Een kleine fout in zo'n DLL leidt dan al snel tot allerhande vage en moelijk te troubleshooten problemen in programma's.

Doet me denken aan een oude versie van zipmagic... Die kon zip files 'transparant' maken voor het systeem, dus zo dat alle programma's een zipfile kunnen zien als een gewone directory. Leuk... ware het niet dat er een bug in de driver die dat programma gebruikte zat waardoor *sommige* programma's ineens geen file meer geopend kregen.

Ander voorbeeldje... Nero. Nero installeert een filter driver waardoor op sommige systemen hibernate spontaan niet meer werkt.

Ik ben er dus gewoon uit principe tegen om dit soort hacks invloed te laten hebben op meer dan het te 'hacken' proces, zelfs als dat betekent dat de te gebruiken oplossing minder mooi is dan zou kunnen.

Het maken van filterende componenten (kernel of userspace) is vaak minder triviaal dan het lijkt; je dekt zelden alle situaties goed af. Ik heb zelf op dit gebied meer ervaring in kernel mode. Opgedaan bij het schrijven van een TDI filter driver om logging van tcp en udp verkeer mogelijk te maken, en ben lang bezig geweest voor dat ook de wat minder vaak voorkomende situaties goed afgehandeld werden.

(bovenstaande argumenten gelden dus in het algemeen tegen hooken en filteren, niet specifiek tegen de door Primal aangedragen mogelijkheid... dat 't niet verkeerd wordt opgevat :))
Een woord: QueueUserAPC
Nooit mee gewerkt... kan je net als ik deed een klein voorbeeldprogrammaatje posten wat de titelbalk van een window weg kan halen op die manier? Ben benieuwd...
En voor nog meer pret over hoe je dat proces nu eigenlijk gaat vinden: CreateToolhelp32Snapshot, Process32First en Process32Next.
Gaan we nu niet meer de kant op 'hoe sporen we een window/proces op'. Dat is geen probleem hier... het aanroepen van die SetWindowLong() was het oorspronkelijke probleem... de rest lukt wel :)

  • Primal
  • Registratie: Augustus 2001
  • Laatst online: 11-09 14:32
Kijk dit vind ik nu een gewone normale leuke discussie over het oplossen van problemen zonder elkaar de haren in te vliegen. :)
Op vrijdag 02 november 2001 17:21 schreef Qlone het volgende:

[..]

Als ie automatisch in de adres space van de ander gemapped wordt gebeurt dat neem ik aan voor *alle* processen. Dat is wat ik tegen zulke oplossingen heb. Een kleine fout in zo'n DLL leidt dan al snel tot allerhande vage en moelijk te troubleshooten problemen in programma's.
Dit klopt niet helemaal. Je kunt namelijk ook 'thread-specifik' hooks zetten. Dat wil zeggen dat je DLL alleen daar in de process-address space wordt gemapped bij het proces waarbij je het wilt.

Waar ik het helemaal met je mee eens ben is als je code buggie is, het tot zeer grote problemen binnen je complete besturingssysteem kan leiden. Een algemene systeem-crash tot gevolg. Daar heb je gedeeltelijk gelijk in. Ik raad ook nooit aan om system-wide hooks te plaatsen, alleen thread-specifik. Dat is toch minder ingrijpend.

Ok, beetje offtopic, maar leuk om toch op een normale manier van iemand anders te horen hoe hij over bepaalde zaken denkt. :)

"The fastest code, is the code that is never called."


  • traviandus
  • Registratie: Februari 2001
  • Laatst online: 25-03-2025
Ik zal vandaag eens aan de slag gaan met de aangedragen oplossingen. De resultaten post ik dan wel hier.
Goeie reden om dat dan maar niet meer te gebruiken Ik weet wel een manier om om die remote alloc heen te werken overigens, maar dat is een wat klungelige oplossing (helemaal 9x stijl ).
En wat is die klungelige oplossing?
Overigens, als je serieus bezig gaat met software ontwikkeling onder windows is het sowieso een goed idee om een NT-gebaseerde versie te nemen; dingen als debuggen en het opvangen van fouten in je code zijn een stuk robuuster daarop.
Daar heb je zeker gelijk in, maar ik ben niet zo veel bezig met Win32 software ontwikkeling. Bovendien moet de hack die ik probeer te maken draaien op een Windows 98 machine (daar kan ik niks aan veranderen)
Dit klopt niet helemaal. Je kunt namelijk ook 'thread-specifik' hooks zetten. Dat wil zeggen dat je DLL alleen daar in de process-address space wordt gemapped bij het proces waarbij je het wilt.
Dat zal ik dan maar proberen. Moet ik wel eerst een flink stuk lezen over Win32 hooks in MSDN, want daar weet ik nog (nauwelijks) iets van.

  • traviandus
  • Registratie: Februari 2001
  • Laatst online: 25-03-2025
Niet gelukt ;( maar wel bijna :)

Ik heb de hook methode geprobeerd. Alleen komen de messages die ik met SendMessage verstuur niet langs mijn hook proc. Messages van windows, zoals het bewegen van de muis over de window, gaan wél via mijn hook procedure.

Hier is mijn code:

De DLL
code:
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
// The DLL containing the hook

#include <windows.h>
#include <fstream.h>
#include <stdio.h>

#defineWM_HIDECAPTIONWM_USER + 1000

typedef LONG (WINAPI *MyGetWindowLong)(HWND, int);
typedef LONG (WINAPI *MySetWindowLong)(HWND, int, LONG);
typedef LONG (WINAPI *MySetWindowPos)(HWND, HWND, int, int, int, int, UINT);

struct Info
{
    MyGetWindowLong mgwl;
    MySetWindowLong mswl;
    MySetWindowPos mswp;
};

BOOL APIENTRY DllMain( HANDLE hModule, 
                 DWORD  ul_reason_for_call, 
                 LPVOID lpReserved
 )
{
    switch(ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
      break;
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
      break;
    }
    return TRUE;
}

extern "C"
LRESULT CALLBACK HookRemoveCaption(int nCode,WPARAM wParam,LPARAM lParam)
{
    CWPSTRUCT* cwp = (CWPSTRUCT*)lParam;
    if (cwp->message == WM_HIDECAPTION) {
      Info LocalData;
      HMODULE hUser32 = GetModuleHandle(__TEXT("User32"));
      LocalData.mgwl = (MyGetWindowLong)GetProcAddress(hUser32, "GetWindowLongA");
      LocalData.mswl = (MySetWindowLong)GetProcAddress(hUser32, "SetWindowLongA");
      LocalData.mswp = (MySetWindowPos)GetProcAddress(hUser32, "SetWindowPos");

      DWORD dwStyle = LocalData.mgwl(cwp->hwnd, GWL_STYLE);
      dwStyle &= ~WS_CAPTION;
      LocalData.mswl(cwp->hwnd, GWL_STYLE, dwStyle);
      LocalData.mswp(cwp->hwnd, 0, 0, 0, 0, 0,       SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);

    }
    return 0; // ..bypass other hooks..
}

De Applicatie
code:
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
#include <windows.h>
#include <stdio.h>
#include <string>
using namespace std;

#pragma check_stack (off)

#defineWM_HIDECAPTIONWM_USER + 1000

#define NBUF 512
char buffer[NBUF];

HWND theVictimHwnd = NULL;

BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam)
{
    GetWindowText(hwnd,buffer,NBUF);
    string wndStr(buffer);
    int loc = wndStr.find((char*)lParam);
    if (loc != string::npos) {
      // match found!
      theVictimHwnd = hwnd;
      GetWindowText(hwnd,buffer,NBUF);
      printf("patching \"%s\"...\n",buffer);
      return FALSE;
    }
   return TRUE;
} 

int main(int argc, char* argv[])
{
    HOOKPROC hkprc;
    HHOOK hook;
    HINSTANCE instDLL;
    DWORD pID;

    if (argc == 1) {
      printf("usage: remcapt <window title>\n");
      return 0;
    }

    // find the handle of the specified window
    EnumWindows(EnumWindowsProc,(LPARAM)argv[1]);
    if (theVictimHwnd == NULL) {
      printf("error: window containing \"%s\" not found\n",argv[1]);
      return 0;
    }

    // install a hook on the specified window
    instDLL = LoadLibrary("..//Dll//Debug//Dll.dll");
    if (instDLL == NULL) {
      printf("error: remcapt.dll not found.");
      return 0;
    }
    hkprc = (HOOKPROC)GetProcAddress(instDLL,"HookRemoveCaption");
    hook = SetWindowsHookEx(WH_CALLWNDPROC,hkprc,instDLL,
    GetWindowThreadProcessId(theVictimHwnd,&pID));
    if (hook == NULL) {
      DWORD Nbr=GetLastError();
      FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,NULL,Nbr,
MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),buffer,NBUF,
NULL);
      printf("error: failed to place hook --%s",buffer);
    }

    // hide caption bar
    SendMessage(theVictimHwnd,WM_HIDECAPTION,0,0);

    Sleep(3000);

    // exit
    if (hook != NULL) UnhookWindowsHookEx(hook);
    FreeLibrary(instDLL);
    return 0;
}

De WM_HIDECAPTION message die wordt verzonden gaat dus niet via mijn hook procedure. :?

  • Primal
  • Registratie: Augustus 2001
  • Laatst online: 11-09 14:32
Messages van bijv. de muis worden d.m.v. de PostMessage functie verstuurd. Deze functie wordt gebruikt in het geval dat er geen synchronisatie hoeft plaats te vinden. De functie wordt door het OS aangeroepen en meteen weer geretouneerd zonder te wachten op het resultaat. Dit in tegenstelling tot de SendMessage functie.

Je hebt dus op zijn minst 2 verschillende manieren van versturen/ontvangen van messages. Daarom heb je ook 2 type hooks nodig, nl.:

-WH_CALLWNDPROC
-WH_GETMESSAGE

Deze geef je dus op als parameter voor de SetWindowsHookEx functie (1 keer voor de CallWndHook en 1 keer voor de GetMessageHook).


De filter c.q. hook-functie voor bijvoorbeeld de messages die verstuurd zijn met PostMessage moet er qua opzet zo uitzien:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
LRESULT CALLBACK SpyGetMsgProc(INT iHookCode,WPARAM wParam,LPARAM lParam)
{
    PMSG pMessage;

    pMessage = (PMSG)lParam;

    // De variabele iHookCode geeft aan of de message 
    // zonder enige modificatie vertraging etc. 
    // doorverzonden moet worden aan de volgende filter-
    // functie in de hook-chain.
    if ((iHookCode >= 0) && (pMessage) && (pMessage->hwnd))
    {
      // Hier kun je dus je code, modificeren van de 
      // window-titel, window-eigenschappen wijzigen, 
      // messages verwijderen etc. In jou geval moet je 
      // dus weten (door te testen op bijv. window-titel) 
      // om welk window het gaat, anders ga je in ieder 
      // window rommelen. :) Ook leuk trouwens.
    }

    // Roep de volgende filter-functie in de 'hook-chain' 
    // aan.
    return(CallNextHookEx(NULL, iHookCode, wParam, lParam));
}

Het is belangrijk dat je in je 'hook' functies als laatste de message door-'passed' naar de volgende filter c.q. hook-functie in de hook-chain. Dat moet je doen middels de volgende functie aanroep:
code:
1
 return(CallNextHookEx(NULL, iHookCode, wParam, lParam));

Een voorbeeld van een filter c.q. hook-functie die message opvangt die met SendMessage verstuurd zijn is:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
LRESULT CALLBACK SpyCallMsgProc(INT iHookCode,WPARAM wParam,LPARAM lParam)
{
    PCWPSTRUCT pCwps;

    pCwps = (PCWPSTRUCT)lParam;

    // De variabele iHookCode geeft aan of de message 
    // zonder enige modificatie vertraging etc. 
    // doorverzonden moet worden aan de volgende filter-
    // functie in de hook-chain.
    if ((iHookCode >= 0) && (pCwps) && (pCwps->hwnd))
    {
      // Hier kun je dus je code, modificeren van de 
      // window-titel, window-eigenschappen wijzigen, 
      // bla bla
    }

    // Roep de volgende filter-functie in de 'hook-chain' 
    // aan.
    return(CallNextHookEx(NULL, iHookCode, wParam, lParam));
}

De filter c.q. hook-functies zitten dus in je DLL!

Vergeet niet de hooks te verwijderen als je applicatie stopt, als je ze niet meer nodig hebt of als het werk gedaan is (bijv. als je de eigenschappen van het window dat je zocht gewijzigd zijn). Doe je dit niet en laat je ze open staan als je applicatie beïndigd is, dan kan dit tot een systeem-crash leiden. Beware!

Verwijderen doe je met de functie UnhookWindowsHookEx.

Ik heb effe een klein stukje geschreven, de rest moet je zelf doen. :) Maar ik heb het idee dat je dat wel lukt, aangezien je toch redelijkerwijs begrijpt waar ik c.q. Qlone het over hebben.

Oh ja, kijk voor jezelf welke oplossing jij het beste vind, misschien een middenweg. In ieder geval is dit weer een goede leerschool voor je. ;) Uiteraard zijn er vele wegen die leiden tot dezelfde oplossing. Sommige zijn korter, andere langer. 8-)

Altijd vrij tot vragen.

"The fastest code, is the code that is never called."


Verwijderd

Op zaterdag 03 november 2001 19:35 schreef traviandus het volgende:
De WM_HIDECAPTION message die wordt verzonden gaat dus niet via mijn hook procedure. :?
Ehh om de verwarring dan maar wat groter te maken, je code werkt gewoon hier... heeft hier 1x gewerkt maar daarna niet meer!?

  • traviandus
  • Registratie: Februari 2001
  • Laatst online: 25-03-2025
Gelukt! :)

Ik heb de code maar even online gezet..

remcapt.cpp
remcapt_dll.cpp
remcapt.def

Ik heb dus de eerder geposte prog aangepast en de suggesties van Primal toegepast.

Qlone en Primal, bedankt voor jullie uitgebreide reacties!

  • Primal
  • Registratie: Augustus 2001
  • Laatst online: 11-09 14:32
Het werkt dus? Ok, great job! *D

"The fastest code, is the code that is never called."


Verwijderd

Wat doen jullie moeilijk? Je hoeft niets met threads of hooks te doen. In een paar regels, alle windows in het systeem transparant maken:

roep ergens

EnumWindows(EnumWindowsProc, 0);

aan, en laat het feest beginnen:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
    LONG windowSettings = GetWindowLong(hwnd, GWL_EXSTYLE);

    // --- Make window transparent
    if (lParam == 0)
    {
        windowSettings |= 0x80000;
        SetWindowLong(hwnd, GWL_EXSTYLE, windowSettings);
        SetLayeredWindowAttributes(hwnd, 0, 150, 0x2);
    }
    else
    {
        windowSettings ^= 0x80000;
        SetWindowLong(hwnd, GWL_EXSTYLE, windowSettings);
        UpdateWindow(hwnd);
    }

    return TRUE;
}

  • Primal
  • Registratie: Augustus 2001
  • Laatst online: 11-09 14:32
Op zondag 04 november 2001 17:30 schreef Kurzweil het volgende:
Wat doen jullie moeilijk?
Tjonge jonge, dat is nou jammer dat het toch nog verpest wordt. Meneer (as I assume) heeft niet goed gelezen. :Z

As I quote myself:
Oh ja, kijk voor jezelf welke oplossing jij het beste vind, misschien een middenweg. In ieder geval is dit weer een goede leerschool voor je. Uiteraard zijn er vele wegen die leiden tot dezelfde oplossing. Sommige zijn korter, andere langer.

"The fastest code, is the code that is never called."


  • traviandus
  • Registratie: Februari 2001
  • Laatst online: 25-03-2025
Wat doen jullie moeilijk? Je hoeft niets met threads of hooks te doen. In een paar regels, alle windows in het systeem transparant maken:
Dat zou toch niet mogen werken...
Op donderdag 01 november 2001 12:37 schreef Qlone het volgende:
Remarks
The SetWindowLong function fails if the window specified by the hWnd parameter does not belong to the same process as the calling thread.
Toch? :?

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 14-09 17:42

Gerco

Professional Newbie

Op maandag 05 november 2001 08:59 schreef traviandus het volgende:
Dat zou toch niet mogen werken...
Toch? :?
Jawel, aangezien je callback functie vanuit het systeem wordt aangeroepen en dus niet vanuit je eigen Thread context. Op die manier kun je dus dingen met alle windows doen.

Of het altijd werkt en of het netjes is is een hele grote 2e :)

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


Verwijderd

Of het altijd werkt en of het netjes is is een hele grote 2e
En ik heb er zeer sterk mijn twijfels bij. Zelfs als enumwindowproc aangeroepen wordt vanuit het systeem, dan is dat nog steeds niet vanuit een thread die 'eigenaar' is van zo'n window.

Verder weet ik niet of je dit getest hebt en op welke versie van windows, maar onder NT/2k/XP worden callbacks uitgevoerd in de context van je eigen proces, ivm beveiliging. (zou mooie boel zijn als je via een enum callback ineens system rechten zou hebben...)

  • traviandus
  • Registratie: Februari 2001
  • Laatst online: 25-03-2025
Op maandag 05 november 2001 11:21 schreef Qlone het volgende:
Verder weet ik niet of je dit getest hebt en op welke versie van windows, maar onder NT/2k/XP worden callbacks uitgevoerd in de context van je eigen proces, ivm beveiliging. (zou mooie boel zijn als je via een enum callback ineens system rechten zou hebben...)
Als het onder Win98 werkt vind ik het best...

Ik zal het straks ff proberen.

  • Primal
  • Registratie: Augustus 2001
  • Laatst online: 11-09 14:32
En dat is nu juist een voordeel van de oplossing/leermethode :) die ik heb beschreven, want daar gebeurt het dus wel.

De DLL die je geschreven hebt wordt namelijk gemapped in het process-address space van het proces waarvan je het wilt (thread-specifik) of van alle draaiende processen (system-wide). Bij een thread-specifik wordt de filter-functie aangeroepen vanuit de context van de thread (eigenaar van het window dat je wilt hacken) en bij een system-wide hook kan de filter functie aangeroepen worden vanuit de context van iedere thread in het OS.

Ik zal dus nogmaals het grote nadeel van 'system-wide' hooks aanstippen. Aangezien ze in de process-address space' van alle draaiende processen worden gemapped, zal dit tenkoste gaan van de performance (op de huidige systemen in de zin van Gigahertzen valt het niet meer zo op, maar op een 166Mhz. Pentium wel :) ). Ander nadeel is dat als je code buggie is je een proces dus helemaal omlaag kunt trekken, omdat ze in zijn address-space zitten. Leuk voor als je wilt hacken :). Dit zijn eigenlijk de 2 grootste nadelen, ook al eerder aangestipt door Qlone.

"The fastest code, is the code that is never called."


  • traviandus
  • Registratie: Februari 2001
  • Laatst online: 25-03-2025
code:
1
2
3
4
5
6
7
8
9
static BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
    //..blabla..

    SetWindowLong(hwnd, GWL_EXSTYLE, windowSettings);

    // ..
      return TRUE;
}
En ik heb er zeer sterk mijn twijfels bij. Zelfs als enumwindowproc aangeroepen wordt vanuit het systeem, dan is dat nog steeds niet vanuit een thread die 'eigenaar' is van zo'n window.
Dit werkt dus inderdaad niet. SetWindowLong() geeft 0 terug (op win98), hij failed dus.

Die CALLBACK functie gewoon een procedure net als iedere andere in je proces, maar met een andere calling convention (FAR) omdat hij van buiten je proces (het OS) moet kunnen worden aangeroepen.

Dus toch niet voor niks geweest om een DLL te schrijven. :)

Edit:
offtopic:
Kurzweil, lParam is toch altijd 0 hier? :?
[code]if (lParam == 0)
{
// ..
}
else
{
// hier komen we dus nooit?
}[/code]
Pagina: 1