吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4709|回复: 27
收起左侧

[MacOS逆向] 破解Paste: 基于LLDB堆栈跟踪与Frida调试

  [复制链接]
QiuChenly 发表于 2023-4-11 19:29
本帖最后由 QiuChenly 于 2023-4-12 00:44 编辑

  没有注入补丁。因为Paste只有一个主程序文件,不方便注入。
本来这个帖子是有剧情的,但是情感失利,妹子常规好感度完美开局48小时内打成残血副本:
油腻男的聊天风格直接触发妹子的无视微信消息大招,绷不住了,绝望下编写此帖,实在没心情创作了😭😭😭😭😭
现在是半夜00:44还在emo😭😭😭😭😭😭😭😭😭😭

0x01 寻找入口点与分析

16811420538989.jpg
  放错图了。这里应该是未激活的状态,差不多意思意思吧这样子。
16811421036157.jpg
  因为楼主买不起苹果电脑手机平板,所以只能幻想自己左苹果右华为胸口纹嘉然脑门贴nanami的雄姿。
  老样子搜索字符串,这次用Sublime Text。
  根据上图的内容,我们尝试搜索“立即开始免费试用”:

16812037573708.jpg
这里"licensing.paywall.title"我们到ida搜索一下:
16812043285737.jpg
按下x看一下xref引用看看函数细节:
16812043519751.jpg
这里函数又被两个地方调用,我们直接用lldb看一下函数调用堆栈.我们记下这个函数地址方便后面下断点.
16812040802761.jpg
加载后我们先输入c让他继续运行。
然后我们给内存地址:0x1002253E0下断点: br s -a 1002253E0
随后输入r重启app,可以看到直接被断下了:
16812044276264.jpg
那么我们往上查堆栈看是谁触发这个Call:

* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 4.1
    frame #0: 0x00000001002253e0 Paste`___lldb_unnamed_symbol16296
Paste`___lldb_unnamed_symbol16296:
->  0x1002253e0 <+0>:  push   rbp
    0x1002253e1 <+1>:  mov    rbp, rsp
    0x1002253e4 <+4>:  lea    rax, [rip + 0x167715]     ; "licensing.paywall.title"
    0x1002253eb <+11>: movabs rsi, -0x8000000000000000
Target 0: (Paste) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 4.1
  * frame #0: 0x00000001002253e0 Paste`___lldb_unnamed_symbol16296
    frame #1: 0x00007ff817b19033 libdispatch.dylib`_dispatch_client_callout + 8
    frame #2: 0x00007ff817b1a267 libdispatch.dylib`_dispatch_once_callout + 20
    frame #3: 0x000000010022544a Paste`___lldb_unnamed_symbol16297 + 42
    frame #4: 0x00000001001f8045 Paste`___lldb_unnamed_symbol14918 + 293
    frame #5: 0x00000001001f8905 Paste`___lldb_unnamed_symbol14923 + 37
    frame #138: 0x00000001002489e6 Paste`___lldb_unnamed_symbol17865 + 86
    frame #139: 0x0000000100248800 Paste`___lldb_unnamed_symbol17861 + 16
    frame #140: 0x0000000100247a8e Paste`___lldb_unnamed_symbol17812 + 302
    frame #141: 0x000000010006127a Paste`___lldb_unnamed_symbol5177 + 778
    frame #142: 0x0000000100066423 Paste`___lldb_unnamed_symbol5291 + 195
    frame #143: 0x0000000100068970 Paste`___lldb_unnamed_symbol5356
    frame #144: 0x0000000100067870 Paste`___lldb_unnamed_symbol5313
    frame #145: 0x0000000100068930 Paste`___lldb_unnamed_symbol5354

那么我们重点关注栈3-5-138-145,因为下面都是系统库,所以我们直接看#3看看有没有发现:

void *sub_100225420()
{
  if ( qword_100466E50 != -1 )
    swift_once(&qword_100466E50, sub_1002253E0);
  return &unk_10046CF50;
}

qword_100466E50必然不是-1,所以这里没有可检查的必要,我们继续回溯到#142: 0x0000000100066423:

