Register Guidelines E-Books Search Today's Posts Mark Forums Read

Go Back   MobileRead Forums > E-Book Readers > Kobo Reader > Kobo Developer's Corner

Notices

Reply
 
Thread Tools Search this Thread
Old 07-31-2021, 06:44 AM   #1
halfdozen
Junior Member
halfdozen began at the beginning.
 
Posts: 8
Karma: 10
Join Date: Jul 2021
Device: Kobo Libra H2O
Finding hooks for NickelHook

Sorry if this has been asked already or if it's completely off topic, I've tried to search around but haven't found anything that offers any insight for finding hooks for using with NickelHook.

I've managed to use NickelHook to hook into QTs `addWidget` which is easy enough as the method signature is known from the documentation but waiting for a certain widget to be attached and looking through everything that gets added isn't ideal - though it's possible.

I'm hoping to hook into a function that's inside of `libnickel.so`, finding the method name isn't a problem (nm makes that easy), but finding the return type or arguments seems like a whole other ballgame.

I'm hoping someone has some suggestions or ideas on the best way to find the function arguments so I can use them with NickelHook - I'm looking for what writes the `More` menu so I can add my own entry to the menu.
halfdozen is offline   Reply With Quote
Old 07-31-2021, 08:09 AM   #2
sherman
Guru
sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.
 
Posts: 729
Karma: 1435688
Join Date: Aug 2008
Location: Auckland - NZ
Device: Kobo Aura H2O, Kobo Forma
You can get the demangled symbol names to know method argument types (beware of the "hidden" 'this' argument).

You're probably going to need to learn the basics of a dissasembler/decompiler to really get an idea however, especially for return types.

I believe geek1011 primarily uses "Hopper" (not free). My main tool of choice is Ghidra (open source). Both tools have their pros and cons. I believe Hopper has better dissasembly capabilities, whereas Ghidra tends to have better decompilation.

My workflow tends to be to look for the relevant class in Ghidra, go to the method I'm interested in, and use the decompilation as a guide to what the method arguments and return value is.

Note that decompilation is far from perfect, it's essentially an educated guess by the reversing tool in question. I've found it copes better with certain classes than others. If you have an idea on how Qt and C++ works, that can help you make educated guesses.

I'm afraid geek1011 is better at it than I am, but I can try to help where possible.
sherman is offline   Reply With Quote
Old 07-31-2021, 12:13 PM   #3
halfdozen
Junior Member
halfdozen began at the beginning.
 
Posts: 8
Karma: 10
Join Date: Jul 2021
Device: Kobo Libra H2O
Thanks that's helpful, I've tried a few disassemblers but they haven't been particularly useful so far though I've only had a quick play. I will give Ghidra a try, I did have a look at Hopper but I'm on a Windows machine so will leave that as a last resort.

Thankfully I've used Qt a lot for work so it's something (I'm sadly ...) very familiar with but injections into hidden code is something new to me.

From what I've tried as well it seems NickelHook doesn't support multiple hooks to the same "end point", whoever hooks last seems to win - not surprising based on the complexity this adds. As a quick way to get started I wanted to hook into the main navigation bar whilst keeping NickelMenu active. Since that worked but prevented NickelMenu from appearing I figured I could hook into NM's override function but for some reason the symbol for that can never be found (this was all a very quick hack to get started so I might of missed something.
halfdozen is offline   Reply With Quote
Old 08-01-2021, 05:55 AM   #4
geek1011
Wizard
geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.
 
Posts: 2,474
Karma: 5070988
Join Date: May 2016
Location: Ontario, Canada
Device: Kobo Mini, Aura Edition 2 v1, Clara HD
Quote:
Originally Posted by halfdozen View Post
Thanks that's helpful, I've tried a few disassemblers but they haven't been particularly useful so far though I've only had a quick play. I will give Ghidra a try, I did have a look at Hopper but I'm on a Windows machine so will leave that as a last resort.
Ghidra's decompiler is far better than anything but IDA, and it's free. But, I recommend disabling the option which hides namespaces (it's on by default) or you'll have a hard time actually reading the output since the class names will be lost. Also, beware that it often gets function arguments wrong and has pretty aggressive code restructuring. And, Ghidra's UI is somewhat clunky, making the disassembly view difficult to use efficiently (symbol search is iffy and doesn't have good fuzzy search or namespace support, navigation of xrefs requires a lot of clicks, and I find the formatting a lot harder to read). Also, if you ever need to do lower level patching, note that Ghidra doesn't detect PLT offsets for functions (you'll need to supplement the data with stuff from IDA, Hopper, or my symdump too).

