Hooker une fonction par injection de code

alecail

Membre confirmé
27 Décembre 2014
76
0
Salut,

Quelles sont les méthodes pour injecter du code dans une application ? Bien sûr je parle d'une application dont on a pas le code source.
Supposons qu'on ait une classe C avec cette methode: -(void) methodwithArgs: (id)sender
Je voudrais, remplacer methodwithArgs: par patchedMethodWithArgs:, qui aurait la même signature, qui appelerait la fonction originale, et qui ferait quelques trucs en plus. Le programme en question a un petit bug, et ça serait plus facile dans mon cas de le patcher.
 
Dernière édition:
Bonjour,

c'est seulement possible par exemple, quand on a le source de l'application et une library tierce dont on n'aurait pas les dites sources ; ce s'appelle du "swizzling". Dans votre cas, rien ne peut être fait, à part contacter l'auteur pour lui signaler le bug.
 
C'est bon, j'ai trouvé.
Il suffit de compiler une classe qui hérite de NSObject, et de faire le swizzling dans la methode +load ce cette classe. Il faut compiler la classe comme dynamiclib, et la charger avec DYLD_INSERT_LIBRARIES. Le code dans +load est exécuté au début du programme, je ne sais exactement quand, je pense pendant une boucle où toutes les classes reçoivent leur message +load. Après, on peut littéralement tout faire, vu qu'avec le runtime Objective-C, on a accès au méta programme via les fonctions d'introspection, et on peut trouver les classes et les methodes via: objc_getClassList, class_getName, class_copyMethodList etc.. et faire l'échange avec: class_getInstanceMethod et method_exchangeImplementations. On peut tout patcher a l'exécution. Je me suis aidé de class-dump pour trouver la méthode, et pour l'instant je NSLog les arguments avant d'appeler la méthode originale. il y a encore du boulot pour faire la correction à laquelle je pensais, mais c'est déjà un grand pas.

Maintenant je voudrais aussi rajouter un bouton dans l'interface, qui enverrait un message à une instance d'une certaine classe.. Je ne sais pas comment trouver une liste des objets instanciés appartenant à une classe donnée.
 
Bonjour,

pour l'interface c'est plus difficile surtout si l'application est signée ; lister les symboles avec nm(1) peut aider à identifier les appels ; tourner l'app dans une session debugger même si certains symboles sont cachés ; peut permettre d'identifier les adresses et remonter le fil ; pour le swizzling oui éviter de le faire sur une class existante ; rediriger les appels sur votre proxy ; mais toujours est-il qu'il faille bien determiner ce qui se passe dans la fonction originale et si celle-ci est assez compliqué ; sans le source c'est assez difficile voir parfois impossible d'ou ma premiere réponse ; vous pouvez aussi avoir quelques difficultés si le code originale est en obj-c++ ; https://github.com/smorr/Mach-O-Scope peut vous être utile ; pour inspecter le block et le jeux d'instructions présent.
 
OK. Et pour hooker une fonction C (i.e hors d'un objet) ?
Sinon je me demande si je ne vais pas trafiquer le runtime lui-même pour qu'il me donne les infos que je cherche. Après tout, il me semble que toute création d'objet passe tôt ou tard par un class_createInstance. Donc hooker cette fonction et attendre de voir passer une demande pour une classe qui m'intéresse. Ensuite, je stocke ces adresses et je les ai sous la main quand j'en a besoin. Ça reste théorique, je n'ai pas encore essayé sur une application concrètement.. mais a priori tout le monde joue avec les mêmes règles.
Et pour l'instant je n'ai pas réellement besoin de RE le code des méthodes, juste de les hooker ou regarder quelles autres méthodes elles appellent.
 
Dernière édition:
Bonjour,

pour votre première question: soit avec une définition weak soit avec dlsym et le même processus de preload ; -> voir DLOPEN(3) (*)
pour la seconde DTRACE(1) vous permettra de faire/d'obtenir ce que vous voulez voir: les appels de class_createInstance et leurs contextes , il est certain que vous pouvez re-compiler un objc-rt modifié ; et changer le ``linkage soit en preload (* cela dépend si c'est une librairie référencée directement ou une dépendance [[lib de lib]] voir flat_namespace, les deux questions étant liées ) ; soit directement avec install_name_tool(1) en éditant les liens du binaire que vous pouvez lister en utilisant otool -L OTOOL(1)

édition:

j'ai trouvé une discussion qui pourrait vous intéresser:

http://stackoverflow.com/questions/...-msgsend-doesnt-print-the-receiver-class-name
 
Dernière édition: