Tuesday, October 26, 2004

Hookers and services

<Technobabble>
No, this post is not related to prostitution. It is, in fact, related to Windows hooks - just as bad. Well, no, not nearly.. Anyway!

First, I'd like to mention that rattle's article on Systemwide Windows Hooks without external DLL is what first sparked my interest in this. Thanks!

I've mainly been experimenting with WH_KEYBOARD and WH_KEYBOARD_LL. As mentionned by MSDN, the NT-specific WH_KEYBOARD_LL delivers notifications in the process that set the hook. This is especially interesing because it means no external DLL need be created. On the the other hand, it makes you wonder about the numerous context switches that will happen upon keyboard input.

The second point I want to explore is exactly that - the delivery of notifications. As far as I can see, hooks use some kind of Windows messages. If, after hooking, the thread is Sleeping or SleepExing (to put the thread in an alertable wait state), hooks are not called. If, however, it is in a GetMessage or PeekMessage-based message pump, it processes messages successfully. What's more, MsgWaitForMultipleObjects returns WAIT_OBJECT_0+nCount (indicative of a message queued in the thread's message queue) when a hook is about to be called.

The strange behavior in this entire system is that, given an application which does not have any windows or other message sources than the hooks, GetMessage never returns! In fact, PeekMessage returns FALSE and never returns a valid message in *lpMsg. The hook procedure gets called, it appears, from inside them (in GetMessage and MsgWaitForMultipleObjects). I always suspected there was much more to GetMessage than meets the eye!

So, take all this, and throw most of it away. This only happens for WH_KEYBOARD_LL and WH_MOUSE_LL (and possibly WH_JOURNALRECORD and WH_JOURNALPLAYBACK). All other hooks seem to still require an external DLL. But wait... My original goal was to hook when the process was registered as a service. Things start to get even weirder in this case.

