There is no risk involved in this article, but a letter has a mechanism to detect BundId, so it is recommended not to log in in large numbers

This paper is based on the application of re-signature

IOS reverse application re-signature + wechat re-signature combat 1

IOS Reverse Shell Script + Script Re-signature 2

Tool: yololib+class_dump 3 Password: 8Ujj

First, initial injection

There are two ways to inject code: through the FrameWork and dylib

1. The script is re-signed

Follow the iOS reverse Shell script + Script re-signature 1 Re-signature

2. The FrameWork is injected

2.1 the new FrameWork

Add a Framework in Xcode File->Target

2.2 Creating a class in the FrameWork

2.3 Adding a Load method

This is not enough; DYLD dynamically loads Frameworks in a project, but not the current FrameWork

2.4 Run and compile

Ensure that the FrameWork is placed in the FrameWorks directory

2.5 Yololib injection into the dynamic library

You are advised to copy and paste yololib to the /usr/local/bin directory. You can call yololib anytime and anywhere

Enable the last line of app.sh (note changing the FrameWork name)

yololib”
T A R G E T A P P P A T H / TARGET_APP_PATH/
APP_BINARY””Frameworks/XXXX.framework/XXXX”

2.6 run

Not surprisingly, ❎❎❎❎❎❎❎❎❎❎ will be printed

3. The dylib injection

It’s just a Target

3.1 the new Library

3.2 Modifying the BaseSDK of dylib

3.3 Changing the Dylib signature

I’ll change it to iPhone Developer

3.4 Adding a Dependency

3.5 Running and Compiling

Adding them is half the battle

3.6 Modifying a Script

yololib”
T A R G E T A P P P A T H / TARGET_APP_PATH/
APP_BINARY””Frameworks/libFXHook.dylib”

3.7 run

Print ❎❎❎❎❎❎❎❎❎❎(sometimes error “image notound”, re-run FrameWorks if dylib is included)

Ii. Method Swizzling for initial use

Definition 1.

