Proxyman for mac lldb 调试 dylib 注入

查看 168|回复 11
作者:Vvvvvoid   
关于

Proxyman (Version 5.1.1 (50101)) (https://proxyman.io/)

Proxyman是一款专为macOS设计的现代本地Web调试代{过}{滤}理工具,它不仅支持macOS平台,还能无缝地与iOS和Android设备进行集成。作为一个网络调试工具,Proxyman的设计旨在提供高性能、直观且功能丰富的解决方案,使开发者能够深入网络层进行调试和问题解决。
环境/软件
  • MacOS
  • IDA/Hopper
  • xcode
    -注入工具: https://github.com/tyilo/insert_dylib

    分析
    免费版有诸多限制; 比如 maping 映射规则只能有一个;


    1.png (184.77 KB, 下载次数: 1)
    下载附件
    2024-4-10 11:24 上传

    从关键字入手 "您已达到免费版可用规则的上";
    全局定位到主程序下 (/Applications/Proxyman.app/Contents/Resources/zh-Hans.lproj/Localizable.strings):
    /* No comment provided by engineer. */
    "You have reached the limit of free rules\n(Limit at %d)" = "您已达到免费版可用规则的上限\\n(限制在 %d 处)";
    主程序 bin 拖入 hopper 中搜索
    aYouHaveReached_100325010:        // aYouHaveReached
    0000000100325010         db         "You have reached the limit of free rules\n(Limit at %d)", 0
    x 查看引用链


    2.png (60.21 KB, 下载次数: 1)
    下载附件
    2024-4-10 11:24 上传

    只要一个引用,进入函数
    0000000100135cd0         lea        rsi, qword [aYouHaveReached_100325010+32]   ; 0x100325030
    然后 F5, 查看假码,看不出来啥..
    在 hopper中 往上看看, 找到函数首
    sub_100135551:
    0000000100135551         cmp        qword [rbp-0x38], 0x2                       ; CODE XREF=sub_100134540+685, sub_100134540+694
    0000000100135556         jne        loc_1001358a2
    000000010013555c         test       rax, rax
    000000010013555f         jne        loc_1001358a2
    用 lldb 调试看看
    lldb "/Applications/Proxyman.app"
    载入后, r 运行;
    程序启动后 ctrl + c ,暂停 , 之后下断点 br s -a 0x100135551
    然后反复复现创建rule规则, 发现断不下来... 有点奇怪;
    我们我们在 lldb 中 dis -a 0x100135551 , lldb 的查看汇编代码似乎比 hopper 的高级呢,找到了真实的函数首;
    (lldb) dis -a 0x100135551
    Proxyman`___lldb_unnamed_symbol9700:
    Proxyman[0x1001324b0] :     pushq  %rbp
    Proxyman[0x1001324b1] :     movq   %rsp, %rbp
    Proxyman[0x1001324b4] :     pushq  %r15
    Proxyman[0x1001324b6] :     pushq  %r14
    Proxyman[0x1001324b8] :     pushq  %r13
    Proxyman[0x1001324ba] :    pushq  %r12
    Proxyman[0x1001324bc] :    pushq  %rbx
    接着下一个断点 br s -a 0x1001324b0
    (lldb) br s -a 0x1001324b0
    Breakpoint 1: address = 0x00000001001324b0
    然后继续创建rule规则, 成功断下来了;
    bt 查看堆栈
    (lldb) bt
    * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 3.1
      * frame #0: 0x00000001001324b0 Proxyman`___lldb_unnamed_symbol9700 // sub_1001324b0 弹框 alert 需要充值
        frame #1: 0x00000001001adefb Proxyman`___lldb_unnamed_symbol12544 + 171 //  call sub_1001324b0
        frame #2: 0x00000001001ad9ef Proxyman`___lldb_unnamed_symbol12534 + 79 // call sub_1001ade50   
        frame #3: 0x0000000102fb0e6c ProxymanCore`ProxymanCore.runOnMainThread(() -> ()) -> () + 140
        frame #4: 0x00000001001ad313 Proxyman`___lldb_unnamed_symbol12530 + 595 // thread
        frame #5: 0x0000000100054ae3 Proxyman`___lldb_unnamed_symbol4628 + 99 // call       sub_1001ad0c0 cmp 01 , // 需要 ret 0
        frame #6: 0x00000001000534ea Proxyman`___lldb_unnamed_symbol4620 + 74
        frame #7: 0x00007ff80aaff2b6 AppKit`-[NSApplication(NSResponder) sendAction:to:from:] + 337
        frame #8: 0x00007ff80aaff12b AppKit`-[NSControl sendAction:to:] + 86
        frame #9: 0x00007ff80aaff05d AppKit`__26-[NSCell _sendActionFrom:]_block_invoke + 131
        frame #10: 0x00007ff80aafef66 AppKit`-[NSCell _sendActionFrom:] + 171
        frame #11: 0x00007ff80aafeeae AppKit`-[NSButtonCell _sendActionFrom:] + 96
        frame #12: 0x00007ff80aafbdd2 AppKit`NSControlTrackMouse + 1823
        frame #13: 0x00007ff80aafb68f AppKit`-[NSCell trackMouse:inRect:ofView:untilMouseUp:] + 125
        frame #14: 0x00007ff80aafb556 AppKit`-[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] + 666
        frame #15: 0x00007ff80aafa94b AppKit`-[NSControl mouseDown:] + 666
        frame #16: 0x00007ff80aaf92f3 AppKit`-[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:] + 4582
        frame #17: 0x00007ff80aa720ce AppKit`-[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] + 404
        frame #18: 0x00007ff80aa71d1f AppKit`-[NSWindow(NSEventRouting) sendEvent:] + 345
        frame #19: 0x00007ff80b2212b6 AppKit`-[NSApplication(NSEventRouting) sendEvent:] + 346
        frame #20: 0x00007ff80addc5c2 AppKit`-[NSApplication _handleEvent:] + 65
        frame #21: 0x00007ff80a90402a AppKit`-[NSApplication run] + 640
        frame #22: 0x00007ff80a8d7ff1 AppKit`NSApplicationMain + 816
        frame #23: 0x0000000100067e79 Proxyman`___lldb_unnamed_symbol5090 + 9
        frame #24: 0x00007ff806e44366 dyld`start + 1942
    前面几个 堆栈没看出啥;
    看 #5: 0x0000000100054ae3


    4.png (131.14 KB, 下载次数: 0)
    下载附件
    2024-4-10 11:24 上传

    简单分析一下; 第 11 行 调用 sub_1001ad0c0 函数, rax == 0 的话会show 一个 windoow; 盲猜是配置 rule 详情的 window
    0000000100054ade         call       sub_1001ad0c0                               ; sub_1001ad0c0
    0000000100054ae3         test       al, 0x1
    0000000100054ae5         je         loc_100054af6
    我们在 0x100054ae3 下一个断点看看; br s -a 0x100054ae3; 然后回到程序,创建规则; 这个时候弹框了, 先不要管;按确定;然后 断下来了;
    lldb 查看当前寄存器 al 为 1, 我们修改为 0 看看,然后 c 继续;
    (lldb) register read al
          al = 0x01
    (lldb) register write al 0
    (lldb) register read al
          al = 0x00
    (lldb)
    发现已经成功出现了创建 rule 的页面了; 但是此刻弹框依然存在;


    5.png (237.45 KB, 下载次数: 1)
    下载附件
    2024-4-10 11:24 上传



    6.png (127.49 KB, 下载次数: 1)
    下载附件
    2024-4-10 11:24 上传

    至此,我们可以得出结论 sub_1001ad0c0 有俩个作用
    [ol]
  • 函数里会判断是否弹框 (具体逻辑逻辑)
  • 函数返回值会判断是否创建 rule (根据返回值 ==0 触发)
    [/ol]
    接着 我们进入函数 sub_1001ad0c0 里看看


    7.png (203.13 KB, 下载次数: 1)
    下载附件
    2024-4-10 11:24 上传

    qword_10044b170, qword_100466550 这俩个地址 是程序的常量,逻辑判断始终成立;不用管;
    函数的返回值取决于 第 14 行
    rax = sub_10001af90(&var_D0, &var_128);
    int sub_10001af90(int arg0, int arg1) {
    ((0x1003bc2d8 + 0x20))(arg1, arg0, 0x1003bc2e0);
    rax = arg1;
    return rax;
    }
    sub_10001af90 这个函数的代码看着有点抽象, 就不继续看了,盲猜他是搞弹框 alert 的;
    我们直接 hook ret 0 看看;
    这里采用 dylib 注入来 hook ;
    注意不要注入主程序, 可能会导致主程序 签名与 heler 不一致; 而启动不了;
    我们去  FrameWoork 下挑一个来注入 /Applications/Proxyman.app/Contents/Frameworks/HexFiend.framework/Versions/A/HexFiend
    DobbyHook((void *)_sub_0x10001af90, ret0, nil);
    注入后 启动程序,成功注册 (居然 license 给了 Setapp..)


    8.png (55.96 KB, 下载次数: 0)
    下载附件
    2024-4-10 11:24 上传

    运行了一段时间; 发现还需要处理下  remainingDays 这个 函数,有概率程序会报错, 我们把调用的地方写入 mov rax 1 即可;
    因为 mov rax 1 比 原生的 call xxx 的机器码长, 所以改成 push 1,pop rax;
    call       imp_stubs$s12ProxymanCore7LicenseV13remainingDaysSiSgvg >>>>> push 1,pop rax
    function $s12ProxymanCore7LicenseV13remainingDaysSiSgvg {
        rax = (*pointer to ProxymanCore.License.remainingDays.getter : Swift.Int?)();
        return rax;
    }
    //push 1,pop rax
    uint8_t ret1Day[5] = {0x6A, 0x01, 0x58, 0x90, 0x90  };
    DobbyCodePatch((void *)_remainingDaysCode, ret1Day,5);
    至此,结束, x64/arm 通杀特征码如下:
    #if defined(__arm64__) || defined(__aarch64__)
        NSString *sub_0x10001af90Code = @"F4 4F BE A9 FD 7B 01 A9 FD 43 00 91 F3 03 01 AA E1 03 00 AA .. .. 00 90 42 C0 20 91 48 80 5F F8 08 11 40 F9 E0 03 13 AA 00 01 3F D6 E0 03 13 AA FD 7B 41 A9 F4 4F C2 A8 C0 03 5F D6";
        NSString *remainingDaysCode = @".. .. .. 94 F4 03 00 AA F5 03 01 AA E0 83 01 91 .. .. .. 94 28 00 80 52 89 FE 7F D3 BF 02 00 72 34 01 88 1A";
    #elif defined(__x86_64__)
        NSString *sub_0x10001af90Code = @"55 48 89 E5 53 50 48 89 F3 48 89 FE 48 8D .. .. .. .. .. 48 8B 42 F8 48 89 DF FF 50 20 48 89 D8 48 83 C4 08 5B 5D C3";
        NSString *remainingDaysCode =@"E8 .. .. .. .. 49 89 C6 41 89 D7 48 8D BD C8 FE FF FF E8 .. .. .. .. 41 B4 01 41 F6 C7 01 75 ..";
        DobbyHook((void *)_sub_0x10001af90, ret0, nil);
       NSLog(@">>>>>> Before %s",[MemoryUtils readMachineCodeStringAtAddress:_remainingDaysCode length:8].UTF8String);
    #if defined(__arm64__) || defined(__aarch64__)
        // nop:0x1F, 0x20, 0x03, 0xD5
        // mov x0,#1
        uint8_t ret1Day[4] = {0x20, 0x00, 0x80, 0xD2  };
        DobbyCodePatch((void *)_remainingDaysCode, ret1Day,4);
    #elif defined(__x86_64__)
        //push 1,pop rax
        uint8_t ret1Day[5] = {0x6A, 0x01, 0x58, 0x90, 0x90  };
        DobbyCodePatch((void *)_remainingDaysCode, ret1Day,5);
    #endif
        NSLog(@">>>>>> After %s",[MemoryUtils readMachineCodeStringAtAddress:_remainingDaysCode length:8].UTF8String);
    #endif
    Quick Start
    项目已经打包 github,可以直接用 xcode 打开 :
    https://github.com/marlkiller/dylib_dobby_hook  
    git clone https://github.com/marlkiller/dylib_dobby_hook.git
    cd script
    sudo sh auto_hack.sh
    About ME
    找个 JAVA 的工作好难呀 , 加上逆向 Surge 搞的我头大, 搞不明白;
    我还是找个软柿子捏捏把...

    下载次数, 函数

  • cyhlnj   

    -------------------------------------
    Translated Report (Full Report Below)
    -------------------------------------
    Process:               Proxyman [2370]
    Path:                  /Applications/Proxyman.app/Contents/MacOS/Proxyman
    Identifier:            com.proxyman.NSProxy
    Version:               5.1.0 (50100)
    Code Type:             ARM-64 (Native)
    Parent Process:        launchd [1]
    User ID:               501
    Date/Time:             2024-04-15 17:13:02.9576 +0800
    OS Version:            macOS 13.5 (22G74)
    Report Version:        12
    Anonymous UUID:        E265310A-937D-ED2A-E258-FF75A2013911
    Time Awake Since Boot: 1100 seconds
    System Integrity Protection: disabled
    Crashed Thread:        0  Dispatch queue: com.apple.main-thread
    Exception Type:        EXC_CRASH (SIGABRT)
    Exception Codes:       0x0000000000000000, 0x0000000000000000
    Termination Reason:    Namespace SIGNAL, Code 6 Abort trap: 6
    Terminating Process:   Proxyman [2370]
    Application Specific Information:
    abort() called
    Application Specific Backtrace 0:
    0   CoreFoundation                      0x000000019487b154 __exceptionPreprocess + 176
    1   libobjc.A.dylib                     0x000000019439a4d4 objc_exception_throw + 60
    2   CoreFoundation                      0x00000001948a81b4 CFArrayApply + 0
    3   libdylib_dobby_hook.dylib           0x00000001008cf5dc -[ProxyManHack hack] + 260
    4   libdylib_dobby_hook.dylib           0x00000001008d3204 +[Constant doHack] + 696
    5   libdylib_dobby_hook.dylib           0x00000001008cf9a0 +[dylib_dobby_hook load] + 180
    6   libobjc.A.dylib                     0x000000019438c460 load_images + 828
    7   dyld                                0x00000001943d9880 _ZN5dyld412RuntimeState14notifyObjCInitEPKNS_6LoaderE + 164
    8   dyld                                0x00000001943e4c04 _ZNK5dyld46Loader23runInitializersBottomUpERNS_12RuntimeStateERN5dyld35ArrayIPKS0_EE + 208
    9   dyld                                0x00000001943e4bec _ZNK5dyld46Loader23runInitializersBottomUpERNS_12RuntimeStateERN5dyld35ArrayIPKS0_EE + 184
    10  dyld                                0x00000001943e4bec _ZNK5dyld46Loader23runInitializersBottomUpERNS_12RuntimeStateERN5dyld35ArrayIPKS0_EE + 184
    11  dyld                                0x00000001943e8264 _ZZNK5dyld46Loader38runInitializersBottomUpPlusUpwardLinksERNS_12RuntimeStateEENK3$_1clEv + 112
    12  dyld                                0x00000001943e4d90 _ZNK5dyld46Loader38runInitializersBottomUpPlusUpwardLinksERNS_12RuntimeStateE + 304
    13  dyld                                0x0000000194408984 _ZN5dyld44APIs25runAllInitializersForMainEv + 468
    14  dyld                                0x00000001943cd2d0 _ZN5dyld4L7prepareERNS_4APIsEPKN5dyld313MachOAnalyzerE + 3480
    15  dyld                                0x00000001943cbe18 start + 1964
    cyhlnj   


    Vvvvvoid 发表于 2024-4-12 18:12
    下的最新版 version 5.1.1,
    特征吗应该通杀后续几个版本吧

    哥 我上次试了 结果破解完显示
    Termination Reason:    Namespace DYLD, Code 1 Library missing
    Library not loaded: @loader_path/../Frameworks/HexFiend.framework/Versions/A/HexFiend
    Referenced from:  /Applications/Proxyman.app/Contents/MacOS/Proxyman
    Reason: tried: '/Applications/Proxyman.app/Contents/MacOS/../Frameworks/HexFiend.framework/Versions/A/HexFiend' (code signature in  '/Applications/Proxyman.app/Contents/Frameworks/HexFiend.framework/Versions/A/HexFiend' not valid for use in process: Trying to load an unsigned library)
    (terminated at launch; ignore backtrace)
    Vvvvvoid
    OP
      

    你这家伙大有赶超我的实力,后起之秀,可怕可怕~@Vvvvvoid
    g320210   


    smile1110 发表于 2024-4-10 13:37
    你这家伙大有赶超我的实力,后起之秀,可怕可怕~@Vvvvvoid

    最近很闲,正好有空学习😄
    vans4u1   

    最近很闲,正好有空学习
    gaoyanchen   

    1:注意不要注入主程序, 可能会导致主程序 签名与 heler 不一致; 而启动不了;
    我们去  FrameWoork 下挑一个来注入 /Applications/Proxyman.app/Contents/Frameworks/HexFiend.framework/Versions/A/HexFiend
    2:因为 mov rax 1 比 原生的 call xxx 的机器码长, 所以改成 push 1,pop rax;
    牛,学到这两点!
    eijop252023   

    学习 学习
    ansenmo   

    学习了666666
    250737355   

    太强了。。感谢大佬分享
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部