【iOS逆向与安全】在iOS状态栏中实现秒表功能的插件开辟指南
媒介在需要准确把握时间的场景中,比方抢购活动或需要在整点进行操作的环境下,用户往往需要正确相识当前的秒数。然而,iOS系统默认的状态栏时间体现并不包含秒数,这给用户带来了未便。
为相识决这一标题,开辟一个在状态栏体现秒数的插件,可以资助用户及时把握准确时间,提升在特定场景下的操作效率。
本篇文章将探讨如何在iOS系统中开辟如许一个插件,旨在为用户提供更准确的时间体现。
一、目标
见下图的状态栏时间位置:
https://i-blog.csdnimg.cn/direct/6a60badd447a4e10b03cf288aaedb8f5.gif#pic_center
二、开辟环境和工具清单
[*]mac系统
[*]frida:动态调试
[*]已越狱iOS设备:脱壳及frida调试
[*]IDA Pro:静态分析
三、步骤
1、查找设置状态栏日期的调用栈
在终端执行下令frida-trace -U -m "*" SpringBoard
并修改setText_.js:
defineHandler({
onEnter(log, args, state) {
log(`-)}]`);
log('UILabel setText called from:\n' +
Thread.backtrace(this.context, Backtracer.ACCURATE)
.map(DebugSymbol.fromAddress).join('\n') + '\n');
},
onLeave(log, retval, state) {
}
});
当时间有变革时,获取到的堆栈信息如下:
-
-
UILabel setText called from:
0x1afd16180 UIKitCore!-
0x1afcf71fc UIKitCore!-
0x1afcfeca4 UIKitCore!-
0x1afd5381c UIKitCore!-
0x1afd3be04 UIKitCore!__78-_block_invoke_2
0x1ad1b2adc CoreFoundation!__NSDICTIONARY_IS_CALLING_OUT_TO_A_BLOCK__
0x1ad129280 CoreFoundation!-
0x1afd3bb60 UIKitCore!-
0x1afd3b7d0 UIKitCore!-
0x1afd39af4 UIKitCore!__30-_block_invoke
0x1afd4f004 UIKitCore!-
0x1afd4ea98 UIKitCore!-
0x1afd4e9d8 UIKitCore!-
0x1afd4e3b0 UIKitCore!-
0x1afd3b4f4 UIKitCore!-
0x1afd7d28c UIKitCore!-
获取到关键方法:
2、检察的源码
使用ida pro9反编译dyld_shared_cache源码。并定位到该方法,获取到关键的伪代码如下:
v38 = objc_retainAutoreleasedReturnValue(objc_msgSend(v6, "data"));
v39 = objc_retainAutoreleasedReturnValue(objc_msgSend(v38, "shortTimeEntry"));
v40 = objc_retainAutoreleasedReturnValue(objc_msgSend(v39, "stringValue"));
v41 = -(self, "pillTimeView");
v42 = objc_retainAutoreleasedReturnValue(v41);
objc_msgSend(v42, "setText:", v40);
获取到关键方法stringValue
3、trace stringValue方法
在终端执行下令frida-trace -U -m "*[* stringValue]" SpringBoard,当时间有变革时,获取到的堆栈信息如下:
-
-
-
-
-
修改__handlers__/_UIStatusBarDataStringEntry/stringValue.js
defineHandler({
onEnter(log, args, state) {
log(`-`);
},
onLeave(log, retval, state) {
log(`-=${ObjC.Object(retval)}=`);
}
});
然后再次运行frida-trace -U -m "*[* stringValue]" SpringBoard,当时间有变革时,获取到的堆栈信息如下:
-
-=nil=
-
-=3月4日周二=
-
-=下午10:09=
-
-=10:09=
-
-=下午10:10=
-
-=nil=
-
-=3月4日周二=
-
-=下午10:10=
-
-=10:10=
确定_UIStatusBarDataStringEntry就是状态栏时间的来源后,继续执行frida-trace -U -m "*" SpringBoard,当时间有变革时,获取到的堆栈信息如下:
-
_UIStatusBarDataStringEntry initFromData called from:
0x1afd4fe8c UIKitCore!+
0x1afd7c788 UIKitCore!-
0x1afd7e214 UIKitCore!-
0x1afd5ec1c UIKitCore!-
0x1afd5ee28 UIKitCore!_UIStatusBarReceivedStatusBarDataAndActions
0x1b020f130 UIKitCore!_XReceivedStatusBarDataAndActions
0x1b4413ef0 AppSupport!migHelperRecievePortCallout
0x1ad1c8fe8 CoreFoundation!__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__
0x1ad1c8378 CoreFoundation!__CFRunLoopDoSource1
0x1ad1c208c CoreFoundation!__CFRunLoopRun
0x1ad1c121c CoreFoundation!CFRunLoopRunSpecific
0x1c4cc5784 GraphicsServices!GSEventRunModal
0x1afbfffe0 UIKitCore!-
0x1afc05854 UIKitCore!UIApplicationMain
0x1d2970194 SpringBoard!SBSystemAppMain
0x1ace816b0 libdyld.dylib!start
通过堆栈信息分析,确认-为我们的目标对象
4、使用frida验证使用结果:
执行下令frida-trace -U -m "-" SpringBoard后,修改该js文件内容为:
defineHandler({
onEnter(log, args, state) {
log(`-} actions:${args} animated:${args}]`);
var structPtr = args;
log("Original timeString:", structPtr.add(43).readCString(64));
const now = new Date();
const hours = String(now.getHours()).padStart(2, '0'); // 补零
const minutes = String(now.getMinutes()).padStart(2, '0'); // 补零
const seconds = String(now.getSeconds()).padStart(2, '0'); // 补零
var newTimeString =`${hours}:${minutes}:${seconds}`;
structPtr.add(43).writeUtf8String(newTimeString);
log("Updated timeString:", structPtr.add(43).readCString(64));
},
onLeave(log, retval, state) {
}
});
当状态栏日期变革后。日期正常体现秒表,说明该函数可用。
5、编写tweak代码
Tweak.x源码如下:
#import <CoreFoundation/CoreFoundation.h>
#import <Foundation/Foundation.h>
#import <Foundation/NSUserDefaults+Private.h>
#import "StatusBarUpdater.h"
#import "Structs.h"
#import "headers.h"
#include <string.h>
#include <sys/time.h>
static NSString * nsDomainString = @"com.witchan.precise-time";
static NSString * nsNotificationString = @"com.witchan.precise-time/preferences.changed";
static BOOL enabled;
static void notificationCallback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
NSNumber * enabledValue = (NSNumber *)[ objectForKey:@"enabled" inDomain:nsDomainString];
enabled = (enabledValue)? : YES;
NSLog(@"=witchan= 插件状态:%d", enabled);
}
%hook UIStatusBarServer
%property (nonatomic, strong) StatusBarUpdater *updater;
// SCD_Struct_UI104结构请从ida pro复制
-(void)_receivedStatusBarData:(SCD_Struct_UI104*)arg1 actions:(int)arg2 animated:(BOOL)arg3 {
if (self.updater == nil) {
self.updater = [ init];
}
if (!enabled) {
;
%orig;
return;
}
// 获取当前时间
NSDate *currentDate = ;
// 创建日期格式化器
NSDateFormatter *dateFormatter = [ init];
// 设置日期格式
; // 24小时制
// 将当前日期格式化为字符串
NSString *formattedTime = ;
NSLog(@"=witchan= now timeString: %@", formattedTime);
// _statusBarData.var1 = strcpy(ret->personName, "12:33:22");
strcpy(arg1->var1, );
%orig(arg1, arg2, arg3);
NSLog(@"=witchan= _receivedStatusBarData: %d %d", arg2, arg3);
// 创建一个新结构体用于复制
//SCD_Struct_UI104 copy;
//memcpy(©, arg1, sizeof(SCD_Struct_UI104));// 正确复制结构体数据
;
;
}
%end
%ctor {
NSLog(@"=witchan= precise time plugin load success");
notificationCallback(NULL, NULL, NULL, NULL, NULL);
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, notificationCallback, (CFStringRef)nsNotificationString, NULL, CFNotificationSuspensionBehaviorCoalesce);
}
完备源码下载地址:https://pan.quark.cn/s/e1152c2f7899
总结
通过上述方法,用户可以在状态栏或屏幕上方及时检察秒数,满足在特定场景下对准确时间的需求,提升操作效率和成功率。
提示:阅读此文档的过程中遇到任何标题,请关住工众好【移动端Android和iOS开辟技术分享】或+99 君羊【812546729】
https://i-blog.csdnimg.cn/direct/49a6de6d5ed14538ae58bb6b8dcb19d6.png#pic_center
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]