__int64 __fastcall sub_100066360()
{
  __int64 v0; // r13
  __int64 *v1; // r14
  __int64 v2; // r15
  __int64 v3; // r12
  __int64 v4; // rax
  __int64 v5; // r14
  __int64 v6; // rbx
  void *v7; // r14
  __int64 v8; // rdi
  __int64 v9; // r13
  __int64 v10; // rbx
  __int64 v11; // r15

  v2 = *v1;
  v3 = *v1;
  swift_task_dealloc(*(_QWORD *)(*v1 + 48));
  if ( v0 )
    swift_errorRelease(v0);
  v4 = *(_QWORD *)(v2 + 24);
  v5 = *(_QWORD *)(v4 + 80);
  v6 = *(_QWORD *)(v4 + 88);
  sub_10000B980(v4 + 56, v5);
  if ( ((*(__int64 (__fastcall **)(__int64, __int64))(v6 + 8))(v5, v6) & 1) != 0 )
  {
    if ( *(_BYTE *)(v2 + 56) == 1 )
    {
      (*(void (**)(void))(v2 + 32))();
    }
    else if ( (sub_100068390() & 1) != 0 )
    {
      sub_100066460();
    }
  }
  else
  {
    v7 = *(void **)(v2 + 40);
    v8 = *(_QWORD *)(v2 + 24);
    v9 = *(_QWORD *)(v2 + 32);
    v10 = *(_QWORD *)(v8 + 280);
    v11 = *(_QWORD *)sub_10000B980(v8 + 144, *(_QWORD *)(v8 + 168));
    swift_retain(v10);
    sub_100060F70(v11, v9, v7, v10);
    swift_release(v10);
  }
  return (*(__int64 (**)(void))(v3 + 8))();
}

可以看到这里(v6 + 8)这个指针所在的地址函数如果等于0 就执行到了我们的#142堆栈。

  else
  {
    v7 = *(void **)(v2 + 40);
    v8 = *(_QWORD *)(v2 + 24);
    v9 = *(_QWORD *)(v2 + 32);
    v10 = *(_QWORD *)(v8 + 280);
    v11 = *(_QWORD *)sub_10000B980(v8 + 144, *(_QWORD *)(v8 + 168));
    swift_retain(v10);
    sub_100060F70(v11, v9, v7, v10);
    swift_release(v10);
  }

所以我们的工作重点放在这里这个判断上,在lldb中给这个地址下断点:

__text:00000001000663A8 loc_1000663A8:                          ; CODE XREF: sub_100066360+3E↑j
__text:00000001000663A8                 mov     rax, [r15+18h]
__text:00000001000663AC                 lea     rdi, [rax+38h]
__text:00000001000663B0                 mov     r14, [rax+50h]
__text:00000001000663B4                 mov     rbx, [rax+58h]
__text:00000001000663B8                 mov     rsi, r14
__text:00000001000663BB                 call    sub_10000B980
__text:00000001000663C0                 mov     r13, rax
__text:00000001000663C3                 mov     rdi, r14
__text:00000001000663C6                 mov     rsi, rbx
__text:00000001000663C9                 call    qword ptr [rbx+8]  <-----这里下断点
__text:00000001000663CC                 test    al, 1
__text:00000001000663CE                 jz      short loc_1000663E1

lldb中输入br s -a 0x1000663c9,然后输入r重启,可以看到自动断下:

Process 28613 resuming
Process 28613 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 6.1
    frame #0: 0x00000001000663c9 Paste`___lldb_unnamed_symbol5291 + 105
