preface

This article will tell you how to do the anti-hook protection step by step, and then introduce you to a commonly used tool in reverse development MonkeyDev. It makes it easy to re-sign and inject code.

1. Anti-hook protection

When we HOOK OC methods of third-party apps, we usually use Method Swizzle. For example πŸ‘‰ uses the system-provided method_exchangeImplementations function to swap imp implementations of the two methods.

So if we write our own App, we’ll use fishHook, and we’ll swap method_exchangeImplementations with the custom function up front, then it’s going to be hard for a third-party attacker to implement a Hook.

Next, we demonstrate how to carry out anti-hook protection through a case.

1.1 Case Preparation

Use fishHook to exchange method_exchangeImplementations.

  1. New App project named asAntiHookSaid,The HOOK case. inViewControllerCreate two buttons on the pagebtn1andbtn2πŸ‘‡

Add the click event code πŸ‘‡

#import "ViewController.h" #import <HookMgr/HookMgr.h> @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; } - (IBAction)btnClick1:(id)sender {NSLog(@" button 1 call! ); } - (IBAction)btnClick2:(id)sender {NSLog(@" button 2 called! ); } @endCopy the code

⚠️ Note: Guard code is better written in the Framework because load method calls are faster than the main App and can be executed before someone else injected the dynamic library.

  1. addtarget, the choice ofFramework, namedHookManager, is set toThe dynamic libraryπŸ‘‡

  1. inHookManager, createAntiHookCodeClass and importfishhookπŸ‘‡

In 4.AntiHookCode.mWrite the following code πŸ‘‡ to the file

#import "AntiHookCode.h" #import "fishhook.h" #import <objc/message.h> @implementation AntiHookCode +(void)load{ struct rebinding reb; reb.name="method_exchangeImplementations"; reb.replacement=my_exchange; reb.replaced=(void *)&sys_exchange; struct rebinding rebs[] = { reb }; rebind_symbols(rebs, 1); } void (*sys_exchange)(Method _Nonnull m1, Method _Nonnull m2); Void my_exchange(Method _Nonnull m1, Method _Nonnull m2){NSLog(@"⚠️⚠️⚠️ detected HOOK⚠️ port ⚠️"); void my_exchange(Method _Nonnull M1, Method _Nonnull m2){NSLog(@"⚠️⚠️⚠️ detected HOOK⚠️ port } @endCopy the code
  1. In the project file directory, createPayloadFolder, build project, will be compiled afterAntiHook.appCopy toContent directoryUnder πŸ‘‡

  1. terminalThe use ofZip commandThat will bePayloadPackaging forAntiHook.ipaπŸ‘‡
zip -ry AntiHook.ipa Payload
Copy the code

1.2 Case Verification

Next, let’s test whether the anti-hook protection of AntiHook project is effective.

  1. Build App project named asHookDemoAs aHeavy signature App.

2. Similarly, addtargetTo createFramework, namedHook, is set toThe dynamic libraryπŸ‘‡

  1. inHook, createInjectclass

  1. Open theInject.mFile, write the following code πŸ‘‡
#import "Inject.h" #import <objc/runtime.h> @implementation Inject +(void)load{ Method sysClick1 = class_getInstanceMethod(objc_getClass("ViewController"), @selector(btnClick1:)); Method myClick1 = class_getInstanceMethod(self, @selector(my_btnClick1)); method_exchangeImplementations(sysClick1, myClick1); } - (void) my_btnClick1 {NSLog (@ "🍺 🍺 🍺 🍺 🍺"); } @endCopy the code

The next step is re-signing (see my previous article 10- Applying re-signing for details).

  1. willappReSign.shFiles,yololibFile, copy toProject rootπŸ‘‡

  1. Project rootCreated in theApp directory, copy the antihook. ipa file that you packaged to the App directory πŸ‘‡

In 7.HookDemo, the choice ofBuild PhasesEnter πŸ‘‡ in Run Script

./appReSign.sh

8. Real machine running project πŸ‘‡

Click button 1πŸ‘‡

As you can see from the above figure, the protection code in the πŸ‘‰ AntiHook project is in effect, and when the injected dynamic library uses method_exchangeImplementations, it can be detected and invalidate the attacker’s HOOK.

1.3 second case

Back to the AntiHook project using method exchange.

  1. To the AntiHook project, in theHookManagerIn the openAntiHookCode.hFile, write the following code πŸ‘‡
