►►►
手动修改时间
►►►
手动修改时间
►►►
自动修改时间
►►►
自动修改时间
tell application "Terminal"
# 关闭自动设置日期
set currentTab to do script "sudo systemsetup -setusingnetworktime off"
# 设置过去时间
do script "sudo date 0415110022" in currentTab
do script "sleep 2" in currentTab
# 打开typora
do script "open /Applications/Typora.app -g" in currentTab
do script "sleep 2" in currentTab
# 开启自动设置日期
do script "sudo systemsetup -setusingnetworktime on" in currentTab
do script "sleep 2" in currentTab
# 退出terminal
do script "killall Terminal" in currentTab
end tell
►►►
修改APP
►►►
修改APP
; Attributes: bp-based frame
; void __cdecl -[LicenseManager showTrailEnd](LicenseManager *self, SEL)
__LicenseManager_showTrailEnd_ proc near
push rbp
mov rbp, rsp
push r15
push r14
push r13
push r12
push rbx
push rax
mov rdi, cs:classRef_NSAlert ; id
mov rsi, cs:selRef_new ; SEL
mov r12, cs:_objc_msgSend_ptr
call r12 ; _objc_msgSend
mov r14, rax
mov rsi, cs:selRef_setMessageText_ ; SEL
lea rdx, cfstr_Error_1 ; "Error"
mov rdi, rax ; id
call r12 ; _objc_msgSend
mov rdi, cs:classRef_I18nUtils ; id
mov rsi, cs:selRef_getLocalizedPanelItem_ ; SEL
lea rdx, cfstr_ThisBetaVersio ; "This beta version of Typora is expired, please download and install a newer version."
call r12 ; _objc_msgSend ; +[I18nUtils getLocalizedPanelItem:]
mov rdi, rax ; id
call _objc_retainAutoreleasedReturnValue
mov rbx, rax
mov rsi, cs:selRef_setInformativeText_ ; SEL
mov rdi, r14 ; id
mov rdx, rax
call r12 ; _objc_msgSend
mov r13, cs:_objc_release_ptr
mov rdi, rbx ; id
call r13 ; _objc_release
mov rdi, cs:classRef_NSRunningApplication ; id
mov rsi, cs:selRef_currentApplication ; SEL
call r12 ; _objc_msgSend
mov rdi, rax ; id
call _objc_retainAutoreleasedReturnValue
mov rbx, rax
mov rsi, cs:selRef_activateWithOptions_ ; SEL
mov edx, 2
mov rdi, rax ; id
call r12 ; _objc_msgSend
mov rdi, rbx ; id
call r13 ; _objc_release
mov rsi, cs:selRef_runModal ; SEL
mov rdi, r14 ; id
call r12 ; _objc_msgSend
mov rdi, cs:classRef_NSWorkspace ; id
mov rsi, cs:selRef_sharedWorkspace ; SEL
call r12 ; _objc_msgSend
mov rdi, rax ; id
call _objc_retainAutoreleasedReturnValue
mov r15, rax
mov rdi, cs:classRef_NSURL ; id
mov rsi, cs:selRef_URLWithString_ ; SEL
lea rdx, cfstr_HttpsTyporaIoD ; "https://typora.io/#download"
call r12 ; _objc_msgSend
mov rdi, rax ; id
call _objc_retainAutoreleasedReturnValue
mov rbx, rax
mov rsi, cs:selRef_openURL_ ; SEL
mov rdi, r15 ; id
mov rdx, rax
call r12 ; _objc_msgSend
mov rdi, rbx ; id
call r13 ; _objc_release
mov rdi, r15 ; id
call r13 ; _objc_release
mov rdi, cs:classRef_NSApplication ; id
mov rsi, cs:selRef_sharedApplication ; SEL
call r12 ; _objc_msgSend
mov rdi, rax ; id
call _objc_retainAutoreleasedReturnValue
mov rbx, rax
mov rsi, cs:selRef_terminate_ ; SEL
mov rdi, rax ; id
xor edx, edx
call r12 ; _objc_msgSend
mov rdi, rbx ; id
call r13 ; _objc_release
mov rdi, r14
mov rax, r13
add rsp, 8
pop rbx
pop r12
pop r13
pop r14
pop r15
pop rbp
jmp rax
__LicenseManager_showTrailEnd_ endp
void __cdecl -[LicenseManager showTrailEnd](LicenseManager *self, SEL a2)
{
NSAlert *v2; // r14
id v3; // rax
id v4; // rbx
id v5; // rax
id v6; // rbx
id v7; // rax
id v8; // r15
NSURL *v9; // rax
NSURL *v10; // rbx
id v11; // rax
id v12; // rbx
v2 = objc_msgSend(&OBJC_CLASS___NSAlert, "new");
objc_msgSend(v2, "setMessageText:", CFSTR("Error"));
v3 = +[I18nUtils getLocalizedPanelItem:](
&OBJC_CLASS___I18nUtils,
"getLocalizedPanelItem:",
CFSTR("This beta version of Typora is expired, please download and install a newer version."));
v4 = objc_retainAutoreleasedReturnValue(v3);
objc_msgSend(v2, "setInformativeText:", v4);
objc_release(v4);
v5 = objc_msgSend(&OBJC_CLASS___NSRunningApplication, "currentApplication");
v6 = objc_retainAutoreleasedReturnValue(v5);
objc_msgSend(v6, "activateWithOptions:", 2LL);
objc_release(v6);
objc_msgSend(v2, "runModal");
v7 = objc_msgSend(&OBJC_CLASS___NSWorkspace, "sharedWorkspace");
v8 = objc_retainAutoreleasedReturnValue(v7);
v9 = objc_msgSend(&OBJC_CLASS___NSURL, "URLWithString:", CFSTR("https://typora.io/#download"));
v10 = objc_retainAutoreleasedReturnValue(v9);
objc_msgSend(v8, "openURL:", v10);
objc_release(v10);
objc_release(v8);
v11 = objc_msgSend(&OBJC_CLASS___NSApplication, "sharedApplication");
v12 = objc_retainAutoreleasedReturnValue(v11);
objc_msgSend(v12, "terminate:", 0LL);
objc_release(v12);
objc_release(v2);
}
主要是以下这几个对象和函数:
NSAlert
该 NSAlert
类的方法允许指定警报级别、警报文本、按钮标题和自定义图标(如果需要)。该类还允许警报显示帮助按钮,并为应用提供特定于警报的帮助的方法。
NSRunningApplication
一个对象,可以操作应用的单个实例并为其提供信息。应用的某些属性是固定的,例如捆绑标识符。其他属性可能会随时间而变化,例如应用是否处于隐藏状态。可以通过键值观察来观察不同的属性,在这种情况下,方法的说明注释会记录此功能。
currentApplication
返回表示此应用程序的函数 NSRunningApplication
。
activateWithOptions
尝试使用指定的选项激活应用程序。
NSApplicationActivateAllWindows = 1 << 0
runModal
将NSAlert作为应用模式对话框运行,并返回标识单击的按钮的常量。
sharedWorkspace 共享工作区
共享工作区对象。
objc_release
如果 value
为 null,则此调用不起作用。否则,它将执行释放操作,就像对象已发送消息 release
一样。
NSURL
表示资源位置的对象,例如远程服务器上的项或本地文件的路径。
URLWithString
创建并返回使用提供的 URL 字符串初始化的 NSURL 对象。
objc_retainAutoreleasedReturnValue
objc_retainAutoreleasedReturnValue
概念是,如果要从自动释放的函数返回一个值,但接下来要做的是对该对象进行保留,那么执行自动释放和保留是绝对没有意义的——我们只是在浪费周期。因此,如果我们能以某种方式确定我们将要保留,那么我们可以节省几个 CPU 周期。在运行应用程序的过程中,这可能会节省大量时间和精力。
如果调用方的指令立即调用objc_retainAutoreleasedReturnValue,则被调用方将省略objc_autoreleaseReturnValue,并将结果保存在线程本地存储中。如果调用方看起来不合作,则被调用方会像往常一样调用 objc_autoreleaseReturnValue。
setInformativeText
设置面板中显示的(可选)信息文本。
objc_msgSend
将具有简单返回值的消息发送到类的实例。
demo:
// in implementation file
- (void)errorPopUp:(NSString *)reason detail:(NSString *)detail {
NSAlert *alert = [[NSAlert alloc] init];
[alert setMessageText:reason];
[alert setInformativeText:detail];
[alert setAlertStyle:NSCriticalAlertStyle]; // or NSWarningAlertStyle, or NSInformationalAlertStyle
[alert addButtonWithTitle:@"OK"];
[alert runModal];
}
根据上面的分析,基本上可以确定这个函数的功能是:
弹窗This beta version of Typora is expired, please download and install a newer version.
,并生成确定按钮,点击按钮后,打开urlhttps://typora.io/#download
,最后执行terminate关闭程序。
那么修复的方法就比较简单了,直接把objc_msgSend(v12, "terminate:", 0LL);
给nop掉就可以让程序弹窗后不再关闭。也可以将showTrailEnd
这个函数nop掉,也就不会弹窗了。
上面的方法比较粗暴,还是想要知道为什么会导致过期,可以继续往上分析。
void __cdecl -[LicenseManager validateBetaTrailEnd](LicenseManager *self, SEL a2)
{
double v2; // xmm0_8
Setting *v3; // rax
Setting *v4; // rbx
id v5; // rax
id v6; // r12
id v7; // rax
id v8; // rbx
id v9; // r13
id v10; // r13
id v11; // rax
id v12; // r15
id v13; // rbx
+[Setting passedSinceBuild](&OBJC_CLASS___Setting, "passedSinceBuild");
v3 = +[Setting sharedInstance](&OBJC_CLASS___Setting, "sharedInstance");
v4 = objc_retainAutoreleasedReturnValue(v3);
v5 = -[Setting get:](v4, "get:", CFSTR("verInitTime"));
v6 = objc_retainAutoreleasedReturnValue(v5);
objc_release(v4);
if ( v6 )
{
v7 = objc_msgSend(&OBJC_CLASS___NSDate, "date");
v8 = objc_retainAutoreleasedReturnValue(v7);
v9 = objc_msgSend(v8, "compare:", v6);
objc_release(v8);
if ( v9 != (id)-1LL )
{
v10 = objc_alloc(&OBJC_CLASS___NSDateInterval);
v11 = objc_msgSend(&OBJC_CLASS___NSDate, "date");
v12 = objc_retainAutoreleasedReturnValue(v11);
v13 = objc_msgSend(v10, "initWithStartDate:endDate:", v6, v12);
objc_msgSend(v13, "duration");
objc_release(v13);
objc_release(v12);
if ( (int)v2 >= 17280001 )
-[LicenseManager showTrailEnd](self, "showTrailEnd");
}
}
objc_release(v6);
}
这个函数主要的功能是获取verInitTime
属性,和现有date计算时间差,然后和17280001进行对比17280001/(3600*24)=200天。那么猜测verInitTime应该就是初次使用时生成的属性,运行超过200天之后就会弹窗。
接下来需要找到verInitTime这个属性保存的位置,从这个位置往上追引用一直没找到。后来换个思路,既然首次运行的时候会生成该文件,那么从main函数开始往下找应该也能找到。
int __cdecl main(int argc, const char **argv, const char **envp)
{
os_log_s *v3; // rbx
Setting *v4; // rax
os_log_s *v5; // rbx
id v6; // rax
os_log_s *v7; // rbx
id v8; // rax
__int16 buf[8]; // [rsp+0h] [rbp-50h] BYREF
__int16 v11[8]; // [rsp+10h] [rbp-40h] BYREF
__int16 v12[24]; // [rsp+20h] [rbp-30h] BYREF
v3 = os_log_create("abnerworks.typora.plist", "userOp");
if ( os_log_type_enabled(v3, OS_LOG_TYPE_INFO) )
{
buf[0] = 0;
_os_log_impl((void *)&_mh_execute_header, v3, OS_LOG_TYPE_INFO, "----Typora Start----", (uint8_t *)buf, 2u);
}
objc_release(v3);
v4 = +[Setting sharedInstance](&OBJC_CLASS___Setting, "sharedInstance");
objc_unsafeClaimAutoreleasedReturnValue(v4);
if ( !NSClassFromString(CFSTR("NSTouchBar")) )
{
v5 = os_log_create("abnerworks.typora.plist", "userOp");
if ( os_log_type_enabled(v5, OS_LOG_TYPE_INFO) )
{
v11[0] = 0;
_os_log_impl((void *)&_mh_execute_header, v5, OS_LOG_TYPE_INFO, "use mock NSTouchBar", (uint8_t *)v11, 2u);
}
objc_release(v5);
v6 = objc_msgSend(&OBJC_CLASS___MockNSTouchBar, "class");
objc_msgSend(&OBJC_CLASS___NSKeyedUnarchiver, "setClass:forClassName:", v6, CFSTR("NSTouchBar"));
}
全盘搜该文件,找到对应路径/Users/xxxx/Library/Preferences/abnerworks.Typora.plist
打开后果然有verInitTime这个属性,那么把这个时间调到100年后就可以了。
免责声明:
本文所提供的信息仅为了解技术原理和安全风险,仅供学习目的,旨在提供有关旧版本软件破解的信息和知识分享。请注意,破解软件可能涉及侵犯版权和法律法规,可能导致严重的法律后果。任何人在使用本文中提供的信息时应自行承担风险和法律责任。本公众号和作者不鼓励、支持或提供任何形式的软件破解行为。
原文始发于微信公众号(山石网科安全技术研究院):Typora LicenseManager过期分析