Paste`___lldb_unnamed_symbol5291:
->  0x1000663c9 <+105>: call   qword ptr [rbx + 0x8]
    0x1000663cc <+108>: test   al, 0x1
    0x1000663ce <+110>: je     0x1000663e1               ; <+129>
    0x1000663d0 <+112>: cmp    byte ptr [r15 + 0x38], 0x1
Target 0: (Paste) stopped.
(lldb) 

我们来StepInto 这个Call:
16812062048060.jpg
我们IDA看一下这个地址所在的函数是干嘛的:

__int64 __fastcall sub_1001FBF10(__int64 a1, __int64 a2)
{
  __int64 v2; // rax
  __int64 v3; // r13
  void *v4; // rsp
  void *v5; // rsp
  __int64 v6; // rdi
  __int64 v7; // rax
  unsigned int v8; // ebx
  _QWORD v10[6]; // [rsp-8h] [rbp-30h] BYREF

  v10[0] = v2;
  sub_10000B6A0(&unk_100454320);
  v4 = alloca(sub_10000C800(&unk_100454320, a2));
  v5 = alloca(sub_10000C800(&unk_100454320, a2));
  v6 = *(_QWORD *)(*(_QWORD *)v3 + 16LL);
  swift_retain(v6);
  _s7Combine19CurrentValueSubjectC5valuexvg();
  swift_release(v6);
  sub_1001FC3D0(v10, v10, &unk_100454320);
  v7 = sub_1001F95A0(0LL);
  v8 = (*(__int64 (__fastcall **)(_QWORD *, __int64, __int64))(*(_QWORD *)(v7 - 8) + 48LL))(v10, 1LL, v7);
  if ( v8 != 1 )
    sub_1001FC400(v10, &unk_100454320);
  LOBYTE(v8) = v8 != 1;
  sub_1001FC400(v10, &unk_100454320);
  return v8;
}

可以看出v8返回值为0或者1,因为他有一个v8!=1的判断在这里,那么我们如果Hook 0x1001FBF10这个函数的返回值是否就ok了呢?
编写Frida代码进行内存注入:

import { HookApp, log } from "./Utils.js";

HookApp("Paste", (hook, point, method, baseAddr, tools) => {
  // setTimeout(() => {
  //   hook(point(0x1f9f10), (ths, r) => {
  //     // r.replace(ptr(2));
  //   });
  // }, 3000);
  hook(point(0x1fbf10), (ths, r) => {
    r.replace(ptr(1));
  });
});

狠狠的按下F5启动,我们看看是否注入成功:
16812068323518.jpg
这里没有去修改有效订阅的那个函数,因为修改了这个信息之后会因为无法读取订阅数据而导致App崩溃,而且Paste只检查了0x1fbf10这个函数,所以我们直接返回1即可完成。

0x02 总结

文中使用的Frida js全文如下:

var appBaseAddr = Module.findBaseAddress("Paste");
var func = appBaseAddr.add(0x1fbf10)
Interceptor.attach(func, {
    onEnter(this1, args) {
    },
    onLeave(retval) {
        retval.replace(0x1)
    },
})

安装python和Frida后,frida -p pid -l main.js启动注入。pid是进程列表中的进程id。

免费评分

参与人数 9威望 +1 吾爱币 +30 热心值 +9 收起 理由
smile1110 + 3 + 1 高手,哈哈哈
SoryuASK + 1 + 1 我很赞同!
jack_king + 1 + 1 我很赞同!
pdc9911 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Zz4794zZ + 1 + 1 用心讨论,共获提升!
外酥内嫩 + 1 + 1 楼主快给我振作起来
pjy612 + 1 + 1 我很赞同!
lingyun011 + 1 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

jack_king 发表于 2023-4-26 10:42
mac m1 使用 rosetta 打开 paste。执行 frida -p  pid -l main.js 的时候报错 Failed to attach: module not found at "/usr/lib/libSystem.B.dylib"

楼主这种问题有没有遇到? frida 和 rosetta都升级最新版了,还是没解决,网上也没找到类似的问题
 楼主| QiuChenly 发表于 2023-4-12 01:13
hoochanlon 发表于 2023-4-11 20:27
那么“0x01 寻找入口点与分析”标题里的最后一段话,“返回1”,意思就是保持订阅试用期内咯。

也并不是  因为他的判断逻辑是如果订阅有效那么这个地址函数一定会返回1 不区分是试用期还是有效授权期 因为这个函数就是一个判断用户是否为vip的功能
hoochanlon 发表于 2023-4-11 20:27
那么“0x01 寻找入口点与分析”标题里的最后一段话,“返回1”,意思就是保持订阅试用期内咯。
Jooing 发表于 2023-4-11 21:49
跪着看完大神贴
pjy612 发表于 2023-4-11 21:54
仙侠风没有了。。。

不过还是好厉害
csdoc 发表于 2023-4-11 22:02
高产的高手!&#128077;
m0fx 发表于 2023-4-11 23:23
膜拜大佬,涨姿势了
deTrident 发表于 2023-4-11 23:55
学习了,原来可以这样注入,查找关键点费了很多功夫吧
xixicoco 发表于 2023-4-11 23:59
大佬厉害啊
SuperMelon 发表于 2023-4-12 05:04
大佬真牛逼
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 09:14

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表