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”
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”
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