ios应用逆向工程1-4章笔记
概念篇+工具篇
1.bundle的概念来源于NeXTSTEP,它不是一个文件,而是一个按某种标准结构来组织的目录,其中包含了二进制文件及运行所需的资源.正向开发中常见的App和framework都是以bundle的形式存在的;framework也是bundle,但framework的bundle中存放的是一个dylib,而不是可执行文件.相对来说,framework的地位比App更高,因为一个App的绝大多数功能都是通过调用framework提供的接口来实现的.将某个bundle确立为逆向目标后,绝大多数逆向线索都可以在bundle内找到,这大大降低了逆向工程的复杂度
2.Xcode自带的plutil工具可查看plist文件,命令为plutil -p xxx.plist
3.ios的app目录中的lproj目录下存放的是各种本地化的字符串(.strings),是ios逆向工程的重要线索,也可以用plutil查看
4.storeapp的数据目录在/var/mobile/Containers/Data
下,以mobile权限运行的系统app的数据目录在/var/mobile/
下,而以root权限运行的系统app的数据目录在/var/root/
下
5.cydia app的安装包格式一般是deb,storeapp的安装包格式一般是ipa,其中deb的属主属组是root:admin,能够以root权限运行,而ipa是苹果为ios推出的专属app安装包格式,属主用户和属组都是mobile,只能以mobile权限运行
6.通俗地说,ios中的沙盒就是一种访问限制机制,我们可以把它看作是权限的一种表现形式,授权文件也是沙盒的一部分.总的来说,沙盒会将app的文件访问范围限制在这个app内部,一个app一般不知道其他app的存在,更别说访问它们了,沙盒还会限制app的功能,例如对icloud接口的调用就必须经过沙盒的允许.越狱本身已经破除了ios的绝大多数安全限制,并对沙盒进行了一定程度的扩充,因此我们往往很容易忽略sandbox的存在,从而碰到一些看似很奇怪的问题.比如某个tweak不能写文件,调用了某个函数却没有出现应有的效果,在确保自己的代码没有问题的前提下,就要回过头来检查这些问题是不是因为权限不够,或者沙盒限制造成的
7.cydia里的各种tweak无一不是以dylib的形式工作的
8.ios实际上存在真正的后台多任务,如接听电话时ios会第一时间将接听电话界面呈现在我们面前.不过,对于storeapp来说,当用户按下home键时,进程就进入后台了,大多数功能都会被暂停
9.在theos新建的工程目录文件夹中,可以创建一个名为layout
的文件夹,然后把工程打包成deb并安装到ios中,此时layout
中的所有文件会被解包到ios文件系统的相同位置(这里的layout
相当于ios中的根目录/
),这极大扩充了deb包的什么用范围
10.命令行安装theos生成的deb到手机的方法:在makefile的最上一行加上本机ip地址THEOS_DEVICE_IP=...
,然后调用make package install
命令完成编译打包安装一条龙服务
11.免ssh输密码
- 删除本机~/.ssh/known_hosts中目标ip对应条目
- 在本机生成ida_rsa.pub文件:
ssh-keygen -t rsa
,生成的文件为~/.ssh/id_rsa.pub
- 在目标机器终端中
ssh-keygen
- 在本机中执行
scp ~/.ssh/id_rsa.pub user@目标ip:~/.ssh/authorized_keys
- 如果希望多台机器ssh到同一目标机器免密码可将多台机器
ssh-keygen -t rsa
生成的id_rsa.pub内容追加到目标机器的authorized_keys文件中
12.reveal的使用
- cydia中搜索安装reveal loader
- 在手机的设置中打开要分析的app的enabled applications开关
- 在macOS中中打开reveal,确保macOS和ios在同一网段内,重启ios中的目标app
13.ida中main windows有两种显示模式,分别是graph view和text view,它们之间可以通过空格键切换.grahp view把被分析的程序逻辑用方块的形式表现出来,当执行遇到分支时,满足判断条件分支的线是绿色的,否则是红色的;当执行没有分支时,线是蓝色的
14.ida中”jump to xref to operand”(快捷键x),点击后出现的窗口罗列了这个文件中显式引用这个符号的所有信息.”xref from”则显示这个符号引用的所有符号
15.越狱ios必须安装”apple file conduit2”,简称afc2,这样才可以浏览ios全系统文件
16.dyld_decache
- 从ios3.1开始,包括frameworks在内的许多库文件被存进了一个大cache里,这个cache文件位于”/System/Library/Caches/com.apple.dyld/dyld_shared_cache_armx”(名为dyld_shared_cache_arm7,dyld_shared_cache_armv7s或dyld_shared_cache_arm64),可以使用KennyTM开发的dyld_decache将其中的二进制文件提取出来.这样做的好处是确保分析的文件来自本机
- 使用dyld_decache之前,要将”System/Library/Caches/com.apple.dyld/dyld_shared_cache_armx”从ios拷贝到macOS,然后再用这个工具提取二进制文件.arm64如果出错可google:
site:iosre.com dsc_extractor
来解决 - 可用ios_deploy来从dyld_shared_cache提取ida的符号文件,ida很依赖这些符号文件(有了它们才能快速和准确的反编译),命令如下
17.CydiaSubstrate是绝大部分tweak正常工作的基础,它由MobileHooker,MobileLoader和Safe mode组成
- MobileHooker的作用是替换系统函数,也就是所谓的hook,它主要包含以下两个函数
void MSHookMessageEx(Class class,SEL selector,IMP replacement,IMP *result);
其中MSHookMessageEx作用于Objective-C函数,通过调用method_setImplementation函数将[class selector]的实现改为replacement,达到hook的目的.Logos语法主要是对此函数作了一层封装,让编写针对Object-C函数的hook代码变得更简单直观了,但其底层实现仍完全基于MSHookMessageEx
void MSHookFunction(void* function,void* replacement,void** p_original);
MSHookFunction作用于C和C++函数,通过编写汇编指令,在进程执行到function时转而执行replacement,同时保存function的指令及其返回地址,使得用户可以选择性地执行function,并保证进程能够在执行完replacement后继续正常运行.MSHookFunction的有一个参数的什么用分别是:替换的原函数,替换函数,以及被MobileHooker保存的原函数.单独的一个MSHookFunction函数是没有意义的,需要有一套固定的体系来承载它,这个体系写法如下.由于Theos仅提供了MSHookMessageEx的封装,掌握这套体系的用法就显得尤为重要了
#import <substrate.h>
returnType (*old_symbol)(args);
returnType new_symbol(args)
{
//Whatever
}
void InitializeMSHookFunction(void) // This function is ofter called in %ctor i.e.constructor
{
MSImageRef image=MSGetImageByName("/path/to/binary/who/contains/the/implementation/of/symbol");
//MSFindSymbol的作用是查找待钩住(hook)的symbol
void *symbol=MSFindSymbol(image,"symbol");
if (symbol)MSHookFunction((void *)symbol,(void *)&new_symbol,(void **)&old_symbol);
else NSLog(@"Symbol not found!");
}
- MobileLoader
MobileLoader的作用是加载第三方dylib.在ios启动时,会由launchd将MobileLoader载入内存,然后MobileLoader会根据dylib的同名plist文件指定的作用范围,有选择地在不同进程里通过dlopen函数打开目录/Library/MobileSubstrate/SynamicLibraries/下的所有dylib.
- Safe mode
因为tweak的本质是dylib,寄生在别的进程里,一旦出错,可能会导致整个进程崩溃,而一旦崩溃的是SpringBoard等系统进程,则会造成iOS瘫痪,所以CydiaSubstrate引入了Safe mode,它会的捕获SIGTRAP,SIGABRT,SIGILL,SIGBUS,SIGSEGV,SIGSYS这6种信号,然后进入安全模式.在安全模式里,所有基于CydiaSubstrate的第三方dylib均会禁用,便于查错与修复
19.Cycript是由saurik推出的一款脚本语言,可以看作是Objective-JavaScript.cycript通过cydia在iphone中安装.笔者认为,cycript最为贴心和实用的功能是它可以帮助我们轻松测试函数效果,效果十分显著,比通过theos生成deb来log记录方便很多.一般来说,选择注入哪个进程,要依测试的具体函数而定,这个函数所属的类存在于哪些进程,则注入这些进程,从而保证这个类是存在的.因为需要用cycript测试的一般都是私有函数,所以一个总的准则是从哪个进程逆向出的函数,就注入这个进程来测试;从哪个库逆向出的函数,就注入链接这个库的进程来测试.与Objective-c相比,cycript不需要声明对象类型,也不需要结尾的分号,常见用法如下
#注入SpringBoard进程
cycript -p SpringBoard或cycript -p pid
#在内存中找一个PARSPedometerInfo类的实例对象
choose(PARSPedometerInfo)
#调用0x166b4fb0处的对象的show函数
[#0x166b4fb0 show]
#对show函数传入参数为3344
[#0x166b4fb0 show:3344]
#新建一个PARSPedometerInfo类的对象实例,并调用它的setIntergratedSteps函数,传入参数99998
myobj=[PARSPedometerInfo alloc]
[myobj setIntegratedSteps:99998]
20.LLDB
全称为”low level debugger”.是由苹果出口,内置于Xcode中的动态调试工具,不但能吃C,C++,Objective-C,还全盘支持OSX,iOS,以及iOS模拟器,lldb是运行在OSX中的,要想测试iOS,还需要debugserver的配合
21.debugserver
最常用的2种场景
- 启动进程
debugserver -x backboard IP:port /path/to/excuteable
- 附加进程
debugserver IP:port -a "ProcessName"
22.lldb
中的image list -o -f
命令可查看加载基址
0x.....a /path/to/excuteable(0x....b)
,其中后面的括号里的地址是加载基址,前面的地址是aslr偏移,根据函数地址下断点时需要通过ida中查看相对偏移+这里的括号里的加载基址,或者通过可执行文件的期望加载基址+aslr偏移+ida中相对偏移.(这里的括号里的加载基址-这里的前面的aslr偏移=可执行文件的期望加载基址)
23.lldb相对于gdb的一个重大改进是可以在进程运行的过程中输入lldb命令.需要注意的是,部分进程(如SpringBoard)在停止一段时间后会因响应超时而自动重启,对于这类进程,要尽量让它维持在运行状态,避免因自动重启而导致调试信息丢失的悲剧发生
24.lldb在某个断点得到触发的时候执行预先设置的指令的用法如下:
br com add 1
(假设1号断点)
执行这条命令后,lldb会要求我们设置一系列指令,以DONE
结束
25.在Objective-C中,[someObject someMethod]的底层实现,实际是objc_msgSend(someObject,someMethod),其中,前者是一个Objective-C对象,后者则可以强制转换成一个字符串
26.有时lldb的解析后的注释的符号不对,这种情况下,需以IDA为准
27.使用dumpdecrypted.dylib脱壳过程:
cp dumpdecrypted.dylib /var/mobile/Containers/Data/Application/xxxxx-xxx-xxx-xxx/Documents/
cd /var/mobile/Containers/Data/Application/xxxxx-xxx-xxx-xxx/Documents/
DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/mobile/Containers/Bundle/Application/xxx-xxx-xxx-xxx../TargetApp.app/TargetApp
这里把dumpdecrypted.dylib拷贝到Documents目录下操作的原因是: StoreAPP对沙盒以外的绝大数目录没有写权限,dumpdecrypted.dylib要写一个decrypted文件,但它是运行在StoreApp中的,与StoreApp的权限相同,于是它的写操作就必须发生在StoreApp拥有写权限的路径下才能成功
28.iOS越狱社区的知名人士Nikias Bassen(@pimskeks)开发了一款可以把本地OSX/Windows端口转发到远程iOS端口的工具usbmuxd,使我们能够通过USB连接线ssh到iOS中,大大增加了ssh连接的速度,也方便了没有wifi的情况,用法为brew install usbmuxd && iproxy local_port remote_port
29.syslogd是iOS中记录系统日志的守护进程,cydia中的syslogd to /var/log/syslog
的作用是把日志写入”/var/log/syslog”文件中,在iOS运行的全过程中这个文件会变得越来越大,可以通过cat /dev/null > /var/log/syslog
来将它清空