#import <Foundation/Foundation.h>
#import <objc/message.h>

CF_EXPORT void (*sys_exchange)(Method _Nonnull m1, Method _Nonnull m2);

@interface AntiHookCode : NSObject

@end
Copy the code
  1. Open theHookManager.hFile, write the following code πŸ‘‡
#import <Foundation/Foundation.h>
#import <HookMgr/AntiHookCode.h>
Copy the code
  1. inAntiHookIn the openViewController.mFile, write the following code πŸ‘‡
#import "ViewController.h" #import <HookManager/HookManager.h> #import <objc/runtime.h> @implementation ViewController -  (void)viewDidLoad { [super viewDidLoad]; Method sysClick2 = class_getInstanceMethod(self.class, @selector(btnClick2:)); Method myClick2 = class_getInstanceMethod(self.class, @selector(test)); sys_exchange(sysClick2, myClick2); } -(void)test{NSLog(@" this project HOOK, 🍺🍺🍺🍺🍺"); } - (IBAction)btnClick1:(id)sender {NSLog(@" button 1 call! ); } - (IBAction)btnClick2:(id)sender {NSLog(@" button 2 called! ); } @endCopy the code
  1. A:runProject, clickButton 2πŸ‘‡

As can be seen from the above figure, the sys_exchange function was successfully hooked in this project.

disadvantages

The above protection method is too simple. It’s going to store the string for method_exchangeImplementations in MachO’s string table. We can use Hopper to open the MachO file in hookManager. framework πŸ‘‡

So, the attacker can get throughstring, it is easy topositioningGo to the protection code, and crack it πŸ‘‰ as in our case above, inearlierThe timing of execution is critical to protectionFunction HOOKAnd letprotectivecodefailure. Therefore, do not use the above method.

Clever protection code should make it hard for attackers to detect and leave as little trace as possible. In the process of running the program, unknowingly kill it.

Second, the MokeyDev

MonkeyDev is a commonly used tool in reverse development, author Liu Peiqing, the original iOS OpenDev upgrade version, a non-jailbreak plug-in development integration magic!

It mainly consists of four modules πŸ‘‡

  1. Logos TweakπŸ‘‰ usetheosTo provide thelogify.plTools to*.xmFiles into*.mmFile is compiled. Integrated withCydia Substrate, you can useMSHookMessageExandMSHookFunctiontoHookThe specifiedAddress and OC functions
  2. CaptainHook TweakπŸ‘‰ useCaptainHook provides the header file to proceedOC functiontheHookAs well asAttribute acquisition
  3. Command-line ToolπŸ‘‰ can be created directly and run onPrison break equipmenttheCommand line tool
  4. MonkeyAppπŸ‘‰ This is automatic integration for third party applicationsReveal,CycriptandInjection dylibThe module. Support for debuggingdylibandThird-party applicationsTo supportPodTo integrate the SDK for your third application, you only need oneHit a shellAfter theIpa or APP fileCan be

2.1 installation MonkeyDev

2.1.1 theos installation

For example, Cydia Substrate is a tool in theOS.

  • Use the following command line to install πŸ‘‡
sudo git clone --recursive https://github.com/theos/theos.git /opt/theos
Copy the code
  • Viewing installation Results

Check the installation path /opt/theos/πŸ‘‡

⚠️ Note: Errors may occur during the installation. For details, see πŸ‘‡

Github.com/theos/theos…

2.1.2 Xcode configuration

  • Specify the Xcode
sudo xcode-select -s /Applications/Xcode.app
Copy the code
  • Install the MonkeyDev plug-in command
sudo /bin/sh -c "$(curl -fsSL https://raw.githubusercontent.com/AloneMonkey/MonkeyDev/master/bin/md-install)"
Copy the code

At this point, the installation is complete, and then restart Xcode. In Xcode, the corresponding function πŸ‘‡ of MonkeyDev will appear

⚠️ Note: xcode 12 types.xcspec not found error πŸ‘‡ was encountered during installation

Run the following command πŸ‘‡

sudo ln -s /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/PrivatePlugIns/IDEOSXSuppor tCore.ideplugin/Contents/Resources /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/SpecificationsCopy the code

2.2 Case Demonstration

Case 1: Use the MokeyDev plug-in to re-sign the application

  1. newMonkeyAppThe project is namedMonKeyDemoπŸ‘‡

