IDA反汇编/反编译静态分析iOS模拟器程序(四)反汇编的符号信息与改名

首先看看windows IDA和xcode的反汇编有什么不同。因为不确定直接分析UIKit的代码会不会有法律问题,还是自己写个例子吧。分析UIKit的时候因为没有完整的debugging symbols,所以得到的反汇编信息会比自己写的代码较少。

一个在命名空间ANameSpace的类DataInternal,一个DataModel的C++类,一个继承自UIButton的TestButton。演示的是TestButton的printLog函数。

这是源码:

namespace ANameSpace
{
    class DataInternal
    {
        int m_sample;
    public:
        void add();
    };
}

class DataModel {
    int m_count;
    int m_index;
    float m_number;
    std::vector m_longData;
    double m_value;
    char m_name[10];
    ANameSpace::DataInternal m_internal;
    static DataModel* s_sharedInstance;
    DataModel();
public:
    int count();
    int index() { return m_index; }
    float number();
    static DataModel *sharedInstance();
    double getValueAfterAddedNumber(double number);
    void addLongData(long data);
};

class DataModel;

@interface TestButton : UIButton
{
    DataModel *m_model;
    NSString *m_printLog;
}

- (bool)inWindow;
@property (nonatomic, assign) DataModel *model;

@end

@interface TestButton (Construct)

+ (TestButton*)createAButton;
- (id)initWithNothing:(id)nilPointer;

@end

@interface TestButton (Test)

- (void)setParam1:(CGRect)p1 para2:(CGFloat)p2;
- (NSString*)printLog;

@end

- (NSString*)printLog
{
    if (m_model->count() == 0)
    {
        if (m_printLog)
            return m_printLog;
        else
            return @"ok";
    }
    else if (m_model->count() == 1)
    {
        if ([self model])
            return @"fine";
        else
            return @"error";
    }
    else
        return m_printLog;
}

这是IDA得到的反汇编:

__text:000026B5 ; =============== S U B R O U T I N E =======================================
__text:000026B5
__text:000026B5 ; Attributes: bp-based frame
__text:000026B5
__text:000026B5 __TestButton_Test__printLog_ proc near
__text:000026B5
__text:000026B5 arg_0           = dword ptr  8
__text:000026B5
__text:000026B5                 push    ebp
__text:000026B6                 mov     ebp, esp
__text:000026B8                 push    ebx
__text:000026B9                 push    edi
__text:000026BA                 push    esi
__text:000026BB                 sub     esp, 0Ch
__text:000026BE                 call    $+5
__text:000026C3                 pop     esi
__text:000026C4                 mov     ebx, ds:(_OBJC_IVAR_$_TestButton_m_model - 26C3h)[esi]
__text:000026CA                 mov     edi, [ebp+arg_0]
__text:000026CD                 mov     eax, [edi+ebx]
__text:000026D0                 mov     [esp], eax
__text:000026D3                 call    __ZN9DataModel5countEv ; DataModel::count(void)
__text:000026D8                 test    eax, eax
__text:000026DA                 jz      short loc_2713
__text:000026DC                 mov     eax, [edi+ebx]
__text:000026DF                 mov     [esp], eax
__text:000026E2                 call    __ZN9DataModel5countEv ; DataModel::count(void)
__text:000026E7                 cmp     eax, 1
__text:000026EA                 jnz     short loc_2729
__text:000026EC                 mov     eax, ds:(off_57FC - 26C3h)[esi]
__text:000026F2                 mov     [esp+4], eax
__text:000026F6                 mov     [esp], edi
__text:000026F9                 call    _objc_msgSend
__text:000026FE                 mov     ecx, eax
__text:00002700                 lea     edx, (cfstr_Error.isa - 26C3h)[esi] ; "error"
__text:00002706                 lea     eax, (cfstr_Fine.isa - 26C3h)[esi] ; "fine"
__text:0000270C                 test    ecx, ecx
__text:0000270E                 cmovz   eax, edx
__text:00002711                 jmp     short loc_2732
__text:00002713 ; ---------------------------------------------------------------------------
__text:00002713
__text:00002713 loc_2713:                               ; CODE XREF: __TestButton_Test__printLog_+25j
__text:00002713                 mov     eax, ds:(_OBJC_IVAR_$_TestButton_m_printLog - 26C3h)[esi]
__text:00002719                 mov     ecx, [edi+eax]
__text:0000271C                 lea     eax, (cfstr_Ok.isa - 26C3h)[esi] ; "ok"
__text:00002722                 test    ecx, ecx
__text:00002724                 cmovnz  eax, ecx
__text:00002727                 jmp     short loc_2732
__text:00002729 ; ---------------------------------------------------------------------------
__text:00002729
__text:00002729 loc_2729:                               ; CODE XREF: __TestButton_Test__printLog_+35j
__text:00002729                 mov     eax, ds:(_OBJC_IVAR_$_TestButton_m_printLog - 26C3h)[esi]
__text:0000272F                 mov     eax, [edi+eax]
__text:00002732
__text:00002732 loc_2732:                               ; CODE XREF: __TestButton_Test__printLog_+5Cj
__text:00002732                                         ; __TestButton_Test__printLog_+72j
__text:00002732                 add     esp, 0Ch
__text:00002735                 pop     esi
__text:00002736                 pop     edi
__text:00002737                 pop     ebx
__text:00002738                 pop     ebp
__text:00002739                 retn
__text:00002739 __TestButton_Test__printLog_ endp

