iOS逆向+越狱

感觉本文涉及内容有点多的,但是自己不愿意写太多,就简单的谢谢关于ios上手的东西吧

初级入手不免要用到,pp助手,i4 tools等

iOS逆向-ipa包重签名及非越狱手机安装多个应用

 

1.常识

我们平时开发的App,程序运行主要就是加载一个Mach-o可执行文件。当我们将程序打包成ipa文件,上传到App Store的时候,期间就是进行了一些加壳操作,比如:数字证书签名等。重签名的目的就是将别人的程序重新签上我们的证书信息。也可以简单理解为将别人的加密文件解密,加上我们自己的加密算法。
2.查看应用是否加壳

将下载好的ipa包解压缩之后,拿到里面的Mach-o文件,cd到所在目录,执行如下命令:

otool -l 可执行文件路径 | grep crypt

其中cryptid代表是否加壳,1代表加壳,0代表已脱壳。其实代表着该可执行文件支持两种架构armv7arm64.
3.查看应用支持架构
lipo -info 文件路径
4.应用脱壳
  • 一、直接从一些第三方应用商店里面下载你想脱壳的应用,例如:PP助手iTools
  • 二、自己脱壳,利用GitHub上开源的一些工具,常用的有Clutchdumdecrypted。具体如何使用,请自行Google
  • 步骤
  • 一台iPhone,越不越狱都行
  • 开发者证书或者企业证书(个人账号也行,但是应用安装上之后,有效期只有7天)
  • 电脑安装 iOS App Signer
5.利用iOS app Signer 给app重写签名

其实重签名的方式有很多,比如:可以利用sigh resign命令,在终端下操作,还可以借助一些逆向相关的重签名工具

  • 第一项:对应的.ipa或者.app路径   ---已经脱壳好的app  可以从皮皮助手下载
  • 第二项:我们自己的签名证书
    • 注意:个人证书不能重签Extension文件,所以要删除ipa包中包含的相应文件,包括Watch里面的Extension,为了方便一般直接将Watch文件删除:
    • 将对用的ipa文件解压,修改一些东西

  • 第三项:证书对应的Profile文件,默认项Re-Sign Only是无效的,选择证书下存在的Profile文件)
  • 第四项:重签名之后的Bundle identifier(选择了Profile文件,一般会自动填写)
  • 下面的几项随便写
  • 签名完毕之后对应的文件夹下会生成重签名之后的ipa包    ---注意:利用iOS App Signer重签名,在删除掉相应的Extension,选择路径的时候,一定要选择Payload文件夹下对应的.app文件,否则会报找不到Payload文件夹的错误:

6.安装重签名之后的微信

 可以用PP助手安装,也可以用Xcode

备注:多个证书可以多次重新签名,安装多个相同的应用

 

 

版本越狱

几乎ipad,iPhone等对应不同版本偶不同的越狱技巧

简单的说通过组件漏洞来进行文件控制,达到控制内核,进而提升用户权限。

下面我简单说几个关键名词  一下转自http://blog.sina.com.cn/s/blog_655dac9e01017wv3.html

越狱的内部工作原理是完全不知道的。许多人把越狱当黑匣子看待;当他们在越狱工具选项里点击jailbreak按钮,认为工作起来像魔术一样。这是由于对于他们所进行的越狱操作并不需要知道越狱的内部工作原理,如用户层漏洞。

越狱的保持(Jailbreak Persistence)

 依赖越狱使用的漏洞,越狱的效果可能长期的,也可能在设备关机再开启后消失。为了描述两种不同的越狱,越狱社区把这两种方式叫做 完美越狱(tethered jailbreak)和非完美越狱(untethered jailbreak)。

  非完美越狱

  完美越狱(Untethered Jailbreaks)

漏洞类型(Exploit Type)