After successful creation, the project contains App and injected dynamic library πŸ‘‡ by default

2. Will the previous caseAntiHook.ipaPackage, copy toMokeyDemoProject directoryTargetAppFolder πŸ‘‡

3. RunMokeyDemoThe project can be re-signed successfully installed πŸ‘‡

⚠️ error ld: file not found: /usr/lib/libstdc++. Dylib

Github.com/longyoung/l…

You can verify the successful installation of theOS in the project path πŸ‘‡

Case 2: Code injection

  1. inMokeyDemoDylib, click onMokeyDemoDylib.xmFile, selectObjective-C++ SourceπŸ‘‡

2. Open theMokeyDemoDylib.xmFile, write the following code πŸ‘‡

#import <UIKit/UIKit.h>

%hook ViewController

- (void)btnClick1:(id)sender {
   NSLog(@"🍺🍺🍺🍺🍺");
}

%end
Copy the code

⚠️ Note: Use Logos syntax. Details can be found in the official documentation

3. The real machine runs the project and detects HOOK code πŸ‘‡

Click button 1 to see the output πŸ‘‡

As verified by the figure above,HOOKSuccess, we reuse%origsaidCalling the original functionπŸ‘‡

- (void) btnClick1: (id) sender {NSLog (@ "🍺 🍺 🍺 🍺 🍺"); %orig; }Copy the code

At this point, we createMokeyAppIn theAntiHookItem, can be detectedmethod_exchangeImplementationsThe use of functions, instructionsProtection code valid.

Case 3: Protection of method_setImplementation

  1. Go back toAntiHookThe project,HookManager.frameworkIn the openAntiHookCode.mFile, change to the following code πŸ‘‡
#import "AntiHookCode.h" #import "fishhook.h" @implementation AntiHookCode +(void)load{ struct rebinding rebExchange; rebExchange.name="method_exchangeImplementations"; rebExchange.replacement=my_check; rebExchange.replaced=(void *)&sys_exchange; struct rebinding rebSetImp; rebSetImp.name="method_setImplementation"; rebSetImp.replacement=my_check; rebSetImp.replaced=(void *)&sys_setImp; struct rebinding rebs[] = { rebExchange, rebSetImp }; rebind_symbols(rebs, 2); } void (*sys_exchange)(Method _Nonnull m1, Method _Nonnull m2); IMP _Nonnull (*sys_setImp)(Method _Nonnull m, IMP _Nonnull imp); Void my_check(Method _Nonnull m1, Method _Nonnull m2){NSLog(@"⚠️⚠️⚠️ detects HOOK⚠️⚠️ snag "); } @endCopy the code
  1. compileAntiHookThe project,AntiHook.appPackage copy toMokeyDemoUnder theTargetAppFolder πŸ‘‡

3. The real machine runsMokeyDemoProject, HOOK code detected πŸ‘‡

Click on theButton 1πŸ‘‡

It turns out that the output is onlyThe original content. Therefore, whenmethod_setImplementationAfter the function is hooked,MokeyDevtheHOOKThe code willfailure!

The principle of MokeyDev Hook

Next, we analyze why MokeyDev’s HOOK code fails.

  • inMokeyDevIs used inSubstrate frameworkWe can do that in theMokeyDemoVerify πŸ‘‡ inside the package

  • inMokeyDemoDylib.xmThe use ofLogosSyntax to write the injection code πŸ‘‡

Also parsed by the libsubstrate. Dylib library πŸ‘‡

And in theMSHookMessageExInside the function, it’s throughget/setMethods,OC methodforHOOK. As shown in theMSHookMessageEx official website description.

So, when the method_setImplementation function is hooked, MokeyDev’s Hook code fails!

conclusion

  • The HOOK protection
    • usingfishHook, modifyMethod SwizzleCorrelation function
      • Is not recommendedUse, the traces of protection are too obvious. Method Swizzle cannot be used by other third party libraries
      • Protection code needsThe firstIs executed, otherwise will be HOOK first, the protection code fails
    • Written by the original projectThe Framework library, take precedence over the loading of the injected library, suitable for writing protective code
  • MokeyDev
    • The original iOSOpenDevUpgrade version, a non-jailbreak plug-in development integration magic
    • useSubstrateThe framework
    • The underlying throughget/setMethods,OC methodforHOOK