![]() |
#1 |
Junior Member
![]() 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. |
![]() |
![]() |
![]() |
#2 |
Guru
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 875
Karma: 2676800
Join Date: Aug 2008
Location: Taranaki - 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. |
![]() |
![]() |
Advert | |
|
![]() |
#3 |
Junior Member
![]() 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. |
![]() |
![]() |
![]() |
#4 | |||
Wizard
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 2,801
Karma: 6990707
Join Date: May 2016
Location: Ontario, Canada
Device: Kobo Mini, Aura Edition 2 v1, Clara HD
|
Quote:
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:
Quote:
___ 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. |
|||
![]() |
![]() |
![]() |
#5 | |
Guru
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 875
Karma: 2676800
Join Date: Aug 2008
Location: Taranaki - NZ
Device: Kobo Aura H2O, Kobo Forma
|
Quote:
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. |
|
![]() |
![]() |
Advert | |
|
![]() |
#6 | ||
Wizard
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 2,801
Karma: 6990707
Join Date: May 2016
Location: Ontario, Canada
Device: Kobo Mini, Aura Edition 2 v1, Clara HD
|
Quote:
Quote:
|
||
![]() |
![]() |
![]() |
#7 |
Junior Member
![]() 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! |
![]() |
![]() |
![]() |
#8 |
Wizard
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 2,801
Karma: 6990707
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. |
![]() |
![]() |
![]() |
#9 |
Junior Member
![]() 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. |
![]() |
![]() |
![]() |
#10 |
Guru
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 875
Karma: 2676800
Join Date: Aug 2008
Location: Taranaki - 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. |
![]() |
![]() |
![]() |
#11 |
Junior Member
![]() Posts: 8
Karma: 10
Join Date: Jul 2021
Device: Kobo Libra H2O
|
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.
|
![]() |
![]() |
![]() |
#12 |
Guru
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 875
Karma: 2676800
Join Date: Aug 2008
Location: Taranaki - 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.
|
![]() |
![]() |
![]() |
#13 |
Junior Member
![]() 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. |
![]() |
![]() |
![]() |
#14 |
Wizard
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 2,801
Karma: 6990707
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. |
![]() |
![]() |
![]() |
#15 |
Junior Member
![]() 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.
|
![]() |
![]() |
![]() |
Thread Tools | Search this Thread |
|
![]() |
||||
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 |