前言
frida
frida-docs
Dynamic instrumentation toolkit for developers, reverse-engineers, and security researchers.
Frida提供了一个名为“ FridaGadget.dylib ” 的动态库,可用于在非越狱设备上测试新开发的应用程序。
The Mach-O (iOS binary format) binary structure: /usr/include/mach-o/*.h
Before continuing, it is necessary to have at least a small understanding of the binary structure of an iOS application.
A Mach-O file consists of 2 main pieces: the header and the data. The header is basically a map of the file describing what it contains and the position of everything contained in it. The data comes directly after the header and consists of a number of binary blobs of data, one after the other.
,---------------------------,
Header | Mach header |
| Segment 1 |
| Section 1 (__text) | --,
|---------------------------| |
Data | blob | <-'
'---------------------------'
- 1、The Mach-O (iOS binary format) binary structure
-1) header structure:The header contains general information about the binary: byte order (magic number), CPU type, amount of load commands, etc.
-2)The load commands section is like a table of contents of the binary:
it describes the position of the segments, symbols table, dynamic symbols table etc.
Each load command includes meta-information, such as type of command, its name, position in a binary, etc.
-3) 链接信息:The data section contains the application code and the data, such as symbol tables, dynamic symbol tables, etc.
官方描述
Header: Specifies the target architecture of the file, such as PPC, PPC64, IA-32, or x86-64.
Load commands: Specify the logical structure of the file and the layout of the file in virtual memory.
Raw segment data: Contains raw data for the segments defined in the load commands.
详情:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/mach-o/loader.h
- 2、The process to insert a new library involves multiple steps
- 1. Insert the library to the application container
- 2. Insert the load command on the load commands section of the binary
- 3. Increment the load command counter on the header section
- 4. Increase the size binary number on the header section
mach header
- 1、可以借助otool 查看 mach header
devzkndeMacBook-Pro:bin devzkn$ otool -h ps Mach header magic cputype cpusubtype caps filetype ncmds sizeofcmds flags 0xfeedfacf 16777223 3 0x80 2 16 1696 0x00200085
cputype其定义参见/usr/include/mach/machine.h
- 2、the filetype field of the mach_header (具体的请查看<mach-o/loader.h>)
#define MH_OBJECT 0x1 /* relocatable object file gcc -c xxx.c 生成xxx.o文件 */
#define MH_EXECUTE 0x2 /* demand paged executable file */
#define MH_FVMLIB 0x3 /* fixed VM shared library file */
#define MH_CORE 0x4 /* core file 崩溃时的Dump文件 */
#define MH_PRELOAD 0x5 /* preloaded executable file */
#define MH_DYLIB 0x6 /* dynamically bound shared library */
#define MH_DYLINKER 0x7 /* dynamic link editor */
#define MH_BUNDLE 0x8 /* dynamically bound bundle file */
#define MH_DYLIB_STUB 0x9 /* shared library stub for static */
/* linking only, no section contents */
#define MH_DSYM 0xa /* companion file with only debug */
/* sections */
#define MH_KEXT_BUNDLE 0xb /* x86_64 kexts 内核扩展文件 */
- 3、flags field of the mach_header
#define MH_PIE 0x200000 /* When this bit is set, the OS will
load the main executable at a
random address. Only used in
MH_EXECUTE filetypes. */
#define MH_ALLOW_STACK_EXECUTION 0x20000/* When this bit is set, all stacks
in the task will be given stack
execution privilege. Only used in
MH_EXECUTE filetypes. */
#define MH_NO_HEAP_EXECUTION 0x1000000 /* When this bit is set, the OS will
run the main executable with
a non-executable heap even on
platforms (e.g. i386) that don't
require it. Only used in MH_EXECUTE
filetypes. */
#define MH_NOUNDEFS 0x1 /* the object file has no undefined
references */
load commands: otool -l git
加载命令的数目以及总的大小在header中已经给出。
具体的可以在loader.h 中查看 Constants for the cmd field of all load commands, the type
#define LC_SEGMENT 0x1 /* segment of this file to be mapped */
#define LC_LOAD_DYLIB 0xc /* load a dynamically linked shared library */
#define LC_ENCRYPTION_INFO 0x21 /* encrypted segment information */
#define LC_CODE_SIGNATURE 0x1d /* local of code signature */
#define LC_UUID 0x1b /* the uuid */
LC_SEGMENT 的数据结构
A segment is made up of zero or more sections.每个段可以拥有零个或多个区域(section)。每一个段(segment)都拥有一段虚拟地址映射到进程的地址空间。
struct segment_command { /* for 32-bit architectures */
uint32_t cmd; /* LC_SEGMENT */
uint32_t cmdsize; /* includes sizeof section structs */
char segname[16]; /* segment name */
uint32_t vmaddr; /* memory address of this segment */
uint32_t vmsize; /* memory size of this segment */
uint32_t fileoff; /* file offset of this segment */
uint32_t filesize; /* amount to map from the file */
vm_prot_t maxprot; /* maximum VM protection */
vm_prot_t initprot; /* initial VM protection */
uint32_t nsects; /* number of sections in segment */
uint32_t flags; /* flags */
};
1)nsects 标志着segment 包含了多少的sections。 2)flag字段 SG_HIGHVM,SG_FVMLIB,SG_NORELOC,SG_PROTECTED_VERSION_1
Section的数据结构
struct section { /* for 32-bit architectures */
char sectname[16]; /* name of this section */
char segname[16]; /* segment this section goes in */
uint32_t addr; /* memory address of this section */
uint32_t size; /* size in bytes of this section */
uint32_t offset; /* file offset of this section */
uint32_t align; /* section alignment (power of 2) */
uint32_t reloff; /* file offset of relocation entries */
uint32_t nreloc; /* number of relocation entries */
uint32_t flags; /* flags (section type and attributes)*/
uint32_t reserved1; /* reserved (for offset or index) */
uint32_t reserved2; /* reserved (for count or sizeof) */
};
- The currently known segment names and the section names in those segments 可以通过otool –s查看某segment的某个section。
段的命名规则是两个下划线紧跟着大写字母(如__TEXT),而section的命名则是两个下划线紧跟着小写字母(__text)。
#define SEG_PAGEZERO "__PAGEZERO" /* the pagezero segment which has no */
/* protections and catches NULL */
/* references for MH_EXECUTE files */
#define SEG_TEXT "__TEXT" /* the tradition UNIX text segment 含有可执行代码和只读的数据。 为了让内核将它 直接从可执行文件映射到共享内存,静态连接器设置该段的虚拟内存权限为不允许写。当这个段被映射到内存后,可以被所有进程共享。(这主要用在frameworks, bundles和共享库等程序中,也可以为同一个可执行文件的多个进程拷贝使用) */
#define SECT_TEXT "__text" /* the real text part of the text */
/* section no headers, and no padding */
#define SECT_FVMLIB_INIT0 "__fvmlib_init0" /* the fvmlib initialization */
/* section */
#define SECT_FVMLIB_INIT1 "__fvmlib_init1" /* the section following the */
/* fvmlib initialization */
/* section */
#define SEG_DATA "__DATA" /* the tradition UNIX data segment */
#define SECT_DATA "__data" /* the real initialized data section */
/* no padding, no bss overlap */
#define SECT_BSS "__bss" /* the real uninitialized data section*/
/* no padding */
#define SECT_COMMON "__common" /* the section common symbols are */
/* allocated in by the link editor */
#define SEG_OBJC "__OBJC" /* objective-C runtime segment */
#define SECT_OBJC_SYMBOLS "__symbol_table" /* symbol table */
#define SECT_OBJC_MODULES "__module_info" /* module information */
#define SECT_OBJC_STRINGS "__selector_strs" /* string table */
#define SECT_OBJC_REFS "__selector_refs" /* string table */
#define SEG_ICON "__ICON" /* the icon segment */
#define SECT_ICON_HEADER "__header" /* the icon headers */
#define SECT_ICON_TIFF "__tiff" /* the icons in tiff format */
#define SEG_LINKEDIT "__LINKEDIT" /* the segment containing all structs */
/* created and maintained by the link */
/* editor. Created with -seglinkedit */
/* option to ld(1) for MH_EXECUTE and */
/* FVMLIB file types only */
#define SEG_UNIXSTACK "__UNIXSTACK" /* the unix stack segment */
#define SEG_IMPORT "__IMPORT" /* the segment for the self (dyld) */
/* modifing code stubs that has read, */
/* write and execute permissions */
devzkndeMacBook-Pro:bin devzkn$ otool -d vi
vi:
Contents of (__DATA,__data) section
devzkndeMacBook-Pro:bin devzkn$ otool -sv __DATA __data vi
vi:
Contents of (__DATA,__data) section
00000001001a2b20 c0 5b 17 00 01 00 00 00 c8 62 17 00 01 00 00 00
00000001001a2b30 cf 5b 17 00 01 00 00 00 37 5c 17 00 01 00 00 00
print the text section (disassemble with -v),当然我们可以借助hopper 和IDA 查看
devzkndeMacBook-Pro:bin devzkn$ otool -tv vi
vi:
(__TEXT,__text) section
0000000100000b34 pushq %rbp
0000000100000b35 movq %rsp, %rbp
0000000100000b38 pushq %r15
0000000100000b3a pushq %r14
0000000100000b3c pushq %r13
install frida on device and mac
- 1、 install frida-server through Cydia:
Start Cydia and add Frida’s repository by navigating to Manage -> Sources -> Edit -> Add and entering https://build.frida.reapt-get update
-rwxr-xr-x 1 root wheel 11292672 Dec 14 00:54 /usr/sbin/frida-server* -rw-r--r-- 1 root wheel 779 Dec 14 00:54 /Library/LaunchDaemons/re.frida.server.plist
- 2、mac里面python自带easy_install pip pip是python的包管理工具
devzkndeMacBook-Pro:site-packages devzkn$ sudo easy_install pip
- 3、install the Frida Python package on your host machine
devzkndeMacBook-Pro:site-packages devzkn$ sudo -H pip install frida
- 4、Connect your device via USB and make sure that Frida work
-U, --usb connect to USB device -a, --applications list only applications -i, --installed include all installed applications devzkndeMacBook-Pro:site-packages devzkn$ frida-ps -Uai PID Name Identifier --- ------------ --------------------------- 904 Cydia com.saurik.Cydia 856 微信 com.tencent.xin 858 邮件 com.apple.mobilemail App Store com.apple.AppStore
- 5、 upgrade frida
devzkndeMacBook-Pro:bin devzkn$ sudo pip install --upgrade frida --ignore-installed six
debug
- 1、pdb.py can be invoked as a script to debug other scripts.
devzkndeMacBook-Pro:frida-ios-dump-master devzkn$ python -m pdb ./dump.py 微信 /Users/devzkn/Downloads/kevin-software/ios-Reverse_Engineering/frida-ios-dump-master/dump.py(7)<module>() -> import sys
- 2、Pdb help
(Pdb) h Documented commands (type help <topic>): ======================================== EOF bt cont enable jump pp run unt a c continue exit l q s until alias cl d h list quit step up args clear debug help n r tbreak w b commands disable ignore next restart u whatis break condition down j p return unalias where
pdb 常用命令
- break 或b : 设置断点 设置断点
- continue或c: 继续执行程序
- list 或l : 查看当前行的代码段
- step 或s : 进入函数
- return 或r : 执行代码直到从当前函数返回
- exit 或 q : 中止并退出
- next 或 n : 执行下一行
- pp : 打印变量的值
(Pdb) pp os.getcwd() '/Users/devzkn/Downloads/kevin\xef\xbc\x8dsoftware/ios-Reverse_Engineering/frida-ios-dump-master'
- help 或者h :
- 1、python print 汉字
(Pdb) print sys.argv ['./dump.py', '\xe5\xbe\xae\xe4\xbf\xa1'] (Pdb) print sys.argv[1] 微信
frida-ios-dump-master的使用
- 1、安装上面步骤install frida on device and mac
- 2、使用usbmuxd 进行端口转发 本地端口2222 转发到iOS的22端口
- 3、执行dump.py
devzkndeMacBook-Pro:bin devzkn$ frida-ps -Uai PID Name Identifier ---- ------------ --------------------------- 1314 App Store com.apple.AppStore 2151 微信 com.tencent.xin 2183 淘宝联盟 com.alimama.moon 1309 设置 com.apple.Preferences
必须在dump.py 所在的目录下执行。即使使用ln -l 也会失败。
devzkndeMacBook-Pro:frida-ios-dump-master devzkn$ ./dump.py 驱蚊大咖 open target app...... start dump target app......
- 4、ln -s dump.py 会仅仅打开app 而已。
devzkndeMacBook-Pro:bin devzkn$ ln -s /Users/devzkn/decrypted/frida-ios-dump-master/dump.py ./dump.py
Q&A
- 1、Operation not permitted: ‘/var/folders/6t/h404bjcd5tb_4q86tpv_251rv_0h0j/T/pip-sYsqDS-uninstall/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/six-1.4.1-py2.7.egg-info’
This is because OS X El Capitan ships with six 1.4.1 installed already and when it attempts to uninstall it (because awscli depends on botocore, botocore depends on python-dateutil, and python-dateutil depends on six >= 1.5) it doesn't have permission to do so because System Integrity Protection doesn't allow even root to modify those directories.
devzkndeMacBook-Pro:site-packages devzkn$ sudo -H pip install --ignore-installed six
- 2、 Ignoring Provides line with DepCompareOp for package libstatusbar
W: Ignoring Provides line with DepCompareOp for package libstatusbar W: Ignoring Provides line with DepCompareOp for package libmoorecon W: You may want to run apt-get update to correct these problems
iPhone:~ root# apt-get update
- 3、frida-server 没有启动
iPhone:/usr/sbin root# killall SpringBoard iPhone:/usr/sbin root# ps -e |grep frida-server 2290 ttys000 0:00.01 grep frida-server
- 4、-sh: /usr/sbin/frida-server: Bad CPU type in executable
installed Frida for 32-bit devices
- 5、 Unable to start server: Error binding to address: Address already in use
removed
- 6、frida-ps
devzkndeMacBook-Pro:site-packages devzkn$ frida-ps --help Usage: frida-ps [options] Options: --version show program's version number and exit -h, --help show this help message and exit -D ID, --device=ID connect to device with the given ID -U, --usb connect to USB device -R, --remote connect to remote frida-server -H HOST, --host=HOST connect to remote frida-server on HOST -a, --applications list only applications -i, --installed include all installed applications
问题求救
前言
今天准备接触下frida, 使用下 AloneMonkey/frida-ios-dump的py, 但是发现了一个问题
Failed to spawn: unable to launch iOS app: timeout
问题具体分析
install frida on device and mac 之后,running the frida-ps command
devzkndeMacBook-Pro:~ devzkn$ frida-ps -Uai PID Name Identifier --- ------------ --------------------------- 824 Cydia com.saurik.Cydia 804 设置 com.apple.Preferences 372 邮件 com.apple.mobilemail
- 但是Failed to spawn
devzkndeMacBook-Pro:~ devzkn$ frida -U -f com.apple.mobilemail ____ / _ | Frida 10.6.27 - A world-class dynamic instrumentation framework | (_| | > _ | Commands: /_/ |_| help -> Displays the help system . . . . object? -> Display information about 'object' . . . . exit/quit -> Exit . . . . . . . . More info at http://www.frida.re/docs/home/ Failed to spawn: unable to launch iOS app: timeout
运行dump.py的时候也没用效果
devzkndeMacBook-Pro:~ devzkn$ /Users/devzkn/Downloads/frida-ios-dump-master/dump.py 邮件
open target app......
devzkndeMacBook-Pro:~ devzkn$
Desktop 运行环境
- 1、 frida version:10.6.27
devzkndeMacBook-Pro:~ devzkn$ frida --version 10.6.27
- Mac version:10.13.1 (17B48)
Device 运行环境
- iPhone version:8.3
iPhone:/System/Library/CoreServices root# cat /System/Library/CoreServices/SystemVersion.plist|grep string* <string>12F70</string> <string>1983-2015 Apple Inc.</string> <string>iPhone OS</string> <string>8.3</string>
使用-P 倒是可以成功:
evzkndeMacBook-Pro:frida-ios-dump-master devzkn$ frida -U -p 1292
____
/ _ | Frida 10.6.27 - A world-class dynamic instrumentation framework
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about 'object'
. . . . exit/quit -> Exit
. . . .
. . . . More info at http://www.frida.re/docs/home/
}
[iPhone::PID::1292]-> obj
ObjC
Object
- 1、 使用./dump.py刚才仅仅成功过一次,无法重现了
devzkndeMacBook-Pro:frida-ios-dump-master devzkn$ ./dump.py xx open target app...... start dump target app......
Failed to spawn: unable to launch iOS app: timeout
问题的解决方法
Frida 从 9.0 开始,改 hook launchd 来 spawn process,Frida 8.2.5 以前是利用 dylib 注入的方式来 spawn。
目前解决方法:
1.降回旧版Frida
2.不要使用spawn
我之前也一直在研究这个问题,目前只知道 Frida spawn process 在修改 kernel process flags 时,会导致32-bit 装置重启,不过我还没研究出为什么,大概只能判断 32-bit, 64-bit kernel 处理稍有不同。
有人懂这一块地也希望能一起研究研究
Failed to spawn 的替代方案
- 1、先使用frida-ps -Uai 查看PID
- 2、使用 frida -p attach
devzkndeMacBook-Pro:zhangkn.github.io devzkn$ frida -U -p 1262
____
/ _ | Frida 10.6.27 - A world-class dynamic instrumentation framework
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about 'object'
. . . . exit/quit -> Exit
. . . .
. . . . More info at http://www.frida.re/docs/home/
[iPhone::PID::1262]->
frida-ios-dump 失败的原因
刚才进行了pdb ,发现执行到这里
(Pdb) l
108 script = loadJsFile(session, APP_JS);
109 name = target.decode('utf8');
110 script.post(name);
111 opened.wait();
112 session.detach();
113 -> createDir(os.getcwd()+"/"+OUTPUT)
114 print "start dump target app......"
115 session = device.attach(name);
116 script = loadJsFile(session, DUMP_JS);
117 script.post("dump");
118 finished.wait();
(Pdb) s
--Return--
> /Users/devzkn/Downloads/kevin-software/ios-Reverse_Engineering/frida-ios-dump-master/dump.py(113)main()->None
-> createDir(os.getcwd()+"/"+OUTPUT)
(Pdb) l
108 script = loadJsFile(session, APP_JS);
109 name = target.decode('utf8');
110 script.post(name);
111 opened.wait();
112 session.detach();
113 -> createDir(os.getcwd()+"/"+OUTPUT)
114 print "start dump target app......"
115 session = device.attach(name);
116 script = loadJsFile(session, DUMP_JS);
117 script.post("dump");
118 finished.wait();
(Pdb) s
UnicodeDecodeError: UnicodeD...ge(128)')
> /Users/devzkn/Downloads/kevin-software/ios-Reverse_Engineering/frida-ios-dump-master/dump.py(127)<module>()
-> main(sys.argv[1])
(Pdb) l
122 if len(sys.argv) < 2:
123 print "usage: ./dump.py 微信"
124 sys.exit(0)
125 else:
126 try:
127 -> main(sys.argv[1])
128 except KeyboardInterrupt:
129 if session:
130 session.detach()
131 sys.exit()
132 except:
(Pdb) s
> /Users/devzkn/Downloads/kevin-software/ios-Reverse_Engineering/frida-ios-dump-master/dump.py(128)<module>()
-> except KeyboardInterrupt:
(Pdb) pp UnicodeDecodeError
<type 'exceptions.UnicodeDecodeError'>
因此,我换了一个路径,就可以了。
因此问题在于createDi的时候,编码失败了。 以后创建目录命名要小心了。
辅助shell
为了解决目前frida-ios-dump-master的一些小问题,写了一个shell
#!/bin/sh
# frida-ps -Uai 查看,来获取参数
# usage: devzkndeMacBook-Pro:~ devzkn$ kndump 邮件
# dump app
cd ~/decrypted/frida-ios-dump-master
rm -rf ./Payload
./dump.py $1
open .
exit 0
参考资源:
frida-scripts Repository including some useful frida script for iOS Reversing Murphy Python 代码调试技巧
mach-o 相关的文档
- 0.mach-o文件格式分析
- 1.mach-o文件加载的全过程(1)
- 2.Mach-O 可执行文件
- 3.iPhone Mach-O文件格式与代码签名
- 4.Dynamic Linking of Imported Functions in Mach-O
- 5.otool详解Mach-o文件头部
- MachORuntime.pdf
- Mach-O Programming Topics
- basics-of-the-mach-o-file-format
- macOS Code Signing In Depth
- iOS启动顺序
- reverse_engineering
在操作过程或者文章有问题的话欢迎在 原文 里提问或指正。