0x00

Typora是一款强大的markdown编辑器,它可以让你轻松地写出美观的文档。但是其一直是不开源的,而且现在也已经开始收费了。所以本着学习探索的精神去逆向看看~

0x01

众所周知Typora是基于electron+reacta开发的,所以先看看js代码~



然后在顺着这个O继续康康~





关键就是这个e.hasActivated = "true" == e.hasActivated 但是这样的话有个小问题就是每次进去的话那个右下角都会有一个未激活悬浮框。而且只进行到这里也没啥意思,话不多说继续弄macos的可执行文件。

0x02

直接上ida,通过刚才的js思路走下去,这个可执行文件里肯定有生成url方法。搜索一下果不其然:



然后我们看到其调用了一个getLicensePanelUrlParams方法。进去康康!





ok!直接开始hook!!打开code编写dylib!

hook其返回值,setReturnValue后然后打印一下看看。

    id LicenseWindowController = NSClassFromString(@"LicenseWindowController");
[LicenseWindowController aspect_hookSelector:@selector(pageURL) withOptions:AspectPositionBefore usingBlock:^(id<AspectInfo> info){
NSInvocation *invocation = info.originalInvocation;
[invocation invoke];
__unsafe_unretained NSArray * tempResultSet;
[invocation getReturnValue:&tempResultSet];
NSLog(@"hook==pageURL-result=%@",tempResultSet);
} error:nil ];
}

嗯,失败了。url参数没变。。估计是哪里还有验证。但是找了一下调用没看到。所以换个思路。

我们看到其获取url参数时是通过LicenseManager类的成员属性获取。所以直接修改这里,我觉得比hook返回值的url更优。那么开始查找~

查找ING~

0x03



找到了读取和写入LicenseInfo的方法那么下面就好说了~



第一眼就看到一个方法,recordFilePathNew



hook住它我们看看返回值~

v3 = objc_msgSend(&OBJC_CLASS___NSKeyedArchiver, "archivedDataWithRootObject:", self->_licenseDict, v2);
v4 = objc_retainAutoreleasedReturnValue(v3);
v5 = v4;
v6 = +[Crypto encryptAES:](&OBJC_CLASS___Crypto, "encryptAES:", v4);
v7 = (void *)objc_retainAutoreleasedReturnValue(v6);
objc_release(v5);
v8 = -[LicenseManager recordFilePathNew](self, "recordFilePathNew");
v9 = objc_retainAutoreleasedReturnValue(v8);
objc_msgSend(v7, "writeToFile:atomically:", v9, 1LL);
//writeLicenseInfo这里我们看到他是把licenseDict AES加密存到了刚才的地址中去。
//那么licenseDict里都有什么呢?
//通过 getLicensePanelUrlParams:
objc_msgSend((void *)self->_licenseDict, "objectForKeyedSubscript:", CFSTR("email"));
objc_msgSend((void *)self->_licenseDict, "objectForKeyedSubscript:", CFSTR("license"));
v27 = -[LicenseManager dayRemains](self, "dayRemains");
v28 = objc_msgSend(&OBJC_CLASS___NSString, "stringWithFormat:", CFSTR("%ld"), v27);
v29 = objc_retainAutoreleasedReturnValue(v28);
v30 = v29;
v31 = objc_msgSend(&OBJC_CLASS___NSURLQueryItem, "queryItemWithName:value:", CFSTR("dayRemains"), v29);
//我们看到了里面有email和license
//然后我们进入LicenseManager dayRemains
signed __int64 __cdecl -[LicenseManager dayRemains](LicenseManager *self, SEL a2)
{
return (signed __int64)-[LicenseManager dayRemainsFrom:](self, "dayRemainsFrom:", 15LL);
}
//通过LicenseManager dayRemainsFrom
objc_msgSend((void *)self->_licenseDict, "setObject:forKeyedSubscript:", v8, CFSTR("installDate"));
//也就是说LicenseManager类的成员字典里_licenseDict包含了邮箱和license以及installDate

installDate安装时间也就是判断我们15天试用的关键。

所以这里只要把这个AES加密后储存的文件定期删除就可以永续15天试用进行一个破解。

但是这样也不太优雅~

可是直接修改类成员hasActivated也不行。

0x04

我们先回顾一下线索。

  • electron是通过接收解析url参数“hasActivated”来判断是不是激活用户。
  • macos里可执行文件修改让其发送url时把hasActivated赋值为true
  • getLicensePanelUrlParams 和 pageUrl修改返回值无效。
  • LicenseManager类里包含两个成员。1_hasLicense,2_licenseDict
  • 直接hook赋值hasActivated也不行,怀疑需要licenseDict。
  • licenseDict包含邮箱和license以及installDate,可以通过修改installDate来破解试用
  • licenseDict会加密储存在本地。

思考:

直接修改发送前的url和hasLicense不行,我怀疑是哪里还有验证,也就是验证licenseDict,尤其是licenseDict里的license。可以选择做掉验证license的方法(最轻松),也可以逆向算法追出正确的license(应该可以毕竟有离线验证)

但是,程序不会哪个环节都会验证license。

划重点,加密存储。既然加密了,估计程序应该会很信任这段数据吧~

所以一般是在存储前验证下license!

思路有了!

我们看看hook下writeLicenseInfo~~

上代码~

    id LicenseManager = NSClassFromString(@"LicenseManager");
[LicenseManager aspect_hookSelector:@selector(writeLicenseInfo) withOptions:AspectPositionBefore usingBlock:^(id<AspectInfo> info){
NSInvocation *invocation = info.originalInvocation;
[invocation invoke];
id instance = info.instance;
[instance setValue:@"1" forKeyPath:@"hasLicense"];
NSDictionary *licenseDict = @{@"email":@"huajia@huaji.com", @"license":@"hackBy:huajia"};
[instance setValue:licenseDict forKeyPath:@"licenseDict"];
} error:nil ];

ok,我们在在原方法调用前执行我们的hook,先是修改了LicenseManager的成员属性hasLicense,让程序误认为我们已经激活,顺便把邮箱和License也加入了,哈哈。然后writeLicenseInfo会把我们的构造加密写入本地文件中,然后其他方法会读取,现在我们运行下程序看看!



233~

mac Typora最新版逆向破解的更多相关文章

  1. Navicat15 For Mysql最新版完美破解图文教程(支持Win和Mac)

    Navicat15 For Mysql最新版完美破解 欢迎关注博主公众号[跟着Mic学架构],专注于分享Java领域技术干货,回复关键字 [面试资料] 可以获得海量面试资料. 申明,本教程 Navic ...

  2. Android逆向破解表单登录程序

    Android逆向破解表单登录程序 Android开发 ADT: android studio(as) 程序界面如下,登录成功时弹出通知登录成功,登录失败时弹出通知登录失败. 布局代码 <?xm ...

  3. 【MyEclipse 2015】 逆向破解实录系列【终】(纯研究)

    声明 My Eclipse 2015 程序版权为Genuitec, L.L.C所有. My Eclipse 2015 的注册码.激活码等授权为Genuitec, L.L.C及其付费用户所有. 本文只从 ...

  4. 【MyEclipse 2015】 逆向破解实录系列【2】(纯研究)

    声明 My Eclipse 2015 程序版权为Genuitec, L.L.C所有. My Eclipse 2015 的注册码.激活码等授权为Genuitec, L.L.C及其付费用户所有. 本文只从 ...

  5. 20165223《网络对抗技术》Exp1 PC平台逆向破解

    目录--PC平台逆向破解 1 逆向及BOF基础实践说明 1.1 实践内容 1.2 实践要求 1.3 基础知识 2 实验步骤 2.1 直接修改程序机器指令,改变程序执行流程 2.2 通过构造输入参数,造 ...

  6. 20155324《网络对抗》Exp1 PC平台逆向破解(5)M

    20155324<网络对抗>Exp1 PC平台逆向破解(5)M 实验目标 本次实践的对象是一个名为~pwn1~的~linux~可执行文件. 该程序正常执行流程是:~main~调用~foo~ ...

  7. 2018-2019-2 20165237《网络攻防技术》Exp1 PC平台逆向破解

    2018-2019-2 20165237<网络攻防技术>Exp1 PC平台逆向破解 一.实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调 ...

  8. 2018-2019-2 20165234 《网络对抗技术》 Exp1 PC平台逆向破解

    实验一 PC平台逆向破解 实验目的 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串. 该程序同时包含另 ...

  9. 20165221 《网络对抗技术》EXP1 PC平台逆向破解

    20165221 <网络对抗技术>EXP1 PC平台逆向破解 一.实验内容 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函 ...

  10. 2018-2019-2 网络对抗技术 20165325 Exp1 PC平台逆向破解

    2018-2019-2 网络对抗技术 20165325 Exp1 PC平台逆向破解(BOF实验) 实验有三个模块: (一)直接修改程序机器指令,改变程序执行流程: (二)通过构造输入参数,造成BOF攻 ...