Hopper has a nice disassembly view (it's a lot more information-dense than the others), but the decompiler is garbage in general (it's too conservative with restructuring and simplification, and it doesn't do much with types, so it's output doesn't usually provide any benefit). There are a few quirks to be aware of: the back/forward navigation doesn't work properly, it sometimes fails to detect procedures with interspersed constant data (you need to null it then recreate the procedure), patching bytes in it will break many features, it leaks memory when loading a binary (so you should restart it after the initial analysis), it often doesn't detect short strings correctly, it doesn't detect enums automatically, and references to constant QStrings (which are initialized in an entry point) aren't detected. Also, don't trust what it tells you about stack variables; it makes a lot of mistakes with libnickel for some reason compared to other binaries.

I'm currently considering switching from Hopper to Binary Ninja, but I haven't had much experience with it yet.

Also, if you ever need to look at the embedded Qt resources, I wrote a tool for that (it should work with any Qt4/5/6 binary): github.com/pgaskin/qrc.


Quote:
From what I've tried as well it seems NickelHook doesn't support multiple hooks to the same "end point", whoever hooks last seems to win - not surprising based on the complexity this adds.
That's a known bug, and I have a few ideas for how to fix it, but it hasn't been a high priority for me since the current mods hook relatively obscure functions which shouldn't need to be hooked my multiple mods. If you do decide to release what you're working on, ensure they don't conflict with the ones used by the current mods. If they do, tell me, and I'll fix this so there aren't issues from conflicts.

Quote:
As a quick way to get started I wanted to hook into the main navigation bar whilst keeping NickelMenu active. Since that worked but prevented NickelMenu from appearing I figured I could hook into NM's override function but for some reason the symbol for that can never be found (this was all a very quick hack to get started so I might of missed something)
To hook into NM's hook functions (which I strongly recommend against for anything but testing since that's an implementation detail which may disappear or change in incompatible ways in the future), you'd need to ensure NM is loaded first, then reference libnm as the library to hook.

___

And as a general piece of advice, always think about forwards compatibility, and how your mod will break if something changes. In general, if you have to break, only do it after a user interaction. If you must hook things which run at boot, fail earlier rather than later so the failsafe can catch it. And try as hard as possible to avoid doing things which may cause memory corruption if something changes internally (e.g. use mangled C++ symbols if you can, try to avoid functions which return stuff on the stack, allocate more memory than necessary when calling constructors, figure out as much as possible at runtime, hook symbols which are intrinsically related to what you're doing [e.g. if you're trying to add a menu, don't hook the view's constructor then try to access the widget at a specific offset; hook the menu's constructor or an add item function instead and go from there] with as few offsets required as possible). And, try to avoid the C++ standard library at all costs (it can create dangerous incompatibilities if the toolchain is updated, especially with how old Kobo's libs are right now) and use the Qt or C versions of things wherever possible.

In addition, remember to consider alternative approaches for whatever you're trying to do, and keep in mind that NH is intended only for modifications which directly extend existing Nickel functionality rather than ones which add new functionality. While NickelHook can be convenient, apart from temporary mods to test things locally, try not to use it if you can help it; it's not the right tool for most kobo-related things. If you're trying the change the behaviour of something built-in rather than extend it, it should be done in kobopatch, not NickelHook. If you just need to access Nickel functionality from another application, use a NickelDBus.

In short, NH should only be used to create standalone mods which supplement user-facing parts of Nickel's existing functionality, not to add unrelated features or change the intended behavior of Nickel. And, safety (both during installation, usage, updates, and failure) should always be the first priority, with backwards/forwards compatibility the second. Stack corruption (from return values, function parameters, incorrect reference usage) and explicit offsets should be avoided at all costs since they can cause hard-to-debug instability in other parts of Nickel which the failsafe can't catch.

___

Also, you may find the Itanium C++ ABI document, the ARM EABI spec, and the Thumb2 encoding manual useful.

Last edited by geek1011; 08-01-2021 at 06:30 AM.
geek1011 is online now   Reply With Quote
Old 08-01-2021, 06:11 AM   #5
sherman
Guru
sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.
 
