Feeds

Change your views: OS X tags exploited

Apple windows insider

Providing a secure and efficient Helpdesk

Mac Secrets Time to conclude our exploration of Apple's mysterious CoreGraphics framework. This time I'll show you how to change the behavior of windows by setting so-called window tags, and I'll exploit window properties to show how to snoop on the windows of another process.

Window tags represent another interesting little corner of the CoreGraphics subsystem. You can think of tags as essentially bit-flags that are associated with each window, but the way in which those bits are set and cleared is somewhat quirky, to say the least.

To set tags, you'd use this routine:

extern CGError CGSSetWindowTags (const CGSConnectionID cid, 
                 CGWindowID wid, int * tag, int tagSize);

In part one of this three-part mini-series I provided an explanation of the wid and cid parameters, which relate to the connection and ID of the window that you're concerned with.

The tag parameter is a pointer to a buffer that holds the tag information you want to set. The window server process allows for up to 64 bits of tag information. Most of the time, you're only concerned with the lower 32 bits in which case you'd point the tag parameter at a 32-bit integer containing the bit flags you want to set, and you'd set the tagSize parameter to 32. To write the higher-order tags, you'd point the tag parameter at a 64-bit quantity and set tagSize to 64.

I emphasize this because some folks think the last parameter should always be 32 - not true. It's usually 32, but I've seen 64 used in plenty of Apple code. If you set tagSize to less than 32, the routine will fail.

I suspect the reason for this rather odd interface is extensibility: it allows the number of tags to be arbitrarily increased without changing the interface. Needless to say, simply passing a 64-bit value would be a lot more straightforward.

To clear one or more tags, you'd use the CGSClearWindowTags routine defined below. In this case, you'd set all the bit flags that you want to clear in the memory pointed to by the tag parameter.

extern CGError CGSClearWindowTags (const CGSConnectionID cid, 
                 CGWindowID wid, int * tag, int tagSize);

Finally, to simply read the existing tag values, you'd use this routine:

extern CGError CGSGetWindowTags (const CGSConnectionID cid, 
                 CGWindowID wid, int * tag, int tagSize);

Note that when setting tag bits, you don't need to call CGSGetWindowTags and "OR in" the bit flags you want before calling CGSSetWindowTags. I've seen code that does this at www.cocoadev.com and it really represents a misunderstanding of how these routines work. The internal OR'ing and AND'ing is done for you - all you need do is supply a mask of the bits you want to set or clear.

All very interesting, but what does this buy us? As an example of what can be done, our demo uses a routine called CGSSetPreventsActivation to determine whether or not a window should activate when it's clicked.

The way this works should be pretty obvious. What's maybe not so obvious is that - internally - CGSSetPreventsActivation is simply a wrapper around CGSSetWindowTags, passing a tag value of 0x00010000 to the inner routine. You'll notice, by the way, that the window can still be activated by Alt-Tab'ing to it, even though it doesn't respond to mouse click activations.

In a similar vein, there are a group of related routines, CGSSetIgnoresCycle, CGSSetIgnoreAsFrontWindow, CGSSetDeferOrdering, CGSSetDeferActivation, which all work by calling CGSSetWindowTags. I don't pretend to understand what they all do - CGSSetIgnoresCycle disables Ctrl-F4 participation, by the way - but I'm on the case. For the terminally curious, the corresponding bit tag mask is show alongside each routine declaration in CGSPrivate.h.

Explore desktop icons

Desktop icons and Exposé thumbnails on display

There's really far too much in CoreGraphics to cover in a few short instalments, but there's one other interesting aspect I want to mention here: properties.

In effect, the window server maintains what you can think of as an NSDictionary object for each connection, and for each window. The per-connection properties stored in this dictionary have interesting key names such as "EnableWindowDoubleBuffering", "DisableDeferredUpdates" . "ClientMayIgnoreEvents" and "ClientIsOppositeEndian". I'd particularly advise you not to fool around with that last one.

You can read and write the connection properties using these two routines:

extern CGError CGSGetConnectionProperty(CGSConnectionID cid, CGSConnectionID targetCID, CFStringRef key, CFTypeRef *outValue);

extern CGError CGSSetConnectionProperty(CGSConnectionID cid, CGSConnectionID targetCID, CFStringRef key, CFTypeRef value);

The cid and targetCID parameters should normally be identical and obtained from CGSDefaultConnection. That's because only privileged programs like the Dock are able to manipulate the data relating to other connections than their own.

Finally, this month's demo project shows how to retrieve the window titles of all the windows that the Finder has open by using window properties. I would imagine that this is easily possible using AppleScript, but really that's not the point.

The key issue here is to demonstrate some of the undocumented CoreGraphics routines in action. If you step through the code in the debugger, you'll find that there are a surprisingly large number of Finder windows - each desktop icon, for example, is a Finder window. Use Quartz Debug and you'll find the same thing.

By using the undocumented property keys I've provided in CGSPrivate.h many other interesting window attributes can be retrieved.

As ever, this month's demo code can be downloaded from here. ®

Top 5 reasons to deploy VMware with Tegile

More from The Register

next story
New 'Cosmos' browser surfs the net by TXT alone
No data plan? No WiFi? No worries ... except sluggish download speed
iOS 8 release: WebGL now runs everywhere. Hurrah for 3D graphics!
HTML 5's pretty neat ... when your browser supports it
Mathematica hits the Web
Wolfram embraces the cloud, promies private cloud cut of its number-cruncher
Mozilla shutters Labs, tells nobody it's been dead for five months
Staffer's blog reveals all as projects languish on GitHub
'People have forgotten just how late the first iPhone arrived ...'
Plus: 'Google's IDEALISM is an injudicious justification for inappropriate biz practices'
SUSE Linux owner Attachmate gobbled by Micro Focus for $2.3bn
Merger will lead to mainframe and COBOL powerhouse
iOS 8 Healthkit gets a bug SO Apple KILLS it. That's real healthcare!
Not fit for purpose on day of launch, says Cupertino
Netscape plugins about to stop working in Chrome for Mac
Google kills off 32-bit Chrome, only on Mac
prev story

Whitepapers

Secure remote control for conventional and virtual desktops
Balancing user privacy and privileged access, in accordance with compliance frameworks and legislation. Evaluating any potential remote control choice.
Intelligent flash storage arrays
Tegile Intelligent Storage Arrays with IntelliFlash helps IT boost storage utilization and effciency while delivering unmatched storage savings and performance.
WIN a very cool portable ZX Spectrum
Win a one-off portable Spectrum built by legendary hardware hacker Ben Heck
High Performance for All
While HPC is not new, it has traditionally been seen as a specialist area – is it now geared up to meet more mainstream requirements?
Beginner's guide to SSL certificates
De-mystify the technology involved and give you the information you need to make the best decision when considering your online security options.