学计算机的那个

不是我觉到、悟到,你给不了我,给了也拿不住;只有我觉到、悟到,才有可能做到,能做到的才是我的.

0%

iOS逆向攻防

OC的消息传递,可以通过Method Swizzle进行Hook,但是遇到共享库里的C函数呢,如何Hook?

fishhook

fishhook是Facebook提供的一个动态修改链接mach-o文件的工具,它利用Mach-o文件加载原理,通过修改懒加载和非懒加载两个表的指针达到Hook C函数的目的。

Hook使用

只有两个文件 “fishhook.h”和“fishhook.c”,它提供的接口仅有一个结构体和两个函数:
rebinding结构体用来确定你要HOOK的函数和要交换的函数地址。

1
2
3
4
5
struce rebinding{
constchar* name;//需要hook的函数名称,C字符串
void * replaement;//新函数的地址
void** replaced;//原始函数地址的指针!
}
1
2
3
4
5
6
7
  /**
arg1: 存放rebinding 结构体的数组
arg2: 数组的长度
*/
int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel);

int rebind_symbols_image(void *header,intptr_t slide,struct rebinding rebindings[],size_t rebindings_nel);

eg:使用Demo Hook一下NSLog

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//函数指针
staticvoid(*sys_nslog)(NSString* format,...);

//定义一个新的函数。HOOK成功后NSLog调用时,会来到这里
void myNSLog(NSString* format,...){
format = [format stringByAppendingString:@"\n上钩了!\n\n"];
sys_nslog(format);//调用系统的NSLog,HOOK成功后sys_nslog指针保存的是Fundation中NSLog的地址
}

- (void)viewDidLoad {
[super viewDidLoad];
//准备rebinding结构体
struct rebinding nslog;
nslog.name = "NSLog";
//需要HOOK的函数名称
nslog.replacement = myNSLog;
//新函数的地址
nslog.replaced = (void *)&sys_nslog;
//原始函数指针
//准备数组,将一个或多个 rebinding 结构体放进去。
struct rebinding rebs[1] = {nslog};
/**
arg1: 存放rebinding 结构体的数组
arg2: 数组的长度
*/
rebind_symbols(rebs, 1);
}

原理分析

MachO

我们生成的ipa包,里面就包含MachO文件,这个文件里包含程序的数据和指令,比如你定义的类,方法,全局变量,方法实现等等。

  • 自定义函数和系统函数的区别
  1. 自定义函数在MachO文件中,在运行时刻进入内存,自定义函数在本镜像文件中。
  2. 系统函数在系统框架中,在运行时刻进入内存,系统函数在系统的动态库中,比如NSLog在Fundtaion这个镜像文件中。

自定义的函数,在编译时刻,编译器就可以确定函数的实现地址(在MachO文件中的偏移地址),但是系统函数是没办法知道的,那么在CPU执行系统函数的时候,如何知道系统函数的地址呢?

PIC(position Independ code)技术

翻译过来就是位置独立代码。

当你的程序要调用一个MachO外部函数的时候,编译器是没办法知道该函数的地址的,所以它在MachO文件里面生成一个列表,这个列表里放指针,让当前的系统函数调用指向这个列表里面对应的指针,等到我们的MachO文件加载进内存时,再将系统函数的真实地址,一个一个的赋值给列表中的指针。

  • 这个列表就是符号表
  • 列表里的指针,成为符号
  • 给里面的指针赋值的过程,称为符号绑定

所以fishhook之所以Hook不了自定义的函数,就是因为自定义的函数,没有通过符号寻找地址这个过程,而系统函数是通过符号去绑定实现地址的。fishhook就是修改了系统函数的符号达到Hook的目的。

fishhook应用,可以hook 函数objc_msgSend 二进制重排减少page fault 来达到启动优化

一次逆向

在技术群里,偶然看到一个直播APP链接,好奇驱动下,下载安装,然后打开了新世界的大门,无法自拔….看着这些诱人又年轻活泼的小姐姐,当然要发挥一下我的聊骚本领,可是发现聊天,加好友,刷礼物都需要金币,这些都是要充值RMB的,我是穷人呀…然后想试试是否可以破解给自己充值。

获取脱壳ipa包

因为是通过企业证书安装的方式,所以并不需要脱壳,所以这一步只需要获取ipa安装包即可,这个App的安装方式是通过一个plist文件(里面包含ipa的真实url),然后会自动安装,所以要想获取ipa的url路径,需要先获取到这个plist文件,这里借助charles来查看app安装链接跳转后的plist文件路径,和返回的ipa的url。

重签名调试

这里就跟之前博客里介绍过的流程一样。

HooK业务

这里Hook了UserModel的一些相关属性,比如金币,level…的getter方法,但是发现并没有什么作用,只是改变了App界面上的数据显示,实际发送礼物等需要消耗金币的操作,后台会去做校验,充值模块又是直接用的H5页面…看来App的破解顶多也只是做个路由转发,并没太大实际作用,再者就是破解优质App,分析别人的技术实现方案了.

想起来之前github上有看到过一个某度网盘的下载限制破解的仓库,于是我去看了下破解方法,下载完代码之后一看,居然也是粗暴的将Uer Model的vip属性getter方法Hook返回为true,然后你就看到可以一直使用vip的下载试用了….想不到大厂的代码也不过如此,再想到我每次面试大厂时的卑微姿态,真的是…

参考

  1. fishHook原理探究
  2. 一行代码解决!iOS 二进制重排启动优化