Posts: 729
Karma: 1435688
Join Date: Aug 2008
Location: Auckland - NZ
Device: Kobo Aura H2O, Kobo Forma
Quote:
Originally Posted by geek1011 View Post
Ghidra's decompiler is far better than anything but IDA, and it's free. But, I recommend disabling the option which hides namespaces (it's on by default) or you'll have a hard time actually reading the output since the class names will be lost.
Just a quick note that this changed in Ghidra 9.2.x+, although I wouldn't use 9.2 for libnickel, for some reason the decompilation is very abridged compared to 9.1.x. Thankfully, Ghidra 10 resolved that, so is good to use.

As noted, I've found that the Ghidra decompilation sometimes struggles with arguments and returns, and if you're like me who hasn't (yet) managed to understand ARM assembly, you have to make some educated guesses.

I've found that the function call graph can be quite useful to see where and how functions and methods are called.
sherman is offline   Reply With Quote
Old 08-01-2021, 06:28 AM   #6
geek1011
Wizard
geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.
 
Posts: 2,474
Karma: 5070988
Join Date: May 2016
Location: Ontario, Canada
Device: Kobo Mini, Aura Edition 2 v1, Clara HD
Quote:
Originally Posted by sherman View Post
Just a quick note that this changed in Ghidra 9.2.x+, although I wouldn't use 9.2 for libnickel, for some reason the decompilation is very abridged compared to 9.1.x. Thankfully, Ghidra 10 resolved that, so is good to use.
Thanks for pointing that out. I'll have to try it when I have time.

Quote:
I've found that the function call graph can be quite useful to see where and how functions and methods are called.
Side note: beware of function calls hidden behind qt metacalls and signals.
geek1011 is online now   Reply With Quote
Old 08-01-2021, 06:41 AM   #7
halfdozen
Junior Member
halfdozen began at the beginning.
 
Posts: 8
Karma: 10
Join Date: Jul 2021
Device: Kobo Libra H2O
After playing with Ghidra last night, I'm amazed at how intuitive it was to get going and compared to the other disassemblers I tried it blew them out of the water. Found the `More` menu I was looking for, and the parameters for the function, it gets created in a similar way to the main navigation bar though a slightly different markup for the buttons inside. Will do a quick hack later to put some new buttons in there to test, then figure out how to make my own view that starts up from the `More` menu.

Making progressive! ��
halfdozen is offline   Reply With Quote
Old 08-01-2021, 06:50 AM   #8
geek1011
Wizard
geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.
 
Posts: 2,474
Karma: 5070988
Join Date: May 2016
Location: Ontario, Canada
Device: Kobo Mini, Aura Edition 2 v1, Clara HD
If you're adding stuff to the More menu, the safest way IIRC should be to hook the MoreView setupUi function, then walk the widget tree to add what you need.

Also, I recently had another idea for stuff like this, but I haven't had a chance to test it in NM yet: registering an event filter for QChildEvent, then handling everything from there with the widget tree instead of hooking the functions which build the UI.
geek1011 is online now   Reply With Quote
Old 08-01-2021, 07:00 AM   #9
halfdozen
Junior Member
halfdozen began at the beginning.
 
Posts: 8
Karma: 10
Join Date: Jul 2021
Device: Kobo Libra H2O
Didn't refresh the page before I wrote my last post, for the most part I'm just playing around to see what I can do but I have a few ideas of things to implement, a better statistics screen that shows more stats and possibly a solitaire game that generates winnable decks.

The main reason for using NickelHook was to implement directly into the Nickel platform (via the more menu), and to use the built in Qt without having to kill Nickel in order to start a new app / view. This last one was the downer for me after looking at how other standalone apps run on the Kobo, I don't want to kill Nickel in order to show a new view where as with NickelHook I can keep Nickel alive.

I have learnt the hard way about putting an error in my code that hooks up to Nickel, wiped my Kobo a few times - thankfully it's an old Aura H2O which I've just replaced so nothing lost.

I won't end up conflicting with NickelMenu or anything else, I might be tempted to raise a PR against NickelMenu that would allow NickelMenu to appear inside of the More menu, this would then conflict. I haven't looked into why it clashes, but I was thinking NickelHook could provide some common hooks to inject into, making it easier for other things to add into places that other NickelHook apps use - this is very much a case of thinking outloud rather than a solid suggestion.

I would be interested to know if theres away to do a standalone app that doesn't require Nickel to be killed whilst still relying on the platforms Qt, instead of building a new Qt.

I haven't seen any issues with Ghidra with the configuration I've used it seems to of disassembled pretty much everything inside of libnickel.so, finding the correct arguments, classes and possible names for everything. I had to disassemble a few times to get it to do this but for the most part it seems to be behaving well.
halfdozen is offline   Reply With Quote
Old 08-01-2021, 07:17 AM   #10
sherman
Guru
sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.
 
Posts: 729
Karma: 1435688
Join Date: Aug 2008
Location: Auckland - NZ
Device: Kobo Aura H2O, Kobo Forma
The big problem we've all been wrestling with is touch handling. If you can somehow solve THAT little problem...

EDIT: As in, we're still trying to understand how Nickel handles it.
sherman is offline   Reply With Quote
Old 08-01-2021, 07:26 AM   #11
halfdozen
Junior Member
halfdozen began at the beginning.
 
Posts: 8
Karma: 10
Join Date: Jul 2021
Device: Kobo Libra H2O
Quote:
Originally Posted by sherman View Post
The big problem we've all been wrestling with is touch handling. If you can somehow solve THAT little problem...

EDIT: As in, we're still trying to understand how Nickel handles it.
I can see how that is a pain point and another reason to rely on Nickel as much as possible as they obviously got this nailed down correctly, it's a shame we can't take advantage of the platform driver whilst using standalone apps as that would save a lot of headaches.
halfdozen is offline   Reply With Quote
Old 08-01-2021, 08:25 AM   #12
sherman
Guru
sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.sherman ought to be getting tired of karma fortunes by now.
 
Posts: 729
Karma: 1435688
Join Date: Aug 2008
Location: Auckland - NZ
Device: Kobo Aura H2O, Kobo Forma
You might also want to look at NickelDBus to see some of my experimentations. More specifically, see the (closed) PR's #10 & #11, issue #9 and the "NDBTouchWidgets" code in the 'advanced-dialogs' branch.
sherman is offline   Reply With Quote
Old 08-01-2021, 08:37 AM   #13
halfdozen
Junior Member
halfdozen began at the beginning.
 
Posts: 8
Karma: 10
Join Date: Jul 2021
Device: Kobo Libra H2O
Interesting work you've done there, I'm guessing from looking at your code that using standard Qt widgets doesn't handle touch correctly, and you end up needing to use the views / widgets that the Kobo UI has implemented in order to support touch?

I've not tried either yet, but noticed the same in NickelMenu that it uses the Kobo defined widgets rather than standard Qt widgets.
halfdozen is offline   Reply With Quote
Old 08-01-2021, 01:01 PM   #14
geek1011
Wizard
geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.geek1011 ought to be getting tired of karma fortunes by now.
 
Posts: 2,474
Karma: 5070988
Join Date: May 2016
Location: Ontario, Canada
Device: Kobo Mini, Aura Edition 2 v1, Clara HD
Yes, in general, that's the case. We also need to use Kobo widgets for consistency since the base Qt ones aren't styled.

Regarding touch, based on what we've found so far, the best place to start looking is at Qt gesture events and the Gesture* classes in libnickel.
geek1011 is online now   Reply With Quote
Old 08-01-2021, 03:32 PM   #15
halfdozen
Junior Member
halfdozen began at the beginning.
 
Posts: 8
Karma: 10
Join Date: Jul 2021
Device: Kobo Libra H2O
I can understand for styling as something like an icon button will be made up of a box or two with a label and icon, but it's odd that the standard Qt widgets don't work by themselves for touch events, was expecting the kobo platform driver would be fully implemented to handle touch for the Qt widgets like other platforms. I guess Kobo has a limited use case and don't need to implement everything, just a few standard widgets but still seems odd for them to approach it this way.
halfdozen is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
[Kindle Touch] Calibre Kindle Collections Plug-in Hooks sumpin Kindle Developer's Corner 68 11-30-2012 06:20 PM
Finding my posts melmac Feedback 5 08-30-2011 02:34 PM
Need help finding an e-reader please Pica Which one should I buy? 28 12-19-2010 09:26 AM
Hooks, They Ain't That Easy plumboz Writers' Corner 8 05-03-2010 08:28 PM
Need help finding this book Katosen Reading Recommendations 5 09-10-2009 09:42 PM


All times are GMT -4. The time now is 08:31 PM.


MobileRead.com is a privately owned, operated and funded community.