Hacking the Weather Station – Part 2

Hacking the Weather Station – Part 2

In HACKING THE WEATHER STATION – PART 1 I indicated I wanted to attempt to communicate with the weather station over USB directly, bypassing the need to use the official software and the Tycon Windows library. To do this though I first wanted to understand just what the WeatherSmart software sends and receives itself.

My first port of call was to look around for some kind of USB sniffing software. I came across and installed USBlyzer which looks something like this:

usblyzer

However I couldn’t figure out how to get it to work properly. I could capture outgoing data easily but not incoming. The title was also in Chinese and I never could figure out why…

Back to square one.

Next idea was to disassemble the Tycon Windows library and see what made that tick. I chose that because it is less than 50kb and so had a smaller code footprint to sift through rather than WeatherSmart itself. However I’ve forgotten more x86 assembler than I remember as it’s been literally a decade since I last did any and so making any progress was slow going. The good thing was I could now see the external API calls it was definitely making, for example:

usb2300_disasm

Above we can clearly see a call to ReadFile amongst others. That got me thinking, rather than fight USB analyzers and assembler, why not just hijack the API calls it makes and point them at my own? That way I can capture all the parameters and data buffers.

I knew hijacking imported functions was possible, back in my Delphi days I’d used a package called madHook but I’d not done anything since, or in .NET. Lucky for me someone else had! After some Googling I came across a package called EasyHook which wrapped up the complicated hooking parts nicely for me.

EasyHook was fairly straightforward to use, for example first you get the address of the function you want to hijack, for example:

LocalHook.GetProcAddress("user32.dll", "MessageBeep");

Then you create a delegate that matches this function’s signature, like so:

[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
delegate bool MessageBeepDelegate(uint uType);

After that you will need to create an actual method that will act as the replacement function. You’d nearly always want to call the original function before you replaced it to keep the software functioning intact, to that end I use DllImport to get the original function pointer. What you end up with is something like this:

[DllImport("user32.dll")]
static extern bool MessageBeep(uint uType);

static bool MessageBeepHook(uint uType)
{
    return MessageBeep(uType); // Original call
}

After that you just have to apply the hook:

var hook = EasyHook.LocalHook.Create(
    EasyHook.LocalHook.GetProcAddress("user32.dll", "MessageBeep"),
    new MessageBeepDelegate(MessageBeepHook),
    null
);

hook.ThreadACL.SetInclusiveACL(new int[] { 0 });

Easy as that. Well, sort of. Things get a little more complicated when you factor in that this needs to happen in a process not my own and that I then have to send the captured data back to my own process to make sense of it.

Luckily EasyHook also provides classes to inject my new fangled hooks into another process and provides IPC mechanisms so I can communicate between them.

So I think my next task will be to hook at minimum the CreateFile, ReadFile and WriteFile API calls, this should give me enough ground to find out what is opened and what is sent and received. We’ll pick that up in the next post.

Leave a Reply