背景
电脑里充斥了大量的 MarkDown 文件,之前都是编译 MacDown 的代码来用,但管理起大量的文件来就力不从心了,同时公司要求不能用其他公司的云产品,朋友推荐了 MWeb,据说是国产 App 难得好用的工具,简单用了下,还不错。
当然,这款 App 不是免费的,不算便宜,可以试用 14 天,
这里还是鼓励大家使用正版,逆向只为学习和玩。。。
分析
Run 起来 App 后,第一反应当然是根据弹框中显示的字符串定位逻辑,将二进制拖进 Hopper 中,
然后发现这些函数都是在 Appdelegate 中,且注意到弹框是在 App 启动后被拉起来,所以搜索 App 的生命周期函数,重点分析一下,就很快找到了线索,
细细分析一下即可知道这里的逻辑是:
- 禁止 UI
- 判断是否有权限(这里采用 c 函数,意图增大逆向难度)
- 如果有权限则取消禁止 UI
- 如果没有权限则走试用等逻辑,这里集成了 DevMateKit 来处理
所以这里关键函数就是这个 sub_100246a60,
所以只要 Hook 这个 c 函数,return 1 即可。
步骤
- 新建 MacOS 动态库
- Hook sub_100246a60,代码如下
intptr_t g_slide;
static void _register_func_for_add_image(const struct mach_header *header, intptr_t slide) {
Dl_info image_info;
int result = dladdr(header, &image_info);
if (result == 0) {
NSLog(@"load mach_header failed");
return;
}
//获取当前的可执行文件路径
// NSString *execName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleExecutable"];
NSString *execName = @"Contents/MacOS/MWeb";
NSString *execPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingFormat:@"/%@", execName];
if (strcmp([execPath UTF8String], image_info.dli_fname) == 0) {
g_slide = slide;
}
}
int (*orig_SubMethod)(char);
int hook_SubMethod(char arg) {
return 1;
}
static void __attribute__((constructor)) initialize(void) {
//注册添加镜像回调
_dyld_register_func_for_add_image(_register_func_for_add_image);
//通过 模块偏移前的基地址 + ASLR偏移量 找到函数真正的地址进行hook
MSHookFunction((void *)(0x0000000100246a60 + g_slide), (void *)hook_SubMethod, (void **)&orig_SubMethod);
这里需要引入 libsubstitute.dylib 和 substrate.h
需要编译 substitute,直接编译会报错 syscall 被弃用,可下载早一些的 SDK 如 MacOSX10.11.sdk,然后放到/Applications/XCode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs下。
然后通过如下命令行编译:
./configure --xcode-sdk macosx10.11 && make -j8
在out目录就可以看到生成的动态库。
将其重命名为libsubstitute.0.dylib 并拷贝到/usr/local/lib/
- 调试时可以在 Build Phases 中添加脚本,
cd ${TARGET_BUILD_DIR}
export DYLD_INSERT_LIBRARIES=./libMWeb.dylib && /Applications/MWeb.app/Contents/MacOS/MWeb
Cmd + B 即可拉起 App,当 App 启动后,通过 Debug - Attach To Process 即可开始断点调试
- 当调试完成后,可参考 打包 中的方法将 App 打包使用,当然也可以对 App 直接用 insert_dylib 进行动态库注入使用