二进制文件分析工具

520 阅读8分钟

file

查看文件的基础信息,是否是fat文件,以及是动态库还是静态库。不限于库文件,基本所有的文件都可以用这个命令了解文件信息,对于库文件来说,可以了解库文件是否是fat文件,支持的架构,以及库是静态库还是动态库。

[user@localhost]$file Foundation

Foundation: Mach-O 64-bit dynamically linked shared library arm64

lipo

用来创建和操作通用(universal)文件,可以用来合并、剔除、抽取不同架构的库文件,创建一个新的fat文件;当然也可以打印库的信息,此处只介绍信息读取。

  1. 打印信息
[user@localhost]$lipo -info Foundation

Non-fat file: Foundation is architecture: arm64
  1. 打印详细信息
[user@localhost]$lipo -detailed_info Foundation

input file Foundation is not a fat file
Non-fat file: Foundation is architecture: arm64
  1. 只打印架构信息,通常用于命令行
[user@localhost]$lipo -archs Foundation

arm64

nm

用来查询符号表

  1. -a 显示所有符号,包括调试符号。默认不添加任何选项时,就是这个效果
[user@localhost]$nm  -a Foundation | head -3

00000001819c0364 t +[NSAddressCheckingResult supportsSecureCoding]
00000001818d124c t +[NSAffineTransform supportsSecureCoding]
00000001818d04f8 t +[NSAffineTransform transform]
  1. -g 显示所有全局(外部)符号
  2. -n 按照数字而非字母排序
    -p 不要排序,按照符号表的顺序显示
    -r 倒序。
  3. -u 只显示未定义的符号
    -U 不显示未定义的符号
  4. -m 以(segment_name,section_name) [external | non-external] 的格式,
    显示符号所在的段名(segment_name)和分区名(section_name)
[user@localhost]$nm  -m Foundation | head -3

00000001819c0364 (__TEXT,__text) non-external +[NSAddressCheckingResult supportsSecureCoding]
00000001818d124c (__TEXT,__text) non-external +[NSAffineTransform supportsSecureCoding]
00000001818d04f8 (__TEXT,__text) non-external +[NSAffineTransform transform]
  1. -j 只显示符号名称,不显示地址和类型
[user@localhost]$nm  -j Foundation | head -3

+[NSAddressCheckingResult supportsSecureCoding]
+[NSAffineTransform supportsSecureCoding]
+[NSAffineTransform transform]
  1. -s 显示特定的段名(segname)下,分区名(sectname)的符号
[user@localhost]$nm  -s __TEXT __const Foundation | head -3

0000000181a7bf68 S _NSAffineTransformStructIdentity
0000000181a7ccc0 S _NSBundleResourceRequestLoadingPriorityUrgent
0000000181a7c038 S _NSDataDeallocatorNone
  1. -arch 指定查询符号表的架构,如果是一个通用(universal)文件,即fat文件时。all选项参数,指定操作所有包含架构。(举例的文件只有arm64,所以,没有使用到)

otool

用来查看对象文件或库文件的特定部分信息

  1. 显示文件头信息 -a 如果是归档文件(通常是.a静态库),显示归档头 -S 如果是归档文件,显示__.SYMDEF文件 -f 显示通用(universal),即fat文件头

  2. -h 显示Mach-O文件头(原文件不可读,通常配合-v使用,转换为可读输出)

[user@localhost]$otool -h KWPlayer.decrypted
KWPlayer.decrypted:
Mach header
      magic  cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
 0xfeedfacf 16777228          0  0x00           2   130      13064 0x00218085
[user@localhost]$otool -hv KWPlayer.decrypted
KWPlayer.decrypted:
Mach header
      magic  cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64    ARM64        ALL  0x00     EXECUTE   130      13064   NOUNDEFS DYLDLINK TWOLEVEL WEAK_DEFINES BINDS_TO_WEAK PIE
  1. -l 显示镜像加载命令,我们可以用来查看文件依赖的动态库信息
[user@localhost]$otool -l KWPlayer.decrypted | head -25
KWPlayer.decrypted:
Load command 0
      cmd LC_SEGMENT_64
  cmdsize 72
  segname __PAGEZERO
   vmaddr 0x0000000000000000
   vmsize 0x0000000100000000
  fileoff 0
 filesize 0
  maxprot 0x00000000
 initprot 0x00000000
   nsects 0
    flags 0x0
Load command 1
      cmd LC_SEGMENT_64
  cmdsize 1032
  segname __TEXT
   vmaddr 0x0000000100000000
   vmsize 0x00000000085f0000
  fileoff 0
 filesize 140443648
  maxprot 0x00000005
 initprot 0x00000005
   nsects 12
    flags 0x0