随机推荐

  1. Redis 数据类型 Stream

    Redis 数据类型 Stream Redis 常用命令,思维导图 >>> Redis Stream 是 Redis 5.0 版本新增加的数据结构. Redis Stream 主要用 ...

  2. 【vue3-element-admin】Husky + Lint-staged + Commitlint + Commitizen + cz-git 配置 Git 提交规范

    前言 本文介绍 vue3-element-admin 如何通过 Husky + Lint-staged + Commitlint + Commitizen + cz-git 来配置 Git 提交代码规 ...

  3. 在CentOS上安装与卸载Docker Engine

    本文参考Docker官网提供的 安装手册编写 测试使用的操作系统版本为CentOS 7.9 安装Docker Engine 要在 CentOS 上开始使用 Docker 引擎,请确保 满足先决条件,然 ...

  4. 数据分析05-matplotlib基本绘图、高级绘图

    数据分析-05 数据分析-05 matplotlib基本功能详解 基本绘图 1)绘图核心API 2)设置线型.线宽 3)设置坐标轴范围 4)设置坐标刻度 5)设置坐标轴 6)图例 7)特殊点 8)备注 ...

  5. day10-好友关注

    功能05-好友关注 6.功能05-好友关注 6.1关注和取关 6.1.1需求分析 在探店图文的详情页面中,可以关注发布笔记的作者: 关注和取关:点击关注按钮就会发出请求(上图):http://127. ...

  6. ChatGPT 中文指令指南,教会你如何使用chatgpt实现中文你想要的答案

    ChatGPT 中文指令指南,教会你如何使用chatgpt实现中文你想要的答案 1.学习英语--替代词典 App 场景 例子 Prompts 解释中文英文意思,并解释单词的词根词缀.可以替代词典. 告 ...

  7. .NET Core 离线生成 Tron 波场私钥和地址笔记

    NuGet 引入依赖库 PM> Install-Package Tron.Wallet.Net 随机生成私钥和对应的地址 using Tron.Wallet.Net; namespace Con ...

  8. 2022-12-12:有n个城市,城市从0到n-1进行编号。小美最初住在k号城市中 在接下来的m天里,小美每天会收到一个任务 她可以选择完成当天的任务或者放弃该任务 第i天的任务需要在ci号城市完成,

    2022-12-12:有n个城市,城市从0到n-1进行编号.小美最初住在k号城市中 在接下来的m天里,小美每天会收到一个任务 她可以选择完成当天的任务或者放弃该任务 第i天的任务需要在ci号城市完成, ...

  9. 2020-09-08:KVM和OpenStack的区别?

    福哥答案2020-09-08:[此答案来自知乎](https://www.zhihu.com/question/419987391)KVM只是一个虚拟机技术,别的还有xen,商业的vmware.vir ...

  10. vue全家桶进阶之路46:Vue3 Axios拦截器

    在Vue.js 3中,使用Axios与Vue.js 2.x中类似,但是需要进行一些修改和更新,下面是Vue.js 3中Axios的定义和使用方式: 首先,你需要安装Axios和Vue.js 3.x,可 ...