Preface During the epidemic period, it is troublesome to punch in the clock at home, so the author thought of realizing this need. This paper describes the process from thinking to a complete analysis demonstration, and basically introduces the knowledge points involved, so the length is longer, and students who are familiar with relevant knowledge can skip by themselves. This article will demonstrate the complete process of actually reversing an application from Idea -> explore -> Debug -> injection. The effect is to modify the rules of Wi-Fi punch in and GPS position punch in, to meet the requirements of normal punch in not required Wi-Fi environment or GPS range. (This paper uses the latest version 5.0.6 of The current Nail. Subsequent updates may change the code logic so that the plug-in is no longer suitable for communication and learning purposes.) Disclaimer: This demonstration of the plug-in does not serve any commercial purpose, nor does it engage in any commercial activity. Note: • This article is based on the plug-in in jailbreak environment. • In non-jailbreak environment, re-sign application modification BundleID pin has corresponding monitoring, which is risky. • There are some changes to the mobile phone virtual location, is another way, this article will not cover. Leading knowledge • 1️, RSA encryption principle & cryptography &HASH • 2️, application signature principle and resignature (resigning wechat application) • 3️, shell script automatic resignature and code injection • 4 Discount, resigning application debugging and code modification (Hook) • 5 DISCOUNT and Mach-O file • 6️ principle and symbol table of Hook/fishHook • 7️ discount and LLDB from shallow to deep • 8️ discount and LLDB advanced part Chisel and Cycript • 9 Retail and prison break • Knowledge on adverse lead, In the article introduced by the author, there is still a lack of knowledge about the application of shell smashing and assembly instructions, which will be continued in the subsequent updates to form a complete set of chapters and columns. • Shell smashing and assembling parts of the content does not affect what we are going to do today with the nail plugin. • AppStroe install a genuine version of the nail. This article uses the latest version (5.0.6) • Reveal, Git-frida-ios-dump can be used to install the shell breaking tool. For details, see git-frida-ios-dump. Static smashing principle and the use and principle of different smashing tools) • Hoper-Mach-o analysis tool extraction password: X07n, DMG decompression password xclient.info. • Sublime Text – Lightweight Text editing tool with high global search efficiency. Reveal page debugging tool many reverse must start from the page, find the corresponding button method hook, Can help us clarify the code and business logic. As we all know, there is no encryption for projects that have been cracked or run by code on the phone. For such applications, we can directly Attach to the running application by Xcode -> Debug -> Attach to Process. This allows you to achieve view-debug. (For how to determine whether MachO application shell, use otool -l + MachO file name). So for the legitimate application, that is, there is no shell application, how to carry out page debugging. Here’s the question Reveal addresses. 1. Install the reveal-for-Mac tool, iv3j, and DMG installation package password: xclient.info. 2. Search for Reveal Loader in Cydia and install it.

3. Mobile phone Settings Open permissions according to the Settings below.

4, environment configuration open the terminal, use SSH, USB port mapping and log in to the mobile phone (on the jailbreak environment of mobile phone and computer port insinuating and file transfer reference jailbreak preliminary this article has a very detailed demonstration and description)

• login

• Copy files from a Mac to a mobile phone. Create a RHRevealLoader folder in the phone root directory /Library/.

Make a copy of RevealServer in the machine-side RevealServer. Framework, rename it libReveal. Dylib, Then copy it to the phone /Library/RHRevealLoader/ directory. SCP -p 12345 -r /Users/libin/Desktop/ reverse/libreveal.dylib Root @ localhost: / Library/RHRevealLoader/copy code You can use the same iFunBox to visualize the operation file. Carry pass Reveal, restart your computer and restart the phone, open the nailing, can be shown as follows.

5. It is suggested that the Reveal on the computer side does not detect the opened application, please check the following problems: • 1️ discount: Check whether the next RevealServer is renamed libReveal. Dylib. • 2️ discount: • 3️ discount: mobile phone and computer terminal Reveal whether to restart. • 4️ discount: mobile phone should be kept on the same LOCAL area network with computer after restarting. The final result is as follows:

Here use Frida-ios-dump for shell smashing. (About shell smashing, the author will update the article specifically about dynamic shell smashing, static shell smashing principle and the use and principle of different shell smashing tools) Map the USB port, log in the phone, and then use the shell smashing.

