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. 部署:Mysql8和Mysql5.7部署同一服务器

    问题描述:将Mysql8.0.22和Mysql5.7.32部署在同一环境下 操作系统:centos7.8 数据库:Mysql8.0.22.Mysql5.7.32 版本 占用端口 实例名 数据文件 端口 ...

  2. 笔记七:进程间的通信(IPC通信之信号灯)

    信号量 定义信号变量:  sem_t sem1 sem2 初始化信号量 P操作           V操作    功能 信号量(POSOX) 信号量灯(IPC) 定义信号变量 sem_t  sem1 ...

  3. 当我第一次通过Kotlin和Compose来实现一个Canvas时, 我收获了什么?

    当我第一次通过Kotlin和Compose来实现一个Canvas时, 我收获了什么? 自从2019年Google推荐Kotlin为Android开发的首选语言以来已经经历了将近四年的时间, Compo ...

  4. 产品质量管理利器,华为云发布CodeArts Defect缺陷管理服务

    摘要:近日,华为云CodeArts Defect缺陷管理服务正式上线,提供结构化缺陷跟踪流程和标准化的质量度量模型. 本文分享自华为云社区<产品质量管理利器,华为云发布CodeArts Defe ...

  5. Netty之数据解码

    一.概况 作为Java世界使用最广泛的网络通信框架Netty,其性能和效率是有目共睹的,好多大公司都在使用如苹果.谷歌.Facebook.Twitter.阿里巴巴等,所以不仅仅是因为Netty有高效的 ...

  6. ai问答:使用vite如何配置多入口页面

    Vite 是一个 web 开发构建工具,它可以用于开发单页应用和多页应用.要在 Vite 中配置多入口,可以: 在 vite.config.js 中定义多个 entry 入口: export defa ...

  7. 2022-06-12:在N*N的正方形棋盘中,有N*N个棋子,那么每个格子正好可以拥有一个棋子。 但是现在有些棋子聚集到一个格子上了,比如: 2 0 3 0 1 0 3 0 0 如上的二维数组代表,一

    2022-06-12:在NN的正方形棋盘中,有NN个棋子,那么每个格子正好可以拥有一个棋子. 但是现在有些棋子聚集到一个格子上了,比如: 2 0 3 0 1 0 3 0 0 如上的二维数组代表,一共3 ...

  8. 2022-04-08:在一张 无向 图上,节点编号0~N-1。老鼠开始在1节点,猫在2节点,0号节点是洞,老鼠想进洞, 老鼠第先出发,猫后出发,轮流行动。 在每个玩家的行动中,他们 必须 沿着图中与所

    2022-04-08:在一张 无向 图上,节点编号0~N-1.老鼠开始在1节点,猫在2节点,0号节点是洞,老鼠想进洞, 老鼠第先出发,猫后出发,轮流行动. 在每个玩家的行动中,他们 必须 沿着图中与所 ...

  9. 2021-04-23:TSP问题 有N个城市,任何两个城市之间的都有距离,任何一座城市到自己的距离都为0。所有点到点的距 离都存在一个N*N的二维数组matrix里,也就是整张图由邻接矩阵表示。现要求

    2021-04-23:TSP问题 有N个城市,任何两个城市之间的都有距离,任何一座城市到自己的距离都为0.所有点到点的距 离都存在一个N*N的二维数组matrix里,也就是整张图由邻接矩阵表示.现要求 ...

  10. 2021-08-30:给定两个字符串str1和str2,在str1中寻找一个最短子串,能包含str2的所有字符,字符顺序无所谓,str1的这个最短子串也可以包含多余的字符。返回这个最短包含子串。

    2021-08-30:给定两个字符串str1和str2,在str1中寻找一个最短子串,能包含str2的所有字符,字符顺序无所谓,str1的这个最短子串也可以包含多余的字符.返回这个最短包含子串. 福大 ...