漏洞的存在位置影响你对设备的存取级别。一些允许低级别的硬件存取。另一些受限于沙盒内的许可权限。 由高到低
  Bootrom级别  =硬件版本

  iBoot级别 <=硬件版本

  Userland级别 =软件版本

 

理解越狱过程(Understanding the Jailbreaking Process)

,把你的iPhone设置为设备固件升级(DFU)状态

当你点击Jailbreak越狱按钮后,红雪指导设置你的iPhone为DFU模式,根据你连接上的设备,提供你可选择的不同的越狱特性。你简单选择你的选项(如多任务手势),点击Next继续按钮,等待红雪完成它的工作。

从用户角度看这是非常简单的过程,但是这这些操作后面发生了很多事情,并且除了越狱社区的少数人,没人真的知道发生了什么。当你读完下面章节后,你将成为了解红雪内部工作的少数人之一。

经作者的允许,下面章节的所有信息都来自一个反编译版本的红雪越狱。由于A5处理器的iPad2或iPhone 4S设备没有一个公开知晓的bootrom漏洞,这些设备的所有越狱必须是用户层面级别的。 这表示bootrom破解和启动ramdisk的头两个步骤必须由MobileSafari漏洞和一个内核漏洞替代,其余的越狱过程工作是一样的。

  破解Bootrom(Exploiting the Bootrom)