Frida’s dump.py can be used in any directory, so you don’t have to CD it to the directory every time. The application ipA is stored in the current directory. If you are interested, you can refer to 2.5.3 Configuring shell to automatically connect USB mapping and login in Jailbreak Preliminary.

After the shell is smashed, the ipA is obtained, which is changed to zip, decompressed, and the package content is displayed. Then the mach-O source file can be found after the shell is smashed. Link password: PJTT To check application encryption:

Use class-dump to export headers after shell breaking. If you are not familiar with class-dump, you can refer to this article on debugging and code modification of recheckout applications. Type the following command: class-dump -h DingTalk -o./headers/ • DingTalk is a Mach -o file in the current directory • -o./headers/ The results are as follows:

At this point, preparation work has been completed, which is what we need to do first in reverse an application. • 1️ one: Run application, page Debug (Reveal, shell cracking application re-signature attached to Xcode, View-debug, Chisel and Cycript, etc., refer to LLDB advanced chapter Chisel and Cycript). • 2️ discount: 4, summary of preparation work In actual reverse development, direct on the code to debug is not recommended, in line with the principle of time is cost, our treatment should be the following process. First clear ideas and source development logic, can static analysis on static analysis (static analysis generally includes class-dump view header files, Macho analysis, assembly code analysis and so on. Of course, is not forced to do not need to analyze assembly, for assembly is very familiar with the students can ignore), as little dynamic debugging, after we have a full grasp of the start of the code. So with all the tools in place, let’s think about business requirements and logic. • When using location GPS clock rule: o We want to be able to clock in without the specified location. • We want to be able to clock in without the specified Wi-Fi connection. First of all, we can think of the following: Idea 1: Start with the button and click method of punching, hook the method or check the assembly for static analysis, check its processing logic, modify the judgment logic, and punch can be normally executed when conditions are not met. Therefore, go to the punch in page and use the Reveal view button method.

Come here and see the unfortunate news that the entire page is a WebView. Even if we can guess which way the WebView interacts with the OC and which fixed methods will be called to continue searching, the time cost is too large. First of all, let’s consider the situation of GPS clocking. Due to the requirements of iOS system, the acquisition of GPS position of any map is almost packaged with the native CLLocationManager. Therefore, we thought of modifying the proxy method to get GPS, so that it will always get the longitude and latitude of the address returned. Wi-fi idea is the same as above. In general, it should be able to meet the requirements. Next, we will try. Debugging process 1, static analysis using Hopper to open the Mach-O after smashing the shell. Search method: locationManager: didUpdateLocations: copying code search results are as follows:

Search to the whole project, there are several classes that implement this method. Then what should we do, to see the compilation of these methods for analysis? The author here does not recommend this method. Because of the usage habits tell us that every time we open the page, we will get the GPS position. So I think we can do this: use dynamic debugging, Hook the method of these classes, keep calling the original method in Hook, but add a print, to find out which class gets the GPS position when the page is opened. To narrow the scope of analysis. Using logos hook is very efficient and convenient. (Students who are not familiar with it can read the actual reverse hook method – logos.) Therefore, go directly to the dynamic debugging stage. Second, dynamic debugging

  1. New construction

After installing the MonkeyDev plugin, select the following new project:

Change the file type to Objective-C++ Source, and keep the content of the file only with the introduction of UIKit.

  1. Gets the Bundle ID of the target project

There are several ways to do this. You can go directly to the info.plist of your app. To mention the use of CYcript in jailbreak environments and custom CY directives (also see Chisel and CYcript in the LLDB advanced section) we use this way: • ① : port mapping and SSH login to the phone • ② : • ③ : Check the pin process ID • ④ : Append the current process with CYcript • ⑤ : import the custom CY directive • ⑥ : Get the Bundle ID and fill it into the project configuration file.

  1. SSH configuration

Writing plug-ins using MonkeyDev requires configuring SSH login information in the project.

The authors have configured the relevant environment variables in.zshrc so that they do not need to be filled in every time.

• MonkeyDev’s tweak uses Theos, • DyLD source code can be seen, Dyld determines whether to load the inserted dynamic library based on the environment variable DYLD_INSERT_LIBRARY. • Jailbreak plugin packaging actually generates a dylib library, which is then copied to the phone via SSH. When the application is loaded, Dyld: const char* const * DYLD_INSERT_LIBRARIES; // load any inserted libraries if ( sEnv.DYLD_INSERT_LIBRARIES ! = NULL ) { for (const char* const* lib = sEnv.DYLD_INSERT_LIBRARIES; *lib ! = NULL; ++lib) loadInsertedDylib(*lib); } copying code 2. Logos here code and nothing to say, is the hooks we respectively in the hopper above search out the implementation of the locationManager: didUpdateLocations: #import