这是lldb的:

HursingTest`-[TestButton(Test) printLog] at TestButton.mm:51:
0x26b3:  pushl  %ebp
0x26b4:  movl   %esp, %ebp
0x26b6:  pushl  %ebx
0x26b7:  pushl  %edi
0x26b8:  pushl  %esi
0x26b9:  subl   $12, %esp
0x26bc:  calll  0x26c1                    ; -[TestButton(Test) printLog] + 14 at TestButton.mm:53
0x26c1:  popl   %esi
0x26c2:  movl   13207(%esi), %ebx
0x26c8:  movl   8(%ebp), %edi
0x26cb:  movl   (%edi,%ebx), %eax
0x26ce:  movl   %eax, (%esp)
0x26d1:  calll  0x2742                    ; DataModel::count() at DataModel.cpp:22
0x26d6:  testl  %eax, %eax
0x26d8:  je     0x2711                    ; -[TestButton(Test) printLog] + 94 at TestButton.mm:55
0x26da:  movl   (%edi,%ebx), %eax
0x26dd:  movl   %eax, (%esp)
0x26e0:  calll  0x2742                    ; DataModel::count() at DataModel.cpp:22
0x26e5:  cmpl   $1, %eax
0x26e8:  jne    0x2727                    ; -[TestButton(Test) printLog] + 116 at TestButton.mm:68
0x26ea:  movl   12607(%esi), %eax
0x26f0:  movl   %eax, 4(%esp)
0x26f4:  movl   %edi, (%esp)
0x26f7:  calll  0x352c                    ; symbol stub for: objc_msgSend
0x26fc:  movl   %eax, %ecx
0x26fe:  leal   13279(%esi), %edx
0x2704:  leal   13263(%esi), %eax
0x270a:  testl  %ecx, %ecx
0x270c:  cmovel %edx, %eax
0x270f:  jmp    0x2730                    ; -[TestButton(Test) printLog] + 125 at TestButton.mm:69
0x2711:  movl   13211(%esi), %eax
0x2717:  movl   (%edi,%eax), %ecx
0x271a:  leal   13247(%esi), %eax
0x2720:  testl  %ecx, %ecx
0x2722:  cmovnel%ecx, %eax
0x2725:  jmp    0x2730                    ; -[TestButton(Test) printLog] + 125 at TestButton.mm:69
0x2727:  movl   13211(%esi), %eax
0x272d:  movl   (%edi,%eax), %eax
0x2730:  addl   $12, %esp
0x2733:  popl   %esi
0x2734:  popl   %edi
0x2735:  popl   %ebx
0x2736:  popl   %ebp
0x2737:  ret    

两者会有以下区别:

1.IDA计算出了成员变量的偏移地址并把symbol直接显示出来

IDA:__text:000026C4                 mov     ebx, ds:(_OBJC_IVAR_$_TestButton_m_model - 26C3h)[esi]
xcode:0x26c2:  movl   13207(%esi), %ebx

TestButton的成员变量DataModel* m_model以_OBJC_IVAR_$_TestButton_m_model 为名显示。(其中IVAR是Objective-C运行时的类型,其概念请参考xcode文档)
2.函数参数在IDA中被赋予名称,ebp+8为arg_0,ebp+12为arg_1。 arg即为argument的缩写,第n个参数在+号后面的偏移量不是绝对的,请参考《xcode反汇编调试iOS模拟器程序(三)查看Objective-C函数与参数》。在函数开头和代码中,名称都会直接替换掉实际偏移量。对于Objective-C函数,arg_0都是self。

IDA:__text:000026CA                 mov     edi, [ebp+arg_0]

xcode:0x26c8:  movl   8(%ebp), %edi

3.常数值型偏移地址被赋予名称,以loc_为前缀。

IDA:jmp     short loc_2732

xcode:0x270f:  jmp    0x2730                    ; -[TestButton(Test) printLog] + 125 at TestButton.mm:69

4.IDA是intel汇编,xcode是AT&T汇编。

另外,IDA在00002713处有一个全减号的注释,这是表示上面的代码不会顺序执行到下面,只可能是有跳转指令才会执行到这里。

在分析UIKit时,代码偏移地址在IDA和xcode间是相差很远的,因为IDA中的地址是相对于库文件的,xcode中的地址是相对于运行中的程序的。不过偏移地址的后三位会相同,因为linker会令部分地址对齐。


这个例子没用到局部变量,如果用到:

__text:0004F0AF __UIView_Geometry__convertSize_toView__ proc near
__text:0004F0AF                                         ; DATA XREF: __objc_const:0075E28Co
__text:0004F0AF
__text:0004F0AF var_18          = dword ptr -18h
__text:0004F0AF var_14          = dword ptr -14h
__text:0004F0AF var_10          = dword ptr -10h
局部变量,即 ebp-xxx 会被命名为 var_xxx。关于局部变量请参考《 xcode反汇编调试iOS模拟器程序(六)函数出入口处的处理与局部变量》

下面这个IDA特性也许比较激动人心:把鼠标悬停在000026EC行的off_57FC上,会有悬浮框显示这个名字的意义。


000026F9处是objc_msgSend函数,所以000026EC这里是在传递selector,悬浮框显示的是selector的字符串。其中aModel的a表示off_57FC处的是字符串。后边的分号注释中,第一行是交叉引用的信息(后面的章节再讲),第二行是symbol信息,所以000026EC行是表示把"model"这个selector字符串的起始地址传到edx。悬停鼠标就能看到,相比于xcode方便多了。

再方便一点,在off_57FC上右键单击,在菜单中选择Rename(或者按快捷键N)

即可为off_7E4960这个自动生成的名字改名,方便以后查看。因为它代表的是selector,所以直接改成selector的名字就最直观了。


修改完毕后就会显示为:

__text:000026EC                 mov     eax, ds:(model - 26C3h)[esi]

各种IDA自动生成的名字都可以改名,怎么易理解就怎么改。为了免除输入麻烦,可以双击off_7E4960跳转到那个地址,然后复制model这个字符串,再回到刚才的界面,rename,粘贴~~~

如果是带参数的selector,粘贴后,冒号会自动变成下划线的。
退出IDA的时候保存到idb文件,下次启动的时候,改名仍然有效。


上一篇:IDA反汇编/反编译静态分析iOS模拟器程序(三)函数表示与搜索函数

下一篇:IDA反汇编/反编译静态分析iOS模拟器程序(五)F5反编译

本文请勿转载。

你可能感兴趣的:(iOS,反汇编/反编译)