Monday 16 January 2023

On small goals, big goals, and overwhelmings

 So, I got two comments on the last bit of blogging, which is not bad considering that I only showed it to one person.  Therefore, I will now go on a bit of a rant as to why they weren't neccessirily as useful as you might have thought, Dear Reader.


So, while I'd ultimately like to automagically pull things off of the garmin gps, there's not much use in reminding me of that when I'm not in a state of "why the hell am I doing this anyway".  At present, that goal feels a very long way off, and so I need to keep it not too much in mind, for if I do I may drown in the enormity of the path ahead.


When I start on something like this, the question is where to start.  I don't want to take apart the actual widget, and doing so won't neccessarily be all that useful anyway.  It is quite small, so there's not likely to be room for such nicities as debug connectors, much less ones that are well-marked.  That means I'm going to have to try to understand it through software reverse engineering.  I like doing software re, but it's a giant topic.  Question The First: what software?  A bit of looking finds a bit of windows software that might help, the android app, and no firmware updates.  (Actually *using* the windows software, I find an update for some translation bits, but I haven't attempted to caprure it, as I doubt it would be very useful.)


The windows software appears to be written using .... can't remember the name now, and I'm doing this as a blind typing blog entry again.  Anyway, the chromium project's web-browser-pretending-to-be-a-desktop application layer.  I'm not sure if it's using that instead of electron, or if electron is really just a small layer over cwf, but I didn't see mention of electron.  I haven't looked too deeply into it as of yet, but it's also not a terribly useful app, as it doesn't actually do anything with regards to getting images/video out of the camera, only doing software updates on it.  Thus, I only gave it a fairly cursory go.


The mobile software is a bit more promising.  I haven't chedked for iOS softare -- I don't use iOS, don't know terribly much about it, and googling for android apps gives you apk download sites quite easily, whereas with iOS I'd have to go through a lot more effort.


I've had mixed luck with reversing android apps in the past.  Ghidra is my prefered method of software re these days.  It is free, wchi is a very nice price point.  It is poewrful, and it's pluggable and scriptable.  It's also open source, so if I want to know a little more detail about what it is doing and it's API, I can always just read the source.  (How useful reading the source is varies a lot.  It's a big project, and it's not always easy to follow.)  However, support for android apps is ... poor, in my experince.  It really works much better the closer to an actual cpu you are, and android executables for this sort of thing -- apk files -- are actually a zip with one or more dex files, which contain postprocessed java vm class files.  While you can load a dex file into ghidra, what it gives you isn't actually terribly useful, and it only gets worse when you have a large application that is packaged into multiple dex files.  The reasons for this are a bit hard to explain, and I'm already plenty offtopic, so I smiply won't.


This time along, I discovered jadx, or possibly rediscovered it.  Anyway, jadx lets you load up an entire apk file, and it gives you a view on it that is actually *highly* useful, with Java code for the bits in the dex, and reasonably readable Java code at that.  Whiile there are a fair few places where the dex file has been obfuscated -- removing readable names and replacing them with extremely short and meaningless ones -- there's also plenty of bits that haven't been.  Reversing the code is largely then a matter of renaming things, and it's smart enough to let you just do that by pressing the 'n' key, and it will take care itself of changing all the references to the old name.  Lovely.


Except there's a problem.  When you look past the surface layers, most of the meat just ... isn't there.  Instead, there's generated wrapper classes using libdjnni.  (Or something like that.  I can't spell so good, even when I'm not typing blind.  And yes, I can type blind surprisngly well, thouhg I am opening my eyes every now and again to make sure my hands haven't gone into off-by-one mode and started typing gibberish.)


Libdjnii is a .... dropbox/foursquare, I want to say .... library that wrapps the java native interface for use with other languages, in this case, c__ in libgecko, mostly, which brings us back to ghidra.


So, libgecko is quite large.  60,897 kB, 59 and a half meg.  For this soft of thing, that's huge, and that's the somewhat smaller armv7 version, not the aarch64 version.  That may not sound big, but for executable code compiled on a real compiler for a real cpu, and not embedding a bunch o fgraphics (as far as I can tell, it doesn't have any, and doesn't even embed user-visible text).  It does, fortunately, have a lot of names and other ELF metadata.


So, it's good that we found where the meat is.  It's good that we have symbolic names for a lot of stuff.  What isn't so good is we now have a huge mess of code to try to look through.


So big, in fact, that when I loaded it up, started going through it, using WiseRenamer to find lots of jucy details, extending it in places, I got into a state where the ghidra interface would randomly lock up for long periods of time.  I'd created too many symbols and types, I think.


I evntually ended updoing that twice over, and switched from the armv7 copy to the aarch64 copy so it'd feel slightly less like I was repeating myself.  With that one, I got to a point where it started slowing down, but not to the point where it was unusable, and started implementing some things to make it less bad.  I cleared out most of the relocation information I'd parsed, which made ghidra have a much easier time of things.  I also removeed all the generated comments, and let WiseRenamer generate most of them again.  This not only gave ghidra  a bit less work to do, it removed some comments that turned out to be more distracting to me than actually useful.


On the plus side, WiseRenamer can now do a fair bit of parsing and extracting knowledge from elf (both 32 and 64) symbols and relocations.  On the minus side, after doing much of this, I realized that I wasn't finding the information I was looking for -- what library imports came from -- not because I was failing to find it due to the layers of pointy pointers, but because it's simply not there.


See, in macho (apple) and PECOFF (windows) executables, when you use a symbol from an external library, there's a record of "the symbol named x from the library named y".  (Mostly.  Obviously I am simplifying here, and pointedly, it's possible to import by ordinal number, not name, on windows.  This isn't common, except when doing mfc.  Sadly, I end up doing mfc rather often...)  ELF binaries / linking doesn't work this way.  Instead, there's a list of "we are using these libraries", and "we want to import a symbol with this name".  However, the two aren't linked together in any meaningful way.  Instead, every time you owant to load a symbol, the system checks for a symbol by that name in ever library.  (Again, a simplifiation.)  That means I'd have to do a much more complicated, and very different, bunch of stuff to allow you to hop between import and implementation easily in ghidra.  Annoying, but not fatal, at least in this case, because libgecko is big.  In fact, it's very big.  It contains a bunch o fstuff for things like map updates, alexa integration, at least one graphics lirbary, speach recognition and generation... oh, and links to liboffnav, which I'm pretty sure is for offline navigation using your locally downloaded garmin maps.  I mean, nice of them to give us all that, but not really needed for this application, which has nothing to do with navigation.


So, yeah, a lot of stuff to look at.  So far, I've managed to identify base URLs for a whole bunch of APIs, several of which seem to be oauth stuff.  


I think that's enough for now.  You might notice that I barefly even menteiond actually running things.  That's a big topic worthy of another post, which I will probably write at some point.  Dynamic reverse engineering work (to be technical abou tit) has it's own challenges, both genreal and increasingly specific.

1 comment:

  1. The goal of having you blog more about a subject seems to have been accomplished :)

    Garmin do make a ton of various navigation/gps/exercise widgets.. Presumably they have it all in one big library and didn't bother to extract the bits they need for the Drive app.

    I assume you looked for firmware updates for the thing itself?

    ReplyDelete