使用 Radare 2 拆卸 Objective C Mach-O 的方法

逆向工程 雷达2 男子气概
2021-06-30 09:42:24

是否可以使用 Radare 2 检索在 Mach-O 文件中声明的 Objective-C 方法的反汇编?

2个回答

本质上,它是以下工作流程:

r2 -A /path/to/binary   // load the binary and perform initial analysis
afl                     // print function symbols
pdf @sym.of.interest    // disassemble
pdc @sym.of.interest    // "decompile" or generate pseudo code

下面是一个如何反汇编MachoViewer函数的例子

@0x4B6169:/$ r2 -A /Applications/MachOView.app/Contents/MacOS/MachOView 2>/dev/null
 -- Run .dmm* to load the flags of the symbols of all modules loaded in the debugger
[0x100001da0]> afl | grep sym.__MachOLayout_get
0x10000b252    4 49           sym.__MachOLayout_getSectionByIndex:_
0x10000b283    4 49           sym.__MachOLayout_getSection64ByIndex:_
0x10000b2b4    4 49           sym.__MachOLayout_getSymbolByIndex:_
0x10000b2e5    4 49           sym.__MachOLayout_getSymbol64ByIndex:_
0x10000b316    4 49           sym.__MachOLayout_getDylibByIndex:_
[0x100001da0]> pdf @sym.__MachOLayout_getSymbolByIndex:_
            ;-- func.10000b2b4:
            ;-- method.MachOLayout.getSymbolByIndex::
╒ (fcn) sym.__MachOLayout_getSymbolByIndex:_ 49
│           0x10000b2b4      55             push rbp
│           0x10000b2b5      4889e5         mov rbp, rsp
│           0x10000b2b8      89d0           mov eax, edx
│           0x10000b2ba      488b151f760f.  mov rdx, qword [rip + 0xf761f] ; [0x1001028e0:8]=176 LEA sym._OBJC_IVAR___MachOLayout.symbols ; sym._OBJC_IVAR___MachOLayout.symbols
│           0x10000b2c1      488b0c17       mov rcx, qword [rdi + rdx]
│           0x10000b2c5      488b541708     mov rdx, qword [rdi + rdx + 8] ; [0x8:8]=0x280000003
│           0x10000b2ca      4829ca         sub rdx, rcx
│           0x10000b2cd      48c1fa03       sar rdx, 3
│           0x10000b2d1      4839d0         cmp rax, rdx
│       ┌─< 0x10000b2d4      7306           jae 0x10000b2dc
│       │   0x10000b2d6      488b04c1       mov rax, qword [rcx + rax*8]
│      ┌──< 0x10000b2da      eb07           jmp 0x10000b2e3
│      ││   ; JMP XREF from 0x10000b2d4 (sym.__MachOLayout_getSymbolByIndex:_)
│      │└─> 0x10000b2dc      488d05e5fd0a.  lea rax, [rip + 0xafde5]   ; 0x1000bb0c8 ; sym.__MachOLayoutgetSymbolByIndex:_::notfound ; sym.__MachOLayoutgetSymbolByIndex:_::notfound
│      │    ; JMP XREF from 0x10000b2da (sym.__MachOLayout_getSymbolByIndex:_)
│      └──> 0x10000b2e3      5d             pop rbp
╘           0x10000b2e4      c3             ret
[0x100001da0]> quit

通过巧妙的逻辑命令输入生成某种形式的伪代码(“反编译”)的工作方式类似:

[0x100001da0]> pdc @sym.__MachOLayout_getSymbolByIndex:_
function sub.__MachOLayoutgetSymbolByIndex:_.notfound_2b4 () {
    loc_0x10000b2b4:

       push rbp
       rbp = rsp
       eax = edx
       rdx = qword sym._OBJC_IVAR___MachOLayout.symbols //[0x1001028e0:8]=176 ; "__text"
       rcx = qword [rdi + rdx]
       rdx = qword [rdi + rdx + 8] //[0x8:8]=0x280000003
       rdx -= rcx
       rdx >>= 3
       var = rax - rdx
       jae 0x10000b2dc          //unlikely
       {
        loc_0x10000b2dc:

         //JMP XREF from 0x10000b2d4 (sub.__MachOLayoutgetSymbolByIndex:_.notfound_2b4)
           rax = [sym.__MachOLayoutgetSymbolByIndex:_::notfound] //method.__MachOLayoutgetSymbolByIndex:_.notfound ; 0x1000bb0c8 ; method.__MachOLayoutgetSymbolByIndex:_.notfound
       do
       {
            loc_0x10000b2e3:

             //JMP XREF from 0x10000b2da (sub.__MachOLayoutgetSymbolByIndex:_.notfound_2b4)
               pop rbp

           } while (?);
       } while (?);
      }
      return;

}

hopper v4 中,您可以执行以下操作:

hopperv4 -e /Applications/MachOView.app/Contents/MacOS/MachOView

这将打开料斗,您可以单击“Proc”。选项卡,然后搜索该功能。点击后会看到如下反汇编(radare2 1.5.0 0 @ darwin-x86-64 git.1.5.0, commit: HEAD build: 2017-05-31__14:31:32):

000000010000b2b4         push       rbp                                         ; Objective C Implementation defined at 0x1000f5de8 (instance method), DATA XREF=0x1000f5de8
000000010000b2b5         mov        rbp, rsp
000000010000b2b8         mov        eax, edx
000000010000b2ba         mov        rdx, qword [_OBJC_IVAR_$_MachOLayout.symbols]
000000010000b2c1         mov        rcx, qword [rdi+rdx]
000000010000b2c5         mov        rdx, qword [rdi+rdx+8]
000000010000b2ca         sub        rdx, rcx
000000010000b2cd         sar        rdx, 0x3
000000010000b2d1         cmp        rax, rdx
000000010000b2d4         jae        loc_10000b2dc

000000010000b2d6         mov        rax, qword [rcx+rax*8]
000000010000b2da         jmp        loc_10000b2e3

                     loc_10000b2dc:
000000010000b2dc         lea        rax, qword [__ZZ32-[MachOLayout getSymbolByIndex:]E8notfound] ; CODE XREF=-[MachOLayout getSymbolByIndex:]+32

                     loc_10000b2e3:
000000010000b2e3         pop        rbp                                         ; CODE XREF=-[MachOLayout getSymbolByIndex:]+38
000000010000b2e4         ret

显然,此时 hopper 中的伪代码仍然比我在radare2 中得到的要好得多。上述 hopper (v4.2.1) 内伪代码的反汇编内容如下:

struct nlist * -[MachOLayout getSymbolByIndex:](void * self, void * _cmd, unsigned int arg2) {
    rax = arg2;
    rcx = self->symbols;
    if (rax < SAR(*(self + *_OBJC_IVAR_$_MachOLayout.symbols + 0x8) - rcx, 0x3)) {
            rax = *(rcx + rax * 0x8);
    }
    else {
            rax = -[MachOLayout getSymbolByIndex:]::notfound;
    }
    return rax;
}

只需使用rabin2 -c.... 现在我必须填写愚蠢的文本来填充 30 个字符