以及最重要的:镜像是否被加密。此处的文件已经进行了脱壳,所以,cryptid为0,表示未加密。如果为0,表示镜像加密。加密的镜像是无法被反汇编(disassemble)的。

[user@localhost]$otool -l KWPlayer.decrypted | grep crypt
KWPlayer.decrypted:
     cryptoff 16384
    cryptsize 140427264
      cryptid 0[user@localhost]$otool -l KWPlayer.decrypted | grep crypt
KWPlayer.decrypted:
     cryptoff 16384
    cryptsize 140427264
      cryptid 0
  1. -s 显示指定段名(segment_name)和分区名(section_name)的内容。通常配合-v、-V使用,对信息进行反汇编和符号化。

  2. -t 显示(__TEXT,__text)分区,即代码段内容,通常配合-v、-V使用,对信息进行反汇编和符号化
    -x 功能类似于-t,显示所有__text分区,不仅限于__TEXT。主要针对一些特殊文件处理

[user@localhost]$otool -tv KWPlayer.decrypted | grep -20 KWPlayer
0000000105a7c4e8 ldr x22, [x19, #0x8]
0000000105a7c4ec cbnz x22, 0x105a7c51c
0000000105a7c4f0 adrp x8, 16512 ; 0x109afc000
0000000105a7c4f4 ldr x0, [x8, #0x6c8] ; Objc class ref: KWPlayerResource
0000000105a7c4f8 bl 0x106eceaa0 ; symbol stub for: _objc_alloc
0000000105a7c4fc adrp x8, 16213 ; 0x1099d1000
0000000105a7c500 ldr x1, [x8, #0xf98] ; Objc selector ref: init
0000000105a7c504 bl 0x106ecebcc ; Objc message: +[KWPlayerResource init]
0000000105a7c508 ldr x8, [x19, #0x8]
0000000105a7c50c str x0, [x19, #0x8]
0000000105a7c510 mov x0, x8
0000000105a7c514 bl 0x106ecebf0 ; symbol stub for: _objc_release
0000000105a7c518 ldr x22, [x19, #0x8]
0000000105a7c51c adrp x8, 16422 ; 0x109aa2000
0000000105a7c520 ldr x21, [x8, #0x9b8] ; Objc selector ref: mediaItem
0000000105a7c524 mov x0, x19
0000000105a7c528 mov x1, x21
0000000105a7c52c bl 0x106ecebcc ; Objc message: -[x0 mediaItem]
0000000105a7c530 mov x29, x29
0000000105a7c534 bl 0x106ecec2c ; symbol stub for: _objc_retainAutoreleasedReturnValue
0000000105a7c538 mov x23, x0
0000000105a7c53c adrp x25, 11124 ; 0x1085f0000
0000000105a7c540 ldr x25, [x25, #0xd20] ; literal pool symbol address: __NSConcreteStackBlock
0000000105a7c544 str x25, [sp, #0x28]
0000000105a7c548 adrp x8, 5213 ; 0x106ed9000
0000000105a7c54c ldr d8, [x8, #0x428]
0000000105a7c550 adr x8, #0x1e4
0000000105a7c554 nop
  1. -d 显示(__DATA,__data)段
  2. -o 显示__OBJC段,段内容会被OC运行时加载。
[user@localhost]$otool -ov KWPlayer.decrypted | grep -20 KWWeakProxy
entsize 24
            count   1
            name    0x10813eee1 shareIns
            types   0x10830b73d @16@0:8
            imp     0x106d5525c
        baseProtocols  0x0
        ivars          0x0
        weakIvarLayout 0x0
        baseProperties 0x0
00000001089e8ad8 0x109d1d220
    isa        0x109d1d248
    superclass 0x0 _OBJC_CLASS_$_NSObject
    cache      0x0 __objc_empty_cache
    vtable     0x0
    data       0x10998b9f8
        flags          0x194 RO_HAS_CXX_STRUCTORS
        instanceStart  8
        instanceSize   16
        reserved       0x0
        ivarLayout     0x0
        name           0x108309915 KWWeakProxy
        baseMethods    0x10998b818
            entsize 24
            count   17
            name    0x107f669f4 initWithTarget:
            types   0x10830b766 @24@0:8@16
            imp     0x106d55bd4
            name    0x107d626af forwardingTargetForSelector:
            types   0x10830ba65 @24@0:8:16
            imp     0x106d55c4c
            name    0x108036edc forwardInvocation:
            types   0x10830b745 v24@0:8@16
            imp     0x106d55c60
            name    0x107d248a3 methodSignatureForSelector:
            types   0x10830ba65 @24@0:8:16
            imp     0x106d55c90
            name    0x107ccca41 respondsToSelector:
            types   0x10830ba9a B24@0:8:16
            imp     0x106d55cac
            name    0x107ccbba0 isEqual:
            types   0x10830ba52 B24@0:8@16
  1. -v 显示详细(符号)信息,如果可能
    -V 显示反汇编指令的参数符号,隐含-v选项,配合-s,-t,-x使用非常有效

  2. -X 不显示反汇编的段起始地址或头信息。

dyld_info

显示程序或动态库包含的动态链接器(dyld) 使用的信息。

  1. -platform 显示文件工作的平台信息(macOS,iOS)
[user@localhost]$dyld_info -platform KWPlayer.decrypted
/Users/sensoro/Desktop/KWPlayer.decrypted [arm64]:
    -platform:
        platform     minOS      sdk
             iOS     9.0       15.4
  1. -segements 显示段和分区信息,以及大小
[user@localhost]$dyld_info -segments KWPlayer.decrypted | head -20
/Users/sensoro/Desktop/KWPlayer.decrypted [arm64]:
    -segments:
        load-offset   segment section        sect-size  seg-size perm
        0x00000000    __TEXT                            137152KB r.x
        0x00004900             __text           116150792
        0x06EC9B08             __stubs           25356
        0x06ECFE14             __stub_helper     24780
        0x06ED5EE0             __const          4259433
        0x072E5D4C             __gcc_except_tab 5837876
        0x07877180             __cstring        4537945
        0x07CCAFD9             __objc_methname  6100937
        0x0829C7A2             __objc_classname 454536
        0x0830B72A             __objc_methtype  682090
        0x083B1F94             __ustring        467168
        0x08424074             __unwind_info    1734220
        0x085CB6C0             __eh_frame       149788
        0x085F0000    __DATA                             29216KB rw.
        0x085F0000             __got             25464
        0x085F6378             __la_symbol_ptr   16904
        0x085FA580             __mod_init_func    7072
  1. -dependents 显示文件链接的所有动态库
[user@localhost]$dyld_info -dependents KWPlayer.decrypted | head -20
/Users/sensoro/Desktop/KWPlayer.decrypted [arm64]:
    -dependents:
        attributes     load path
                       /usr/lib/libbz2.1.0.dylib
                       /usr/lib/libSystem.B.dylib
                       /usr/lib/libc++.1.dylib
                       /usr/lib/libiconv.2.dylib
                       /usr/lib/libicucore.A.dylib
                       /usr/lib/libresolv.9.dylib
                       /usr/lib/libsqlite3.dylib
                       /usr/lib/libxml2.2.dylib
                       /usr/lib/libz.1.dylib
                       @rpath/AFNetworking.framework/AFNetworking
                       /System/Library/Frameworks/AVFoundation.framework/AVFoundation
        weak_import    /System/Library/Frameworks/AVKit.framework/AVKit
                       /System/Library/Frameworks/Accelerate.framework/Accelerate
                       /System/Library/Frameworks/AdSupport.framework/AdSupport
                       @rpath/App.framework/App
        weak_import    /System/Library/Frameworks/AppTrackingTransparency.framework/AppTrackingTransparency
                       @rpath/Aspects.framework/Aspects
  1. -inits 显示所有的静态初始化器和OC +load方法
[user@localhost]$dyld_info -inits KWPlayer.decrypted | head -20
/Users/sensoro/Desktop/KWPlayer.decrypted [arm64]:
    -inits:
        0x000111C0  __mh_execute_header + 0x111C0
        0x00011DF8  __ZN6Thread7cleanupEPv + 0x110
        0x00018FBC  __ZN6Thread19start_routine_afterEPv + 0x15D8
        0x0001B470  __ZN6Thread19start_routine_afterEPv + 0x3A8C
        0x0001D2A4  __ZN6Thread19start_routine_afterEPv + 0x58C0
        0x00029710  __ZN6Thread19start_routine_afterEPv + 0x11D2C
        0x00029740  __ZN6Thread19start_routine_afterEPv + 0x11D5C
        0x00029770  __ZN6Thread19start_routine_afterEPv + 0x11D8C
        0x000297A0  __ZN6Thread19start_routine_afterEPv + 0x11DBC
        0x000297D0  __ZN6Thread19start_routine_afterEPv + 0x11DEC
        0x00029800  __ZN6Thread19start_routine_afterEPv + 0x11E1C
        0x00029830  __ZN6Thread19start_routine_afterEPv + 0x11E4C
        0x00029860  __ZN6Thread19start_routine_afterEPv + 0x11E7C
        0x0002D150  __ZN6Thread19start_routine_afterEPv + 0x1576C
        0x0002D180  __ZN6Thread19start_routine_afterEPv + 0x1579C
        0x0002D23C  __ZN6Thread19start_routine_afterEPv + 0x15858
        0x0002DE20  __ZN6Thread19start_routine_afterEPv + 0x1643C
        0x00031D84  __ZN6Thread19start_routine_afterEPv + 0x1A3A0
        
[user@localhost]$dyld_info -inits KWPlayer.decrypted | tail -20
        0x0943EEE0  +[BLYWCSessionDelegateInterceptor load]
        0x094AE468  +[JVClientController load]
        0x094B1B70  +[JVIntegrate load]
        0x094C0838  +[JCommonServiceController load]
        0x094C5D88  +[JPUSHReceivedPacketController load]
        0x094CA3B8  +[JCORENetworkReachabilityManager load]
        0x094EF7A0  +[TGGDTPODS_GDTCacheManager load]
        0x094FFEF8  +[TGGDTPODS_GDataXMLNode load]
        0x0956FC20  +[VLNLog load]
        0x09645400  +[KWPAppDelegate load]
        0x096BE588  +[LaunchMusic load]
        0x096BE750  +[JXGlobalModuleRouter load]
        0x0909CE50  +[(fxTouch) load]
        0x0918BEB0  +[(Placeholder) load]
        0x09316DA8  +[(MJRefresh) load]
        0x09316E28  +[(MJRefresh) load]
        0x0942DE78  +[(BuglyMartian) load]
        0x0943ED88  +[(BUGLY_WCSessionRuntime) load]
        0x094AAD10  +[(JVhook) load]
        0x099A0C10  +[(SkinSupport) load]
  1. -exports 显示所有导出符号
    -imports 显示所有导入符号
[user@localhost]dyld_info -imports KWPlayer.decrypted | tail -10
/Users/sensoro/Desktop/KWPlayer.decrypted [arm64]:
0x0000  0x002  __Block_copy 
0x0001  0x002  __DefaultRuneLocale 

[user@localhost]$dyld_info -exports KWPlayer.decrypted | tail -10
        0x052CCA38  _cramer_solve [weak_def]
        0x052CC8B4  _det [weak_def]
        0x052CC9F0  _deinit_square_matrix [weak_def]
        0x056AF194  _ABInputPortReceiveLive [weak_def]
        0x056AF1A0  _ABInputPortIsConnected [weak_def]
        0x056AF1C0  _ABOutputPortSendAudio [weak_def]
        0x056AF1E0  _ABOutputPortIsConnected [weak_def]
        0x056AF200  _ABOutputPortGetConnectedPortAttributes [weak_def]
        0x056AF220  _ABOutputPortGetAverageLatency [weak_def]
        0x09EAFF88  _ABConnectionsChangedNotification [weak_def]
  1. -objc 显示OC定义的类和分类信息
[sensoro@ninjia:~/Desktop]$dyld_info -objc /Users/sensoro/Desktop/KWPlayer.decrypted | head -20
/Users/sensoro/Desktop/KWPlayer.decrypted [arm64]:
    -objc:
              type       vmaddr   data-vmaddr   name
             class   0x109B79278    0x1089EF7B0   FANetCheckResultModel
            method   0x1089EF608                 status
            method   0x1089EF620                 setStatus:
            method   0x1089EF638                 score
            method   0x1089EF650                 setScore:
            method   0x1089EF668                 networkType
            method   0x1089EF680                 setNetworkType:
            method   0x1089EF698                 detailInfo
            method   0x1089EF6B0                 setDetailInfo:
            method   0x1089EF6C8                 .cxx_destruct
        meta-class   0x109B792A0    0x1089EF5B8   FANetCheckResultModel
             class   0x109B792C8    0x1089EF8C8   FANetCheck
            method   0x1089EF868                 init
            method   0x1089EF880                 startCheckWithHostList:
            method   0x1089EF898                 stopCheck
            method   0x1089EF8B0                 dealloc
        meta-class   0x109B792F0    0x1089EF818   FANetCheck
  1. -fixups 显示一个简单的列表,包含动态链接器(dyld)修复的位置信息
    -fixup_chains 如果文件使用了链式修复,显示链的格式和起始位置
    -fixup_chain_details 显示一个列表,包含所有的修复链的原始位信息和意义
    -symbolic_fixups 按照数据符号分组显示所有的修复
    -validate_only 格式校验。如果文件是合法的,不显示任何信息,否则显示格式错误部分的信息。

libtool

用于从对象文件,创建库文件(动态库Mach-O或静态库ar),详细的使用方法可以使用man libtool