红雪的越狱开始时利用the limera1n 的DFU bootrom漏洞来使在高权限级别执行代码成为可能。这个漏洞是一个前A5处理器设备的bootrom中USB DFU堆栈中的基于堆的缓冲区溢出漏洞。我们这里不讨论漏洞的细节。如果感兴趣,你可以在诸如THEiPHONEWiKi(http://theiphonewiki.com/wiki/index.php?title=Limera1n_Exploit)的一些地方找到这个漏洞的说明和源代码。

对越狱来说,你唯一需要知道的是这个漏洞用来给bootrom里的签名验证代码打补丁修改,允许你启动专门的ramdisk,给Low-Level-Bootloader (LLB)、 iBoot和内核的版本打补丁。 Chronic Dev Team团队已在GitHub(https://github.com/Chronic-Dev/syringe)上释放了同样执行效果的源代码。由于红雪没有公开源代码,如果你想重头编写自己的越狱工具,这些代码是一个很好的起点。

  启动Ramdisk(Booting the Ramdisk)

红雪利用 limera1n 漏洞启动一个打补丁修改过的内核和一个预先定制的ramdisk。内核被打了一些越狱补丁以便允许执行未签名的代码。然而,它并没包括在已完美越狱的系统中发现所有内核补丁。依据用户在越狱时设置的开关选项,ramdisk在每次运行时都在根目录创建不同的文件,形成定制的ramdisk。这些文件的存在在晚些时候会被ramdisk上的越狱执行过程检测到,以此决定红雪的哪种特性被激活。例如noUntetherHacks文件的存在会使红雪跳过完美越狱漏洞的安装。

ramdisk启动时,内核会运行 ramdisk的/sbin/launchd的二进制文件,它包括一个初始化越狱的小型stub程序。这个程序首先在系统里装载root根文件系统和数据分区,为修改需要,以上装载好的文件系统和数据分区是可读写。最终,一个越狱的执行程序会接管并执行所有接下来的步骤。

  越狱文件系统(Jailbreaking the Filesystem)

 iPhone的文件系统缺省分成2个分区,第一个分区是root根文件系统,存放iOS的操作系统文件和如MobileMail,MobileSafari的标准应用程序集。早期的iOS版本里,root根文件系统的大小接近分区的容量大小,分区没有多少剩余空间。虽然root文件系统是假设为不可修改的,分区也缺省装载为只读的,但如今root根文件系统接近1GB大小,分区有200MB左右空间剩余。设备的其余存储空间分配给第二个分区,即数据分区,它装载在/private/var目录下,可以读写。在根目录的 /etc/fstab文件里有以下配置:

/dev/disk0s1 / hfs ro 0 1
/dev/disk0s2 /private/var hfs rw,nosuid,nodev 0 2

你可以看到,数据分区的装载配置文件有 nodev 和nosuid标志。为了防止文件系统层面的攻击,nodev标志是确保设备节点在可写的数据分区里的存在将会被忽略。nosuid标志是告知内核在数据分区里执行时忽略suid位。suid位表示执行时需要以超级用户root身份执行,或与当前用户不同的一个用户来执行。这些标志都是iOS内部用来防止权限提升漏洞的防御措施。

不管是bootrom级别,还是用户层面级别的漏洞,这个缺省的配置是所有越狱面临的难题。因为他们通常需要对root根文件系统进行修改,使程序在设备重启后还能存在,或能增加服务和守护进程。所以每次越狱获得超级用户root的权限后的第一个动作就是重新装载root根文件系统,使之可读可写。为了使设备重启后修改也生效,下一个步骤就是用下面类似的配置替换系统的/etc/fstab文件:

/dev/disk0s1 / hfs rw 0 1
/dev/disk0s2 /private/var hfs rw 0 2

这个新的文件系统的配置文件将装载root根目录文件为可读可写,并从第二个分区的装载配置中移去nosuid和nodev标志。

  安装完美越狱破解(Installing the Untethering Exploit)

每次当一个新版本的iOS出现,原先的已知漏洞就被修复了。 所以在一个有限的时间窗口里,红雪在老设备上能越狱新的固件,但不能安装完美越狱漏洞。

一旦得到了一个新的完美越狱漏洞,红雪的作者就会修改程序来安装新的漏洞。 由于每个漏洞都是不同的,所以都需要不同的安装步骤。

虽然实际的完美越狱漏洞安装是不同的,但都是在root根文件系统里重命名和移动一些文件,并拷贝一些文件到它上面。当你反编译当前的红雪软件版本,你会发现它从4.2.1到5.0.1的大部分iOS版本上都支持安装完美越狱漏洞,发现每个完美越狱漏洞需要那些文件。

  安装 AFC2服务(Installing the AFC2 Service)

苹果文件连接 (AFC)是一个运行在每台iPhone上的文件传送服务,它允许你通过USB连线存取iPhone的/var/mobile/Media的目录里的文件。AFC服务由lockdownd守护进程提供,被命名为com.apple.afc 。但lockdownd守护进程只提供存取服务,实际由afcd守护进程实现。在MAC上通过MobileDevice.framework,在Windows PC上通过 iTunesMobileDevice.dll来使用。

afcd还提供lockdownd的第二个服务,它注册为com.apple.crashreportcopymobile。它用来从设备向电脑复制CrashReporter报告,并只限制于/var/mobile/Library/Logs/CrashReporter目录和子目录的读写存取 。

由于这些服务运行于mobile用户的许可权限下,被锁定于特定目录下,他们对于越狱的作用是受限的。所以红雪和其他越狱工具向lockdownd注册了一个额外的服务,叫做com.apple.afc2。这个服务利用afcd守护进程提供对整个文件系统的root超级用户权限的读写存取,这是一个大部分用户都不知道的相当危险的越狱特性。这意味着一台没有密码保护或在未锁定状态的越狱过的iPhone,只要连接上一个USB充电站或其他人的电脑,就给了另一方在没有用户交互下的整个文件系统的读取存取权限。他们可以窃取你的所有数据或安装系统后门。

com.apple.afc2服务通过更改在/System/Library/Lockdown/Services.plist文件里的lockdownd配置来安装。这是一个正常的.plist 文件,可以通过 .plist文件的标准工具或API来修改。

  安装基本程序库(Installing Base Utilities)

 

  应用程序隐藏(Application Stashing)

 当从苹果的应用程序商店安装应用时,它们被安装在/var/mobile/Applications目录里,该目录驻留在iPhone的大容量的数据分区里。可以安装的应用程序的数量依赖于数据分区的空闲空间。空闲空间通常有上GB 容量,所以对安装应用程序数量来讲不是真正的限制.

Cydia是越狱者制做的相当于苹果AppStore的应用程序商店,通过Cydia下载的越狱应用的安装地点是不同的。像Cydia自身和其他内置的二进制文件安装在root根目录的/Application目录下。前面提到,root根文件系统的容量取决于固件的版本、容量和设备类型。通常在1GB和1.5GB之间,有大约200MB的空闲,这点容量对安装应用程序来说是不多的。

另外,墙纸和铃声也存放在根目录的 /Library/Wallpaper 和 /Library/Ringtones目录下,所以从Cydia安装的每个墙纸和铃声也也会占用掉有限的应用程序空间。

为解决这个问题,各种越狱都实现了应用程序隐藏技术。它是在iPhone的数据分区创建了/var/stash的新目录,并把一些正常情况下位于root根文件系统下的应用程序移到/var/stash目录下,原来的目录替换为链接到新目录的符号链接。

以下清单是通过程序隐藏转移到/var/stash下的目录:

 

然而,不是所有的越狱工具和所有版本的越狱工具都进行应用程序隐藏。因为这样,Cydia创建时在第一次调用时会进行检测,这是Cydia里的重新组织文件系统(“Reorganizing Filesystem”)的耗时较长的步骤。

  安装程序包 (Bundle Installation)

 

  安装后过程(Post-Installation Process)

内核payload。

  执行内核Payloads并修改内核(Executing Kernel Payloads and Patches)

虽然每个内核漏洞和每个payload是不同的,但能把越狱所用的内核级的payload分为为4个部分:

(1)修复内核状态Kernel State Reparation

(2)权限提升Privilege Escalation

(3)修改内核Kernel patching
(4)清理并返回Clean return
接下来的章节对他们进行详细描述

  修复内核状态(Kernel State Reparation)

  权限提升(Privilege Escalation)

 由于iPhone上的所有应用程序的都以权限较少的用户(如mobile,_wireless,_mdsnresponder,_securityd)角色运行,一个内核漏洞的payload执行后,通常要把应用程序的运行进程的权限提升到root超级用户权限。 如果少了这一步骤,有些操作是不可能完成的的,像重新装载root根文件系统到可写状态,或修改属于root超级用户的文件。所有这些在越狱的初始安装时都时需要的。只用于完美越狱的重启后执行的内核漏洞不需要这一步骤,因为通常已经已root超级用户角色运行。

在内核内部,提升当前运行进程的权限是很容易的。只需要修改进程的proc_t结构的信用值。这个结构在XNU源代码的/bsd/sys/proc_internal.h文件的proc结构里定义。依据不同的内核漏洞payload开始运行方法的不同,取得当前进程的proc_t结构的指针的方法是不同的。在以前公开的许多iOS内核漏洞里,用于覆盖系统调用表里的系统调用程序的地址的办法是不同的。内核漏洞的payload由调用被覆盖的系统调用来触发。在这种情况下,它获得的proc_t结构是微不足道的,因为它是系统调用程序的第一参数。

得到proc_t结构的地址的更通用的方法是调用current_proc()内核函数,它能取回这个结构的的地址。这个函数是一个内核输出的符号,很容易找到。由于刚开始的内核漏洞能检测使用的内核版本,并且内核里没有地址随机化,所以它可以把函数的地址硬编码到内核漏洞里。

取到proc_t结构的地址的第三个方法是使用通过sysctl接口泄露的内核地址信息。这项技术是由noir在破解OpenBSD内核的过程中首先发表的(详见www.phrack.org/issues.html?issue=60&id=06),并被nemo用于XNU内核(详见www.phrack.org/issues.html?issue=64&id=11)。这个泄露的信息允许用户态进程通过一个简单的sysctl系统调用取到proc结构的内核地址。

在取到进程proc_t结构的地址后,结构里的p_ucred成员用来修改连接的ucred结构。 这个元素可以通过proc_ucred()函数读取,或直接读取。下面的反汇编代码表明在当前iOS版本里结构里p_ucred域的偏移量是0×84.

_proc_ucred:

LDR.W           R0, [R0,#0x84]
BX              LR

在/bsd/sys/ucred.h文件里有ucred结构的定义。结构里还包含拥有这个结构的进程的用户ID和组ID。

struct ucred {
TAILQ_ENTRY(ucred)  cr_link;
u_long  cr_ref;        
struct posix_cred {

uid_t   cr_uid;        
uid_t   cr_ruid;       
uid_t   cr_svuid;      
short   cr_ngroups;    
gid_t   cr_groups[NGROUPS];
gid_t   cr_rgid;       
gid_t   cr_svgid;      
uid_t   cr_gmuid;      
int cr_flags;      
} cr_posix;
struct label    *cr_label; 

struct au_session cr_audit;    

};

为了提升拥有这个结构的进程的权限,结构偏移量0x0c处的cr_uid域被设置为0。如你预料的,偏移量是0x0c,而不是0×08,是因为一个TAILQ_ENTRY条目是8byte的。当然,其他元素也能被修改。然而一旦uid值等于0,用户态的进程就能利用系统调用更改它的许可权限。

修改内核(Kernel Patching)

内核级payload最重要的部分是对内核代码和数据进行内核级别的修改,使安全功能失效,

 然而,接下来的章节向你介绍这些补丁和它们背后的原理,你可以用它们来开发你自己的内核修改补丁,运用于未来的iOS版本。

  security.mac.proc_enforce变量

security.mac.proc_enforce是个系统调用变量,它控制着是否在进程操作中使能MAC策略。变量禁止时,各种进程策略检查和限制就被关掉了。例如,对fork(), setpriority(), kill() 和 wait() 系统调用的限制。 除此以外,这个变量还控制着代码签名blob的数字签名是否合法。变量禁止时,代码签名blob的数字签名是非法的二进制代码也可以被执行。

  内核的cs_enforcement_disable变量

/osfmk/vm/vm_fault.c文件的页错误处理程序的源代码里有一个cs_enforcement_disable变量,它控制着页错误处理程序的代码签名是否起作用。

  AMFI模块的cs_enforcement_disable变量

 只有在一些我们知道的未公开的越狱里proc_enforce标志没有更改,在这种情况下,补丁是有效的。

  PE_i_can_has_debugger函数

iOS内核有一个PE_i_can_has_debugger()函数,内核和一些内核扩展里都用它来决定是否允许调试。在一些iOS内核扩展里设置调试启动参数会引起内核错误。所以当前的大部分越狱不再修改这个函数代码,而是修改内核里的debug_enable 变量。为了确定这个变量的地址,必须分析PE_i_can_has_debugger()函数的代码。因为这个变量位于一个未初始化的数据段里,修改只能在运行时进行。为了查找启动时初始化这个变量的代码,需要搜索debug-enabled字符串,可以直接找到把值复制到变量的代码。

  vm_map_enter函数

当内存映射到进程的地址空间时,内核函数vm_map_enter()被用于分配一段虚拟地址映射。

  vm_map_protect函数

vm_map_protect() 是内核函数,它在映射内存的保护改变时被调用。

因为这个修改,越狱减弱了iOS设备的内存保护。我们建议当用户想运行需要修改自身代码的应用程序时才进行这个补丁修改。这些修改的问题是禁止了非执行内存的限制,以致对iPhone应用程序的远程攻击不需要实现百分百的ROP操作。相反,这些攻击或恶意程序只需要一个利用 mprotect()函数来注入执行代码的简短的ROP stub。

  AMFI二进制信任缓冲区(AMFI Binary Trust Cache)

AMFI内核模块负责检查签名代码blob的数字签名的合法性。它注册了一些MAC的策略处理句柄,如vnode_check_signature钩子,它在每次内核增加一个新的签名代码blob时都会被调用;AMFI处理程序对来自苹果的证书验证签名。

  0号进程任务陷阱(Task_for_pid 0)

虽然这个补丁修改对大部分越狱者都是没有必要的,我们把它记录下来是因为它涉及一个mach陷阱,下面我们会向你介绍一种在iOS二进制内核里寻找mach陷阱表(mach_trap_table)的策略。

task_for_pid()是一个mach陷阱,会返回另一个进程的任务端口,以它的进程ID命名。这局限于用户ID相同的进程,除非请求任务端口的进程是特权的。

修改沙盒 (Sandbox Patches)

 Comex的内核修改补丁的最后一步就是改变沙盒的行为。没有这个修改补丁,越狱过的iPhone不能运行类似MobileSafari 和 MobileMail的应用程序。因为越狱后/Applications 目录已经移到/var/stash/Applications目录了,这违反了沙盒机制。 奇怪的是目前我们只知道这两个应用程序受影响。即使没有修改沙盒,其他所有的内置应用程序看起来都能完美运行。

这个修改补丁包括两块:第一块是用钩子(hook)覆盖sb_evaluate()函数的开始部分;第二块是在内核里的未用区域写入新代码。这个函数的更多信息,可以回顾第5章。这个修改补丁改变了沙盒仿真的修为,去存取处理不同的特定的目录。

在描述新的仿真功能前,由于没有符号表可用,我们要找到在内核代码里定位sb_evaluate()函数的方法。一个可能性是在沙盒内核扩展里搜索mac策略处理程序表。一些mac策略处理程序会用到sb_evaluate()函数。当前的iOS内核里很容易搜索到错误操作码的字符。因为只能在你的函数里使用它,一旦找到它的数据引用,你要找到它所用的函数的开始的地方。

定位到sb_evaluate()函数的地址后,可以给它安装一个钩子函数,让它跳转到一个内核未使用的区域,在那里你可以放置其余代码。我们在第9章里已经讨论过如何找到未用的区域。在comex的GitHub程序库里可以找到datautils0程序的源代码,它模拟了钩子的功能,我们现在要仔细研究它。代码的总体想法是对/private/var/mobile和private/var/mobile/Library/Preferences里的文件避免进行沙盒检查。代码开始时检查提供的vnode是否为0,如果为0,不调用钩子函数,只是跳过检查,执行原来的处理程序。

  清空缓存(Clearing the Caches)

  清理并返回(Clean Return)

 提升权限,修改安全特性,脱离内核的掌控后,唯一要做的是让内核空间保持在清洁的状态,防止内核不稳定或立即崩溃。通常只需要把普遍意义上的CPU寄存器的值恢复到调用内核payload前的值,并返回保存的程序指针。万一内核堆栈被溢出了,由于真实的堆栈的值被溢出的缓冲区覆盖,导致不可能恢复。这种情况下,可以返回一个未被破坏的以前的堆栈帧。

另一个退出内核的办法是调用内核的thread_exception_return()函数。由于这个函数在内核里没有符号表,需要通过模式匹配扫描和交叉引用扫描找到这个函数。当内核堆栈帧不可能回退时需要执行完当前内核线程的例外情况,需要调用这个函数来恢复内核。因此,可以用它来离开漏洞payload后的内核。但是,内核应该尽可能通过返回正确的堆栈帧的来离开,否者,离开后内核不能保证还在稳定状态。

 

 

以上参考:作者:czj_warrior
链接:https://www.jianshu.com/p/25e1f44c90f7

http://blog.sina.com.cn/s/blog_655dac9e01017wv3.html

 

iOS逆向+越狱

上一篇:C语言中,为什么字符串可以赋值给字符指针变量


下一篇:高精度快速幂(Java版)