In OC, the relationship between SEL and IMP is like the “table of contents” of a book. SEL is the method number, like the “title.” IMP is the real address of the method implementation, like the “page number.” There is a one-to-one correspondence. Method_exchangeImplementations (<#Method _Nonnull M1 #>, <#Method _Nonnull m2#>), The technique of swapping SEL and IMP with this function is called Method Swizzle.

I prefer to understand the relationship between SEL and IMP as the cover and book of the book. The original book of Three Kingdoms and Water Margin is the cover of Water Margin after the method exchange

2. Code demonstration

NSURL * url = [NSURLURLWithString: [@ "www.Felix.com/ learn" stringByAddingPercentEncodingWithAllowedCharacters: [ NSCharacterSetURLQueryAllowedCharacterSet]]]; NSLog( @"%@",url);Copy the code

For example, if the above code seems tedious, you can use Method Swizzling

2.1 Creating an NSURL classification

2.2 Method Exchange

#import <objc/runtime.h> @implementation NSURL (FXUrl) + (void)load URLWithString = class_getClassMethod( self, @selector(URLWithString:)); Method FXURLWithString = class_getClassMethod(self, @selector(FX_URLWithString:)); // Swaps method method_exchangeImplementations(URLWithString, FXURLWithString); } + (instancetype)FX_URLWithString:( NSString*)string { NSURL*url = [ NSURLFX_URLWithString:string]; if(! url) { string = [string stringByAddingPercentEncodingWithAllowedCharacters:[ NSCharacterSetURLQueryAllowedCharacterSet]]; } return[ NSURLFX_URLWithString:string]; } @endCopy the code

Question 2.3 points

① Why should classification be used to do method exchange?

This will be mentioned below

Is the custom FX_URLWithString recursive?

A: The load method is executed earlier. The method swap has already occurred when FX_URLWithString is called. If you want to call FX_URLWithString, you should call URLWithString

You see the officer may feel too simple, then back to the signature project began to focus

Goal: Click the “Register” button to disable it

1. Obtain the object name and method name

As mentioned in the previous article, selecting the control prints the corresponding information by address (possibly showing the object name and method name directly)

2. Export MachO headers using class-dump

The MachO file is in the compiled IPA package

3. Search for header file view method declarations

Sublime is used here, looking for the class globally (if you can’t find it, look for the parent) and then for the method

4. Swap methods

Continue in the FrameWork injection code in section 1

#import "InjectCode.h" #import <objc/runtime.h> @implementation InjectCode + ( void)load { Method oldMethod = class_getInstanceMethod(objc_getClass( "WCAccountLoginControlLogic"), @selector(onFirstViewRegister)); Method newMethod = class_getInstanceMethod( self, @selector(FX_onFirstViewRegister)); method_exchangeImplementations(oldMethod, newMethod); } - (void)FX_onFirstViewRegister {NSLog(@" want to register? Want to register first dozen money!" ); } @endCopy the code

Hook wechat — stealing login passwords

Objective: Click the “Login” button to obtain the account and password and continue to log in

1. The analysis

Print the address to go to the header file list to find declared methods

Found this is a method with no parameters, so where to get the account and password?

We can look for clues in the Viewcontroller variables

Two suspicious instance variables _textFieldUserNameItem and _textFieldUserPwdItem were found

So if I look at WCAccountTextFieldItem and I don’t see anything that actually makes sense, why don’t I look for the parent class

The WCUITextField *m_textField instance variable looks a little useful

How to determine if it is the account and password we are looking for?

Enter the account and password and debug it on ViewDebug

As shown in the figure below, we have found the direction to write Hook code

(lldb) po 0x133800600

< WCAccountMainLoginViewController:0x133800600>

(lldb) po [(WCAccountMainLoginViewController *) 0x133800600valueForKey:@ "_textFieldUserNameItem"]

< WCAccountTextFieldItem:0x28231f180>

(lldb) po [(WCAccountTextFieldItem *) 0x28231f180valueForKey:@ "m_textField"]

< WCUITextField:0x13090d600; baseClass = UITextField; frame = ( 200; 34544); text = 'Felix'; opaque = NO; autoresize = W+H; tintColor = UIExtendedSRGBColorSpace 0.007843140.73333301; gestureRecognizers = < NSArray:0x280891650>; layer = < CALayer:0x280612560>>
Copy the code

2. Start the hooks

#import "InjectCode.h" #import <objc/runtime.h> #import "UIKit/UIKit.h" //@interface WCAccountTextFieldItem: NSObject // //@end @implementation InjectCode + ( void)load { Method oldMethod = class_getInstanceMethod(objc_getClass( "WCAccountMainLoginViewController"), @selector(onNext)); Method newMethod = class_getInstanceMethod( self, @selector(FX_onNext)); method_exchangeImplementations(oldMethod, newMethod); } - (void)FX_onNext {// /// declare WCAccountTextFieldItem, WCAccountTextFieldItem * Account = [self valueForKey:@"_textFieldUserNameItem"]; // /// Import UIKit framework // UITextField *accountTF = [Account valueForKey:@"m_textField"]; UITextField*accountTF = [[ selfvalueForKey: @"_textFieldUserNameItem"] valueForKey: @"m_textField"]; UITextField*passwordTF = [[ selfvalueForKey: @"_textFieldUserNameItem"] valueForKey: @"m_textField"]; NSLog(@" Account: "%@" n Password: "%@" ", accounttf.text, passwordtf.text); [ selfFX_onNext]; } @endCopy the code

As we await the magical moment with joy, a familiar smell arrives

Collapse reason: WCAccountMainLoginViewController cannot find FX_onNext method code, namely the original engineering WCAccountMainLoginViewController no FX_onNext statement

OC method calls have two hidden arguments: self (method caller) and CMD (method number). In the FrameWork, the IMP of onNext is replaced by FX_onNext. The page calls the login method to our custom method implementation. Then send the VC an FX_onNext message, which must be an unrecognized selector sent to instance

At this moment, the benefits of classification Hook are incisively and vividly reflected, directly add a method to the classification is done

3. Solve the crash and complete the Hook

3.1 class_addMethod method

Use the class_addMethod method to allow the original method to be called.

#import "InjectCode.h" #import <objc/runtime.h> #import "UIKit/UIKit.h" @implementation InjectCode + ( void)load { /** * Select * from class where id = 1; select * from class where id = 1; select * from class where id = 1; Types of representative @ selecter (can help document to look at the method) * / BOOLdidAddMethod = class_addMethod (objc_getClass (" WCAccountMainLoginViewController "), @selector(FX_onNext), FX_onNext, "v@:"); If (didAddMethod) {NSLog(@" add method succeeded "); Method oldMethod = class_getInstanceMethod(objc_getClass( "WCAccountMainLoginViewController"), @selector(onNext)); Method newMethod = class_getInstanceMethod(objc_getClass( "WCAccountMainLoginViewController"), @selector(FX_onNext)); method_exchangeImplementations(oldMethod, newMethod); IMP voidFX_onNext(idself, SEL _cmd) {UITextField*accountTF = [[selfvalueForKey: @"_textFieldUserNameItem"] valueForKey: @"m_textField"]; UITextField*passwordTF = [[ selfvalueForKey: @"_textFieldUserNameItem"] valueForKey: @"m_textField"]; NSLog(@" Account: "%@" Password: "%@" ", accounttf.text, passwordtf.text); SelfperformSelector: @selector(FX_onNext)] } @endCopy the code

3.2 class_replaceMethod method

Save the original method, using the replaceMethod method to the IMP of the original method overwrite

#import "InjectCode.h" #import <objc/runtime.h> #import "UIKit/UIKit.h" @implementation InjectCode + ( void)load { onNext = method_getImplementation(class_getInstanceMethod(objc_getClass( "WCAccountMainLoginViewController"), @selector(onNext))); class_replaceMethod(objc_getClass( "WCAccountMainLoginViewController"), @selector(onNext), FX_onNext, "v@:"); } IMP (*onNext)( idself,SEL _cmd); voidFX_onNext( idself, SEL _cmd) { UITextField*accountTF = [[ selfvalueForKey: @"_textFieldUserNameItem"] valueForKey: @"m_textField"]; UITextField*passwordTF = [[ selfvalueForKey: @"_textFieldUserNameItem"] valueForKey: @"m_textField"]; NSLog(@" Account: "%@" Password: "%@" ", accounttf.text, passwordtf.text); // use the original logic onNext(self,_cmd); }Copy the code

3.3 method_setImplementation method

Save the original method and override the IMP of the original method using the setImplementation method

#import "InjectCode.h" #import <objc/runtime.h> #import "UIKit/UIKit.h" @implementation InjectCode + ( void)load { onNext = method_getImplementation(class_getInstanceMethod(objc_getClass( "WCAccountMainLoginViewController"), @selector(onNext))); method_setImplementation(class_getInstanceMethod(objc_getClass( "WCAccountMainLoginViewController"), @selector(onNext)), FX_onNext); } IMP (*onNext)( idself,SEL _cmd); IMP voidFX_onNext(idself, SEL _cmd) {UITextField*accountTF = [[selfvalueForKey: @"_textFieldUserNameItem"] valueForKey: @"m_textField"]; UITextField*passwordTF = [[ selfvalueForKey: @"_textFieldUserNameItem"] valueForKey: @"m_textField"]; NSLog(@" Account: "%@" Password: "%@" ", accounttf.text, passwordtf.text); // use the original logic onNext(self,_cmd); } @endCopy the code

Five, the Runtime API

// 1. Objc_xxx series functions

// Function name function function

Objc _getClass gets the Class object

Objc _getMetaClass gets the MetaClass object

Objc _allocateClassPair allocates space and creates classes (member variables can only be added after creation but before registration)

Objc _registerClassPair Registers a class (you can use the class to create objects after registration)

Objc _disposeClassPair unregisters a class

Objc _allocateProtocol Specifies the space creation protocol

Objc _registerProtocol Registers a protocol

Objc _constructInstance Constructs an instance object (invalid under ARC)

Objc _destructInstance destructInstance of an instance object (invalid under ARC)

Objc _setAssociatedObject associates an object with an instance object

Objc _getAssociatedObje*ct Gets the associated object of the instance object

Objc _removeAssociatedObjects clears all associated objects of the instance object

The objC family of functions focuses on macro usage, such as class and protocol space allocation, registration, and logout operations

// 2. Class_xxx series functions

Function name Function function

Class_addIvar adds an instance variable to the class

Class_addProperty Adds attributes to the class

Class_addMethod adds a method to a class

Class_addProtocol is the class compliance protocol

Class_replaceMethod replaces the implementation of a method of a class

Class_getName Gets the class name

Class_isMetaClass Determines whether it is a metaclass

Objc _getProtocol Gets a protocol

Objc _copyProtocolList Copies the list of protocols registered at runtime

Class_getSuperclass Gets the parent class of a class

Class_setSuperclass Sets the parent class of a class

Class_getProperty Gets a property of a class

Class_getInstanceVariable gets the instance variable

Class_getClassVariable Gets a class variable

Class_getInstanceMethod Method of obtaining an instance

Class_getClassMethod Gets the class method

An implementation of the class_getMethodImplementation method

Class_getInstanceSize Gets the size of the instance of the class

Class_respondsToSelector Determines whether a class implements a method

Class_conformsToProtocol Determines whether a class complies with a protocol

Class_createInstance Creates an instance of the class

Class_copyIvarList List of instance variables for copying a class

Class_copyMethodList The list of methods used to copy a class

Class_copyProtocolList List of protocols followed by copy classes

Class_copyPropertyList Property list of the copy class

The class_ family of functions focuses on the internals of a class, such as instance variables, attributes, methods, protocols, etc

// 3.object_xxx series of functions

Function name Function function

Object_copy Object copy(ARC invalid)

Dispose object_Dispose object (ARC invalid)

Object_getClassName Gets the class name of the object

Object_getClass Gets the Class of the object

Object_setClass Sets the Class of the object

Object_getIvar gets the value of the instance variable in the object

Object_setIvar Sets the value of the instance variable in the object

Object_getInstanceVariable Retrieves the value of an instance variable in an object (not available in ARC, using object_getIvar)

Object_setInstanceVariable Sets the value of an instance variable in an object (not available in ARC, using object_setIvar)

The objCET _ family of functions focuses on object perspectives, such as instance variables

// 4. Method_xxx series of functions

Function name Function function

Method-_getname Obtains the method name

Method _getImplementation Gets the implementation of the method

Method _getTypeEncoding Indicates the type encoding of the method

Method _getNumberOfArguments Obtains the number of method parameters

Method _copyReturnType Return type of a copy method

Method _getReturnType Gets the return type of the method

Method _copyArgumentType Specifies the parameter type of the copied method

Method _getArgumentType Gets the parameter type of the method

Method. _getDeion Description of the method

Method _setImplementation Implementation of the set method

Method _exchangeImplementations implementation of the replacement method

The method-_ family of functions focuses on the inside of a method, the parameters and return value types of the method and the implementation of the method

// 5. Property_xxx series functions

Function name Function function

Property _getName Gets the name of the property

Property _getAttributes Gets a list of attributes for an attribute

Property _copyAttributeList List of copied attributes

Property _copyAttributeValue Specifies the value of a copy attribute

Property _ is a class function that looks inside an attribute, such as its properties

// 6.protocol_xxx series functions

Function name Function function

Protocol _conformsToProtocol Determines whether a protocol complies with another protocol

Protocol _isEqual Checks whether two protocols are consistent

Protocol _getName Obtains the protocol name

Protocol _copyPropertyList Property list of the copy protocol

Protocol _copyProtocolList List of protocols to which a protocol is copied

Protocol _copyMethodDeionList List of methods used to copy protocols

Protocol _addProtocol Indicates that a protocol complies with another protocol

Protocol _addProperty Adds an attribute to a protocol

Protocol _getProperty Gets a property of the protocol

Protocol _addMethodDeion Adds a method description to the protocol

Protocol _getMethodDeion Gets the description of a method in the protocol

// 7. Ivar_xxx series functions

Function name Function function

Ivar _getName Obtains the IVAR name

Ivar _getTypeEncoding Indicates the type encoding

Ivar _getOffset Obtains the offset

// 8. Sel_xxx series functions

Function name Function function

Sel _getName Obtains the name

Sel _getUid Registration method

Sel _registerName Registration method

Sel _isEqual Checks whether methods are equal

// imp_xxx series of functions

Function name Function function

Imp _implementationWithBlock Creates an IMP from a code block

Imp _getBlock gets the code block in the function pointer

Imp _removeBlock Removes code blocks from IMP