The service (it may be worth mentionning that it is set as an "interactive service" - interaction with the desktop is permitted) seems to be able to use WH_KEYBOARD, but still to a very restricted extent. (Normal processes simply didn't have their hook procedure called at all.) I observed that the hook procedure is called when the events are being delivered to a console window. As soon as events are received by other windows, the hook stops functionning, and switching back to a console window does not "re-enable" it. (Note that the message processing is still necessary for services.)

Soon to come... Hooking in other desktops and window stations. Probably yet another ugly beast, but I love it. I love it all.
</Technobabble>

Sunday, October 24, 2004

*chemistry nerd here*

Outrageously cool:
http://antoine.frostburg.edu/chem/senese/101/electrons/faq/orange-streetlights.shtml
.. especially "a nightmarish, monochromatic black-and-yellow effect". I'd like to see this.

Sunday, October 17, 2004

Windows, oh, Windows

<Technobabble>
For the past few hours, I have been struggling with WinPcap to send RAW packets over a WAN interface. It just doesn't want to.

PacketSendPacket returns FALSE. Peeking into Packet32.c, it first checks if the adapter on which the packet is to be sent is an NDIS adapter. Since WAN adapters don't qualify as such, a write isn't even attempted. If, however, I force a WriteFile of the packet, it fails with ERROR_INVALID_HANDLE (error 6). Go figure.

I was determined not to stop there. The NPF driver's IRP_MJ_WRITE handler is NPF_Write, in Write.c. I don't know enough about kernel programming or debugging to go further than staring at the handler blankly. I suspect NdisSend (line 129) might cause the ERROR_INVALID_HANDLE, because the handle refers to an NDISWAN adapter, rather than an NDIS adapter? (I'm not very familiar with the Windows network driver architecture, either.)

Any help would be highly appreciated!
</Technobabble>

Wednesday, October 13, 2004

Hacking Winamp... well not really

<Technobabble>
I've posted a small description of my creation on the Winamp forums, and I will duplicate it here, for I see no reason to reformulate what I've already written.


I was trying to get a program to retrieve the current track name from Winamp. To my disappointment, the IPC messages are divided in general-use and in-process messages. My first through was that I would have to go through the hassle of writing a general plugin, just for getting the track name!

However, there's another solution. Fortunately, Windows (NT+ definitely, not sure about 9x) allows you to read other processes' memory without having to inject a DLL in them. Later realizing that Winamp (probably) returns a static buffer from IPC_GETPLAYLISTTITLE relieved me, because that meant the lifetime of the buffer was rather long.

(For conciseness in my blog, you will need to click on the following link to see the actual code.)


...this general technique can be applied for most, if not all, "in-process" IPCs. For the messages that require you to pass a pointer to some data (ex. IPC_SETSKIN), one can use VirtualAllocEx to allocate memory in Winamp's process, and then WriteProcessMemory to transfer the data. The message can then be sent, and the memory can finally be freed with VirtualFreeEx. The downside is that VirtualAlloc/FreeEx are only supported in Windows NT and later.
</Technobabble>

Tuesday, October 12, 2004

Fatigue, addiction, school and poetry

Going to bed late is really bad for you, from a day-to-day productiveness point of view. Not only do you look like crap, you don't feel like doing anything, either.

But it keeps happening to so many of us, regularly. It's chronic lack of sleep, and it seems to be slightly addictive. Night after night, I don't feel like going to sleep because...?

In a way, this sleeplessness makes me somewhat drowsy, if not partly unconscious. Similarly to the way I imagine (since I've never experienced them) being under the influence of alcohol or drugs, specifically psychedelics, it renders you more "loose" from a social point of view and sheds light on certain things that might not have occured to you before. Some ideas are much more focused, and it seems like answers to various problems are within reach. But is the mind just playing tricks on itself? Are these ideas truly there, and can they really be of any use to us?

Could this (potentially illusional) state of enlightenment be the reason drugs are so widespread? Could it be a prime cause of some of their addictive properties? Let us extend this theory and say that lack of sleep is addictive. Oh, boy!

Well, I was going to talk about school and how I feel with respect to it, its place in my life, and so on, about an hour ago when I started writing this entry. But now I don't really feel like it. :P

To finish off, I'd like to include an extract of The Rhyme of the Ancient Mariner by Samuel Taylor Coleridge, written around the 1800's. A quick Google search for "The Rhyme of the Ancient Mariner" yields many pertinent results, should you choose to research it further.

Day after day, day after day,
We stuck, nor breath nor motion;
As idle as a painted ship
Upon a painted ocean.


Ciao!

Monday, October 11, 2004

TransmitFile

<Technobabble>
The TransmitFile API is friggin' cool!

Well.. it's pretty cool, but not developed enough, in my opinion. It's a great idea because efficiency goes up significantly - it saves at least two buffer copies, one ReadFile and one send. Also, it uses the standard asynchronous I/O mechanism (the OVERLAPPED structure) and, knowing that SOCKETs are in fact HANDLEs under cloak, you can use the standard wait functions on the handle returned by socket.

One of its problems, however, is that there's no way (that I know of) to query the progress of a TransmitFile (in fact, is there a way to generally query the progress of an asynchronous I/O operation?). The OVERLAPPED structure does not change until the end of the operation, which is why GetOverlappedResult is useless.
Attempting to retrieve the file pointer during the operation constantly returns a position of 4096 bytes into the file (why 4096, I don't know).
Is there some ioctl or socket option to query the number of bytes sent on a given socket?
Either way, there must be some file pointer somewhere in AFD.SYS (this is the driver that carries out the actual operation)!

I've conceived a hack for this, however. Instead of sending the entire file in one call, I use many calls that send "quantas". In the application, I dynamically adjust the quanta size to obtain roughly 500 ms per quanta (this allows for a reasonable refresh rate of the interface). Also, I found it prudent to provide "sanity checks" for the quanta size. My lower limit is 4096 bytes, while the upper limit is 262144 (256K) bytes.
</Technobabble>

Good morning!

This weekend of being alone at home has made me realize one very important thing. If my parents aren't around, there's no end to how late I will go to bed. Bad, especially since I plan on living by myself in university. *sigh*.

How's my blog?

I think I'm finally done fiddling with my blog template.. Hope you like the look!

My First Post... Ever!

Uhm, wow... I have a blog. Hum.
This blog has one purpose: to share and get feedback on, my ideas. Basically, this involves two main areas: programming, and personal matters.
Sharing and feedback play an equal role, in my opinion, so please do comment (anonymously, if you so wish) - I very much appreciate it.