%hook AMapLocationCLMDelegate

  • (void)locationManager:(id)arg1 didUpdateLocations:(id)arg2{ %log; %orig;

} %end

%hook AMapLocationManager

  • (void)locationManager:(id)arg1 didUpdateLocations:(id)arg2{ %log; %orig;

} %end

%hook DTCLocationManager

  • (void)locationManager:(id)arg1 didUpdateLocations:(id)arg2{ %log; %orig;

} %end

%hook LALocationManager

  • (void)locationManager:(id)arg1 didUpdateLocations:(id)arg2{ %log; %orig;

} %end

%hook LAPLocationInfo

  • (void)dt_locationManager:(id)arg1 didUpdateLocations:(id)arg2{ %log; %orig;

} %end

%hook DTLocationJSAPIHandler

  • (void)dt_locationManager:(id)arg1 didUpdateLocations:(id)arg2{ %log; %orig;

} %end

%hook VILocationManager

  • (void)locationManager:(id)arg1 didUpdateLocations:(id)arg2{ %log; %orig;

} %end

%hook MAMapView

  • (void)locationManager:(id)arg1 didUpdateLocations:(id)arg2{ %log; %orig;

} %end Make sure local port 12345 is mapped to port 22 on the other end of the USB phone. CMD + shift + 2 to open the device page Open the console. Enter search DingTalk to select process.

• Search results show that didUpdateLocations calls to AMapLocationCLMDelegate and AMapLocationManager are the most frequent and always come in pairs. There is a proxy relationship between the Manager and the delegate. After the Manager obtains positioning information, it calls back to the protocol executor through the proxy. • Store the address records of AMapLocationCLMDelegate and AMapLocationManager. Memory breakpoints Since the production package is unsigned, it is not possible to use the class name and method name breakpoints, so we use memory address breakpoints. • SSH mapping and login. Mobile terminal input: • DebugServer *:12346 -a DingTalk copy code • MAC side enter LLDB into breakpoint state, Then input, process the connect connect: / / localhost: 12346 copying code (the above is the way of escape environment using usb tune LLDB). Use methods + class memory address to get the list of methods and address of the class (this instruction comes from the LLDB plug-in – loadCommands).

The didUpdateLocations method of the AMapLocationCLMDelegate class can be broken using the b + method memory address.

Note: some students may often use the above method to add breakpoints to the jailbreak environment. Normally that’s fine, but remember what we did? We hook the method, which means that the method implementation imp has been replaced by our own method, therefore, the above way is wrong!! Call the didUpdateLocations method of AMapLocationCLMDelegate. You can see the logos Hook code that we clearly wrote. So how do we break the original method without hook? • Obtain the offset of the first address based on Mach -O.

• Obtain the first address of mach-O

The calculation principle involves ALSR and pageZero knowledge, reference LLDB from shallow to deep at the end of the article. Calculate the method address of AMapLocationCLMDelegate 0x100267EE8 and the method address of AMapLocationManager 0x1002786E4. Let’s add breakpoints separately. After adding breakpoints, let’s go to the next call:

It can be found that the entry is not our hook method, OK, the two methods memory breakpoints added. Using BT, we can see the function nested call relationship, which verifies our previous conjecture:

After the above debugging, we found that the location of AMapLocationManager was called in the punch card page. So, next, let’s look at the class header file.5. Go to sublime and open the class-dump header. CMD + Shift + f search @interface AMapLocationManager. Finding all the methods and attributes of this class, we then hook all the methods of this class, add print to view and investigate their logic and call flow. Because this class has many methods, it is too troublesome to write by hand. In fact, when we configure Theos, there is a script inside.

Copy the amaplocationManager. h we dumped to the project directory. Enter the command:

After execution, drag the generated logamapManager. xm into the project, select Objective-C++ Source as the type, and compile the project. At this time, generate an additional logamapManager. mm in the project folder, and drag the project.

Cxx_destruct: () {cxx_destruct: () {cxx_destruct: () {cxx_destruct: () {cxx_destruct: () {cxx_destruct: () { There is no need to analyze. I’ve added four class declarations here, @interface CLLocationManager @end @interface AMapNetworkManager @end @interface cllocation@end @interface AMapLocationReGeocode @end Copy the code to comment out the positioning methods of the several classes of our previous hook, so as to prevent too much printing affecting the judgment. Rebuild and view the console print.

Here we see that the manager calls startUpdatingLocation, followed by didUpdateLocations. So again, we find the address breakpoint for startUpdatingLocation. Once the breakpoint has been successfully placed, enter the punch page again. At the breakpoint, BT looks at the function call stack.

  1. Locate the function call flow

• In the figure above, we see that the function name is not displayed for symbolic reasons, so we want to know the function name, again, we can calculate. The actual address of the process function is shown in the figure. • Then subtract the random offset value of the Mach-O first address: ALSR is the first address offset based on Mach-O, so we can go to Hopper search to get the class name and function name. Arm 64 subtracts 0x10000000 from the calculation). For example, #2 in the function call stack, the actual function address is 0x00000001024eaad8, Subtract the mach-O header address (ALSR) obtained from the image list and remove the first 1 (page zero) to 0x94000 to get 0x102456AD8. Go to Hopper, press G and enter the memory address to find the following:

Hopper on Mac terminal is too slow. Hopper on Mac terminal is too slow. Frame #1: frame #1: frame #1: 0x00000001085250e8 [AMapLocationManager startUpdatingLocation] frame #2: 0x102456AD8 DingTalk [DTALocationManager dt_startUpdatingLocation] ? DingTalk + 248 frame #3: 0x1039148B0 DingTalk [LAPLocationInfo start:to:]? DingTalk + 1980 frame #4: 0x103959010 DingTalk` [LAPluginInstanceCollector handleJavaScriptRequest:callback:]? DingTalk + 52 copy code here we find the call starting point: webView js and OC interaction callback. That is, the webView page loads, communicates with the OC, and calls up the start location. Then, hook this method, adding print. % hook LAPluginInstanceCollector

  • (void)handleJavaScriptRequest:(id)arg1 callback:(id)arg2{ %orig; NSLog(@”LBHook\n\n\n\n\n” “arg1Class = %@\n” “arg1 = %@\n” “arg2Class = %@\n” “arg2 = %@\n” ,[arg1 class],arg1,[arg2 class],arg2); }

%end copies the code

By adding print, we see that parameter 1 is an NSDictionary parameter. Parameter 2 is a stack block. If we don’t find the latitude and longitude information in the first parameter, we need to look at the block. So we need to look at the Block’s signature, which is a very old problem, and it’s implemented in Aspect and other source libraries. This is the procedure for fetching Block_descriptor_3’s signature based on the memory offset at the flags flag. Struct Block_layout {void *isa; volatile int32_t flags; // contains ref count int32_t reserved; BlockInvokeFunction invoke; // Implement the address! struct Block_descriptor_1 *descriptor; // imported variables };

#define BLOCK_DESCRIPTOR_1 1 struct Block_descriptor_1 { uintptr_t reserved; uintptr_t size; };

#define BLOCK_DESCRIPTOR_2 1 struct Block_descriptor_2 { // requires BLOCK_HAS_COPY_DISPOSE BlockCopyFunction copy; BlockDisposeFunction dispose; };

#define BLOCK_DESCRIPTOR_3 1 struct Block_descriptor_3 { // requires BLOCK_HAS_SIGNATURE const char *signature; const char *layout; // contents depend on BLOCK_HAS_EXTENDED_LAYOUT }; Copy the code Then according to the above about the same way, we can give [LAPluginInstanceCollector handleJavaScriptRequest: callback:] add breakpoints. Run to the breakpoint after successful addition.

Once we get the block address, we’re going to get its signature.

Copying code with Po [NSMethodSignature signatureWithObjCTypes:”v16@?0@8″] clearly shows that a block is a block with no return value, an ID parameter. To determine the type of the block argument, we nested a block and called the original method to our own block. We call the original block in our custom block and add a print. Therefore, we changed the hook code is as follows: % hook LAPluginInstanceCollector

  • (void)handleJavaScriptRequest:(NSDictionary *)arg1 callback:(void(^)(id))arg2{ id myCallBack = ^(id block_arg){ NSLog(@”arg1 %@\n block_argClass: %@\nblock_arg:%@\n”,arg1,[block_arg class],block_arg);

    // Keep the original use!! arg2(block_arg);Copy the code

    }; %orig(arg1,myCallBack);

} %end copy the code to compile and install, re-open the pin, and view the console printout. As you can see, the block parameter type is NSDictionary. At the same time, we also see the most desired GPS position information. ⚠️ analysis completed: Therefore, we can definitely assume that the startUpdatingLocation of AMapLocationManager is called in this method and a dictionary is called back into the block after the location is obtained. Therefore, in this method, the longitude and latitude are written directly as the longitude and latitude of the desired location. It can completely meet our requirements. Of course, we can see that parameter 1 and parameter 2 have many different situations and states in the print. Through checking, we can find that when the action in parameter 1 is start and the keep in parameter 2 is 1, It means you need to regain latitude and longitude. Therefore, modify the code. 9. Modify the original code logic % hook LAPluginInstanceCollector

  • (void)handleJavaScriptRequest:(NSDictionary *)arg1 callback:(void(^)(id))arg2{ if([arg1[@”action”] IsEqualToString :@”start”]){// May need to modify the location information! // Define a myBlock id myCallBack = ^(NSDictionary * block_arg){if([block_arg[@”keep”] isEqualToString:@”1″]){// GPS needs to be modified

    NSMutableDictionary * tempDic = [NSMutableDictionary dictionaryWithDictionary:block_arg]; // Change the value of the dictionary in block! TempDic [@ "result"] [@ "latitude"] = @ "28.1924070001"; TempDic [@ "result"] [@ "longitude"] = @ "112.9788130003"; // Use the modified! arg2(tempDic); }else{// Keep the original use!! arg2(block_arg); }}; %orig(arg1,myCallBack);Copy the code

    }else{ %orig; }

} %end copy code 10. Effect view • Not installed plug-in: punch out display remote. WiFi and GPS punch card plug-in the complete version of WiFi punch card exploration ideas and GPS position punch card exactly the same. After exploration, it is also found that the method of interaction between JS of our final hook and OC to obtain the current connection WiFi information is consistent with the macIp of the WiFi set by the administrator. Hook code complete version: %hook LAPluginInstanceCollector

  • (void)handleJavaScriptRequest:(NSDictionary *)arg1 callback:(void(^)(id))arg2{ if([arg1[@”action”] IsEqualToString :@”start”]){// May need to modify the location information! // Define a myBlock id myCallBack = ^(NSDictionary * block_arg){if([block_arg[@”keep”] isEqualToString:@”1″]){// GPS needs to be modified

    NSMutableDictionary * tempDic = [NSMutableDictionary dictionaryWithDictionary:block_arg]; // Change the value of the dictionary in block! TempDic [@"result"][@"latitude"] = @"31.8567980000"; TempDic [@ "result"] [@ "longitude"] = @ "118.8274580000"; // Use the modified! arg2(tempDic); }else{// Keep the original call!! arg2(block_arg); }}; %orig(arg1,myCallBack);Copy the code

    }else if([arg1[@”action”] isEqualToString:@”getInterface”]){ // define a myBlock id myCallBack = ^(NSDictionary * block_arg){

    NSMutableDictionary * tempDic = [NSMutableDictionary dictionaryWithDictionary:block_arg]; // Change the value of the dictionary in block! MacIP tempDic[@"result"][@" macIP "] = @"f0:b4:29:6b:fe:51"; // Use the modified! arg2(tempDic); }; %orig(arg1,myCallBack);Copy the code

    }else{ %orig; }

} %end copy code WiFi effect is not demonstrated, and GPS rules behave the same. Conclusion • 1️ discount: This article shows in detail how to make a prison break plug-in from scratch, and most of the debugging tools and knowledge points involved are introduced. • 2️ one: In the reverse process, clear thinking is very important, while to master cycript, shell breaking, jailbreak environment LLDB debugging, Theos, Chisel, and other static analysis and dynamic debugging tools, the underlying principle is also essential. • 3️ one: After sorting out ideas, try to use static analysis (assembly also belongs to static analysis, which depends on personal situation), when the general idea is sorted out, dynamic debugging can be carried out, hook code and breakpoint debugging, cycript and other tools to help straighten out the source code logic. • 4️ one: Finally, we found that actually hook injection to modify code is very simple, the reverse road is such, combing and derivation often takes a lot of time. Finally, the demo plugin has no commercial purpose and does not engage in any commercial activities. Pure original article, reproduced please indicate the source.